From c26321b9f8c53698ec4d1303fafccedd2e12b2ff Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 28 Mar 2014 14:02:50 +0400 Subject: [PATCH 01/43] chmod +x bin/rails bin/rake --- bin/rails | 0 bin/rake | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/rails mode change 100644 => 100755 bin/rake diff --git a/bin/rails b/bin/rails old mode 100644 new mode 100755 diff --git a/bin/rake b/bin/rake old mode 100644 new mode 100755 From 42a97c5c290d1006f1c7ca19e846b9a2b322f679 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 28 Mar 2014 14:07:02 +0400 Subject: [PATCH 02/43] chmod +x bin/bundle --- bin/bundle | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/bundle diff --git a/bin/bundle b/bin/bundle old mode 100644 new mode 100755 From e367a5e0dd37bff1c9f9f38e488c0eb8fd763a8d Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 29 Mar 2014 02:14:37 +0400 Subject: [PATCH 03/43] #370: generate sitemap --- Gemfile | 1 + Gemfile.lock | 3 + app/controllers/sitemap_controller.rb | 11 ++ app/views/sitemap/robots.erb | 22 +++ config/routes.rb | 5 + config/schedule.rb | 4 + config/sitemap.rb | 58 ++++++++ public/robots.txt | 202 -------------------------- 8 files changed, 104 insertions(+), 202 deletions(-) create mode 100644 app/controllers/sitemap_controller.rb create mode 100644 app/views/sitemap/robots.erb create mode 100644 config/sitemap.rb delete mode 100644 public/robots.txt diff --git a/Gemfile b/Gemfile index d8aace642..0abd5a1e6 100644 --- a/Gemfile +++ b/Gemfile @@ -83,6 +83,7 @@ gem 'compass-rails', '~> 1.1.6' gem 'uglifier', '~> 2.4' gem 'therubyracer', '~> 0.12.1', platforms: [:mri, :rbx] gem 'therubyrhino', '~> 1.73.1', platforms: :jruby +gem 'sitemap_generator' group :production do diff --git a/Gemfile.lock b/Gemfile.lock index 80bf4e1f1..98a69e95b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -395,6 +395,8 @@ GEM rack (~> 1.4) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) + sitemap_generator (5.0.1) + builder skinny (0.2.3) eventmachine (~> 1.0.0) thin (~> 1.5.0) @@ -536,6 +538,7 @@ DEPENDENCIES shotgun shoulda shoulda-matchers + sitemap_generator skype soundmanager-rails state_machine (~> 1.2) diff --git a/app/controllers/sitemap_controller.rb b/app/controllers/sitemap_controller.rb new file mode 100644 index 000000000..521a6bee3 --- /dev/null +++ b/app/controllers/sitemap_controller.rb @@ -0,0 +1,11 @@ +class SitemapController < ApplicationController + + def show + redirect_to "/sitemaps/#{request.host_with_port.gsub(/www./, '')}/sitemap.xml.gz" + end + + def robots + render file: 'sitemap/robots', layout: false, content_type: Mime::TEXT + end + +end \ No newline at end of file diff --git a/app/views/sitemap/robots.erb b/app/views/sitemap/robots.erb new file mode 100644 index 000000000..4462e67de --- /dev/null +++ b/app/views/sitemap/robots.erb @@ -0,0 +1,22 @@ +# robots.txt for <%= root_url %> + +User-agent: * +Disallow: /*/*/tree/* +Disallow: /*/*/blob/* +Disallow: /*/*/wiki/*/* +Disallow: /*/*/issues?* +Disallow: /*/*/commits/* +Disallow: /*/blame/ +Disallow: /*/raw/ +Disallow: /*.git +Disallow: /*.git/ +Disallow: /search +Disallow: /users/sign_up +Disallow: /users/sign_in +Disallow: /users/password/new +Disallow: /users/register_requests/new +Disallow: /invite.html +Disallow: /thanks.html +Allow: / +Host: <%= root_url.gsub(/\/$/, '') %> +Sitemap: <%= sitemap_url %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index bc6ffc4cb..997b23cae 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,9 @@ Rosa::Application.routes.draw do + + # Redirect sitemap1.xml.gz file on AWS S3 + match '/sitemap.xml.gz' => 'sitemap#show', via: [:get, :post, :head], as: :sitemap + match '/robots.txt' => 'sitemap#robots', via: [:get, :post, :head], as: :robots + resource :contact, only: [:new, :create, :sended] do get '/' => 'contacts#new' get :sended diff --git a/config/schedule.rb b/config/schedule.rb index 9e9cb2b29..6ac012db6 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -26,6 +26,10 @@ every :day, at: '3:00 am' do rake 'activity_feeds:clear', output: 'log/activity_feeds.log' end +every :day, at: '2:30 am' do + rake 'sitemap:refresh', output: 'log/sitemap.log' +end + every 1.hour do rake 'buildlist:clear:outdated_canceling', output: 'log/canceling_build_list_clear.log' end diff --git a/config/sitemap.rb b/config/sitemap.rb new file mode 100644 index 000000000..d014fbe85 --- /dev/null +++ b/config/sitemap.rb @@ -0,0 +1,58 @@ +%w(abf.rosalinux.ru abf.io).each do |domain| + + SitemapGenerator::Sitemap.create( + default_host: "https://#{domain}", + sitemaps_path: "sitemaps/#{domain}" + ) do + + # root + add(root_path) + + # Projects + Project.opened.find_each do |project| + add(project_path(project), lastmod: project.updated_at) + end + + # BuildLists + BuildList.for_status(BuildList::BUILD_PUBLISHED). + where(platforms: { visibility: 'open' }, projects: { visibility: 'open' }). + joins(:save_to_platform, :project). + find_each do |bl| + add(build_list_path(bl), lastmod: bl.updated_at) + end + + # Platforms + Platform.opened.find_each do |platform| + add(platform_path(platform), lastmod: platform.updated_at) + + # Repositories + add(platform_repositories_path(platform), lastmod: platform.updated_at) + platform.repositories.find_each do |repository| + add(platform_repository_path(platform, repository), lastmod: repository.updated_at) + end + + + # Products + add(platform_products_path(platform), lastmod: platform.updated_at) + platform.products.find_each do |product| + add(platform_product_path(platform, product), lastmod: product.updated_at) + + # ProductBuildList (ISO) + product.product_build_lists.for_status(ProductBuildList::BUILD_COMPLETED).find_each do |pbl| + add(platform_product_product_build_list_path(platform, product, pbl), lastmod: pbl.updated_at) + end + end + end + + # Users + User.find_each do |user| + add(user_path(user), lastmod: user.updated_at) + end + + # Groups + Group.find_each do |group| + add(group_path(group), lastmod: group.updated_at) + end + + end +end \ No newline at end of file diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index b7e1b54d9..000000000 --- a/public/robots.txt +++ /dev/null @@ -1,202 +0,0 @@ -User-agent: Googlebot -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: baiduspider -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: msnbot -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: naverbot -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: seznambot -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: Slurp -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: teoma -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: Yandex -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: CCBot -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: Telefonica -Allow: /*/*/tree/master -Allow: /*/*/blob/master -Disallow: /*/*/tree/* -Disallow: /*/*/blob/* -Disallow: /*/*/wiki/*/* -Disallow: /*/*/issues?* -Disallow: /*/*/commits/* -Disallow: /*/blame/ -Disallow: /*/raw/ -Disallow: /*.git -Disallow: /*.git/ -Disallow: /search -Disallow: /users/sign_up -Disallow: /users/sign_in -Disallow: /users/password/new -Disallow: /users/register_requests/new -Disallow: /invite.html -Disallow: /thanks.html - -User-agent: * -Disallow: / From f495da7f743bf1f2094e8108d615e13969d7810e Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 29 Mar 2014 03:09:04 +0400 Subject: [PATCH 04/43] #370: update deploy.rb.sample --- config/deploy.rb.sample | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/deploy.rb.sample b/config/deploy.rb.sample index 66d98e9b2..22264e80a 100644 --- a/config/deploy.rb.sample +++ b/config/deploy.rb.sample @@ -49,6 +49,10 @@ namespace :deploy do # It will survive downloads folder between deployments run "mkdir -p #{fetch :shared_path}/downloads" run "ln -nfs #{fetch :shared_path}/downloads/ #{fetch :release_path}/public/downloads" + + # It will survive sitemaps folder between deployments + run "mkdir -p #{fetch :shared_path}/sitemaps" + run "ln -nfs #{fetch :shared_path}/sitemaps #{fetch :release_path}/public/sitemaps" end task :symlink_pids, :roles => :app do From b1e98bd92f4d6a0211e4f3abcedb0fe726e23e5f Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Mon, 31 Mar 2014 14:25:56 +0400 Subject: [PATCH 05/43] Fixed: confirmation_instructions --- app/controllers/users/confirmations_controller.rb | 3 +++ app/views/devise/confirmations/new.html.haml | 12 +++++------- .../devise/mailer/confirmation_instructions.en.haml | 2 +- .../devise/mailer/confirmation_instructions.ru.haml | 2 +- config/locales/devise.en.yml | 3 +++ config/locales/devise.ru.yml | 3 +++ config/routes.rb | 5 ++++- 7 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 app/controllers/users/confirmations_controller.rb diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb new file mode 100644 index 000000000..9fa4f9fe1 --- /dev/null +++ b/app/controllers/users/confirmations_controller.rb @@ -0,0 +1,3 @@ +class Users::ConfirmationsController < Devise::ConfirmationsController + layout 'application' +end diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml index b4fa14592..899bd28b6 100644 --- a/app/views/devise/confirmations/new.html.haml +++ b/app/views/devise/confirmations/new.html.haml @@ -1,5 +1,5 @@ .block - %h2= title t("devise.confirmations.resend_header") + %h2= title t("devise.confirmations.new.title") .content - if resource.errors.present? .flash @@ -10,14 +10,12 @@ = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: "form" }) do |f| = f.hidden_field :reset_password_token .group.wat-cf - .left - = f.label :email, class: "label" - .right - = f.text_field :email, class: "text_field" + = f.label :email, class: "label" + = f.text_field :email, class: "text_field" .group.navform.wat-cf %button.button{tyle: "submit"} - = image_tag("choose.png", alt: t("devise.confirmations.send")) - = t("devise.confirmations.send") + = image_tag("choose.png", alt: t("devise.confirmations.new.submit_html")) + = t("devise.confirmations.new.submit_html") %span.text_button_padding = render "devise/shared/links" \ No newline at end of file diff --git a/app/views/devise/mailer/confirmation_instructions.en.haml b/app/views/devise/mailer/confirmation_instructions.en.haml index 398c38d2b..27b54554f 100644 --- a/app/views/devise/mailer/confirmation_instructions.en.haml +++ b/app/views/devise/mailer/confirmation_instructions.en.haml @@ -1,6 +1,6 @@ %p Welcome #{@resource.email}! %p You can confirm your account through the link below: -%p= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @resource.confirmation_token) +%p= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %br %p== Support team «ROSA ABF» diff --git a/app/views/devise/mailer/confirmation_instructions.ru.haml b/app/views/devise/mailer/confirmation_instructions.ru.haml index 167378049..88caad2cc 100644 --- a/app/views/devise/mailer/confirmation_instructions.ru.haml +++ b/app/views/devise/mailer/confirmation_instructions.ru.haml @@ -1,6 +1,6 @@ %p Здравствуйте, #{@resource.email}! %p Вы можете подтвердить свой аккаунт, перейдя по ссылке снизу: -%p= link_to 'Подтвердить мой аккаунт', confirmation_url(@resource, confirmation_token: @resource.confirmation_token) +%p= link_to 'Подтвердить мой аккаунт', confirmation_url(@resource, confirmation_token: @token) %br %p== Команда поддержки «ROSA ABF» diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index 0dceccf2d..be6968e6e 100644 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -38,6 +38,9 @@ en: send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.' confirmed: 'Your account was successfully confirmed. You are now signed in.' + new: + title: "Resend confirmation instructions" + submit_html: "Resend the instructions »" registrations: signed_up: 'Welcome! You have signed up successfully.' signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.' diff --git a/config/locales/devise.ru.yml b/config/locales/devise.ru.yml index b25fd5976..f63a68ffd 100644 --- a/config/locales/devise.ru.yml +++ b/config/locales/devise.ru.yml @@ -41,6 +41,9 @@ ru: send_paranoid_instructions: 'Если Ваш e-mail существует, то в течение нескольких минут вы получите e-mail с инструкциями по подтверждению вашей учётной записи.' confirmed: "Ваша учётная запись подтверждена. Теперь вы вошли в систему." error: "Неверный код подтверждения." + new: + title: "Отправить инструкцию по подтверждению учётной записи" + submit_html: "Отправить инструкцию »" registrations: signed_up: "Добро пожаловать! Вы успешно зарегистрировались." signed_up_but_unconfirmed: 'Сообщение для подтверждения учетной записи было отправлено на Ваш email. Пожалуйста откройте ссылку из письма для активации.' diff --git a/config/routes.rb b/config/routes.rb index bc6ffc4cb..1e868fb64 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,10 @@ Rosa::Application.routes.draw do post 'users' => 'users/registrations#create', as: :user_registration end - devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }, skip: [:registrations] + devise_for :users, controllers: { + omniauth_callbacks: 'users/omniauth_callbacks', + confirmations: 'users/confirmations' + }, skip: [:registrations] namespace :api do namespace :v1 do From f0dc7b5151e05af91ec54ff93c3ae84c79136601 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Mon, 31 Mar 2014 22:49:54 +0400 Subject: [PATCH 06/43] #370: added specs for SitemapController --- spec/controllers/sitemap_controller_spec.rb | 36 +++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 spec/controllers/sitemap_controller_spec.rb diff --git a/spec/controllers/sitemap_controller_spec.rb b/spec/controllers/sitemap_controller_spec.rb new file mode 100644 index 000000000..ac0aae359 --- /dev/null +++ b/spec/controllers/sitemap_controller_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe SitemapController do + describe 'robots' do + + it 'is successful' do + get :robots + response.should be_success + response.should render_template('sitemap/robots') + end + + context 'validate robots.txt' do + render_views + + it 'ensures that Host is correct' do + get :robots + response.body.should match(/^Host: http:\/\/test.host$/) + end + + it 'ensures that Sitemap is correct' do + get :robots + response.body.should match(/^Sitemap: http:\/\/test.host\/sitemap.xml.gz$/) + end + end + end + + describe 'show' do + + it 'is successful' do + get :show + response.should redirect_to("/sitemaps/test.host/sitemap.xml.gz") + end + + end + +end From 164569b2ad2505fd8da3de0f875a6118c3886a3d Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 2 Apr 2014 21:16:51 +0400 Subject: [PATCH 07/43] Hook for to slow DB request --- app/models/ability.rb | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 4d63e56a4..108af5fc9 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -81,7 +81,8 @@ class Ability can [:read, :log, :owned, :everything], BuildList, user_id: user.id can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'User', owner_id: user.id} can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'Group', owner_id: user_group_ids} - can([:read, :log, :everything, :list], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project} + # can([:read, :log, :everything, :list], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project} + can([:read, :log, :everything, :list], BuildList, read_relations_for_build_lists_and_projects) {|build_list| can? :read, build_list.project} can(:publish_into_testing, BuildList) { |build_list| can?(:create, build_list) && build_list.save_to_platform.main? } can(:create, BuildList) {|build_list| @@ -202,10 +203,35 @@ class Ability key = parent ? "#{parent.singularize}_id" : 'id' parent ||= table - ["#{table}.#{key} IN ( - SELECT target_id FROM relations WHERE relations.target_type = ? AND + ["#{table}.#{key} = ANY ( + ARRAY ( + SELECT target_id + FROM relations + WHERE relations.target_type = ? AND (relations.actor_type = 'User' AND relations.actor_id = ? OR - relations.actor_type = 'Group' AND relations.actor_id IN (?)))", parent.classify, @user, user_group_ids] + relations.actor_type = 'Group' AND relations.actor_id IN (?)) + ) + )", parent.classify, @user, user_group_ids + ] + end + + def read_relations_for_build_lists_and_projects + ["build_lists.project_id = ANY ( + ARRAY ( + SELECT target_id + FROM relations + INNER JOIN projects ON projects.id = relations.target_id + WHERE relations.target_type = 'Project' AND + ( + projects.owner_type = 'User' AND projects.owner_id != :user OR + projects.owner_type = 'Group' AND projects.owner_id NOT IN (:groups) + ) AND ( + relations.actor_type = 'User' AND relations.actor_id = :user OR + relations.actor_type = 'Group' AND relations.actor_id IN (:groups) + ) + ) + )", { user: @user, groups: user_group_ids } + ] end def local_reader?(target) From 3ad56638b7c6b328beb50555f6960ef6c1692b25 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 5 Apr 2014 22:37:27 +0400 Subject: [PATCH 08/43] Added specs for MassBuild --- app/models/mass_build.rb | 14 +++++------- spec/models/mass_build_spec.rb | 40 +++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/app/models/mass_build.rb b/app/models/mass_build.rb index 653ff9c60..998d2faea 100644 --- a/app/models/mass_build.rb +++ b/app/models/mass_build.rb @@ -104,12 +104,10 @@ class MassBuild < ActiveRecord::Base where( status: status, mass_build_id: self.id - ).joins(:project, :arch).find_in_batches(batch_size: 100) do |build_lists| - build_lists.each do |build_list| - report << "ID: #{build_list.id}; " - report << "PROJECT_NAME: #{build_list.project_name}; " - report << "ARCH: #{build_list.arch_name}\n" - end + ).joins(:project, :arch).find_each(batch_size: 100) do |build_list| + report << "ID: #{build_list.id}; " + report << "PROJECT_NAME: #{build_list.project_name}; " + report << "ARCH: #{build_list.arch_name}\n" end report end @@ -117,8 +115,8 @@ class MassBuild < ActiveRecord::Base def publish(user, *statuses) builds = build_lists.where(status: statuses) builds.update_all(publisher_id: user.id) - builds.order(:id).find_in_batches(batch_size: 50) do |bls| - bls.each{ |bl| bl.can_publish? && bl.has_new_packages? && bl.now_publish } + builds.find_each(batch_size: 50) do |bl| + bl.now_publish if bl.can_publish? && bl.has_new_packages? end end diff --git a/spec/models/mass_build_spec.rb b/spec/models/mass_build_spec.rb index 510fc4a5e..171c1a174 100644 --- a/spec/models/mass_build_spec.rb +++ b/spec/models/mass_build_spec.rb @@ -33,9 +33,47 @@ describe MassBuild do at ab ) - mass_build = FactoryGirl.create(:mass_build, projects_list: projects_list) + mass_build = FactoryGirl.build(:mass_build, projects_list: projects_list) + mass_build.should be_valid list = mass_build.projects_list.split(/[\r]*\n/) list.should have(2).items list.should include('at', 'ab') end + + it '#generate_list' do + mb = FactoryGirl.build(:mass_build) + bl = double(:build_list) + + # allow(service).to receive(:already_pulled?).with(post.identifier).and_return(true) + # allow(BuildList).to receive(:find_each).and_yield(bl) + BuildList.stub_chain(:select, :where, :joins, :find_each).and_yield(bl) + expect(bl).to receive(:id) + expect(bl).to receive(:project_name) + expect(bl).to receive(:arch_name) + mb.send(:generate_list, 0) + end + + it '#publish' do + mb = FactoryGirl.build(:mass_build) + user = double(:user, id: 123) + + bl1 = double(:build_list, can_publish?: true, has_new_packages?: true) + bl2 = double(:build_list, can_publish?: true, has_new_packages?: false) + bl3 = double(:build_list, can_publish?: false, has_new_packages?: true) + bl4 = double(:build_list, can_publish?: false, has_new_packages?: false) + + finder = double(:finder) + allow(mb).to receive(:build_lists).and_return(finder) + allow(finder).to receive(:where).and_return(finder) + allow(finder).to receive(:find_each).and_yield(bl1).and_yield(bl2).and_yield(bl3).and_yield(bl4) + + expect(finder).to receive(:update_all).with(publisher_id: user.id) + expect(bl1).to receive(:now_publish) + expect(bl2).to_not receive(:now_publish) + expect(bl3).to_not receive(:now_publish) + expect(bl4).to_not receive(:now_publish) + + mb.send(:publish, user, []) + end + end From 773c1701adfa721b6fb6350c98277e0f558afc59 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 5 Apr 2014 23:19:04 +0400 Subject: [PATCH 09/43] Cleans ApiDefender statistics --- Gemfile | 1 + Gemfile.lock | 2 ++ app/jobs/clean_api_defender_statistics_job.rb | 17 ++++++++++ config/resque_schedule.yml | 9 +++++- .../clean_api_defender_statistics_job_spec.rb | 31 +++++++++++++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 app/jobs/clean_api_defender_statistics_job.rb create mode 100644 spec/jobs/clean_api_defender_statistics_job_spec.rb diff --git a/Gemfile b/Gemfile index 0abd5a1e6..5a9d2bbca 100644 --- a/Gemfile +++ b/Gemfile @@ -125,4 +125,5 @@ group :test do gem 'mock_redis', '~> 0.11' gem 'rake' gem 'test_after_commit' + gem 'timecop' end diff --git a/Gemfile.lock b/Gemfile.lock index 98a69e95b..f071bdfcc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -432,6 +432,7 @@ GEM time_diff (0.3.0) activesupport i18n + timecop (0.7.1) tmp_cache (0.1.1) treetop (1.4.15) polyglot @@ -546,6 +547,7 @@ DEPENDENCIES therubyracer (~> 0.12.1) therubyrhino (~> 1.73.1) time_diff + timecop uglifier (~> 2.4) underscore-rails whenever (~> 0.9.0) diff --git a/app/jobs/clean_api_defender_statistics_job.rb b/app/jobs/clean_api_defender_statistics_job.rb new file mode 100644 index 000000000..788534917 --- /dev/null +++ b/app/jobs/clean_api_defender_statistics_job.rb @@ -0,0 +1,17 @@ +class CleanApiDefenderStatisticsJob + @queue = :clone_build + + def self.perform + deadline = Date.today - 1.month + Redis.current.keys.select do |key| + next if key !~ /^throttle:/ + # See: https://github.com/datagraph/rack-throttle/blob/master/lib/rack/throttle/daily.rb#L41 + # Formats: + # 'throttle:uname:%Y-%m-%dT%H', 'throttle:uname:%Y-%m-%d' + # example: "throttle:proyvind:2014-01-25T20", "throttle:proyvind:2014-01-25" + date = key.gsub(/.*:/, '').gsub(/T.*/, '') + Redis.current.del(key) if Date.parse(date) < deadline + end + end + +end diff --git a/config/resque_schedule.yml b/config/resque_schedule.yml index 60cd0e700..44b2dfac2 100644 --- a/config/resque_schedule.yml +++ b/config/resque_schedule.yml @@ -17,4 +17,11 @@ build_lists_queues_monitoring: - '1m' class: 'BuildListsQueuesMonitoringJob' queue: hook - description: 'Monitoring for "user/mass-build" queues' \ No newline at end of file + description: 'Monitoring for "user/mass-build" queues' + +clean_api_defender_statistics: + every: + - '1d' + class: 'CleanApiDefenderStatisticsJob' + queue: clone_build + description: 'Cleans ApiDefender statistics' \ No newline at end of file diff --git a/spec/jobs/clean_api_defender_statistics_job_spec.rb b/spec/jobs/clean_api_defender_statistics_job_spec.rb new file mode 100644 index 000000000..228c232f9 --- /dev/null +++ b/spec/jobs/clean_api_defender_statistics_job_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe CleanApiDefenderStatisticsJob do + + it 'ensures that not raises error' do + lambda do + CleanApiDefenderStatisticsJob.perform + end.should_not raise_exception + end + + it 'ensures that cleans only old statistics' do + today = Date.today + Timecop.freeze(today) do + key1 = "throttle:key1:#{today.strftime('%Y-%m-%d')}" + key2 = "throttle:key2:#{today.strftime('%Y-%m-%d')}T01" + key3 = "throttle:key1:#{(today - 32.days).strftime('%Y-%m-%d')}" + key4 = "throttle:key2:#{(today - 32.days).strftime('%Y-%m-%d')}T01" + key5 = "other:throttle:key:#{(today - 32.days).strftime('%Y-%m-%d')}" + @redis_instance.set key1, 1 + @redis_instance.set key2, 1 + @redis_instance.set key3, 1 + @redis_instance.set key4, 1 + @redis_instance.set key5, 1 + + CleanApiDefenderStatisticsJob.perform + @redis_instance.keys.should include(key1, key2, key5) + @redis_instance.keys.should_not include(key3, key4) + end + end + +end From 37be95b9aef2eaecd5e5b2f21ed611ca9020347d Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 5 Apr 2014 23:20:44 +0400 Subject: [PATCH 10/43] Updated comments --- app/jobs/clean_api_defender_statistics_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/jobs/clean_api_defender_statistics_job.rb b/app/jobs/clean_api_defender_statistics_job.rb index 788534917..6fea6e786 100644 --- a/app/jobs/clean_api_defender_statistics_job.rb +++ b/app/jobs/clean_api_defender_statistics_job.rb @@ -8,7 +8,7 @@ class CleanApiDefenderStatisticsJob # See: https://github.com/datagraph/rack-throttle/blob/master/lib/rack/throttle/daily.rb#L41 # Formats: # 'throttle:uname:%Y-%m-%dT%H', 'throttle:uname:%Y-%m-%d' - # example: "throttle:proyvind:2014-01-25T20", "throttle:proyvind:2014-01-25" + # example: "throttle:uname1:2014-01-25T20", "throttle:uname1:2014-01-25" date = key.gsub(/.*:/, '').gsub(/T.*/, '') Redis.current.del(key) if Date.parse(date) < deadline end From c41fc4d0bb41a2c7ad560791be3c6179aa55823a Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Mon, 7 Apr 2014 23:00:42 +0400 Subject: [PATCH 11/43] #373: added use_cached_chroot field --- .../projects/build_lists_controller.rb | 4 ++-- app/models/build_list.rb | 15 ++++++++++++--- app/views/api/v1/build_lists/show.json.jbuilder | 2 +- .../projects/build_lists/_new_form.html.haml | 7 ++----- app/views/projects/build_lists/show.html.haml | 3 +++ config/locales/models/build_list.en.yml | 1 + config/locales/models/build_list.ru.yml | 1 + ...7181059_add_use_cached_chroot_to_build_list.rb | 11 +++++++++++ db/schema.rb | 3 ++- 9 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 db/migrate/20140407181059_add_use_cached_chroot_to_build_list.rb diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb index 16f8ca298..97bf9437d 100644 --- a/app/controllers/projects/build_lists_controller.rb +++ b/app/controllers/projects/build_lists_controller.rb @@ -190,12 +190,12 @@ class Projects::BuildListsController < Projects::BaseController def create_from_build_list return if params[:build_list_id].blank? - build_list = BuildList.find(params[:build_list_id]) + @build_list = @project.build_lists.find(params[:build_list_id]) params[:build_list] ||= {} keys = [:save_to_repository_id, :auto_publish_status, :include_repos, :extra_params, :project_version, :update_type, :auto_create_container, - :extra_repositories, :extra_build_lists, :build_for_platform_id] + :extra_repositories, :extra_build_lists, :build_for_platform_id, :use_cached_chroot] keys.each { |key| params[:build_list][key] = build_list.send(key) } params[:arches] = [build_list.arch_id.to_s] [:owner_filter, :status_filter].each { |t| params[t] = 'true' if %w(true undefined).exclude? params[t] } diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 83e10413a..9ac0694ec 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -30,8 +30,15 @@ class BuildList < ActiveRecord::Base AUTO_PUBLISH_STATUS_TESTING = 'testing' AUTO_PUBLISH_STATUSES = [AUTO_PUBLISH_STATUS_NONE, AUTO_PUBLISH_STATUS_DEFAULT, AUTO_PUBLISH_STATUS_TESTING] - validates :project_id, :project_version, :arch, :include_repos, - :build_for_platform_id, :save_to_platform_id, :save_to_repository_id, presence: true + validates :project_id, + :project_version, + :arch, + :include_repos, + :build_for_platform_id, + :save_to_platform_id, + :use_cached_chroot, + :save_to_repository_id, + presence: true validates_numericality_of :priority, greater_than_or_equal_to: 0 validates :external_nodes, inclusion: { in: EXTERNAL_NODES }, allow_blank: true validates :auto_publish_status, inclusion: { in: AUTO_PUBLISH_STATUSES } @@ -64,7 +71,8 @@ class BuildList < ActiveRecord::Base :arch_id, :project_id, :save_to_repository_id, :update_type, :save_to_platform_id, :project_version, :auto_create_container, :extra_repositories, :extra_build_lists, :extra_params, :external_nodes, - :include_testing_subrepository, :auto_publish_status + :include_testing_subrepository, :auto_publish_status, + :use_cached_chroot LIVE_TIME = 4.week # for unpublished MAX_LIVE_TIME = 3.month # for published @@ -508,6 +516,7 @@ class BuildList < ActiveRecord::Base cmd_params = { 'GIT_PROJECT_ADDRESS' => git_project_address, 'COMMIT_HASH' => commit_hash, + 'USE_CACHED_CHROOT' => use_cached_chroot?, 'EXTRA_CFG_OPTIONS' => extra_params['cfg_options'], 'EXTRA_CFG_URPM_OPTIONS' => extra_params['cfg_urpm_options'], 'EXTRA_BUILD_SRC_RPM_OPTIONS' => extra_params['build_src_rpm'], diff --git a/app/views/api/v1/build_lists/show.json.jbuilder b/app/views/api/v1/build_lists/show.json.jbuilder index 2e7718912..0d8d119c3 100644 --- a/app/views/api/v1/build_lists/show.json.jbuilder +++ b/app/views/api/v1/build_lists/show.json.jbuilder @@ -2,7 +2,7 @@ json.build_list do json.(@build_list, :id, :container_status, :status, :duration) json.(@build_list, :update_type, :priority, :new_core) json.(@build_list, :advisory, :mass_build) - json.(@build_list, :auto_publish_status, :package_version, :commit_hash, :last_published_commit_hash, :auto_create_container) + json.(@build_list, :auto_publish_status, :package_version, :commit_hash, :last_published_commit_hash, :auto_create_container, :use_cached_chroot) json.build_log_url log_build_list_path(@build_list) if @build_list.container_published? diff --git a/app/views/projects/build_lists/_new_form.html.haml b/app/views/projects/build_lists/_new_form.html.haml index 2b60680c1..6e319d2c5 100644 --- a/app/views/projects/build_lists/_new_form.html.haml +++ b/app/views/projects/build_lists/_new_form.html.haml @@ -46,12 +46,9 @@ - selected = params[:build_list].try(:[], :auto_publish_status) ? {selected: params[:build_list][:auto_publish_status]} : {} = f.select :auto_publish_status, auto_publish_statuses, selected = f.label :auto_publish_status - .both - - %i(auto_create_container include_testing_subrepository).each do |kind| + - %i(auto_create_container include_testing_subrepository use_cached_chroot).each do |kind| .both - - checked, field = params[:build_list].try(:[], kind), "build_list[#{kind}]" - = hidden_field_tag field, false, id: nil - = check_box_tag field, true, checked + = f.check_box kind = f.label kind .both - selected = params[:build_list].try(:[], :external_nodes) ? {selected: params[:build_list][:external_nodes]} : {} diff --git a/app/views/projects/build_lists/show.html.haml b/app/views/projects/build_lists/show.html.haml index 4215b6d25..fcf3241d1 100644 --- a/app/views/projects/build_lists/show.html.haml +++ b/app/views/projects/build_lists/show.html.haml @@ -63,6 +63,9 @@ .leftlist= t("activerecord.attributes.build_list.auto_create_container") .rightlist= t("layout.#{@build_list.auto_create_container?}_") .both + .leftlist= t("activerecord.attributes.build_list.use_cached_chroot") + .rightlist= t("layout.#{@build_list.use_cached_chroot?}_") + .both .leftlist= t("activerecord.attributes.build_list.project_version") .rightlist= link_to @build_list.project_version, tree_path(@build_list.project, @build_list.project_version) .both diff --git a/config/locales/models/build_list.en.yml b/config/locales/models/build_list.en.yml index 651c6a10d..da920d984 100644 --- a/config/locales/models/build_list.en.yml +++ b/config/locales/models/build_list.en.yml @@ -10,6 +10,7 @@ en: extra_repositories: Extra repositories extra_build_lists: Extra build lists auto_create_container: Create container automatically + use_cached_chroot: Use cached chroot container_path: Container path status: Status project_id: Project diff --git a/config/locales/models/build_list.ru.yml b/config/locales/models/build_list.ru.yml index c20f0b33d..4ea7165e5 100644 --- a/config/locales/models/build_list.ru.yml +++ b/config/locales/models/build_list.ru.yml @@ -10,6 +10,7 @@ ru: extra_repositories: Дополнительные репозитории extra_build_lists: Дополнительные сборки auto_create_container: Создать контейнер автоматически + use_cached_chroot: Использовать кэшированный chroot container_path: Путь до контейнера status: Статус project_id: Проект diff --git a/db/migrate/20140407181059_add_use_cached_chroot_to_build_list.rb b/db/migrate/20140407181059_add_use_cached_chroot_to_build_list.rb new file mode 100644 index 000000000..8909c5e83 --- /dev/null +++ b/db/migrate/20140407181059_add_use_cached_chroot_to_build_list.rb @@ -0,0 +1,11 @@ +class AddUseCachedChrootToBuildList < ActiveRecord::Migration + def change + # Make existing build_lists 'false', but default to 'true' in the future. + add_column :build_lists, :use_cached_chroot, :boolean, null: false, default: false + change_column :build_lists, :use_cached_chroot, :boolean, null: false, default: true + end + + def down + remove_column :build_lists, :use_cached_chroot + end +end diff --git a/db/schema.rb b/db/schema.rb index f7f7e1d11..59c1f068d 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: 20140306102620) do +ActiveRecord::Schema.define(version: 20140407181059) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -140,6 +140,7 @@ ActiveRecord::Schema.define(version: 20140306102620) do t.integer "builder_id" t.boolean "include_testing_subrepository" t.string "auto_publish_status", default: "default", null: false + t.boolean "use_cached_chroot", default: true, null: false t.index ["advisory_id"], :name => "index_build_lists_on_advisory_id" t.index ["arch_id"], :name => "index_build_lists_on_arch_id" t.index ["mass_build_id", "status"], :name => "index_build_lists_on_mass_build_id_and_status" From 7d0b2998dc05ec0c0c914c7685e0681094b64929 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 01:30:01 +0400 Subject: [PATCH 12/43] #373: refactoring, added specs --- .../api/v1/platforms_controller.rb | 24 +++++++++++-- app/models/platform.rb | 36 +++++++++++-------- config/routes.rb | 5 +-- .../api/v1/platforms_controller_spec.rb | 14 ++++++++ 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/v1/platforms_controller.rb b/app/controllers/api/v1/platforms_controller.rb index 4fdeccf63..d8b8c2b53 100644 --- a/app/controllers/api/v1/platforms_controller.rb +++ b/app/controllers/api/v1/platforms_controller.rb @@ -1,12 +1,14 @@ class Api::V1::PlatformsController < Api::V1::BaseController before_filter :authenticate_user! skip_before_filter :authenticate_user!, only: :allowed - skip_before_filter :authenticate_user!, only: [:show, :platforms_for_build, :members] if APP_CONFIG['anonymous_access'] + skip_before_filter :authenticate_user!, only: %i(show platforms_for_build members cached_chroot) if APP_CONFIG['anonymous_access'] + before_filter :set_token, only: %i(allowed cached_chroot) - load_and_authorize_resource except: :allowed + load_and_authorize_resource except: %i(allowed cached_chroot) + load_resource only: :cached_chroot def allowed - if Platform.allowed?(params[:path] || '', request) + if Platform.allowed?(params[:path] || '', @token) render nothing: true else render nothing: true, status: 403 @@ -21,6 +23,14 @@ class Api::V1::PlatformsController < Api::V1::BaseController def show end + def cached_chroot + if sha1 = @platform.cached_chroot(@token, params[:arch]) + redirect_to "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}" + else + render nothing: true, status: 403 + end + end + def platforms_for_build @platforms = Platform.main.opened.paginate(paginate_params) render :index @@ -72,4 +82,12 @@ class Api::V1::PlatformsController < Api::V1::BaseController destroy_subject @platform end + protected + + def set_token + if request.authorization.present? + @token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) + end + end + end diff --git a/app/models/platform.rb b/app/models/platform.rb index 7b8fbc5fc..b1b5fe8f5 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -7,6 +7,7 @@ class Platform < ActiveRecord::Base include Owner include EventLoggable + CACHED_CHROOT_PRODUCT_NAME = 'cached-chroot' AUTOMATIC_METADATA_REGENERATIONS = %w(day week) VISIBILITIES = %w(open hidden) NAME_PATTERN = /[\w\-\.]+/ @@ -211,34 +212,41 @@ class Platform < ActiveRecord::Base end # Checks access rights to platform and caching for 1 day. - def self.allowed?(path, request) + def self.allowed?(path, token) platform_name = path.gsub(/^[\/]+/, '') .match(/^(#{NAME_PATTERN}\/|#{NAME_PATTERN}$)/) return true unless platform_name platform_name = platform_name[0].gsub(/\//, '') - if request.authorization.present? - token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) - end - Rails.cache.fetch([platform_name, token, :platform_allowed], expires_in: 2.minutes) do platform = Platform.find_by name: platform_name next false unless platform next true unless platform.hidden? next false unless token - next true if platform.tokens.by_active.where(authentication_token: token).exists? - - user = User.find_by authentication_token: token - current_ability = Ability.new(user) - if user && current_ability.can?(:show, platform) - true - else - false - end + platform.has_access?(token) end end + def cached_chroot(token, arch) + return false if personal? + Rails.cache.fetch([:cached_chroot, token, name, arch], expires_in: 10.minutes) do + product = products.where(name: CACHED_CHROOT_PRODUCT_NAME).first + next false unless product + pbl = product.product_build_lists.for_status(ProductBuildList::BUILD_COMPLETED).recent.first + next false unless pbl + next false if hidden? && !has_access?(token) + pbl.results.results.find{ |r| r['file_name'] =~ /^cached-chroot-#{arch}/ } || false + end + end + + def has_access?(token) + return true if tokens.by_active.where(authentication_token: token).exists? + user = User.find_by(authentication_token: token) + current_ability = Ability.new(user) + user && current_ability.can?(:show, self) ? true : false + end + def self.autostart_metadata_regeneration(value) Platform.main.where(automatic_metadata_regeneration: value).each(&:regenerate) end diff --git a/config/routes.rb b/config/routes.rb index 10f43ecef..96c4bda6b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,13 +33,14 @@ Rosa::Application.routes.draw do put :publish_into_testing } end - resources :arches, only: [:index] - resources :platforms, only: [:index, :show, :update, :destroy, :create] do + resources :arches, only: :index + resources :platforms, only: %i(index show update destroy create), constraints: { id: Platform::NAME_PATTERN } do collection { get :platforms_for_build get :allowed } member { + get :cached_chroot get :members put :add_member delete :remove_member diff --git a/spec/controllers/api/v1/platforms_controller_spec.rb b/spec/controllers/api/v1/platforms_controller_spec.rb index b30d0f061..68735259f 100644 --- a/spec/controllers/api/v1/platforms_controller_spec.rb +++ b/spec/controllers/api/v1/platforms_controller_spec.rb @@ -12,6 +12,7 @@ shared_examples_for 'api platform user with reader rights' do get :members, id: @platform.id, format: :json response.should render_template(:members) end + end shared_examples_for 'api platform user with owner rights' do @@ -192,6 +193,12 @@ shared_examples_for 'api platform user without reader rights for hidden platform response.body.should == {"message" => "Access violation to this page!"}.to_json end end + + it "should not be able to perform cached_chroot action" do + get :cached_chroot, id: @platform.id, format: :json + response.status.should == 403 + end + end shared_examples_for "api platform user with show rights" do @@ -200,6 +207,13 @@ shared_examples_for "api platform user with show rights" do response.should render_template(:show) end + it 'should be able to perform cached_chroot action' do + Rails.stub_chain(:cache, :fetch).and_return('sha1') + http_login (@admin || @user).authentication_token, '' if @platform.hidden? + get :cached_chroot, id: @platform.id, format: :json + response.should redirect_to("#{APP_CONFIG['file_store_url']}/api/v1/file_stores/sha1") + end + it 'should be able to perform platforms_for_build action' do get :platforms_for_build, format: :json response.should render_template(:index) From 81c3f6aaa636e6d7d2d8bde26ed61069e4bb2eff Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 01:37:11 +0400 Subject: [PATCH 13/43] #373: rollback changes --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 108af5fc9..8e9a5336d 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -18,7 +18,7 @@ class Ability can :read, Issue, project: { visibility: 'open' } can [:read, :commits, :files], PullRequest, to_project: {visibility: 'open'} can [:read, :log, :everything], BuildList, project: {visibility: 'open'} - can [:read, :log], ProductBuildList#, product: {platform: {visibility: 'open'}} # double nested hash don't work + can [:read, :log], ProductBuildList, product: {platform: {visibility: 'open'}} can [:read, :search], Advisory # Platforms block From 02d291a032dfb7b6392544f620c5126c256e6dba Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 01:51:21 +0400 Subject: [PATCH 14/43] #373: send token to product_build_list --- app/models/product_build_list.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 884b8b31f..e9bec061e 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -34,6 +34,8 @@ class ProductBuildList < ActiveRecord::Base BUILD_CANCELING => :build_canceling }.freeze + CACHED_CHROOT_TOKEN_DESCRIPTION = 'cached-chroot' + belongs_to :product belongs_to :project belongs_to :arch @@ -164,14 +166,22 @@ class ProductBuildList < ActiveRecord::Base 'tar.gz', opts ) + + cmd_params = "BUILD_ID=#{id} " + if product.platform.hidden? + token = product.platform.tokens.by_active.where(description: CACHED_CHROOT_TOKEN_DESCRIPTION).first + cmd_params << "TOKEN=#{token.authentication_token} " if token + end + cmd_params << params.to_s + { id: id, # TODO: remove comment # srcpath: 'http://dl.dropbox.com/u/945501/avokhmin-test-iso-script-5d9b463d4e9c06ea8e7c89e1b7ff5cb37e99e27f.tar.gz', - srcpath: srcpath, - params: ("BUILD_ID=#{id} " << params.to_s), - time_living: time_living, - main_script: main_script, + srcpath: srcpath, + params: cmd_params, + time_living: time_living, + main_script: main_script, platform: { type: product.platform.distrib_type, name: product.platform.name, From 0bae4d30f8f59292b709603c706dd1932ec8e4dd Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 01:54:12 +0400 Subject: [PATCH 15/43] #373: rollback changes --- app/controllers/projects/build_lists_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb index 97bf9437d..96254d147 100644 --- a/app/controllers/projects/build_lists_controller.rb +++ b/app/controllers/projects/build_lists_controller.rb @@ -190,7 +190,7 @@ class Projects::BuildListsController < Projects::BaseController def create_from_build_list return if params[:build_list_id].blank? - @build_list = @project.build_lists.find(params[:build_list_id]) + build_list = @project.build_lists.find(params[:build_list_id]) params[:build_list] ||= {} keys = [:save_to_repository_id, :auto_publish_status, :include_repos, :extra_params, From 6e584e1ec9366c2dadc8b7d411cf31d5c93a6f35 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 01:56:13 +0400 Subject: [PATCH 16/43] #373: cleanup --- app/models/platform.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/platform.rb b/app/models/platform.rb index b1b5fe8f5..467466fe6 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -223,7 +223,6 @@ class Platform < ActiveRecord::Base platform = Platform.find_by name: platform_name next false unless platform next true unless platform.hidden? - next false unless token platform.has_access?(token) end end @@ -241,7 +240,8 @@ class Platform < ActiveRecord::Base end def has_access?(token) - return true if tokens.by_active.where(authentication_token: token).exists? + return false if token.blank? + return true if tokens.by_active.where(authentication_token: token).exists? user = User.find_by(authentication_token: token) current_ability = Ability.new(user) user && current_ability.can?(:show, self) ? true : false From afb3b183c8471c6a5c70ea012a301db732a837cd Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 02:12:22 +0400 Subject: [PATCH 17/43] #373: rollback changes --- app/views/projects/build_lists/_new_form.html.haml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/projects/build_lists/_new_form.html.haml b/app/views/projects/build_lists/_new_form.html.haml index 6e319d2c5..7ecb3a86e 100644 --- a/app/views/projects/build_lists/_new_form.html.haml +++ b/app/views/projects/build_lists/_new_form.html.haml @@ -48,7 +48,9 @@ = f.label :auto_publish_status - %i(auto_create_container include_testing_subrepository use_cached_chroot).each do |kind| .both - = f.check_box kind + - checked = params[:build_list].try(:[], kind) + - checked = @build_list.send(kind) if checked.nil? + = f.check_box kind, checked: checked = f.label kind .both - selected = params[:build_list].try(:[], :external_nodes) ? {selected: params[:build_list][:external_nodes]} : {} From 7842f72eb3f04b2618f6ff9f02f89aedee271785 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 17:00:39 +0400 Subject: [PATCH 18/43] Fixed: Access violation to this page --- app/controllers/api/v1/base_controller.rb | 28 ----------------- app/controllers/application_controller.rb | 30 +++++++++++++++++++ .../projects/git/base_controller.rb | 5 +++- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index 712173c44..f06fb29ee 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -13,34 +13,6 @@ class Api::V1::BaseController < ApplicationController protected - # For this example, we are simply using token authentication - # via parameters. However, anyone could use Rails's token - # authentication features to get the token from a header. - def authenticate_user! - user_token = params[:authentication_token].presence - unless user_token - credentials = decode_credentials.select(&:present?) - user_token = credentials.first if credentials.size == 1 - end - user = user_token && User.find_by_authentication_token(user_token.to_s) - - if user - # Notice we are passing store false, so the user is not - # actually stored in the session and a token is needed - # for every request. If you want the token to work as a - # sign in token, you can simply remove store: false. - sign_in user, store: false - else - super - end - end - - # Helper to decode credentials from HTTP. - def decode_credentials - return [] unless request.authorization && request.authorization =~ /^Basic (.*)/m - Base64.decode64($1).split(/:/, 2) - end - def set_csv_file_headers(file_name) headers['Content-Type'] = 'text/csv' headers['Content-disposition'] = "attachment; filename=\"#{file_name}.csv\"" diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e92eae50e..c717b55db 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -37,6 +37,36 @@ class ApplicationController < ActionController::Base protected + # For this example, we are simply using token authentication + # via parameters. However, anyone could use Rails's token + # authentication features to get the token from a header. + def authenticate_user! + if user = find_user_by_token + # Notice we are passing store false, so the user is not + # actually stored in the session and a token is needed + # for every request. If you want the token to work as a + # sign in token, you can simply remove store: false. + sign_in user, store: false + else + super + end + end + + def authenticate_user + if user = find_user_by_token + sign_in user, store: false + end + end + + def find_user_by_token + user_token = params[:authentication_token].presence + if user_token.blank? && request.authorization.present? + token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) + user_token = token if pass.blank? + end + user = user_token && User.find_by_authentication_token(user_token.to_s) + end + def render_500(e) #check for exceptions Airbrake ignores by default and exclude them from manual Airbrake notification if Rails.env.production? && !AIRBRAKE_IGNORE.include?(e.class) diff --git a/app/controllers/projects/git/base_controller.rb b/app/controllers/projects/git/base_controller.rb index 6608f073f..203c746ed 100644 --- a/app/controllers/projects/git/base_controller.rb +++ b/app/controllers/projects/git/base_controller.rb @@ -1,6 +1,9 @@ class Projects::Git::BaseController < Projects::BaseController before_filter :authenticate_user! - skip_before_filter :authenticate_user!, only: [:show, :index, :blame, :raw, :archive, :diff, :tags, :branches] if APP_CONFIG['anonymous_access'] + if APP_CONFIG['anonymous_access'] + skip_before_filter :authenticate_user!, only: %i(show index blame raw archive diff tags branches) + before_filter :authenticate_user, only: %i(show index blame raw archive diff tags branches) + end load_and_authorize_resource :project before_filter :set_treeish_and_path From 35a2be81cf8ec7a0439103dd05614e855dcae790 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 9 Apr 2014 01:07:50 +0400 Subject: [PATCH 19/43] #373: rollback changes --- .../api/v1/platforms_controller.rb | 28 ++++--------------- app/models/build_list.rb | 9 ++++-- app/models/platform.rb | 22 ++++++--------- config/routes.rb | 3 +- .../api/v1/platforms_controller_spec.rb | 13 --------- 5 files changed, 23 insertions(+), 52 deletions(-) diff --git a/app/controllers/api/v1/platforms_controller.rb b/app/controllers/api/v1/platforms_controller.rb index d8b8c2b53..52bc77c46 100644 --- a/app/controllers/api/v1/platforms_controller.rb +++ b/app/controllers/api/v1/platforms_controller.rb @@ -1,14 +1,14 @@ class Api::V1::PlatformsController < Api::V1::BaseController before_filter :authenticate_user! skip_before_filter :authenticate_user!, only: :allowed - skip_before_filter :authenticate_user!, only: %i(show platforms_for_build members cached_chroot) if APP_CONFIG['anonymous_access'] - before_filter :set_token, only: %i(allowed cached_chroot) - - load_and_authorize_resource except: %i(allowed cached_chroot) - load_resource only: :cached_chroot + skip_before_filter :authenticate_user!, only: [:show, :platforms_for_build, :members] if APP_CONFIG['anonymous_access'] + load_and_authorize_resource except: :allowed def allowed - if Platform.allowed?(params[:path] || '', @token) + if request.authorization.present? + token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) + end + if Platform.allowed?(params[:path] || '', token) render nothing: true else render nothing: true, status: 403 @@ -23,14 +23,6 @@ class Api::V1::PlatformsController < Api::V1::BaseController def show end - def cached_chroot - if sha1 = @platform.cached_chroot(@token, params[:arch]) - redirect_to "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}" - else - render nothing: true, status: 403 - end - end - def platforms_for_build @platforms = Platform.main.opened.paginate(paginate_params) render :index @@ -82,12 +74,4 @@ class Api::V1::PlatformsController < Api::V1::BaseController destroy_subject @platform end - protected - - def set_token - if request.authorization.present? - @token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) - end - end - end diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 9ac0694ec..08fca978d 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -513,15 +513,20 @@ class BuildList < ActiveRecord::Base git_project_address = project.git_project_address user # git_project_address.gsub!(/^http:\/\/(0\.0\.0\.0|localhost)\:[\d]+/, 'https://abf.rosalinux.ru') unless Rails.env.production? + cmd_params = { 'GIT_PROJECT_ADDRESS' => git_project_address, 'COMMIT_HASH' => commit_hash, - 'USE_CACHED_CHROOT' => use_cached_chroot?, 'EXTRA_CFG_OPTIONS' => extra_params['cfg_options'], 'EXTRA_CFG_URPM_OPTIONS' => extra_params['cfg_urpm_options'], 'EXTRA_BUILD_SRC_RPM_OPTIONS' => extra_params['build_src_rpm'], 'EXTRA_BUILD_RPM_OPTIONS' => extra_params['build_rpm'] - }.map{ |k, v| "#{k}='#{v}'" }.join(' ') + } + if use_cached_chroot? + sha1 = build_for_platform.cached_chroot(arch.name) + cmd_params.merge!('CACHED_CHROOT_SHA1' => sha1) if sha1.present? + end + cmd_params = cmd_params.map{ |k, v| "#{k}='#{v}'" }.join(' ') { id: id, diff --git a/app/models/platform.rb b/app/models/platform.rb index 467466fe6..c3af78768 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -223,30 +223,26 @@ class Platform < ActiveRecord::Base platform = Platform.find_by name: platform_name next false unless platform next true unless platform.hidden? - platform.has_access?(token) + return false if token.blank? + return true if platform.tokens.by_active.where(authentication_token: token).exists? + user = User.find_by(authentication_token: token) + current_ability = Ability.new(user) + user && current_ability.can?(:show, platform) ? true : false end end - def cached_chroot(token, arch) + def cached_chroot(arch) return false if personal? - Rails.cache.fetch([:cached_chroot, token, name, arch], expires_in: 10.minutes) do + Rails.cache.fetch([:cached_chroot, name, arch], expires_in: 10.minutes) do product = products.where(name: CACHED_CHROOT_PRODUCT_NAME).first next false unless product pbl = product.product_build_lists.for_status(ProductBuildList::BUILD_COMPLETED).recent.first next false unless pbl - next false if hidden? && !has_access?(token) - pbl.results.results.find{ |r| r['file_name'] =~ /^cached-chroot-#{arch}/ } || false + result = pbl.results.results.find{ |r| r['file_name'] =~ /-#{arch}.tar.gz$/ } + result.present? ? result['sha1'] : false end end - def has_access?(token) - return false if token.blank? - return true if tokens.by_active.where(authentication_token: token).exists? - user = User.find_by(authentication_token: token) - current_ability = Ability.new(user) - user && current_ability.can?(:show, self) ? true : false - end - def self.autostart_metadata_regeneration(value) Platform.main.where(automatic_metadata_regeneration: value).each(&:regenerate) end diff --git a/config/routes.rb b/config/routes.rb index 96c4bda6b..52b31fc5b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,13 +34,12 @@ Rosa::Application.routes.draw do } end resources :arches, only: :index - resources :platforms, only: %i(index show update destroy create), constraints: { id: Platform::NAME_PATTERN } do + resources :platforms, only: %i(index show update destroy create) do collection { get :platforms_for_build get :allowed } member { - get :cached_chroot get :members put :add_member delete :remove_member diff --git a/spec/controllers/api/v1/platforms_controller_spec.rb b/spec/controllers/api/v1/platforms_controller_spec.rb index 68735259f..f4096a858 100644 --- a/spec/controllers/api/v1/platforms_controller_spec.rb +++ b/spec/controllers/api/v1/platforms_controller_spec.rb @@ -193,12 +193,6 @@ shared_examples_for 'api platform user without reader rights for hidden platform response.body.should == {"message" => "Access violation to this page!"}.to_json end end - - it "should not be able to perform cached_chroot action" do - get :cached_chroot, id: @platform.id, format: :json - response.status.should == 403 - end - end shared_examples_for "api platform user with show rights" do @@ -207,13 +201,6 @@ shared_examples_for "api platform user with show rights" do response.should render_template(:show) end - it 'should be able to perform cached_chroot action' do - Rails.stub_chain(:cache, :fetch).and_return('sha1') - http_login (@admin || @user).authentication_token, '' if @platform.hidden? - get :cached_chroot, id: @platform.id, format: :json - response.should redirect_to("#{APP_CONFIG['file_store_url']}/api/v1/file_stores/sha1") - end - it 'should be able to perform platforms_for_build action' do get :platforms_for_build, format: :json response.should render_template(:index) From 4a3068ce427dc20553dc785fb5a416a65e35e512 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 9 Apr 2014 01:16:36 +0400 Subject: [PATCH 20/43] #373: misprint --- app/models/platform.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/platform.rb b/app/models/platform.rb index c3af78768..1f043350e 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -238,7 +238,7 @@ class Platform < ActiveRecord::Base next false unless product pbl = product.product_build_lists.for_status(ProductBuildList::BUILD_COMPLETED).recent.first next false unless pbl - result = pbl.results.results.find{ |r| r['file_name'] =~ /-#{arch}.tar.gz$/ } + result = pbl.results.find{ |r| r['file_name'] =~ /-#{arch}.tar.gz$/ } result.present? ? result['sha1'] : false end end From 09f14687add799e4acc67780bab2eb3664435d63 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Wed, 9 Apr 2014 12:28:02 +0600 Subject: [PATCH 21/43] fix edit password url --- app/views/devise/mailer/reset_password_instructions.en.haml | 2 +- app/views/devise/mailer/reset_password_instructions.ru.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/devise/mailer/reset_password_instructions.en.haml b/app/views/devise/mailer/reset_password_instructions.en.haml index 0dc18ebde..cd1d6d736 100644 --- a/app/views/devise/mailer/reset_password_instructions.en.haml +++ b/app/views/devise/mailer/reset_password_instructions.en.haml @@ -1,7 +1,7 @@ %p Hello #{@resource.email}! %p Someone has requested a link to change your password, and you can do this through the link below. -%p= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @resource.reset_password_token) +%p= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %p If you didn't request this, please ignore this email. %p Your password won't change until you access the link above and create a new one. %br diff --git a/app/views/devise/mailer/reset_password_instructions.ru.haml b/app/views/devise/mailer/reset_password_instructions.ru.haml index e89020a59..007c21e27 100644 --- a/app/views/devise/mailer/reset_password_instructions.ru.haml +++ b/app/views/devise/mailer/reset_password_instructions.ru.haml @@ -1,7 +1,7 @@ %p Здравствуйте, #{@resource.email}! %p Кто-то запросил смену Вашего пароля. Чтобы сменить пароль, перейдите по ссылке снизу. -%p= link_to 'Сменить пароль', edit_password_url(@resource, reset_password_token: @resource.reset_password_token) +%p= link_to 'Сменить пароль', edit_password_url(@resource, reset_password_token: @rtoken) %p Пожалуйста, проигнорируйте это письмо, если оно попало к Вам по ошибке. %p Ваш пароль не поменяется, пока вы не перейдете по ссылке и не создадите новый. %br From 80cd7bcd52181cf44d970027da31ccdf8bf42c4f Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Wed, 9 Apr 2014 12:43:12 +0600 Subject: [PATCH 22/43] fix mistype with reset password token --- app/views/devise/mailer/reset_password_instructions.ru.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/devise/mailer/reset_password_instructions.ru.haml b/app/views/devise/mailer/reset_password_instructions.ru.haml index 007c21e27..cfc8cd369 100644 --- a/app/views/devise/mailer/reset_password_instructions.ru.haml +++ b/app/views/devise/mailer/reset_password_instructions.ru.haml @@ -1,7 +1,7 @@ %p Здравствуйте, #{@resource.email}! %p Кто-то запросил смену Вашего пароля. Чтобы сменить пароль, перейдите по ссылке снизу. -%p= link_to 'Сменить пароль', edit_password_url(@resource, reset_password_token: @rtoken) +%p= link_to 'Сменить пароль', edit_password_url(@resource, reset_password_token: @token) %p Пожалуйста, проигнорируйте это письмо, если оно попало к Вам по ошибке. %p Ваш пароль не поменяется, пока вы не перейдете по ссылке и не создадите новый. %br From 0000487cf806286618fcb6a761ef105059c3c67e Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Wed, 9 Apr 2014 14:41:56 +0600 Subject: [PATCH 23/43] fix authenticate_user method --- app/controllers/application_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c717b55db..8e7e582ad 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -55,6 +55,8 @@ class ApplicationController < ActionController::Base def authenticate_user if user = find_user_by_token sign_in user, store: false + else + super end end From 8a2aa1f6660a3fb36f62df25237833a31e438134 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 9 Apr 2014 12:46:09 +0400 Subject: [PATCH 24/43] #373: remove validation for use_cached_chroot --- app/models/build_list.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 08fca978d..54fe6ca5d 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -36,7 +36,6 @@ class BuildList < ActiveRecord::Base :include_repos, :build_for_platform_id, :save_to_platform_id, - :use_cached_chroot, :save_to_repository_id, presence: true validates_numericality_of :priority, greater_than_or_equal_to: 0 From 2aec96d989e463afeecdc9eda2aa72ae7b9a5f6e Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Wed, 9 Apr 2014 14:52:42 +0600 Subject: [PATCH 25/43] Revert "fix authenticate_user method" This reverts commit 0000487cf806286618fcb6a761ef105059c3c67e. --- app/controllers/application_controller.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8e7e582ad..c717b55db 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -55,8 +55,6 @@ class ApplicationController < ActionController::Base def authenticate_user if user = find_user_by_token sign_in user, store: false - else - super end end From 2ecf2c1d91ae57df093a143a4972f69146cb02b2 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 9 Apr 2014 12:53:53 +0400 Subject: [PATCH 26/43] #373: rollback ability.rb --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 8e9a5336d..108af5fc9 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -18,7 +18,7 @@ class Ability can :read, Issue, project: { visibility: 'open' } can [:read, :commits, :files], PullRequest, to_project: {visibility: 'open'} can [:read, :log, :everything], BuildList, project: {visibility: 'open'} - can [:read, :log], ProductBuildList, product: {platform: {visibility: 'open'}} + can [:read, :log], ProductBuildList#, product: {platform: {visibility: 'open'}} # double nested hash don't work can [:read, :search], Advisory # Platforms block From c65853e072e44d40bfb5e8f5d19cf1c468e3f552 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 9 Apr 2014 22:44:19 +0400 Subject: [PATCH 27/43] #373: added ability to destroy ProductBuildList --- .../product_build_list_controller.js.erb | 9 +++++++++ .../product_build_lists_controller.rb | 11 +++-------- app/models/product_build_list.rb | 6 +++++- .../product_build_lists/show.html.haml | 19 ++++++++++--------- .../product_build_lists/show.json.jbuilder | 3 ++- config/routes.rb | 2 +- .../product_build_lists_controller_spec.rb | 8 +++++++- 7 files changed, 37 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb b/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb index 33875bc07..972f5718c 100644 --- a/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb +++ b/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb @@ -28,4 +28,13 @@ RosaABF.controller('ProductBuildListController', ['$scope', '$http', '$timeout', } $scope.refresh(); + $scope.updateStatus = function() { + $http.put( + Routes.product_build_list_path($scope.id), + {product_build_list: {not_delete: $scope.not_delete}, format: 'json'} + ).success(function(results) { + $scope.getProductBuildList(); + }); + } + }]); \ No newline at end of file diff --git a/app/controllers/platforms/product_build_lists_controller.rb b/app/controllers/platforms/product_build_lists_controller.rb index 91ad44d67..3a93c5f40 100644 --- a/app/controllers/platforms/product_build_lists_controller.rb +++ b/app/controllers/platforms/product_build_lists_controller.rb @@ -3,7 +3,7 @@ class Platforms::ProductBuildListsController < Platforms::BaseController before_filter :authenticate_user! skip_before_filter :authenticate_user!, only: [:index, :show, :log] if APP_CONFIG['anonymous_access'] - before_filter :redirect_to_full_path_if_short_url, only: :show + before_filter :redirect_to_full_path_if_short_url, only: [:show, :update] load_and_authorize_resource :platform, except: :index load_and_authorize_resource :product, through: :platform, except: :index load_and_authorize_resource :product_build_list, through: :product, except: :index @@ -25,13 +25,8 @@ class Platforms::ProductBuildListsController < Platforms::BaseController end def update - if @product_build_list.update_attributes(not_delete: (params[:product_build_list] || {})[:not_delete]) - flash[:notice] = t('flash.product_build_list.updated') - else - flash[:error] = t('flash.product_build_list.update_error') - flash[:warning] = @product_build_list.errors.full_messages.join('. ') - end - redirect_to platform_product_product_build_list_path(@platform, @product, @product_build_list) + @product_build_list.update_attributes(not_delete: (params[:product_build_list] || {})[:not_delete]) + render nothing: true end def cancel diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index e9bec061e..8f3e78951 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -122,8 +122,12 @@ class ProductBuildList < ActiveRecord::Base status == BUILD_CANCELING end + def can_destroy? + ![BUILD_STARTED, BUILD_PENDING, BUILD_CANCELING].include?(status) + end + def can_cancel? - [BUILD_STARTED, BUILD_PENDING].include? status + [BUILD_STARTED, BUILD_PENDING].include?(status) end def event_log_message diff --git a/app/views/platforms/product_build_lists/show.html.haml b/app/views/platforms/product_build_lists/show.html.haml index ba72e27d1..0c2a2e739 100644 --- a/app/views/platforms/product_build_lists/show.html.haml +++ b/app/views/platforms/product_build_lists/show.html.haml @@ -38,17 +38,18 @@ %br - if can?(:update, pbl) - = form_for pbl, - url: platform_product_product_build_list_path(pbl.product.platform,pbl.product, pbl), - html: {'ng-show' => "pbl.status == #{ProductBuildList::BUILD_COMPLETED}"} do |f| - - .leftlist= f.label :not_delete + %div{'ng-show' => "pbl.status == #{ProductBuildList::BUILD_COMPLETED}"} + .leftlist= t('activerecord.attributes.product_build_list.not_delete') .rightlist - = f.select :not_delete, [false, true].collect{|status| [t("layout.#{status}_"), status]}, {selected: pbl.not_delete} - .both - %br - = submit_tag t('layout.update'), data: {'disable-with' => t('layout.processing')} + = select_tag 'not_delete', options_for_select([false, true].map{|status| [t("layout.#{status}_"), status]}), {'ng-model' => "not_delete", 'ng-change' => 'updateStatus()', 'ng-init' => "not_delete = '#{pbl.not_delete}'"} .both + - if can?(:destroy, pbl) + = link_to t('layout.product_build_lists.delete'), + platform_product_product_build_list_path(pbl.product.platform, pbl.product, pbl), + method: :delete, data: { confirm: t("layout.confirm") }, class: 'button', + 'ng-show' => 'pbl.can_destroy' + .both + %br .flash_notify{'ng-hide' => 'pbl.not_delete'} .alert.alert-error - days = pbl.autostarted? ? ProductBuildList::LIVE_TIME : ProductBuildList::MAX_LIVE_TIME diff --git a/app/views/platforms/product_build_lists/show.json.jbuilder b/app/views/platforms/product_build_lists/show.json.jbuilder index 502a92275..767b642f1 100644 --- a/app/views/platforms/product_build_lists/show.json.jbuilder +++ b/app/views/platforms/product_build_lists/show.json.jbuilder @@ -2,7 +2,8 @@ json.product_build_list do json.(@product_build_list, :id, :status, :human_status, :not_delete) json.notified_at l(@product_build_list.updated_at, format: :long) - json.can_cancel @product_build_list.can_cancel? + json.can_cancel @product_build_list.can_cancel? + json.can_destroy @product_build_list.can_destroy? json.results @product_build_list.results do |result| json.file_name result['file_name'] diff --git a/config/routes.rb b/config/routes.rb index 52b31fc5b..c7ad7cf84 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -231,7 +231,7 @@ Rosa::Application.routes.draw do resources :maintainers, only: [:index] end - resources :product_build_lists, only: [:index, :show] + resources :product_build_lists, only: [:index, :show, :update] end resources :autocompletes, only: [] do diff --git a/spec/controllers/platforms/product_build_lists_controller_spec.rb b/spec/controllers/platforms/product_build_lists_controller_spec.rb index ef83e4eb0..85f317886 100644 --- a/spec/controllers/platforms/product_build_lists_controller_spec.rb +++ b/spec/controllers/platforms/product_build_lists_controller_spec.rb @@ -36,7 +36,7 @@ shared_examples_for 'product build list admin' do it 'should be able to perform update action' do put :update, valid_attributes_for_show.merge(product_build_list: {time_living: 100,not_delete: true}) - response.should redirect_to(platform_product_product_build_list_path(@product.platform, @product, @pbl)) + response.should be_success end it "ensures that only not_delete field of product build list has been updated" do @@ -73,6 +73,12 @@ shared_examples_for 'product build list user without admin rights' do put :cancel, valid_attributes_for_show response.should_not redirect_to(platform_product_product_build_list_path(@product.platform, @product, @pbl)) end + + it 'should not be able to perform update action' do + put :update, valid_attributes_for_show + response.should_not be_success + end + end shared_examples_for 'product build list user' do From 4d0453b73847492629a10aa85f3514c21078f508 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 10 Apr 2014 00:07:36 +0400 Subject: [PATCH 28/43] #373: cleanup --- .../controllers/product_build_list_controller.js.erb | 4 ++-- app/controllers/platforms/product_build_lists_controller.rb | 2 +- app/views/platforms/product_build_lists/show.html.haml | 2 +- app/views/platforms/product_build_lists/show.json.jbuilder | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb b/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb index 972f5718c..07d6eb181 100644 --- a/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb +++ b/app/assets/javascripts/angularjs/controllers/product_build_list_controller.js.erb @@ -31,9 +31,9 @@ RosaABF.controller('ProductBuildListController', ['$scope', '$http', '$timeout', $scope.updateStatus = function() { $http.put( Routes.product_build_list_path($scope.id), - {product_build_list: {not_delete: $scope.not_delete}, format: 'json'} + {product_build_list: {not_delete: $scope.pbl.not_delete}, format: 'json'} ).success(function(results) { - $scope.getProductBuildList(); + $scope.pbl = $scope.subject = results.product_build_list; }); } diff --git a/app/controllers/platforms/product_build_lists_controller.rb b/app/controllers/platforms/product_build_lists_controller.rb index 3a93c5f40..e2e22f6c6 100644 --- a/app/controllers/platforms/product_build_lists_controller.rb +++ b/app/controllers/platforms/product_build_lists_controller.rb @@ -26,7 +26,7 @@ class Platforms::ProductBuildListsController < Platforms::BaseController def update @product_build_list.update_attributes(not_delete: (params[:product_build_list] || {})[:not_delete]) - render nothing: true + render :show end def cancel diff --git a/app/views/platforms/product_build_lists/show.html.haml b/app/views/platforms/product_build_lists/show.html.haml index 0c2a2e739..170194d36 100644 --- a/app/views/platforms/product_build_lists/show.html.haml +++ b/app/views/platforms/product_build_lists/show.html.haml @@ -41,7 +41,7 @@ %div{'ng-show' => "pbl.status == #{ProductBuildList::BUILD_COMPLETED}"} .leftlist= t('activerecord.attributes.product_build_list.not_delete') .rightlist - = select_tag 'not_delete', options_for_select([false, true].map{|status| [t("layout.#{status}_"), status]}), {'ng-model' => "not_delete", 'ng-change' => 'updateStatus()', 'ng-init' => "not_delete = '#{pbl.not_delete}'"} + = select_tag 'not_delete', options_for_select([false, true].map{|status| [t("layout.#{status}_"), status]}), {'ng-model' => "pbl.not_delete", 'ng-change' => 'updateStatus()'} .both - if can?(:destroy, pbl) = link_to t('layout.product_build_lists.delete'), diff --git a/app/views/platforms/product_build_lists/show.json.jbuilder b/app/views/platforms/product_build_lists/show.json.jbuilder index 767b642f1..e0d1270c0 100644 --- a/app/views/platforms/product_build_lists/show.json.jbuilder +++ b/app/views/platforms/product_build_lists/show.json.jbuilder @@ -1,7 +1,8 @@ json.product_build_list do - json.(@product_build_list, :id, :status, :human_status, :not_delete) + json.(@product_build_list, :id, :status, :human_status) json.notified_at l(@product_build_list.updated_at, format: :long) + json.not_delete @product_build_list.not_delete?.to_s json.can_cancel @product_build_list.can_cancel? json.can_destroy @product_build_list.can_destroy? From be6bd727a605b8c5d7e1627ea6809f0fe7aa4a25 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 10 Apr 2014 01:20:39 +0400 Subject: [PATCH 29/43] Fixed: Assign container --- app/assets/javascripts/extra/tracker.js | 7 ++++--- app/controllers/projects/base_controller.rb | 6 +++--- app/models/issue.rb | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/extra/tracker.js b/app/assets/javascripts/extra/tracker.js index f287fff87..0c30c20f5 100644 --- a/app/assets/javascripts/extra/tracker.js +++ b/app/assets/javascripts/extra/tracker.js @@ -108,7 +108,8 @@ $(document).ready(function() { $('#search_user').on('keyup', function() { path = $('#search_user_path').attr('path'); data = $(this).serialize(); - dom = $('#manage_issue_users_list'); + // dom = $('#manage_issue_users_list'); + dom = $('#assigned-popup .list'); return search_items(path, data, dom); }); @@ -116,11 +117,11 @@ $(document).ready(function() { $('.users-search-popup').hide(); }); - $('#assigned-container .icon-share').on('click', function() { + $(document).on('click', '#assigned-container .icon-share', function() { $('#assigned-popup').show(); }); - $('#assigned-popup .people.selected').on('click', function() { + $(document).on('click', '#assigned-popup .people.selected', function() { var form = $('#assigned-popup .edit_assignee'); var item = $(this); if (form.length == 0) { diff --git a/app/controllers/projects/base_controller.rb b/app/controllers/projects/base_controller.rb index a360737a4..9157a8a10 100644 --- a/app/controllers/projects/base_controller.rb +++ b/app/controllers/projects/base_controller.rb @@ -6,9 +6,9 @@ class Projects::BaseController < ApplicationController def find_collaborators search = "%#{params[:search_user]}%" - users = User.joins(groups: :projects).where(projects: {id: @project.id}).where("users.uname ILIKE ?", search) - users2 = @project.collaborators.where("users.uname ILIKE ?", search) - @users = (users + users2).uniq.sort {|x,y| x.uname <=> y.uname}.first(10) + @users = @project.collaborators.where("users.uname ILIKE ?", search) + @users |= @project.owner.members.where("users.uname ILIKE ?", search) if @project.owner.is_a?(Group) + @users = @users.sort_by(&:uname).first(10) end def find_project diff --git a/app/models/issue.rb b/app/models/issue.rb index cffdfbffb..7c0fd8c64 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -97,7 +97,7 @@ class Issue < ActiveRecord::Base def subscribe_issue_assigned_user if self.assignee_id && self.assignee_id_changed? - self.subscribes.where(user_id: self.assignee_id_was).first.destroy unless self.assignee_id_was.blank? + self.subscribes.where(user_id: self.assignee_id_was).first.try(:destroy) unless self.assignee_id_was.blank? if self.assignee.notifier.issue_assign && !self.subscribes.exists?(user_id: self.assignee_id) self.subscribes.create(user_id: self.assignee_id) end From fd13427794c27a4d8f49b6a40d92cb699e1890ce Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 10 Apr 2014 20:59:15 +0400 Subject: [PATCH 30/43] Optimize query for /projects page --- app/models/ability.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 108af5fc9..d78d54d64 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -64,7 +64,8 @@ class Ability can :read, Project, visibility: 'open' can [:read, :archive, :membered, :get_id], Project, owner_type: 'User', owner_id: user.id can [:read, :archive, :membered, :get_id], Project, owner_type: 'Group', owner_id: user_group_ids - can([:read, :archive, :membered, :get_id], Project, read_relations_for('projects')) {|project| local_reader? project} + # can([:read, :archive, :membered, :get_id], Project, read_relations_for('projects')) {|project| local_reader? project} + can([:read, :archive, :membered, :get_id], Project, read_relations_with_projects) {|project| local_reader? project} can(:write, Project) {|project| local_writer? project} # for grack can [:update, :sections, :manage_collaborators, :autocomplete_maintainers, :add_member, :remove_member, :update_member, :members, :schedule], Project do |project| local_admin? project @@ -82,7 +83,8 @@ class Ability can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'User', owner_id: user.id} can [:read, :log, :related, :everything], BuildList, project: {owner_type: 'Group', owner_id: user_group_ids} # can([:read, :log, :everything, :list], BuildList, read_relations_for('build_lists', 'projects')) {|build_list| can? :read, build_list.project} - can([:read, :log, :everything, :list], BuildList, read_relations_for_build_lists_and_projects) {|build_list| can? :read, build_list.project} + # can([:read, :log, :everything, :list], BuildList, read_relations_for_build_lists_and_projects) {|build_list| can? :read, build_list.project} + can([:read, :log, :everything, :list], BuildList, read_relations_with_projects('build_lists')) {|build_list| can? :read, build_list.project} can(:publish_into_testing, BuildList) { |build_list| can?(:create, build_list) && build_list.save_to_platform.main? } can(:create, BuildList) {|build_list| @@ -215,8 +217,11 @@ class Ability ] end - def read_relations_for_build_lists_and_projects - ["build_lists.project_id = ANY ( + def read_relations_with_projects(table = nil) + key = table ? 'project_id' : 'id' + table ||= 'projects' + + ["#{table}.#{key} = ANY ( ARRAY ( SELECT target_id FROM relations From 43fc57ec371d6c0cbf11eaa45360347e9425345f Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 11 Apr 2014 00:09:02 +0400 Subject: [PATCH 31/43] refactoring according to Alexander's comments --- app/models/ability.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index d78d54d64..5ca7f4ea6 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -217,10 +217,8 @@ class Ability ] end - def read_relations_with_projects(table = nil) - key = table ? 'project_id' : 'id' - table ||= 'projects' - + def read_relations_with_projects(table = 'projects') + key = table == 'projects' ? 'id' : 'project_id' ["#{table}.#{key} = ANY ( ARRAY ( SELECT target_id From cf479a144dd3ee61b6f533a99ffe5bce80316330 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 12 Apr 2014 00:29:43 +0400 Subject: [PATCH 32/43] ActiveAdmin integration --- Gemfile | 1 + Gemfile.lock | 47 +++++++ app/admin/dashboards.rb | 30 +++++ app/admin/event_logs.rb | 37 ++++++ app/admin/flash_notifies.rb | 28 ++++ app/admin/register_requests.rb | 20 +++ app/admin/resque.rb | 3 + app/admin/users.rb | 56 ++++++++ app/assets/javascripts/active_admin.js.coffee | 1 + app/assets/stylesheets/active_admin.css.scss | 17 +++ app/controllers/admin/base_controller.rb | 4 - .../admin/event_logs_controller.rb | 5 - .../admin/flash_notifies_controller.rb | 41 ------ .../admin/register_requests_controller.rb | 20 --- app/controllers/admin/users_controller.rb | 92 ------------- app/helpers/active_admin/admin_helper.rb | 10 ++ app/models/user.rb | 3 + .../index.html.haml | 0 .../{users => _users}/_sidebar.html.haml | 0 .../_users_ajax.json.jbuilder | 0 .../admin/{users => _users}/edit.html.haml | 0 .../admin/{users => _users}/index.html.haml | 0 .../admin/{users => _users}/new.html.haml | 0 .../admin/event_logs/_description.html.haml | 8 -- .../admin/event_logs/_event_log.html.haml | 7 - app/views/admin/event_logs/index.html.haml | 14 -- .../admin/flash_notifies/_form.html.haml | 21 --- app/views/admin/flash_notifies/edit.html.haml | 6 - .../admin/flash_notifies/index.html.haml | 22 ---- app/views/admin/flash_notifies/new.html.haml | 6 - app/views/layouts/menu/_top.html.haml | 2 +- config/application.rb | 4 +- config/initializers/active_admin.rb | 91 +++++++++++++ config/initializers/kaminari.rb | 3 + config/routes.rb | 31 ++--- lib/deploy_info.rb | 14 ++ .../admin/dashboard_controller_spec.rb | 5 + .../admin/event_logs_controller_spec.rb | 5 + .../admin/flash_notifies_controller_spec.rb | 121 +----------------- .../register_requests_controller_spec.rb | 5 + .../admin/resque_controller_spec.rb | 5 + .../admin/users_controller_spec.rb | 5 + .../support/shared_examples/admin_examples.rb | 22 ++++ 43 files changed, 422 insertions(+), 390 deletions(-) create mode 100644 app/admin/dashboards.rb create mode 100644 app/admin/event_logs.rb create mode 100644 app/admin/flash_notifies.rb create mode 100644 app/admin/register_requests.rb create mode 100644 app/admin/resque.rb create mode 100644 app/admin/users.rb create mode 100644 app/assets/javascripts/active_admin.js.coffee create mode 100644 app/assets/stylesheets/active_admin.css.scss delete mode 100644 app/controllers/admin/base_controller.rb delete mode 100644 app/controllers/admin/event_logs_controller.rb delete mode 100644 app/controllers/admin/flash_notifies_controller.rb delete mode 100644 app/controllers/admin/register_requests_controller.rb delete mode 100644 app/controllers/admin/users_controller.rb create mode 100644 app/helpers/active_admin/admin_helper.rb rename app/views/admin/{register_requests => _register_requests}/index.html.haml (100%) rename app/views/admin/{users => _users}/_sidebar.html.haml (100%) rename app/views/admin/{users => _users}/_users_ajax.json.jbuilder (100%) rename app/views/admin/{users => _users}/edit.html.haml (100%) rename app/views/admin/{users => _users}/index.html.haml (100%) rename app/views/admin/{users => _users}/new.html.haml (100%) delete mode 100644 app/views/admin/event_logs/_description.html.haml delete mode 100644 app/views/admin/event_logs/_event_log.html.haml delete mode 100644 app/views/admin/event_logs/index.html.haml delete mode 100644 app/views/admin/flash_notifies/_form.html.haml delete mode 100644 app/views/admin/flash_notifies/edit.html.haml delete mode 100644 app/views/admin/flash_notifies/index.html.haml delete mode 100644 app/views/admin/flash_notifies/new.html.haml create mode 100644 config/initializers/active_admin.rb create mode 100644 config/initializers/kaminari.rb create mode 100644 lib/deploy_info.rb create mode 100644 spec/controllers/admin/dashboard_controller_spec.rb create mode 100644 spec/controllers/admin/event_logs_controller_spec.rb create mode 100644 spec/controllers/admin/register_requests_controller_spec.rb create mode 100644 spec/controllers/admin/resque_controller_spec.rb create mode 100644 spec/controllers/admin/users_controller_spec.rb create mode 100644 spec/support/shared_examples/admin_examples.rb diff --git a/Gemfile b/Gemfile index 5a9d2bbca..b57ecdbce 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,7 @@ source 'https://rubygems.org' gem 'rails', '4.0.4' +gem 'activeadmin', github: 'gregbell/active_admin' gem 'pg', '~> 0.17.1' gem 'schema_plus', '~> 1.4.0' ######## diff --git a/Gemfile.lock b/Gemfile.lock index f071bdfcc..f157f1d21 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,6 +8,24 @@ GIT resque (> 1.25) resque-scheduler +GIT + remote: git://github.com/gregbell/active_admin.git + revision: 5ac883c59978799829a8c085fab47f858574c42f + specs: + activeadmin (1.0.0.pre) + arbre (~> 1.0) + bourbon + coffee-rails + devise (~> 3.2) + formtastic (~> 2.3.0.rc2) + inherited_resources (~> 1.3) + jquery-rails + jquery-ui-rails + kaminari (~> 0.15) + rails (>= 3.2, <= 4.1) + ransack (~> 1.0) + sass-rails + GIT remote: git://github.com/rosa-abf/cancan.git revision: fe1089b70c08d3ed11bac4f8e69ecb3d1d9adc29 @@ -65,6 +83,8 @@ GEM activerecord (>= 3.0.0) angular-i18n (0.1.2) angularjs-rails (1.2.14) + arbre (1.0.1) + activesupport (>= 3.0.0) arel (4.0.2) atomic (1.1.16) attr_encrypted (1.3.2) @@ -82,6 +102,9 @@ GEM daemons (~> 1.1.4) i18n (>= 0.5.0) state_machine (~> 1.1) + bourbon (3.1.8) + sass (>= 3.2.0) + thor builder (3.1.4) callsite (0.0.11) cape (1.8.0) @@ -138,6 +161,8 @@ GEM faraday (0.9.0) multipart-post (>= 1.2, < 3) ffi (1.9.3) + formtastic (2.3.0.rc2) + actionpack (>= 3.0) friendly_id (5.0.3) activerecord (>= 4.0.0) fssm (0.2.10) @@ -168,11 +193,17 @@ GEM activesupport (>= 4.0.1) haml (>= 3.1, < 5.0) railties (>= 4.0.1) + has_scope (0.6.0.rc) + actionpack (>= 3.2, < 5) + activesupport (>= 3.2, < 5) hashie (2.0.5) highline (1.6.21) hike (1.2.3) hirb (0.7.1) i18n (0.6.9) + inherited_resources (1.4.1) + has_scope (~> 0.6.0.rc) + responders (~> 1.0.0.rc) jbuilder (2.0.4) activesupport (>= 3.0.0) multi_json (>= 1.2.0) @@ -180,12 +211,17 @@ GEM jquery-rails (2.3.0) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) + jquery-ui-rails (4.2.0) + railties (>= 3.2.16) js-routes (0.9.7) railties (>= 3.2) sprockets-rails json (1.8.1) jwt (0.1.11) multi_json (>= 1.5) + kaminari (0.15.1) + actionpack (>= 3.0.0) + activesupport (>= 3.0.0) libv8 (3.16.14.3) localeapp (0.7.1) gli @@ -272,6 +308,8 @@ GEM cocaine (~> 0.5.3) mime-types pg (0.17.1) + polyamorous (0.6.4) + activerecord (>= 3.0) polyglot (0.3.4) posix-spawn (0.3.8) protected_attributes (1.0.7) @@ -308,6 +346,12 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (10.1.1) + ransack (1.2.1) + actionpack (>= 3.0) + activerecord (>= 3.0) + activesupport (>= 3.0) + i18n + polyamorous (~> 0.6.0) rdiscount (2.1.7) redcarpet (3.1.1) redis (3.0.7) @@ -330,6 +374,8 @@ GEM redis-store (1.1.4) redis (>= 2.2) ref (1.0.5) + responders (1.0.0) + railties (>= 3.2, < 5) resque (1.25.2) mono_logger (~> 1.0) multi_json (~> 1.0) @@ -463,6 +509,7 @@ PLATFORMS DEPENDENCIES RedCloth + activeadmin! airbrake (~> 3.1.2) ancestry (~> 2.0.0) angular-i18n (= 0.1.2) diff --git a/app/admin/dashboards.rb b/app/admin/dashboards.rb new file mode 100644 index 000000000..a19c8caec --- /dev/null +++ b/app/admin/dashboards.rb @@ -0,0 +1,30 @@ +ActiveAdmin.register_page 'Dashboard' do + + menu priority: 1 + + content do + + columns do + column do + panel "Deploy Information" do + require 'deploy_info' + + abf = "https://abf.io/abf/rosa-build/" + #jenkins = "https://ci.shuttlerock.com/" + + attributes_table_for DeployInfo do + row('Branch') { link_to DeployInfo::BRANCH, "#{abf}tree/#{DeployInfo::BRANCH}" } + row('Commit') { link_to DeployInfo::GIT_COMMIT, "#{abf}commit/#{DeployInfo::GIT_COMMIT}" } + row('Build Number') { DeployInfo::BUILD_NUMBER } + row('Build ID') { DeployInfo::BUILD_ID } + row('Deployer') { DeployInfo::DEPLOYER } + row(:message) { pre DeployInfo.message } + end + end # panel + end # column + end # columns + + + end # content + +end diff --git a/app/admin/event_logs.rb b/app/admin/event_logs.rb new file mode 100644 index 000000000..2359d6aba --- /dev/null +++ b/app/admin/event_logs.rb @@ -0,0 +1,37 @@ +ActiveAdmin.register EventLog do + + menu parent: 'Misc' + + actions :all, except: %i(create update new edit destroy) + + controller do + def scoped_collection + EventLog.includes(:user) + end + end + + index do + column :id + column :kind + column :created_at + column :user + column :ip + column :protocol + column('Description') do |el| + msg = %w([) + msg << I18n.t("event_log.controllers.#{el.controller.underscore}", default: el.controller) << "]" + msg << I18n.t("event_log.actions.#{el.controller.underscore}.#{el.action}", default: :"event_log.actions.#{el.action}") + if el.eventable_id.present? and el.eventable_type.present? + msg << '' << I18n.t("activerecord.models.#{el.eventable_type.underscore}") + msg << el.eventable_name + msg << "(id##{el.eventable_id})" # link_to "id##{el.eventable_id}", el.eventable + end + msg << el.message.to_s + msg.join(' ') + end + + + default_actions + end + +end diff --git a/app/admin/flash_notifies.rb b/app/admin/flash_notifies.rb new file mode 100644 index 000000000..957e0429e --- /dev/null +++ b/app/admin/flash_notifies.rb @@ -0,0 +1,28 @@ +ActiveAdmin.register FlashNotify do + + menu parent: 'Misc' + + index do + column :id + column(:body_en) do |fn| + fn.body_en.truncate(18) + end + column(:body_ru) do |fn| + fn.body_ru.truncate(18) + end + column :published + + default_actions + end + + form do |f| + f.inputs do + f.input :body_en + f.input :body_ru + f.input :status, as: :select, collection: FlashNotify::STATUSES, include_blank: false + f.input :published + end + f.actions + end + +end diff --git a/app/admin/register_requests.rb b/app/admin/register_requests.rb new file mode 100644 index 000000000..f2374d391 --- /dev/null +++ b/app/admin/register_requests.rb @@ -0,0 +1,20 @@ +ActiveAdmin.register RegisterRequest do + + menu parent: 'Misc' + + index do + column :id + column :name + + column('User') do |request| + user = User.find_by(email: request.email) if request.approved + link_to(user.uname, admin_user_path(user)) if user + end + column :interest + column :more + column :created_at + + default_actions + end + +end diff --git a/app/admin/resque.rb b/app/admin/resque.rb new file mode 100644 index 000000000..2dfdc7105 --- /dev/null +++ b/app/admin/resque.rb @@ -0,0 +1,3 @@ +ActiveAdmin.register_page 'Resque' do + menu priority: 100, label: 'Resque', url: '/admin/resque/overview' +end \ No newline at end of file diff --git a/app/admin/users.rb b/app/admin/users.rb new file mode 100644 index 000000000..2c712520b --- /dev/null +++ b/app/admin/users.rb @@ -0,0 +1,56 @@ +ActiveAdmin.register User do + + menu priority: 2 + + filter :uname + filter :email + filter :role, as: :select, collection: User::EXTENDED_ROLES + filter :created_at + + controller do + def update(options={}, &block) + user_params = params[:user] + resource.role = user_params.delete(:role) + user_params.delete(:password) if user_params[:password].blank? + user_params.delete(:password_confirmation) if user_params[:password_confirmation].blank? + super + end + end + + index do + column :id + column(:uname) do |user| + link_to(user.uname, user_path(user)) + end + column :email + column :created_at + column :role + + default_actions + end + + form do |f| + f.inputs do + f.input :name + f.input :email + f.input :uname + f.input :role, as: :select, collection: User::EXTENDED_ROLES, include_blank: false + f.input :password + f.input :password_confirmation + end + f.actions + end + + action_item only: %i(show edit) do + link_to 'Reset token', reset_token_admin_user_path(resource), + 'data-method' => :put, + data: { confirm: 'Are you sure you want to reset token?' } + end + + member_action :reset_token, :method => :put do + resource.reset_authentication_token! + flash[:info] = 'User token reseted successfully' + redirect_to admin_user_path(resource) + end + +end diff --git a/app/assets/javascripts/active_admin.js.coffee b/app/assets/javascripts/active_admin.js.coffee new file mode 100644 index 000000000..3752dcef6 --- /dev/null +++ b/app/assets/javascripts/active_admin.js.coffee @@ -0,0 +1 @@ +#= require active_admin/base diff --git a/app/assets/stylesheets/active_admin.css.scss b/app/assets/stylesheets/active_admin.css.scss new file mode 100644 index 000000000..90ba1d475 --- /dev/null +++ b/app/assets/stylesheets/active_admin.css.scss @@ -0,0 +1,17 @@ +// SASS variable overrides must be declared before loading up Active Admin's styles. +// +// To view the variables that Active Admin provides, take a look at +// `app/assets/stylesheets/active_admin/mixins/_variables.css.scss` in the +// Active Admin source. +// +// For example, to change the sidebar width: +// $sidebar-width: 242px; + +// Active Admin's got SASS! +@import "active_admin/mixins"; +@import "active_admin/base"; + +// Overriding any non-variable SASS must be done after the fact. +// For example, to change the default status-tag color: +// +// .status_tag { background: #6090DB; } diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb deleted file mode 100644 index a1f559897..000000000 --- a/app/controllers/admin/base_controller.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Admin::BaseController < ApplicationController - before_filter :authenticate_user! - load_and_authorize_resource -end diff --git a/app/controllers/admin/event_logs_controller.rb b/app/controllers/admin/event_logs_controller.rb deleted file mode 100644 index e099acbb2..000000000 --- a/app/controllers/admin/event_logs_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::EventLogsController < Admin::BaseController - def index - @event_logs = EventLog.default_order.eager_loading.paginate page: params[:page] - end -end diff --git a/app/controllers/admin/flash_notifies_controller.rb b/app/controllers/admin/flash_notifies_controller.rb deleted file mode 100644 index 97f2ca7e9..000000000 --- a/app/controllers/admin/flash_notifies_controller.rb +++ /dev/null @@ -1,41 +0,0 @@ -class Admin::FlashNotifiesController < Admin::BaseController - def index - @flash_notifies = FlashNotify.paginate(page: params[:page], per_page: 20) - end - - def new - @flash_notify = FlashNotify.new(published: true) - end - - def create - @flash_notify = FlashNotify.new(params[:flash_notify]) - if @flash_notify.save - flash[:notice] = t("flash.flash_notify.saved") - redirect_to admin_flash_notifies_path - else - flash[:error] = t("flash.flash_notify.save_error") - flash[:warning] = @flash_notify.errors.full_messages.join('. ') - render :new - end - end - - def update - if @flash_notify.update_attributes(params[:flash_notify]) - flash[:notice] = t("flash.flash_notify.saved") - redirect_to admin_flash_notifies_path - else - flash[:error] = t("flash.flash_notify.save_error") - flash[:warning] = @flash_notify.errors.full_messages.join('. ') - render :edit - end - end - - def destroy - if @flash_notify.destroy - flash[:notice] = t("flash.flash_notify.destroyed") - else - flash[:error] = t("flash.flash_notify.destroy_error") - end - redirect_to admin_flash_notifies_path - end -end diff --git a/app/controllers/admin/register_requests_controller.rb b/app/controllers/admin/register_requests_controller.rb deleted file mode 100644 index 0dda01db0..000000000 --- a/app/controllers/admin/register_requests_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -class Admin::RegisterRequestsController < Admin::BaseController - def index - @register_requests = @register_requests.send((params[:scope] || 'unprocessed').to_sym).paginate(page: params[:page]) - end - - def update - RegisterRequest.where(id: params[:request_ids]).each(¶ms[:update_type].to_sym) if params[:update_type].present? && params[:request_ids].present? - redirect_to action: :index - end - - def approve - @register_request.approve - redirect_to action: :index - end - - def reject - @register_request.reject - redirect_to action: :index - end -end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb deleted file mode 100644 index 84984d612..000000000 --- a/app/controllers/admin/users_controller.rb +++ /dev/null @@ -1,92 +0,0 @@ -class Admin::UsersController < Admin::BaseController - include AvatarHelper - prepend_before_filter :find_user - load_and_authorize_resource collection: [:system, :list] - - def index - @filter = params[:filter] || 'all' - end - - def system - @users, @filter = @users.system, 'system' - render :index - end - - def new - @user.role = 'system' if params[:system] == 'true' - end - - def create - @user.role = params[:role] - @user.email, @user.password = "#{@user.uname}@rosalinux.ru", SecureRandom.base64 if @user.system? - @user.confirmed_at = Time.now.utc - if (@user.save rescue false) - flash[:notice] = t('flash.user.saved') - flash[:warning] = @user.authentication_token - redirect_to(@user.system? ? system_admin_users_path : admin_users_path) - else - flash[:error] = t('flash.user.save_error') - flash[:warning] = @user.errors.full_messages.join('. ') - @system = @user.system? - - render action: :new - end - end - - def edit - end - - def update - @user.role = params[:role] - if @user.update_without_password(params[:user]) - update_avatar(@user, params) - flash[:notice] = t('flash.user.saved') - redirect_to admin_users_path - else - flash[:error] = t('flash.user.save_error') - flash[:warning] = @user.errors.full_messages.join('. ') - render action: :edit - end - end - - def destroy - @user.destroy - flash[:notice] = t("flash.user.destroyed") - redirect_to(@user.system? ? system_admin_users_path : admin_users_path) - end - - def list - if params[:system] != 'true' - colName, @users = %w(name uname email created_at), @users.opened - else - colName, @users, @system_list = ['uname'], @users.system, true - end - sort_col = params[:iSortCol_0] || 0 - sort_dir = params[:sSortDir_0]=="asc" ? 'asc' : 'desc' - order = "users.#{colName[sort_col.to_i]} #{sort_dir}" - - @users = @users.paginate(page: (params[:iDisplayStart].to_i/params[:iDisplayLength].to_i).to_i + 1, per_page: params[:iDisplayLength]) - @total_users = @users.count - if !params[:sSearch].blank? && search = "%#{params[:sSearch]}%" - @users = @users.where('users.name ILIKE ? or users.uname ILIKE ? or users.email ILIKE ?', search, search, search) - end - @filter = params[:filter] || 'all' - @users = @users.send(@filter) if ['real', 'admin', 'banned', 'tester'].include? @filter - @users = @users.order(order) - - render partial: 'users_ajax', layout: false - end - - def reset_auth_token - @user.reset_authentication_token! - flash[:notice] = t("flash.user.reset_auth_token") - flash[:warning] = @user.authentication_token - redirect_to system_admin_users_path - end - - protected - - def find_user - @user = User.find_by!(uname: params[:id]) if params[:id].present? - end -end diff --git a/app/helpers/active_admin/admin_helper.rb b/app/helpers/active_admin/admin_helper.rb new file mode 100644 index 000000000..4cc19f59c --- /dev/null +++ b/app/helpers/active_admin/admin_helper.rb @@ -0,0 +1,10 @@ +module ActiveAdmin::AdminHelper + + include ActiveAdmin::Views + + def admin_polymorphic_path(resource) + self.send("admin_#{resource.class.to_s.underscore}_path", resource) + end + +end + diff --git a/app/models/user.rb b/app/models/user.rb index 3e84c89ec..ed10519fd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,7 @@ class User < Avatar + extend FriendlyId + friendly_id :uname, use: [:finders] + include PersonalRepository include ActsLikeMember include Feed::User diff --git a/app/views/admin/register_requests/index.html.haml b/app/views/admin/_register_requests/index.html.haml similarity index 100% rename from app/views/admin/register_requests/index.html.haml rename to app/views/admin/_register_requests/index.html.haml diff --git a/app/views/admin/users/_sidebar.html.haml b/app/views/admin/_users/_sidebar.html.haml similarity index 100% rename from app/views/admin/users/_sidebar.html.haml rename to app/views/admin/_users/_sidebar.html.haml diff --git a/app/views/admin/users/_users_ajax.json.jbuilder b/app/views/admin/_users/_users_ajax.json.jbuilder similarity index 100% rename from app/views/admin/users/_users_ajax.json.jbuilder rename to app/views/admin/_users/_users_ajax.json.jbuilder diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/_users/edit.html.haml similarity index 100% rename from app/views/admin/users/edit.html.haml rename to app/views/admin/_users/edit.html.haml diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/_users/index.html.haml similarity index 100% rename from app/views/admin/users/index.html.haml rename to app/views/admin/_users/index.html.haml diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/_users/new.html.haml similarity index 100% rename from app/views/admin/users/new.html.haml rename to app/views/admin/_users/new.html.haml diff --git a/app/views/admin/event_logs/_description.html.haml b/app/views/admin/event_logs/_description.html.haml deleted file mode 100644 index 9c53f2405..000000000 --- a/app/views/admin/event_logs/_description.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -= surround '[', ']' do - = I18n.t "event_log.controllers.#{el.controller.underscore}", default: el.controller -= I18n.t "event_log.actions.#{el.controller.underscore}.#{el.action}", default: :"event_log.actions.#{el.action}" -- if el.eventable_id.present? and el.eventable_type.present? - = I18n.t "activerecord.models.#{el.eventable_type.underscore}" - = el.eventable_name - = "(id##{el.eventable_id})" # link_to "id##{el.eventable_id}", el.eventable -= el.message diff --git a/app/views/admin/event_logs/_event_log.html.haml b/app/views/admin/event_logs/_event_log.html.haml deleted file mode 100644 index 91e8562e4..000000000 --- a/app/views/admin/event_logs/_event_log.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -%tr{class: cycle("odd", "even")} - %td= event_log.kind - %td= event_log.created_at - %td= link_to_if event_log.user_id, event_log.user_name, event_log.user #{controller: "users", action: "show", id: event_log.user_id} - %td= event_log.ip - %td= event_log.protocol - %td= render 'description', el: event_log \ No newline at end of file diff --git a/app/views/admin/event_logs/index.html.haml b/app/views/admin/event_logs/index.html.haml deleted file mode 100644 index 66057901e..000000000 --- a/app/views/admin/event_logs/index.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -%h3.fix= title t("layout.event_logs.list_header") - -%table#datatable.tablesorter.list-users - %tr - %th.first= t("activerecord.attributes.event_log.kind") - %th= t("activerecord.attributes.event_log.created_at") - %th= t("activerecord.attributes.event_log.user") - %th= t("activerecord.attributes.event_log.ip") - %th= t("activerecord.attributes.event_log.protocol") - %th.last= t("activerecord.attributes.event_log.description") - = render @event_logs -= will_paginate - -= render 'submenu' diff --git a/app/views/admin/flash_notifies/_form.html.haml b/app/views/admin/flash_notifies/_form.html.haml deleted file mode 100644 index 46b41be64..000000000 --- a/app/views/admin/flash_notifies/_form.html.haml +++ /dev/null @@ -1,21 +0,0 @@ -.leftlist= f.label :body_ru, t("activerecord.attributes.flash_notify.body_ru"), class: :label -.rightlist= f.text_area :body_ru, class: 'text_field' -.both - -.leftlist= f.label :body_en, t("activerecord.attributes.flash_notify.body_en"), class: :label -.rightlist= f.text_area :body_en, class: 'text_field' -.both - -.leftlist= f.label :status, t("activerecord.attributes.flash_notify.status"), class: :label -.rightlist= f.select :status, FlashNotify::STATUSES -.both - -.leftlist= f.label :published, t("activerecord.attributes.flash_notify.published"), class: :label -.rightlist= f.check_box :published -.both - -.button_block - = submit_tag t('layout.save'), data: {'disable-with' => t('layout.saving')} - %span.text_button_padding= t("layout.or") - = link_to t("layout.cancel"), admin_flash_notifies_path, class: "button" - diff --git a/app/views/admin/flash_notifies/edit.html.haml b/app/views/admin/flash_notifies/edit.html.haml deleted file mode 100644 index 240d1cad4..000000000 --- a/app/views/admin/flash_notifies/edit.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -%h3= t("layout.flash_notifies.edit_header") - -= form_for @flash_notify, url: admin_flash_notify_path(@flash_notify), html: { class: :form } do |f| - = render "form", f: f - -= render 'submenu' diff --git a/app/views/admin/flash_notifies/index.html.haml b/app/views/admin/flash_notifies/index.html.haml deleted file mode 100644 index cb2d66698..000000000 --- a/app/views/admin/flash_notifies/index.html.haml +++ /dev/null @@ -1,22 +0,0 @@ -= link_to t("layout.flash_notifies.new"), new_admin_flash_notify_path, class: 'button' if can? :create, FlashNotify - -%table#myTable.tablesorter.flash_notifys{cellspacing: "0", cellpadding: "0"} - %thead - %tr - %th.th1= t("activerecord.attributes.flash_notify.body_en") - %th.th2= t("activerecord.attributes.flash_notify.body_ru") - %th.th3= t("activerecord.attributes.flash_notify.published") - %th.th3= t("layout.flash_notifies.actions") - %tbody - - @flash_notifies.each do |flash_notify| - %tr{class: cycle("odd", "even")} - %td= flash_notify.body_en.truncate 18 - %td= flash_notify.body_ru.truncate 18 - %td= flash_notify.published - %td - = link_to t("layout.flash_notifies.edit"), edit_admin_flash_notify_path(flash_notify) - = link_to t("layout.flash_notifies.delete"), admin_flash_notify_path(flash_notify), method: :delete, data: { confirm: t("layout.mass_builds.cancel_confirm") } if can?(:delete, flash_notify) - -= will_paginate @flash_notifies - -= render 'submenu' diff --git a/app/views/admin/flash_notifies/new.html.haml b/app/views/admin/flash_notifies/new.html.haml deleted file mode 100644 index c1f9ec45d..000000000 --- a/app/views/admin/flash_notifies/new.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -%h3= t("layout.flash_notifies.new_header") - -= form_for @flash_notify, url: admin_flash_notifies_path, html: { class: :form } do |f| - = render "form", f: f - -= render 'submenu' diff --git a/app/views/layouts/menu/_top.html.haml b/app/views/layouts/menu/_top.html.haml index af327be48..936e7a767 100644 --- a/app/views/layouts/menu/_top.html.haml +++ b/app/views/layouts/menu/_top.html.haml @@ -4,4 +4,4 @@ - if can? :index, base.to_s.classify.constantize %li= link_to title, send(:"#{namespace}#{base}_path"), class: top_menu_class(base) - if current_user.try(:admin?) and which_menu == 'top_menu' - %li= link_to t('admins_menu_header'), admin_users_path, class: top_menu_class('admin') \ No newline at end of file + %li= link_to t('admins_menu_header'), admin_root_path, class: top_menu_class('admin') \ No newline at end of file diff --git a/config/application.rb b/config/application.rb index 08dfc07f9..0af3dcd24 100644 --- a/config/application.rb +++ b/config/application.rb @@ -50,7 +50,9 @@ module Rosa config.encoding = "utf-8" # Enable the asset pipeline - config.assets.enabled = true + config.assets.enabled = true + config.assets.initialize_on_precompile = false # http://bit.ly/u7pQKz + config.assets.precompile += %w(active_admin.js active_admin.css) # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb new file mode 100644 index 000000000..877101fd9 --- /dev/null +++ b/config/initializers/active_admin.rb @@ -0,0 +1,91 @@ +ActiveAdmin.setup do |config| + + # == Site Title + # + # Set the title that is displayed on the main layout + # for each of the active admin pages. + # + config.site_title = "ABF" + + + # == Default Namespace + # + # Set the default namespace each administration resource + # will be added to. + # + # eg: + # config.default_namespace = :hello_world + # + # This will create resources in the HelloWorld module and + # will namespace routes to /hello_world/* + # + # To set no namespace by default, use: + # config.default_namespace = false + config.default_namespace = :admin + + + # == User Authentication + # + # Active Admin will automatically call an authentication + # method in a before filter of all controller actions to + # ensure that there is a currently logged in admin user. + # + # This setting changes the method which Active Admin calls + # within the controller. + config.authentication_method = :authenticate_user! + + + # == Current User + # + # Active Admin will associate actions with the current + # user performing them. + # + # This setting changes the method which Active Admin calls + # to return the currently logged in user. + config.current_user_method = :current_user + + + # == Admin Comments + # + # Admin comments allow you to add comments to any model for admin use + # + # Admin comments are enabled by default in the default + # namespace only. You can turn them on in a namesapce + # by adding them to the comments array. + # + # config.allow_comments_in = [:admin] + config.allow_comments = false + + + # == Controller Filters + # + # You can add before, after and around filters to all of your + # Active Admin resources from here. + # + # config.before_filter :do_something_awesome + config.before_filter :check_admin_role + + + # == Register Stylesheets & Javascripts + # + # We recommend using the built in Active Admin layout and loading + # up your own stylesheets / javascripts to customize the look + # and feel. + # + # To load a stylesheet: + # config.register_stylesheet 'my_stylesheet.css' + # + # To load a javascript file: + # config.register_javascript 'my_javascript.js' + + config.logout_link_path = :destroy_user_session_path +end + +# Block admin access to non-admin-users. +ActiveAdmin::BaseController.class_eval do + # include ActionController::Caching::Sweeping + protected + def check_admin_role + raise ActiveRecord::RecordNotFound unless current_user.admin? + end +end diff --git a/config/initializers/kaminari.rb b/config/initializers/kaminari.rb new file mode 100644 index 000000000..25279cf5f --- /dev/null +++ b/config/initializers/kaminari.rb @@ -0,0 +1,3 @@ +Kaminari.configure do |config| + config.page_method_name = :per_page_kaminari +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index c7ad7cf84..54e5e8797 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,14 @@ Rosa::Application.routes.draw do + # ActiveAdmin routes. + ActiveAdmin.routes(self) + + namespace :admin do + constraints Rosa::Constraints::AdminAccess do + mount Resque::Server => 'resque' + end + end + # Redirect sitemap1.xml.gz file on AWS S3 match '/sitemap.xml.gz' => 'sitemap#show', via: [:get, :post, :head], as: :sitemap match '/robots.txt' => 'sitemap#robots', via: [:get, :post, :head], as: :robots @@ -147,28 +156,6 @@ Rosa::Application.routes.draw do root to: 'home#activity' end - namespace :admin do - resources :users do - collection do - get :list - get :system - end - put :reset_auth_token, on: :member - end - resources :register_requests, only: [:index] do - put :update, on: :collection - member do - get :approve - get :reject - end - end - resources :flash_notifies - resources :event_logs, only: :index - constraints Rosa::Constraints::AdminAccess do - mount Resque::Server => 'resque' - end - end - resources :advisories, only: [:index, :show, :search] do get :search, on: :collection end diff --git a/lib/deploy_info.rb b/lib/deploy_info.rb new file mode 100644 index 000000000..197ed80eb --- /dev/null +++ b/lib/deploy_info.rb @@ -0,0 +1,14 @@ +# This file gets overwritten during deploy process +module DeployInfo + BRANCH=`git rev-parse --abbrev-ref HEAD`.strip + GIT_COMMIT=`git rev-parse HEAD`.strip + BUILD_NUMBER='dev' + BUILD_ID='dev' + DEPLOYER=`git config user.name`.strip + + def message + `git log -1 --pretty=medium`.strip + end + + module_function :message +end diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb new file mode 100644 index 000000000..a83e0c3b7 --- /dev/null +++ b/spec/controllers/admin/dashboard_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Admin::DashboardController do + it_should_behave_like 'an admin controller' +end diff --git a/spec/controllers/admin/event_logs_controller_spec.rb b/spec/controllers/admin/event_logs_controller_spec.rb new file mode 100644 index 000000000..836c560e1 --- /dev/null +++ b/spec/controllers/admin/event_logs_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Admin::EventLogsController do + it_should_behave_like 'an admin controller' +end diff --git a/spec/controllers/admin/flash_notifies_controller_spec.rb b/spec/controllers/admin/flash_notifies_controller_spec.rb index 73aa69a9d..f6f3a6d20 100644 --- a/spec/controllers/admin/flash_notifies_controller_spec.rb +++ b/spec/controllers/admin/flash_notifies_controller_spec.rb @@ -1,124 +1,5 @@ require 'spec_helper' describe Admin::FlashNotifiesController do - before(:each) do - stub_symlink_methods - - @user = FactoryGirl.create(:user) - @create_params = { - flash_notify: { - body_ru: "Hello! I`m ru body", - body_en: "Hello! I`m en body", - status: "error", - published: true - } - } - - @flash_notify = FactoryGirl.create(:flash_notify) - @flash_notify2 = FactoryGirl.create(:flash_notify) - - @update_params = { - id: @flash_notify, - flash_notify: { - body_ru: "updated!" - } - } - end - - context 'for guest' do - [:index, :create, :update, :edit, :new, :destroy].each do |action| - it "should not be able to perform #{ action } action" do - get action, id: @flash_notify - response.should redirect_to(new_user_session_path) - end - end - - it 'should not change objects count on create' do - lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(0) - end - - it 'should not change objects count on destroy' do - lambda { delete :destroy, id: @flash_notify }.should change{ FlashNotify.count }.by(0) - end - - it 'should not change flash notify body on update' do - put :update, @update_params - @flash_notify.reload.body_ru.should_not == "updated!" - end - end - - context 'for global admin' do - before(:each) do - @admin = FactoryGirl.create(:admin) - @user = FactoryGirl.create(:user) - set_session_for(@admin) - end - - it 'should load 2 flash notifies objects on index' do - get :index - assigns[:flash_notifies].count.should == 2 - end - - [:index, :new, :edit].each do |action| - it "should be able to perform #{action} action" do - get action, id: @flash_notify - response.should render_template(action) - end - end - - it 'should be able to perform create action' do - post :create, @create_params - response.should redirect_to(admin_flash_notifies_path) - end - - it 'should change objects count on create' do - lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(1) - end - - it 'should be able to perform destroy action' do - delete :destroy, id: @flash_notify - response.should redirect_to(admin_flash_notifies_path) - end - - it 'should change objects count on destroy' do - lambda { delete :destroy, id: @flash_notify }.should change{ FlashNotify.count }.by(-1) - end - - it 'should be able to perform update action' do - put :update, @update_params - response.should redirect_to(admin_flash_notifies_path) - end - - it 'should change flash notify body on update' do - put :update, @update_params - @flash_notify.reload.body_ru.should == "updated!" - end - end - - context 'for simple user' do - before(:each) do - @user = FactoryGirl.create(:user) - set_session_for(@user) - end - - [:index, :create, :update, :edit, :new, :destroy].each do |action| - it "should not be able to perform #{ action } action" do - get action, id: @flash_notify - response.should redirect_to(forbidden_path) - end - end - - it 'should not change objects count on create' do - lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(0) - end - - it 'should not change objects count on destroy' do - lambda { delete :destroy, id: @flash_notify }.should change{ FlashNotify.count }.by(0) - end - - it 'should not change flash notify body on update' do - put :update, @update_params - @flash_notify.reload.body_ru.should_not == "updated!" - end - end + it_should_behave_like 'an admin controller' end diff --git a/spec/controllers/admin/register_requests_controller_spec.rb b/spec/controllers/admin/register_requests_controller_spec.rb new file mode 100644 index 000000000..6ecf3583a --- /dev/null +++ b/spec/controllers/admin/register_requests_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Admin::RegisterRequestsController do + it_should_behave_like 'an admin controller' +end diff --git a/spec/controllers/admin/resque_controller_spec.rb b/spec/controllers/admin/resque_controller_spec.rb new file mode 100644 index 000000000..820e4f955 --- /dev/null +++ b/spec/controllers/admin/resque_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Admin::ResqueController do + it_should_behave_like 'an admin controller' +end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb new file mode 100644 index 000000000..86c5f0ae6 --- /dev/null +++ b/spec/controllers/admin/users_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe Admin::UsersController do + it_should_behave_like 'an admin controller' +end diff --git a/spec/support/shared_examples/admin_examples.rb b/spec/support/shared_examples/admin_examples.rb new file mode 100644 index 000000000..88ca350cc --- /dev/null +++ b/spec/support/shared_examples/admin_examples.rb @@ -0,0 +1,22 @@ +shared_examples_for 'an admin controller' do + + it 'redirects to login when accessed unauthorised' do + get :index + response.should redirect_to(new_user_session_path) + end + + it 'raises a 404 for non-admin users' do + user = User.first || FactoryGirl.create(:user) + sign_in user + get :index + response.should redirect_to('/404.html') + end + + it 'is successful for admin users' do + user = User.first || FactoryGirl.create(:admin) + sign_in user + get :index + response.should be_success + end + +end \ No newline at end of file From f175505c43429b1ae0fe54fd2c36c96023d2a405 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Sat, 12 Apr 2014 00:46:00 +0400 Subject: [PATCH 33/43] Fixed: logout_link --- config/initializers/active_admin.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb index 877101fd9..fc86dff40 100644 --- a/config/initializers/active_admin.rb +++ b/config/initializers/active_admin.rb @@ -78,7 +78,8 @@ ActiveAdmin.setup do |config| # To load a javascript file: # config.register_javascript 'my_javascript.js' - config.logout_link_path = :destroy_user_session_path + config.logout_link_path = :destroy_user_session_path + config.logout_link_method = :delete end # Block admin access to non-admin-users. From 0dbc69db50d0e47a8a40e80d39ab4aef9dda4d68 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Sat, 12 Apr 2014 09:18:04 +0600 Subject: [PATCH 34/43] add site title link to the root page --- config/initializers/active_admin.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb index fc86dff40..f43f1603e 100644 --- a/config/initializers/active_admin.rb +++ b/config/initializers/active_admin.rb @@ -6,7 +6,7 @@ ActiveAdmin.setup do |config| # for each of the active admin pages. # config.site_title = "ABF" - + config.site_title_link = "/" # == Default Namespace # From 0d5aa59c642d40fda9351ffb4d1b7e4e701e60c2 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Sat, 12 Apr 2014 09:43:41 +0600 Subject: [PATCH 35/43] [#369] move old bootstrap; remove unneeded files --- .../assets/javascripts/bootstrap-popover.js | 98 ------- .../assets/javascripts/bootstrap-tooltip.js | 275 ------------------ vendor/assets/javascripts/vendor.js | 4 - .../{bootstrap.scss => old-bootstrap.scss} | 0 vendor/assets/stylesheets/vendor.scss | 2 +- 5 files changed, 1 insertion(+), 378 deletions(-) delete mode 100644 vendor/assets/javascripts/bootstrap-popover.js delete mode 100644 vendor/assets/javascripts/bootstrap-tooltip.js rename vendor/assets/stylesheets/{bootstrap.scss => old-bootstrap.scss} (100%) diff --git a/vendor/assets/javascripts/bootstrap-popover.js b/vendor/assets/javascripts/bootstrap-popover.js deleted file mode 100644 index 39fbe358e..000000000 --- a/vendor/assets/javascripts/bootstrap-popover.js +++ /dev/null @@ -1,98 +0,0 @@ -/* =========================================================== - * bootstrap-popover.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#popovers - * =========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* POPOVER PUBLIC CLASS DEFINITION - * =============================== */ - - var Popover = function ( element, options ) { - this.init('popover', element, options) - } - - - /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js - ========================================== */ - - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { - - constructor: Popover - - , setContent: function () { - var $tip = this.tip() - , title = this.getTitle() - , content = this.getContent() - - $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title) - $tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content) - - $tip.removeClass('fade top bottom left right in') - } - - , hasContent: function () { - return this.getTitle() || this.getContent() - } - - , getContent: function () { - var content - , $e = this.$element - , o = this.options - - content = $e.attr('data-content') - || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) - - return content - } - - , tip: function () { - if (!this.$tip) { - this.$tip = $(this.options.template) - } - return this.$tip - } - - }) - - - /* POPOVER PLUGIN DEFINITION - * ======================= */ - - $.fn.popover = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('popover') - , options = typeof option == 'object' && option - if (!data) $this.data('popover', (data = new Popover(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.popover.Constructor = Popover - - $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { - placement: 'right' - , content: '' - , template: '

' - }) - -}(window.jQuery); \ No newline at end of file diff --git a/vendor/assets/javascripts/bootstrap-tooltip.js b/vendor/assets/javascripts/bootstrap-tooltip.js deleted file mode 100644 index b476f1c4e..000000000 --- a/vendor/assets/javascripts/bootstrap-tooltip.js +++ /dev/null @@ -1,275 +0,0 @@ -/* =========================================================== - * bootstrap-tooltip.js v2.0.4 - * http://twitter.github.com/bootstrap/javascript.html#tooltips - * Inspired by the original jQuery.tipsy by Jason Frame - * =========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* TOOLTIP PUBLIC CLASS DEFINITION - * =============================== */ - - var Tooltip = function (element, options) { - this.init('tooltip', element, options) - } - - Tooltip.prototype = { - - constructor: Tooltip - - , init: function (type, element, options) { - var eventIn - , eventOut - - this.type = type - this.$element = $(element) - this.options = this.getOptions(options) - this.enabled = true - - if (this.options.trigger != 'manual') { - eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' - eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' - this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this)) - this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this)) - } - - this.options.selector ? - (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : - this.fixTitle() - } - - , getOptions: function (options) { - options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) - - if (options.delay && typeof options.delay == 'number') { - options.delay = { - show: options.delay - , hide: options.delay - } - } - - return options - } - - , enter: function (e) { - var self = $(e.currentTarget)[this.type](this._options).data(this.type) - - if (!self.options.delay || !self.options.delay.show) return self.show() - - clearTimeout(this.timeout) - self.hoverState = 'in' - this.timeout = setTimeout(function() { - if (self.hoverState == 'in') self.show() - }, self.options.delay.show) - } - - , leave: function (e) { - var self = $(e.currentTarget)[this.type](this._options).data(this.type) - - if (this.timeout) clearTimeout(this.timeout) - if (!self.options.delay || !self.options.delay.hide) return self.hide() - - self.hoverState = 'out' - this.timeout = setTimeout(function() { - if (self.hoverState == 'out') self.hide() - }, self.options.delay.hide) - } - - , show: function () { - var $tip - , inside - , pos - , actualWidth - , actualHeight - , placement - , tp - - if (this.hasContent() && this.enabled) { - $tip = this.tip() - this.setContent() - - if (this.options.animation) { - $tip.addClass('fade') - } - - placement = typeof this.options.placement == 'function' ? - this.options.placement.call(this, $tip[0], this.$element[0]) : - this.options.placement - - inside = /in/.test(placement) - - $tip - .remove() - .css({ top: 0, left: 0, display: 'block' }) - .appendTo(inside ? this.$element : document.body) - - pos = this.getPosition(inside) - - actualWidth = $tip[0].offsetWidth - actualHeight = $tip[0].offsetHeight - - switch (inside ? placement.split(' ')[1] : placement) { - case 'bottom': - tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} - break - case 'top': - tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} - break - case 'left': - tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} - break - case 'right': - tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} - break - } - - $tip - .css(tp) - .addClass(placement) - .addClass('in') - } - } - - , isHTML: function(text) { - // html string detection logic adapted from jQuery - return typeof text != 'string' - || ( text.charAt(0) === "<" - && text.charAt( text.length - 1 ) === ">" - && text.length >= 3 - ) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text) - } - - , setContent: function () { - var $tip = this.tip() - , title = this.getTitle() - - $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title) - $tip.removeClass('fade in top bottom left right') - } - - , hide: function () { - var that = this - , $tip = this.tip() - - $tip.removeClass('in') - - function removeWithAnimation() { - var timeout = setTimeout(function () { - $tip.off($.support.transition.end).remove() - }, 500) - - $tip.one($.support.transition.end, function () { - clearTimeout(timeout) - $tip.remove() - }) - } - - $.support.transition && this.$tip.hasClass('fade') ? - removeWithAnimation() : - $tip.remove() - } - - , fixTitle: function () { - var $e = this.$element - if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { - $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') - } - } - - , hasContent: function () { - return this.getTitle() - } - - , getPosition: function (inside) { - return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { - width: this.$element[0].offsetWidth - , height: this.$element[0].offsetHeight - }) - } - - , getTitle: function () { - var title - , $e = this.$element - , o = this.options - - title = $e.attr('data-original-title') - || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) - - return title - } - - , tip: function () { - return this.$tip = this.$tip || $(this.options.template) - } - - , validate: function () { - if (!this.$element[0].parentNode) { - this.hide() - this.$element = null - this.options = null - } - } - - , enable: function () { - this.enabled = true - } - - , disable: function () { - this.enabled = false - } - - , toggleEnabled: function () { - this.enabled = !this.enabled - } - - , toggle: function () { - this[this.tip().hasClass('in') ? 'hide' : 'show']() - } - - } - - - /* TOOLTIP PLUGIN DEFINITION - * ========================= */ - - $.fn.tooltip = function ( option ) { - return this.each(function () { - var $this = $(this) - , data = $this.data('tooltip') - , options = typeof option == 'object' && option - if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.tooltip.Constructor = Tooltip - - $.fn.tooltip.defaults = { - animation: true - , placement: 'top' - , selector: false - , template: '
' - , trigger: 'hover' - , title: '' - , delay: 0 - } - -}(window.jQuery); diff --git a/vendor/assets/javascripts/vendor.js b/vendor/assets/javascripts/vendor.js index 08fc17f77..5c01d700c 100644 --- a/vendor/assets/javascripts/vendor.js +++ b/vendor/assets/javascripts/vendor.js @@ -11,10 +11,6 @@ //= require bootstrap-button //= require bootstrap-dropdown //= require bootstrap-tab -// require bootstrap-tooltip -// require bootstrap-popover //= require bootstrap-alert //= require bootstrap-tab //= require chosen.jquery -// require html5shiv -// require_tree . diff --git a/vendor/assets/stylesheets/bootstrap.scss b/vendor/assets/stylesheets/old-bootstrap.scss similarity index 100% rename from vendor/assets/stylesheets/bootstrap.scss rename to vendor/assets/stylesheets/old-bootstrap.scss diff --git a/vendor/assets/stylesheets/vendor.scss b/vendor/assets/stylesheets/vendor.scss index 0264d0a7f..5020011a8 100644 --- a/vendor/assets/stylesheets/vendor.scss +++ b/vendor/assets/stylesheets/vendor.scss @@ -13,5 +13,5 @@ @import "codemirror/modes/rpm-spec"; @import "codemirror/modes/tiddlywiki"; -@import "bootstrap"; +@import "old-bootstrap"; @import "chosen.scss"; \ No newline at end of file From b577cd2b6083e96693482cbeb26f124a53214cb1 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Mon, 14 Apr 2014 14:09:08 +0400 Subject: [PATCH 36/43] Update puma 2.8.1 => 2.8.2 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index f157f1d21..39a1ff379 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -314,7 +314,7 @@ GEM posix-spawn (0.3.8) protected_attributes (1.0.7) activemodel (>= 4.0.1, < 5.0) - puma (2.8.1) + puma (2.8.2) rack (>= 1.1, < 2.0) pygments.rb (0.5.4) posix-spawn (~> 0.3.6) From f23259775e81dbc39564b452b5656d6697668164 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 15:11:14 +0600 Subject: [PATCH 37/43] [#369] remove codemirror; use pygments --- Gemfile | 1 - Gemfile.lock | 2 +- app/assets/javascripts/application.js | 6 - app/assets/javascripts/extra/comment.js | 2 +- app/assets/javascripts/extra/log-wrapper.js | 3 +- app/assets/javascripts/extra/preview.js | 2 +- app/assets/javascripts/extra/tracker.js | 2 +- app/assets/stylesheets/design/custom.scss | 13 +- app/helpers/git_helper.rb | 16 + app/models/build_list.rb | 6 +- .../projects/git/blobs/_blame_table.html.haml | 21 +- .../git/blobs/_render_as_text.html.haml | 7 +- app/views/projects/git/blobs/_show.html.haml | 4 - app/views/shared/_feed_message.html.haml | 4 +- vendor/assets/javascripts/codemirror.js | 2959 ----------------- .../javascripts/codemirror/keymaps/emacs.js | 29 - .../javascripts/codemirror/keymaps/vim.js | 347 -- .../javascripts/codemirror/modes/clike.js | 234 -- .../javascripts/codemirror/modes/clojure.js | 208 -- .../codemirror/modes/coffeescript.js | 342 -- .../javascripts/codemirror/modes/css.js | 125 - .../javascripts/codemirror/modes/diff.js | 14 - .../javascripts/codemirror/modes/gfm.js | 108 - .../assets/javascripts/codemirror/modes/go.js | 173 - .../javascripts/codemirror/modes/groovy.js | 211 -- .../javascripts/codemirror/modes/haskell.js | 243 -- .../codemirror/modes/htmlembedded.js | 68 - .../javascripts/codemirror/modes/htmlmixed.js | 84 - .../codemirror/modes/javascript.js | 361 -- .../javascripts/codemirror/modes/jinja2.js | 42 - .../javascripts/codemirror/modes/less.js | 186 -- .../javascripts/codemirror/modes/lua.js | 141 - .../javascripts/codemirror/modes/markdown.js | 243 -- .../javascripts/codemirror/modes/mysql.js | 189 -- .../javascripts/codemirror/modes/ntriples.js | 172 - .../javascripts/codemirror/modes/pascal.js | 139 - .../javascripts/codemirror/modes/perl.js | 817 ----- .../javascripts/codemirror/modes/php.js | 122 - .../javascripts/codemirror/modes/plsql.js | 217 -- .../javascripts/codemirror/modes/python.js | 341 -- .../assets/javascripts/codemirror/modes/r.js | 142 - .../codemirror/modes/rpm-changes.js | 20 - .../javascripts/codemirror/modes/rpm-spec.js | 67 - .../javascripts/codemirror/modes/rst.js | 327 -- .../javascripts/codemirror/modes/ruby.js | 201 -- .../javascripts/codemirror/modes/rust.js | 433 --- .../javascripts/codemirror/modes/scheme.js | 203 -- .../javascripts/codemirror/modes/shell.js | 119 - .../javascripts/codemirror/modes/smalltalk.js | 140 - .../javascripts/codemirror/modes/sparql.js | 143 - .../javascripts/codemirror/modes/stex.js | 168 - .../codemirror/modes/tiddlywiki.js | 375 --- .../javascripts/codemirror/modes/velocity.js | 147 - .../javascripts/codemirror/modes/verilog.js | 194 -- .../javascripts/codemirror/modes/xml.js | 261 -- .../javascripts/codemirror/modes/xmlpure.js | 490 --- .../javascripts/codemirror/modes/yaml.js | 96 - .../assets/javascripts/codemirror/overlay.js | 51 - .../assets/javascripts/codemirror/runmode.js | 49 - vendor/assets/javascripts/vendor.js | 4 +- vendor/assets/stylesheets/codemirror.scss | 106 - .../stylesheets/codemirror/modes/diff.scss | 3 - .../codemirror/modes/rpm-spec.scss | 5 - .../codemirror/modes/tiddlywiki.scss | 21 - .../stylesheets/codemirror/themes/cobalt.scss | 18 - .../codemirror/themes/eclipse.scss | 25 - .../codemirror/themes/elegant.scss | 10 - .../codemirror/themes/monokai.scss | 28 - .../stylesheets/codemirror/themes/neat.scss | 9 - .../stylesheets/codemirror/themes/night.scss | 21 - .../codemirror/themes/rubyblue.scss | 21 - vendor/assets/stylesheets/vendor.scss | 10 +- 72 files changed, 50 insertions(+), 12061 deletions(-) delete mode 100644 vendor/assets/javascripts/codemirror.js delete mode 100644 vendor/assets/javascripts/codemirror/keymaps/emacs.js delete mode 100644 vendor/assets/javascripts/codemirror/keymaps/vim.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/clike.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/clojure.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/coffeescript.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/css.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/diff.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/gfm.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/go.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/groovy.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/haskell.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/htmlembedded.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/htmlmixed.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/javascript.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/jinja2.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/less.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/lua.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/markdown.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/mysql.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/ntriples.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/pascal.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/perl.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/php.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/plsql.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/python.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/r.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/rpm-changes.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/rpm-spec.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/rst.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/ruby.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/rust.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/scheme.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/shell.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/smalltalk.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/sparql.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/stex.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/tiddlywiki.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/velocity.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/verilog.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/xml.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/xmlpure.js delete mode 100644 vendor/assets/javascripts/codemirror/modes/yaml.js delete mode 100644 vendor/assets/javascripts/codemirror/overlay.js delete mode 100644 vendor/assets/javascripts/codemirror/runmode.js delete mode 100644 vendor/assets/stylesheets/codemirror.scss delete mode 100644 vendor/assets/stylesheets/codemirror/modes/diff.scss delete mode 100644 vendor/assets/stylesheets/codemirror/modes/rpm-spec.scss delete mode 100644 vendor/assets/stylesheets/codemirror/modes/tiddlywiki.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/cobalt.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/eclipse.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/elegant.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/monokai.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/neat.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/night.scss delete mode 100644 vendor/assets/stylesheets/codemirror/themes/rubyblue.scss diff --git a/Gemfile b/Gemfile index b57ecdbce..6038611d1 100644 --- a/Gemfile +++ b/Gemfile @@ -86,7 +86,6 @@ gem 'therubyracer', '~> 0.12.1', platforms: [:mri, :rbx] gem 'therubyrhino', '~> 1.73.1', platforms: :jruby gem 'sitemap_generator' - group :production do gem "airbrake", '~> 3.1.2' gem 'bluepill', '~> 0.0.60', require: false diff --git a/Gemfile.lock b/Gemfile.lock index f157f1d21..bfe8bd1c6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -167,7 +167,7 @@ GEM activerecord (>= 4.0.0) fssm (0.2.10) gemoji (1.2.1) - github-linguist (2.10.9) + github-linguist (2.10.11) charlock_holmes (~> 0.6.6) escape_utils (>= 0.3.1) mime-types (~> 1.19) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index b547db2c5..3c90f9cb2 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -87,12 +87,6 @@ $(document).ready(function() { return false; }); - window.CodeMirrorRun = function(code) { - CodeMirror.runMode(code.innerHTML.replace(/&/gi, '&').replace(/</gi, '<').replace(/>/gi, '>'), code.className, code); - } - - $('.md_and_cm code').each(function (code) { CodeMirrorRun(this); }); - window.updateTime = function () { $('.datetime_moment').each(function() { $(this).html(moment($(this).attr('origin_datetime'), 'X').fromNow()); diff --git a/app/assets/javascripts/extra/comment.js b/app/assets/javascripts/extra/comment.js index be8b17a10..bccb8da44 100644 --- a/app/assets/javascripts/extra/comment.js +++ b/app/assets/javascripts/extra/comment.js @@ -24,7 +24,7 @@ $(document).ready(function() { var cancel_button = form.find('.cancel_edit_comment.button'); var id = cancel_button.attr('id').match(/\d+$/)[0]; cancel_button.click(); - $('#comment'+id+', #diff-comment'+id).find('.cm-s-default.md_and_cm').html(data).find('code').each(function (code) { CodeMirrorRun(this); }) + $('#comment'+id+', #diff-comment'+id).find('.cm-s-default.md_and_cm').html(data); }, error: function(data){ form.before(data.responseText); diff --git a/app/assets/javascripts/extra/log-wrapper.js b/app/assets/javascripts/extra/log-wrapper.js index d449d233c..cd19cef5a 100644 --- a/app/assets/javascripts/extra/log-wrapper.js +++ b/app/assets/javascripts/extra/log-wrapper.js @@ -50,7 +50,8 @@ function initLogWrapper() { var hScroll = l.scrollLeft; var onBottom = Math.abs((l.clientHeight + vScroll - l.scrollHeight)) < getLineHeight(l); - CodeMirror.runMode(data.log.replace(/&/gi, '&'), "text/x-sh", document.getElementById("output")); + $("#output").html(data.log); + //CodeMirror.runMode(data.log.replace(/&/gi, '&'), "text/x-sh", document.getElementById("output")); $logCont.scrollLeft(hScroll); $logCont.scrollTop((onBottom || first_open) ? l.scrollHeight - l.clientHeight : vScroll); diff --git a/app/assets/javascripts/extra/preview.js b/app/assets/javascripts/extra/preview.js index 4eb397844..9e2c26bef 100644 --- a/app/assets/javascripts/extra/preview.js +++ b/app/assets/javascripts/extra/preview.js @@ -15,7 +15,7 @@ $(document).ready(function() { url: preview_url, data: el_dup.serialize(), success: function(data){ - preview.html(data).find('code').each(function (code) { CodeMirrorRun(this); }) + preview.html(data); } }); }; diff --git a/app/assets/javascripts/extra/tracker.js b/app/assets/javascripts/extra/tracker.js index 0c30c20f5..03c6e6349 100644 --- a/app/assets/javascripts/extra/tracker.js +++ b/app/assets/javascripts/extra/tracker.js @@ -214,7 +214,7 @@ $(document).ready(function() { form.fadeOut('slow'); $('#edit_issue_content').fadeIn('slow'); $('h3.issue_title').html(form.find('#issue_title').attr('value')); - $('.fulltext.view.issue_body').html(data).find('code').each(function (code) { CodeMirrorRun(this); }) + $('.fulltext.view.issue_body').html(data); }, error: function(data){ form.before(data.responseText); diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss index c94067c43..dacea7ba2 100644 --- a/app/assets/stylesheets/design/custom.scss +++ b/app/assets/stylesheets/design/custom.scss @@ -393,7 +393,7 @@ div.comment textarea { resize: none } #repo-wrapper div.file div.data .formatted { overflow-x: auto; overflow-y: none; - white-space: pre; + //white-space: pre; } table.tablesorter tbody td a .issue_title { @@ -474,6 +474,11 @@ div.blame_data tr td.lines { div.blame_data tr td.code { padding: 0 10px !important; font-size: 12px; + width: auto; + font-family: "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace; + color: #000000; + padding: 10px 5px 0px; + margin-left: 45px; } div.blame_data tr td.code pre { @@ -1588,6 +1593,8 @@ table.tablesorter.platform-maintainers.static-search thead tr.search th input[ty code { background-color: transparent; border: none; + margin: 0; + padding: 0; } } @@ -1790,10 +1797,6 @@ table#myTable thead tr.search th form.button_to div input { max-width: 860px; } -.CodeMirror { - border: 1px solid #DDDDDD; -} - .semi { opacity: 0.5; } diff --git a/app/helpers/git_helper.rb b/app/helpers/git_helper.rb index 371bed4a3..1e44b61d1 100644 --- a/app/helpers/git_helper.rb +++ b/app/helpers/git_helper.rb @@ -102,4 +102,20 @@ module GitHelper h end end + + def blob_highlight(blob) + if blob.mime_type == 'text/rpm-spec' + Pygments.highlight blob.data, lexer: 'spec' + else + blob.colorize + end.html_safe + end + + def blame_highlight(blob, text) + if blob.mime_type == 'text/rpm-spec' + Pygments.highlight(text, lexer: 'spec') + else + blob.lexer.highlight text + end.html_safe + end end diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 54fe6ca5d..123569f8e 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -472,7 +472,11 @@ class BuildList < ActiveRecord::Base end def log(load_lines) - new_core? ? abf_worker_log : I18n.t('layout.build_lists.log.not_available') + if new_core? + Pygments.highlight abf_worker_log, lexer: 'sh' + else + I18n.t('layout.build_lists.log.not_available') + end end def last_published(testing = false) diff --git a/app/views/projects/git/blobs/_blame_table.html.haml b/app/views/projects/git/blobs/_blame_table.html.haml index 4c08e12fa..3ade6e176 100644 --- a/app/views/projects/git/blobs/_blame_table.html.haml +++ b/app/views/projects/git/blobs/_blame_table.html.haml @@ -18,24 +18,15 @@ = index - index += 1 - %td.code.cm-s-default - %pre - %div= elem[1].first + %td.code.formatted + = preserve do + = blame_highlight @blob, elem[1].first - elem[1][1..-1].each do |line| %tr %td.lines = index - index += 1 - %td.code.cm-s-default - %pre - %div= line - -:javascript - $(document).ready(function() { - var $code_rows = $('.code.cm-s-default pre div'); - var mode = "#{File.extname(@blob.name) == '.spec' ? 'text/x-rpm-spec' : @blob.mime_type}" - $code_rows.each(function() { - CodeMirror.runMode($(this).text().replace(/&/gi, '&'), mode, this.parentElement.parentElement); - }); - }); + %td.code.formatted + = preserve do + = blame_highlight @blob, line diff --git a/app/views/projects/git/blobs/_render_as_text.html.haml b/app/views/projects/git/blobs/_render_as_text.html.haml index 3105d704e..3e34f335f 100644 --- a/app/views/projects/git/blobs/_render_as_text.html.haml +++ b/app/views/projects/git/blobs/_render_as_text.html.haml @@ -1,6 +1,5 @@ .gutter= render_line_numbers(@blob.loc) -#output.formatted.cm-s-default - %pre#code - :preserve - #{h(@blob.data).html_safe} +#output.formatted + = preserve do + = blob_highlight(@blob) .both diff --git a/app/views/projects/git/blobs/_show.html.haml b/app/views/projects/git/blobs/_show.html.haml index b3d1f4606..dcbc218d3 100644 --- a/app/views/projects/git/blobs/_show.html.haml +++ b/app/views/projects/git/blobs/_show.html.haml @@ -8,7 +8,3 @@ .top= render 'top' .data= render "render_as_#{@blob.render_as}" -:javascript - $(document).ready(function() { - CodeMirror.runMode($('#code').text().replace(/&/gi, '&'), "#{@blob.raw_mime_type.content_type}", document.getElementById("output")); - }); \ No newline at end of file diff --git a/app/views/shared/_feed_message.html.haml b/app/views/shared/_feed_message.html.haml index 2d14d40fe..3b88866ef 100644 --- a/app/views/shared/_feed_message.html.haml +++ b/app/views/shared/_feed_message.html.haml @@ -23,6 +23,6 @@ .fulltext{class: "#{presenter.expandable? ? "hidden" : ''} #{presenter.caption? ? "" : "alone"}", id: presenter.expandable? ? "content-expand#{item_no}" : ''} .md_and_cm{class: presenter.is_reference_to_issue ? '' : 'cm-s-default'} - =presenter.is_reference_to_issue ? presenter.content : markdown(presenter.content) + = preserve do + = presenter.is_reference_to_issue ? presenter.content : markdown(presenter.content) .both - diff --git a/vendor/assets/javascripts/codemirror.js b/vendor/assets/javascripts/codemirror.js deleted file mode 100644 index 7bd580f4a..000000000 --- a/vendor/assets/javascripts/codemirror.js +++ /dev/null @@ -1,2959 +0,0 @@ -// All functions that need access to the editor's state live inside -// the CodeMirror function. Below that, at the bottom of the file, -// some utilities are defined. - -// CodeMirror is the only global var we claim -var CodeMirror = (function() { - // This is the function that produces an editor instance. Its - // closure is used to store the editor state. - function CodeMirror(place, givenOptions) { - // Determine effective options based on given values and defaults. - var options = {}, defaults = CodeMirror.defaults; - for (var opt in defaults) - if (defaults.hasOwnProperty(opt)) - options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt]; - - // The element in which the editor lives. - var wrapper = document.createElement("div"); - wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : ""); - // This mess creates the base DOM structure for the editor. - wrapper.innerHTML = - '
' + // Wraps and hides input textarea - '
' + - '
' + - '
' + // Set to the height of the text, causes scrolling - '
' + // Moved around its parent to cover visible view - '
' + - // Provides positioning relative to (visible) text origin - '
' + - '
' + - '
 
' + // Absolutely positioned blinky cursor - '
' + // DIVs containing the selection and the actual code - '
'; - if (place.appendChild) place.appendChild(wrapper); else place(wrapper); - // I've never seen more elegant code in my life. - var inputDiv = wrapper.firstChild, input = inputDiv.firstChild, - scroller = wrapper.lastChild, code = scroller.firstChild, - mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild, - lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild, - cursor = measure.nextSibling, selectionDiv = cursor.nextSibling, - lineDiv = selectionDiv.nextSibling; - themeChanged(); - // Needed to hide big blue blinking cursor on Mobile Safari - if (ios) input.style.width = "0px"; - if (!webkit) lineSpace.draggable = true; - lineSpace.style.outline = "none"; - if (options.tabindex != null) input.tabIndex = options.tabindex; - if (options.autofocus) focusInput(); - if (!options.gutter && !options.lineNumbers) gutter.style.display = "none"; - // Needed to handle Tab key in KHTML - if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute"; - - // Check for problem with IE innerHTML not working when we have a - // P (or similar) parent node. - try { stringWidth("x"); } - catch (e) { - if (e.message.match(/runtime/i)) - e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)"); - throw e; - } - - // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval. - var poll = new Delayed(), highlight = new Delayed(), blinker; - - // mode holds a mode API object. doc is the tree of Line objects, - // work an array of lines that should be parsed, and history the - // undo history (instance of History constructor). - var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), work, focused; - loadMode(); - // The selection. These are always maintained to point at valid - // positions. Inverted is used to remember that the user is - // selecting bottom-to-top. - var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false}; - // Selection-related flags. shiftSelecting obviously tracks - // whether the user is holding shift. - var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText, - overwrite = false, suppressEdits = false; - // Variables used by startOperation/endOperation to track what - // happened during the operation. - var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone, - gutterDirty, callbacks; - // Current visible range (may be bigger than the view window). - var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0; - // bracketHighlighted is used to remember that a bracket has been - // marked. - var bracketHighlighted; - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - var maxLine = "", maxWidth; - var tabCache = {}; - - // Initialize the content. - operation(function(){setValue(options.value || ""); updateInput = false;})(); - var history = new History(); - - // Register our event handlers. - connect(scroller, "mousedown", operation(onMouseDown)); - connect(scroller, "dblclick", operation(onDoubleClick)); - connect(lineSpace, "dragstart", onDragStart); - connect(lineSpace, "selectstart", e_preventDefault); - // Gecko browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for Gecko. - if (!gecko) connect(scroller, "contextmenu", onContextMenu); - connect(scroller, "scroll", function() { - lastScrollPos = scroller.scrollTop; - updateDisplay([]); - if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px"; - if (options.onScroll) options.onScroll(instance); - }); - connect(window, "resize", function() {updateDisplay(true);}); - connect(input, "keyup", operation(onKeyUp)); - connect(input, "input", fastPoll); - connect(input, "keydown", operation(onKeyDown)); - connect(input, "keypress", operation(onKeyPress)); - connect(input, "focus", onFocus); - connect(input, "blur", onBlur); - - connect(scroller, "dragenter", e_stop); - connect(scroller, "dragover", e_stop); - connect(scroller, "drop", operation(onDrop)); - connect(scroller, "paste", function(){focusInput(); fastPoll();}); - connect(input, "paste", fastPoll); - connect(input, "cut", operation(function(){ - if (!options.readOnly) replaceSelection(""); - })); - - // Needed to handle Tab key in KHTML - if (khtml) connect(code, "mouseup", function() { - if (document.activeElement == input) input.blur(); - focusInput(); - }); - - // IE throws unspecified error in certain cases, when - // trying to access activeElement before onload - var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { } - if (hasFocus || options.autofocus) setTimeout(onFocus, 20); - else onBlur(); - - function isLine(l) {return l >= 0 && l < doc.size;} - // The instance object that we'll return. Mostly calls out to - // local functions in the CodeMirror function. Some do some extra - // range checking and/or clipping. operation is used to wrap the - // call so that changes it makes are tracked, and the display is - // updated afterwards. - var instance = wrapper.CodeMirror = { - getValue: getValue, - setValue: operation(setValue), - getSelection: getSelection, - replaceSelection: operation(replaceSelection), - focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();}, - setOption: function(option, value) { - var oldVal = options[option]; - options[option] = value; - if (option == "mode" || option == "indentUnit") loadMode(); - else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();} - else if (option == "readOnly" && !value) {resetInput(true);} - else if (option == "theme") themeChanged(); - else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); - else if (option == "tabSize") updateDisplay(true); - if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") { - gutterChanged(); - updateDisplay(true); - } - }, - getOption: function(option) {return options[option];}, - undo: operation(undo), - redo: operation(redo), - indentLine: operation(function(n, dir) { - if (typeof dir != "string") { - if (dir == null) dir = options.smartIndent ? "smart" : "prev"; - else dir = dir ? "add" : "subtract"; - } - if (isLine(n)) indentLine(n, dir); - }), - indentSelection: operation(indentSelected), - historySize: function() {return {undo: history.done.length, redo: history.undone.length};}, - clearHistory: function() {history = new History();}, - matchBrackets: operation(function(){matchBrackets(true);}), - getTokenAt: operation(function(pos) { - pos = clipPos(pos); - return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch); - }), - getStateAfter: function(line) { - line = clipLine(line == null ? doc.size - 1: line); - return getStateBefore(line + 1); - }, - cursorCoords: function(start, mode) { - if (start == null) start = sel.inverted; - return this.charCoords(start ? sel.from : sel.to, mode); - }, - charCoords: function(pos, mode) { - pos = clipPos(pos); - if (mode == "local") return localCoords(pos, false); - if (mode == "div") return localCoords(pos, true); - return pageCoords(pos); - }, - coordsChar: function(coords) { - var off = eltOffset(lineSpace); - return coordsChar(coords.x - off.left, coords.y - off.top); - }, - markText: operation(markText), - setBookmark: setBookmark, - findMarksAt: findMarksAt, - setMarker: operation(addGutterMarker), - clearMarker: operation(removeGutterMarker), - setLineClass: operation(setLineClass), - hideLine: operation(function(h) {return setLineHidden(h, true);}), - showLine: operation(function(h) {return setLineHidden(h, false);}), - onDeleteLine: function(line, f) { - if (typeof line == "number") { - if (!isLine(line)) return null; - line = getLine(line); - } - (line.handlers || (line.handlers = [])).push(f); - return line; - }, - lineInfo: lineInfo, - addWidget: function(pos, node, scroll, vert, horiz) { - pos = localCoords(clipPos(pos)); - var top = pos.yBot, left = pos.x; - node.style.position = "absolute"; - code.appendChild(node); - if (vert == "over") top = pos.y; - else if (vert == "near") { - var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()), - hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft(); - if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight) - top = pos.y - node.offsetHeight; - if (left + node.offsetWidth > hspace) - left = hspace - node.offsetWidth; - } - node.style.top = (top + paddingTop()) + "px"; - node.style.left = node.style.right = ""; - if (horiz == "right") { - left = code.clientWidth - node.offsetWidth; - node.style.right = "0px"; - } else { - if (horiz == "left") left = 0; - else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2; - node.style.left = (left + paddingLeft()) + "px"; - } - if (scroll) - scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight); - }, - - lineCount: function() {return doc.size;}, - clipPos: clipPos, - getCursor: function(start) { - if (start == null) start = sel.inverted; - return copyPos(start ? sel.from : sel.to); - }, - somethingSelected: function() {return !posEq(sel.from, sel.to);}, - setCursor: operation(function(line, ch, user) { - if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user); - else setCursor(line, ch, user); - }), - setSelection: operation(function(from, to, user) { - (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from)); - }), - getLine: function(line) {if (isLine(line)) return getLine(line).text;}, - getLineHandle: function(line) {if (isLine(line)) return getLine(line);}, - setLine: operation(function(line, text) { - if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length}); - }), - removeLine: operation(function(line) { - if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0})); - }), - replaceRange: operation(replaceRange), - getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));}, - - triggerOnKeyDown: operation(onKeyDown), - execCommand: function(cmd) {return commands[cmd](instance);}, - // Stuff used by commands, probably not much use to outside code. - moveH: operation(moveH), - deleteH: operation(deleteH), - moveV: operation(moveV), - toggleOverwrite: function() { - if(overwrite){ - overwrite = false; - cursor.className = cursor.className.replace(" CodeMirror-overwrite", ""); - } else { - overwrite = true; - cursor.className += " CodeMirror-overwrite"; - } - }, - - posFromIndex: function(off) { - var lineNo = 0, ch; - doc.iter(0, doc.size, function(line) { - var sz = line.text.length + 1; - if (sz > off) { ch = off; return true; } - off -= sz; - ++lineNo; - }); - return clipPos({line: lineNo, ch: ch}); - }, - indexFromPos: function (coords) { - if (coords.line < 0 || coords.ch < 0) return 0; - var index = coords.ch; - doc.iter(0, coords.line, function (line) { - index += line.text.length + 1; - }); - return index; - }, - scrollTo: function(x, y) { - if (x != null) scroller.scrollLeft = x; - if (y != null) scroller.scrollTop = y; - updateDisplay([]); - }, - - operation: function(f){return operation(f)();}, - refresh: function(){ - updateDisplay(true); - if (scroller.scrollHeight > lastScrollPos) - scroller.scrollTop = lastScrollPos; - }, - getInputField: function(){return input;}, - getWrapperElement: function(){return wrapper;}, - getScrollerElement: function(){return scroller;}, - getGutterElement: function(){return gutter;} - }; - - function getLine(n) { return getLineAt(doc, n); } - function updateLineHeight(line, height) { - gutterDirty = true; - var diff = height - line.height; - for (var n = line; n; n = n.parent) n.height += diff; - } - - function setValue(code) { - var top = {line: 0, ch: 0}; - updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length}, - splitLines(code), top, top); - updateInput = true; - } - function getValue(code) { - var text = []; - doc.iter(0, doc.size, function(line) { text.push(line.text); }); - return text.join("\n"); - } - - function onMouseDown(e) { - setShift(e_prop(e, "shiftKey")); - // Check whether this is a click in a widget - for (var n = e_target(e); n != wrapper; n = n.parentNode) - if (n.parentNode == code && n != mover) return; - - // See if this is a click in the gutter - for (var n = e_target(e); n != wrapper; n = n.parentNode) - if (n.parentNode == gutterText) { - if (options.onGutterClick) - options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e); - return e_preventDefault(e); - } - - var start = posFromMouse(e); - - switch (e_button(e)) { - case 3: - if (gecko && !mac) onContextMenu(e); - return; - case 2: - if (start) setCursor(start.line, start.ch, true); - return; - } - // For button 1, if it was clicked inside the editor - // (posFromMouse returning non-null), we have to adjust the - // selection. - if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;} - - if (!focused) onFocus(); - - var now = +new Date; - if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { - e_preventDefault(e); - setTimeout(focusInput, 20); - return selectLine(start.line); - } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { - lastDoubleClick = {time: now, pos: start}; - e_preventDefault(e); - return selectWordAt(start); - } else { lastClick = {time: now, pos: start}; } - - var last = start, going; - if (dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) && - !posLess(start, sel.from) && !posLess(sel.to, start)) { - // Let the drag handler handle this. - if (webkit) lineSpace.draggable = true; - var up = connect(document, "mouseup", operation(function(e2) { - if (webkit) lineSpace.draggable = false; - draggingText = false; - up(); - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2); - setCursor(start.line, start.ch, true); - focusInput(); - } - }), true); - draggingText = true; - // IE's approach to draggable - if (lineSpace.dragDrop) lineSpace.dragDrop(); - return; - } - e_preventDefault(e); - setCursor(start.line, start.ch, true); - - function extend(e) { - var cur = posFromMouse(e, true); - if (cur && !posEq(cur, last)) { - if (!focused) onFocus(); - last = cur; - setSelectionUser(start, cur); - updateInput = false; - var visible = visibleLines(); - if (cur.line >= visible.to || cur.line < visible.from) - going = setTimeout(operation(function(){extend(e);}), 150); - } - } - - function done(e) { - clearTimeout(going); - var cur = posFromMouse(e); - if (cur) setSelectionUser(start, cur); - e_preventDefault(e); - focusInput(); - updateInput = true; - move(); up(); - } - var move = connect(document, "mousemove", operation(function(e) { - clearTimeout(going); - e_preventDefault(e); - if (!ie && !e_button(e)) done(e); - else extend(e); - }), true); - var up = connect(document, "mouseup", operation(done), true); - } - function onDoubleClick(e) { - for (var n = e_target(e); n != wrapper; n = n.parentNode) - if (n.parentNode == gutterText) return e_preventDefault(e); - var start = posFromMouse(e); - if (!start) return; - lastDoubleClick = {time: +new Date, pos: start}; - e_preventDefault(e); - selectWordAt(start); - } - function onDrop(e) { - e.preventDefault(); - var pos = posFromMouse(e, true), files = e.dataTransfer.files; - if (!pos || options.readOnly) return; - if (files && files.length && window.FileReader && window.File) { - function loadFile(file, i) { - var reader = new FileReader; - reader.onload = function() { - text[i] = reader.result; - if (++read == n) { - pos = clipPos(pos); - operation(function() { - var end = replaceRange(text.join(""), pos, pos); - setSelectionUser(pos, end); - })(); - } - }; - reader.readAsText(file); - } - var n = files.length, text = Array(n), read = 0; - for (var i = 0; i < n; ++i) loadFile(files[i], i); - } - else { - try { - var text = e.dataTransfer.getData("Text"); - if (text) { - var curFrom = sel.from, curTo = sel.to; - setSelectionUser(pos, pos); - if (draggingText) replaceRange("", curFrom, curTo); - replaceSelection(text); - focusInput(); - } - } - catch(e){} - } - } - function onDragStart(e) { - var txt = getSelection(); - e.dataTransfer.setData("Text", txt); - - // Use dummy image instead of default browsers image. - if (gecko || chrome) { - var img = document.createElement('img'); - img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image - e.dataTransfer.setDragImage(img, 0, 0); - } - } - - function doHandleBinding(bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound]; - if (!bound) return false; - } - var prevShift = shiftSelecting; - try { - if (options.readOnly) suppressEdits = true; - if (dropShift) shiftSelecting = null; - bound(instance); - } catch(e) { - if (e != Pass) throw e; - return false; - } finally { - shiftSelecting = prevShift; - suppressEdits = false; - } - return true; - } - function handleKeyBinding(e) { - // Handle auto keymap transitions - var startMap = getKeyMap(options.keyMap), next = startMap.auto; - clearTimeout(maybeTransition); - if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() { - if (getKeyMap(options.keyMap) == startMap) { - options.keyMap = (next.call ? next.call(null, instance) : next); - } - }, 50); - - var name = keyNames[e_prop(e, "keyCode")], handled = false; - if (name == null || e.altGraphKey) return false; - if (e_prop(e, "altKey")) name = "Alt-" + name; - if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name; - if (e_prop(e, "metaKey")) name = "Cmd-" + name; - - if (e_prop(e, "shiftKey")) { - handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap, - function(b) {return doHandleBinding(b, true);}) - || lookupKey(name, options.extraKeys, options.keyMap, function(b) { - if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b); - }); - } else { - handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding); - } - if (handled) { - e_preventDefault(e); - if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; } - } - return handled; - } - function handleCharBinding(e, ch) { - var handled = lookupKey("'" + ch + "'", options.extraKeys, - options.keyMap, doHandleBinding); - if (handled) e_preventDefault(e); - return handled; - } - - var lastStoppedKey = null, maybeTransition; - function onKeyDown(e) { - if (!focused) onFocus(); - if (ie && e.keyCode == 27) { e.returnValue = false; } - if (pollingFast) { if (readInput()) pollingFast = false; } - if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; - var code = e_prop(e, "keyCode"); - // IE does strange things with escape. - setShift(code == 16 || e_prop(e, "shiftKey")); - // First give onKeyEvent option a chance to handle this. - var handled = handleKeyBinding(e); - if (window.opera) { - lastStoppedKey = handled ? code : null; - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey")) - replaceSelection(""); - } - } - function onKeyPress(e) { - if (pollingFast) readInput(); - if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; - var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode"); - if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} - if (((window.opera && !e.which) || khtml) && handleKeyBinding(e)) return; - var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) { - if (mode.electricChars.indexOf(ch) > -1) - setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75); - } - if (handleCharBinding(e, ch)) return; - fastPoll(); - } - function onKeyUp(e) { - if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; - if (e_prop(e, "keyCode") == 16) shiftSelecting = null; - } - - function onFocus() { - if (options.readOnly == "nocursor") return; - if (!focused) { - if (options.onFocus) options.onFocus(instance); - focused = true; - if (wrapper.className.search(/\bCodeMirror-focused\b/) == -1) - wrapper.className += " CodeMirror-focused"; - if (!leaveInputAlone) resetInput(true); - } - slowPoll(); - restartBlink(); - } - function onBlur() { - if (focused) { - if (options.onBlur) options.onBlur(instance); - focused = false; - if (bracketHighlighted) - operation(function(){ - if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; } - })(); - wrapper.className = wrapper.className.replace(" CodeMirror-focused", ""); - } - clearInterval(blinker); - setTimeout(function() {if (!focused) shiftSelecting = null;}, 150); - } - - // Replace the range from from to to by the strings in newText. - // Afterwards, set the selection to selFrom, selTo. - function updateLines(from, to, newText, selFrom, selTo) { - if (suppressEdits) return; - if (history) { - var old = []; - doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); }); - history.addChange(from.line, newText.length, old); - while (history.done.length > options.undoDepth) history.done.shift(); - } - updateLinesNoUndo(from, to, newText, selFrom, selTo); - } - function unredoHelper(from, to) { - if (!from.length) return; - var set = from.pop(), out = []; - for (var i = set.length - 1; i >= 0; i -= 1) { - var change = set[i]; - var replaced = [], end = change.start + change.added; - doc.iter(change.start, end, function(line) { replaced.push(line.text); }); - out.push({start: change.start, added: change.old.length, old: replaced}); - var pos = clipPos({line: change.start + change.old.length - 1, - ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])}); - updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos); - } - updateInput = true; - to.push(out); - } - function undo() {unredoHelper(history.done, history.undone);} - function redo() {unredoHelper(history.undone, history.done);} - - function updateLinesNoUndo(from, to, newText, selFrom, selTo) { - if (suppressEdits) return; - var recomputeMaxLength = false, maxLineLength = maxLine.length; - if (!options.lineWrapping) - doc.iter(from.line, to.line, function(line) { - if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;} - }); - if (from.line != to.line || newText.length > 1) gutterDirty = true; - - var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line); - // First adjust the line structure, taking some care to leave highlighting intact. - if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == "") { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = [], prevLine = null; - if (from.line) { - prevLine = getLine(from.line - 1); - prevLine.fixMarkEnds(lastLine); - } else lastLine.fixMarkStarts(); - for (var i = 0, e = newText.length - 1; i < e; ++i) - added.push(Line.inheritMarks(newText[i], prevLine)); - if (nlines) doc.remove(from.line, nlines, callbacks); - if (added.length) doc.insert(from.line, added); - } else if (firstLine == lastLine) { - if (newText.length == 1) - firstLine.replace(from.ch, to.ch, newText[0]); - else { - lastLine = firstLine.split(to.ch, newText[newText.length-1]); - firstLine.replace(from.ch, null, newText[0]); - firstLine.fixMarkEnds(lastLine); - var added = []; - for (var i = 1, e = newText.length - 1; i < e; ++i) - added.push(Line.inheritMarks(newText[i], firstLine)); - added.push(lastLine); - doc.insert(from.line + 1, added); - } - } else if (newText.length == 1) { - firstLine.replace(from.ch, null, newText[0]); - lastLine.replace(null, to.ch, ""); - firstLine.append(lastLine); - doc.remove(from.line + 1, nlines, callbacks); - } else { - var added = []; - firstLine.replace(from.ch, null, newText[0]); - lastLine.replace(null, to.ch, newText[newText.length-1]); - firstLine.fixMarkEnds(lastLine); - for (var i = 1, e = newText.length - 1; i < e; ++i) - added.push(Line.inheritMarks(newText[i], firstLine)); - if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks); - doc.insert(from.line + 1, added); - } - if (options.lineWrapping) { - var perLine = scroller.clientWidth / charWidth() - 3; - doc.iter(from.line, from.line + newText.length, function(line) { - if (line.hidden) return; - var guess = Math.ceil(line.text.length / perLine) || 1; - if (guess != line.height) updateLineHeight(line, guess); - }); - } else { - doc.iter(from.line, i + newText.length, function(line) { - var l = line.text; - if (l.length > maxLineLength) { - maxLine = l; maxLineLength = l.length; maxWidth = null; - recomputeMaxLength = false; - } - }); - if (recomputeMaxLength) { - maxLineLength = 0; maxLine = ""; maxWidth = null; - doc.iter(0, doc.size, function(line) { - var l = line.text; - if (l.length > maxLineLength) { - maxLineLength = l.length; maxLine = l; - } - }); - } - } - - // Add these lines to the work array, so that they will be - // highlighted. Adjust work lines if lines were added/removed. - var newWork = [], lendiff = newText.length - nlines - 1; - for (var i = 0, l = work.length; i < l; ++i) { - var task = work[i]; - if (task < from.line) newWork.push(task); - else if (task > to.line) newWork.push(task + lendiff); - } - var hlEnd = from.line + Math.min(newText.length, 500); - highlightLines(from.line, hlEnd); - newWork.push(hlEnd); - work = newWork; - startWorker(100); - // Remember that these lines changed, for updating the display - changes.push({from: from.line, to: to.line + 1, diff: lendiff}); - var changeObj = {from: from, to: to, text: newText}; - if (textChanged) { - for (var cur = textChanged; cur.next; cur = cur.next) {} - cur.next = changeObj; - } else textChanged = changeObj; - - // Update the selection - function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;} - setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line)); - - // Make sure the scroll-size div has the correct height. - if (scroller.clientHeight) - code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px"; - } - - function replaceRange(code, from, to) { - from = clipPos(from); - if (!to) to = from; else to = clipPos(to); - code = splitLines(code); - function adjustPos(pos) { - if (posLess(pos, from)) return pos; - if (!posLess(to, pos)) return end; - var line = pos.line + code.length - (to.line - from.line) - 1; - var ch = pos.ch; - if (pos.line == to.line) - ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0)); - return {line: line, ch: ch}; - } - var end; - replaceRange1(code, from, to, function(end1) { - end = end1; - return {from: adjustPos(sel.from), to: adjustPos(sel.to)}; - }); - return end; - } - function replaceSelection(code, collapse) { - replaceRange1(splitLines(code), sel.from, sel.to, function(end) { - if (collapse == "end") return {from: end, to: end}; - else if (collapse == "start") return {from: sel.from, to: sel.from}; - else return {from: sel.from, to: end}; - }); - } - function replaceRange1(code, from, to, computeSel) { - var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length; - var newSel = computeSel({line: from.line + code.length - 1, ch: endch}); - updateLines(from, to, code, newSel.from, newSel.to); - } - - function getRange(from, to) { - var l1 = from.line, l2 = to.line; - if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch); - var code = [getLine(l1).text.slice(from.ch)]; - doc.iter(l1 + 1, l2, function(line) { code.push(line.text); }); - code.push(getLine(l2).text.slice(0, to.ch)); - return code.join("\n"); - } - function getSelection() { - return getRange(sel.from, sel.to); - } - - var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll - function slowPoll() { - if (pollingFast) return; - poll.set(options.pollInterval, function() { - startOperation(); - readInput(); - if (focused) slowPoll(); - endOperation(); - }); - } - function fastPoll() { - var missed = false; - pollingFast = true; - function p() { - startOperation(); - var changed = readInput(); - if (!changed && !missed) {missed = true; poll.set(60, p);} - else {pollingFast = false; slowPoll();} - endOperation(); - } - poll.set(20, p); - } - - // Previnput is a hack to work with IME. If we reset the textarea - // on every change, that breaks IME. So we look for changes - // compared to the previous content instead. (Modern browsers have - // events that indicate IME taking place, but these are not widely - // supported or compatible enough yet to rely on.) - var prevInput = ""; - function readInput() { - if (leaveInputAlone || !focused || hasSelection(input) || options.readOnly) return false; - var text = input.value; - if (text == prevInput) return false; - shiftSelecting = null; - var same = 0, l = Math.min(prevInput.length, text.length); - while (same < l && prevInput[same] == text[same]) ++same; - if (same < prevInput.length) - sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)}; - else if (overwrite && posEq(sel.from, sel.to)) - sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))}; - replaceSelection(text.slice(same), "end"); - prevInput = text; - return true; - } - function resetInput(user) { - if (!posEq(sel.from, sel.to)) { - prevInput = ""; - input.value = getSelection(); - selectInput(input); - } else if (user) prevInput = input.value = ""; - } - - function focusInput() { - if (options.readOnly != "nocursor") input.focus(); - } - - function scrollEditorIntoView() { - if (!cursor.getBoundingClientRect) return; - var rect = cursor.getBoundingClientRect(); - // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden - if (ie && rect.top == rect.bottom) return; - var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight); - if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView(); - } - function scrollCursorIntoView() { - var cursor = localCoords(sel.inverted ? sel.from : sel.to); - var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x; - return scrollIntoView(x, cursor.y, x, cursor.yBot); - } - function scrollIntoView(x1, y1, x2, y2) { - var pl = paddingLeft(), pt = paddingTop(); - y1 += pt; y2 += pt; x1 += pl; x2 += pl; - var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true; - if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1); scrolled = true;} - else if (y2 > screentop + screen) {scroller.scrollTop = y2 - screen; scrolled = true;} - - var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft; - var gutterw = options.fixedGutter ? gutter.clientWidth : 0; - if (x1 < screenleft + gutterw) { - if (x1 < 50) x1 = 0; - scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw); - scrolled = true; - } - else if (x2 > screenw + screenleft - 3) { - scroller.scrollLeft = x2 + 10 - screenw; - scrolled = true; - if (x2 > code.clientWidth) result = false; - } - if (scrolled && options.onScroll) options.onScroll(instance); - return result; - } - - function visibleLines() { - var lh = textHeight(), top = scroller.scrollTop - paddingTop(); - var from_height = Math.max(0, Math.floor(top / lh)); - var to_height = Math.ceil((top + scroller.clientHeight) / lh); - return {from: lineAtHeight(doc, from_height), - to: lineAtHeight(doc, to_height)}; - } - // Uses a set of changes plus the current scroll position to - // determine which DOM updates have to be made, and makes the - // updates. - function updateDisplay(changes, suppressCallback) { - if (!scroller.clientWidth) { - showingFrom = showingTo = displayOffset = 0; - return; - } - // Compute the new visible window - var visible = visibleLines(); - // Bail out if the visible area is already rendered and nothing changed. - if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) return; - var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100); - if (showingFrom < from && from - showingFrom < 20) from = showingFrom; - if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo); - - // Create a range of theoretically intact lines, and punch holes - // in that using the change info. - var intact = changes === true ? [] : - computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes); - // Clip off the parts that won't be visible - var intactLines = 0; - for (var i = 0; i < intact.length; ++i) { - var range = intact[i]; - if (range.from < from) {range.domStart += (from - range.from); range.from = from;} - if (range.to > to) range.to = to; - if (range.from >= range.to) intact.splice(i--, 1); - else intactLines += range.to - range.from; - } - if (intactLines == to - from) return; - intact.sort(function(a, b) {return a.domStart - b.domStart;}); - - var th = textHeight(), gutterDisplay = gutter.style.display; - lineDiv.style.display = "none"; - patchDisplay(from, to, intact); - lineDiv.style.display = gutter.style.display = ""; - - // Position the mover div to align with the lines it's supposed - // to be showing (which will cover the visible display) - var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th; - // This is just a bogus formula that detects when the editor is - // resized or the font size changes. - if (different) lastSizeC = scroller.clientHeight + th; - showingFrom = from; showingTo = to; - displayOffset = heightAtLine(doc, from); - mover.style.top = (displayOffset * th) + "px"; - if (scroller.clientHeight) - code.style.height = (doc.height * th + 2 * paddingTop()) + "px"; - - // Since this is all rather error prone, it is honoured with the - // only assertion in the whole file. - if (lineDiv.childNodes.length != showingTo - showingFrom) - throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) + - " nodes=" + lineDiv.childNodes.length); - - if (options.lineWrapping) { - maxWidth = scroller.clientWidth; - var curNode = lineDiv.firstChild, heightChanged = false; - doc.iter(showingFrom, showingTo, function(line) { - if (!line.hidden) { - var height = Math.round(curNode.offsetHeight / th) || 1; - if (line.height != height) { - updateLineHeight(line, height); - gutterDirty = heightChanged = true; - } - } - curNode = curNode.nextSibling; - }); - if (heightChanged) - code.style.height = (doc.height * th + 2 * paddingTop()) + "px"; - } else { - if (maxWidth == null) maxWidth = stringWidth(maxLine); - if (maxWidth > scroller.clientWidth) { - lineSpace.style.width = maxWidth + "px"; - // Needed to prevent odd wrapping/hiding of widgets placed in here. - code.style.width = ""; - code.style.width = scroller.scrollWidth + "px"; - } else { - lineSpace.style.width = code.style.width = ""; - } - } - gutter.style.display = gutterDisplay; - if (different || gutterDirty) updateGutter(); - updateSelection(); - if (!suppressCallback && options.onUpdate) options.onUpdate(instance); - return true; - } - - function computeIntact(intact, changes) { - for (var i = 0, l = changes.length || 0; i < l; ++i) { - var change = changes[i], intact2 = [], diff = change.diff || 0; - for (var j = 0, l2 = intact.length; j < l2; ++j) { - var range = intact[j]; - if (change.to <= range.from && change.diff) - intact2.push({from: range.from + diff, to: range.to + diff, - domStart: range.domStart}); - else if (change.to <= range.from || change.from >= range.to) - intact2.push(range); - else { - if (change.from > range.from) - intact2.push({from: range.from, to: change.from, domStart: range.domStart}); - if (change.to < range.to) - intact2.push({from: change.to + diff, to: range.to + diff, - domStart: range.domStart + (change.to - range.from)}); - } - } - intact = intact2; - } - return intact; - } - - function patchDisplay(from, to, intact) { - // The first pass removes the DOM nodes that aren't intact. - if (!intact.length) lineDiv.innerHTML = ""; - else { - function killNode(node) { - var tmp = node.nextSibling; - node.parentNode.removeChild(node); - return tmp; - } - var domPos = 0, curNode = lineDiv.firstChild, n; - for (var i = 0; i < intact.length; ++i) { - var cur = intact[i]; - while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;} - for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;} - } - while (curNode) curNode = killNode(curNode); - } - // This pass fills in the lines that actually changed. - var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from; - var scratch = document.createElement("div"); - doc.iter(from, to, function(line) { - if (nextIntact && nextIntact.to == j) nextIntact = intact.shift(); - if (!nextIntact || nextIntact.from > j) { - if (line.hidden) var html = scratch.innerHTML = "
";
-          else {
-            var html = ''
-              + line.getHTML(makeTab) + '';
-            // Kludge to make sure the styled element lies behind the selection (by z-index)
-            if (line.bgClassName)
-              html = '
 
' + html + "
"; - } - scratch.innerHTML = html; - lineDiv.insertBefore(scratch.firstChild, curNode); - } else { - curNode = curNode.nextSibling; - } - ++j; - }); - } - - function updateGutter() { - if (!options.gutter && !options.lineNumbers) return; - var hText = mover.offsetHeight, hEditor = scroller.clientHeight; - gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px"; - var html = [], i = showingFrom, normalNode; - doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) { - if (line.hidden) { - html.push("
");
-        } else {
-          var marker = line.gutterMarker;
-          var text = options.lineNumbers ? i + options.firstLineNumber : null;
-          if (marker && marker.text)
-            text = marker.text.replace("%N%", text != null ? text : "");
-          else if (text == null)
-            text = "\u00a0";
-          html.push((marker && marker.style ? '
' : "
"), text);
-          for (var j = 1; j < line.height; ++j) html.push("
 "); - html.push("
"); - if (!marker) normalNode = i; - } - ++i; - }); - gutter.style.display = "none"; - gutterText.innerHTML = html.join(""); - // Make sure scrolling doesn't cause number gutter size to pop - if (normalNode != null) { - var node = gutterText.childNodes[normalNode - showingFrom]; - var minwidth = String(doc.size).length, val = eltText(node), pad = ""; - while (val.length + pad.length < minwidth) pad += "\u00a0"; - if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild); - } - gutter.style.display = ""; - lineSpace.style.marginLeft = gutter.offsetWidth + "px"; - gutterDirty = false; - } - function updateSelection() { - var collapsed = posEq(sel.from, sel.to); - var fromPos = localCoords(sel.from, true); - var toPos = collapsed ? fromPos : localCoords(sel.to, true); - var headPos = sel.inverted ? fromPos : toPos, th = textHeight(); - var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv); - inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px"; - inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px"; - if (collapsed) { - cursor.style.top = headPos.y + "px"; - cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px"; - cursor.style.display = ""; - selectionDiv.style.display = "none"; - } else { - var sameLine = fromPos.y == toPos.y, html = ""; - function add(left, top, right, height) { - html += '
'; - } - var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth; - var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight; - if (sel.from.ch && fromPos.y >= 0) { - var right = sameLine ? clientWidth - toPos.x : 0; - add(fromPos.x, fromPos.y, right, th); - } - var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0)); - var middleHeight = Math.min(toPos.y, clientHeight) - middleStart; - if (middleHeight > 0.2 * th) - add(0, middleStart, 0, middleHeight); - if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th) - add(0, toPos.y, clientWidth - toPos.x, th); - selectionDiv.innerHTML = html; - cursor.style.display = "none"; - selectionDiv.style.display = ""; - } - } - - function setShift(val) { - if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from); - else shiftSelecting = null; - } - function setSelectionUser(from, to) { - var sh = shiftSelecting && clipPos(shiftSelecting); - if (sh) { - if (posLess(sh, from)) from = sh; - else if (posLess(to, sh)) to = sh; - } - setSelection(from, to); - userSelChange = true; - } - // Update the selection. Last two args are only used by - // updateLines, since they have to be expressed in the line - // numbers before the update. - function setSelection(from, to, oldFrom, oldTo) { - goalColumn = null; - if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;} - if (posEq(sel.from, from) && posEq(sel.to, to)) return; - if (posLess(to, from)) {var tmp = to; to = from; from = tmp;} - - // Skip over hidden lines. - if (from.line != oldFrom) { - var from1 = skipHidden(from, oldFrom, sel.from.ch); - // If there is no non-hidden line left, force visibility on current line - if (!from1) setLineHidden(from.line, false); - else from = from1; - } - if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch); - - if (posEq(from, to)) sel.inverted = false; - else if (posEq(from, sel.to)) sel.inverted = false; - else if (posEq(to, sel.from)) sel.inverted = true; - - if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) { - var head = sel.inverted ? from : to; - if (head.line != sel.from.line && sel.from.line < doc.size) { - var oldLine = getLine(sel.from.line); - if (/^\s+$/.test(oldLine.text)) - setTimeout(operation(function() { - if (oldLine.parent && /^\s+$/.test(oldLine.text)) { - var no = lineNo(oldLine); - replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length}); - } - }, 10)); - } - } - - sel.from = from; sel.to = to; - selectionChanged = true; - } - function skipHidden(pos, oldLine, oldCh) { - function getNonHidden(dir) { - var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1; - while (lNo != end) { - var line = getLine(lNo); - if (!line.hidden) { - var ch = pos.ch; - if (ch > oldCh || ch > line.text.length) ch = line.text.length; - return {line: lNo, ch: ch}; - } - lNo += dir; - } - } - var line = getLine(pos.line); - if (!line.hidden) return pos; - if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1); - else return getNonHidden(-1) || getNonHidden(1); - } - function setCursor(line, ch, user) { - var pos = clipPos({line: line, ch: ch || 0}); - (user ? setSelectionUser : setSelection)(pos, pos); - } - - function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));} - function clipPos(pos) { - if (pos.line < 0) return {line: 0, ch: 0}; - if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length}; - var ch = pos.ch, linelen = getLine(pos.line).text.length; - if (ch == null || ch > linelen) return {line: pos.line, ch: linelen}; - else if (ch < 0) return {line: pos.line, ch: 0}; - else return pos; - } - - function findPosH(dir, unit) { - var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch; - var lineObj = getLine(line); - function findNextLine() { - for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) { - var lo = getLine(l); - if (!lo.hidden) { line = l; lineObj = lo; return true; } - } - } - function moveOnce(boundToLine) { - if (ch == (dir < 0 ? 0 : lineObj.text.length)) { - if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0; - else return false; - } else ch += dir; - return true; - } - if (unit == "char") moveOnce(); - else if (unit == "column") moveOnce(true); - else if (unit == "word") { - var sawWord = false; - for (;;) { - if (dir < 0) if (!moveOnce()) break; - if (isWordChar(lineObj.text.charAt(ch))) sawWord = true; - else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;} - if (dir > 0) if (!moveOnce()) break; - } - } - return {line: line, ch: ch}; - } - function moveH(dir, unit) { - var pos = dir < 0 ? sel.from : sel.to; - if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit); - setCursor(pos.line, pos.ch, true); - } - function deleteH(dir, unit) { - if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to); - else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to); - else replaceRange("", sel.from, findPosH(dir, unit)); - userSelChange = true; - } - var goalColumn = null; - function moveV(dir, unit) { - var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true); - if (goalColumn != null) pos.x = goalColumn; - if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight); - else if (unit == "line") dist = textHeight(); - var target = coordsChar(pos.x, pos.y + dist * dir + 2); - if (unit == "page") scroller.scrollTop += localCoords(target, true).y - pos.y; - setCursor(target.line, target.ch, true); - goalColumn = pos.x; - } - - function selectWordAt(pos) { - var line = getLine(pos.line).text; - var start = pos.ch, end = pos.ch; - while (start > 0 && isWordChar(line.charAt(start - 1))) --start; - while (end < line.length && isWordChar(line.charAt(end))) ++end; - setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end}); - } - function selectLine(line) { - setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0})); - } - function indentSelected(mode) { - if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode); - var e = sel.to.line - (sel.to.ch ? 0 : 1); - for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode); - } - - function indentLine(n, how) { - if (!how) how = "add"; - if (how == "smart") { - if (!mode.indent) how = "prev"; - else var state = getStateBefore(n); - } - - var line = getLine(n), curSpace = line.indentation(options.tabSize), - curSpaceString = line.text.match(/^\s*/)[0], indentation; - if (how == "prev") { - if (n) indentation = getLine(n-1).indentation(options.tabSize); - else indentation = 0; - } - else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text); - else if (how == "add") indentation = curSpace + options.indentUnit; - else if (how == "subtract") indentation = curSpace - options.indentUnit; - indentation = Math.max(0, indentation); - var diff = indentation - curSpace; - - if (!diff) { - if (sel.from.line != n && sel.to.line != n) return; - var indentString = curSpaceString; - } - else { - var indentString = "", pos = 0; - if (options.indentWithTabs) - for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";} - while (pos < indentation) {++pos; indentString += " ";} - } - - replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length}); - } - - function loadMode() { - mode = CodeMirror.getMode(options, options.mode); - doc.iter(0, doc.size, function(line) { line.stateAfter = null; }); - work = [0]; - startWorker(); - } - function gutterChanged() { - var visible = options.gutter || options.lineNumbers; - gutter.style.display = visible ? "" : "none"; - if (visible) gutterDirty = true; - else lineDiv.parentNode.style.marginLeft = 0; - } - function wrappingChanged(from, to) { - if (options.lineWrapping) { - wrapper.className += " CodeMirror-wrap"; - var perLine = scroller.clientWidth / charWidth() - 3; - doc.iter(0, doc.size, function(line) { - if (line.hidden) return; - var guess = Math.ceil(line.text.length / perLine) || 1; - if (guess != 1) updateLineHeight(line, guess); - }); - lineSpace.style.width = code.style.width = ""; - } else { - wrapper.className = wrapper.className.replace(" CodeMirror-wrap", ""); - maxWidth = null; maxLine = ""; - doc.iter(0, doc.size, function(line) { - if (line.height != 1 && !line.hidden) updateLineHeight(line, 1); - if (line.text.length > maxLine.length) maxLine = line.text; - }); - } - changes.push({from: 0, to: doc.size}); - } - function makeTab(col) { - var w = options.tabSize - col % options.tabSize, cached = tabCache[w]; - if (cached) return cached; - for (var str = '', i = 0; i < w; ++i) str += " "; - return (tabCache[w] = {html: str + "", width: w}); - } - function themeChanged() { - scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") + - options.theme.replace(/(^|\s)\s*/g, " cm-s-"); - } - - function TextMarker() { this.set = []; } - TextMarker.prototype.clear = operation(function() { - var min = Infinity, max = -Infinity; - for (var i = 0, e = this.set.length; i < e; ++i) { - var line = this.set[i], mk = line.marked; - if (!mk || !line.parent) continue; - var lineN = lineNo(line); - min = Math.min(min, lineN); max = Math.max(max, lineN); - for (var j = 0; j < mk.length; ++j) - if (mk[j].marker == this) mk.splice(j--, 1); - } - if (min != Infinity) - changes.push({from: min, to: max + 1}); - }); - TextMarker.prototype.find = function() { - var from, to; - for (var i = 0, e = this.set.length; i < e; ++i) { - var line = this.set[i], mk = line.marked; - for (var j = 0; j < mk.length; ++j) { - var mark = mk[j]; - if (mark.marker == this) { - if (mark.from != null || mark.to != null) { - var found = lineNo(line); - if (found != null) { - if (mark.from != null) from = {line: found, ch: mark.from}; - if (mark.to != null) to = {line: found, ch: mark.to}; - } - } - } - } - } - return {from: from, to: to}; - }; - - function markText(from, to, className) { - from = clipPos(from); to = clipPos(to); - var tm = new TextMarker(); - if (!posLess(from, to)) return tm; - function add(line, from, to, className) { - getLine(line).addMark(new MarkedText(from, to, className, tm)); - } - if (from.line == to.line) add(from.line, from.ch, to.ch, className); - else { - add(from.line, from.ch, null, className); - for (var i = from.line + 1, e = to.line; i < e; ++i) - add(i, null, null, className); - add(to.line, null, to.ch, className); - } - changes.push({from: from.line, to: to.line + 1}); - return tm; - } - - function setBookmark(pos) { - pos = clipPos(pos); - var bm = new Bookmark(pos.ch); - getLine(pos.line).addMark(bm); - return bm; - } - - function findMarksAt(pos) { - pos = clipPos(pos); - var markers = [], marked = getLine(pos.line).marked; - if (!marked) return markers; - for (var i = 0, e = marked.length; i < e; ++i) { - var m = marked[i]; - if ((m.from == null || m.from <= pos.ch) && - (m.to == null || m.to >= pos.ch)) - markers.push(m.marker || m); - } - return markers; - } - - function addGutterMarker(line, text, className) { - if (typeof line == "number") line = getLine(clipLine(line)); - line.gutterMarker = {text: text, style: className}; - gutterDirty = true; - return line; - } - function removeGutterMarker(line) { - if (typeof line == "number") line = getLine(clipLine(line)); - line.gutterMarker = null; - gutterDirty = true; - } - - function changeLine(handle, op) { - var no = handle, line = handle; - if (typeof handle == "number") line = getLine(clipLine(handle)); - else no = lineNo(handle); - if (no == null) return null; - if (op(line, no)) changes.push({from: no, to: no + 1}); - else return null; - return line; - } - function setLineClass(handle, className, bgClassName) { - return changeLine(handle, function(line) { - if (line.className != className || line.bgClassName != bgClassName) { - line.className = className; - line.bgClassName = bgClassName; - return true; - } - }); - } - function setLineHidden(handle, hidden) { - return changeLine(handle, function(line, no) { - if (line.hidden != hidden) { - line.hidden = hidden; - updateLineHeight(line, hidden ? 0 : 1); - var fline = sel.from.line, tline = sel.to.line; - if (hidden && (fline == no || tline == no)) { - var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from; - var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to; - // Can't hide the last visible line, we'd have no place to put the cursor - if (!to) return; - setSelection(from, to); - } - return (gutterDirty = true); - } - }); - } - - function lineInfo(line) { - if (typeof line == "number") { - if (!isLine(line)) return null; - var n = line; - line = getLine(line); - if (!line) return null; - } - else { - var n = lineNo(line); - if (n == null) return null; - } - var marker = line.gutterMarker; - return {line: n, handle: line, text: line.text, markerText: marker && marker.text, - markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName}; - } - - function stringWidth(str) { - measure.innerHTML = "
x
"; - measure.firstChild.firstChild.firstChild.nodeValue = str; - return measure.firstChild.firstChild.offsetWidth || 10; - } - // These are used to go from pixel positions to character - // positions, taking varying character widths into account. - function charFromX(line, x) { - if (x <= 0) return 0; - var lineObj = getLine(line), text = lineObj.text; - function getX(len) { - measure.innerHTML = "
" + lineObj.getHTML(makeTab, len) + "
"; - return measure.firstChild.firstChild.offsetWidth; - } - var from = 0, fromX = 0, to = text.length, toX; - // Guess a suitable upper bound for our search. - var estimated = Math.min(to, Math.ceil(x / charWidth())); - for (;;) { - var estX = getX(estimated); - if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2)); - else {toX = estX; to = estimated; break;} - } - if (x > toX) return to; - // Try to guess a suitable lower bound as well. - estimated = Math.floor(to * 0.8); estX = getX(estimated); - if (estX < x) {from = estimated; fromX = estX;} - // Do a binary search between these bounds. - for (;;) { - if (to - from <= 1) return (toX - x > x - fromX) ? from : to; - var middle = Math.ceil((from + to) / 2), middleX = getX(middle); - if (middleX > x) {to = middle; toX = middleX;} - else {from = middle; fromX = middleX;} - } - } - - var tempId = Math.floor(Math.random() * 0xffffff).toString(16); - function measureLine(line, ch) { - if (ch == 0) return {top: 0, left: 0}; - var extra = ""; - // Include extra text at the end to make sure the measured line is wrapped in the right way. - if (options.lineWrapping) { - var end = line.text.indexOf(" ", ch + 6); - extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0))); - } - measure.innerHTML = "
" + line.getHTML(makeTab, ch) +
-        '' + htmlEscape(line.text.charAt(ch) || " ") + "" +
-        extra + "
"; - var elt = document.getElementById("CodeMirror-temp-" + tempId); - var top = elt.offsetTop, left = elt.offsetLeft; - // Older IEs report zero offsets for spans directly after a wrap - if (ie && top == 0 && left == 0) { - var backup = document.createElement("span"); - backup.innerHTML = "x"; - elt.parentNode.insertBefore(backup, elt.nextSibling); - top = backup.offsetTop; - } - return {top: top, left: left}; - } - function localCoords(pos, inLineWrap) { - var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0)); - if (pos.ch == 0) x = 0; - else { - var sp = measureLine(getLine(pos.line), pos.ch); - x = sp.left; - if (options.lineWrapping) y += Math.max(0, sp.top); - } - return {x: x, y: y, yBot: y + lh}; - } - // Coords must be lineSpace-local - function coordsChar(x, y) { - if (y < 0) y = 0; - var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th); - var lineNo = lineAtHeight(doc, heightPos); - if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length}; - var lineObj = getLine(lineNo), text = lineObj.text; - var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0; - if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0}; - function getX(len) { - var sp = measureLine(lineObj, len); - if (tw) { - var off = Math.round(sp.top / th); - return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth); - } - return sp.left; - } - var from = 0, fromX = 0, to = text.length, toX; - // Guess a suitable upper bound for our search. - var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw)); - for (;;) { - var estX = getX(estimated); - if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2)); - else {toX = estX; to = estimated; break;} - } - if (x > toX) return {line: lineNo, ch: to}; - // Try to guess a suitable lower bound as well. - estimated = Math.floor(to * 0.8); estX = getX(estimated); - if (estX < x) {from = estimated; fromX = estX;} - // Do a binary search between these bounds. - for (;;) { - if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to}; - var middle = Math.ceil((from + to) / 2), middleX = getX(middle); - if (middleX > x) {to = middle; toX = middleX;} - else {from = middle; fromX = middleX;} - } - } - function pageCoords(pos) { - var local = localCoords(pos, true), off = eltOffset(lineSpace); - return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot}; - } - - var cachedHeight, cachedHeightFor, measureText; - function textHeight() { - if (measureText == null) { - measureText = "
";
-        for (var i = 0; i < 49; ++i) measureText += "x
"; - measureText += "x
"; - } - var offsetHeight = lineDiv.clientHeight; - if (offsetHeight == cachedHeightFor) return cachedHeight; - cachedHeightFor = offsetHeight; - measure.innerHTML = measureText; - cachedHeight = measure.firstChild.offsetHeight / 50 || 1; - measure.innerHTML = ""; - return cachedHeight; - } - var cachedWidth, cachedWidthFor = 0; - function charWidth() { - if (scroller.clientWidth == cachedWidthFor) return cachedWidth; - cachedWidthFor = scroller.clientWidth; - return (cachedWidth = stringWidth("x")); - } - function paddingTop() {return lineSpace.offsetTop;} - function paddingLeft() {return lineSpace.offsetLeft;} - - function posFromMouse(e, liberal) { - var offW = eltOffset(scroller, true), x, y; - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX; y = e.clientY; } catch (e) { return null; } - // This is a mess of a heuristic to try and determine whether a - // scroll-bar was clicked or not, and to return null if one was - // (and !liberal). - if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight)) - return null; - var offL = eltOffset(lineSpace, true); - return coordsChar(x - offL.left, y - offL.top); - } - function onContextMenu(e) { - var pos = posFromMouse(e), scrollPos = scroller.scrollTop; - if (!pos || window.opera) return; // Opera is difficult. - if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) - operation(setCursor)(pos.line, pos.ch); - - var oldCSS = input.style.cssText; - inputDiv.style.position = "absolute"; - input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + - "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " + - "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; - leaveInputAlone = true; - var val = input.value = getSelection(); - focusInput(); - selectInput(input); - function rehide() { - var newVal = splitLines(input.value).join("\n"); - if (newVal != val) operation(replaceSelection)(newVal, "end"); - inputDiv.style.position = "relative"; - input.style.cssText = oldCSS; - if (ie_lt9) scroller.scrollTop = scrollPos; - leaveInputAlone = false; - resetInput(true); - slowPoll(); - } - - if (gecko) { - e_stop(e); - var mouseup = connect(window, "mouseup", function() { - mouseup(); - setTimeout(rehide, 20); - }, true); - } else { - setTimeout(rehide, 50); - } - } - - // Cursor-blinking - function restartBlink() { - clearInterval(blinker); - var on = true; - cursor.style.visibility = ""; - blinker = setInterval(function() { - cursor.style.visibility = (on = !on) ? "" : "hidden"; - }, 650); - } - - var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; - function matchBrackets(autoclear) { - var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1; - var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; - if (!match) return; - var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles; - for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2) - if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;} - - var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; - function scan(line, from, to) { - if (!line.text) return; - var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur; - for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) { - var text = st[i]; - if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;} - for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) { - if (pos >= from && pos < to && re.test(cur = text.charAt(j))) { - var match = matching[cur]; - if (match.charAt(1) == ">" == forward) stack.push(cur); - else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; - else if (!stack.length) return {pos: pos, match: true}; - } - } - } - } - for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) { - var line = getLine(i), first = i == head.line; - var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length); - if (found) break; - } - if (!found) found = {pos: null, match: false}; - var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; - var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style), - two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style); - var clear = operation(function(){one.clear(); two && two.clear();}); - if (autoclear) setTimeout(clear, 800); - else bracketHighlighted = clear; - } - - // Finds the line to start with when starting a parse. Tries to - // find a line with a stateAfter, so that it can start with a - // valid state. If that fails, it returns the line with the - // smallest indentation, which tends to need the least context to - // parse correctly. - function findStartLine(n) { - var minindent, minline; - for (var search = n, lim = n - 40; search > lim; --search) { - if (search == 0) return 0; - var line = getLine(search-1); - if (line.stateAfter) return search; - var indented = line.indentation(options.tabSize); - if (minline == null || minindent > indented) { - minline = search - 1; - minindent = indented; - } - } - return minline; - } - function getStateBefore(n) { - var start = findStartLine(n), state = start && getLine(start-1).stateAfter; - if (!state) state = startState(mode); - else state = copyState(mode, state); - doc.iter(start, n, function(line) { - line.highlight(mode, state, options.tabSize); - line.stateAfter = copyState(mode, state); - }); - if (start < n) changes.push({from: start, to: n}); - if (n < doc.size && !getLine(n).stateAfter) work.push(n); - return state; - } - function highlightLines(start, end) { - var state = getStateBefore(start); - doc.iter(start, end, function(line) { - line.highlight(mode, state, options.tabSize); - line.stateAfter = copyState(mode, state); - }); - } - function highlightWorker() { - var end = +new Date + options.workTime; - var foundWork = work.length; - while (work.length) { - if (!getLine(showingFrom).stateAfter) var task = showingFrom; - else var task = work.pop(); - if (task >= doc.size) continue; - var start = findStartLine(task), state = start && getLine(start-1).stateAfter; - if (state) state = copyState(mode, state); - else state = startState(mode); - - var unchanged = 0, compare = mode.compareStates, realChange = false, - i = start, bail = false; - doc.iter(i, doc.size, function(line) { - var hadState = line.stateAfter; - if (+new Date > end) { - work.push(i); - startWorker(options.workDelay); - if (realChange) changes.push({from: task, to: i + 1}); - return (bail = true); - } - var changed = line.highlight(mode, state, options.tabSize); - if (changed) realChange = true; - line.stateAfter = copyState(mode, state); - if (compare) { - if (hadState && compare(hadState, state)) return true; - } else { - if (changed !== false || !hadState) unchanged = 0; - else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, ""))) - return true; - } - ++i; - }); - if (bail) return; - if (realChange) changes.push({from: task, to: i + 1}); - } - if (foundWork && options.onHighlightComplete) - options.onHighlightComplete(instance); - } - function startWorker(time) { - if (!work.length) return; - highlight.set(time, operation(highlightWorker)); - } - - // Operations are used to wrap changes in such a way that each - // change won't have to update the cursor and display (which would - // be awkward, slow, and error-prone), but instead updates are - // batched and then all combined and executed at once. - function startOperation() { - updateInput = userSelChange = textChanged = null; - changes = []; selectionChanged = false; callbacks = []; - } - function endOperation() { - var reScroll = false, updated; - if (selectionChanged) reScroll = !scrollCursorIntoView(); - if (changes.length) updated = updateDisplay(changes, true); - else { - if (selectionChanged) updateSelection(); - if (gutterDirty) updateGutter(); - } - if (reScroll) scrollCursorIntoView(); - if (selectionChanged) {scrollEditorIntoView(); restartBlink();} - - if (focused && !leaveInputAlone && - (updateInput === true || (updateInput !== false && selectionChanged))) - resetInput(userSelChange); - - if (selectionChanged && options.matchBrackets) - setTimeout(operation(function() { - if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;} - if (posEq(sel.from, sel.to)) matchBrackets(false); - }), 20); - var tc = textChanged, cbs = callbacks; // these can be reset by callbacks - if (selectionChanged && options.onCursorActivity) - options.onCursorActivity(instance); - if (tc && options.onChange && instance) - options.onChange(instance, tc); - for (var i = 0; i < cbs.length; ++i) cbs[i](instance); - if (updated && options.onUpdate) options.onUpdate(instance); - } - var nestedOperation = 0; - function operation(f) { - return function() { - if (!nestedOperation++) startOperation(); - try {var result = f.apply(this, arguments);} - finally {if (!--nestedOperation) endOperation();} - return result; - }; - } - - for (var ext in extensions) - if (extensions.propertyIsEnumerable(ext) && - !instance.propertyIsEnumerable(ext)) - instance[ext] = extensions[ext]; - return instance; - } // (end of function CodeMirror) - - // The default configuration options. - CodeMirror.defaults = { - value: "", - mode: null, - theme: "default", - indentUnit: 2, - indentWithTabs: false, - smartIndent: true, - tabSize: 4, - keyMap: "default", - extraKeys: null, - electricChars: true, - autoClearEmptyLines: false, - onKeyEvent: null, - lineWrapping: false, - lineNumbers: false, - gutter: false, - fixedGutter: false, - firstLineNumber: 1, - readOnly: false, - onChange: null, - onCursorActivity: null, - onGutterClick: null, - onHighlightComplete: null, - onUpdate: null, - onFocus: null, onBlur: null, onScroll: null, - matchBrackets: false, - workTime: 100, - workDelay: 200, - pollInterval: 100, - undoDepth: 40, - tabindex: null, - autofocus: null - }; - - var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); - var mac = ios || /Mac/.test(navigator.platform); - var win = /Win/.test(navigator.platform); - - // Known modes, by name and by MIME - var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; - CodeMirror.defineMode = function(name, mode) { - if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; - modes[name] = mode; - }; - CodeMirror.defineMIME = function(mime, spec) { - mimeModes[mime] = spec; - }; - CodeMirror.resolveMode = function(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) - spec = mimeModes[spec]; - else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) - return CodeMirror.resolveMode("application/xml"); - if (typeof spec == "string") return {name: spec}; - else return spec || {name: "null"}; - }; - CodeMirror.getMode = function(options, spec) { - var spec = CodeMirror.resolveMode(spec); - var mfactory = modes[spec.name]; - if (!mfactory) { - if (window.console) console.warn("No mode " + spec.name + " found, falling back to plain text."); - return CodeMirror.getMode(options, "text/plain"); - } - return mfactory(options, spec); - }; - CodeMirror.listModes = function() { - var list = []; - for (var m in modes) - if (modes.propertyIsEnumerable(m)) list.push(m); - return list; - }; - CodeMirror.listMIMEs = function() { - var list = []; - for (var m in mimeModes) - if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]}); - return list; - }; - - var extensions = CodeMirror.extensions = {}; - CodeMirror.defineExtension = function(name, func) { - extensions[name] = func; - }; - - var commands = CodeMirror.commands = { - selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});}, - killLine: function(cm) { - var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); - if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0}); - else cm.replaceRange("", from, sel ? to : {line: from.line}); - }, - deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});}, - undo: function(cm) {cm.undo();}, - redo: function(cm) {cm.redo();}, - goDocStart: function(cm) {cm.setCursor(0, 0, true);}, - goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);}, - goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);}, - goLineStartSmart: function(cm) { - var cur = cm.getCursor(); - var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/)); - cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true); - }, - goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);}, - goLineUp: function(cm) {cm.moveV(-1, "line");}, - goLineDown: function(cm) {cm.moveV(1, "line");}, - goPageUp: function(cm) {cm.moveV(-1, "page");}, - goPageDown: function(cm) {cm.moveV(1, "page");}, - goCharLeft: function(cm) {cm.moveH(-1, "char");}, - goCharRight: function(cm) {cm.moveH(1, "char");}, - goColumnLeft: function(cm) {cm.moveH(-1, "column");}, - goColumnRight: function(cm) {cm.moveH(1, "column");}, - goWordLeft: function(cm) {cm.moveH(-1, "word");}, - goWordRight: function(cm) {cm.moveH(1, "word");}, - delCharLeft: function(cm) {cm.deleteH(-1, "char");}, - delCharRight: function(cm) {cm.deleteH(1, "char");}, - delWordLeft: function(cm) {cm.deleteH(-1, "word");}, - delWordRight: function(cm) {cm.deleteH(1, "word");}, - indentAuto: function(cm) {cm.indentSelection("smart");}, - indentMore: function(cm) {cm.indentSelection("add");}, - indentLess: function(cm) {cm.indentSelection("subtract");}, - insertTab: function(cm) {cm.replaceSelection("\t", "end");}, - transposeChars: function(cm) { - var cur = cm.getCursor(), line = cm.getLine(cur.line); - if (cur.ch > 0 && cur.ch < line.length - 1) - cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), - {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1}); - }, - newlineAndIndent: function(cm) { - cm.replaceSelection("\n", "end"); - cm.indentLine(cm.getCursor().line); - }, - toggleOverwrite: function(cm) {cm.toggleOverwrite();} - }; - - var keyMap = CodeMirror.keyMap = {}; - keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "insertTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" - }; - // Note that the save and find-related commands aren't defined by - // default. Unknown commands are simply ignored. - keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", - "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find", - "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", - fallthrough: "basic" - }; - keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft", - "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft", - "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find", - "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", "Cmd-]": "indentMore", - fallthrough: ["basic", "emacsy"] - }; - keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; - keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageUp", "Shift-Ctrl-V": "goPageDown", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft", - "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" - }; - - function getKeyMap(val) { - if (typeof val == "string") return keyMap[val]; - else return val; - } - function lookupKey(name, extraMap, map, handle) { - function lookup(map) { - map = getKeyMap(map); - var found = map[name]; - if (found != null && handle(found)) return true; - if (map.catchall) return handle(map.catchall); - var fallthrough = map.fallthrough; - if (fallthrough == null) return false; - if (Object.prototype.toString.call(fallthrough) != "[object Array]") - return lookup(fallthrough); - for (var i = 0, e = fallthrough.length; i < e; ++i) { - if (lookup(fallthrough[i])) return true; - } - return false; - } - if (extraMap && lookup(extraMap)) return true; - return lookup(map); - } - function isModifierKey(event) { - var name = keyNames[e_prop(event, "keyCode")]; - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; - } - - CodeMirror.fromTextArea = function(textarea, options) { - if (!options) options = {}; - options.value = textarea.value; - if (!options.tabindex && textarea.tabindex) - options.tabindex = textarea.tabindex; - if (options.autofocus == null && textarea.getAttribute("autofocus") != null) - options.autofocus = true; - - function save() {textarea.value = instance.getValue();} - if (textarea.form) { - // Deplorable hack to make the submit method do the right thing. - var rmSubmit = connect(textarea.form, "submit", save, true); - if (typeof textarea.form.submit == "function") { - var realSubmit = textarea.form.submit; - function wrappedSubmit() { - save(); - textarea.form.submit = realSubmit; - textarea.form.submit(); - textarea.form.submit = wrappedSubmit; - } - textarea.form.submit = wrappedSubmit; - } - } - - textarea.style.display = "none"; - var instance = CodeMirror(function(node) { - textarea.parentNode.insertBefore(node, textarea.nextSibling); - }, options); - instance.save = save; - instance.getTextArea = function() { return textarea; }; - instance.toTextArea = function() { - save(); - textarea.parentNode.removeChild(instance.getWrapperElement()); - textarea.style.display = ""; - if (textarea.form) { - rmSubmit(); - if (typeof textarea.form.submit == "function") - textarea.form.submit = realSubmit; - } - }; - return instance; - }; - - // Utility functions for working with state. Exported because modes - // sometimes need to do this. - function copyState(mode, state) { - if (state === true) return state; - if (mode.copyState) return mode.copyState(state); - var nstate = {}; - for (var n in state) { - var val = state[n]; - if (val instanceof Array) val = val.concat([]); - nstate[n] = val; - } - return nstate; - } - CodeMirror.copyState = copyState; - function startState(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true; - } - CodeMirror.startState = startState; - - // The character stream used by a mode's parser. - function StringStream(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - } - StringStream.prototype = { - eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == 0;}, - peek: function() {return this.string.charAt(this.pos);}, - next: function() { - if (this.pos < this.string.length) - return this.string.charAt(this.pos++); - }, - eat: function(match) { - var ch = this.string.charAt(this.pos); - if (typeof match == "string") var ok = ch == match; - else var ok = ch && (match.test ? match.test(ch) : match(ch)); - if (ok) {++this.pos; return ch;} - }, - eatWhile: function(match) { - var start = this.pos; - while (this.eat(match)){} - return this.pos > start; - }, - eatSpace: function() { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; - return this.pos > start; - }, - skipToEnd: function() {this.pos = this.string.length;}, - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) {this.pos = found; return true;} - }, - backUp: function(n) {this.pos -= n;}, - column: function() {return countColumn(this.string, this.start, this.tabSize);}, - indentation: function() {return countColumn(this.string, null, this.tabSize);}, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - function cased(str) {return caseInsensitive ? str.toLowerCase() : str;} - if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { - if (consume !== false) this.pos += pattern.length; - return true; - } - } - else { - var match = this.string.slice(this.pos).match(pattern); - if (match && consume !== false) this.pos += match[0].length; - return match; - } - }, - current: function(){return this.string.slice(this.start, this.pos);} - }; - CodeMirror.StringStream = StringStream; - - function MarkedText(from, to, className, marker) { - this.from = from; this.to = to; this.style = className; this.marker = marker; - } - MarkedText.prototype = { - attach: function(line) { this.marker.set.push(line); }, - detach: function(line) { - var ix = indexOf(this.marker.set, line); - if (ix > -1) this.marker.set.splice(ix, 1); - }, - split: function(pos, lenBefore) { - if (this.to <= pos && this.to != null) return null; - var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore; - var to = this.to == null ? null : this.to - pos + lenBefore; - return new MarkedText(from, to, this.style, this.marker); - }, - dup: function() { return new MarkedText(null, null, this.style, this.marker); }, - clipTo: function(fromOpen, from, toOpen, to, diff) { - if (fromOpen && to > this.from && (to < this.to || this.to == null)) - this.from = null; - else if (this.from != null && this.from >= from) - this.from = Math.max(to, this.from) + diff; - if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null)) - this.to = null; - else if (this.to != null && this.to > from) - this.to = to < this.to ? this.to + diff : from; - }, - isDead: function() { return this.from != null && this.to != null && this.from >= this.to; }, - sameSet: function(x) { return this.marker == x.marker; } - }; - - function Bookmark(pos) { - this.from = pos; this.to = pos; this.line = null; - } - Bookmark.prototype = { - attach: function(line) { this.line = line; }, - detach: function(line) { if (this.line == line) this.line = null; }, - split: function(pos, lenBefore) { - if (pos < this.from) { - this.from = this.to = (this.from - pos) + lenBefore; - return this; - } - }, - isDead: function() { return this.from > this.to; }, - clipTo: function(fromOpen, from, toOpen, to, diff) { - if ((fromOpen || from < this.from) && (toOpen || to > this.to)) { - this.from = 0; this.to = -1; - } else if (this.from > from) { - this.from = this.to = Math.max(to, this.from) + diff; - } - }, - sameSet: function(x) { return false; }, - find: function() { - if (!this.line || !this.line.parent) return null; - return {line: lineNo(this.line), ch: this.from}; - }, - clear: function() { - if (this.line) { - var found = indexOf(this.line.marked, this); - if (found != -1) this.line.marked.splice(found, 1); - this.line = null; - } - } - }; - - // Line objects. These hold state related to a line, including - // highlighting info (the styles array). - function Line(text, styles) { - this.styles = styles || [text, null]; - this.text = text; - this.height = 1; - this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null; - this.stateAfter = this.parent = this.hidden = null; - } - Line.inheritMarks = function(text, orig) { - var ln = new Line(text), mk = orig && orig.marked; - if (mk) { - for (var i = 0; i < mk.length; ++i) { - if (mk[i].to == null && mk[i].style) { - var newmk = ln.marked || (ln.marked = []), mark = mk[i]; - var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln); - } - } - } - return ln; - } - Line.prototype = { - // Replace a piece of a line, keeping the styles around it intact. - replace: function(from, to_, text) { - var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_; - copyStyles(0, from, this.styles, st); - if (text) st.push(text, null); - copyStyles(to, this.text.length, this.styles, st); - this.styles = st; - this.text = this.text.slice(0, from) + text + this.text.slice(to); - this.stateAfter = null; - if (mk) { - var diff = text.length - (to - from); - for (var i = 0; i < mk.length; ++i) { - var mark = mk[i]; - mark.clipTo(from == null, from || 0, to_ == null, to, diff); - if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);} - } - } - }, - // Split a part off a line, keeping styles and markers intact. - split: function(pos, textBefore) { - var st = [textBefore, null], mk = this.marked; - copyStyles(pos, this.text.length, this.styles, st); - var taken = new Line(textBefore + this.text.slice(pos), st); - if (mk) { - for (var i = 0; i < mk.length; ++i) { - var mark = mk[i]; - var newmark = mark.split(pos, textBefore.length); - if (newmark) { - if (!taken.marked) taken.marked = []; - taken.marked.push(newmark); newmark.attach(taken); - if (newmark == mark) mk.splice(i--, 1); - } - } - } - return taken; - }, - append: function(line) { - var mylen = this.text.length, mk = line.marked, mymk = this.marked; - this.text += line.text; - copyStyles(0, line.text.length, line.styles, this.styles); - if (mymk) { - for (var i = 0; i < mymk.length; ++i) - if (mymk[i].to == null) mymk[i].to = mylen; - } - if (mk && mk.length) { - if (!mymk) this.marked = mymk = []; - outer: for (var i = 0; i < mk.length; ++i) { - var mark = mk[i]; - if (!mark.from) { - for (var j = 0; j < mymk.length; ++j) { - var mymark = mymk[j]; - if (mymark.to == mylen && mymark.sameSet(mark)) { - mymark.to = mark.to == null ? null : mark.to + mylen; - if (mymark.isDead()) { - mymark.detach(this); - mk.splice(i--, 1); - } - continue outer; - } - } - } - mymk.push(mark); - mark.attach(this); - mark.from += mylen; - if (mark.to != null) mark.to += mylen; - } - } - }, - fixMarkEnds: function(other) { - var mk = this.marked, omk = other.marked; - if (!mk) return; - for (var i = 0; i < mk.length; ++i) { - var mark = mk[i], close = mark.to == null; - if (close && omk) { - for (var j = 0; j < omk.length; ++j) - if (omk[j].sameSet(mark)) {close = false; break;} - } - if (close) mark.to = this.text.length; - } - }, - fixMarkStarts: function() { - var mk = this.marked; - if (!mk) return; - for (var i = 0; i < mk.length; ++i) - if (mk[i].from == null) mk[i].from = 0; - }, - addMark: function(mark) { - mark.attach(this); - if (this.marked == null) this.marked = []; - this.marked.push(mark); - this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);}); - }, - // Run the given mode's parser over a line, update the styles - // array, which contains alternating fragments of text and CSS - // classes. - highlight: function(mode, state, tabSize) { - var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0; - var changed = false, curWord = st[0], prevWord; - if (this.text == "" && mode.blankLine) mode.blankLine(state); - while (!stream.eol()) { - var style = mode.token(stream, state); - var substr = this.text.slice(stream.start, stream.pos); - stream.start = stream.pos; - if (pos && st[pos-1] == style) - st[pos-2] += substr; - else if (substr) { - if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true; - st[pos++] = substr; st[pos++] = style; - prevWord = curWord; curWord = st[pos]; - } - // Give up when line is ridiculously long - if (stream.pos > 5000) { - st[pos++] = this.text.slice(stream.pos); st[pos++] = null; - break; - } - } - if (st.length != pos) {st.length = pos; changed = true;} - if (pos && st[pos-2] != prevWord) changed = true; - // Short lines with simple highlights return null, and are - // counted as changed by the driver because they are likely to - // highlight the same way in various contexts. - return changed || (st.length < 5 && this.text.length < 10 ? null : false); - }, - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(mode, state, ch) { - var txt = this.text, stream = new StringStream(txt); - while (stream.pos < ch && !stream.eol()) { - stream.start = stream.pos; - var style = mode.token(stream, state); - } - return {start: stream.start, - end: stream.pos, - string: stream.current(), - className: style || null, - state: state}; - }, - indentation: function(tabSize) {return countColumn(this.text, null, tabSize);}, - // Produces an HTML fragment for the line, taking selection, - // marking, and highlighting into account. - getHTML: function(makeTab, endAt) { - var html = [], first = true, col = 0; - function span(text, style) { - if (!text) return; - // Work around a bug where, in some compat modes, IE ignores leading spaces - if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1); - first = false; - if (text.indexOf("\t") == -1) { - col += text.length; - var escaped = htmlEscape(text); - } else { - var escaped = ""; - for (var pos = 0;;) { - var idx = text.indexOf("\t", pos); - if (idx == -1) { - escaped += htmlEscape(text.slice(pos)); - col += text.length - pos; - break; - } else { - col += idx - pos; - var tab = makeTab(col); - escaped += htmlEscape(text.slice(pos, idx)) + tab.html; - col += tab.width; - pos = idx + 1; - } - } - } - if (style) html.push('', escaped, ""); - else html.push(escaped); - } - var st = this.styles, allText = this.text, marked = this.marked; - var len = allText.length; - if (endAt != null) len = Math.min(endAt, len); - function styleToClass(style) { - if (!style) return null; - return "cm-" + style.replace(/ +/g, " cm-"); - } - - if (!allText && endAt == null) - span(" "); - else if (!marked || !marked.length) - for (var i = 0, ch = 0; ch < len; i+=2) { - var str = st[i], style = st[i+1], l = str.length; - if (ch + l > len) str = str.slice(0, len - ch); - ch += l; - span(str, styleToClass(style)); - } - else { - var pos = 0, i = 0, text = "", style, sg = 0; - var nextChange = marked[0].from || 0, marks = [], markpos = 0; - function advanceMarks() { - var m; - while (markpos < marked.length && - ((m = marked[markpos]).from == pos || m.from == null)) { - if (m.style != null) marks.push(m); - ++markpos; - } - nextChange = markpos < marked.length ? marked[markpos].from : Infinity; - for (var i = 0; i < marks.length; ++i) { - var to = marks[i].to || Infinity; - if (to == pos) marks.splice(i--, 1); - else nextChange = Math.min(to, nextChange); - } - } - var m = 0; - while (pos < len) { - if (nextChange == pos) advanceMarks(); - var upto = Math.min(len, nextChange); - while (true) { - if (text) { - var end = pos + text.length; - var appliedStyle = style; - for (var j = 0; j < marks.length; ++j) - appliedStyle = (appliedStyle ? appliedStyle + " " : "") + marks[j].style; - span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle); - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} - pos = end; - } - text = st[i++]; style = styleToClass(st[i++]); - } - } - } - return html.join(""); - }, - cleanUp: function() { - this.parent = null; - if (this.marked) - for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this); - } - }; - // Utility used by replace and split above - function copyStyles(from, to, source, dest) { - for (var i = 0, pos = 0, state = 0; pos < to; i+=2) { - var part = source[i], end = pos + part.length; - if (state == 0) { - if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]); - if (end >= from) state = 1; - } - else if (state == 1) { - if (end > to) dest.push(part.slice(0, to - pos), source[i+1]); - else dest.push(part, source[i+1]); - } - pos = end; - } - } - - // Data structure that holds the sequence of lines. - function LeafChunk(lines) { - this.lines = lines; - this.parent = null; - for (var i = 0, e = lines.length, height = 0; i < e; ++i) { - lines[i].parent = this; - height += lines[i].height; - } - this.height = height; - } - LeafChunk.prototype = { - chunkSize: function() { return this.lines.length; }, - remove: function(at, n, callbacks) { - for (var i = at, e = at + n; i < e; ++i) { - var line = this.lines[i]; - this.height -= line.height; - line.cleanUp(); - if (line.handlers) - for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]); - } - this.lines.splice(at, n); - }, - collapse: function(lines) { - lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); - }, - insertHeight: function(at, lines, height) { - this.height += height; - this.lines.splice.apply(this.lines, [at, 0].concat(lines)); - for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; - }, - iterN: function(at, n, op) { - for (var e = at + n; at < e; ++at) - if (op(this.lines[at])) return true; - } - }; - function BranchChunk(children) { - this.children = children; - var size = 0, height = 0; - for (var i = 0, e = children.length; i < e; ++i) { - var ch = children[i]; - size += ch.chunkSize(); height += ch.height; - ch.parent = this; - } - this.size = size; - this.height = height; - this.parent = null; - } - BranchChunk.prototype = { - chunkSize: function() { return this.size; }, - remove: function(at, n, callbacks) { - this.size -= n; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var rm = Math.min(n, sz - at), oldHeight = child.height; - child.remove(at, rm, callbacks); - this.height -= oldHeight - child.height; - if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } - if ((n -= rm) == 0) break; - at = 0; - } else at -= sz; - } - if (this.size - n < 25) { - var lines = []; - this.collapse(lines); - this.children = [new LeafChunk(lines)]; - this.children[0].parent = this; - } - }, - collapse: function(lines) { - for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); - }, - insert: function(at, lines) { - var height = 0; - for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; - this.insertHeight(at, lines, height); - }, - insertHeight: function(at, lines, height) { - this.size += lines.length; - this.height += height; - for (var i = 0, e = this.children.length; i < e; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at <= sz) { - child.insertHeight(at, lines, height); - if (child.lines && child.lines.length > 50) { - while (child.lines.length > 50) { - var spilled = child.lines.splice(child.lines.length - 25, 25); - var newleaf = new LeafChunk(spilled); - child.height -= newleaf.height; - this.children.splice(i + 1, 0, newleaf); - newleaf.parent = this; - } - this.maybeSpill(); - } - break; - } - at -= sz; - } - }, - maybeSpill: function() { - if (this.children.length <= 10) return; - var me = this; - do { - var spilled = me.children.splice(me.children.length - 5, 5); - var sibling = new BranchChunk(spilled); - if (!me.parent) { // Become the parent node - var copy = new BranchChunk(me.children); - copy.parent = me; - me.children = [copy, sibling]; - me = copy; - } else { - me.size -= sibling.size; - me.height -= sibling.height; - var myIndex = indexOf(me.parent.children, me); - me.parent.children.splice(myIndex + 1, 0, sibling); - } - sibling.parent = me.parent; - } while (me.children.length > 10); - me.parent.maybeSpill(); - }, - iter: function(from, to, op) { this.iterN(from, to - from, op); }, - iterN: function(at, n, op) { - for (var i = 0, e = this.children.length; i < e; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var used = Math.min(n, sz - at); - if (child.iterN(at, used, op)) return true; - if ((n -= used) == 0) break; - at = 0; - } else at -= sz; - } - } - }; - - function getLineAt(chunk, n) { - while (!chunk.lines) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize(); - if (n < sz) { chunk = child; break; } - n -= sz; - } - } - return chunk.lines[n]; - } - function lineNo(line) { - if (line.parent == null) return null; - var cur = line.parent, no = indexOf(cur.lines, line); - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0, e = chunk.children.length; ; ++i) { - if (chunk.children[i] == cur) break; - no += chunk.children[i].chunkSize(); - } - } - return no; - } - function lineAtHeight(chunk, h) { - var n = 0; - outer: do { - for (var i = 0, e = chunk.children.length; i < e; ++i) { - var child = chunk.children[i], ch = child.height; - if (h < ch) { chunk = child; continue outer; } - h -= ch; - n += child.chunkSize(); - } - return n; - } while (!chunk.lines); - for (var i = 0, e = chunk.lines.length; i < e; ++i) { - var line = chunk.lines[i], lh = line.height; - if (h < lh) break; - h -= lh; - } - return n + i; - } - function heightAtLine(chunk, n) { - var h = 0; - outer: do { - for (var i = 0, e = chunk.children.length; i < e; ++i) { - var child = chunk.children[i], sz = child.chunkSize(); - if (n < sz) { chunk = child; continue outer; } - n -= sz; - h += child.height; - } - return h; - } while (!chunk.lines); - for (var i = 0; i < n; ++i) h += chunk.lines[i].height; - return h; - } - - // The history object 'chunks' changes that are made close together - // and at almost the same time into bigger undoable units. - function History() { - this.time = 0; - this.done = []; this.undone = []; - } - History.prototype = { - addChange: function(start, added, old) { - this.undone.length = 0; - var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1]; - var dtime = time - this.time; - if (dtime > 400 || !last) { - this.done.push([{start: start, added: added, old: old}]); - } else if (last.start > start + old.length || last.start + last.added < start - last.added + last.old.length) { - cur.push({start: start, added: added, old: old}); - } else { - var oldoff = 0; - if (start < last.start) { - for (var i = last.start - start - 1; i >= 0; --i) - last.old.unshift(old[i]); - oldoff = Math.min(0, added - old.length); - last.added += last.start - start + oldoff; - last.start = start; - } else if (last.start < start) { - oldoff = start - last.start; - added += oldoff; - } - for (var i = last.added - oldoff, e = old.length; i < e; ++i) - last.old.push(old[i]); - if (last.added < added) last.added = added; - } - this.time = time; - } - }; - - function stopMethod() {e_stop(this);} - // Ensure an event has a stop method. - function addStop(event) { - if (!event.stop) event.stop = stopMethod; - return event; - } - - function e_preventDefault(e) { - if (e.preventDefault) e.preventDefault(); - else e.returnValue = false; - } - function e_stopPropagation(e) { - if (e.stopPropagation) e.stopPropagation(); - else e.cancelBubble = true; - } - function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} - CodeMirror.e_stop = e_stop; - CodeMirror.e_preventDefault = e_preventDefault; - CodeMirror.e_stopPropagation = e_stopPropagation; - - function e_target(e) {return e.target || e.srcElement;} - function e_button(e) { - if (e.which) return e.which; - else if (e.button & 1) return 1; - else if (e.button & 2) return 3; - else if (e.button & 4) return 2; - } - - // Allow 3rd-party code to override event properties by adding an override - // object to an event object. - function e_prop(e, prop) { - var overridden = e.override && e.override.hasOwnProperty(prop); - return overridden ? e.override[prop] : e[prop]; - } - - // Event handler registration. If disconnect is true, it'll return a - // function that unregisters the handler. - function connect(node, type, handler, disconnect) { - if (typeof node.addEventListener == "function") { - node.addEventListener(type, handler, false); - if (disconnect) return function() {node.removeEventListener(type, handler, false);}; - } - else { - var wrapHandler = function(event) {handler(event || window.event);}; - node.attachEvent("on" + type, wrapHandler); - if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);}; - } - } - CodeMirror.connect = connect; - - function Delayed() {this.id = null;} - Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}}; - - var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; - - var gecko = /gecko\/\d{7}/i.test(navigator.userAgent); - var ie = /MSIE \d/.test(navigator.userAgent); - var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent); - var webkit = /WebKit\//.test(navigator.userAgent); - var chrome = /Chrome\//.test(navigator.userAgent); - var khtml = /KHTML\//.test(navigator.userAgent); - - // Detect drag-and-drop - var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie_lt9) return false; - var div = document.createElement('div'); - return "draggable" in div || "dragDrop" in div; - }(); - - var lineSep = "\n"; - // Feature-detect whether newlines in textareas are converted to \r\n - (function () { - var te = document.createElement("textarea"); - te.value = "foo\nbar"; - if (te.value.indexOf("\r") > -1) lineSep = "\r\n"; - }()); - - // Counts the column offset in a string, taking tabs into account. - // Used mostly to find indentation. - function countColumn(string, end, tabSize) { - if (end == null) { - end = string.search(/[^\s\u00a0]/); - if (end == -1) end = string.length; - } - for (var i = 0, n = 0; i < end; ++i) { - if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); - else ++n; - } - return n; - } - - function computedStyle(elt) { - if (elt.currentStyle) return elt.currentStyle; - return window.getComputedStyle(elt, null); - } - - // Find the position of an element by following the offsetParent chain. - // If screen==true, it returns screen (rather than page) coordinates. - function eltOffset(node, screen) { - var bod = node.ownerDocument.body; - var x = 0, y = 0, skipBody = false; - for (var n = node; n; n = n.offsetParent) { - var ol = n.offsetLeft, ot = n.offsetTop; - // Firefox reports weird inverted offsets when the body has a border. - if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); } - else { x += ol, y += ot; } - if (screen && computedStyle(n).position == "fixed") - skipBody = true; - } - var e = screen && !skipBody ? null : bod; - for (var n = node.parentNode; n != e; n = n.parentNode) - if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;} - return {left: x, top: y}; - } - // Use the faster and saner getBoundingClientRect method when possible. - if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) { - // Take the parts of bounding client rect that we are interested in so we are able to edit if need be, - // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page) - try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; } - catch(e) { box = {top: 0, left: 0}; } - if (!screen) { - // Get the toplevel scroll, working around browser differences. - if (window.pageYOffset == null) { - var t = document.documentElement || document.body.parentNode; - if (t.scrollTop == null) t = document.body; - box.top += t.scrollTop; box.left += t.scrollLeft; - } else { - box.top += window.pageYOffset; box.left += window.pageXOffset; - } - } - return box; - }; - - // Get a node's text content. - function eltText(node) { - return node.textContent || node.innerText || node.nodeValue || ""; - } - function selectInput(node) { - if (ios) { // Mobile Safari apparently has a bug where select() is broken. - node.selectionStart = 0; - node.selectionEnd = node.value.length; - } else node.select(); - } - - // Operations on {line, ch} objects. - function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} - function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} - function copyPos(x) {return {line: x.line, ch: x.ch};} - - var escapeElement = document.createElement("pre"); - function htmlEscape(str) { - escapeElement.textContent = str; - return escapeElement.innerHTML; - } - // Recent (late 2011) Opera betas insert bogus newlines at the start - // of the textContent, so we strip those. - if (htmlEscape("a") == "\na") - htmlEscape = function(str) { - escapeElement.textContent = str; - return escapeElement.innerHTML.slice(1); - }; - // Some IEs don't preserve tabs through innerHTML - else if (htmlEscape("\t") != "\t") - htmlEscape = function(str) { - escapeElement.innerHTML = ""; - escapeElement.appendChild(document.createTextNode(str)); - return escapeElement.innerHTML; - }; - CodeMirror.htmlEscape = htmlEscape; - - // Used to position the cursor after an undo/redo by finding the - // last edited character. - function editEnd(from, to) { - if (!to) return 0; - if (!from) return to.length; - for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j) - if (from.charAt(i) != to.charAt(j)) break; - return j + 1; - } - - function indexOf(collection, elt) { - if (collection.indexOf) return collection.indexOf(elt); - for (var i = 0, e = collection.length; i < e; ++i) - if (collection[i] == elt) return i; - return -1; - } - function isWordChar(ch) { - return /\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase(); - } - - // See if "".split is the broken IE version, if so, provide an - // alternative way to split lines. - var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { - var pos = 0, nl, result = []; - while ((nl = string.indexOf("\n", pos)) > -1) { - result.push(string.slice(pos, string.charAt(nl-1) == "\r" ? nl - 1 : nl)); - pos = nl + 1; - } - result.push(string.slice(pos)); - return result; - } : function(string){return string.split(/\r?\n/);}; - CodeMirror.splitLines = splitLines; - - var hasSelection = window.getSelection ? function(te) { - try { return te.selectionStart != te.selectionEnd; } - catch(e) { return false; } - } : function(te) { - try {var range = te.ownerDocument.selection.createRange();} - catch(e) {} - if (!range || range.parentElement() != te) return false; - return range.compareEndPoints("StartToEnd", range) != 0; - }; - - CodeMirror.defineMode("null", function() { - return {token: function(stream) {stream.skipToEnd();}}; - }); - CodeMirror.defineMIME("text/plain", "null"); - - var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", - 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", - 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 127: "Delete", 186: ";", 187: "=", 188: ",", - 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'", 63276: "PageUp", - 63277: "PageDown", 63275: "End", 63273: "Home", 63234: "Left", 63232: "Up", 63235: "Right", - 63233: "Down", 63302: "Insert", 63272: "Delete"}; - CodeMirror.keyNames = keyNames; - (function() { - // Number keys - for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); - // Alphabetic keys - for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); - // Function keys - for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; - })(); - - return CodeMirror; -})(); diff --git a/vendor/assets/javascripts/codemirror/keymaps/emacs.js b/vendor/assets/javascripts/codemirror/keymaps/emacs.js deleted file mode 100644 index 8fd3564e2..000000000 --- a/vendor/assets/javascripts/codemirror/keymaps/emacs.js +++ /dev/null @@ -1,29 +0,0 @@ -// TODO number prefixes -(function() { - // Really primitive kill-ring implementation. - var killRing = []; - function addToRing(str) { - killRing.push(str); - if (killRing.length > 50) killRing.shift(); - } - function getFromRing() { return killRing[killRing.length - 1] || ""; } - function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); } - - CodeMirror.keyMap.emacs = { - "Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");}, - "Ctrl-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");}, - "Ctrl-Alt-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");}, - "Alt-W": function(cm) {addToRing(cm.getSelection());}, - "Ctrl-Y": function(cm) {cm.replaceSelection(getFromRing());}, - "Alt-Y": function(cm) {cm.replaceSelection(popFromRing());}, - "Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", - "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace", - "Ctrl-Z": "undo", "Cmd-Z": "undo", - fallthrough: ["basic", "emacsy"] - }; - - CodeMirror.keyMap["emacs-Ctrl-X"] = { - "Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": "undo", "K": "close", - auto: "emacs", catchall: function(cm) {/*ignore*/} - }; -})(); diff --git a/vendor/assets/javascripts/codemirror/keymaps/vim.js b/vendor/assets/javascripts/codemirror/keymaps/vim.js deleted file mode 100644 index f8fa5e07b..000000000 --- a/vendor/assets/javascripts/codemirror/keymaps/vim.js +++ /dev/null @@ -1,347 +0,0 @@ -(function() { - var count = ""; - var sdir = "f"; - var buf = ""; - var yank = 0; - var mark = []; - function emptyBuffer() { buf = ""; } - function pushInBuffer(str) { buf += str; }; - function pushCountDigit(digit) { return function(cm) {count += digit;} } - function popCount() { var i = parseInt(count); count = ""; return i || 1; } - function countTimes(func) { - if (typeof func == "string") func = CodeMirror.commands[func]; - return function(cm) { for (var i = 0, c = popCount(); i < c; ++i) func(cm); } - } - - function iterObj(o, f) { - for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]); - } - - var word = [/\w/, /[^\w\s]/], bigWord = [/\S/]; - function findWord(line, pos, dir, regexps) { - var stop = 0, next = -1; - if (dir > 0) { stop = line.length; next = 0; } - var start = stop, end = stop; - // Find bounds of next one. - outer: for (; pos != stop; pos += dir) { - for (var i = 0; i < regexps.length; ++i) { - if (regexps[i].test(line.charAt(pos + next))) { - start = pos; - for (; pos != stop; pos += dir) { - if (!regexps[i].test(line.charAt(pos + next))) break; - } - end = pos; - break outer; - } - } - } - return {from: Math.min(start, end), to: Math.max(start, end)}; - } - function moveToWord(cm, regexps, dir, where) { - var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word; - while (true) { - word = findWord(line, ch, dir, regexps); - ch = word[where == "end" ? "to" : "from"]; - if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? "from" : "to"]; - else break; - } - cm.setCursor(cur.line, word[where == "end" ? "to" : "from"], true); - } - function joinLineNext(cm) { - var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line); - CodeMirror.commands.goLineEnd(cm); - if (cur.line != cm.lineCount()) { - CodeMirror.commands.goLineEnd(cm); - cm.replaceSelection(" ", "end"); - CodeMirror.commands.delCharRight(cm); - } - } - function editCursor(mode) { - if (mode == "vim-insert") { - // put in your cursor css changing code - } else if (mode == "vim") { - // put in your cursor css changing code - } - } - function delTillMark(cm, cHar) { - var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l; - cm.setCursor(start); - for (var c = start; c <= end; c++) { - pushInBuffer("\n"+cm.getLine(start)); - cm.removeLine(start); - } - } - function yankTillMark(cm, cHar) { - var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l; - for (var c = start; c <= end; c++) { - pushInBuffer("\n"+cm.getLine(c)); - } - cm.setCursor(start); - } - - var map = CodeMirror.keyMap.vim = { - "0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);}, - "A": function(cm) {popCount(); cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");}, - "Shift-A": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");}, - "I": function(cm) {popCount(); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");}, - "Shift-I": function(cm) {popCount(); CodeMirror.commands.goLineStartSmart(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");}, - "O": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.replaceSelection("\n", "end"); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");}, - "Shift-O": function(cm) {popCount(); CodeMirror.commands.goLineStart(cm); cm.replaceSelection("\n", "start"); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");}, - "G": function(cm) {cm.setOption("keyMap", "vim-prefix-g");}, - "D": function(cm) {cm.setOption("keyMap", "vim-prefix-d"); emptyBuffer();}, - "M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];}, - "Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;}, - "/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f"}, - "Shift-/": function(cm) { - var f = CodeMirror.commands.find; - if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; } - }, - "N": function(cm) { - var fn = CodeMirror.commands.findNext; - if (fn) sdir != "r" ? fn(cm) : CodeMirror.commands.findPrev(cm); - }, - "Shift-N": function(cm) { - var fn = CodeMirror.commands.findNext; - if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm); - }, - "Shift-G": function(cm) {count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count)-1); popCount(); CodeMirror.commands.goLineStart(cm);}, - catchall: function(cm) {/*ignore*/} - }; - // Add bindings for number keys - for (var i = 1; i < 10; ++i) map[i] = pushCountDigit(i); - // Add bindings that are influenced by number keys - iterObj({"H": "goColumnLeft", "L": "goColumnRight", "J": "goLineDown", "K": "goLineUp", - "Left": "goColumnLeft", "Right": "goColumnRight", "Down": "goLineDown", "Up": "goLineUp", - "Backspace": "goCharLeft", "Space": "goCharRight", - "B": function(cm) {moveToWord(cm, word, -1, "end");}, - "E": function(cm) {moveToWord(cm, word, 1, "end");}, - "W": function(cm) {moveToWord(cm, word, 1, "start");}, - "Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");}, - "Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");}, - "Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");}, - "X": function(cm) {CodeMirror.commands.delCharRight(cm)}, - "P": function(cm) { - var cur = cm.getCursor().line; - if (buf!= "") { - CodeMirror.commands.goLineEnd(cm); - cm.replaceSelection(buf, "end"); - } - cm.setCursor(cur+1); - }, - "Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm)}, - "Shift-J": function(cm) {joinLineNext(cm)}, - "Shift-`": function(cm) { - var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1}); - cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase(); - cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1}); - cm.setCursor(cur.line, cur.ch+1); - }, - "Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm)}, - "Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm)}, - "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "U": "undo", "Ctrl-R": "redo", "Shift-4": "goLineEnd"}, - function(key, cmd) { map[key] = countTimes(cmd); }); - - CodeMirror.keyMap["vim-prefix-g"] = { - "E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}), - "Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}), - auto: "vim", - catchall: function(cm) {/*ignore*/} - }; - - CodeMirror.keyMap["vim-prefix-m"] = { - "A": function(cm) {mark["A"] = cm.getCursor().line;}, - "Shift-A": function(cm) {mark["Shift-A"] = cm.getCursor().line;}, - "B": function(cm) {mark["B"] = cm.getCursor().line;}, - "Shift-B": function(cm) {mark["Shift-B"] = cm.getCursor().line;}, - "C": function(cm) {mark["C"] = cm.getCursor().line;}, - "Shift-C": function(cm) {mark["Shift-C"] = cm.getCursor().line;}, - "D": function(cm) {mark["D"] = cm.getCursor().line;}, - "Shift-D": function(cm) {mark["Shift-D"] = cm.getCursor().line;}, - "E": function(cm) {mark["E"] = cm.getCursor().line;}, - "Shift-E": function(cm) {mark["Shift-E"] = cm.getCursor().line;}, - "F": function(cm) {mark["F"] = cm.getCursor().line;}, - "Shift-F": function(cm) {mark["Shift-F"] = cm.getCursor().line;}, - "G": function(cm) {mark["G"] = cm.getCursor().line;}, - "Shift-G": function(cm) {mark["Shift-G"] = cm.getCursor().line;}, - "H": function(cm) {mark["H"] = cm.getCursor().line;}, - "Shift-H": function(cm) {mark["Shift-H"] = cm.getCursor().line;}, - "I": function(cm) {mark["I"] = cm.getCursor().line;}, - "Shift-I": function(cm) {mark["Shift-I"] = cm.getCursor().line;}, - "J": function(cm) {mark["J"] = cm.getCursor().line;}, - "Shift-J": function(cm) {mark["Shift-J"] = cm.getCursor().line;}, - "K": function(cm) {mark["K"] = cm.getCursor().line;}, - "Shift-K": function(cm) {mark["Shift-K"] = cm.getCursor().line;}, - "L": function(cm) {mark["L"] = cm.getCursor().line;}, - "Shift-L": function(cm) {mark["Shift-L"] = cm.getCursor().line;}, - "M": function(cm) {mark["M"] = cm.getCursor().line;}, - "Shift-M": function(cm) {mark["Shift-M"] = cm.getCursor().line;}, - "N": function(cm) {mark["N"] = cm.getCursor().line;}, - "Shift-N": function(cm) {mark["Shift-N"] = cm.getCursor().line;}, - "O": function(cm) {mark["O"] = cm.getCursor().line;}, - "Shift-O": function(cm) {mark["Shift-O"] = cm.getCursor().line;}, - "P": function(cm) {mark["P"] = cm.getCursor().line;}, - "Shift-P": function(cm) {mark["Shift-P"] = cm.getCursor().line;}, - "Q": function(cm) {mark["Q"] = cm.getCursor().line;}, - "Shift-Q": function(cm) {mark["Shift-Q"] = cm.getCursor().line;}, - "R": function(cm) {mark["R"] = cm.getCursor().line;}, - "Shift-R": function(cm) {mark["Shift-R"] = cm.getCursor().line;}, - "S": function(cm) {mark["S"] = cm.getCursor().line;}, - "Shift-S": function(cm) {mark["Shift-S"] = cm.getCursor().line;}, - "T": function(cm) {mark["T"] = cm.getCursor().line;}, - "Shift-T": function(cm) {mark["Shift-T"] = cm.getCursor().line;}, - "U": function(cm) {mark["U"] = cm.getCursor().line;}, - "Shift-U": function(cm) {mark["Shift-U"] = cm.getCursor().line;}, - "V": function(cm) {mark["V"] = cm.getCursor().line;}, - "Shift-V": function(cm) {mark["Shift-V"] = cm.getCursor().line;}, - "W": function(cm) {mark["W"] = cm.getCursor().line;}, - "Shift-W": function(cm) {mark["Shift-W"] = cm.getCursor().line;}, - "X": function(cm) {mark["X"] = cm.getCursor().line;}, - "Shift-X": function(cm) {mark["Shift-X"] = cm.getCursor().line;}, - "Y": function(cm) {mark["Y"] = cm.getCursor().line;}, - "Shift-Y": function(cm) {mark["Shift-Y"] = cm.getCursor().line;}, - "Z": function(cm) {mark["Z"] = cm.getCursor().line;}, - "Shift-Z": function(cm) {mark["Shift-Z"] = cm.getCursor().line;}, - auto: "vim", - catchall: function(cm) {/*ignore*/} - } - - CodeMirror.keyMap["vim-prefix-d"] = { - "D": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line)); cm.removeLine(cm.getCursor().line); }), - "'": function(cm) {cm.setOption("keyMap", "vim-prefix-d'"); emptyBuffer();}, - auto: "vim", - catchall: function(cm) {/*ignore*/} - }; - - CodeMirror.keyMap["vim-prefix-d'"] = { - "A": function(cm) {delTillMark(cm,"A");}, - "Shift-A": function(cm) {delTillMark(cm,"Shift-A");}, - "B": function(cm) {delTillMark(cm,"B");}, - "Shift-B": function(cm) {delTillMark(cm,"Shift-B");}, - "C": function(cm) {delTillMark(cm,"C");}, - "Shift-C": function(cm) {delTillMark(cm,"Shift-C");}, - "D": function(cm) {delTillMark(cm,"D");}, - "Shift-D": function(cm) {delTillMark(cm,"Shift-D");}, - "E": function(cm) {delTillMark(cm,"E");}, - "Shift-E": function(cm) {delTillMark(cm,"Shift-E");}, - "F": function(cm) {delTillMark(cm,"F");}, - "Shift-F": function(cm) {delTillMark(cm,"Shift-F");}, - "G": function(cm) {delTillMark(cm,"G");}, - "Shift-G": function(cm) {delTillMark(cm,"Shift-G");}, - "H": function(cm) {delTillMark(cm,"H");}, - "Shift-H": function(cm) {delTillMark(cm,"Shift-H");}, - "I": function(cm) {delTillMark(cm,"I");}, - "Shift-I": function(cm) {delTillMark(cm,"Shift-I");}, - "J": function(cm) {delTillMark(cm,"J");}, - "Shift-J": function(cm) {delTillMark(cm,"Shift-J");}, - "K": function(cm) {delTillMark(cm,"K");}, - "Shift-K": function(cm) {delTillMark(cm,"Shift-K");}, - "L": function(cm) {delTillMark(cm,"L");}, - "Shift-L": function(cm) {delTillMark(cm,"Shift-L");}, - "M": function(cm) {delTillMark(cm,"M");}, - "Shift-M": function(cm) {delTillMark(cm,"Shift-M");}, - "N": function(cm) {delTillMark(cm,"N");}, - "Shift-N": function(cm) {delTillMark(cm,"Shift-N");}, - "O": function(cm) {delTillMark(cm,"O");}, - "Shift-O": function(cm) {delTillMark(cm,"Shift-O");}, - "P": function(cm) {delTillMark(cm,"P");}, - "Shift-P": function(cm) {delTillMark(cm,"Shift-P");}, - "Q": function(cm) {delTillMark(cm,"Q");}, - "Shift-Q": function(cm) {delTillMark(cm,"Shift-Q");}, - "R": function(cm) {delTillMark(cm,"R");}, - "Shift-R": function(cm) {delTillMark(cm,"Shift-R");}, - "S": function(cm) {delTillMark(cm,"S");}, - "Shift-S": function(cm) {delTillMark(cm,"Shift-S");}, - "T": function(cm) {delTillMark(cm,"T");}, - "Shift-T": function(cm) {delTillMark(cm,"Shift-T");}, - "U": function(cm) {delTillMark(cm,"U");}, - "Shift-U": function(cm) {delTillMark(cm,"Shift-U");}, - "V": function(cm) {delTillMark(cm,"V");}, - "Shift-V": function(cm) {delTillMark(cm,"Shift-V");}, - "W": function(cm) {delTillMark(cm,"W");}, - "Shift-W": function(cm) {delTillMark(cm,"Shift-W");}, - "X": function(cm) {delTillMark(cm,"X");}, - "Shift-X": function(cm) {delTillMark(cm,"Shift-X");}, - "Y": function(cm) {delTillMark(cm,"Y");}, - "Shift-Y": function(cm) {delTillMark(cm,"Shift-Y");}, - "Z": function(cm) {delTillMark(cm,"Z");}, - "Shift-Z": function(cm) {delTillMark(cm,"Shift-Z");}, - auto: "vim", - catchall: function(cm) {/*ignore*/} - }; - - CodeMirror.keyMap["vim-prefix-y'"] = { - "A": function(cm) {yankTillMark(cm,"A");}, - "Shift-A": function(cm) {yankTillMark(cm,"Shift-A");}, - "B": function(cm) {yankTillMark(cm,"B");}, - "Shift-B": function(cm) {yankTillMark(cm,"Shift-B");}, - "C": function(cm) {yankTillMark(cm,"C");}, - "Shift-C": function(cm) {yankTillMark(cm,"Shift-C");}, - "D": function(cm) {yankTillMark(cm,"D");}, - "Shift-D": function(cm) {yankTillMark(cm,"Shift-D");}, - "E": function(cm) {yankTillMark(cm,"E");}, - "Shift-E": function(cm) {yankTillMark(cm,"Shift-E");}, - "F": function(cm) {yankTillMark(cm,"F");}, - "Shift-F": function(cm) {yankTillMark(cm,"Shift-F");}, - "G": function(cm) {yankTillMark(cm,"G");}, - "Shift-G": function(cm) {yankTillMark(cm,"Shift-G");}, - "H": function(cm) {yankTillMark(cm,"H");}, - "Shift-H": function(cm) {yankTillMark(cm,"Shift-H");}, - "I": function(cm) {yankTillMark(cm,"I");}, - "Shift-I": function(cm) {yankTillMark(cm,"Shift-I");}, - "J": function(cm) {yankTillMark(cm,"J");}, - "Shift-J": function(cm) {yankTillMark(cm,"Shift-J");}, - "K": function(cm) {yankTillMark(cm,"K");}, - "Shift-K": function(cm) {yankTillMark(cm,"Shift-K");}, - "L": function(cm) {yankTillMark(cm,"L");}, - "Shift-L": function(cm) {yankTillMark(cm,"Shift-L");}, - "M": function(cm) {yankTillMark(cm,"M");}, - "Shift-M": function(cm) {yankTillMark(cm,"Shift-M");}, - "N": function(cm) {yankTillMark(cm,"N");}, - "Shift-N": function(cm) {yankTillMark(cm,"Shift-N");}, - "O": function(cm) {yankTillMark(cm,"O");}, - "Shift-O": function(cm) {yankTillMark(cm,"Shift-O");}, - "P": function(cm) {yankTillMark(cm,"P");}, - "Shift-P": function(cm) {yankTillMark(cm,"Shift-P");}, - "Q": function(cm) {yankTillMark(cm,"Q");}, - "Shift-Q": function(cm) {yankTillMark(cm,"Shift-Q");}, - "R": function(cm) {yankTillMark(cm,"R");}, - "Shift-R": function(cm) {yankTillMark(cm,"Shift-R");}, - "S": function(cm) {yankTillMark(cm,"S");}, - "Shift-S": function(cm) {yankTillMark(cm,"Shift-S");}, - "T": function(cm) {yankTillMark(cm,"T");}, - "Shift-T": function(cm) {yankTillMark(cm,"Shift-T");}, - "U": function(cm) {yankTillMark(cm,"U");}, - "Shift-U": function(cm) {yankTillMark(cm,"Shift-U");}, - "V": function(cm) {yankTillMark(cm,"V");}, - "Shift-V": function(cm) {yankTillMark(cm,"Shift-V");}, - "W": function(cm) {yankTillMark(cm,"W");}, - "Shift-W": function(cm) {yankTillMark(cm,"Shift-W");}, - "X": function(cm) {yankTillMark(cm,"X");}, - "Shift-X": function(cm) {yankTillMark(cm,"Shift-X");}, - "Y": function(cm) {yankTillMark(cm,"Y");}, - "Shift-Y": function(cm) {yankTillMark(cm,"Shift-Y");}, - "Z": function(cm) {yankTillMark(cm,"Z");}, - "Shift-Z": function(cm) {yankTillMark(cm,"Shift-Z");}, - auto: "vim", - catchall: function(cm) {/*ignore*/} - }; - - CodeMirror.keyMap["vim-prefix-y"] = { - "Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }), - "'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();}, - auto: "vim", - catchall: function(cm) {/*ignore*/} - }; - - CodeMirror.keyMap["vim-insert"] = { - "Esc": function(cm) { - cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true); - cm.setOption("keyMap", "vim"); - editCursor("vim"); - }, - "Ctrl-N": function(cm) {/* Code to bring up autocomplete hint */}, - "Ctrl-P": function(cm) {/* Code to bring up autocomplete hint */}, - fallthrough: ["default"] - }; -})(); diff --git a/vendor/assets/javascripts/codemirror/modes/clike.js b/vendor/assets/javascripts/codemirror/modes/clike.js deleted file mode 100644 index 484d8b0cc..000000000 --- a/vendor/assets/javascripts/codemirror/modes/clike.js +++ /dev/null @@ -1,234 +0,0 @@ -CodeMirror.defineMode("clike", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "word"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}" - }; -}); - -(function() { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var cKeywords = "auto if break int case long char register continue return default short do sizeof " + - "double static else struct entry switch extern typedef float union for unsigned " + - "goto while enum void const signed volatile"; - - function cppHook(stream, state) { - if (!state.startOfLine) return false; - stream.skipToEnd(); - return "meta"; - } - - // C#-style strings where "" escapes a quote. - function tokenAtString(stream, state) { - var next; - while ((next = stream.next()) != null) { - if (next == '"' && !stream.eat('"')) { - state.tokenize = null; - break; - } - } - return "string"; - } - - CodeMirror.defineMIME("application/x-csrc", { - name: "clike", - keywords: words(cKeywords), - blockKeywords: words("case do else for if switch while struct"), - atoms: words("null"), - hooks: {"#": cppHook} - }); - CodeMirror.defineMIME("application/x-c++src", { - name: "clike", - keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + - "static_cast typeid catch operator template typename class friend private " + - "this using const_cast inline public throw virtual delete mutable protected " + - "wchar_t"), - blockKeywords: words("catch class do else finally for if struct switch try while"), - atoms: words("true false null"), - hooks: {"#": cppHook} - }); - CodeMirror.defineMIME("application/x-java", { - name: "clike", - keywords: words("abstract assert boolean break byte case catch char class const continue default " + - "do double else enum extends final finally float for goto if implements import " + - "instanceof int interface long native new package private protected public " + - "return short static strictfp super switch synchronized this throw throws transient " + - "try void volatile while"), - blockKeywords: words("catch class do else finally for if switch try while"), - atoms: words("true false null"), - hooks: { - "@": function(stream, state) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - CodeMirror.defineMIME("application/x-csharp", { - name: "clike", - keywords: words("abstract as base bool break byte case catch char checked class const continue decimal" + - " default delegate do double else enum event explicit extern finally fixed float for" + - " foreach goto if implicit in int interface internal is lock long namespace new object" + - " operator out override params private protected public readonly ref return sbyte sealed short" + - " sizeof stackalloc static string struct switch this throw try typeof uint ulong unchecked" + - " unsafe ushort using virtual void volatile while add alias ascending descending dynamic from get" + - " global group into join let orderby partial remove select set value var yield"), - blockKeywords: words("catch class do else finally for foreach if struct switch try while"), - atoms: words("true false null"), - hooks: { - "@": function(stream, state) { - if (stream.eat('"')) { - state.tokenize = tokenAtString; - return tokenAtString(stream, state); - } - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); -}()); diff --git a/vendor/assets/javascripts/codemirror/modes/clojure.js b/vendor/assets/javascripts/codemirror/modes/clojure.js deleted file mode 100644 index 2f0237bfd..000000000 --- a/vendor/assets/javascripts/codemirror/modes/clojure.js +++ /dev/null @@ -1,208 +0,0 @@ -/** - * Author: Hans Engel - * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun) - */ -CodeMirror.defineMode("clojure", function (config, mode) { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", TAG = "tag", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword"; - var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1; - - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var atoms = makeKeywords("true false nil"); - - var keywords = makeKeywords( - // Control structures - "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle" + - - // Built-ins - "* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq"); - - var indentKeys = makeKeywords( - // Built-ins - "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch" + - - // Binding forms - "let letfn binding loop for doseq dotimes when-let if-let" + - - // Data structures - "defstruct struct-map assoc" + - - // clojure.test - "testing deftest" + - - // contrib - "handler-case handle dotrace deftrace"); - - var tests = { - digit: /\d/, - digit_or_colon: /[\d:]/, - hex: /[0-9a-fA-F]/, - sign: /[+-]/, - exponent: /[eE]/, - keyword_char: /[^\s\(\[\;\)\]]/, - basic: /[\w\$_\-]/, - lang_keyword: /[\w*+!\-_?:\/]/ - }; - - function stateStack(indent, type, prev) { // represents a state stack object - this.indent = indent; - this.type = type; - this.prev = prev; - } - - function pushStack(state, indent, type) { - state.indentStack = new stateStack(indent, type, state.indentStack); - } - - function popStack(state) { - state.indentStack = state.indentStack.prev; - } - - function isNumber(ch, stream){ - // hex - if ( ch === '0' && 'x' == stream.peek().toLowerCase() ) { - stream.eat('x'); - stream.eatWhile(tests.hex); - return true; - } - - // leading sign - if ( ch == '+' || ch == '-' ) { - stream.eat(tests.sign); - ch = stream.next(); - } - - if ( tests.digit.test(ch) ) { - stream.eat(ch); - stream.eatWhile(tests.digit); - - if ( '.' == stream.peek() ) { - stream.eat('.'); - stream.eatWhile(tests.digit); - } - - if ( 'e' == stream.peek().toLowerCase() ) { - stream.eat(tests.exponent); - stream.eat(tests.sign); - stream.eatWhile(tests.digit); - } - - return true; - } - - return false; - } - - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false, - }; - }, - - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = stream.indentation(); - } - - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - - switch(state.mode){ - case "string": // multi-line string parsing mode - var next, escaped = false; - while ((next = stream.next()) != null) { - if (next == "\"" && !escaped) { - - state.mode = false; - break; - } - escaped = !escaped && next == "\\"; - } - returnType = STRING; // continue on in string mode - break; - default: // default parsing mode - var ch = stream.next(); - - if (ch == "\"") { - state.mode = "string"; - returnType = STRING; - } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { - returnType = ATOM; - } else if (ch == ";") { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else if (ch == "(" || ch == "[") { - var keyWord = ''; var indentTemp = stream.column(); - /** - Either - (indent-word .. - (non-indent-word .. - (;something else, bracket, etc. - */ - - while ((letter = stream.eat(tests.keyword_char)) != null) { - keyWord += letter; - } - - if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word - - pushStack(state, indentTemp + INDENT_WORD_SKIP, ch); - } else { // non-indent word - // we continue eating the spaces - stream.eatSpace(); - if (stream.eol() || stream.peek() == ";") { - // nothing significant after - // we restart indentation 1 space after - pushStack(state, indentTemp + 1, ch); - } else { - pushStack(state, indentTemp + stream.current().length, ch); // else we match - } - } - stream.backUp(stream.current().length - 1); // undo all the eating - - returnType = BRACKET; - } else if (ch == ")" || ch == "]") { - returnType = BRACKET; - if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) { - popStack(state); - } - } else if ( ch == ":" ) { - stream.eatWhile(tests.lang_keyword); - return TAG; - } else { - stream.eatWhile(tests.basic); - - if (keywords && keywords.propertyIsEnumerable(stream.current())) { - returnType = BUILTIN; - } else if ( atoms && atoms.propertyIsEnumerable(stream.current()) ) { - returnType = ATOM; - } else returnType = null; - } - } - - return returnType; - }, - - indent: function (state, textAfter) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - } - }; -}); - -CodeMirror.defineMIME("text/x-clojure", "clojure"); -CodeMirror.defineMIME("application/x-clojure", "clojure"); diff --git a/vendor/assets/javascripts/codemirror/modes/coffeescript.js b/vendor/assets/javascripts/codemirror/modes/coffeescript.js deleted file mode 100644 index 3a0f88160..000000000 --- a/vendor/assets/javascripts/codemirror/modes/coffeescript.js +++ /dev/null @@ -1,342 +0,0 @@ -/** - * Link to the project's GitHub page: - * https://github.com/pickhardt/coffeescript-codemirror-mode - */ -CodeMirror.defineMode('coffeescript', function(conf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]"); - var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]'); - var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))"); - var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))"); - var identifiers = new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*"); - - var wordOperators = wordRegexp(['and', 'or', 'not', - 'is', 'isnt', 'in', - 'instanceof', 'typeof']); - var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else', - 'switch', 'try', 'catch', 'finally', 'class']; - var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete', - 'do', 'in', 'of', 'new', 'return', 'then', - 'this', 'throw', 'when', 'until']; - - var keywords = wordRegexp(indentKeywords.concat(commonKeywords)); - - indentKeywords = wordRegexp(indentKeywords); - - - var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])"); - var regexPrefixes = new RegExp("^(/{3}|/)"); - var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no']; - var constants = wordRegexp(commonConstants); - - // Tokenizers - function tokenBase(stream, state) { - // Handle scope changes - if (stream.sol()) { - var scopeOffset = state.scopes[0].offset; - if (stream.eatSpace()) { - var lineOffset = stream.indentation(); - if (lineOffset > scopeOffset) { - return 'indent'; - } else if (lineOffset < scopeOffset) { - return 'dedent'; - } - return null; - } else { - if (scopeOffset > 0) { - dedent(stream, state); - } - } - } - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle multi line comments - if (stream.match("###")) { - state.tokenize = longComment; - return state.tokenize(stream, state); - } - - // Single line comment - if (ch === '#') { - stream.skipToEnd(); - return 'comment'; - } - - // Handle number literals - if (stream.match(/^-?[0-9\.]/, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) { - floatLiteral = true; - } - if (stream.match(/^-?\d+\.\d*/)) { - floatLiteral = true; - } - if (stream.match(/^-?\.\d+/)) { - floatLiteral = true; - } - - if (floatLiteral) { - // prevent from getting extra . on 1.. - if (stream.peek() == "."){ - stream.backUp(1); - } - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^-?0x[0-9a-f]+/i)) { - intLiteral = true; - } - // Decimal - if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) { - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^-?0(?![\dx])/i)) { - intLiteral = true; - } - if (intLiteral) { - return 'number'; - } - } - - // Handle strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenFactory(stream.current(), 'string'); - return state.tokenize(stream, state); - } - // Handle regex literals - if (stream.match(regexPrefixes)) { - if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division - state.tokenize = tokenFactory(stream.current(), 'string-2'); - return state.tokenize(stream, state); - } else { - stream.backUp(1); - } - } - - // Handle operators and delimiters - if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) { - return 'punctuation'; - } - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) { - return 'operator'; - } - if (stream.match(singleDelimiters)) { - return 'punctuation'; - } - - if (stream.match(constants)) { - return 'atom'; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(identifiers)) { - return 'variable'; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenFactory(delimiter, outclass) { - var singleline = delimiter.length == 1; - return function tokenString(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\/\\]/); - if (stream.eat('\\')) { - stream.next(); - if (singleline && stream.eol()) { - return outclass; - } - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return outclass; - } else { - stream.eat(/['"\/]/); - } - } - if (singleline) { - if (conf.mode.singleLineStringErrors) { - outclass = ERRORCLASS - } else { - state.tokenize = tokenBase; - } - } - return outclass; - }; - } - - function longComment(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^#]/); - if (stream.match("###")) { - state.tokenize = tokenBase; - break; - } - stream.eatWhile("#"); - } - return "comment" - } - - function indent(stream, state, type) { - type = type || 'coffee'; - var indentUnit = 0; - if (type === 'coffee') { - for (var i = 0; i < state.scopes.length; i++) { - if (state.scopes[i].type === 'coffee') { - indentUnit = state.scopes[i].offset + conf.indentUnit; - break; - } - } - } else { - indentUnit = stream.column() + stream.current().length; - } - state.scopes.unshift({ - offset: indentUnit, - type: type - }); - } - - function dedent(stream, state) { - if (state.scopes.length == 1) return; - if (state.scopes[0].type === 'coffee') { - var _indent = stream.indentation(); - var _indent_index = -1; - for (var i = 0; i < state.scopes.length; ++i) { - if (_indent === state.scopes[i].offset) { - _indent_index = i; - break; - } - } - if (_indent_index === -1) { - return true; - } - while (state.scopes[0].offset !== _indent) { - state.scopes.shift(); - } - return false - } else { - state.scopes.shift(); - return false; - } - } - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = state.tokenize(stream, state); - current = stream.current(); - if (style === 'variable') { - return 'variable'; - } else { - return ERRORCLASS; - } - } - - // Handle properties - if (current === '@') { - stream.eat('@'); - return 'keyword'; - } - - // Handle scope changes. - if (current === 'return') { - state.dedent += 1; - } - if (((current === '->' || current === '=>') && - !state.lambda && - state.scopes[0].type == 'coffee' && - stream.peek() === '') - || style === 'indent') { - indent(stream, state); - } - var delimiter_index = '[({'.indexOf(current); - if (delimiter_index !== -1) { - indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1)); - } - if (indentKeywords.exec(current)){ - indent(stream, state); - } - if (current == 'then'){ - dedent(stream, state); - } - - - if (style === 'dedent') { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - delimiter_index = '])}'.indexOf(current); - if (delimiter_index !== -1) { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') { - if (state.scopes.length > 1) state.scopes.shift(); - state.dedent -= 1; - } - - return style; - } - - var external = { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - scopes: [{offset:basecolumn || 0, type:'coffee'}], - lastToken: null, - lambda: false, - dedent: 0 - }; - }, - - token: function(stream, state) { - var style = tokenLexer(stream, state); - - state.lastToken = {style:style, content: stream.current()}; - - if (stream.eol() && stream.lambda) { - state.lambda = false; - } - - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) { - return 0; - } - - return state.scopes[0].offset; - } - - }; - return external; -}); - -CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript'); -CodeMirror.defineMIME('application/x-coffeescript', 'coffeescript'); diff --git a/vendor/assets/javascripts/codemirror/modes/css.js b/vendor/assets/javascripts/codemirror/modes/css.js deleted file mode 100644 index 0aa40c4fd..000000000 --- a/vendor/assets/javascripts/codemirror/modes/css.js +++ /dev/null @@ -1,125 +0,0 @@ -CodeMirror.defineMode("css", function(config) { - var indentUnit = config.indentUnit, type; - function ret(style, tp) {type = tp; return style;} - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());} - else if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - else if (ch == "<" && stream.eat("!")) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } - else if (ch == "=") ret(null, "compare"); - else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - else if (ch == "#") { - stream.eatWhile(/[\w\\\-]/); - return ret("atom", "hash"); - } - else if (ch == "!") { - stream.match(/^\s*\w*/); - return ret("keyword", "important"); - } - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } - else if (/[,.+>*\/]/.test(ch)) { - return ret(null, "select-op"); - } - else if (/[;{}:\[\]]/.test(ch)) { - return ret(null, ch); - } - else { - stream.eatWhile(/[\w\\\-]/); - return ret("variable", "variable"); - } - } - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - var context = state.stack[state.stack.length-1]; - if (type == "hash" && context == "rule") style = "atom"; - else if (style == "variable") { - if (context == "rule") style = "number"; - else if (!context || context == "@media{") style = "tag"; - } - - if (context == "rule" && /^[\{\};]$/.test(type)) - state.stack.pop(); - if (type == "{") { - if (context == "@media") state.stack[state.stack.length-1] = "@media{"; - else state.stack.push("{"); - } - else if (type == "}") state.stack.pop(); - else if (type == "@media") state.stack.push("@media"); - else if (context == "{" && type != "comment") state.stack.push("rule"); - return style; - }, - - indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; - return state.baseIndent + n * indentUnit; - }, - - electricChars: "}" - }; -}); - -CodeMirror.defineMIME("text/css", "css"); -CodeMirror.defineMIME('application/x-coffeescript', 'css'); \ No newline at end of file diff --git a/vendor/assets/javascripts/codemirror/modes/diff.js b/vendor/assets/javascripts/codemirror/modes/diff.js deleted file mode 100644 index b5da18ccc..000000000 --- a/vendor/assets/javascripts/codemirror/modes/diff.js +++ /dev/null @@ -1,14 +0,0 @@ -CodeMirror.defineMode("diff", function() { - return { - token: function(stream) { - var ch = stream.next(); - stream.skipToEnd(); - if (ch == "+") return "plus"; - if (ch == "-") return "minus"; - if (ch == "@") return "rangeinfo"; - } - }; -}); - -CodeMirror.defineMIME("text/x-diff", "diff"); -CodeMirror.defineMIME("application/x-diff", "diff"); diff --git a/vendor/assets/javascripts/codemirror/modes/gfm.js b/vendor/assets/javascripts/codemirror/modes/gfm.js deleted file mode 100644 index 1e9d7d872..000000000 --- a/vendor/assets/javascripts/codemirror/modes/gfm.js +++ /dev/null @@ -1,108 +0,0 @@ -CodeMirror.defineMode("gfm", function(config, parserConfig) { - var mdMode = CodeMirror.getMode(config, "markdown"); - var aliases = { - html: "htmlmixed", - js: "javascript", - json: "application/json", - c: "text/x-csrc", - "c++": "text/x-c++src", - java: "text/x-java", - csharp: "text/x-csharp", - "c#": "text/x-csharp", - }; - - // make this lazy so that we don't need to load GFM last - var getMode = (function () { - var i, modes = {}, mimes = {}, mime; - - var list = CodeMirror.listModes(); - for (i = 0; i < list.length; i++) { - modes[list[i]] = list[i]; - } - var mimesList = CodeMirror.listMIMEs(); - for (i = 0; i < mimesList.length; i++) { - mime = mimesList[i].mime; - mimes[mime] = mimesList[i].mime; - } - - for (var a in aliases) { - if (aliases[a] in modes || aliases[a] in mimes) - modes[a] = aliases[a]; - } - - return function (lang) { - return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null; - } - }()); - - function markdown(stream, state) { - // intercept fenced code blocks - if (stream.sol() && stream.match(/^```([\w+#]*)/)) { - // try switching mode - state.localMode = getMode(RegExp.$1) - if (state.localMode) - state.localState = state.localMode.startState(); - - state.token = local; - return 'code'; - } - - return mdMode.token(stream, state.mdState); - } - - function local(stream, state) { - if (stream.sol() && stream.match(/^```/)) { - state.localMode = state.localState = null; - state.token = markdown; - return 'code'; - } - else if (state.localMode) { - return state.localMode.token(stream, state.localState); - } else { - stream.skipToEnd(); - return 'code'; - } - } - - // custom handleText to prevent emphasis in the middle of a word - // and add autolinking - function handleText(stream, mdState) { - var match; - if (stream.match(/^\w+:\/\/\S+/)) { - return 'linkhref'; - } - if (stream.match(/^[^\[*\\<>` _][^\[*\\<>` ]*[^\[*\\<>` _]/)) { - return mdMode.getType(mdState); - } - if (match = stream.match(/^[^\[*\\<>` ]+/)) { - var word = match[0]; - if (word[0] === '_' && word[word.length-1] === '_') { - stream.backUp(word.length); - return undefined; - } - return mdMode.getType(mdState); - } - if (stream.eatSpace()) { - return null; - } - } - - return { - startState: function() { - var mdState = mdMode.startState(); - mdState.text = handleText; - return {token: markdown, mode: "markdown", mdState: mdState, - localMode: null, localState: null}; - }, - - copyState: function(state) { - return {token: state.token, mode: state.mode, mdState: CodeMirror.copyState(mdMode, state.mdState), - localMode: state.localMode, - localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null}; - }, - - token: function(stream, state) { - return state.token(stream, state); - } - } -}); diff --git a/vendor/assets/javascripts/codemirror/modes/go.js b/vendor/assets/javascripts/codemirror/modes/go.js deleted file mode 100644 index 57f7a575c..000000000 --- a/vendor/assets/javascripts/codemirror/modes/go.js +++ /dev/null @@ -1,173 +0,0 @@ -CodeMirror.defineMode("go", function(config, parserConfig) { - var indentUnit = config.indentUnit; - - var keywords = { - "break":true, "case":true, "chan":true, "const":true, "continue":true, - "default":true, "defer":true, "else":true, "fallthrough":true, "for":true, - "func":true, "go":true, "goto":true, "if":true, "import":true, "interface":true, - "map":true, "package":true, "range":true, "return":true, "select":true, - "struct":true, "switch":true, "type":true, "var":true, "bool":true, "byte":true, - "complex64":true, "complex128":true, "float32":true, "float64":true, - "int8":true, "int16":true, "int32":true, "int64":true, "string":true, - "uint8":true, "uint16":true, "uint32":true, "uint64":true, "int":true, - "uint":true, "uintptr":true - }; - - var atoms = { - "true":true, "false":true, "iota":true, "nil":true, "append":true, - "cap":true, "close":true, "complex":true, "copy":true, "imag":true, "len":true, - "make":true, "new":true, "panic":true, "print":true, "println":true, - "real":true, "recover":true - }; - - var blockKeywords = { - "else":true, "for":true, "func":true, "if":true, "interface":true, - "select":true, "struct":true, "switch":true - }; - - var isOperatorChar = /[+\-*&^%:=<>!|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'" || ch == "`") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\d\.]/.test(ch)) { - if (ch == ".") { - stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); - } else if (ch == "0") { - stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); - } else { - stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); - } - return "number"; - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "word"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || quote == "`")) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented; - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-go", "go"); -CodeMirror.defineMIME("application/x-go", "go"); diff --git a/vendor/assets/javascripts/codemirror/modes/groovy.js b/vendor/assets/javascripts/codemirror/modes/groovy.js deleted file mode 100644 index 06a2f54a5..000000000 --- a/vendor/assets/javascripts/codemirror/modes/groovy.js +++ /dev/null @@ -1,211 +0,0 @@ -CodeMirror.defineMode("groovy", function(config, parserConfig) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = words( - "abstract as assert boolean break byte case catch char class const continue def default " + - "do double else enum extends final finally float for goto if implements import in " + - "instanceof int interface long native new package private protected public return " + - "short static strictfp super switch synchronized threadsafe throw throws transient " + - "try void volatile while"); - var blockKeywords = words("catch class do else finally for if switch try while enum interface def"); - var atoms = words("null true false this"); - - var curPunc; - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - return startString(ch, stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); } - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize.push(tokenComment); - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - if (expectExpression(state.lastToken)) { - return startString(ch, stream, state); - } - } - if (ch == "-" && stream.eat(">")) { - curPunc = "->"; - return null; - } - if (/[+\-*&%=<>!?|\/~]/.test(ch)) { - stream.eatWhile(/[+\-*&%=<>|~]/); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; } - if (state.lastToken == ".") return "property"; - if (stream.eat(":")) { curPunc = "proplabel"; return "property"; } - var cur = stream.current(); - if (atoms.propertyIsEnumerable(cur)) { return "atom"; } - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - return "word"; - } - tokenBase.isBase = true; - - function startString(quote, stream, state) { - var tripleQuoted = false; - if (quote != "/" && stream.eat(quote)) { - if (stream.eat(quote)) tripleQuoted = true; - else return "string"; - } - function t(stream, state) { - var escaped = false, next, end = !tripleQuoted; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - if (!tripleQuoted) { break; } - if (stream.match(quote + quote)) { end = true; break; } - } - if (quote == '"' && next == "$" && !escaped && stream.eat("{")) { - state.tokenize.push(tokenBaseUntilBrace()); - return "string"; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize.pop(); - return "string"; - } - state.tokenize.push(t); - return t(stream, state); - } - - function tokenBaseUntilBrace() { - var depth = 1; - function t(stream, state) { - if (stream.peek() == "}") { - depth--; - if (depth == 0) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } - } else if (stream.peek() == "{") { - depth++; - } - return tokenBase(stream, state); - } - t.isBase = true; - return t; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize.pop(); - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function expectExpression(last) { - return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) || - last == "newstatement" || last == "keyword" || last == "proplabel"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: [tokenBase], - context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false), - indented: 0, - startOfLine: true, - lastToken: null - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - // Automatic semicolon insertion - if (ctx.type == "statement" && !expectExpression(state.lastToken)) { - popContext(state); ctx = state.context; - } - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = state.tokenize[state.tokenize.length-1](stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - // Handle indentation for {x -> \n ... } - else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") { - popContext(state); - state.context.align = false; - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - state.lastToken = curPunc || style; - return style; - }, - - indent: function(state, textAfter) { - if (!state.tokenize[state.tokenize.length-1].isBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.context; - if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : config.indentUnit); - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-groovy", "groovy"); -CodeMirror.defineMIME("application/x-groovy", "groovy"); diff --git a/vendor/assets/javascripts/codemirror/modes/haskell.js b/vendor/assets/javascripts/codemirror/modes/haskell.js deleted file mode 100644 index 552d30b13..000000000 --- a/vendor/assets/javascripts/codemirror/modes/haskell.js +++ /dev/null @@ -1,243 +0,0 @@ -CodeMirror.defineMode("haskell", function(cmCfg, modeCfg) { - - function switchState(source, setState, f) { - setState(f); - return f(source, setState); - } - - // These should all be Unicode extended, as per the Haskell 2010 report - var smallRE = /[a-z_]/; - var largeRE = /[A-Z]/; - var digitRE = /[0-9]/; - var hexitRE = /[0-9A-Fa-f]/; - var octitRE = /[0-7]/; - var idRE = /[a-z_A-Z0-9']/; - var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/; - var specialRE = /[(),;[\]`{}]/; - var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer - - function normal(source, setState) { - if (source.eatWhile(whiteCharRE)) { - return null; - } - - var ch = source.next(); - if (specialRE.test(ch)) { - if (ch == '{' && source.eat('-')) { - var t = "comment"; - if (source.eat('#')) { - t = "meta"; - } - return switchState(source, setState, ncomment(t, 1)); - } - return null; - } - - if (ch == '\'') { - if (source.eat('\\')) { - source.next(); // should handle other escapes here - } - else { - source.next(); - } - if (source.eat('\'')) { - return "string"; - } - return "error"; - } - - if (ch == '"') { - return switchState(source, setState, stringLiteral); - } - - if (largeRE.test(ch)) { - source.eatWhile(idRE); - if (source.eat('.')) { - return "qualifier"; - } - return "variable-2"; - } - - if (smallRE.test(ch)) { - source.eatWhile(idRE); - return "variable"; - } - - if (digitRE.test(ch)) { - if (ch == '0') { - if (source.eat(/[xX]/)) { - source.eatWhile(hexitRE); // should require at least 1 - return "integer"; - } - if (source.eat(/[oO]/)) { - source.eatWhile(octitRE); // should require at least 1 - return "number"; - } - } - source.eatWhile(digitRE); - var t = "number"; - if (source.eat('.')) { - t = "number"; - source.eatWhile(digitRE); // should require at least 1 - } - if (source.eat(/[eE]/)) { - t = "number"; - source.eat(/[-+]/); - source.eatWhile(digitRE); // should require at least 1 - } - return t; - } - - if (symbolRE.test(ch)) { - if (ch == '-' && source.eat(/-/)) { - source.eatWhile(/-/); - if (!source.eat(symbolRE)) { - source.skipToEnd(); - return "comment"; - } - } - var t = "variable"; - if (ch == ':') { - t = "variable-2"; - } - source.eatWhile(symbolRE); - return t; - } - - return "error"; - } - - function ncomment(type, nest) { - if (nest == 0) { - return normal; - } - return function(source, setState) { - var currNest = nest; - while (!source.eol()) { - var ch = source.next(); - if (ch == '{' && source.eat('-')) { - ++currNest; - } - else if (ch == '-' && source.eat('}')) { - --currNest; - if (currNest == 0) { - setState(normal); - return type; - } - } - } - setState(ncomment(type, currNest)); - return type; - } - } - - function stringLiteral(source, setState) { - while (!source.eol()) { - var ch = source.next(); - if (ch == '"') { - setState(normal); - return "string"; - } - if (ch == '\\') { - if (source.eol() || source.eat(whiteCharRE)) { - setState(stringGap); - return "string"; - } - if (source.eat('&')) { - } - else { - source.next(); // should handle other escapes here - } - } - } - setState(normal); - return "error"; - } - - function stringGap(source, setState) { - if (source.eat('\\')) { - return switchState(source, setState, stringLiteral); - } - source.next(); - setState(normal); - return "error"; - } - - - var wellKnownWords = (function() { - var wkw = {}; - function setType(t) { - return function () { - for (var i = 0; i < arguments.length; i++) - wkw[arguments[i]] = t; - } - } - - setType("keyword")( - "case", "class", "data", "default", "deriving", "do", "else", "foreign", - "if", "import", "in", "infix", "infixl", "infixr", "instance", "let", - "module", "newtype", "of", "then", "type", "where", "_"); - - setType("keyword")( - "\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>"); - - setType("builtin")( - "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<", - "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**"); - - setType("builtin")( - "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq", - "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT", - "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left", - "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read", - "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS", - "String", "True"); - - setType("builtin")( - "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf", - "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling", - "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", - "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", - "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", - "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", - "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap", - "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", - "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents", - "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized", - "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", - "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map", - "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound", - "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or", - "otherwise", "pi", "pred", "print", "product", "properFraction", - "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", - "readIO", "readList", "readLn", "readParen", "reads", "readsPrec", - "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse", - "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", - "sequence", "sequence_", "show", "showChar", "showList", "showParen", - "showString", "shows", "showsPrec", "significand", "signum", "sin", - "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum", - "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger", - "toRational", "truncate", "uncurry", "undefined", "unlines", "until", - "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip", - "zip3", "zipWith", "zipWith3"); - - return wkw; - })(); - - - - return { - startState: function () { return { f: normal }; }, - copyState: function (s) { return { f: s.f }; }, - - token: function(stream, state) { - var t = state.f(stream, function(s) { state.f = s; }); - var w = stream.current(); - return (w in wellKnownWords) ? wellKnownWords[w] : t; - } - }; - -}); - -CodeMirror.defineMIME("text/x-haskell", "haskell"); -CodeMirror.defineMIME("application/x-haskell", "haskell"); diff --git a/vendor/assets/javascripts/codemirror/modes/htmlembedded.js b/vendor/assets/javascripts/codemirror/modes/htmlembedded.js deleted file mode 100644 index 08e170ea9..000000000 --- a/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +++ /dev/null @@ -1,68 +0,0 @@ -CodeMirror.defineMode("htmlembedded", function(config, parserConfig) { - - //config settings - var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i, - scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i; - - //inner modes - var scriptingMode, htmlMixedMode; - - //tokenizer when in html mode - function htmlDispatch(stream, state) { - if (stream.match(scriptStartRegex, false)) { - state.token=scriptingDispatch; - return scriptingMode.token(stream, state.scriptState); - } - else - return htmlMixedMode.token(stream, state.htmlState); - } - - //tokenizer when in scripting mode - function scriptingDispatch(stream, state) { - if (stream.match(scriptEndRegex, false)) { - state.token=htmlDispatch; - return htmlMixedMode.token(stream, state.htmlState); - } - else - return scriptingMode.token(stream, state.scriptState); - } - - - return { - startState: function() { - scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec); - htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed"); - return { - token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch, - htmlState : htmlMixedMode.startState(), - scriptState : scriptingMode.startState() - } - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (state.token == htmlDispatch) - return htmlMixedMode.indent(state.htmlState, textAfter); - else - return scriptingMode.indent(state.scriptState, textAfter); - }, - - copyState: function(state) { - return { - token : state.token, - htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState), - scriptState : CodeMirror.copyState(scriptingMode, state.scriptState) - } - }, - - - electricChars: "/{}:" - } -}); - -CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"}); -CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"}); -CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"}); diff --git a/vendor/assets/javascripts/codemirror/modes/htmlmixed.js b/vendor/assets/javascripts/codemirror/modes/htmlmixed.js deleted file mode 100644 index c4e58a646..000000000 --- a/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +++ /dev/null @@ -1,84 +0,0 @@ -CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true}); - var jsMode = CodeMirror.getMode(config, "javascript"); - var cssMode = CodeMirror.getMode(config, "css"); - - function html(stream, state) { - var style = htmlMode.token(stream, state.htmlState); - if (style == "tag" && stream.current() == ">" && state.htmlState.context) { - if (/^script$/i.test(state.htmlState.context.tagName)) { - state.token = javascript; - state.localState = jsMode.startState(htmlMode.indent(state.htmlState, "")); - state.mode = "javascript"; - } - else if (/^style$/i.test(state.htmlState.context.tagName)) { - state.token = css; - state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); - state.mode = "css"; - } - } - return style; - } - function maybeBackup(stream, pat, style) { - var cur = stream.current(); - var close = cur.search(pat); - if (close > -1) stream.backUp(cur.length - close); - return style; - } - function javascript(stream, state) { - if (stream.match(/^<\/\s*script\s*>/i, false)) { - state.token = html; - state.curState = null; - state.mode = "html"; - return html(stream, state); - } - return maybeBackup(stream, /<\/\s*script\s*>/, - jsMode.token(stream, state.localState)); - } - function css(stream, state) { - if (stream.match(/^<\/\s*style\s*>/i, false)) { - state.token = html; - state.localState = null; - state.mode = "html"; - return html(stream, state); - } - return maybeBackup(stream, /<\/\s*style\s*>/, - cssMode.token(stream, state.localState)); - } - - return { - startState: function() { - var state = htmlMode.startState(); - return {token: html, localState: null, mode: "html", htmlState: state}; - }, - - copyState: function(state) { - if (state.localState) - var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState); - return {token: state.token, localState: local, mode: state.mode, - htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (state.token == html || /^\s*<\//.test(textAfter)) - return htmlMode.indent(state.htmlState, textAfter); - else if (state.token == javascript) - return jsMode.indent(state.localState, textAfter); - else - return cssMode.indent(state.localState, textAfter); - }, - - compareStates: function(a, b) { - return htmlMode.compareStates(a.htmlState, b.htmlState); - }, - - electricChars: "/{}:" - } -}); - -CodeMirror.defineMIME("text/html", "htmlmixed"); -CodeMirror.defineMIME("application/html", "htmlmixed"); diff --git a/vendor/assets/javascripts/codemirror/modes/javascript.js b/vendor/assets/javascripts/codemirror/modes/javascript.js deleted file mode 100644 index 401b04f8d..000000000 --- a/vendor/assets/javascripts/codemirror/modes/javascript.js +++ /dev/null @@ -1,361 +0,0 @@ -CodeMirror.defineMode("javascript", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var jsonMode = parserConfig.json; - - // Tokenizer - - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}; - return { - "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), - "function": kw("function"), "catch": kw("catch"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "typeof": operator, "instanceof": operator, - "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom - }; - }(); - - var isOperatorChar = /[+\-*&%=<>!?|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; - escaped = !escaped && next == "\\"; - } - return escaped; - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - - function jsTokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") - return chain(stream, state, jsTokenString(ch)); - else if (/[\[\]{}\(\),;\:\.]/.test(ch)) - return ret(ch); - else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } - else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } - else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, jsTokenComment); - } - else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } - else if (state.reAllowed) { - nextUntilUnescaped(stream, "/"); - stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla - return ret("regexp", "string-2"); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - } - else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - else { - stream.eatWhile(/[\w\$_]/); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.kwAllowed) ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - - function jsTokenString(quote) { - return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = jsTokenBase; - return ret("string", "string"); - }; - } - - function jsTokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function register(varname) { - var state = cx.state; - if (state.context) { - cx.marked = "def"; - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return; - state.localVars = {name: varname, next: state.localVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: {name: "arguments"}}; - function pushcontext() { - if (!cx.state.context) cx.state.localVars = defaultVars; - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - function pushlex(type, info) { - var result = function() { - var state = cx.state; - state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info) - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - return function expecting(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(arguments.callee); - }; - } - - function statement(type) { - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), block, poplex); - if (type == ";") return cont(); - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), - poplex, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); - if (type == "function") return cont(functiondef); - if (type == "keyword c") return cont(maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator); - if (type == "operator") return cont(expression); - if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - - function maybeoperator(type, value) { - if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator); - if (type == "operator") return cont(expression); - if (type == ";") return; - if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); - if (type == ".") return cont(property, maybeoperator); - if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); - } - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperator, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type) { - if (type == "variable") cx.marked = "property"; - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); - } - function commasep(what, end) { - function proceed(type) { - if (type == ",") return cont(what, proceed); - if (type == end) return cont(); - return cont(expect(end)); - } - return function commaSeparated(type) { - if (type == end) return cont(); - else return pass(what, proceed); - }; - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function vardef1(type, value) { - if (type == "variable"){register(value); return cont(vardef2);} - return cont(); - } - function vardef2(type, value) { - if (value == "=") return cont(expression, vardef2); - if (type == ",") return cont(vardef1); - } - function forspec1(type) { - if (type == "var") return cont(vardef1, forspec2); - if (type == ";") return pass(forspec2); - if (type == "variable") return cont(formaybein); - return pass(forspec2); - } - function formaybein(type, value) { - if (value == "in") return cont(expression); - return cont(maybeoperator, forspec2); - } - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in") return cont(expression); - return cont(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); - } - function functiondef(type, value) { - if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); - } - function funarg(type, value) { - if (type == "variable") {register(value); return cont();} - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: jsTokenBase, - reAllowed: true, - kwAllowed: true, - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: null, - context: null, - indented: 0 - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/); - state.kwAllowed = type != '.'; - return parseJS(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize != jsTokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, - type = lexical.type, closing = firstChar == type; - if (type == "vardef") return lexical.indented + 4; - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "stat" || type == "form") return lexical.indented + indentUnit; - else if (lexical.info == "switch" && !closing) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricChars: ":{}" - }; -}); - -CodeMirror.defineMIME("text/javascript", "javascript"); -CodeMirror.defineMIME("application/javascript", "javascript"); -CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); diff --git a/vendor/assets/javascripts/codemirror/modes/jinja2.js b/vendor/assets/javascripts/codemirror/modes/jinja2.js deleted file mode 100644 index 75419d846..000000000 --- a/vendor/assets/javascripts/codemirror/modes/jinja2.js +++ /dev/null @@ -1,42 +0,0 @@ -CodeMirror.defineMode("jinja2", function(config, parserConf) { - var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false", - "loop", "none", "self", "super", "if", "as", "not", "and", - "else", "import", "with", "without", "context"]; - keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - var ch = stream.next(); - if (ch == "{") { - if (ch = stream.eat(/\{|%|#/)) { - stream.eat("-"); - state.tokenize = inTag(ch); - return "tag"; - } - } - } - function inTag (close) { - if (close == "{") { - close = "}"; - } - return function (stream, state) { - var ch = stream.next(); - if ((ch == close || (ch == "-" && stream.eat(close))) - && stream.eat("}")) { - state.tokenize = tokenBase; - return "tag"; - } - if (stream.match(keywords)) { - return "keyword"; - } - return close == "#" ? "comment" : "string"; - }; - } - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } - }; -}); diff --git a/vendor/assets/javascripts/codemirror/modes/less.js b/vendor/assets/javascripts/codemirror/modes/less.js deleted file mode 100644 index 29a0a1f13..000000000 --- a/vendor/assets/javascripts/codemirror/modes/less.js +++ /dev/null @@ -1,186 +0,0 @@ -CodeMirror.defineMode("less", function(config) { - var indentUnit = config.indentUnit, type; - function ret(style, tp) {type = tp; return style;} - //html5 tags - var tags = ["a","abbr","acronym","address","applet","area","article","aside","audio","b","base","basefont","bdi","bdo","big","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","command","datalist","dd","del","details","dfn","dir","div","dl","dt","em","embed","fieldset","figcaption","figure","font","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","keygen","kbd","label","legend","li","link","map","mark","menu","meta","meter","nav","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strike","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","tt","u","ul","var","video","wbr"]; - - function inTagsArray(val){ - for(var i=0; i*\/]/.test(ch)) {//removed . dot character original was [,.+>*\/] - return ret(null, "select-op"); - } - else if (/[;{}:\[\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\[\]] - if(ch == ":"){ - stream.eatWhile(/[active|hover|link|visited]/); - if( stream.current().match(/[active|hover|link|visited]/)){ - return ret("tag", "tag"); - }else{ - return ret(null, ch); - } - }else{ - return ret(null, ch); - } - } - else if (ch == ".") { // lesscss - stream.eatWhile(/[\a-zA-Z0-9\-_]/); - return ret("tag", "tag"); - } - else if (ch == "#") { // lesscss - stream.match(/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/); - if(stream.current().length >1){ - if(stream.current().match(/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/) != null){ - return ret("number", "unit"); - }else{ - stream.eatWhile(/[\w\-]/); - return ret("atom", "tag"); - } - }else{ - stream.eatWhile(/[\w\-]/); - return ret("atom", "tag"); - } - } - else if (ch == "&") { - stream.eatWhile(/[\w\-]/); - return ret(null, ch); - } - else { - stream.eatWhile(/[\w\\\-_.%{]/); - if( stream.eat("(") ){ // lesscss - return ret(null, ch); - }else if( stream.current().match(/\-\d|\-.\d/) ){ // lesscss match e.g.: -5px -0.4 etc... - return ret("number", "unit"); - }else if( inTagsArray(stream.current()) ){ // lesscss match html tags - return ret("tag", "tag"); - }else{ - return ret("variable", "variable"); - } - } - - } - - function tokenSComment(stream, state) {// SComment = Slash comment - stream.skipToEnd(); - state.tokenize = tokenBase; - return ret("comment", "comment"); - } - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - var context = state.stack[state.stack.length-1]; - if (type == "hash" && context == "rule") style = "atom"; - else if (style == "variable") { - if (context == "rule") style = null; //"tag" - else if (!context || context == "@media{") style = "tag"; - } - - if (context == "rule" && /^[\{\};]$/.test(type)) - state.stack.pop(); - if (type == "{") { - if (context == "@media") state.stack[state.stack.length-1] = "@media{"; - else state.stack.push("{"); - } - else if (type == "}") state.stack.pop(); - else if (type == "@media") state.stack.push("@media"); - else if (context == "{" && type != "comment") state.stack.push("rule"); - return style; - }, - - indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; - return state.baseIndent + n * indentUnit; - }, - - electricChars: "}" - }; -}); - -CodeMirror.defineMIME("text/less", "less"); diff --git a/vendor/assets/javascripts/codemirror/modes/lua.js b/vendor/assets/javascripts/codemirror/modes/lua.js deleted file mode 100644 index 0e221aa1b..000000000 --- a/vendor/assets/javascripts/codemirror/modes/lua.js +++ /dev/null @@ -1,141 +0,0 @@ -// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's -// CodeMirror 1 mode. -// highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting - -CodeMirror.defineMode("lua", function(config, parserConfig) { - var indentUnit = config.indentUnit; - - function prefixRE(words) { - return new RegExp("^(?:" + words.join("|") + ")", "i"); - } - function wordRE(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var specials = wordRE(parserConfig.specials || []); - - // long list of standard functions from lua manual - var builtins = wordRE([ - "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load", - "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require", - "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall", - - "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield", - - "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable", - "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable", - "debug.setupvalue","debug.traceback", - - "close","flush","lines","read","seek","setvbuf","write", - - "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin", - "io.stdout","io.tmpfile","io.type","io.write", - - "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg", - "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max", - "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh", - "math.sqrt","math.tan","math.tanh", - - "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale", - "os.time","os.tmpname", - - "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload", - "package.seeall", - - "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub", - "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper", - - "table.concat","table.insert","table.maxn","table.remove","table.sort" - ]); - var keywords = wordRE(["and","break","elseif","false","nil","not","or","return", - "true","function", "end", "if", "then", "else", "do", - "while", "repeat", "until", "for", "in", "local" ]); - - var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]); - var dedentTokens = wordRE(["end", "until", "\\)", "}"]); - var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]); - - function readBracket(stream) { - var level = 0; - while (stream.eat("=")) ++level; - stream.eat("["); - return level; - } - - function normal(stream, state) { - var ch = stream.next(); - if (ch == "-" && stream.eat("-")) { - if (stream.eat("[")) - return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state); - stream.skipToEnd(); - return "comment"; - } - if (ch == "\"" || ch == "'") - return (state.cur = string(ch))(stream, state); - if (ch == "[" && /[\[=]/.test(stream.peek())) - return (state.cur = bracketed(readBracket(stream), "string"))(stream, state); - if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return "number"; - } - if (/[\w_]/.test(ch)) { - stream.eatWhile(/[\w\\\-_.]/); - return "variable"; - } - return null; - } - - function bracketed(level, style) { - return function(stream, state) { - var curlev = null, ch; - while ((ch = stream.next()) != null) { - if (curlev == null) {if (ch == "]") curlev = 0;} - else if (ch == "=") ++curlev; - else if (ch == "]" && curlev == level) { state.cur = normal; break; } - else curlev = null; - } - return style; - }; - } - - function string(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.cur = normal; - return "string"; - }; - } - - return { - startState: function(basecol) { - return {basecol: basecol || 0, indentDepth: 0, cur: normal}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.cur(stream, state); - var word = stream.current(); - if (style == "variable") { - if (keywords.test(word)) style = "keyword"; - else if (builtins.test(word)) style = "builtin"; - else if (specials.test(word)) style = "variable-2"; - } - if ((style != "comment") && (style != "string")){ - if (indentTokens.test(word)) ++state.indentDepth; - else if (dedentTokens.test(word)) --state.indentDepth; - } - return style; - }, - - indent: function(state, textAfter) { - var closing = dedentPartial.test(textAfter); - return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0)); - } - }; -}); - -CodeMirror.defineMIME("text/x-lua", "lua"); -CodeMirror.defineMIME("application/x-lua", "lua"); diff --git a/vendor/assets/javascripts/codemirror/modes/markdown.js b/vendor/assets/javascripts/codemirror/modes/markdown.js deleted file mode 100644 index 34227f592..000000000 --- a/vendor/assets/javascripts/codemirror/modes/markdown.js +++ /dev/null @@ -1,243 +0,0 @@ -CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { - - var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true }); - - var header = 'header' - , code = 'comment' - , quote = 'quote' - , list = 'string' - , hr = 'hr' - , linktext = 'link' - , linkhref = 'string' - , em = 'em' - , strong = 'strong' - , emstrong = 'emstrong'; - - var hrRE = /^[*-=_]/ - , ulRE = /^[*-+]\s+/ - , olRE = /^[0-9]\.\s+/ - , headerRE = /^(?:\={3,}|-{3,})$/ - , codeRE = /^(k:\t|\s{4,})/ - , textRE = /^[^\[*_\\<>`]+/; - - function switchInline(stream, state, f) { - state.f = state.inline = f; - return f(stream, state); - } - - function switchBlock(stream, state, f) { - state.f = state.block = f; - return f(stream, state); - } - - - // Blocks - - function blockNormal(stream, state) { - if (stream.match(codeRE)) { - stream.skipToEnd(); - return code; - } - - if (stream.eatSpace()) { - return null; - } - - if (stream.peek() === '#' || stream.match(headerRE)) { - stream.skipToEnd(); - return header; - } - if (stream.eat('>')) { - state.indentation++; - return quote; - } - if (stream.peek() === '[') { - return switchInline(stream, state, footnoteLink); - } - if (hrRE.test(stream.peek())) { - var re = new RegExp('(?:\s*['+stream.peek()+']){3,}$'); - if (stream.match(re, true)) { - return hr; - } - } - - var match; - if (match = stream.match(ulRE, true) || stream.match(olRE, true)) { - state.indentation += match[0].length; - return list; - } - - return switchInline(stream, state, state.inline); - } - - function htmlBlock(stream, state) { - var style = htmlMode.token(stream, state.htmlState); - if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) { - state.f = inlineNormal; - state.block = blockNormal; - } - return style; - } - - - // Inline - function getType(state) { - return state.strong ? (state.em ? emstrong : strong) - : (state.em ? em : null); - } - - function handleText(stream, state) { - if (stream.match(textRE, true)) { - return getType(state); - } - return undefined; - } - - function inlineNormal(stream, state) { - var style = state.text(stream, state) - if (typeof style !== 'undefined') - return style; - - var ch = stream.next(); - - if (ch === '\\') { - stream.next(); - return getType(state); - } - if (ch === '`') { - return switchInline(stream, state, inlineElement(code, '`')); - } - if (ch === '[') { - return switchInline(stream, state, linkText); - } - if (ch === '<' && stream.match(/^\w/, false)) { - stream.backUp(1); - return switchBlock(stream, state, htmlBlock); - } - - var t = getType(state); - if (ch === '*' || ch === '_') { - if (stream.eat(ch)) { - return (state.strong = !state.strong) ? getType(state) : t; - } - return (state.em = !state.em) ? getType(state) : t; - } - - return getType(state); - } - - function linkText(stream, state) { - while (!stream.eol()) { - var ch = stream.next(); - if (ch === '\\') stream.next(); - if (ch === ']') { - state.inline = state.f = linkHref; - return linktext; - } - } - return linktext; - } - - function linkHref(stream, state) { - stream.eatSpace(); - var ch = stream.next(); - if (ch === '(' || ch === '[') { - return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']')); - } - return 'error'; - } - - function footnoteLink(stream, state) { - if (stream.match(/^[^\]]*\]:/, true)) { - state.f = footnoteUrl; - return linktext; - } - return switchInline(stream, state, inlineNormal); - } - - function footnoteUrl(stream, state) { - stream.eatSpace(); - stream.match(/^[^\s]+/, true); - state.f = state.inline = inlineNormal; - return linkhref; - } - - function inlineRE(endChar) { - if (!inlineRE[endChar]) { - // match any not-escaped-non-endChar and any escaped char - // then match endChar or eol - inlineRE[endChar] = new RegExp('^(?:[^\\\\\\' + endChar + ']|\\\\.)*(?:\\' + endChar + '|$)'); - } - return inlineRE[endChar]; - } - - function inlineElement(type, endChar, next) { - next = next || inlineNormal; - return function(stream, state) { - stream.match(inlineRE(endChar)); - state.inline = state.f = next; - return type; - }; - } - - return { - startState: function() { - return { - f: blockNormal, - - block: blockNormal, - htmlState: htmlMode.startState(), - indentation: 0, - - inline: inlineNormal, - text: handleText, - em: false, - strong: false - }; - }, - - copyState: function(s) { - return { - f: s.f, - - block: s.block, - htmlState: CodeMirror.copyState(htmlMode, s.htmlState), - indentation: s.indentation, - - inline: s.inline, - text: s.text, - em: s.em, - strong: s.strong - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.f = state.block; - var previousIndentation = state.indentation - , currentIndentation = 0; - while (previousIndentation > 0) { - if (stream.eat(' ')) { - previousIndentation--; - currentIndentation++; - } else if (previousIndentation >= 4 && stream.eat('\t')) { - previousIndentation -= 4; - currentIndentation += 4; - } else { - break; - } - } - state.indentation = currentIndentation; - - if (currentIndentation > 0) return null; - } - return state.f(stream, state); - }, - - getType: getType - }; - -}); - -CodeMirror.defineMIME("text/x-markdown", "markdown"); -CodeMirror.defineMIME("application/x-markdown", "markdown"); diff --git a/vendor/assets/javascripts/codemirror/modes/mysql.js b/vendor/assets/javascripts/codemirror/modes/mysql.js deleted file mode 100644 index 50bcec98c..000000000 --- a/vendor/assets/javascripts/codemirror/modes/mysql.js +++ /dev/null @@ -1,189 +0,0 @@ -/* - * MySQL Mode for CodeMirror 2 by MySQL-Tools - * @author James Thorne (partydroid) - * @link http://github.com/partydroid/MySQL-Tools - * @link http://mysqltools.org - * @version 02/Jan/2012 -*/ -CodeMirror.defineMode("mysql", function(config) { - var indentUnit = config.indentUnit; - var curPunc; - - function wordRegexp(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", - "isblank", "isliteral", "union", "a"]); - var keywords = wordRegexp([ - ('ACCESSIBLE'),('ALTER'),('AS'),('BEFORE'),('BINARY'),('BY'),('CASE'),('CHARACTER'),('COLUMN'),('CONTINUE'),('CROSS'),('CURRENT_TIMESTAMP'),('DATABASE'),('DAY_MICROSECOND'),('DEC'),('DEFAULT'), - ('DESC'),('DISTINCT'),('DOUBLE'),('EACH'),('ENCLOSED'),('EXIT'),('FETCH'),('FLOAT8'),('FOREIGN'),('GRANT'),('HIGH_PRIORITY'),('HOUR_SECOND'),('IN'),('INNER'),('INSERT'),('INT2'),('INT8'), - ('INTO'),('JOIN'),('KILL'),('LEFT'),('LINEAR'),('LOCALTIME'),('LONG'),('LOOP'),('MATCH'),('MEDIUMTEXT'),('MINUTE_SECOND'),('NATURAL'),('NULL'),('OPTIMIZE'),('OR'),('OUTER'),('PRIMARY'), - ('RANGE'),('READ_WRITE'),('REGEXP'),('REPEAT'),('RESTRICT'),('RIGHT'),('SCHEMAS'),('SENSITIVE'),('SHOW'),('SPECIFIC'),('SQLSTATE'),('SQL_CALC_FOUND_ROWS'),('STARTING'),('TERMINATED'), - ('TINYINT'),('TRAILING'),('UNDO'),('UNLOCK'),('USAGE'),('UTC_DATE'),('VALUES'),('VARCHARACTER'),('WHERE'),('WRITE'),('ZEROFILL'),('ALL'),('AND'),('ASENSITIVE'),('BIGINT'),('BOTH'),('CASCADE'), - ('CHAR'),('COLLATE'),('CONSTRAINT'),('CREATE'),('CURRENT_TIME'),('CURSOR'),('DAY_HOUR'),('DAY_SECOND'),('DECLARE'),('DELETE'),('DETERMINISTIC'),('DIV'),('DUAL'),('ELSEIF'),('EXISTS'),('FALSE'), - ('FLOAT4'),('FORCE'),('FULLTEXT'),('HAVING'),('HOUR_MINUTE'),('IGNORE'),('INFILE'),('INSENSITIVE'),('INT1'),('INT4'),('INTERVAL'),('ITERATE'),('KEYS'),('LEAVE'),('LIMIT'),('LOAD'),('LOCK'), - ('LONGTEXT'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MEDIUMINT'),('MINUTE_MICROSECOND'),('MODIFIES'),('NO_WRITE_TO_BINLOG'),('ON'),('OPTIONALLY'),('OUT'),('PRECISION'),('PURGE'),('READS'), - ('REFERENCES'),('RENAME'),('REQUIRE'),('REVOKE'),('SCHEMA'),('SELECT'),('SET'),('SPATIAL'),('SQLEXCEPTION'),('SQL_BIG_RESULT'),('SSL'),('TABLE'),('TINYBLOB'),('TO'),('TRUE'),('UNIQUE'), - ('UPDATE'),('USING'),('UTC_TIMESTAMP'),('VARCHAR'),('WHEN'),('WITH'),('YEAR_MONTH'),('ADD'),('ANALYZE'),('ASC'),('BETWEEN'),('BLOB'),('CALL'),('CHANGE'),('CHECK'),('CONDITION'),('CONVERT'), - ('CURRENT_DATE'),('CURRENT_USER'),('DATABASES'),('DAY_MINUTE'),('DECIMAL'),('DELAYED'),('DESCRIBE'),('DISTINCTROW'),('DROP'),('ELSE'),('ESCAPED'),('EXPLAIN'),('FLOAT'),('FOR'),('FROM'), - ('GROUP'),('HOUR_MICROSECOND'),('IF'),('INDEX'),('INOUT'),('INT'),('INT3'),('INTEGER'),('IS'),('KEY'),('LEADING'),('LIKE'),('LINES'),('LOCALTIMESTAMP'),('LONGBLOB'),('LOW_PRIORITY'), - ('MEDIUMBLOB'),('MIDDLEINT'),('MOD'),('NOT'),('NUMERIC'),('OPTION'),('ORDER'),('OUTFILE'),('PROCEDURE'),('READ'),('REAL'),('RELEASE'),('REPLACE'),('RETURN'),('RLIKE'),('SECOND_MICROSECOND'), - ('SEPARATOR'),('SMALLINT'),('SQL'),('SQLWARNING'),('SQL_SMALL_RESULT'),('STRAIGHT_JOIN'),('THEN'),('TINYTEXT'),('TRIGGER'),('UNION'),('UNSIGNED'),('USE'),('UTC_TIME'),('VARBINARY'),('VARYING'), - ('WHILE'),('XOR'),('FULL'),('COLUMNS'),('MIN'),('MAX'),('STDEV'),('COUNT') - ]); - var operatorChars = /[*+\-<>=&|]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - curPunc = null; - if (ch == "$" || ch == "?") { - stream.match(/^[\w\d]*/); - return "variable-2"; - } - else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { - stream.match(/^[^\s\u00a0>]*>?/); - return "atom"; - } - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } - else if (ch == "`") { - state.tokenize = tokenOpLiteral(ch); - return state.tokenize(stream, state); - } - else if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return null; - } - else if (ch == "-") { - ch2 = stream.next(); - if(ch2=="-") - { - stream.skipToEnd(); - return "comment"; - } - - } - else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return null; - } - else if (ch == ":") { - stream.eatWhile(/[\w\d\._\-]/); - return "atom"; - } - else { - stream.eatWhile(/[_\w\d]/); - if (stream.eat(":")) { - stream.eatWhile(/[\w\d_\-]/); - return "atom"; - } - var word = stream.current(), type; - if (ops.test(word)) - return null; - else if (keywords.test(word)) - return "keyword"; - else - return "variable"; - } - } - - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - - function tokenOpLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "variable-2"; - }; - } - - - function pushContext(state, type, col) { - state.context = {prev: state.context, indent: state.indent, col: col, type: type}; - } - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - context: null, - indent: 0, - col: 0}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) state.context.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { - state.context.align = true; - } - - if (curPunc == "(") pushContext(state, ")", stream.column()); - else if (curPunc == "[") pushContext(state, "]", stream.column()); - else if (curPunc == "{") pushContext(state, "}", stream.column()); - else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type == "pattern") popContext(state); - if (state.context && curPunc == state.context.type) popContext(state); - } - else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); - else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) - pushContext(state, "pattern", stream.column()); - else if (state.context.type == "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - - return style; - }, - - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) - while (context && context.type == "pattern") context = context.prev; - - var closing = context && firstChar == context.type; - if (!context) - return 0; - else if (context.type == "pattern") - return context.col; - else if (context.align) - return context.col + (closing ? 0 : 1); - else - return context.indent + (closing ? 0 : indentUnit); - } - }; -}); - -CodeMirror.defineMIME("text/x-mysql", "mysql"); -CodeMirror.defineMIME("application/x-mysql", "mysql"); diff --git a/vendor/assets/javascripts/codemirror/modes/ntriples.js b/vendor/assets/javascripts/codemirror/modes/ntriples.js deleted file mode 100644 index 3b6cb4167..000000000 --- a/vendor/assets/javascripts/codemirror/modes/ntriples.js +++ /dev/null @@ -1,172 +0,0 @@ -/********************************************************** -* This script provides syntax highlighting support for -* the Ntriples format. -* Ntriples format specification: -* http://www.w3.org/TR/rdf-testcases/#ntriples -***********************************************************/ - -/* - The following expression defines the defined ASF grammar transitions. - - pre_subject -> - { - ( writing_subject_uri | writing_bnode_uri ) - -> pre_predicate - -> writing_predicate_uri - -> pre_object - -> writing_object_uri | writing_object_bnode | - ( - writing_object_literal - -> writing_literal_lang | writing_literal_type - ) - -> post_object - -> BEGIN - } otherwise { - -> ERROR - } -*/ -CodeMirror.defineMode("ntriples", function() { - - Location = { - PRE_SUBJECT : 0, - WRITING_SUB_URI : 1, - WRITING_BNODE_URI : 2, - PRE_PRED : 3, - WRITING_PRED_URI : 4, - PRE_OBJ : 5, - WRITING_OBJ_URI : 6, - WRITING_OBJ_BNODE : 7, - WRITING_OBJ_LITERAL : 8, - WRITING_LIT_LANG : 9, - WRITING_LIT_TYPE : 10, - POST_OBJ : 11, - ERROR : 12 - }; - function transitState(currState, c) { - var currLocation = currState.location; - var ret; - - // Opening. - if (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI; - else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI; - else if(currLocation == Location.PRE_PRED && c == '<') ret = Location.WRITING_PRED_URI; - else if(currLocation == Location.PRE_OBJ && c == '<') ret = Location.WRITING_OBJ_URI; - else if(currLocation == Location.PRE_OBJ && c == '_') ret = Location.WRITING_OBJ_BNODE; - else if(currLocation == Location.PRE_OBJ && c == '"') ret = Location.WRITING_OBJ_LITERAL; - - // Closing. - else if(currLocation == Location.WRITING_SUB_URI && c == '>') ret = Location.PRE_PRED; - else if(currLocation == Location.WRITING_BNODE_URI && c == ' ') ret = Location.PRE_PRED; - else if(currLocation == Location.WRITING_PRED_URI && c == '>') ret = Location.PRE_OBJ; - else if(currLocation == Location.WRITING_OBJ_URI && c == '>') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_OBJ_BNODE && c == ' ') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '"') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ; - - // Closing typed and language literal. - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG; - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE; - - // Spaces. - else if( c == ' ' && - ( - currLocation == Location.PRE_SUBJECT || - currLocation == Location.PRE_PRED || - currLocation == Location.PRE_OBJ || - currLocation == Location.POST_OBJ - ) - ) ret = currLocation; - - // Reset. - else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT; - - // Error - else ret = Location.ERROR; - - currState.location=ret; - } - - untilSpace = function(c) { return c != ' '; }; - untilEndURI = function(c) { return c != '>'; }; - return { - startState: function() { - return { - location : Location.PRE_SUBJECT, - uris : [], - anchors : [], - bnodes : [], - langs : [], - types : [] - }; - }, - token: function(stream, state) { - var ch = stream.next(); - if(ch == '<') { - transitState(state, ch); - var parsedURI = ''; - stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} ); - state.uris.push(parsedURI); - if( stream.match('#', false) ) return 'variable'; - stream.next(); - transitState(state, '>'); - return 'variable'; - } - if(ch == '#') { - var parsedAnchor = ''; - stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false}); - state.anchors.push(parsedAnchor); - return 'variable-2'; - } - if(ch == '>') { - transitState(state, '>'); - return 'variable'; - } - if(ch == '_') { - transitState(state, ch); - var parsedBNode = ''; - stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;}); - state.bnodes.push(parsedBNode); - stream.next(); - transitState(state, ' '); - return 'builtin'; - } - if(ch == '"') { - transitState(state, ch); - stream.eatWhile( function(c) { return c != '"'; } ); - stream.next(); - if( stream.peek() != '@' && stream.peek() != '^' ) { - transitState(state, '"'); - } - return 'string'; - } - if( ch == '@' ) { - transitState(state, '@'); - var parsedLang = ''; - stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;}); - state.langs.push(parsedLang); - stream.next(); - transitState(state, ' '); - return 'string-2'; - } - if( ch == '^' ) { - stream.next(); - transitState(state, '^'); - var parsedType = ''; - stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} ); - state.types.push(parsedType); - stream.next(); - transitState(state, '>'); - return 'variable'; - } - if( ch == ' ' ) { - transitState(state, ch); - } - if( ch == '.' ) { - transitState(state, ch); - } - } - }; -}); - -CodeMirror.defineMIME("text/n-triples", "ntriples"); diff --git a/vendor/assets/javascripts/codemirror/modes/pascal.js b/vendor/assets/javascripts/codemirror/modes/pascal.js deleted file mode 100644 index de72df533..000000000 --- a/vendor/assets/javascripts/codemirror/modes/pascal.js +++ /dev/null @@ -1,139 +0,0 @@ -CodeMirror.defineMode("pascal", function(config) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = words("and array begin case const div do downto else end file for forward integer " + - "boolean char function goto if in label mod nil not of or packed procedure " + - "program record repeat set string then to type until var while with"); - var blockKeywords = words("case do else for if switch while struct then of"); - var atoms = {"null": true}; - - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == "#" && state.startOfLine) { - stream.skipToEnd(); - return "meta"; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (ch == "(" && stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "word"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !escaped) state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == ")" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" ) - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == ctx.type) popContext(state); - else if ( ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-pascal", "pascal"); -CodeMirror.defineMIME("application/x-pascal", "pascal"); diff --git a/vendor/assets/javascripts/codemirror/modes/perl.js b/vendor/assets/javascripts/codemirror/modes/perl.js deleted file mode 100644 index fa744c85a..000000000 --- a/vendor/assets/javascripts/codemirror/modes/perl.js +++ /dev/null @@ -1,817 +0,0 @@ -// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08) -// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com) -CodeMirror.defineMode("perl",function(config,parserConfig){ - // http://perldoc.perl.org - var PERL={ // null - magic touch - // 1 - keyword - // 2 - def - // 3 - atom - // 4 - operator - // 5 - variable-2 (predefined) - // [x,y] - x=1,2,3; y=must be defined if x{...} - // PERL operators - '->' : 4, - '++' : 4, - '--' : 4, - '**' : 4, - // ! ~ \ and unary + and - - '=~' : 4, - '!~' : 4, - '*' : 4, - '/' : 4, - '%' : 4, - 'x' : 4, - '+' : 4, - '-' : 4, - '.' : 4, - '<<' : 4, - '>>' : 4, - // named unary operators - '<' : 4, - '>' : 4, - '<=' : 4, - '>=' : 4, - 'lt' : 4, - 'gt' : 4, - 'le' : 4, - 'ge' : 4, - '==' : 4, - '!=' : 4, - '<=>' : 4, - 'eq' : 4, - 'ne' : 4, - 'cmp' : 4, - '~~' : 4, - '&' : 4, - '|' : 4, - '^' : 4, - '&&' : 4, - '||' : 4, - '//' : 4, - '..' : 4, - '...' : 4, - '?' : 4, - ':' : 4, - '=' : 4, - '+=' : 4, - '-=' : 4, - '*=' : 4, // etc. ??? - ',' : 4, - '=>' : 4, - '::' : 4, - // list operators (rightward) - 'not' : 4, - 'and' : 4, - 'or' : 4, - 'xor' : 4, - // PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;) - 'BEGIN' : [5,1], - 'END' : [5,1], - 'PRINT' : [5,1], - 'PRINTF' : [5,1], - 'GETC' : [5,1], - 'READ' : [5,1], - 'READLINE' : [5,1], - 'DESTROY' : [5,1], - 'TIE' : [5,1], - 'TIEHANDLE' : [5,1], - 'UNTIE' : [5,1], - 'STDIN' : 5, - 'STDIN_TOP' : 5, - 'STDOUT' : 5, - 'STDOUT_TOP' : 5, - 'STDERR' : 5, - 'STDERR_TOP' : 5, - '$ARG' : 5, - '$_' : 5, - '@ARG' : 5, - '@_' : 5, - '$LIST_SEPARATOR' : 5, - '$"' : 5, - '$PROCESS_ID' : 5, - '$PID' : 5, - '$$' : 5, - '$REAL_GROUP_ID' : 5, - '$GID' : 5, - '$(' : 5, - '$EFFECTIVE_GROUP_ID' : 5, - '$EGID' : 5, - '$)' : 5, - '$PROGRAM_NAME' : 5, - '$0' : 5, - '$SUBSCRIPT_SEPARATOR' : 5, - '$SUBSEP' : 5, - '$;' : 5, - '$REAL_USER_ID' : 5, - '$UID' : 5, - '$<' : 5, - '$EFFECTIVE_USER_ID' : 5, - '$EUID' : 5, - '$>' : 5, - '$a' : 5, - '$b' : 5, - '$COMPILING' : 5, - '$^C' : 5, - '$DEBUGGING' : 5, - '$^D' : 5, - '${^ENCODING}' : 5, - '$ENV' : 5, - '%ENV' : 5, - '$SYSTEM_FD_MAX' : 5, - '$^F' : 5, - '@F' : 5, - '${^GLOBAL_PHASE}' : 5, - '$^H' : 5, - '%^H' : 5, - '@INC' : 5, - '%INC' : 5, - '$INPLACE_EDIT' : 5, - '$^I' : 5, - '$^M' : 5, - '$OSNAME' : 5, - '$^O' : 5, - '${^OPEN}' : 5, - '$PERLDB' : 5, - '$^P' : 5, - '$SIG' : 5, - '%SIG' : 5, - '$BASETIME' : 5, - '$^T' : 5, - '${^TAINT}' : 5, - '${^UNICODE}' : 5, - '${^UTF8CACHE}' : 5, - '${^UTF8LOCALE}' : 5, - '$PERL_VERSION' : 5, - '$^V' : 5, - '${^WIN32_SLOPPY_STAT}' : 5, - '$EXECUTABLE_NAME' : 5, - '$^X' : 5, - '$1' : 5, // - regexp $1, $2... - '$MATCH' : 5, - '$&' : 5, - '${^MATCH}' : 5, - '$PREMATCH' : 5, - '$`' : 5, - '${^PREMATCH}' : 5, - '$POSTMATCH' : 5, - "$'" : 5, - '${^POSTMATCH}' : 5, - '$LAST_PAREN_MATCH' : 5, - '$+' : 5, - '$LAST_SUBMATCH_RESULT' : 5, - '$^N' : 5, - '@LAST_MATCH_END' : 5, - '@+' : 5, - '%LAST_PAREN_MATCH' : 5, - '%+' : 5, - '@LAST_MATCH_START' : 5, - '@-' : 5, - '%LAST_MATCH_START' : 5, - '%-' : 5, - '$LAST_REGEXP_CODE_RESULT' : 5, - '$^R' : 5, - '${^RE_DEBUG_FLAGS}' : 5, - '${^RE_TRIE_MAXBUF}' : 5, - '$ARGV' : 5, - '@ARGV' : 5, - 'ARGV' : 5, - 'ARGVOUT' : 5, - '$OUTPUT_FIELD_SEPARATOR' : 5, - '$OFS' : 5, - '$,' : 5, - '$INPUT_LINE_NUMBER' : 5, - '$NR' : 5, - '$.' : 5, - '$INPUT_RECORD_SEPARATOR' : 5, - '$RS' : 5, - '$/' : 5, - '$OUTPUT_RECORD_SEPARATOR' : 5, - '$ORS' : 5, - '$\\' : 5, - '$OUTPUT_AUTOFLUSH' : 5, - '$|' : 5, - '$ACCUMULATOR' : 5, - '$^A' : 5, - '$FORMAT_FORMFEED' : 5, - '$^L' : 5, - '$FORMAT_PAGE_NUMBER' : 5, - '$%' : 5, - '$FORMAT_LINES_LEFT' : 5, - '$-' : 5, - '$FORMAT_LINE_BREAK_CHARACTERS' : 5, - '$:' : 5, - '$FORMAT_LINES_PER_PAGE' : 5, - '$=' : 5, - '$FORMAT_TOP_NAME' : 5, - '$^' : 5, - '$FORMAT_NAME' : 5, - '$~' : 5, - '${^CHILD_ERROR_NATIVE}' : 5, - '$EXTENDED_OS_ERROR' : 5, - '$^E' : 5, - '$EXCEPTIONS_BEING_CAUGHT' : 5, - '$^S' : 5, - '$WARNING' : 5, - '$^W' : 5, - '${^WARNING_BITS}' : 5, - '$OS_ERROR' : 5, - '$ERRNO' : 5, - '$!' : 5, - '%OS_ERROR' : 5, - '%ERRNO' : 5, - '%!' : 5, - '$CHILD_ERROR' : 5, - '$?' : 5, - '$EVAL_ERROR' : 5, - '$@' : 5, - '$OFMT' : 5, - '$#' : 5, - '$*' : 5, - '$ARRAY_BASE' : 5, - '$[' : 5, - '$OLD_PERL_VERSION' : 5, - '$]' : 5, - // PERL blocks - 'if' :[1,1], - elsif :[1,1], - 'else' :[1,1], - 'while' :[1,1], - unless :[1,1], - 'for' :[1,1], - foreach :[1,1], - // PERL functions - 'abs' :1, // - absolute value function - accept :1, // - accept an incoming socket connect - alarm :1, // - schedule a SIGALRM - 'atan2' :1, // - arctangent of Y/X in the range -PI to PI - bind :1, // - binds an address to a socket - binmode :1, // - prepare binary files for I/O - bless :1, // - create an object - bootstrap :1, // - 'break' :1, // - break out of a "given" block - caller :1, // - get context of the current subroutine call - chdir :1, // - change your current working directory - chmod :1, // - changes the permissions on a list of files - chomp :1, // - remove a trailing record separator from a string - chop :1, // - remove the last character from a string - chown :1, // - change the owership on a list of files - chr :1, // - get character this number represents - chroot :1, // - make directory new root for path lookups - close :1, // - close file (or pipe or socket) handle - closedir :1, // - close directory handle - connect :1, // - connect to a remote socket - 'continue' :[1,1], // - optional trailing block in a while or foreach - 'cos' :1, // - cosine function - crypt :1, // - one-way passwd-style encryption - dbmclose :1, // - breaks binding on a tied dbm file - dbmopen :1, // - create binding on a tied dbm file - 'default' :1, // - defined :1, // - test whether a value, variable, or function is defined - 'delete' :1, // - deletes a value from a hash - die :1, // - raise an exception or bail out - 'do' :1, // - turn a BLOCK into a TERM - dump :1, // - create an immediate core dump - each :1, // - retrieve the next key/value pair from a hash - endgrent :1, // - be done using group file - endhostent :1, // - be done using hosts file - endnetent :1, // - be done using networks file - endprotoent :1, // - be done using protocols file - endpwent :1, // - be done using passwd file - endservent :1, // - be done using services file - eof :1, // - test a filehandle for its end - 'eval' :1, // - catch exceptions or compile and run code - 'exec' :1, // - abandon this program to run another - exists :1, // - test whether a hash key is present - exit :1, // - terminate this program - 'exp' :1, // - raise I to a power - fcntl :1, // - file control system call - fileno :1, // - return file descriptor from filehandle - flock :1, // - lock an entire file with an advisory lock - fork :1, // - create a new process just like this one - format :1, // - declare a picture format with use by the write() function - formline :1, // - internal function used for formats - getc :1, // - get the next character from the filehandle - getgrent :1, // - get next group record - getgrgid :1, // - get group record given group user ID - getgrnam :1, // - get group record given group name - gethostbyaddr :1, // - get host record given its address - gethostbyname :1, // - get host record given name - gethostent :1, // - get next hosts record - getlogin :1, // - return who logged in at this tty - getnetbyaddr :1, // - get network record given its address - getnetbyname :1, // - get networks record given name - getnetent :1, // - get next networks record - getpeername :1, // - find the other end of a socket connection - getpgrp :1, // - get process group - getppid :1, // - get parent process ID - getpriority :1, // - get current nice value - getprotobyname :1, // - get protocol record given name - getprotobynumber :1, // - get protocol record numeric protocol - getprotoent :1, // - get next protocols record - getpwent :1, // - get next passwd record - getpwnam :1, // - get passwd record given user login name - getpwuid :1, // - get passwd record given user ID - getservbyname :1, // - get services record given its name - getservbyport :1, // - get services record given numeric port - getservent :1, // - get next services record - getsockname :1, // - retrieve the sockaddr for a given socket - getsockopt :1, // - get socket options on a given socket - given :1, // - glob :1, // - expand filenames using wildcards - gmtime :1, // - convert UNIX time into record or string using Greenwich time - 'goto' :1, // - create spaghetti code - grep :1, // - locate elements in a list test true against a given criterion - hex :1, // - convert a string to a hexadecimal number - 'import' :1, // - patch a module's namespace into your own - index :1, // - find a substring within a string - int :1, // - get the integer portion of a number - ioctl :1, // - system-dependent device control system call - 'join' :1, // - join a list into a string using a separator - keys :1, // - retrieve list of indices from a hash - kill :1, // - send a signal to a process or process group - last :1, // - exit a block prematurely - lc :1, // - return lower-case version of a string - lcfirst :1, // - return a string with just the next letter in lower case - length :1, // - return the number of bytes in a string - 'link' :1, // - create a hard link in the filesytem - listen :1, // - register your socket as a server - local : 2, // - create a temporary value for a global variable (dynamic scoping) - localtime :1, // - convert UNIX time into record or string using local time - lock :1, // - get a thread lock on a variable, subroutine, or method - 'log' :1, // - retrieve the natural logarithm for a number - lstat :1, // - stat a symbolic link - m :null, // - match a string with a regular expression pattern - map :1, // - apply a change to a list to get back a new list with the changes - mkdir :1, // - create a directory - msgctl :1, // - SysV IPC message control operations - msgget :1, // - get SysV IPC message queue - msgrcv :1, // - receive a SysV IPC message from a message queue - msgsnd :1, // - send a SysV IPC message to a message queue - my : 2, // - declare and assign a local variable (lexical scoping) - 'new' :1, // - next :1, // - iterate a block prematurely - no :1, // - unimport some module symbols or semantics at compile time - oct :1, // - convert a string to an octal number - open :1, // - open a file, pipe, or descriptor - opendir :1, // - open a directory - ord :1, // - find a character's numeric representation - our : 2, // - declare and assign a package variable (lexical scoping) - pack :1, // - convert a list into a binary representation - 'package' :1, // - declare a separate global namespace - pipe :1, // - open a pair of connected filehandles - pop :1, // - remove the last element from an array and return it - pos :1, // - find or set the offset for the last/next m//g search - print :1, // - output a list to a filehandle - printf :1, // - output a formatted list to a filehandle - prototype :1, // - get the prototype (if any) of a subroutine - push :1, // - append one or more elements to an array - q :null, // - singly quote a string - qq :null, // - doubly quote a string - qr :null, // - Compile pattern - quotemeta :null, // - quote regular expression magic characters - qw :null, // - quote a list of words - qx :null, // - backquote quote a string - rand :1, // - retrieve the next pseudorandom number - read :1, // - fixed-length buffered input from a filehandle - readdir :1, // - get a directory from a directory handle - readline :1, // - fetch a record from a file - readlink :1, // - determine where a symbolic link is pointing - readpipe :1, // - execute a system command and collect standard output - recv :1, // - receive a message over a Socket - redo :1, // - start this loop iteration over again - ref :1, // - find out the type of thing being referenced - rename :1, // - change a filename - require :1, // - load in external functions from a library at runtime - reset :1, // - clear all variables of a given name - 'return' :1, // - get out of a function early - reverse :1, // - flip a string or a list - rewinddir :1, // - reset directory handle - rindex :1, // - right-to-left substring search - rmdir :1, // - remove a directory - s :null, // - replace a pattern with a string - say :1, // - print with newline - scalar :1, // - force a scalar context - seek :1, // - reposition file pointer for random-access I/O - seekdir :1, // - reposition directory pointer - select :1, // - reset default output or do I/O multiplexing - semctl :1, // - SysV semaphore control operations - semget :1, // - get set of SysV semaphores - semop :1, // - SysV semaphore operations - send :1, // - send a message over a socket - setgrent :1, // - prepare group file for use - sethostent :1, // - prepare hosts file for use - setnetent :1, // - prepare networks file for use - setpgrp :1, // - set the process group of a process - setpriority :1, // - set a process's nice value - setprotoent :1, // - prepare protocols file for use - setpwent :1, // - prepare passwd file for use - setservent :1, // - prepare services file for use - setsockopt :1, // - set some socket options - shift :1, // - remove the first element of an array, and return it - shmctl :1, // - SysV shared memory operations - shmget :1, // - get SysV shared memory segment identifier - shmread :1, // - read SysV shared memory - shmwrite :1, // - write SysV shared memory - shutdown :1, // - close down just half of a socket connection - 'sin' :1, // - return the sine of a number - sleep :1, // - block for some number of seconds - socket :1, // - create a socket - socketpair :1, // - create a pair of sockets - 'sort' :1, // - sort a list of values - splice :1, // - add or remove elements anywhere in an array - 'split' :1, // - split up a string using a regexp delimiter - sprintf :1, // - formatted print into a string - 'sqrt' :1, // - square root function - srand :1, // - seed the random number generator - stat :1, // - get a file's status information - state :1, // - declare and assign a state variable (persistent lexical scoping) - study :1, // - optimize input data for repeated searches - 'sub' :1, // - declare a subroutine, possibly anonymously - 'substr' :1, // - get or alter a portion of a stirng - symlink :1, // - create a symbolic link to a file - syscall :1, // - execute an arbitrary system call - sysopen :1, // - open a file, pipe, or descriptor - sysread :1, // - fixed-length unbuffered input from a filehandle - sysseek :1, // - position I/O pointer on handle used with sysread and syswrite - system :1, // - run a separate program - syswrite :1, // - fixed-length unbuffered output to a filehandle - tell :1, // - get current seekpointer on a filehandle - telldir :1, // - get current seekpointer on a directory handle - tie :1, // - bind a variable to an object class - tied :1, // - get a reference to the object underlying a tied variable - time :1, // - return number of seconds since 1970 - times :1, // - return elapsed time for self and child processes - tr :null, // - transliterate a string - truncate :1, // - shorten a file - uc :1, // - return upper-case version of a string - ucfirst :1, // - return a string with just the next letter in upper case - umask :1, // - set file creation mode mask - undef :1, // - remove a variable or function definition - unlink :1, // - remove one link to a file - unpack :1, // - convert binary structure into normal perl variables - unshift :1, // - prepend more elements to the beginning of a list - untie :1, // - break a tie binding to a variable - use :1, // - load in a module at compile time - utime :1, // - set a file's last access and modify times - values :1, // - return a list of the values in a hash - vec :1, // - test or set particular bits in a string - wait :1, // - wait for any child process to die - waitpid :1, // - wait for a particular child process to die - wantarray :1, // - get void vs scalar vs list context of current subroutine call - warn :1, // - print debugging info - when :1, // - write :1, // - print a picture record - y :null}; // - transliterate a string - - var RXstyle="string-2"; - var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type - - function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;) - state.chain=null; // 12 3tail - state.style=null; - state.tail=null; - state.tokenize=function(stream,state){ - var e=false,c,i=0; - while(c=stream.next()){ - if(c===chain[i]&&!e){ - if(chain[++i]!==undefined){ - state.chain=chain[i]; - state.style=style; - state.tail=tail} - else if(tail) - stream.eatWhile(tail); - state.tokenize=tokenPerl; - return style} - e=!e&&c=="\\"} - return style}; - return state.tokenize(stream,state)} - - function tokenSOMETHING(stream,state,string){ - state.tokenize=function(stream,state){ - if(stream.string==string) - state.tokenize=tokenPerl; - stream.skipToEnd(); - return "string"}; - return state.tokenize(stream,state)} - - function tokenPerl(stream,state){ - if(stream.eatSpace()) - return null; - if(state.chain) - return tokenChain(stream,state,state.chain,state.style,state.tail); - if(stream.match(/^\-?[\d\.]/,false)) - if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/)) - return 'number'; - if(stream.match(/^<<(?=\w)/)){ // NOTE: <"],RXstyle,RXmodifiers)} - if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); - return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}} - else if(c=="q"){ - c=stream.look(1); - if(c=="("){ - stream.eatSuffix(2); - return tokenChain(stream,state,[")"],"string")} - if(c=="["){ - stream.eatSuffix(2); - return tokenChain(stream,state,["]"],"string")} - if(c=="{"){ - stream.eatSuffix(2); - return tokenChain(stream,state,["}"],"string")} - if(c=="<"){ - stream.eatSuffix(2); - return tokenChain(stream,state,[">"],"string")} - if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); - return tokenChain(stream,state,[stream.eat(c)],"string")}} - else if(c=="w"){ - c=stream.look(1); - if(c=="("){ - stream.eatSuffix(2); - return tokenChain(stream,state,[")"],"bracket")} - if(c=="["){ - stream.eatSuffix(2); - return tokenChain(stream,state,["]"],"bracket")} - if(c=="{"){ - stream.eatSuffix(2); - return tokenChain(stream,state,["}"],"bracket")} - if(c=="<"){ - stream.eatSuffix(2); - return tokenChain(stream,state,[">"],"bracket")} - if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); - return tokenChain(stream,state,[stream.eat(c)],"bracket")}} - else if(c=="r"){ - c=stream.look(1); - if(c=="("){ - stream.eatSuffix(2); - return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)} - if(c=="["){ - stream.eatSuffix(2); - return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)} - if(c=="{"){ - stream.eatSuffix(2); - return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)} - if(c=="<"){ - stream.eatSuffix(2); - return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)} - if(/[\^'"!~\/]/.test(c)){ - stream.eatSuffix(1); - return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}} - else if(/[\^'"!~\/(\[{<]/.test(c)){ - if(c=="("){ - stream.eatSuffix(1); - return tokenChain(stream,state,[")"],"string")} - if(c=="["){ - stream.eatSuffix(1); - return tokenChain(stream,state,["]"],"string")} - if(c=="{"){ - stream.eatSuffix(1); - return tokenChain(stream,state,["}"],"string")} - if(c=="<"){ - stream.eatSuffix(1); - return tokenChain(stream,state,[">"],"string")} - if(/[\^'"!~\/]/.test(c)){ - return tokenChain(stream,state,[stream.eat(c)],"string")}}}} - if(ch=="m"){ - var c=stream.look(-2); - if(!(c&&/\w/.test(c))){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(/[\^'"!~\/]/.test(c)){ - return tokenChain(stream,state,[c],RXstyle,RXmodifiers)} - if(c=="("){ - return tokenChain(stream,state,[")"],RXstyle,RXmodifiers)} - if(c=="["){ - return tokenChain(stream,state,["]"],RXstyle,RXmodifiers)} - if(c=="{"){ - return tokenChain(stream,state,["}"],RXstyle,RXmodifiers)} - if(c=="<"){ - return tokenChain(stream,state,[">"],RXstyle,RXmodifiers)}}}} - if(ch=="s"){ - var c=/[\/>\]})\w]/.test(stream.look(-2)); - if(!c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}} - if(ch=="y"){ - var c=/[\/>\]})\w]/.test(stream.look(-2)); - if(!c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}} - if(ch=="t"){ - var c=/[\/>\]})\w]/.test(stream.look(-2)); - if(!c){ - c=stream.eat("r");if(c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}} - if(ch=="`"){ - return tokenChain(stream,state,[ch],"variable-2")} - if(ch=="/"){ - if(!/~\s*$/.test(stream.prefix())) - return "operator"; - else - return tokenChain(stream,state,[ch],RXstyle,RXmodifiers)} - if(ch=="$"){ - var p=stream.pos; - if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}")) - return "variable-2"; - else - stream.pos=p} - if(/[$@%]/.test(ch)){ - var p=stream.pos; - if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){ - var c=stream.current(); - if(PERL[c]) - return "variable-2"} - stream.pos=p} - if(/[$@%&]/.test(ch)){ - if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){ - var c=stream.current(); - if(PERL[c]) - return "variable-2"; - else - return "variable"}} - if(ch=="#"){ - if(stream.look(-2)!="$"){ - stream.skipToEnd(); - return "comment"}} - if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){ - var p=stream.pos; - stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/); - if(PERL[stream.current()]) - return "operator"; - else - stream.pos=p} - if(ch=="_"){ - if(stream.pos==1){ - if(stream.suffix(6)=="_END__"){ - return tokenChain(stream,state,['\0'],"comment")} - else if(stream.suffix(7)=="_DATA__"){ - return tokenChain(stream,state,['\0'],"variable-2")} - else if(stream.suffix(7)=="_C__"){ - return tokenChain(stream,state,['\0'],"string")}}} - if(/\w/.test(ch)){ - var p=stream.pos; - if(stream.look(-2)=="{"&&(stream.look(0)=="}"||stream.eatWhile(/\w/)&&stream.look(0)=="}")) - return "string"; - else - stream.pos=p} - if(/[A-Z]/.test(ch)){ - var l=stream.look(-2); - var p=stream.pos; - stream.eatWhile(/[A-Z_]/); - if(/[\da-z]/.test(stream.look(0))){ - stream.pos=p} - else{ - var c=PERL[stream.current()]; - if(!c) - return "meta"; - if(c[1]) - c=c[0]; - if(l!=":"){ - if(c==1) - return "keyword"; - else if(c==2) - return "def"; - else if(c==3) - return "atom"; - else if(c==4) - return "operator"; - else if(c==5) - return "variable-2"; - else - return "meta"} - else - return "meta"}} - if(/[a-zA-Z_]/.test(ch)){ - var l=stream.look(-2); - stream.eatWhile(/\w/); - var c=PERL[stream.current()]; - if(!c) - return "meta"; - if(c[1]) - c=c[0]; - if(l!=":"){ - if(c==1) - return "keyword"; - else if(c==2) - return "def"; - else if(c==3) - return "atom"; - else if(c==4) - return "operator"; - else if(c==5) - return "variable-2"; - else - return "meta"} - else - return "meta"} - return null} - - return{ - startState:function(){ - return{ - tokenize:tokenPerl, - chain:null, - style:null, - tail:null}}, - token:function(stream,state){ - return (state.tokenize||tokenPerl)(stream,state)}, - electricChars:"{}"}}); - -CodeMirror.defineMIME("text/x-perl", "perl"); -CodeMirror.defineMIME("application/x-perl", "perl"); - -// it's like "peek", but need for look-ahead or look-behind if index < 0 -CodeMirror.StringStream.prototype.look=function(c){ - return this.string.charAt(this.pos+(c||0))}; - -// return a part of prefix of current stream from current position -CodeMirror.StringStream.prototype.prefix=function(c){ - if(c){ - var x=this.pos-c; - return this.string.substr((x>=0?x:0),c)} - else{ - return this.string.substr(0,this.pos-1)}}; - -// return a part of suffix of current stream from current position -CodeMirror.StringStream.prototype.suffix=function(c){ - var y=this.string.length; - var x=y-this.pos+1; - return this.string.substr(this.pos,(c&&c=(y=this.string.length-1)) - this.pos=y; - else - this.pos=x}; diff --git a/vendor/assets/javascripts/codemirror/modes/php.js b/vendor/assets/javascripts/codemirror/modes/php.js deleted file mode 100644 index 82da0f0a9..000000000 --- a/vendor/assets/javascripts/codemirror/modes/php.js +++ /dev/null @@ -1,122 +0,0 @@ -(function() { - function keywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - function heredoc(delim) { - return function(stream, state) { - if (stream.match(delim)) state.tokenize = null; - else stream.skipToEnd(); - return "string"; - } - } - var phpConfig = { - name: "clike", - keywords: keywords("abstract and array as break case catch cfunction class clone const continue declare " + - "default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends " + - "final for foreach function global goto if implements interface instanceof namespace " + - "new or private protected public static switch throw try use var while xor return" + - "die echo empty exit eval include include_once isset list require require_once print unset"), - blockKeywords: keywords("catch do else elseif for foreach if switch try while"), - atoms: keywords("true false null TRUE FALSE NULL"), - multiLineStrings: true, - hooks: { - "$": function(stream, state) { - stream.eatWhile(/[\w\$_]/); - return "variable-2"; - }, - "<": function(stream, state) { - if (stream.match(/</; - state.mode = 'php'; - } - else if (style == "tag" && stream.current() == ">" && state.curState.context) { - if (/^script$/i.test(state.curState.context.tagName)) { - state.curMode = jsMode; - state.curState = jsMode.startState(htmlMode.indent(state.curState, "")); - state.curClose = /^<\/\s*script\s*>/i; - state.mode = 'javascript'; - } - else if (/^style$/i.test(state.curState.context.tagName)) { - state.curMode = cssMode; - state.curState = cssMode.startState(htmlMode.indent(state.curState, "")); - state.curClose = /^<\/\s*style\s*>/i; - state.mode = 'css'; - } - } - return style; - } - else if (stream.match(state.curClose, false)) { - state.curMode = htmlMode; - state.curState = state.html; - state.curClose = null; - state.mode = 'html'; - return dispatch(stream, state); - } - else return state.curMode.token(stream, state.curState); - } - - return { - startState: function() { - var html = htmlMode.startState(); - return {html: html, - php: phpMode.startState(), - curMode: parserConfig.startOpen ? phpMode : htmlMode, - curState: parserConfig.startOpen ? phpMode.startState() : html, - curClose: parserConfig.startOpen ? /^\?>/ : null, - mode: parserConfig.startOpen ? 'php' : 'html'} - }, - - copyState: function(state) { - var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html), - php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur; - if (state.curState == html) cur = htmlNew; - else if (state.curState == php) cur = phpNew; - else cur = CodeMirror.copyState(state.curMode, state.curState); - return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur, - curClose: state.curClose, mode: state.mode}; - }, - - token: dispatch, - - indent: function(state, textAfter) { - if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) || - (state.curMode == phpMode && /^\?>/.test(textAfter))) - return htmlMode.indent(state.html, textAfter); - return state.curMode.indent(state.curState, textAfter); - }, - - electricChars: "/{}:" - } - }); - CodeMirror.defineMIME("application/x-httpd-php", "php"); - CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true}); - CodeMirror.defineMIME("text/x-php", phpConfig); - CodeMirror.defineMIME("application/x-php", phpConfig); -})(); diff --git a/vendor/assets/javascripts/codemirror/modes/plsql.js b/vendor/assets/javascripts/codemirror/modes/plsql.js deleted file mode 100644 index a30d7a091..000000000 --- a/vendor/assets/javascripts/codemirror/modes/plsql.js +++ /dev/null @@ -1,217 +0,0 @@ -CodeMirror.defineMode("plsql", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords, - functions = parserConfig.functions, - types = parserConfig.types, - sqlplus = parserConfig.sqlplus, - multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[+\-*&%=<>!?:\/|]/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - var type; - function ret(tp, style) { - type = tp; - return style; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - // start of string? - if (ch == '"' || ch == "'") - return chain(stream, state, tokenString(ch)); - // is it one of the special signs []{}().,;? Seperator? - else if (/[\[\]{}\(\),;\.]/.test(ch)) - return ret(ch); - // start of a number value? - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return ret("number", "number"); - } - // multi line comment or simple operator? - else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, tokenComment); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator"); - } - } - // single line comment or simple operator? - else if (ch == "-") { - if (stream.eat("-")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } - else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator"); - } - } - // pl/sql variable? - else if (ch == "@" || ch == "$") { - stream.eatWhile(/[\w\d\$_]/); - return ret("word", "variable"); - } - // is it a operator? - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator"); - } - else { - // get the whole word - stream.eatWhile(/[\w\$_]/); - // is it one of the listed keywords? - if (keywords && keywords.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "keyword"); - // is it one of the listed functions? - if (functions && functions.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "builtin"); - // is it one of the listed types? - if (types && types.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "variable-2"); - // is it one of the listed sqlplus keywords? - if (sqlplus && sqlplus.propertyIsEnumerable(stream.current().toLowerCase())) return ret("keyword", "variable-3"); - // default: just a "word" - return ret("word", "plsql-word"); - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return ret("string", "plsql-string"); - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "plsql-comment"); - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - startOfLine: true - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - } - }; -}); - -(function() { - function keywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var cKeywords = "abort accept access add all alter and any array arraylen as asc assert assign at attributes audit " + - "authorization avg " + - "base_table begin between binary_integer body boolean by " + - "case cast char char_base check close cluster clusters colauth column comment commit compress connect " + - "connected constant constraint crash create current currval cursor " + - "data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete " + - "desc digits dispose distinct do drop " + - "else elsif enable end entry escape exception exception_init exchange exclusive exists exit external " + - "fast fetch file for force form from function " + - "generic goto grant group " + - "having " + - "identified if immediate in increment index indexes indicator initial initrans insert interface intersect " + - "into is " + - "key " + - "level library like limited local lock log logging long loop " + - "master maxextents maxtrans member minextents minus mislabel mode modify multiset " + - "new next no noaudit nocompress nologging noparallel not nowait number_base " + - "object of off offline on online only open option or order out " + - "package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior " + - "private privileges procedure public " + - "raise range raw read rebuild record ref references refresh release rename replace resource restrict return " + - "returning reverse revoke rollback row rowid rowlabel rownum rows run " + - "savepoint schema segment select separate session set share snapshot some space split sql start statement " + - "storage subtype successful synonym " + - "tabauth table tables tablespace task terminate then to trigger truncate type " + - "union unique unlimited unrecoverable unusable update use using " + - "validate value values variable view views " + - "when whenever where while with work"; - - var cFunctions = "abs acos add_months ascii asin atan atan2 average " + - "bfilename " + - "ceil chartorowid chr concat convert cos cosh count " + - "decode deref dual dump dup_val_on_index " + - "empty error exp " + - "false floor found " + - "glb greatest " + - "hextoraw " + - "initcap instr instrb isopen " + - "last_day least lenght lenghtb ln lower lpad ltrim lub " + - "make_ref max min mod months_between " + - "new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower " + - "nls_sort nls_upper nlssort no_data_found notfound null nvl " + - "others " + - "power " + - "rawtohex reftohex round rowcount rowidtochar rpad rtrim " + - "sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate " + - "tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc " + - "uid upper user userenv " + - "variance vsize"; - - var cTypes = "bfile blob " + - "character clob " + - "dec " + - "float " + - "int integer " + - "mlslabel " + - "natural naturaln nchar nclob number numeric nvarchar2 " + - "real rowtype " + - "signtype smallint string " + - "varchar varchar2"; - - var cSqlplus = "appinfo arraysize autocommit autoprint autorecovery autotrace " + - "blockterminator break btitle " + - "cmdsep colsep compatibility compute concat copycommit copytypecheck " + - "define describe " + - "echo editfile embedded escape exec execute " + - "feedback flagger flush " + - "heading headsep " + - "instance " + - "linesize lno loboffset logsource long longchunksize " + - "markup " + - "native newpage numformat numwidth " + - "pagesize pause pno " + - "recsep recsepchar release repfooter repheader " + - "serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber " + - "sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix " + - "tab term termout time timing trimout trimspool ttitle " + - "underline " + - "verify version " + - "wrap"; - - CodeMirror.defineMIME("application/x-plsql", { - name: "plsql", - keywords: keywords(cKeywords), - functions: keywords(cFunctions), - types: keywords(cTypes), - sqlplus: keywords(cSqlplus) - }); -}()); diff --git a/vendor/assets/javascripts/codemirror/modes/python.js b/vendor/assets/javascripts/codemirror/modes/python.js deleted file mode 100644 index a2007f406..000000000 --- a/vendor/assets/javascripts/codemirror/modes/python.js +++ /dev/null @@ -1,341 +0,0 @@ -CodeMirror.defineMode("python", function(conf, parserConf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!]"); - var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]'); - var doubleOperators = new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"); - var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"); - var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); - - var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']); - var commonkeywords = ['as', 'assert', 'break', 'class', 'continue', - 'def', 'del', 'elif', 'else', 'except', 'finally', - 'for', 'from', 'global', 'if', 'import', - 'lambda', 'pass', 'raise', 'return', - 'try', 'while', 'with', 'yield']; - var commonBuiltins = ['abs', 'all', 'any', 'bin', 'bool', 'bytearray', 'callable', 'chr', - 'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod', - 'enumerate', 'eval', 'filter', 'float', 'format', 'frozenset', - 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', - 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', - 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', - 'object', 'oct', 'open', 'ord', 'pow', 'property', 'range', - 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', - 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', - 'type', 'vars', 'zip', '__import__', 'NotImplemented', - 'Ellipsis', '__debug__']; - var py2 = {'builtins': ['apply', 'basestring', 'buffer', 'cmp', 'coerce', 'execfile', - 'file', 'intern', 'long', 'raw_input', 'reduce', 'reload', - 'unichr', 'unicode', 'xrange', 'False', 'True', 'None'], - 'keywords': ['exec', 'print']}; - var py3 = {'builtins': ['ascii', 'bytes', 'exec', 'print'], - 'keywords': ['nonlocal', 'False', 'True', 'None']}; - - if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) { - commonkeywords = commonkeywords.concat(py3.keywords); - commonBuiltins = commonBuiltins.concat(py3.builtins); - var stringPrefixes = new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))", "i"); - } else { - commonkeywords = commonkeywords.concat(py2.keywords); - commonBuiltins = commonBuiltins.concat(py2.builtins); - var stringPrefixes = new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i"); - } - var keywords = wordRegexp(commonkeywords); - var builtins = wordRegexp(commonBuiltins); - - var indentInfo = null; - - // tokenizers - function tokenBase(stream, state) { - // Handle scope changes - if (stream.sol()) { - var scopeOffset = state.scopes[0].offset; - if (stream.eatSpace()) { - var lineOffset = stream.indentation(); - if (lineOffset > scopeOffset) { - indentInfo = 'indent'; - } else if (lineOffset < scopeOffset) { - indentInfo = 'dedent'; - } - return null; - } else { - if (scopeOffset > 0) { - dedent(stream, state); - } - } - } - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle Comments - if (ch === '#') { - stream.skipToEnd(); - return 'comment'; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.]/, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; } - if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; } - if (stream.match(/^\.\d+/)) { floatLiteral = true; } - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; } - // Binary - if (stream.match(/^0b[01]+/i)) { intLiteral = true; } - // Octal - if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; } - // Decimal - if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return 'number'; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) { - return null; - } - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) { - return 'operator'; - } - if (stream.match(singleDelimiters)) { - return null; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(builtins)) { - return 'builtin'; - } - - if (stream.match(identifiers)) { - return 'variable'; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) { - delimiter = delimiter.substr(1); - } - var singleline = delimiter.length == 1; - var OUTCLASS = 'string'; - - return function tokenString(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\\]/); - if (stream.eat('\\')) { - stream.next(); - if (singleline && stream.eol()) { - return OUTCLASS; - } - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - return ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return OUTCLASS; - }; - } - - function indent(stream, state, type) { - type = type || 'py'; - var indentUnit = 0; - if (type === 'py') { - if (state.scopes[0].type !== 'py') { - state.scopes[0].offset = stream.indentation(); - return; - } - for (var i = 0; i < state.scopes.length; ++i) { - if (state.scopes[i].type === 'py') { - indentUnit = state.scopes[i].offset + conf.indentUnit; - break; - } - } - } else { - indentUnit = stream.column() + stream.current().length; - } - state.scopes.unshift({ - offset: indentUnit, - type: type - }); - } - - function dedent(stream, state, type) { - type = type || 'py'; - if (state.scopes.length == 1) return; - if (state.scopes[0].type === 'py') { - var _indent = stream.indentation(); - var _indent_index = -1; - for (var i = 0; i < state.scopes.length; ++i) { - if (_indent === state.scopes[i].offset) { - _indent_index = i; - break; - } - } - if (_indent_index === -1) { - return true; - } - while (state.scopes[0].offset !== _indent) { - state.scopes.shift(); - } - return false - } else { - if (type === 'py') { - state.scopes[0].offset = stream.indentation(); - return false; - } else { - if (state.scopes[0].type != type) { - return true; - } - state.scopes.shift(); - return false; - } - } - } - - function tokenLexer(stream, state) { - indentInfo = null; - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = state.tokenize(stream, state); - current = stream.current(); - if (style === 'variable' || style === 'builtin') { - return 'variable'; - } else { - return ERRORCLASS; - } - } - - // Handle decorators - if (current === '@') { - style = state.tokenize(stream, state); - current = stream.current(); - if (style === 'variable' - || current === '@staticmethod' - || current === '@classmethod') { - return 'meta'; - } else { - return ERRORCLASS; - } - } - - // Handle scope changes. - if (current === 'pass' || current === 'return') { - state.dedent += 1; - } - if ((current === ':' && !state.lambda && state.scopes[0].type == 'py') - || indentInfo === 'indent') { - indent(stream, state); - } - var delimiter_index = '[({'.indexOf(current); - if (delimiter_index !== -1) { - indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1)); - } - if (indentInfo === 'dedent') { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - delimiter_index = '])}'.indexOf(current); - if (delimiter_index !== -1) { - if (dedent(stream, state, current)) { - return ERRORCLASS; - } - } - if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'py') { - if (state.scopes.length > 1) state.scopes.shift(); - state.dedent -= 1; - } - - return style; - } - - var external = { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - scopes: [{offset:basecolumn || 0, type:'py'}], - lastToken: null, - lambda: false, - dedent: 0 - }; - }, - - token: function(stream, state) { - var style = tokenLexer(stream, state); - - state.lastToken = {style:style, content: stream.current()}; - - if (stream.eol() && stream.lambda) { - state.lambda = false; - } - - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) { - return 0; - } - - return state.scopes[0].offset; - } - - }; - return external; -}); - -CodeMirror.defineMIME("text/x-python", "python"); -CodeMirror.defineMIME("application/x-python", "python"); diff --git a/vendor/assets/javascripts/codemirror/modes/r.js b/vendor/assets/javascripts/codemirror/modes/r.js deleted file mode 100644 index e22cc8e32..000000000 --- a/vendor/assets/javascripts/codemirror/modes/r.js +++ /dev/null @@ -1,142 +0,0 @@ -CodeMirror.defineMode("r", function(config) { - function wordObj(str) { - var words = str.split(" "), res = {}; - for (var i = 0; i < words.length; ++i) res[words[i]] = true; - return res; - } - var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_"); - var builtins = wordObj("list quote bquote eval return call parse deparse"); - var keywords = wordObj("if else repeat while function for in next break"); - var blockkeywords = wordObj("if else repeat while function for"); - var opChars = /[+\-*\/^<>=!&|~$:]/; - var curPunc; - - function tokenBase(stream, state) { - curPunc = null; - var ch = stream.next(); - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } else if (ch == "0" && stream.eat("x")) { - stream.eatWhile(/[\da-f]/i); - return "number"; - } else if (ch == "." && stream.eat(/\d/)) { - stream.match(/\d*(?:e[+\-]?\d+)?/); - return "number"; - } else if (/\d/.test(ch)) { - stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/); - return "number"; - } else if (ch == "'" || ch == '"') { - state.tokenize = tokenString(ch); - return "string"; - } else if (ch == "." && stream.match(/.[.\d]+/)) { - return "keyword"; - } else if (/[\w\.]/.test(ch) && ch != "_") { - stream.eatWhile(/[\w\.]/); - var word = stream.current(); - if (atoms.propertyIsEnumerable(word)) return "atom"; - if (keywords.propertyIsEnumerable(word)) { - if (blockkeywords.propertyIsEnumerable(word)) curPunc = "block"; - return "keyword"; - } - if (builtins.propertyIsEnumerable(word)) return "builtin"; - return "variable"; - } else if (ch == "%") { - if (stream.skipTo("%")) stream.next(); - return "variable-2"; - } else if (ch == "<" && stream.eat("-")) { - return "arrow"; - } else if (ch == "=" && state.ctx.argList) { - return "arg-is"; - } else if (opChars.test(ch)) { - if (ch == "$") return "dollar"; - stream.eatWhile(opChars); - return "operator"; - } else if (/[\(\){}\[\];]/.test(ch)) { - curPunc = ch; - if (ch == ";") return "semi"; - return null; - } else { - return null; - } - } - - function tokenString(quote) { - return function(stream, state) { - if (stream.eat("\\")) { - var ch = stream.next(); - if (ch == "x") stream.match(/^[a-f0-9]{2}/i); - else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next(); - else if (ch == "u") stream.match(/^[a-f0-9]{4}/i); - else if (ch == "U") stream.match(/^[a-f0-9]{8}/i); - else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/); - return "string-2"; - } else { - var next; - while ((next = stream.next()) != null) { - if (next == quote) { state.tokenize = tokenBase; break; } - if (next == "\\") { stream.backUp(1); break; } - } - return "string"; - } - }; - } - - function push(state, type, stream) { - state.ctx = {type: type, - indent: state.indent, - align: null, - column: stream.column(), - prev: state.ctx}; - } - function pop(state) { - state.indent = state.ctx.indent; - state.ctx = state.ctx.prev; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - ctx: {type: "top", - indent: -config.indentUnit, - align: false}, - indent: 0, - afterIdent: false}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.ctx.align == null) state.ctx.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (style != "comment" && state.ctx.align == null) state.ctx.align = true; - - var ctype = state.ctx.type; - if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state); - if (curPunc == "{") push(state, "}", stream); - else if (curPunc == "(") { - push(state, ")", stream); - if (state.afterIdent) state.ctx.argList = true; - } - else if (curPunc == "[") push(state, "]", stream); - else if (curPunc == "block") push(state, "block", stream); - else if (curPunc == ctype) pop(state); - state.afterIdent = style == "variable" || style == "keyword"; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx, - closing = firstChar == ctx.type; - if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indent + (closing ? 0 : config.indentUnit); - } - }; -}); - -CodeMirror.defineMIME("text/x-rsrc", "r"); -CodeMirror.defineMIME("application/x-rsrc", "r"); diff --git a/vendor/assets/javascripts/codemirror/modes/rpm-changes.js b/vendor/assets/javascripts/codemirror/modes/rpm-changes.js deleted file mode 100644 index f0f94684c..000000000 --- a/vendor/assets/javascripts/codemirror/modes/rpm-changes.js +++ /dev/null @@ -1,20 +0,0 @@ -CodeMirror.defineMode("changes", function(config, modeConfig) { - var headerSeperator = /^-+$/; - var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /; - var simpleEmail = /^[\w+.-]+@[\w.-]+/; - - return { - token: function(stream) { - if (stream.sol()) { - if (stream.match(headerSeperator)) { return 'tag'; } - if (stream.match(headerLine)) { return 'tag'; } - } - if (stream.match(simpleEmail)) { return 'string'; } - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-changes", "changes"); -CodeMirror.defineMIME("application/x-rpm-changes", "changes"); diff --git a/vendor/assets/javascripts/codemirror/modes/rpm-spec.js b/vendor/assets/javascripts/codemirror/modes/rpm-spec.js deleted file mode 100644 index 099805d72..000000000 --- a/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +++ /dev/null @@ -1,67 +0,0 @@ -// Quick and dirty spec file highlighting - -CodeMirror.defineMode("spec", function(config, modeConfig) { - var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/; - - var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/; - var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/; - var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros - var control_flow_simple = /^%(else|endif)/; // rpm control flow macros - var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros - - return { - startState: function () { - return { - controlFlow: false, - macroParameters: false, - section: false, - }; - }, - token: function (stream, state) { - var ch = stream.peek(); - if (ch == "#") { stream.skipToEnd(); return "comment"; } - - if (stream.sol()) { - if (stream.match(preamble)) { return "preamble"; } - if (stream.match(section)) { return "section"; } - } - - if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT' - if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}' - - if (stream.match(control_flow_simple)) { return "keyword"; } - if (stream.match(control_flow_complex)) { - state.controlFlow = true; - return "keyword"; - } - if (state.controlFlow) { - if (stream.match(operators)) { return "operator"; } - if (stream.match(/^(\d+)/)) { return "number"; } - if (stream.eol()) { state.controlFlow = false; } - } - - if (stream.match(arch)) { return "number"; } - - // Macros like '%make_install' or '%attr(0775,root,root)' - if (stream.match(/^%[\w]+/)) { - if (stream.match(/^\(/)) { state.macroParameters = true; } - return "macro"; - } - if (state.macroParameters) { - if (stream.match(/^\d+/)) { return "number";} - if (stream.match(/^\)/)) { - state.macroParameters = false; - return "macro"; - } - } - if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}' - - //TODO: Include bash script sub-parser (CodeMirror supports that) - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-spec", "spec"); -CodeMirror.defineMIME("application/x-rpm-spec", "spec"); diff --git a/vendor/assets/javascripts/codemirror/modes/rst.js b/vendor/assets/javascripts/codemirror/modes/rst.js deleted file mode 100644 index 526f37cd3..000000000 --- a/vendor/assets/javascripts/codemirror/modes/rst.js +++ /dev/null @@ -1,327 +0,0 @@ -CodeMirror.defineMode('rst', function(config, options) { - function setState(state, fn, ctx) { - state.fn = fn; - setCtx(state, ctx); - } - - function setCtx(state, ctx) { - state.ctx = ctx || {}; - } - - function setNormal(state, ch) { - if (ch && (typeof ch !== 'string')) { - var str = ch.current(); - ch = str[str.length-1]; - } - - setState(state, normal, {back: ch}); - } - - function hasMode(mode) { - if (mode) { - var modes = CodeMirror.listModes(); - - for (var i in modes) { - if (modes[i] == mode) { - return true; - } - } - } - - return false; - } - - function getMode(mode) { - if (hasMode(mode)) { - return CodeMirror.getMode(config, mode); - } else { - return null; - } - } - - var verbatimMode = getMode(options.verbatim); - var pythonMode = getMode('python'); - - var reSection = /^[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]/; - var reDirective = /^\s*\w([-:.\w]*\w)?::(\s|$)/; - var reHyperlink = /^\s*_[\w-]+:(\s|$)/; - var reFootnote = /^\s*\[(\d+|#)\](\s|$)/; - var reCitation = /^\s*\[[A-Za-z][\w-]*\](\s|$)/; - var reFootnoteRef = /^\[(\d+|#)\]_/; - var reCitationRef = /^\[[A-Za-z][\w-]*\]_/; - var reDirectiveMarker = /^\.\.(\s|$)/; - var reVerbatimMarker = /^::\s*$/; - var rePreInline = /^[-\s"([{/:.,;!?\\_]/; - var reEnumeratedList = /^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/; - var reBulletedList = /^\s*[-\+\*]\s/; - var reExamples = /^\s+(>>>|In \[\d+\]:)\s/; - - function normal(stream, state) { - var ch, sol, i; - - if (stream.eat(/\\/)) { - ch = stream.next(); - setNormal(state, ch); - return null; - } - - sol = stream.sol(); - - if (sol && (ch = stream.eat(reSection))) { - for (i = 0; stream.eat(ch); i++); - - if (i >= 3 && stream.match(/^\s*$/)) { - setNormal(state, null); - return 'header'; - } else { - stream.backUp(i + 1); - } - } - - if (sol && stream.match(reDirectiveMarker)) { - if (!stream.eol()) { - setState(state, directive); - } - return 'meta'; - } - - if (stream.match(reVerbatimMarker)) { - if (!verbatimMode) { - setState(state, verbatim); - } else { - var mode = verbatimMode; - - setState(state, verbatim, { - mode: mode, - local: mode.startState() - }); - } - return 'meta'; - } - - if (sol && stream.match(reExamples, false)) { - if (!pythonMode) { - setState(state, verbatim); - return 'meta'; - } else { - var mode = pythonMode; - - setState(state, verbatim, { - mode: mode, - local: mode.startState() - }); - - return null; - } - } - - function testBackward(re) { - return sol || !state.ctx.back || re.test(state.ctx.back); - } - - function testForward(re) { - return stream.eol() || stream.match(re, false); - } - - function testInline(re) { - return stream.match(re) && testBackward(/\W/) && testForward(/\W/); - } - - if (testInline(reFootnoteRef)) { - setNormal(state, stream); - return 'footnote'; - } - - if (testInline(reCitationRef)) { - setNormal(state, stream); - return 'citation'; - } - - ch = stream.next(); - - if (testBackward(rePreInline)) { - if ((ch === ':' || ch === '|') && stream.eat(/\S/)) { - var token; - - if (ch === ':') { - token = 'builtin'; - } else { - token = 'atom'; - } - - setState(state, inline, { - ch: ch, - wide: false, - prev: null, - token: token - }); - - return token; - } - - if (ch === '*' || ch === '`') { - var orig = ch, - wide = false; - - ch = stream.next(); - - if (ch == orig) { - wide = true; - ch = stream.next(); - } - - if (ch && !/\s/.test(ch)) { - var token; - - if (orig === '*') { - token = wide ? 'strong' : 'em'; - } else { - token = wide ? 'string' : 'string-2'; - } - - setState(state, inline, { - ch: orig, // inline() has to know what to search for - wide: wide, // are we looking for `ch` or `chch` - prev: null, // terminator must not be preceeded with whitespace - token: token // I don't want to recompute this all the time - }); - - return token; - } - } - } - - setNormal(state, ch); - return null; - } - - function inline(stream, state) { - var ch = stream.next(), - token = state.ctx.token; - - function finish(ch) { - state.ctx.prev = ch; - return token; - } - - if (ch != state.ctx.ch) { - return finish(ch); - } - - if (/\s/.test(state.ctx.prev)) { - return finish(ch); - } - - if (state.ctx.wide) { - ch = stream.next(); - - if (ch != state.ctx.ch) { - return finish(ch); - } - } - - if (!stream.eol() && !rePostInline.test(stream.peek())) { - if (state.ctx.wide) { - stream.backUp(1); - } - - return finish(ch); - } - - setState(state, normal); - setNormal(state, ch); - - return token; - } - - function directive(stream, state) { - var token = null; - - if (stream.match(reDirective)) { - token = 'attribute'; - } else if (stream.match(reHyperlink)) { - token = 'link'; - } else if (stream.match(reFootnote)) { - token = 'quote'; - } else if (stream.match(reCitation)) { - token = 'quote'; - } else { - stream.eatSpace(); - - if (stream.eol()) { - setNormal(state, stream); - return null; - } else { - stream.skipToEnd(); - setState(state, comment); - return 'comment'; - } - } - - // FIXME this is unreachable - setState(state, body, {start: true}); - return token; - } - - function body(stream, state) { - var token = 'body'; - - if (!state.ctx.start || stream.sol()) { - return block(stream, state, token); - } - - stream.skipToEnd(); - setCtx(state); - - return token; - } - - function comment(stream, state) { - return block(stream, state, 'comment'); - } - - function verbatim(stream, state) { - if (!verbatimMode) { - return block(stream, state, 'meta'); - } else { - if (stream.sol()) { - if (!stream.eatSpace()) { - setNormal(state, stream); - } - - return null; - } - - return verbatimMode.token(stream, state.ctx.local); - } - } - - function block(stream, state, token) { - if (stream.eol() || stream.eatSpace()) { - stream.skipToEnd(); - return token; - } else { - setNormal(state, stream); - return null; - } - } - - return { - startState: function() { - return {fn: normal, ctx: {}}; - }, - - copyState: function(state) { - return {fn: state.fn, ctx: state.ctx}; - }, - - token: function(stream, state) { - var token = state.fn(stream, state); - return token; - } - }; -}); - -CodeMirror.defineMIME("text/x-rst", "rst"); -CodeMirror.defineMIME("application/x-rst", "rst"); diff --git a/vendor/assets/javascripts/codemirror/modes/ruby.js b/vendor/assets/javascripts/codemirror/modes/ruby.js deleted file mode 100644 index 1b42ad9ae..000000000 --- a/vendor/assets/javascripts/codemirror/modes/ruby.js +++ /dev/null @@ -1,201 +0,0 @@ -CodeMirror.defineMode("ruby", function(config, parserConfig) { - function wordObj(words) { - var o = {}; - for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true; - return o; - } - var keywords = wordObj([ - "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else", - "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or", - "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless", - "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc", - "caller", "lambda", "proc", "public", "protected", "private", "require", "load", - "require_relative", "extend", "autoload" - ]); - var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then", - "catch", "loop", "proc", "begin"]); - var dedentWords = wordObj(["end", "until"]); - var matching = {"[": "]", "{": "}", "(": ")"}; - var curPunc; - - function chain(newtok, stream, state) { - state.tokenize.push(newtok); - return newtok(stream, state); - } - - function tokenBase(stream, state) { - curPunc = null; - if (stream.sol() && stream.match("=begin") && stream.eol()) { - state.tokenize.push(readBlockComment); - return "comment"; - } - if (stream.eatSpace()) return null; - var ch = stream.next(); - if (ch == "`" || ch == "'" || ch == '"' || - (ch == "/" && !stream.eol() && stream.peek() != " ")) { - return chain(readQuoted(ch, "string", ch == '"'), stream, state); - } else if (ch == "%") { - var style, embed = false; - if (stream.eat("s")) style = "atom"; - else if (stream.eat(/[WQ]/)) { style = "string"; embed = true; } - else if (stream.eat(/[wxqr]/)) style = "string"; - var delim = stream.eat(/[^\w\s]/); - if (!delim) return "operator"; - if (matching.propertyIsEnumerable(delim)) delim = matching[delim]; - return chain(readQuoted(delim, style, embed, true), stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } else if (ch == "<" && stream.eat("<")) { - stream.eat("-"); - stream.eat(/[\'\"\`]/); - var match = stream.match(/^\w+/); - stream.eat(/[\'\"\`]/); - if (match) return chain(readHereDoc(match[0]), stream, state); - return null; - } else if (ch == "0") { - if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/); - else if (stream.eat("b")) stream.eatWhile(/[01]/); - else stream.eatWhile(/[0-7]/); - return "number"; - } else if (/\d/.test(ch)) { - stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/); - return "number"; - } else if (ch == "?") { - while (stream.match(/^\\[CM]-/)) {} - if (stream.eat("\\")) stream.eatWhile(/\w/); - else stream.next(); - return "string"; - } else if (ch == ":") { - if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state); - if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state); - stream.eatWhile(/[\w\?]/); - return "atom"; - } else if (ch == "@") { - stream.eat("@"); - stream.eatWhile(/[\w\?]/); - return "variable-2"; - } else if (ch == "$") { - stream.next(); - stream.eatWhile(/[\w\?]/); - return "variable-3"; - } else if (/\w/.test(ch)) { - stream.eatWhile(/[\w\?]/); - if (stream.eat(":")) return "atom"; - return "ident"; - } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) { - curPunc = "|"; - return null; - } else if (/[\(\)\[\]{}\\;]/.test(ch)) { - curPunc = ch; - return null; - } else if (ch == "-" && stream.eat(">")) { - return "arrow"; - } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) { - stream.eatWhile(/[=+\-\/*:\.^%<>~|]/); - return "operator"; - } else { - return null; - } - } - - function tokenBaseUntilBrace() { - var depth = 1; - return function(stream, state) { - if (stream.peek() == "}") { - depth--; - if (depth == 0) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } - } else if (stream.peek() == "{") { - depth++; - } - return tokenBase(stream, state); - }; - } - function readQuoted(quote, style, embed, unescaped) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && (unescaped || !escaped)) { - state.tokenize.pop(); - break; - } - if (embed && ch == "#" && !escaped && stream.eat("{")) { - state.tokenize.push(tokenBaseUntilBrace(arguments.callee)); - break; - } - escaped = !escaped && ch == "\\"; - } - return style; - }; - } - function readHereDoc(phrase) { - return function(stream, state) { - if (stream.match(phrase)) state.tokenize.pop(); - else stream.skipToEnd(); - return "string"; - }; - } - function readBlockComment(stream, state) { - if (stream.sol() && stream.match("=end") && stream.eol()) - state.tokenize.pop(); - stream.skipToEnd(); - return "comment"; - } - - return { - startState: function() { - return {tokenize: [tokenBase], - indented: 0, - context: {type: "top", indented: -config.indentUnit}, - continuedLine: false, - lastTok: null, - varList: false}; - }, - - token: function(stream, state) { - if (stream.sol()) state.indented = stream.indentation(); - var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype; - if (style == "ident") { - var word = stream.current(); - style = keywords.propertyIsEnumerable(stream.current()) ? "keyword" - : /^[A-Z]/.test(word) ? "tag" - : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def" - : "variable"; - if (indentWords.propertyIsEnumerable(word)) kwtype = "indent"; - else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent"; - else if ((word == "if" || word == "unless") && stream.column() == stream.indentation()) - kwtype = "indent"; - } - if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style; - if (curPunc == "|") state.varList = !state.varList; - - if (kwtype == "indent" || /[\(\[\{]/.test(curPunc)) - state.context = {prev: state.context, type: curPunc || style, indented: state.indented}; - else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev) - state.context = state.context.prev; - - if (stream.eol()) - state.continuedLine = (curPunc == "\\" || style == "operator"); - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0); - var ct = state.context; - var closing = ct.type == matching[firstChar] || - ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter); - return ct.indented + (closing ? 0 : config.indentUnit) + - (state.continuedLine ? config.indentUnit : 0); - }, - electricChars: "}de" // enD and rescuE - - }; -}); - -CodeMirror.defineMIME("text/x-ruby", "ruby"); -CodeMirror.defineMIME("application/x-ruby", "ruby"); - diff --git a/vendor/assets/javascripts/codemirror/modes/rust.js b/vendor/assets/javascripts/codemirror/modes/rust.js deleted file mode 100644 index 3efb8e76d..000000000 --- a/vendor/assets/javascripts/codemirror/modes/rust.js +++ /dev/null @@ -1,433 +0,0 @@ -CodeMirror.defineMode("rust", function() { - var indentUnit = 4, altIndentUnit = 2; - var valKeywords = { - "if": "if-style", "while": "if-style", "else": "else-style", - "do": "else-style", "ret": "else-style", "fail": "else-style", - "break": "atom", "cont": "atom", "const": "let", "resource": "fn", - "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface", - "impl": "impl", "type": "type", "enum": "enum", "mod": "mod", - "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op", - "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style", - "export": "else-style", "copy": "op", "log": "op", "log_err": "op", - "use": "op", "bind": "op", "self": "atom" - }; - var typeKeywords = function() { - var keywords = {"fn": "fn", "block": "fn", "obj": "obj"}; - var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" "); - for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom"; - return keywords; - }(); - var operatorChar = /[+\-*&%=<>!?|\.@]/; - - // Tokenizer - - // Used as scratch variable to communicate multiple values without - // consing up tons of objects. - var tcat, content; - function r(tc, style) { - tcat = tc; - return style; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"') { - state.tokenize = tokenString; - return state.tokenize(stream, state); - } - if (ch == "'") { - tcat = "atom"; - if (stream.eat("\\")) { - if (stream.skipTo("'")) { stream.next(); return "string"; } - else { return "error"; } - } else { - stream.next(); - return stream.eat("'") ? "string" : "error"; - } - } - if (ch == "/") { - if (stream.eat("/")) { stream.skipToEnd(); return "comment"; } - if (stream.eat("*")) { - state.tokenize = tokenComment(1); - return state.tokenize(stream, state); - } - } - if (ch == "#") { - if (stream.eat("[")) { tcat = "open-attr"; return null; } - stream.eatWhile(/\w/); - return r("macro", "meta"); - } - if (ch == ":" && stream.match(":<")) { - return r("op", null); - } - if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) { - var flp = false; - if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) { - stream.eatWhile(/\d/); - if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); } - if (stream.match(/^e[+\-]?\d+/i)) { flp = true; } - } - if (flp) stream.match(/^f(?:32|64)/); - else stream.match(/^[ui](?:8|16|32|64)/); - return r("atom", "number"); - } - if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null); - if (ch == "-" && stream.eat(">")) return r("->", null); - if (ch.match(operatorChar)) { - stream.eatWhile(operatorChar); - return r("op", null); - } - stream.eatWhile(/\w/); - content = stream.current(); - if (stream.match(/^::\w/)) { - stream.backUp(1); - return r("prefix", "variable-2"); - } - if (state.keywords.propertyIsEnumerable(content)) - return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword"); - return r("name", "variable"); - } - - function tokenString(stream, state) { - var ch, escaped = false; - while (ch = stream.next()) { - if (ch == '"' && !escaped) { - state.tokenize = tokenBase; - return r("atom", "string"); - } - escaped = !escaped && ch == "\\"; - } - // Hack to not confuse the parser when a string is split in - // pieces. - return r("op", "string"); - } - - function tokenComment(depth) { - return function(stream, state) { - var lastCh = null, ch; - while (ch = stream.next()) { - if (ch == "/" && lastCh == "*") { - if (depth == 1) { - state.tokenize = tokenBase; - break; - } else { - state.tokenize = tokenComment(depth - 1); - return state.tokenize(stream, state); - } - } - if (ch == "*" && lastCh == "/") { - state.tokenize = tokenComment(depth + 1); - return state.tokenize(stream, state); - } - lastCh = ch; - } - return "comment"; - }; - } - - // Parser - - var cx = {state: null, stream: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - - function pushlex(type, info) { - var result = function() { - var state = cx.state; - state.lexical = {indented: state.indented, column: cx.stream.column(), - type: type, prev: state.lexical, info: info}; - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - function typecx() { cx.state.keywords = typeKeywords; } - function valcx() { cx.state.keywords = valKeywords; } - poplex.lex = typecx.lex = valcx.lex = true; - - function commasep(comb, end) { - function more(type) { - if (type == ",") return cont(comb, more); - if (type == end) return cont(); - return cont(more); - } - return function(type) { - if (type == end) return cont(); - return pass(comb, more); - }; - } - - function stat_of(comb, tag) { - return cont(pushlex("stat", tag), comb, poplex, block); - } - function block(type) { - if (type == "}") return cont(); - if (type == "let") return stat_of(letdef1, "let"); - if (type == "fn") return stat_of(fndef); - if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block); - if (type == "enum") return stat_of(enumdef); - if (type == "mod") return stat_of(mod); - if (type == "iface") return stat_of(iface); - if (type == "impl") return stat_of(impl); - if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex); - if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block); - return pass(pushlex("stat"), expression, poplex, endstatement, block); - } - function endstatement(type) { - if (type == ";") return cont(); - return pass(); - } - function expression(type) { - if (type == "atom" || type == "name") return cont(maybeop); - if (type == "{") return cont(pushlex("}"), exprbrace, poplex); - if (type.match(/[\[\(]/)) return matchBrackets(type, expression); - if (type.match(/[\]\)\};,]/)) return pass(); - if (type == "if-style") return cont(expression, expression); - if (type == "else-style" || type == "op") return cont(expression); - if (type == "for") return cont(pattern, maybetype, inop, expression, expression); - if (type == "alt") return cont(expression, altbody); - if (type == "fn") return cont(fndef); - if (type == "macro") return cont(macro); - return cont(); - } - function maybeop(type) { - if (content == ".") return cont(maybeprop); - if (content == "::<"){return cont(typarams, maybeop);} - if (type == "op" || content == ":") return cont(expression); - if (type == "(" || type == "[") return matchBrackets(type, expression); - return pass(); - } - function maybeprop(type) { - if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);} - return pass(expression); - } - function exprbrace(type) { - if (type == "op") { - if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block); - if (content == "||") return cont(poplex, pushlex("}", "block"), block); - } - if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":" - && !cx.stream.match("::", false))) - return pass(record_of(expression)); - return pass(block); - } - function record_of(comb) { - function ro(type) { - if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);} - if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);} - if (type == ":") return cont(comb, ro); - if (type == "}") return cont(); - return cont(ro); - } - return ro; - } - function blockvars(type) { - if (type == "name") {cx.marked = "def"; return cont(blockvars);} - if (type == "op" && content == "|") return cont(); - return cont(blockvars); - } - - function letdef1(type) { - if (type.match(/[\]\)\};]/)) return cont(); - if (content == "=") return cont(expression, letdef2); - if (type == ",") return cont(letdef1); - return pass(pattern, maybetype, letdef1); - } - function letdef2(type) { - if (type.match(/[\]\)\};,]/)) return pass(letdef1); - else return pass(expression, letdef2); - } - function maybetype(type) { - if (type == ":") return cont(typecx, rtype, valcx); - return pass(); - } - function inop(type) { - if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();} - return pass(); - } - function fndef(type) { - if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);} - if (type == "name") {cx.marked = "def"; return cont(fndef);} - if (content == "<") return cont(typarams, fndef); - if (type == "{") return pass(expression); - if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef); - if (type == "->") return cont(typecx, rtype, valcx, fndef); - if (type == ";") return cont(); - return cont(fndef); - } - function tydef(type) { - if (type == "name") {cx.marked = "def"; return cont(tydef);} - if (content == "<") return cont(typarams, tydef); - if (content == "=") return cont(typecx, rtype, valcx); - return cont(tydef); - } - function enumdef(type) { - if (type == "name") {cx.marked = "def"; return cont(enumdef);} - if (content == "<") return cont(typarams, enumdef); - if (content == "=") return cont(typecx, rtype, valcx, endstatement); - if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex); - return cont(enumdef); - } - function enumblock(type) { - if (type == "}") return cont(); - if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock); - if (content.match(/^\w+$/)) cx.marked = "def"; - return cont(enumblock); - } - function mod(type) { - if (type == "name") {cx.marked = "def"; return cont(mod);} - if (type == "{") return cont(pushlex("}"), block, poplex); - return pass(); - } - function iface(type) { - if (type == "name") {cx.marked = "def"; return cont(iface);} - if (content == "<") return cont(typarams, iface); - if (type == "{") return cont(pushlex("}"), block, poplex); - return pass(); - } - function impl(type) { - if (content == "<") return cont(typarams, impl); - if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);} - if (type == "name") {cx.marked = "def"; return cont(impl);} - if (type == "{") return cont(pushlex("}"), block, poplex); - return pass(); - } - function typarams(type) { - if (content == ">") return cont(); - if (content == ",") return cont(typarams); - if (content == ":") return cont(rtype, typarams); - return pass(rtype, typarams); - } - function argdef(type) { - if (type == "name") {cx.marked = "def"; return cont(argdef);} - if (type == ":") return cont(typecx, rtype, valcx); - return pass(); - } - function rtype(type) { - if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); } - if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);} - if (type == "atom") return cont(rtypemaybeparam); - if (type == "op" || type == "obj") return cont(rtype); - if (type == "fn") return cont(fntype); - if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex); - return matchBrackets(type, rtype); - } - function rtypemaybeparam(type) { - if (content == "<") return cont(typarams); - return pass(); - } - function fntype(type) { - if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype); - if (type == "->") return cont(rtype); - return pass(); - } - function pattern(type) { - if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);} - if (type == "atom") return cont(patternmaybeop); - if (type == "op") return cont(pattern); - if (type.match(/[\]\)\};,]/)) return pass(); - return matchBrackets(type, pattern); - } - function patternmaybeop(type) { - if (type == "op" && content == ".") return cont(); - if (content == "to") {cx.marked = "keyword"; return cont(pattern);} - else return pass(); - } - function altbody(type) { - if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex); - return pass(); - } - function altblock1(type) { - if (type == "}") return cont(); - if (type == "|") return cont(altblock1); - if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);} - if (type.match(/[\]\);,]/)) return cont(altblock1); - return pass(pattern, altblock2); - } - function altblock2(type) { - if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1); - else return pass(altblock1); - } - - function macro(type) { - if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression); - return pass(); - } - function matchBrackets(type, comb) { - if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex); - if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex); - if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex); - return cont(); - } - - function parse(state, stream, style) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; - - while (true) { - var combinator = cc.length ? cc.pop() : block; - if (combinator(tcat)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - return cx.marked || style; - } - } - } - - return { - startState: function() { - return { - tokenize: tokenBase, - cc: [], - lexical: {indented: -indentUnit, column: 0, type: "top", align: false}, - keywords: valKeywords, - indented: 0 - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - tcat = content = null; - var style = state.tokenize(stream, state); - if (style == "comment") return style; - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - if (tcat == "prefix") return style; - if (!content) content = stream.current(); - return parse(state, stream, style); - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, - type = lexical.type, closing = firstChar == type; - if (type == "stat") return lexical.indented + indentUnit; - if (lexical.align) return lexical.column + (closing ? 0 : 1); - return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit)); - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-rustsrc", "rust"); -CodeMirror.defineMIME("application/x-rustsrc", "rust"); diff --git a/vendor/assets/javascripts/codemirror/modes/scheme.js b/vendor/assets/javascripts/codemirror/modes/scheme.js deleted file mode 100644 index 04437757a..000000000 --- a/vendor/assets/javascripts/codemirror/modes/scheme.js +++ /dev/null @@ -1,203 +0,0 @@ -/** - * Author: Koh Zi Han, based on implementation by Koh Zi Chun - */ -CodeMirror.defineMode("scheme", function (config, mode) { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword"; - var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1; - - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?"); - var indentKeys = makeKeywords("define let letrec let* lambda"); - - - function stateStack(indent, type, prev) { // represents a state stack object - this.indent = indent; - this.type = type; - this.prev = prev; - } - - function pushStack(state, indent, type) { - state.indentStack = new stateStack(indent, type, state.indentStack); - } - - function popStack(state) { - state.indentStack = state.indentStack.prev; - } - - /** - * Scheme numbers are complicated unfortunately. - * Checks if we're looking at a number, which might be possibly a fraction. - * Also checks that it is not part of a longer identifier. Returns true/false accordingly. - */ - function isNumber(ch, stream){ - if(/[0-9]/.exec(ch) != null){ - stream.eatWhile(/[0-9]/); - stream.eat(/\//); - stream.eatWhile(/[0-9]/); - if (stream.eol() || !(/[a-zA-Z\-\_\/]/.exec(stream.peek()))) return true; - stream.backUp(stream.current().length - 1); // undo all the eating - } - return false; - } - - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false, - sExprComment: false - }; - }, - - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = stream.indentation(); - } - - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - - switch(state.mode){ - case "string": // multi-line string parsing mode - var next, escaped = false; - while ((next = stream.next()) != null) { - if (next == "\"" && !escaped) { - - state.mode = false; - break; - } - escaped = !escaped && next == "\\"; - } - returnType = STRING; // continue on in scheme-string mode - break; - case "comment": // comment parsing mode - var next, maybeEnd = false; - while ((next = stream.next()) != null) { - if (next == "#" && maybeEnd) { - - state.mode = false; - break; - } - maybeEnd = (next == "|"); - } - returnType = COMMENT; - break; - case "s-expr-comment": // s-expr commenting mode - state.mode = false; - if(stream.peek() == "(" || stream.peek() == "["){ - // actually start scheme s-expr commenting mode - state.sExprComment = 0; - }else{ - // if not we just comment the entire of the next token - stream.eatWhile(/[^/s]/); // eat non spaces - returnType = COMMENT; - break; - } - default: // default parsing mode - var ch = stream.next(); - - if (ch == "\"") { - state.mode = "string"; - returnType = STRING; - - } else if (ch == "'") { - returnType = ATOM; - } else if (ch == '#') { - if (stream.eat("|")) { // Multi-line comment - state.mode = "comment"; // toggle to comment mode - returnType = COMMENT; - } else if (stream.eat(/[tf]/)) { // #t/#f (atom) - returnType = ATOM; - } else if (stream.eat(';')) { // S-Expr comment - state.mode = "s-expr-comment"; - returnType = COMMENT; - } - - } else if (ch == ";") { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (ch == "-"){ - - if(!isNaN(parseInt(stream.peek()))){ - stream.eatWhile(/[\/0-9]/); - returnType = NUMBER; - }else{ - returnType = null; - } - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else if (ch == "(" || ch == "[") { - var keyWord = ''; var indentTemp = stream.column(); - /** - Either - (indent-word .. - (non-indent-word .. - (;something else, bracket, etc. - */ - - while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) { - keyWord += letter; - } - - if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word - - pushStack(state, indentTemp + INDENT_WORD_SKIP, ch); - } else { // non-indent word - // we continue eating the spaces - stream.eatSpace(); - if (stream.eol() || stream.peek() == ";") { - // nothing significant after - // we restart indentation 1 space after - pushStack(state, indentTemp + 1, ch); - } else { - pushStack(state, indentTemp + stream.current().length, ch); // else we match - } - } - stream.backUp(stream.current().length - 1); // undo all the eating - - if(typeof state.sExprComment == "number") state.sExprComment++; - - returnType = BRACKET; - } else if (ch == ")" || ch == "]") { - returnType = BRACKET; - if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) { - popStack(state); - - if(typeof state.sExprComment == "number"){ - if(--state.sExprComment == 0){ - returnType = COMMENT; // final closing bracket - state.sExprComment = false; // turn off s-expr commenting mode - } - } - } - } else { - stream.eatWhile(/[\w\$_\-]/); - - if (keywords && keywords.propertyIsEnumerable(stream.current())) { - returnType = BUILTIN; - }else returnType = null; - } - } - return (typeof state.sExprComment == "number") ? COMMENT : returnType; - }, - - indent: function (state, textAfter) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - } - }; -}); - -CodeMirror.defineMIME("text/x-scheme", "scheme"); -CodeMirror.defineMIME("application/x-scheme", "scheme"); diff --git a/vendor/assets/javascripts/codemirror/modes/shell.js b/vendor/assets/javascripts/codemirror/modes/shell.js deleted file mode 100644 index e48ce5368..000000000 --- a/vendor/assets/javascripts/codemirror/modes/shell.js +++ /dev/null @@ -1,119 +0,0 @@ -CodeMirror.defineMode('shell', function(config) { - - var words = {}; - function define(style, string) { - var split = string.split(' '); - for(var i = 0; i < split.length; i++) { - words[split[i]] = style; - } - }; - - // Atoms - define('atom', 'true false'); - - // Keywords - define('keyword', 'if then do else elif while until for in esac fi fin ' + - 'fil done exit set unset export function'); - - // Commands - define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' + - 'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' + - 'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' + - 'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' + - 'touch vi vim wall wc wget who write yes zsh'); - - function tokenBase(stream, state) { - - var sol = stream.sol(); - var ch = stream.next(); - - if (ch === '\'' || ch === '"' || ch === '`') { - state.tokens.unshift(tokenString(ch)); - return tokenize(stream, state); - } - if (ch === '#') { - if (sol && stream.eat('!')) { - stream.skipToEnd(); - return 'meta'; // 'comment'? - } - stream.skipToEnd(); - return 'comment'; - } - if (ch === '$') { - state.tokens.unshift(tokenDollar); - return tokenize(stream, state); - } - if (ch === '+' || ch === '=') { - return 'operator'; - } - if (ch === '-') { - stream.eat('-'); - stream.eatWhile(/\w/); - return 'attribute'; - } - if (/\d/.test(ch)) { - stream.eatWhile(/\d/); - if(!/\w/.test(stream.peek())) { - return 'number'; - } - } - stream.eatWhile(/\w/); - var cur = stream.current(); - if (stream.peek() === '=' && /\w+/.test(cur)) return 'def'; - return words.hasOwnProperty(cur) ? words[cur] : null; - } - - function tokenString(quote) { - return function(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === quote && !escaped) { - end = true; - break; - } - if (next === '$' && !escaped && quote !== '\'') { - escaped = true; - stream.backUp(1); - state.tokens.unshift(tokenDollar); - break; - } - escaped = !escaped && next === '\\'; - } - if (end || !escaped) { - state.tokens.shift(); - } - return (quote === '`' || quote === ')' ? 'quote' : 'string'); - }; - }; - - var tokenDollar = function(stream, state) { - if (state.tokens.length > 1) stream.eat('$'); - var ch = stream.next(), hungry = /\w/; - if (ch === '{') hungry = /[^}]/; - if (ch === '(') { - state.tokens[0] = tokenString(')'); - return tokenize(stream, state); - } - if (!/\d/.test(ch)) { - stream.eatWhile(hungry); - stream.eat('}'); - } - state.tokens.shift(); - return 'def'; - }; - - function tokenize(stream, state) { - return (state.tokens[0] || tokenBase) (stream, state); - }; - - return { - startState: function() {return {tokens:[]};}, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME('text/x-sh', 'shell'); -CodeMirror.defineMIME('application/x-sh', 'shell'); diff --git a/vendor/assets/javascripts/codemirror/modes/smalltalk.js b/vendor/assets/javascripts/codemirror/modes/smalltalk.js deleted file mode 100644 index c8db72d09..000000000 --- a/vendor/assets/javascripts/codemirror/modes/smalltalk.js +++ /dev/null @@ -1,140 +0,0 @@ -CodeMirror.defineMode('smalltalk', function(config, modeConfig) { - - var specialChars = /[+\-/\\*~<>=@%|&?!.:;^]/; - var keywords = /true|false|nil|self|super|thisContext/; - - var Context = function(tokenizer, parent) { - this.next = tokenizer; - this.parent = parent; - }; - - var Token = function(name, context, eos) { - this.name = name; - this.context = context; - this.eos = eos; - }; - - var State = function() { - this.context = new Context(next, null); - this.expectVariable = true; - this.indentation = 0; - this.userIndentationDelta = 0; - }; - - State.prototype.userIndent = function(indentation) { - this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0; - }; - - var next = function(stream, context, state) { - var token = new Token(null, context, false); - var char = stream.next(); - - if (char === '"') { - token = nextComment(stream, new Context(nextComment, context)); - - } else if (char === '\'') { - token = nextString(stream, new Context(nextString, context)); - - } else if (char === '#') { - stream.eatWhile(/[^ .]/); - token.name = 'string-2'; - - } else if (char === '$') { - stream.eatWhile(/[^ ]/); - token.name = 'string-2'; - - } else if (char === '|' && state.expectVariable) { - token.context = new Context(nextTemporaries, context); - - } else if (/[\[\]{}()]/.test(char)) { - token.name = 'bracket'; - token.eos = /[\[{(]/.test(char); - - if (char === '[') { - state.indentation++; - } else if (char === ']') { - state.indentation = Math.max(0, state.indentation - 1); - } - - } else if (specialChars.test(char)) { - stream.eatWhile(specialChars); - token.name = 'operator'; - token.eos = char !== ';'; // ; cascaded message expression - - } else if (/\d/.test(char)) { - stream.eatWhile(/[\w\d]/); - token.name = 'number' - - } else if (/[\w_]/.test(char)) { - stream.eatWhile(/[\w\d_]/); - token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null; - - } else { - token.eos = state.expectVariable; - } - - return token; - }; - - var nextComment = function(stream, context) { - stream.eatWhile(/[^"]/); - return new Token('comment', stream.eat('"') ? context.parent : context, true); - }; - - var nextString = function(stream, context) { - stream.eatWhile(/[^']/); - return new Token('string', stream.eat('\'') ? context.parent : context, false); - }; - - var nextTemporaries = function(stream, context, state) { - var token = new Token(null, context, false); - var char = stream.next(); - - if (char === '|') { - token.context = context.parent; - token.eos = true; - - } else { - stream.eatWhile(/[^|]/); - token.name = 'variable'; - } - - return token; - } - - return { - startState: function() { - return new State; - }, - - token: function(stream, state) { - state.userIndent(stream.indentation()); - - if (stream.eatSpace()) { - return null; - } - - var token = state.context.next(stream, state.context, state); - state.context = token.context; - state.expectVariable = token.eos; - - state.lastToken = token; - return token.name; - }, - - blankLine: function(state) { - state.userIndent(0); - }, - - indent: function(state, textAfter) { - var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta; - return (state.indentation + i) * config.indentUnit; - }, - - electricChars: ']' - }; - -}); - -CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'}); -CodeMirror.defineMIME('application/x-stsrc', {name: 'smalltalk'}); diff --git a/vendor/assets/javascripts/codemirror/modes/sparql.js b/vendor/assets/javascripts/codemirror/modes/sparql.js deleted file mode 100644 index ceb52942f..000000000 --- a/vendor/assets/javascripts/codemirror/modes/sparql.js +++ /dev/null @@ -1,143 +0,0 @@ -CodeMirror.defineMode("sparql", function(config) { - var indentUnit = config.indentUnit; - var curPunc; - - function wordRegexp(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", - "isblank", "isliteral", "union", "a"]); - var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe", - "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional", - "graph", "by", "asc", "desc"]); - var operatorChars = /[*+\-<>=&|]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - curPunc = null; - if (ch == "$" || ch == "?") { - stream.match(/^[\w\d]*/); - return "variable-2"; - } - else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { - stream.match(/^[^\s\u00a0>]*>?/); - return "atom"; - } - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } - else if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return null; - } - else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return null; - } - else if (ch == ":") { - stream.eatWhile(/[\w\d\._\-]/); - return "atom"; - } - else { - stream.eatWhile(/[_\w\d]/); - if (stream.eat(":")) { - stream.eatWhile(/[\w\d_\-]/); - return "atom"; - } - var word = stream.current(), type; - if (ops.test(word)) - return null; - else if (keywords.test(word)) - return "keyword"; - else - return "variable"; - } - } - - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - - function pushContext(state, type, col) { - state.context = {prev: state.context, indent: state.indent, col: col, type: type}; - } - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - context: null, - indent: 0, - col: 0}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) state.context.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { - state.context.align = true; - } - - if (curPunc == "(") pushContext(state, ")", stream.column()); - else if (curPunc == "[") pushContext(state, "]", stream.column()); - else if (curPunc == "{") pushContext(state, "}", stream.column()); - else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type == "pattern") popContext(state); - if (state.context && curPunc == state.context.type) popContext(state); - } - else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); - else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) - pushContext(state, "pattern", stream.column()); - else if (state.context.type == "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - - return style; - }, - - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) - while (context && context.type == "pattern") context = context.prev; - - var closing = context && firstChar == context.type; - if (!context) - return 0; - else if (context.type == "pattern") - return context.col; - else if (context.align) - return context.col + (closing ? 0 : 1); - else - return context.indent + (closing ? 0 : indentUnit); - } - }; -}); - -CodeMirror.defineMIME("application/x-sparql-query", "sparql"); diff --git a/vendor/assets/javascripts/codemirror/modes/stex.js b/vendor/assets/javascripts/codemirror/modes/stex.js deleted file mode 100644 index 763a8dc50..000000000 --- a/vendor/assets/javascripts/codemirror/modes/stex.js +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de) - * Licence: MIT - */ - -CodeMirror.defineMode("stex", function(cmCfg, modeCfg) -{ - function pushCommand(state, command) { - state.cmdState.push(command); - } - - function peekCommand(state) { - if (state.cmdState.length>0) - return state.cmdState[state.cmdState.length-1]; - else - return null; - } - - function popCommand(state) { - if (state.cmdState.length>0) { - var plug = state.cmdState.pop(); - plug.closeBracket(); - } - } - - function applyMostPowerful(state) { - var context = state.cmdState; - for (var i = context.length - 1; i >= 0; i--) { - var plug = context[i]; - if (plug.name=="DEFAULT") - continue; - return plug.styleIdentifier(); - } - return null; - } - - function addPluginPattern(pluginName, cmdStyle, brackets, styles) { - return function () { - this.name=pluginName; - this.bracketNo = 0; - this.style=cmdStyle; - this.styles = styles; - this.brackets = brackets; - - this.styleIdentifier = function(content) { - if (this.bracketNo<=this.styles.length) - return this.styles[this.bracketNo-1]; - else - return null; - }; - this.openBracket = function(content) { - this.bracketNo++; - return "bracket"; - }; - this.closeBracket = function(content) { - }; - } - } - - var plugins = new Array(); - - plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]); - plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]); - plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]); - plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]); - plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]); - - plugins["DEFAULT"] = function () { - this.name="DEFAULT"; - this.style="tag"; - - this.styleIdentifier = function(content) { - }; - this.openBracket = function(content) { - }; - this.closeBracket = function(content) { - }; - }; - - function setState(state, f) { - state.f = f; - } - - function normal(source, state) { - if (source.match(/^\\[a-z]+/)) { - var cmdName = source.current(); - cmdName = cmdName.substr(1, cmdName.length-1); - var plug = plugins[cmdName]; - if (typeof(plug) == 'undefined') { - plug = plugins["DEFAULT"]; - } - plug = new plug(); - pushCommand(state, plug); - setState(state, beginParams); - return plug.style; - } - - var ch = source.next(); - if (ch == "%") { - setState(state, inCComment); - return "comment"; - } - else if (ch=='}' || ch==']') { - plug = peekCommand(state); - if (plug) { - plug.closeBracket(ch); - setState(state, beginParams); - } else - return "error"; - return "bracket"; - } else if (ch=='{' || ch=='[') { - plug = plugins["DEFAULT"]; - plug = new plug(); - pushCommand(state, plug); - return "bracket"; - } - else if (/\d/.test(ch)) { - source.eatWhile(/[\w.%]/); - return "atom"; - } - else { - source.eatWhile(/[\w-_]/); - return applyMostPowerful(state); - } - } - - function inCComment(source, state) { - source.skipToEnd(); - setState(state, normal); - return "comment"; - } - - function beginParams(source, state) { - var ch = source.peek(); - if (ch == '{' || ch == '[') { - var lastPlug = peekCommand(state); - var style = lastPlug.openBracket(ch); - source.eat(ch); - setState(state, normal); - return "bracket"; - } - if (/[ \t\r]/.test(ch)) { - source.eat(ch); - return null; - } - setState(state, normal); - lastPlug = peekCommand(state); - if (lastPlug) { - popCommand(state); - } - return normal(source, state); - } - - return { - startState: function() { return { f:normal, cmdState:[] }; }, - copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; }, - - token: function(stream, state) { - var t = state.f(stream, state); - var w = stream.current(); - return t; - } - }; -}); - - -CodeMirror.defineMIME("text/x-stex", "stex"); -CodeMirror.defineMIME("application/x-stex", "stex"); diff --git a/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js b/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js deleted file mode 100644 index b31e99faf..000000000 --- a/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +++ /dev/null @@ -1,375 +0,0 @@ -/*** - |''Name''|tiddlywiki.js| - |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror2| - |''Author''|PMario| - |''Version''|0.1.6| - |''Status''|''beta''| - |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]| - |''Documentation''|http://codemirror.tiddlyspace.com/| - |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]| - |''CoreVersion''|2.5.0| - |''Requires''|codemirror.js| - |''Keywords''|syntax highlighting color code mirror codemirror| - ! Info - CoreVersion parameter is needed for TiddlyWiki only! - ***/ -//{{{ -CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) { - var indentUnit = config.indentUnit; - - // Tokenizer - var textwords = function () { - function kw(type) { - return { - type: type, - style: "text" - }; - } - return {}; - }(); - - var keywords = function () { - function kw(type) { - return { type: type, style: "macro"}; - } - return { - "allTags": kw('allTags'), "closeAll": kw('closeAll'), "list": kw('list'), - "newJournal": kw('newJournal'), "newTiddler": kw('newTiddler'), - "permaview": kw('permaview'), "saveChanges": kw('saveChanges'), - "search": kw('search'), "slider": kw('slider'), "tabs": kw('tabs'), - "tag": kw('tag'), "tagging": kw('tagging'), "tags": kw('tags'), - "tiddler": kw('tiddler'), "timeline": kw('timeline'), - "today": kw('today'), "version": kw('version'), "option": kw('option'), - - "with": kw('with'), - "filter": kw('filter') - }; - }(); - - var isSpaceName = /[\w_\-]/i, - reHR = /^\-\-\-\-+$/, - reWikiCommentStart = /^\/\*\*\*$/, // /*** - reWikiCommentStop = /^\*\*\*\/$/, // ***/ - reBlockQuote = /^<<<$/, - - reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ - reJsCodeStop = /^\/\/\}\}\}$/, // //}}} - reXmlCodeStart = /^$/, - reXmlCodeStop = /^$/, - - reCodeBlockStart = /^\{\{\{$/, - reCodeBlockStop = /^\}\}\}$/, - - reCodeStart = /\{\{\{/, - reUntilCodeStop = /.*?\}\}\}/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - // used for strings - function nextUntilUnescaped(stream, end) { - var escaped = false, - next; - while ((next = stream.next()) != null) { - if (next == end && !escaped) return false; - escaped = !escaped && next == "\\"; - } - return escaped; - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - - function ret(tp, style, cont) { - type = tp; - content = cont; - return style; - } - - function jsTokenBase(stream, state) { - var sol = stream.sol(), - ch, tch; - - state.block = false; // indicates the start of a code block. - - ch = stream.peek(); // don't eat, to make match simpler - - // check start of blocks - if (sol && /[<\/\*{}\-]/.test(ch)) { - if (stream.match(reCodeBlockStart)) { - state.block = true; - return chain(stream, state, twTokenCode); - } - if (stream.match(reBlockQuote)) { - return ret('quote', 'quote'); - } - if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) { - return ret('code', 'code'); - } - if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) { - return ret('code', 'code'); - } - if (stream.match(reHR)) { - return ret('hr', 'hr'); - } - } // sol - var ch = stream.next(); - - if (sol && /[\/\*!#;:>|]/.test(ch)) { - if (ch == "!") { // tw header - stream.skipToEnd(); - return ret("header", "header"); - } - if (ch == "*") { // tw list - stream.eatWhile('*'); - return ret("list", "list"); - } - if (ch == "#") { // tw numbered list - stream.eatWhile('#'); - return ret("list", "list"); - } - if (ch == ";") { // tw list - stream.eatWhile(';'); - return ret("list", "list"); - } - if (ch == ":") { // tw list - stream.eatWhile(':'); - return ret("list", "list"); - } - if (ch == ">") { // single line quote - stream.eatWhile(">"); - return ret("quote", "quote"); - } - if (ch == '|') { - return ret('table', 'table'); - } - } - - if (ch == '{' && stream.match(/\{\{/)) { - return chain(stream, state, twTokenCode); - } - - // rudimentary html:// file:// link matching. TW knows much more ... - if (/[hf]/i.test(ch)) { - if (/[ti]/i.test(stream.peek()) && stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) { - return ret("link-external", "link-external"); - } - } - // just a little string indicator, don't want to have the whole string covered - if (ch == '"') { - return ret('string', 'string'); - } - if (/[\[\]]/.test(ch)) { // check for [[..]] - if (stream.peek() == ch) { - stream.next(); - return ret('brace', 'brace'); - } - } - if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting - stream.eatWhile(isSpaceName); - return ret("link-external", "link-external"); - } - if (/\d/.test(ch)) { // numbers - stream.eatWhile(/\d/); - return ret("number", "number"); - } - if (ch == "/") { // tw invisible comment - if (stream.eat("%")) { - return chain(stream, state, twTokenComment); - } - else if (stream.eat("/")) { // - return chain(stream, state, twTokenEm); - } - } - if (ch == "_") { // tw underline - if (stream.eat("_")) { - return chain(stream, state, twTokenUnderline); - } - } - if (ch == "-") { // tw strikethrough TODO looks ugly .. different handling see below; - if (stream.eat("-")) { - return chain(stream, state, twTokenStrike); - } - } - if (ch == "'") { // tw bold - if (stream.eat("'")) { - return chain(stream, state, twTokenStrong); - } - } - if (ch == "<") { // tw macro - if (stream.eat("<")) { - return chain(stream, state, twTokenMacro); - } - } - else { - return ret(ch); - } - - stream.eatWhile(/[\w\$_]/); - var word = stream.current(), - known = textwords.propertyIsEnumerable(word) && textwords[word]; - - return known ? ret(known.type, known.style, word) : ret("text", null, word); - - } // jsTokenBase() - - function twTokenString(quote) { - return function (stream, state) { - if (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase; - return ret("string", "string"); - }; - } - - // tw invisible comment - function twTokenComment(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "%"); - } - return ret("comment", "comment"); - } - - // tw strong / bold - function twTokenStrong(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "'" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "'"); - } - return ret("text", "strong"); - } - - // tw code - function twTokenCode(stream, state) { - var ch, sb = state.block; - - if (sb && stream.current()) { - return ret("code", "code"); - } - - if (!sb && stream.match(reUntilCodeStop)) { - state.tokenize = jsTokenBase; - return ret("code", "code-inline"); - } - - if (sb && stream.sol() && stream.match(reCodeBlockStop)) { - state.tokenize = jsTokenBase; - return ret("code", "code"); - } - - ch = stream.next(); - return (sb) ? ret("code", "code") : ret("code", "code-inline"); - } - - // tw em / italic - function twTokenEm(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "/"); - } - return ret("text", "em"); - } - - // tw underlined text - function twTokenUnderline(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "_" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "_"); - } - return ret("text", "underlined"); - } - - // tw strike through text looks ugly - // TODO just strike through the first and last 2 chars if possible. - function twTokenStrike(stream, state) { - var maybeEnd = false, - ch, nr; - - while (ch = stream.next()) { - if (ch == "-" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "-"); - } - return ret("text", "line-through"); - } - - // macro - function twTokenMacro(stream, state) { - var ch, tmp, word, known; - - if (stream.current() == '<<') { - return ret('brace', 'macro'); - } - - ch = stream.next(); - if (!ch) { - state.tokenize = jsTokenBase; - return ret(ch); - } - if (ch == ">") { - if (stream.peek() == '>') { - stream.next(); - state.tokenize = jsTokenBase; - return ret("brace", "macro"); - } - } - - stream.eatWhile(/[\w\$_]/); - word = stream.current(); - known = keywords.propertyIsEnumerable(word) && keywords[word]; - - if (known) { - return ret(known.type, known.style, word); - } - else { - return ret("macro", null, word); - } - } - - // Interface - return { - startState: function (basecolumn) { - return { - tokenize: jsTokenBase, - indented: 0, - level: 0 - }; - }, - - token: function (stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - }, - - electricChars: "" - }; -}); - -CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki"); -CodeMirror.defineMIME("application/x-tiddlywiki", "tiddlywiki"); -//}}} diff --git a/vendor/assets/javascripts/codemirror/modes/velocity.js b/vendor/assets/javascripts/codemirror/modes/velocity.js deleted file mode 100644 index 882d70736..000000000 --- a/vendor/assets/javascripts/codemirror/modes/velocity.js +++ /dev/null @@ -1,147 +0,0 @@ -CodeMirror.defineMode("velocity", function(config) { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var indentUnit = config.indentUnit - var keywords = parseWords("#end #else #break #stop #[[ #]] " + - "#{end} #{else} #{break} #{stop}"); - var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " + - "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}"); - var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent $velocityCount"); - var isOperatorChar = /[+\-*&%=<>!?:\/|]/; - var multiLineStrings =true; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - // start of string? - if ((ch == '"' || ch == "'") && state.inParams) - return chain(stream, state, tokenString(ch)); - // is it one of the special signs []{}().,;? Seperator? - else if (/[\[\]{}\(\),;\.]/.test(ch)) { - if (ch == "(" && beforeParams) state.inParams = true; - else if (ch == ")") state.inParams = false; - return null; - } - // start of a number value? - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - // multi line comment? - else if (ch == "#" && stream.eat("*")) { - return chain(stream, state, tokenComment); - } - // unparsed content? - else if (ch == "#" && stream.match(/ *\[ *\[/)) { - return chain(stream, state, tokenUnparsed); - } - // single line comment? - else if (ch == "#" && stream.eat("#")) { - stream.skipToEnd(); - return "comment"; - } - // variable? - else if (ch == "$") { - stream.eatWhile(/[\w\d\$_\.{}]/); - // is it one of the specials? - if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) { - return "keyword"; - } - else { - state.beforeParams = true; - return "builtin"; - } - } - // is it a operator? - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - else { - // get the whole word - stream.eatWhile(/[\w\$_{}]/); - var word = stream.current().toLowerCase(); - // is it one of the listed keywords? - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - // is it one of the listed functions? - if (functions && functions.propertyIsEnumerable(word) || - stream.current().match(/^#[a-z0-9_]+ *$/i) && stream.peek()=="(") { - state.beforeParams = true; - return "keyword"; - } - // default: just a "word" - return null; - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == "]") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME("text/velocity", "velocity"); -CodeMirror.defineMIME("application/velocity", "velocity"); diff --git a/vendor/assets/javascripts/codemirror/modes/verilog.js b/vendor/assets/javascripts/codemirror/modes/verilog.js deleted file mode 100644 index ebeb64154..000000000 --- a/vendor/assets/javascripts/codemirror/modes/verilog.js +++ /dev/null @@ -1,194 +0,0 @@ -CodeMirror.defineMode("verilog", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[&|~>")); - else return null; - } - else if (stream.match("--")) return chain(inBlock("comment", "-->")); - else if (stream.match("DOCTYPE", true, true)) { - stream.eatWhile(/[\w\._\-]/); - return chain(doctype(1)); - } - else return null; - } - else if (stream.eat("?")) { - stream.eatWhile(/[\w\._\-]/); - state.tokenize = inBlock("meta", "?>"); - return "meta"; - } - else { - type = stream.eat("/") ? "closeTag" : "openTag"; - stream.eatSpace(); - tagName = ""; - var c; - while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; - state.tokenize = inTag; - return "tag"; - } - } - else if (ch == "&") { - var ok; - if (stream.eat("#")) { - if (stream.eat("x")) { - ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); - } else { - ok = stream.eatWhile(/[\d]/) && stream.eat(";"); - } - } else { - ok = stream.eatWhile(/[\w]/) && stream.eat(";"); - } - return ok ? "atom" : "error"; - } - else { - stream.eatWhile(/[^&<]/); - return null; - } - } - - function inTag(stream, state) { - var ch = stream.next(); - if (ch == ">" || (ch == "/" && stream.eat(">"))) { - state.tokenize = inText; - type = ch == ">" ? "endTag" : "selfcloseTag"; - return "tag"; - } - else if (ch == "=") { - type = "equals"; - return null; - } - else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - return state.tokenize(stream, state); - } - else { - stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/); - return "word"; - } - } - - function inAttribute(quote) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inTag; - break; - } - } - return "string"; - }; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - return style; - }; - } - function doctype(depth) { - return function(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch == "<") { - state.tokenize = doctype(depth + 1); - return state.tokenize(stream, state); - } else if (ch == ">") { - if (depth == 1) { - state.tokenize = inText; - break; - } else { - state.tokenize = doctype(depth - 1); - return state.tokenize(stream, state); - } - } - } - return "meta"; - }; - } - - var curState, setStyle; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - - function pushContext(tagName, startOfLine) { - var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); - curState.context = { - prev: curState.context, - tagName: tagName, - indent: curState.indented, - startOfLine: startOfLine, - noIndent: noIndent - }; - } - function popContext() { - if (curState.context) curState.context = curState.context.prev; - } - - function element(type) { - if (type == "openTag") { - curState.tagName = tagName; - return cont(attributes, endtag(curState.startOfLine)); - } else if (type == "closeTag") { - var err = false; - if (curState.context) { - err = curState.context.tagName != tagName; - } else { - err = true; - } - if (err) setStyle = "error"; - return cont(endclosetag(err)); - } - return cont(); - } - function endtag(startOfLine) { - return function(type) { - if (type == "selfcloseTag" || - (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) - return cont(); - if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();} - return cont(); - }; - } - function endclosetag(err) { - return function(type) { - if (err) setStyle = "error"; - if (type == "endTag") { popContext(); return cont(); } - setStyle = "error"; - return cont(arguments.callee); - } - } - - function attributes(type) { - if (type == "word") {setStyle = "attribute"; return cont(attributes);} - if (type == "equals") return cont(attvalue, attributes); - if (type == "string") {setStyle = "error"; return cont(attributes);} - return pass(); - } - function attvalue(type) { - if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();} - if (type == "string") return cont(attvaluemaybe); - return pass(); - } - function attvaluemaybe(type) { - if (type == "string") return cont(attvaluemaybe); - else return pass(); - } - - return { - startState: function() { - return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null}; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.startOfLine = true; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - - setStyle = type = tagName = null; - var style = state.tokenize(stream, state); - state.type = type; - if ((style || type) && style != "comment") { - curState = state; - while (true) { - var comb = state.cc.pop() || element; - if (comb(type || style)) break; - } - } - state.startOfLine = false; - return setStyle || style; - }, - - indent: function(state, textAfter, fullLine) { - var context = state.context; - if ((state.tokenize != inTag && state.tokenize != inText) || - context && context.noIndent) - return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; - if (alignCDATA && /", parseDocument)); - } else if(stream.eatSpace() || stream.eol() ) { - stream.skipToEnd(); - return STYLE_ERROR; - } else { - // element - state.tokenize = parseElementTagName; - return STYLE_ELEMENT_NAME; - } - } - - // error on line - stream.skipToEnd(); - return STYLE_ERROR; - } - - /////////////////////////////////////////////////////////////////////////// - // context: XML element start-tag or end-tag - // - // - element start-tag can contain attributes - // - element start-tag may self-close (or start an element block if it doesn't) - // - element end-tag can contain only the tag name - function parseElementTagName(stream, state) { - // get the name of the tag - var startPos = stream.pos; - if(stream.match(/^[a-zA-Z_:][-a-zA-Z0-9_:.]*/)) { - // element start-tag - var tagName = stream.string.substring(startPos, stream.pos); - pushContext(state, tagName); - state.tokenize = parseElement; - return STYLE_ELEMENT_NAME; - } else if(stream.match(/^\/[a-zA-Z_:][-a-zA-Z0-9_:.]*( )*>/)) { - // element end-tag - var endTagName = stream.string.substring(startPos + 1, stream.pos - 1).trim(); - var oldContext = popContext(state); - state.tokenize = state.context == null ? parseDocument : parseElementBlock; - if(oldContext == null || endTagName != oldContext.tagName) { - // the start and end tag names should match - error - return STYLE_ERROR; - } - return STYLE_ELEMENT_NAME; - } else { - // no tag name - error - state.tokenize = state.context == null ? parseDocument : parseElementBlock; - stream.eatWhile(/[^>]/); - stream.eat(">"); - return STYLE_ERROR; - } - - stream.skipToEnd(); - return null; - } - - function parseElement(stream, state) { - if(stream.match(/^\/>/)) { - // self-closing tag - popContext(state); - state.tokenize = state.context == null ? parseDocument : parseElementBlock; - return STYLE_ELEMENT_NAME; - } else if(stream.eat(/^>/)) { - state.tokenize = parseElementBlock; - return STYLE_ELEMENT_NAME; - } else if(isTokenSeparated(stream) && stream.match(/^[a-zA-Z_:][-a-zA-Z0-9_:.]*( )*=/)) { - // attribute - state.tokenize = parseAttribute; - return STYLE_ATTRIBUTE; - } - - // no other options - this is an error - state.tokenize = state.context == null ? parseDocument : parseDocument; - stream.eatWhile(/[^>]/); - stream.eat(">"); - return STYLE_ERROR; - } - - /////////////////////////////////////////////////////////////////////////// - // context: attribute - // - // attribute values may contain everything, except: - // - the ending quote (with ' or ") - this marks the end of the value - // - the character "<" - should never appear - // - ampersand ("&") - unless it starts a reference: a string that ends with a semi-colon (";") - // ---> note: this parser is lax in what may be put into a reference string, - // ---> consult http://www.w3.org/TR/REC-xml/#NT-Reference if you want to make it tighter - function parseAttribute(stream, state) { - var quote = stream.next(); - if(quote != "\"" && quote != "'") { - // attribute must be quoted - stream.skipToEnd(); - state.tokenize = parseElement; - return STYLE_ERROR; - } - - state.tokParams.quote = quote; - state.tokenize = parseAttributeValue; - return STYLE_WORD; - } - - // @todo: find out whether this attribute value spans multiple lines, - // and if so, push a context for it in order not to indent it - // (or something of the sort..) - function parseAttributeValue(stream, state) { - var ch = ""; - while(!stream.eol()) { - ch = stream.next(); - if(ch == state.tokParams.quote) { - // end quote found - state.tokenize = parseElement; - return STYLE_WORD; - } else if(ch == "<") { - // can't have less-than signs in an attribute value, ever - stream.skipToEnd() - state.tokenize = parseElement; - return STYLE_ERROR; - } else if(ch == "&") { - // reference - look for a semi-colon, or return error if none found - ch = stream.next(); - - // make sure that semi-colon isn't right after the ampersand - if(ch == ';') { - stream.skipToEnd() - state.tokenize = parseElement; - return STYLE_ERROR; - } - - // make sure no less-than characters slipped in - while(!stream.eol() && ch != ";") { - if(ch == "<") { - // can't have less-than signs in an attribute value, ever - stream.skipToEnd() - state.tokenize = parseElement; - return STYLE_ERROR; - } - ch = stream.next(); - } - if(stream.eol() && ch != ";") { - // no ampersand found - error - stream.skipToEnd(); - state.tokenize = parseElement; - return STYLE_ERROR; - } - } - } - - // attribute value continues to next line - return STYLE_WORD; - } - - /////////////////////////////////////////////////////////////////////////// - // context: element block - // - // a block can contain: - // - elements - // - text - // - CDATA sections - // - comments - function parseElementBlock(stream, state) { - if(stream.eat("<")) { - if(stream.match("?")) { - pushContext(state, TAG_INSTRUCTION); - state.tokenize = parseProcessingInstructionStartTag; - return STYLE_INSTRUCTION; - } else if(stream.match("!--")) { - // new context: comment - pushContext(state, TAG_COMMENT); - return chain(stream, state, inBlock(STYLE_COMMENT, "-->", - state.context == null ? parseDocument : parseElementBlock)); - } else if(stream.match("![CDATA[")) { - // new context: CDATA section - pushContext(state, TAG_CDATA); - return chain(stream, state, inBlock(STYLE_TEXT, "]]>", - state.context == null ? parseDocument : parseElementBlock)); - } else if(stream.eatSpace() || stream.eol() ) { - stream.skipToEnd(); - return STYLE_ERROR; - } else { - // element - state.tokenize = parseElementTagName; - return STYLE_ELEMENT_NAME; - } - } else if(stream.eat("&")) { - stream.eatWhile(/[^;]/); - stream.eat(";"); - return STYLE_ENTITIES; - } else { - // new context: text - pushContext(state, TAG_TEXT); - state.tokenize = parseText; - return null; - } - - state.tokenize = state.context == null ? parseDocument : parseElementBlock; - stream.skipToEnd(); - return null; - } - - function parseText(stream, state) { - stream.eatWhile(/[^<]/); - if(!stream.eol()) { - // we cannot possibly be in the document context, - // just inside an element block - popContext(state); - state.tokenize = parseElementBlock; - } - return STYLE_TEXT; - } - - /////////////////////////////////////////////////////////////////////////// - // context: XML processing instructions - // - // XML processing instructions (PIs) allow documents to contain instructions for applications. - // PI format: - // - 'name' can be anything other than 'xml' (case-insensitive) - // - 'data' can be anything which doesn't contain '?>' - // XML declaration is a special PI (see XML declaration context below) - function parseProcessingInstructionStartTag(stream, state) { - if(stream.match("xml", true, true)) { - // xml declaration - if(state.lineNumber > 1 || stream.pos > 5) { - state.tokenize = parseDocument; - stream.skipToEnd(); - return STYLE_ERROR; - } else { - state.tokenize = parseDeclarationVersion; - return STYLE_INSTRUCTION; - } - } - - // regular processing instruction - if(isTokenSeparated(stream) || stream.match("?>")) { - // we have a space after the start-tag, or nothing but the end-tag - // either way - error! - state.tokenize = parseDocument; - stream.skipToEnd(); - return STYLE_ERROR; - } - - state.tokenize = parseProcessingInstructionBody; - return STYLE_INSTRUCTION; - } - - function parseProcessingInstructionBody(stream, state) { - stream.eatWhile(/[^?]/); - if(stream.eat("?")) { - if(stream.eat(">")) { - popContext(state); - state.tokenize = state.context == null ? parseDocument : parseElementBlock; - } - } - return STYLE_INSTRUCTION; - } - - - /////////////////////////////////////////////////////////////////////////// - // context: XML declaration - // - // XML declaration is of the following format: - // - // - must start at the first character of the first line - // - may span multiple lines - // - must include 'version' - // - may include 'encoding' and 'standalone' (in that order after 'version') - // - attribute names must be lowercase - // - cannot contain anything else on the line - function parseDeclarationVersion(stream, state) { - state.tokenize = parseDeclarationEncoding; - - if(isTokenSeparated(stream) && stream.match(/^version( )*=( )*"([a-zA-Z0-9_.:]|\-)+"/)) { - return STYLE_INSTRUCTION; - } - stream.skipToEnd(); - return STYLE_ERROR; - } - - function parseDeclarationEncoding(stream, state) { - state.tokenize = parseDeclarationStandalone; - - if(isTokenSeparated(stream) && stream.match(/^encoding( )*=( )*"[A-Za-z]([A-Za-z0-9._]|\-)*"/)) { - return STYLE_INSTRUCTION; - } - return null; - } - - function parseDeclarationStandalone(stream, state) { - state.tokenize = parseDeclarationEndTag; - - if(isTokenSeparated(stream) && stream.match(/^standalone( )*=( )*"(yes|no)"/)) { - return STYLE_INSTRUCTION; - } - return null; - } - - function parseDeclarationEndTag(stream, state) { - state.tokenize = parseDocument; - - if(stream.match("?>") && stream.eol()) { - popContext(state); - return STYLE_INSTRUCTION; - } - stream.skipToEnd(); - return STYLE_ERROR; - } - - /////////////////////////////////////////////////////////////////////////// - // returned object - return { - electricChars: "/[", - - startState: function() { - return { - tokenize: parseDocument, - tokParams: {}, - lineNumber: 0, - lineError: false, - context: null, - indented: 0 - }; - }, - - token: function(stream, state) { - if(stream.sol()) { - // initialize a new line - state.lineNumber++; - state.lineError = false; - state.indented = stream.indentation(); - } - - // eat all (the spaces) you can - if(stream.eatSpace()) return null; - - // run the current tokenize function, according to the state - var style = state.tokenize(stream, state); - - // is there an error somewhere in the line? - state.lineError = (state.lineError || style == "error"); - - return style; - }, - - blankLine: function(state) { - // blank lines are lines too! - state.lineNumber++; - state.lineError = false; - }, - - indent: function(state, textAfter) { - if(state.context) { - if(state.context.noIndent == true) { - // do not indent - no return value at all - return; - } - if(textAfter.match(/^<\/.*/)) { - // end-tag - indent back to last context - return state.context.indent; - } - if(textAfter.match(/^ state.keyCol) { - stream.skipToEnd(); return "string"; - } else if (state.literal) { state.literal = false; } - if (stream.sol()) { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - /* document start */ - if(stream.match(/---/)) { return "def"; } - /* document end */ - if (stream.match(/\.\.\./)) { return "def"; } - /* array list item */ - if (stream.match(/\s*-\s+/)) { return 'meta'; } - } - /* pairs (associative arrays) -> key */ - if (!state.pair && stream.match(/^\s*([a-z0-9\._-])+(?=\s*:)/i)) { - state.pair = true; - state.keyCol = stream.indentation(); - return "atom"; - } - if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; } - - /* inline pairs/lists */ - if (stream.match(/^(\{|\}|\[|\])/)) { - if (ch == '{') - state.inlinePairs++; - else if (ch == '}') - state.inlinePairs--; - else if (ch == '[') - state.inlineList++; - else - state.inlineList--; - return 'meta'; - } - - /* list seperator */ - if (state.inlineList > 0 && !esc && ch == ',') { - stream.next(); - return 'meta'; - } - /* pairs seperator */ - if (state.inlinePairs > 0 && !esc && ch == ',') { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - stream.next(); - return 'meta'; - } - - /* start of value of a pair */ - if (state.pairStart) { - /* block literals */ - if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; }; - /* references */ - if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; } - /* numbers */ - if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; } - if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; } - /* keywords */ - if (stream.match(keywordRegex)) { return 'keyword'; } - } - - /* nothing found, continue */ - state.pairStart = false; - state.escaped = (ch == '\\'); - stream.next(); - return null; - }, - startState: function() { - return { - pair: false, - pairStart: false, - keyCol: 0, - inlinePairs: 0, - inlineList: 0, - literal: false, - escaped: false - }; - } - }; -}); - -CodeMirror.defineMIME("text/x-yaml", "yaml"); -CodeMirror.defineMIME("application/x-yaml", "yaml"); diff --git a/vendor/assets/javascripts/codemirror/overlay.js b/vendor/assets/javascripts/codemirror/overlay.js deleted file mode 100644 index c4cdf9fc8..000000000 --- a/vendor/assets/javascripts/codemirror/overlay.js +++ /dev/null @@ -1,51 +0,0 @@ -// Utility function that allows modes to be combined. The mode given -// as the base argument takes care of most of the normal mode -// functionality, but a second (typically simple) mode is used, which -// can override the style of text. Both modes get to parse all of the -// text, but when both assign a non-null style to a piece of code, the -// overlay wins, unless the combine argument was true, in which case -// the styles are combined. - -CodeMirror.overlayParser = function(base, overlay, combine) { - return { - startState: function() { - return { - base: CodeMirror.startState(base), - overlay: CodeMirror.startState(overlay), - basePos: 0, baseCur: null, - overlayPos: 0, overlayCur: null - }; - }, - copyState: function(state) { - return { - base: CodeMirror.copyState(base, state.base), - overlay: CodeMirror.copyState(overlay, state.overlay), - basePos: state.basePos, baseCur: null, - overlayPos: state.overlayPos, overlayCur: null - }; - }, - - token: function(stream, state) { - if (stream.start == state.basePos) { - state.baseCur = base.token(stream, state.base); - state.basePos = stream.pos; - } - if (stream.start == state.overlayPos) { - stream.pos = stream.start; - state.overlayCur = overlay.token(stream, state.overlay); - state.overlayPos = stream.pos; - } - stream.pos = Math.min(state.basePos, state.overlayPos); - if (stream.eol()) state.basePos = state.overlayPos = 0; - - if (state.overlayCur == null) return state.baseCur; - if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur; - else return state.overlayCur; - }, - - indent: function(state, textAfter) { - return base.indent(state.base, textAfter); - }, - electricChars: base.electricChars - }; -}; diff --git a/vendor/assets/javascripts/codemirror/runmode.js b/vendor/assets/javascripts/codemirror/runmode.js deleted file mode 100644 index fc58d857d..000000000 --- a/vendor/assets/javascripts/codemirror/runmode.js +++ /dev/null @@ -1,49 +0,0 @@ -CodeMirror.runMode = function(string, modespec, callback, options) { - var mode = CodeMirror.getMode(CodeMirror.defaults, modespec); - var isNode = callback.nodeType == 1; - var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize; - if (isNode) { - var node = callback, accum = [], col = 0; - callback = function(text, style) { - if (text == "\n") { - accum.push("
"); - col = 0; - return; - } - var escaped = ""; - // HTML-escape and replace tabs - for (var pos = 0;;) { - var idx = text.indexOf("\t", pos); - if (idx == -1) { - escaped += CodeMirror.htmlEscape(text.slice(pos)); - col += text.length - pos; - break; - } else { - col += idx - pos; - escaped += CodeMirror.htmlEscape(text.slice(pos, idx)); - var size = tabSize - col % tabSize; - col += size; - for (var i = 0; i < size; ++i) escaped += " "; - pos = idx + 1; - } - } - - if (style) - accum.push("" + escaped + ""); - else - accum.push(escaped); - } - } - var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode); - for (var i = 0, e = lines.length; i < e; ++i) { - if (i) callback("\n"); - var stream = new CodeMirror.StringStream(lines[i]); - while (!stream.eol()) { - var style = mode.token(stream, state); - callback(stream.current(), style, i, stream.start); - stream.start = stream.pos; - } - } - if (isNode) - node.innerHTML = accum.join(""); -}; diff --git a/vendor/assets/javascripts/vendor.js b/vendor/assets/javascripts/vendor.js index 5c01d700c..dd31bf90c 100644 --- a/vendor/assets/javascripts/vendor.js +++ b/vendor/assets/javascripts/vendor.js @@ -3,9 +3,7 @@ //= require gollum/gollum.placeholder //= require gollum/editor/gollum.editor //= require jquery.dataTables -//= require codemirror -//= require codemirror/runmode -//= require_tree ./codemirror/modes + //= require cusel //= require bootstrap-modal //= require bootstrap-button diff --git a/vendor/assets/stylesheets/codemirror.scss b/vendor/assets/stylesheets/codemirror.scss deleted file mode 100644 index d1f4d6c68..000000000 --- a/vendor/assets/stylesheets/codemirror.scss +++ /dev/null @@ -1,106 +0,0 @@ -.CodeMirror { - line-height: 1em; - font-family: monospace; -} - -.CodeMirror-scroll { - overflow: auto; - /* This is needed to prevent an IE[67] bug where the scrolled content - is visible outside of the scrolling box. */ - position: relative; -} - -.CodeMirror-gutter { - position: absolute; left: 0; top: 0; - z-index: 10; - background-color: #f7f7f7; - border-right: 1px solid #eee; - min-width: 2em; - height: 100%; -} -.CodeMirror-gutter-text { - color: #aaa; - text-align: right; - padding: .4em .2em .4em .4em; - white-space: pre !important; -} -.CodeMirror-lines { - padding: .4em; -} - -.CodeMirror pre { - -moz-border-radius: 0; - -webkit-border-radius: 0; - -o-border-radius: 0; - border-radius: 0; - border-width: 0; margin: 0; padding: 0; background: transparent; - font-family: inherit; - font-size: inherit; - padding: 0; margin: 0; - white-space: pre; - word-wrap: normal; -} - -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; -} -.CodeMirror-wrap .CodeMirror-scroll { - overflow-x: hidden; -} - -.CodeMirror textarea { - outline: none !important; -} - -.CodeMirror pre.CodeMirror-cursor { - z-index: 10; - position: absolute; - visibility: hidden; - border-left: 1px solid black; -} -.CodeMirror-focused pre.CodeMirror-cursor { - visibility: visible; -} - -div.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; } - -.CodeMirror-searching { - background: #ffa; - background: rgba(255, 255, 0, .4); -} - -/* Default theme */ - -.cm-s-default span.cm-keyword {color: #708;} -.cm-s-default span.cm-atom {color: #219;} -.cm-s-default span.cm-number {color: #164;} -.cm-s-default span.cm-def {color: #00f;} -.cm-s-default span.cm-variable {color: black;} -.cm-s-default span.cm-variable-2 {color: #05a;} -.cm-s-default span.cm-variable-3 {color: #085;} -.cm-s-default span.cm-property {color: black;} -.cm-s-default span.cm-operator {color: black;} -.cm-s-default span.cm-comment {color: #a50;} -.cm-s-default span.cm-string {color: #a11;} -.cm-s-default span.cm-string-2 {color: #f50;} -.cm-s-default span.cm-meta {color: #555;} -.cm-s-default span.cm-error {color: #f00;} -.cm-s-default span.cm-qualifier {color: #555;} -.cm-s-default span.cm-builtin {color: #30a;} -.cm-s-default span.cm-bracket {color: #cc7;} -.cm-s-default span.cm-tag {color: #170;} -.cm-s-default span.cm-attribute {color: #00c;} -.cm-s-default span.cm-header {color: #a0a;} -.cm-s-default span.cm-quote {color: #090;} -.cm-s-default span.cm-hr {color: #999;} -.cm-s-default span.cm-link {color: #00c;} - -span.cm-header, span.cm-strong {font-weight: bold;} -span.cm-em {font-style: italic;} -span.cm-emstrong {font-style: italic; font-weight: bold;} -span.cm-link {text-decoration: underline;} - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} diff --git a/vendor/assets/stylesheets/codemirror/modes/diff.scss b/vendor/assets/stylesheets/codemirror/modes/diff.scss deleted file mode 100644 index 0e96ab21e..000000000 --- a/vendor/assets/stylesheets/codemirror/modes/diff.scss +++ /dev/null @@ -1,3 +0,0 @@ -span.cm-rangeinfo {color: #a0b;} -span.cm-minus {color: red;} -span.cm-plus {color: #2b2;} diff --git a/vendor/assets/stylesheets/codemirror/modes/rpm-spec.scss b/vendor/assets/stylesheets/codemirror/modes/rpm-spec.scss deleted file mode 100644 index d0a5d430c..000000000 --- a/vendor/assets/stylesheets/codemirror/modes/rpm-spec.scss +++ /dev/null @@ -1,5 +0,0 @@ -.cm-s-default span.cm-preamble {color: #b26818; font-weight: bold;} -.cm-s-default span.cm-macro {color: #b218b2;} -.cm-s-default span.cm-section {color: green; font-weight: bold;} -.cm-s-default span.cm-script {color: red;} -.cm-s-default span.cm-issue {color: yellow;} diff --git a/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.scss b/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.scss deleted file mode 100644 index 767f3de2a..000000000 --- a/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.scss +++ /dev/null @@ -1,21 +0,0 @@ -.cm-s-default span.cm-header {color: blue; font-weight:bold;} -.cm-s-default span.cm-code {color: #a50;} -.cm-s-default span.cm-code-inline {color: #660;} - -.cm-s-default span.cm-quote {color: #555;} -.cm-s-default span.cm-list {color: #c60;} -.cm-s-default span.cm-hr {color: #999;} -.cm-s-default span.cm-em {font-style: italic;} -.cm-s-default span.cm-strong {font-weight: bold;} - -.cm-s-default span.cm-link-external {color: blue;} -.cm-s-default span.cm-brace {color: #170; font-weight: bold;} -.cm-s-default span.cm-macro {color: #9E3825;} -.cm-s-default span.cm-table {color: blue;} -.cm-s-default span.cm-warning {color: red; font-weight: bold;} - -.cm-s-default span.cm-underlined {text-decoration: underline;} -.cm-s-default span.cm-line-through {text-decoration: line-through;} - -.cm-s-default span.cm-comment {color: #666;} - diff --git a/vendor/assets/stylesheets/codemirror/themes/cobalt.scss b/vendor/assets/stylesheets/codemirror/themes/cobalt.scss deleted file mode 100644 index dbbb7e496..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/cobalt.scss +++ /dev/null @@ -1,18 +0,0 @@ -.cm-s-cobalt { background: #002240; color: white; } -.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; } -.cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; } -.cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-cobalt span.cm-comment { color: #08f; } -.cm-s-cobalt span.cm-atom { color: #845dc4; } -.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; } -.cm-s-cobalt span.cm-keyword { color: #ffee80; } -.cm-s-cobalt span.cm-string { color: #3ad900; } -.cm-s-cobalt span.cm-meta { color: #ff9d00; } -.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; } -.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; } -.cm-s-cobalt span.cm-error { color: #9d1e15; } -.cm-s-cobalt span.cm-bracket { color: #d8d8d8; } -.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; } -.cm-s-cobalt span.cm-link { color: #845dc4; } diff --git a/vendor/assets/stylesheets/codemirror/themes/eclipse.scss b/vendor/assets/stylesheets/codemirror/themes/eclipse.scss deleted file mode 100644 index 41f6fcbdf..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/eclipse.scss +++ /dev/null @@ -1,25 +0,0 @@ -.cm-s-eclipse span.cm-meta {color: #FF1717;} -.cm-s-eclipse span.cm-keyword { font-weight: bold; color: #7F0055; } -.cm-s-eclipse span.cm-atom {color: #219;} -.cm-s-eclipse span.cm-number {color: #164;} -.cm-s-eclipse span.cm-def {color: #00f;} -.cm-s-eclipse span.cm-variable {color: black;} -.cm-s-eclipse span.cm-variable-2 {color: #0000C0;} -.cm-s-eclipse span.cm-variable-3 {color: #0000C0;} -.cm-s-eclipse span.cm-property {color: black;} -.cm-s-eclipse span.cm-operator {color: black;} -.cm-s-eclipse span.cm-comment {color: #3F7F5F;} -.cm-s-eclipse span.cm-string {color: #2A00FF;} -.cm-s-eclipse span.cm-string-2 {color: #f50;} -.cm-s-eclipse span.cm-error {color: #f00;} -.cm-s-eclipse span.cm-qualifier {color: #555;} -.cm-s-eclipse span.cm-builtin {color: #30a;} -.cm-s-eclipse span.cm-bracket {color: #cc7;} -.cm-s-eclipse span.cm-tag {color: #170;} -.cm-s-eclipse span.cm-attribute {color: #00c;} -.cm-s-eclipse span.cm-link {color: #219;} - -.cm-s-eclipse .CodeMirror-matchingbracket { - border:1px solid grey; - color:black !important;; -} diff --git a/vendor/assets/stylesheets/codemirror/themes/elegant.scss b/vendor/assets/stylesheets/codemirror/themes/elegant.scss deleted file mode 100644 index 29afa982d..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/elegant.scss +++ /dev/null @@ -1,10 +0,0 @@ -.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;} -.cm-s-elegant span.cm-comment {color: #262;font-style: italic;} -.cm-s-elegant span.cm-meta {color: #555;font-style: italic;} -.cm-s-elegant span.cm-variable {color: black;} -.cm-s-elegant span.cm-variable-2 {color: #b11;} -.cm-s-elegant span.cm-qualifier {color: #555;} -.cm-s-elegant span.cm-keyword {color: #730;} -.cm-s-elegant span.cm-builtin {color: #30a;} -.cm-s-elegant span.cm-error {background-color: #fdd;} -.cm-s-elegant span.cm-link {color: #762;} diff --git a/vendor/assets/stylesheets/codemirror/themes/monokai.scss b/vendor/assets/stylesheets/codemirror/themes/monokai.scss deleted file mode 100644 index f01d066f1..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/monokai.scss +++ /dev/null @@ -1,28 +0,0 @@ -/* Based on Sublime Text's Monokai theme */ - -.cm-s-monokai {background: #272822; color: #f8f8f2;} -.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;} -.cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;} -.cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;} -.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;} - -.cm-s-monokai span.cm-comment {color: #75715e;} -.cm-s-monokai span.cm-atom {color: #ae81ff;} -.cm-s-monokai span.cm-number {color: #ae81ff;} - -.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;} -.cm-s-monokai span.cm-keyword {color: #f92672;} -.cm-s-monokai span.cm-string {color: #e6db74;} - -.cm-s-monokai span.cm-variable {color: #a6e22e;} -.cm-s-monokai span.cm-variable-2 {color: #9effff;} -.cm-s-monokai span.cm-def {color: #fd971f;} -.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;} -.cm-s-monokai span.cm-bracket {color: #f8f8f2;} -.cm-s-monokai span.cm-tag {color: #f92672;} -.cm-s-monokai span.cm-link {color: #ae81ff;} - -.cm-s-monokai .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/vendor/assets/stylesheets/codemirror/themes/neat.scss b/vendor/assets/stylesheets/codemirror/themes/neat.scss deleted file mode 100644 index 6d2dbf5f6..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/neat.scss +++ /dev/null @@ -1,9 +0,0 @@ -.cm-s-neat span.cm-comment { color: #a86; } -.cm-s-neat span.cm-keyword { font-weight: bold; color: blue; } -.cm-s-neat span.cm-string { color: #a22; } -.cm-s-neat span.cm-builtin { font-weight: bold; color: #077; } -.cm-s-neat span.cm-special { font-weight: bold; color: #0aa; } -.cm-s-neat span.cm-variable { color: black; } -.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; } -.cm-s-neat span.cm-meta {color: #555;} -.cm-s-neat span.cm-link { color: #3a3; } diff --git a/vendor/assets/stylesheets/codemirror/themes/night.scss b/vendor/assets/stylesheets/codemirror/themes/night.scss deleted file mode 100644 index 3b296e4ab..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/night.scss +++ /dev/null @@ -1,21 +0,0 @@ -/* Loosely based on the Midnight Textmate theme */ - -.cm-s-night { background: #0a001f; color: #f8f8f8; } -.cm-s-night div.CodeMirror-selected { background: #a8f !important; } -.cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; } -.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-night span.cm-comment { color: #6900a1; } -.cm-s-night span.cm-atom { color: #845dc4; } -.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; } -.cm-s-night span.cm-keyword { color: #599eff; } -.cm-s-night span.cm-string { color: #37f14a; } -.cm-s-night span.cm-meta { color: #7678e2; } -.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; } -.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; } -.cm-s-night span.cm-error { color: #9d1e15; } -.cm-s-night span.cm-bracket { color: #8da6ce; } -.cm-s-night span.cm-comment { color: #6900a1; } -.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; } -.cm-s-night span.cm-link { color: #845dc4; } diff --git a/vendor/assets/stylesheets/codemirror/themes/rubyblue.scss b/vendor/assets/stylesheets/codemirror/themes/rubyblue.scss deleted file mode 100644 index bdbb11336..000000000 --- a/vendor/assets/stylesheets/codemirror/themes/rubyblue.scss +++ /dev/null @@ -1,21 +0,0 @@ -.cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; } /* - customized editor font - */ - -.cm-s-rubyblue { background: #112435; color: white; } -.cm-s-rubyblue div.CodeMirror-selected { background: #0000FF !important; } -.cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; } -.cm-s-rubyblue .CodeMirror-gutter-text { color: white; } -.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; } - -.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; } -.cm-s-rubyblue span.cm-atom { color: #F4C20B; } -.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; } -.cm-s-rubyblue span.cm-keyword { color: #F0F; } -.cm-s-rubyblue span.cm-string { color: #F08047; } -.cm-s-rubyblue span.cm-meta { color: #F0F; } -.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; } -.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; } -.cm-s-rubyblue span.cm-error { color: #AF2018; } -.cm-s-rubyblue span.cm-bracket { color: #F0F; } -.cm-s-rubyblue span.cm-link { color: #F4C20B; } -.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; } -.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; } diff --git a/vendor/assets/stylesheets/vendor.scss b/vendor/assets/stylesheets/vendor.scss index 5020011a8..852b153e2 100644 --- a/vendor/assets/stylesheets/vendor.scss +++ b/vendor/assets/stylesheets/vendor.scss @@ -7,11 +7,7 @@ //@import "gollum/template"; @import "gollum/editor"; -@import "codemirror"; -@import "codemirror/themes/eclipse"; -@import "codemirror/modes/diff"; -@import "codemirror/modes/rpm-spec"; -@import "codemirror/modes/tiddlywiki"; - @import "old-bootstrap"; -@import "chosen.scss"; \ No newline at end of file +@import "chosen.scss"; + +@import "pygments"; \ No newline at end of file From 015518d89c1a09854bc9248c8c0ea254213180e4 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 15:14:58 +0600 Subject: [PATCH 38/43] [#345] fix update commit --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 54e5e8797..d7b4e35d2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -371,7 +371,7 @@ Rosa::Application.routes.draw do # Commit comments post '/commit/:commit_id/comments(.:format)' => "comments#create", as: :project_commit_comments get '/commit/:commit_id/comments/:id(.:format)' => "comments#edit", as: :edit_project_commit_comment - put '/commit/:commit_id/comments/:id(.:format)' => "comments#update", as: :project_commit_comment + patch '/commit/:commit_id/comments/:id(.:format)' => "comments#update", as: :project_commit_comment delete '/commit/:commit_id/comments/:id(.:format)' => "comments#destroy" get '/commit/:commit_id/add_line_comments(.:format)' => "comments#new_line", as: :new_line_commit_comment # Commit subscribes From 176266622a25abef0ec9006240ae0e0b4a5ca70d Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 15:36:36 +0600 Subject: [PATCH 39/43] [#369] remove old code --- app/assets/javascripts/extra/log-wrapper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/extra/log-wrapper.js b/app/assets/javascripts/extra/log-wrapper.js index cd19cef5a..b3f570de2 100644 --- a/app/assets/javascripts/extra/log-wrapper.js +++ b/app/assets/javascripts/extra/log-wrapper.js @@ -51,7 +51,6 @@ function initLogWrapper() { var onBottom = Math.abs((l.clientHeight + vScroll - l.scrollHeight)) < getLineHeight(l); $("#output").html(data.log); - //CodeMirror.runMode(data.log.replace(/&/gi, '&'), "text/x-sh", document.getElementById("output")); $logCont.scrollLeft(hScroll); $logCont.scrollTop((onBottom || first_open) ? l.scrollHeight - l.clientHeight : vScroll); From 1aadcf02b95335b33668b3bd7b6a129847e3d9a4 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 15:40:07 +0600 Subject: [PATCH 40/43] [#345] fix compressing css & js --- config/environments/production.rb | 4 ++++ config/environments/staging.rb | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/config/environments/production.rb b/config/environments/production.rb index ff123a3df..ce0b0eebc 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -65,5 +65,9 @@ Rosa::Application.configure do # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) config.assets.precompile += %w(login.css login.js reg_session.css tour.css tour.js gollum/editor/langs/*.js moment/ru.js) + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + config.assets.css_compressor = :sass + config.eager_load = true end diff --git a/config/environments/staging.rb b/config/environments/staging.rb index f5b7d0681..aee5535d7 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -64,6 +64,10 @@ Rosa::Application.configure do # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) config.assets.precompile += %w(login.css login.js reg_session.css tour.css tour.js gollum/editor/langs/*.js moment/ru.js) + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + config.assets.css_compressor = :sass + config.eager_load = true config.log_redis = true end From 5a9623645f0a7a101bd3ca121951429b817e520b Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 15:54:23 +0600 Subject: [PATCH 41/43] [#369] add default pygments styles --- vendor/assets/stylesheets/pygments.scss | 92 +++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 vendor/assets/stylesheets/pygments.scss diff --git a/vendor/assets/stylesheets/pygments.scss b/vendor/assets/stylesheets/pygments.scss new file mode 100644 index 000000000..61a35b4df --- /dev/null +++ b/vendor/assets/stylesheets/pygments.scss @@ -0,0 +1,92 @@ +/* ========================================================== + * pygments-css + * https://github.com/richleland/pygments-css + * ========================================================== + * + * This is free and unencumbered software released into the public domain. + + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + + * For more information, please refer to */ + + +.hll { background-color: #ffffcc } +.c { color: #999988; font-style: italic } /* Comment */ +.err { color: #a61717; background-color: #e3d2d2 } /* Error */ +.k { color: #000000; font-weight: bold } /* Keyword */ +.o { color: #000000; font-weight: bold } /* Operator */ +.cm { color: #999988; font-style: italic } /* Comment.Multiline */ +.cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */ +.c1 { color: #999988; font-style: italic } /* Comment.Single */ +.cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */ +.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ +.ge { color: #000000; font-style: italic } /* Generic.Emph */ +.gr { color: #aa0000 } /* Generic.Error */ +.gh { color: #999999 } /* Generic.Heading */ +.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ +.go { color: #888888 } /* Generic.Output */ +.gp { color: #555555 } /* Generic.Prompt */ +.gs { font-weight: bold } /* Generic.Strong */ +.gu { color: #aaaaaa } /* Generic.Subheading */ +.gt { color: #aa0000 } /* Generic.Traceback */ +.kc { color: #000000; font-weight: bold } /* Keyword.Constant */ +.kd { color: #000000; font-weight: bold } /* Keyword.Declaration */ +.kn { color: #000000; font-weight: bold } /* Keyword.Namespace */ +.kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */ +.kr { color: #000000; font-weight: bold } /* Keyword.Reserved */ +.kt { color: #445588; font-weight: bold } /* Keyword.Type */ +.m { color: #009999 } /* Literal.Number */ +.s { color: #d01040 } /* Literal.String */ +.na { color: #008080 } /* Name.Attribute */ +.nb { color: #0086B3 } /* Name.Builtin */ +.nc { color: #445588; font-weight: bold } /* Name.Class */ +.no { color: #008080 } /* Name.Constant */ +.nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */ +.ni { color: #800080 } /* Name.Entity */ +.ne { color: #990000; font-weight: bold } /* Name.Exception */ +.nf { color: #990000; font-weight: bold } /* Name.Function */ +.nl { color: #990000; font-weight: bold } /* Name.Label */ +.nn { color: #555555 } /* Name.Namespace */ +.nt { color: #000080 } /* Name.Tag */ +.nv { color: #008080 } /* Name.Variable */ +.ow { color: #000000; font-weight: bold } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mf { color: #009999 } /* Literal.Number.Float */ +.mh { color: #009999 } /* Literal.Number.Hex */ +.mi { color: #009999 } /* Literal.Number.Integer */ +.mo { color: #009999 } /* Literal.Number.Oct */ +.sb { color: #d01040 } /* Literal.String.Backtick */ +.sc { color: #d01040 } /* Literal.String.Char */ +.sd { color: #d01040 } /* Literal.String.Doc */ +.s2 { color: #d01040 } /* Literal.String.Double */ +.se { color: #d01040 } /* Literal.String.Escape */ +.sh { color: #d01040 } /* Literal.String.Heredoc */ +.si { color: #d01040 } /* Literal.String.Interpol */ +.sx { color: #d01040 } /* Literal.String.Other */ +.sr { color: #009926 } /* Literal.String.Regex */ +.s1 { color: #d01040 } /* Literal.String.Single */ +.ss { color: #990073 } /* Literal.String.Symbol */ +.bp { color: #999999 } /* Name.Builtin.Pseudo */ +.vc { color: #008080 } /* Name.Variable.Class */ +.vg { color: #008080 } /* Name.Variable.Global */ +.vi { color: #008080 } /* Name.Variable.Instance */ +.il { color: #009999 } /* Literal.Number.Integer.Long */ From c005d9ca1aab0f4781d3b16817073d8f72cd3c96 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 16:27:00 +0600 Subject: [PATCH 42/43] [#369] remove comment --- app/assets/stylesheets/design/custom.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss index dacea7ba2..e9075f85f 100644 --- a/app/assets/stylesheets/design/custom.scss +++ b/app/assets/stylesheets/design/custom.scss @@ -393,7 +393,6 @@ div.comment textarea { resize: none } #repo-wrapper div.file div.data .formatted { overflow-x: auto; overflow-y: none; - //white-space: pre; } table.tablesorter tbody td a .issue_title { From 4872ba549f2690f52ef55410b02a8ca78e307285 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Tue, 15 Apr 2014 16:39:35 +0600 Subject: [PATCH 43/43] [#369] add pygments to the product build list log --- app/controllers/platforms/product_build_lists_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/platforms/product_build_lists_controller.rb b/app/controllers/platforms/product_build_lists_controller.rb index e2e22f6c6..2e3d1a145 100644 --- a/app/controllers/platforms/product_build_lists_controller.rb +++ b/app/controllers/platforms/product_build_lists_controller.rb @@ -40,7 +40,7 @@ class Platforms::ProductBuildListsController < Platforms::BaseController def log render json: { - log: @product_build_list.abf_worker_log, + log: Pygments.highlight(@product_build_list.abf_worker_log, lexer: 'sh'), building: @product_build_list.build_started? } end