codemirror-rails 2.24 → 2.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Rakefile +19 -0
- data/codemirror-rails.gemspec +6 -1
- data/lib/codemirror/rails/version.rb +2 -2
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +56 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/codemirror_rails_integration_test.rb +13 -0
- data/test/test_helper.rb +13 -0
- data/vendor/assets/javascripts/codemirror.js +381 -197
- data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +1 -1
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +649 -94
- data/vendor/assets/javascripts/codemirror/modes/clike.js +53 -7
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +12 -7
- data/vendor/assets/javascripts/codemirror/modes/diff.js +24 -5
- data/vendor/assets/javascripts/codemirror/modes/ecl.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/erlang.js +463 -0
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +38 -2
- data/vendor/assets/javascripts/codemirror/modes/go.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/groovy.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/haxe.js +432 -0
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/less.js +93 -93
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +29 -6
- data/vendor/assets/javascripts/codemirror/modes/mysql.js +6 -8
- data/vendor/assets/javascripts/codemirror/modes/ocaml.js +114 -0
- data/vendor/assets/javascripts/codemirror/modes/pascal.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/pig.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/plsql.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/python.js +13 -16
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -8
- data/vendor/assets/javascripts/codemirror/modes/scheme.js +74 -46
- data/vendor/assets/javascripts/codemirror/modes/shell.js +22 -7
- data/vendor/assets/javascripts/codemirror/modes/stex.js +7 -5
- data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +14 -14
- data/vendor/assets/javascripts/codemirror/modes/vb.js +260 -0
- data/vendor/assets/javascripts/codemirror/modes/verilog.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -1
- data/vendor/assets/javascripts/codemirror/modes/xquery.js +3 -3
- data/vendor/assets/javascripts/codemirror/utils/closetag.js +24 -34
- data/vendor/assets/javascripts/codemirror/utils/dialog.js +5 -1
- data/vendor/assets/javascripts/codemirror/utils/foldcode.js +10 -5
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +8 -3
- data/vendor/assets/javascripts/codemirror/utils/loadmode.js +2 -1
- data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/multiplex.js +81 -0
- data/vendor/assets/javascripts/codemirror/utils/overlay.js +2 -1
- data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +123 -0
- data/vendor/assets/javascripts/codemirror/utils/search.js +16 -12
- data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +4 -0
- data/vendor/assets/javascripts/codemirror/utils/xml-hint.js +137 -0
- data/vendor/assets/stylesheets/codemirror.css +59 -4
- data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +14 -21
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +1 -2
- data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +21 -0
- data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +2 -3
- data/vendor/assets/stylesheets/codemirror/themes/night.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +27 -0
- data/vendor/assets/stylesheets/codemirror/utils/dialog.css +4 -0
- metadata +98 -5
- data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +0 -5
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Dummy::Application.configure do
|
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb
|
|
3
|
+
|
|
4
|
+
# In the development environment your application's code is reloaded on
|
|
5
|
+
# every request. This slows down response time but is perfect for development
|
|
6
|
+
# since you don't have to restart the web server when you make code changes.
|
|
7
|
+
config.cache_classes = false
|
|
8
|
+
|
|
9
|
+
# Log error messages when you accidentally call methods on nil.
|
|
10
|
+
config.whiny_nils = true
|
|
11
|
+
|
|
12
|
+
# Show full error reports and disable caching
|
|
13
|
+
config.consider_all_requests_local = true
|
|
14
|
+
config.action_controller.perform_caching = false
|
|
15
|
+
|
|
16
|
+
# Don't care if the mailer can't send
|
|
17
|
+
config.action_mailer.raise_delivery_errors = false
|
|
18
|
+
|
|
19
|
+
# Print deprecation notices to the Rails logger
|
|
20
|
+
config.active_support.deprecation = :log
|
|
21
|
+
|
|
22
|
+
# Only use best-standards-support built into browsers
|
|
23
|
+
config.action_dispatch.best_standards_support = :builtin
|
|
24
|
+
|
|
25
|
+
# Raise exception on mass assignment protection for Active Record models
|
|
26
|
+
config.active_record.mass_assignment_sanitizer = :strict
|
|
27
|
+
|
|
28
|
+
# Log the query plan for queries taking more than this (works
|
|
29
|
+
# with SQLite, MySQL, and PostgreSQL)
|
|
30
|
+
config.active_record.auto_explain_threshold_in_seconds = 0.5
|
|
31
|
+
|
|
32
|
+
# Do not compress assets
|
|
33
|
+
config.assets.compress = false
|
|
34
|
+
|
|
35
|
+
# Expands the lines which load the assets
|
|
36
|
+
config.assets.debug = true
|
|
37
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Dummy::Application.configure do
|
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb
|
|
3
|
+
|
|
4
|
+
# Code is not reloaded between requests
|
|
5
|
+
config.cache_classes = true
|
|
6
|
+
|
|
7
|
+
# Full error reports are disabled and caching is turned on
|
|
8
|
+
config.consider_all_requests_local = false
|
|
9
|
+
config.action_controller.perform_caching = true
|
|
10
|
+
|
|
11
|
+
# Disable Rails's static asset server (Apache or nginx will already do this)
|
|
12
|
+
config.serve_static_assets = false
|
|
13
|
+
|
|
14
|
+
# Compress JavaScripts and CSS
|
|
15
|
+
config.assets.compress = true
|
|
16
|
+
|
|
17
|
+
# Don't fallback to assets pipeline if a precompiled asset is missed
|
|
18
|
+
config.assets.compile = false
|
|
19
|
+
|
|
20
|
+
# Generate digests for assets URLs
|
|
21
|
+
config.assets.digest = true
|
|
22
|
+
|
|
23
|
+
# Defaults to Rails.root.join("public/assets")
|
|
24
|
+
# config.assets.manifest = YOUR_PATH
|
|
25
|
+
|
|
26
|
+
# Specifies the header that your server uses for sending files
|
|
27
|
+
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
|
|
28
|
+
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
|
|
29
|
+
|
|
30
|
+
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
|
31
|
+
# config.force_ssl = true
|
|
32
|
+
|
|
33
|
+
# See everything in the log (default is :info)
|
|
34
|
+
# config.log_level = :debug
|
|
35
|
+
|
|
36
|
+
# Prepend all log lines with the following tags
|
|
37
|
+
# config.log_tags = [ :subdomain, :uuid ]
|
|
38
|
+
|
|
39
|
+
# Use a different logger for distributed setups
|
|
40
|
+
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
|
|
41
|
+
|
|
42
|
+
# Use a different cache store in production
|
|
43
|
+
# config.cache_store = :mem_cache_store
|
|
44
|
+
|
|
45
|
+
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
|
46
|
+
# config.action_controller.asset_host = "http://assets.example.com"
|
|
47
|
+
|
|
48
|
+
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
|
|
49
|
+
# config.assets.precompile += %w( search.js )
|
|
50
|
+
|
|
51
|
+
# Disable delivery errors, bad email addresses will be ignored
|
|
52
|
+
# config.action_mailer.raise_delivery_errors = false
|
|
53
|
+
|
|
54
|
+
# Enable threaded mode
|
|
55
|
+
# config.threadsafe!
|
|
56
|
+
|
|
57
|
+
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
|
58
|
+
# the I18n.default_locale when a translation can not be found)
|
|
59
|
+
config.i18n.fallbacks = true
|
|
60
|
+
|
|
61
|
+
# Send deprecation notices to registered listeners
|
|
62
|
+
config.active_support.deprecation = :notify
|
|
63
|
+
|
|
64
|
+
# Log the query plan for queries taking more than this (works
|
|
65
|
+
# with SQLite, MySQL, and PostgreSQL)
|
|
66
|
+
# config.active_record.auto_explain_threshold_in_seconds = 0.5
|
|
67
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Dummy::Application.configure do
|
|
2
|
+
# Settings specified here will take precedence over those in config/application.rb
|
|
3
|
+
|
|
4
|
+
# The test environment is used exclusively to run your application's
|
|
5
|
+
# test suite. You never need to work with it otherwise. Remember that
|
|
6
|
+
# your test database is "scratch space" for the test suite and is wiped
|
|
7
|
+
# and recreated between test runs. Don't rely on the data there!
|
|
8
|
+
config.cache_classes = true
|
|
9
|
+
|
|
10
|
+
# Configure static asset server for tests with Cache-Control for performance
|
|
11
|
+
config.serve_static_assets = true
|
|
12
|
+
config.static_cache_control = "public, max-age=3600"
|
|
13
|
+
|
|
14
|
+
# Log error messages when you accidentally call methods on nil
|
|
15
|
+
config.whiny_nils = true
|
|
16
|
+
|
|
17
|
+
# Show full error reports and disable caching
|
|
18
|
+
config.consider_all_requests_local = true
|
|
19
|
+
config.action_controller.perform_caching = false
|
|
20
|
+
|
|
21
|
+
# Raise exceptions instead of rendering exception templates
|
|
22
|
+
config.action_dispatch.show_exceptions = false
|
|
23
|
+
|
|
24
|
+
# Disable request forgery protection in test environment
|
|
25
|
+
config.action_controller.allow_forgery_protection = false
|
|
26
|
+
|
|
27
|
+
# Tell Action Mailer not to deliver emails to the real world.
|
|
28
|
+
# The :test delivery method accumulates sent emails in the
|
|
29
|
+
# ActionMailer::Base.deliveries array.
|
|
30
|
+
config.action_mailer.delivery_method = :test
|
|
31
|
+
|
|
32
|
+
# Raise exception on mass assignment protection for Active Record models
|
|
33
|
+
config.active_record.mass_assignment_sanitizer = :strict
|
|
34
|
+
|
|
35
|
+
# Print deprecation notices to the stderr
|
|
36
|
+
config.active_support.deprecation = :stderr
|
|
37
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
|
4
|
+
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
|
5
|
+
|
|
6
|
+
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
|
7
|
+
# Rails.backtrace_cleaner.remove_silencers!
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
# Add new inflection rules using the following format
|
|
4
|
+
# (all these examples are active by default):
|
|
5
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
|
6
|
+
# inflect.plural /^(ox)$/i, '\1en'
|
|
7
|
+
# inflect.singular /^(ox)en/i, '\1'
|
|
8
|
+
# inflect.irregular 'person', 'people'
|
|
9
|
+
# inflect.uncountable %w( fish sheep )
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# These inflection rules are supported but not enabled by default:
|
|
13
|
+
# ActiveSupport::Inflector.inflections do |inflect|
|
|
14
|
+
# inflect.acronym 'RESTful'
|
|
15
|
+
# end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
# Your secret key for verifying the integrity of signed cookies.
|
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
|
5
|
+
# Make sure the secret is at least 30 characters and all random,
|
|
6
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
|
7
|
+
Dummy::Application.config.secret_token = '17f0c3cb560a96dbd11a2322311215f4457303a24e9e09a49a3d538129decaa98eadf5a27f4e100940452796238c3e54bd131229ca341ea5379f894f09540fa8'
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
Dummy::Application.config.session_store :cookie_store, key: '_dummy_session'
|
|
4
|
+
|
|
5
|
+
# Use the database for sessions instead of the cookie-based default,
|
|
6
|
+
# which shouldn't be used to store highly confidential information
|
|
7
|
+
# (create the session table with "rails generate session_migration")
|
|
8
|
+
# Dummy::Application.config.session_store :active_record_store
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
#
|
|
3
|
+
# This file contains settings for ActionController::ParamsWrapper which
|
|
4
|
+
# is enabled by default.
|
|
5
|
+
|
|
6
|
+
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
|
7
|
+
ActiveSupport.on_load(:action_controller) do
|
|
8
|
+
wrap_parameters format: [:json]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Disable root element in JSON by default.
|
|
12
|
+
ActiveSupport.on_load(:active_record) do
|
|
13
|
+
self.include_root_in_json = false
|
|
14
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Dummy::Application.routes.draw do
|
|
2
|
+
# The priority is based upon order of creation:
|
|
3
|
+
# first created -> highest priority.
|
|
4
|
+
|
|
5
|
+
# Sample of regular route:
|
|
6
|
+
# match 'products/:id' => 'catalog#view'
|
|
7
|
+
# Keep in mind you can assign values other than :controller and :action
|
|
8
|
+
|
|
9
|
+
# Sample of named route:
|
|
10
|
+
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
|
|
11
|
+
# This route can be invoked with purchase_url(:id => product.id)
|
|
12
|
+
|
|
13
|
+
# Sample resource route (maps HTTP verbs to controller actions automatically):
|
|
14
|
+
# resources :products
|
|
15
|
+
|
|
16
|
+
# Sample resource route with options:
|
|
17
|
+
# resources :products do
|
|
18
|
+
# member do
|
|
19
|
+
# get 'short'
|
|
20
|
+
# post 'toggle'
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# collection do
|
|
24
|
+
# get 'sold'
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
|
|
28
|
+
# Sample resource route with sub-resources:
|
|
29
|
+
# resources :products do
|
|
30
|
+
# resources :comments, :sales
|
|
31
|
+
# resource :seller
|
|
32
|
+
# end
|
|
33
|
+
|
|
34
|
+
# Sample resource route with more complex sub-resources
|
|
35
|
+
# resources :products do
|
|
36
|
+
# resources :comments
|
|
37
|
+
# resources :sales do
|
|
38
|
+
# get 'recent', :on => :collection
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
|
|
42
|
+
# Sample resource route within a namespace:
|
|
43
|
+
# namespace :admin do
|
|
44
|
+
# # Directs /admin/products/* to Admin::ProductsController
|
|
45
|
+
# # (app/controllers/admin/products_controller.rb)
|
|
46
|
+
# resources :products
|
|
47
|
+
# end
|
|
48
|
+
|
|
49
|
+
# You can have the root of your site routed with "root"
|
|
50
|
+
# just remember to delete public/index.html.
|
|
51
|
+
# root :to => 'welcome#index'
|
|
52
|
+
|
|
53
|
+
# See how all your routes lay out with "rake routes"
|
|
54
|
+
|
|
55
|
+
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
|
56
|
+
# Note: This route will make all actions in every controller accessible via GET requests.
|
|
57
|
+
# match ':controller(/:action(/:id))(.:format)'
|
|
58
|
+
end
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
|
7
|
+
div.dialog {
|
|
8
|
+
width: 25em;
|
|
9
|
+
padding: 0 4em;
|
|
10
|
+
margin: 4em auto 0 auto;
|
|
11
|
+
border: 1px solid #ccc;
|
|
12
|
+
border-right-color: #999;
|
|
13
|
+
border-bottom-color: #999;
|
|
14
|
+
}
|
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<!-- This file lives in public/404.html -->
|
|
21
|
+
<div class="dialog">
|
|
22
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
|
23
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
|
24
|
+
</div>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
|
7
|
+
div.dialog {
|
|
8
|
+
width: 25em;
|
|
9
|
+
padding: 0 4em;
|
|
10
|
+
margin: 4em auto 0 auto;
|
|
11
|
+
border: 1px solid #ccc;
|
|
12
|
+
border-right-color: #999;
|
|
13
|
+
border-bottom-color: #999;
|
|
14
|
+
}
|
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<!-- This file lives in public/422.html -->
|
|
21
|
+
<div class="dialog">
|
|
22
|
+
<h1>The change you wanted was rejected.</h1>
|
|
23
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
|
24
|
+
</div>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
|
7
|
+
div.dialog {
|
|
8
|
+
width: 25em;
|
|
9
|
+
padding: 0 4em;
|
|
10
|
+
margin: 4em auto 0 auto;
|
|
11
|
+
border: 1px solid #ccc;
|
|
12
|
+
border-right-color: #999;
|
|
13
|
+
border-bottom-color: #999;
|
|
14
|
+
}
|
|
15
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<!-- This file lives in public/500.html -->
|
|
21
|
+
<div class="dialog">
|
|
22
|
+
<h1>We're sorry, but something went wrong.</h1>
|
|
23
|
+
</div>
|
|
24
|
+
</body>
|
|
25
|
+
</html>
|
|
File without changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
|
3
|
+
|
|
4
|
+
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
|
5
|
+
require File.expand_path('../../config/boot', __FILE__)
|
|
6
|
+
require 'rails/commands'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
describe 'codemiror-rails integration' do
|
|
4
|
+
it 'provides codemirror.js on the asset pipeline' do
|
|
5
|
+
visit '/assets/codemirror.js'
|
|
6
|
+
page.text.must_include 'var CodeMirror'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'provides codemirror css on the asset pipeline' do
|
|
10
|
+
visit '/assets/codemirror.css'
|
|
11
|
+
page.text.must_include '.CodeMirror'
|
|
12
|
+
end
|
|
13
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../dummy/config/environment.rb', __FILE__)
|
|
4
|
+
require 'rails/test_help'
|
|
5
|
+
require 'minitest/autorun'
|
|
6
|
+
require 'capybara/rails'
|
|
7
|
+
|
|
8
|
+
Rails.backtrace_cleaner.remove_silencers!
|
|
9
|
+
|
|
10
|
+
class IntegrationTest < MiniTest::Spec
|
|
11
|
+
include Capybara::DSL
|
|
12
|
+
register_spec_type(/integration$/, self)
|
|
13
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CodeMirror version 2.
|
|
1
|
+
// CodeMirror version 2.32
|
|
2
2
|
//
|
|
3
3
|
// All functions that need access to the editor's state live inside
|
|
4
4
|
// the CodeMirror function. Below that, at the bottom of the file,
|
|
@@ -23,14 +23,19 @@ var CodeMirror = (function() {
|
|
|
23
23
|
'<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
|
|
24
24
|
'<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
|
|
25
25
|
'autocorrect="off" autocapitalize="off"></textarea></div>' +
|
|
26
|
+
'<div class="CodeMirror-scrollbar">' + // The vertical scrollbar. Horizontal scrolling is handled by the scroller itself.
|
|
27
|
+
'<div class="CodeMirror-scrollbar-inner">' + // The empty scrollbar content, used solely for managing the scrollbar thumb.
|
|
28
|
+
'</div></div>' + // This must be before the scroll area because it's float-right.
|
|
26
29
|
'<div class="CodeMirror-scroll" tabindex="-1">' +
|
|
27
30
|
'<div style="position: relative">' + // Set to the height of the text, causes scrolling
|
|
28
31
|
'<div style="position: relative">' + // Moved around its parent to cover visible view
|
|
29
32
|
'<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
|
|
30
33
|
// Provides positioning relative to (visible) text origin
|
|
31
34
|
'<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
|
|
32
|
-
|
|
35
|
+
// Used to measure text size
|
|
36
|
+
'<div style="position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"></div>' +
|
|
33
37
|
'<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor
|
|
38
|
+
'<pre class="CodeMirror-cursor" style="visibility: hidden"> </pre>' + // Used to force a width
|
|
34
39
|
'<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
|
|
35
40
|
'</div></div></div></div></div>';
|
|
36
41
|
if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
|
|
@@ -39,12 +44,13 @@ var CodeMirror = (function() {
|
|
|
39
44
|
scroller = wrapper.lastChild, code = scroller.firstChild,
|
|
40
45
|
mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
|
|
41
46
|
lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
|
|
42
|
-
cursor = measure.nextSibling,
|
|
43
|
-
lineDiv = selectionDiv.nextSibling
|
|
44
|
-
|
|
47
|
+
cursor = measure.nextSibling, widthForcer = cursor.nextSibling,
|
|
48
|
+
selectionDiv = widthForcer.nextSibling, lineDiv = selectionDiv.nextSibling,
|
|
49
|
+
scrollbar = inputDiv.nextSibling, scrollbarInner = scrollbar.firstChild;
|
|
50
|
+
themeChanged(); keyMapChanged();
|
|
45
51
|
// Needed to hide big blue blinking cursor on Mobile Safari
|
|
46
52
|
if (ios) input.style.width = "0px";
|
|
47
|
-
if (!webkit)
|
|
53
|
+
if (!webkit) scroller.draggable = true;
|
|
48
54
|
lineSpace.style.outline = "none";
|
|
49
55
|
if (options.tabindex != null) input.tabIndex = options.tabindex;
|
|
50
56
|
if (options.autofocus) focusInput();
|
|
@@ -52,6 +58,17 @@ var CodeMirror = (function() {
|
|
|
52
58
|
// Needed to handle Tab key in KHTML
|
|
53
59
|
if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
|
|
54
60
|
|
|
61
|
+
// Check for OS X >= 10.7. If so, we need to force a width on the scrollbar, and
|
|
62
|
+
// make it overlap the content. (But we only do this if the scrollbar doesn't already
|
|
63
|
+
// have a natural width. If the mouse is plugged in or the user sets the system pref
|
|
64
|
+
// to always show scrollbars, the scrollbar shouldn't overlap.)
|
|
65
|
+
if (mac_geLion) {
|
|
66
|
+
scrollbar.className += (overlapScrollbars() ? " cm-sb-overlap" : " cm-sb-nonoverlap");
|
|
67
|
+
} else if (ie_lt8) {
|
|
68
|
+
// Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
|
|
69
|
+
scrollbar.className += " cm-sb-ie7";
|
|
70
|
+
}
|
|
71
|
+
|
|
55
72
|
// Check for problem with IE innerHTML not working when we have a
|
|
56
73
|
// P (or similar) parent node.
|
|
57
74
|
try { stringWidth("x"); }
|
|
@@ -75,7 +92,7 @@ var CodeMirror = (function() {
|
|
|
75
92
|
var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
|
|
76
93
|
// Selection-related flags. shiftSelecting obviously tracks
|
|
77
94
|
// whether the user is holding shift.
|
|
78
|
-
var shiftSelecting, lastClick, lastDoubleClick,
|
|
95
|
+
var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, lastScrollLeft = 0, draggingText,
|
|
79
96
|
overwrite = false, suppressEdits = false;
|
|
80
97
|
// Variables used by startOperation/endOperation to track what
|
|
81
98
|
// happened during the operation.
|
|
@@ -88,7 +105,7 @@ var CodeMirror = (function() {
|
|
|
88
105
|
var bracketHighlighted;
|
|
89
106
|
// Tracks the maximum line length so that the horizontal scrollbar
|
|
90
107
|
// can be kept static when scrolling.
|
|
91
|
-
var maxLine = "",
|
|
108
|
+
var maxLine = "", updateMaxLine = false, maxLineChanged = true;
|
|
92
109
|
var tabCache = {};
|
|
93
110
|
|
|
94
111
|
// Initialize the content.
|
|
@@ -103,12 +120,11 @@ var CodeMirror = (function() {
|
|
|
103
120
|
// which point we can't mess with it anymore. Context menu is
|
|
104
121
|
// handled in onMouseDown for Gecko.
|
|
105
122
|
if (!gecko) connect(scroller, "contextmenu", onContextMenu);
|
|
106
|
-
connect(scroller, "scroll",
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
});
|
|
123
|
+
connect(scroller, "scroll", onScroll);
|
|
124
|
+
connect(scrollbar, "scroll", onScroll);
|
|
125
|
+
connect(scrollbar, "mousedown", function() {if (focused) setTimeout(focusInput, 0);});
|
|
126
|
+
connect(scroller, "mousewheel", onMouseWheel);
|
|
127
|
+
connect(scroller, "DOMMouseScroll", onMouseWheel);
|
|
112
128
|
connect(window, "resize", function() {updateDisplay(true);});
|
|
113
129
|
connect(input, "keyup", operation(onKeyUp));
|
|
114
130
|
connect(input, "input", fastPoll);
|
|
@@ -118,7 +134,7 @@ var CodeMirror = (function() {
|
|
|
118
134
|
connect(input, "blur", onBlur);
|
|
119
135
|
|
|
120
136
|
if (options.dragDrop) {
|
|
121
|
-
connect(
|
|
137
|
+
connect(scroller, "dragstart", onDragStart);
|
|
122
138
|
function drag_(e) {
|
|
123
139
|
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
|
124
140
|
e_stop(e);
|
|
@@ -166,6 +182,7 @@ var CodeMirror = (function() {
|
|
|
166
182
|
else if (option == "theme") themeChanged();
|
|
167
183
|
else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
|
|
168
184
|
else if (option == "tabSize") updateDisplay(true);
|
|
185
|
+
else if (option == "keyMap") keyMapChanged();
|
|
169
186
|
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
|
|
170
187
|
gutterChanged();
|
|
171
188
|
updateDisplay(true);
|
|
@@ -184,6 +201,15 @@ var CodeMirror = (function() {
|
|
|
184
201
|
indentSelection: operation(indentSelected),
|
|
185
202
|
historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
|
|
186
203
|
clearHistory: function() {history = new History();},
|
|
204
|
+
setHistory: function(histData) {
|
|
205
|
+
history = new History();
|
|
206
|
+
history.done = histData.done;
|
|
207
|
+
history.undone = histData.undone;
|
|
208
|
+
},
|
|
209
|
+
getHistory: function() {
|
|
210
|
+
history.time = 0;
|
|
211
|
+
return {done: history.done.concat([]), undone: history.undone.concat([])};
|
|
212
|
+
},
|
|
187
213
|
matchBrackets: operation(function(){matchBrackets(true);}),
|
|
188
214
|
getTokenAt: operation(function(pos) {
|
|
189
215
|
pos = clipPos(pos);
|
|
@@ -275,7 +301,7 @@ var CodeMirror = (function() {
|
|
|
275
301
|
if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));
|
|
276
302
|
}),
|
|
277
303
|
replaceRange: operation(replaceRange),
|
|
278
|
-
getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
|
|
304
|
+
getRange: function(from, to, lineSep) {return getRange(clipPos(from), clipPos(to), lineSep);},
|
|
279
305
|
|
|
280
306
|
triggerOnKeyDown: operation(onKeyDown),
|
|
281
307
|
execCommand: function(cmd) {return commands[cmd](instance);},
|
|
@@ -313,16 +339,28 @@ var CodeMirror = (function() {
|
|
|
313
339
|
},
|
|
314
340
|
scrollTo: function(x, y) {
|
|
315
341
|
if (x != null) scroller.scrollLeft = x;
|
|
316
|
-
if (y != null)
|
|
342
|
+
if (y != null) scrollbar.scrollTop = y;
|
|
317
343
|
updateDisplay([]);
|
|
318
344
|
},
|
|
345
|
+
getScrollInfo: function() {
|
|
346
|
+
return {x: scroller.scrollLeft, y: scrollbar.scrollTop,
|
|
347
|
+
height: scrollbar.scrollHeight, width: scroller.scrollWidth};
|
|
348
|
+
},
|
|
349
|
+
setSize: function(width, height) {
|
|
350
|
+
function interpret(val) {
|
|
351
|
+
val = String(val);
|
|
352
|
+
return /^\d+$/.test(val) ? val + "px" : val;
|
|
353
|
+
}
|
|
354
|
+
if (width != null) wrapper.style.width = interpret(width);
|
|
355
|
+
if (height != null) scroller.style.height = interpret(height);
|
|
356
|
+
},
|
|
319
357
|
|
|
320
358
|
operation: function(f){return operation(f)();},
|
|
321
359
|
compoundChange: function(f){return compoundChange(f);},
|
|
322
360
|
refresh: function(){
|
|
323
|
-
updateDisplay(true);
|
|
324
|
-
if (
|
|
325
|
-
|
|
361
|
+
updateDisplay(true, null, lastScrollTop);
|
|
362
|
+
if (scrollbar.scrollHeight > lastScrollTop)
|
|
363
|
+
scrollbar.scrollTop = lastScrollTop;
|
|
326
364
|
},
|
|
327
365
|
getInputField: function(){return input;},
|
|
328
366
|
getWrapperElement: function(){return wrapper;},
|
|
@@ -343,10 +381,24 @@ var CodeMirror = (function() {
|
|
|
343
381
|
splitLines(code), top, top);
|
|
344
382
|
updateInput = true;
|
|
345
383
|
}
|
|
346
|
-
function getValue() {
|
|
384
|
+
function getValue(lineSep) {
|
|
347
385
|
var text = [];
|
|
348
386
|
doc.iter(0, doc.size, function(line) { text.push(line.text); });
|
|
349
|
-
return text.join("\n");
|
|
387
|
+
return text.join(lineSep || "\n");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function onScroll(e) {
|
|
391
|
+
if (scroller.scrollTop) {
|
|
392
|
+
scrollbar.scrollTop += scroller.scrollTop;
|
|
393
|
+
scroller.scrollTop = 0;
|
|
394
|
+
}
|
|
395
|
+
if (lastScrollTop != scrollbar.scrollTop || lastScrollLeft != scroller.scrollLeft) {
|
|
396
|
+
lastScrollTop = scrollbar.scrollTop;
|
|
397
|
+
lastScrollLeft = scroller.scrollLeft;
|
|
398
|
+
updateDisplay([]);
|
|
399
|
+
if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
|
|
400
|
+
if (options.onScroll) options.onScroll(instance);
|
|
401
|
+
}
|
|
350
402
|
}
|
|
351
403
|
|
|
352
404
|
function onMouseDown(e) {
|
|
@@ -367,10 +419,12 @@ var CodeMirror = (function() {
|
|
|
367
419
|
|
|
368
420
|
switch (e_button(e)) {
|
|
369
421
|
case 3:
|
|
370
|
-
if (gecko
|
|
422
|
+
if (gecko) onContextMenu(e);
|
|
371
423
|
return;
|
|
372
424
|
case 2:
|
|
373
425
|
if (start) setCursor(start.line, start.ch, true);
|
|
426
|
+
setTimeout(focusInput, 20);
|
|
427
|
+
e_preventDefault(e);
|
|
374
428
|
return;
|
|
375
429
|
}
|
|
376
430
|
// For button 1, if it was clicked inside the editor
|
|
@@ -380,24 +434,27 @@ var CodeMirror = (function() {
|
|
|
380
434
|
|
|
381
435
|
if (!focused) onFocus();
|
|
382
436
|
|
|
383
|
-
var now = +new Date;
|
|
437
|
+
var now = +new Date, type = "single";
|
|
384
438
|
if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
|
|
439
|
+
type = "triple";
|
|
385
440
|
e_preventDefault(e);
|
|
386
441
|
setTimeout(focusInput, 20);
|
|
387
|
-
|
|
442
|
+
selectLine(start.line);
|
|
388
443
|
} else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
|
|
444
|
+
type = "double";
|
|
389
445
|
lastDoubleClick = {time: now, pos: start};
|
|
390
446
|
e_preventDefault(e);
|
|
391
|
-
|
|
447
|
+
var word = findWordAt(start);
|
|
448
|
+
setSelectionUser(word.from, word.to);
|
|
392
449
|
} else { lastClick = {time: now, pos: start}; }
|
|
393
450
|
|
|
394
451
|
var last = start, going;
|
|
395
452
|
if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
|
|
396
|
-
!posLess(start, sel.from) && !posLess(sel.to, start)) {
|
|
453
|
+
!posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
|
|
397
454
|
// Let the drag handler handle this.
|
|
398
|
-
if (webkit)
|
|
455
|
+
if (webkit) scroller.draggable = true;
|
|
399
456
|
function dragEnd(e2) {
|
|
400
|
-
if (webkit)
|
|
457
|
+
if (webkit) scroller.draggable = false;
|
|
401
458
|
draggingText = false;
|
|
402
459
|
up(); drop();
|
|
403
460
|
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
|
|
@@ -410,18 +467,33 @@ var CodeMirror = (function() {
|
|
|
410
467
|
var drop = connect(scroller, "drop", operation(dragEnd), true);
|
|
411
468
|
draggingText = true;
|
|
412
469
|
// IE's approach to draggable
|
|
413
|
-
if (
|
|
470
|
+
if (scroller.dragDrop) scroller.dragDrop();
|
|
414
471
|
return;
|
|
415
472
|
}
|
|
416
473
|
e_preventDefault(e);
|
|
417
|
-
setCursor(start.line, start.ch, true);
|
|
474
|
+
if (type == "single") setCursor(start.line, start.ch, true);
|
|
475
|
+
|
|
476
|
+
var startstart = sel.from, startend = sel.to;
|
|
477
|
+
|
|
478
|
+
function doSelect(cur) {
|
|
479
|
+
if (type == "single") {
|
|
480
|
+
setSelectionUser(start, cur);
|
|
481
|
+
} else if (type == "double") {
|
|
482
|
+
var word = findWordAt(cur);
|
|
483
|
+
if (posLess(cur, startstart)) setSelectionUser(word.from, startend);
|
|
484
|
+
else setSelectionUser(startstart, word.to);
|
|
485
|
+
} else if (type == "triple") {
|
|
486
|
+
if (posLess(cur, startstart)) setSelectionUser(startend, clipPos({line: cur.line, ch: 0}));
|
|
487
|
+
else setSelectionUser(startstart, clipPos({line: cur.line + 1, ch: 0}));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
418
490
|
|
|
419
491
|
function extend(e) {
|
|
420
492
|
var cur = posFromMouse(e, true);
|
|
421
493
|
if (cur && !posEq(cur, last)) {
|
|
422
494
|
if (!focused) onFocus();
|
|
423
495
|
last = cur;
|
|
424
|
-
|
|
496
|
+
doSelect(cur);
|
|
425
497
|
updateInput = false;
|
|
426
498
|
var visible = visibleLines();
|
|
427
499
|
if (cur.line >= visible.to || cur.line < visible.from)
|
|
@@ -432,7 +504,7 @@ var CodeMirror = (function() {
|
|
|
432
504
|
function done(e) {
|
|
433
505
|
clearTimeout(going);
|
|
434
506
|
var cur = posFromMouse(e);
|
|
435
|
-
if (cur)
|
|
507
|
+
if (cur) doSelect(cur);
|
|
436
508
|
e_preventDefault(e);
|
|
437
509
|
focusInput();
|
|
438
510
|
updateInput = true;
|
|
@@ -449,11 +521,7 @@ var CodeMirror = (function() {
|
|
|
449
521
|
function onDoubleClick(e) {
|
|
450
522
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
|
451
523
|
if (n.parentNode == gutterText) return e_preventDefault(e);
|
|
452
|
-
var start = posFromMouse(e);
|
|
453
|
-
if (!start) return;
|
|
454
|
-
lastDoubleClick = {time: +new Date, pos: start};
|
|
455
524
|
e_preventDefault(e);
|
|
456
|
-
selectWordAt(start);
|
|
457
525
|
}
|
|
458
526
|
function onDrop(e) {
|
|
459
527
|
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
|
@@ -477,8 +545,9 @@ var CodeMirror = (function() {
|
|
|
477
545
|
}
|
|
478
546
|
var n = files.length, text = Array(n), read = 0;
|
|
479
547
|
for (var i = 0; i < n; ++i) loadFile(files[i], i);
|
|
480
|
-
}
|
|
481
|
-
|
|
548
|
+
} else {
|
|
549
|
+
// Don't do a replace if the drop happened inside of the selected text.
|
|
550
|
+
if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return;
|
|
482
551
|
try {
|
|
483
552
|
var text = e.dataTransfer.getData("Text");
|
|
484
553
|
if (text) {
|
|
@@ -499,7 +568,7 @@ var CodeMirror = (function() {
|
|
|
499
568
|
e.dataTransfer.setData("Text", txt);
|
|
500
569
|
|
|
501
570
|
// Use dummy image instead of default browsers image.
|
|
502
|
-
if (gecko || chrome) {
|
|
571
|
+
if (gecko || chrome || opera) {
|
|
503
572
|
var img = document.createElement('img');
|
|
504
573
|
img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
|
|
505
574
|
e.dataTransfer.setDragImage(img, 0, 0);
|
|
@@ -556,6 +625,7 @@ var CodeMirror = (function() {
|
|
|
556
625
|
if (stopped) handled = false;
|
|
557
626
|
if (handled) {
|
|
558
627
|
e_preventDefault(e);
|
|
628
|
+
restartBlink();
|
|
559
629
|
if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
|
|
560
630
|
}
|
|
561
631
|
return handled;
|
|
@@ -563,7 +633,10 @@ var CodeMirror = (function() {
|
|
|
563
633
|
function handleCharBinding(e, ch) {
|
|
564
634
|
var handled = lookupKey("'" + ch + "'", options.extraKeys,
|
|
565
635
|
options.keyMap, function(b) { return doHandleBinding(b, true); });
|
|
566
|
-
if (handled)
|
|
636
|
+
if (handled) {
|
|
637
|
+
e_preventDefault(e);
|
|
638
|
+
restartBlink();
|
|
639
|
+
}
|
|
567
640
|
return handled;
|
|
568
641
|
}
|
|
569
642
|
|
|
@@ -578,7 +651,7 @@ var CodeMirror = (function() {
|
|
|
578
651
|
setShift(code == 16 || e_prop(e, "shiftKey"));
|
|
579
652
|
// First give onKeyEvent option a chance to handle this.
|
|
580
653
|
var handled = handleKeyBinding(e);
|
|
581
|
-
if (
|
|
654
|
+
if (opera) {
|
|
582
655
|
lastStoppedKey = handled ? code : null;
|
|
583
656
|
// Opera has no cut event... we try to at least catch the key combo
|
|
584
657
|
if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
|
|
@@ -589,8 +662,8 @@ var CodeMirror = (function() {
|
|
|
589
662
|
if (pollingFast) readInput();
|
|
590
663
|
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
591
664
|
var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
|
|
592
|
-
if (
|
|
593
|
-
if (((
|
|
665
|
+
if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
|
|
666
|
+
if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
|
|
594
667
|
var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
|
|
595
668
|
if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
|
|
596
669
|
if (mode.electricChars.indexOf(ch) > -1)
|
|
@@ -609,8 +682,8 @@ var CodeMirror = (function() {
|
|
|
609
682
|
if (!focused) {
|
|
610
683
|
if (options.onFocus) options.onFocus(instance);
|
|
611
684
|
focused = true;
|
|
612
|
-
if (
|
|
613
|
-
|
|
685
|
+
if (scroller.className.search(/\bCodeMirror-focused\b/) == -1)
|
|
686
|
+
scroller.className += " CodeMirror-focused";
|
|
614
687
|
if (!leaveInputAlone) resetInput(true);
|
|
615
688
|
}
|
|
616
689
|
slowPoll();
|
|
@@ -624,12 +697,48 @@ var CodeMirror = (function() {
|
|
|
624
697
|
operation(function(){
|
|
625
698
|
if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
|
|
626
699
|
})();
|
|
627
|
-
|
|
700
|
+
scroller.className = scroller.className.replace(" CodeMirror-focused", "");
|
|
628
701
|
}
|
|
629
702
|
clearInterval(blinker);
|
|
630
703
|
setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
|
|
631
704
|
}
|
|
632
705
|
|
|
706
|
+
function chopDelta(delta) {
|
|
707
|
+
// Make sure we always scroll a little bit for any nonzero delta.
|
|
708
|
+
if (delta > 0.0 && delta < 1.0) return 1;
|
|
709
|
+
else if (delta > -1.0 && delta < 0.0) return -1;
|
|
710
|
+
else return Math.round(delta);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function onMouseWheel(e) {
|
|
714
|
+
var deltaX = 0, deltaY = 0;
|
|
715
|
+
if (e.type == "DOMMouseScroll") { // Firefox
|
|
716
|
+
var delta = -e.detail * 8.0;
|
|
717
|
+
if (e.axis == e.HORIZONTAL_AXIS) deltaX = delta;
|
|
718
|
+
else if (e.axis == e.VERTICAL_AXIS) deltaY = delta;
|
|
719
|
+
} else if (e.wheelDeltaX !== undefined && e.wheelDeltaY !== undefined) { // WebKit
|
|
720
|
+
deltaX = e.wheelDeltaX / 3.0;
|
|
721
|
+
deltaY = e.wheelDeltaY / 3.0;
|
|
722
|
+
} else if (e.wheelDelta !== undefined) { // IE or Opera
|
|
723
|
+
deltaY = e.wheelDelta / 3.0;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
var scrolled = false;
|
|
727
|
+
deltaX = chopDelta(deltaX);
|
|
728
|
+
deltaY = chopDelta(deltaY);
|
|
729
|
+
if ((deltaX > 0 && scroller.scrollLeft > 0) ||
|
|
730
|
+
(deltaX < 0 && scroller.scrollLeft + scroller.clientWidth < scroller.scrollWidth)) {
|
|
731
|
+
scroller.scrollLeft -= deltaX;
|
|
732
|
+
scrolled = true;
|
|
733
|
+
}
|
|
734
|
+
if ((deltaY > 0 && scrollbar.scrollTop > 0) ||
|
|
735
|
+
(deltaY < 0 && scrollbar.scrollTop + scrollbar.clientHeight < scrollbar.scrollHeight)) {
|
|
736
|
+
scrollbar.scrollTop -= deltaY;
|
|
737
|
+
scrolled = true;
|
|
738
|
+
}
|
|
739
|
+
if (scrolled) e_stop(e);
|
|
740
|
+
}
|
|
741
|
+
|
|
633
742
|
// Replace the range from from to to by the strings in newText.
|
|
634
743
|
// Afterwards, set the selection to selFrom, selTo.
|
|
635
744
|
function updateLines(from, to, newText, selFrom, selTo) {
|
|
@@ -650,8 +759,8 @@ var CodeMirror = (function() {
|
|
|
650
759
|
var replaced = [], end = change.start + change.added;
|
|
651
760
|
doc.iter(change.start, end, function(line) { replaced.push(line.text); });
|
|
652
761
|
out.push({start: change.start, added: change.old.length, old: replaced});
|
|
653
|
-
var pos =
|
|
654
|
-
|
|
762
|
+
var pos = {line: change.start + change.old.length - 1,
|
|
763
|
+
ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])};
|
|
655
764
|
updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
|
|
656
765
|
}
|
|
657
766
|
updateInput = true;
|
|
@@ -665,7 +774,7 @@ var CodeMirror = (function() {
|
|
|
665
774
|
var recomputeMaxLength = false, maxLineLength = maxLine.length;
|
|
666
775
|
if (!options.lineWrapping)
|
|
667
776
|
doc.iter(from.line, to.line + 1, function(line) {
|
|
668
|
-
if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
|
777
|
+
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
|
669
778
|
});
|
|
670
779
|
if (from.line != to.line || newText.length > 1) gutterDirty = true;
|
|
671
780
|
|
|
@@ -721,20 +830,12 @@ var CodeMirror = (function() {
|
|
|
721
830
|
} else {
|
|
722
831
|
doc.iter(from.line, from.line + newText.length, function(line) {
|
|
723
832
|
var l = line.text;
|
|
724
|
-
if (l.length > maxLineLength) {
|
|
725
|
-
maxLine = l; maxLineLength = l.length;
|
|
833
|
+
if (!line.hidden && l.length > maxLineLength) {
|
|
834
|
+
maxLine = l; maxLineLength = l.length; maxLineChanged = true;
|
|
726
835
|
recomputeMaxLength = false;
|
|
727
836
|
}
|
|
728
837
|
});
|
|
729
|
-
if (recomputeMaxLength)
|
|
730
|
-
maxLineLength = 0; maxLine = ""; maxWidth = null;
|
|
731
|
-
doc.iter(0, doc.size, function(line) {
|
|
732
|
-
var l = line.text;
|
|
733
|
-
if (l.length > maxLineLength) {
|
|
734
|
-
maxLineLength = l.length; maxLine = l;
|
|
735
|
-
}
|
|
736
|
-
});
|
|
737
|
-
}
|
|
838
|
+
if (recomputeMaxLength) updateMaxLine = true;
|
|
738
839
|
}
|
|
739
840
|
|
|
740
841
|
// Add these lines to the work array, so that they will be
|
|
@@ -760,11 +861,55 @@ var CodeMirror = (function() {
|
|
|
760
861
|
|
|
761
862
|
// Update the selection
|
|
762
863
|
function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
|
|
763
|
-
setSelection(selFrom, selTo
|
|
864
|
+
setSelection(clipPos(selFrom), clipPos(selTo),
|
|
865
|
+
updateLine(sel.from.line), updateLine(sel.to.line));
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
function needsScrollbar() {
|
|
869
|
+
var realHeight = doc.height * textHeight() + 2 * paddingTop();
|
|
870
|
+
return realHeight - 1 > scroller.offsetHeight ? realHeight : false;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
function updateVerticalScroll(scrollTop) {
|
|
874
|
+
var scrollHeight = needsScrollbar();
|
|
875
|
+
scrollbar.style.display = scrollHeight ? "block" : "none";
|
|
876
|
+
if (scrollHeight) {
|
|
877
|
+
scrollbarInner.style.height = scrollHeight + "px";
|
|
878
|
+
scrollbar.style.height = scroller.offsetHeight + "px";
|
|
879
|
+
if (scrollTop != null) scrollbar.scrollTop = scrollTop;
|
|
880
|
+
}
|
|
881
|
+
// Position the mover div to align with the current virtual scroll position
|
|
882
|
+
mover.style.top = (displayOffset * textHeight() - scrollbar.scrollTop) + "px";
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// On Mac OS X Lion and up, detect whether the mouse is plugged in by measuring
|
|
886
|
+
// the width of a div with a scrollbar in it. If the width is <= 1, then
|
|
887
|
+
// the mouse isn't plugged in and scrollbars should overlap the content.
|
|
888
|
+
function overlapScrollbars() {
|
|
889
|
+
var tmpSb = document.createElement('div'),
|
|
890
|
+
tmpSbInner = document.createElement('div');
|
|
891
|
+
tmpSb.className = "CodeMirror-scrollbar";
|
|
892
|
+
tmpSb.style.cssText = "position: absolute; left: -9999px; height: 100px;";
|
|
893
|
+
tmpSbInner.className = "CodeMirror-scrollbar-inner";
|
|
894
|
+
tmpSbInner.style.height = "200px";
|
|
895
|
+
tmpSb.appendChild(tmpSbInner);
|
|
896
|
+
|
|
897
|
+
document.body.appendChild(tmpSb);
|
|
898
|
+
var result = (tmpSb.offsetWidth <= 1);
|
|
899
|
+
document.body.removeChild(tmpSb);
|
|
900
|
+
return result;
|
|
901
|
+
}
|
|
764
902
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
903
|
+
function computeMaxLength() {
|
|
904
|
+
var maxLineLength = 0;
|
|
905
|
+
maxLine = ""; maxLineChanged = true;
|
|
906
|
+
doc.iter(0, doc.size, function(line) {
|
|
907
|
+
var l = line.text;
|
|
908
|
+
if (!line.hidden && l.length > maxLineLength) {
|
|
909
|
+
maxLineLength = l.length; maxLine = l;
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
updateMaxLine = false;
|
|
768
913
|
}
|
|
769
914
|
|
|
770
915
|
function replaceRange(code, from, to) {
|
|
@@ -800,16 +945,16 @@ var CodeMirror = (function() {
|
|
|
800
945
|
updateLines(from, to, code, newSel.from, newSel.to);
|
|
801
946
|
}
|
|
802
947
|
|
|
803
|
-
function getRange(from, to) {
|
|
948
|
+
function getRange(from, to, lineSep) {
|
|
804
949
|
var l1 = from.line, l2 = to.line;
|
|
805
950
|
if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);
|
|
806
951
|
var code = [getLine(l1).text.slice(from.ch)];
|
|
807
952
|
doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });
|
|
808
953
|
code.push(getLine(l2).text.slice(0, to.ch));
|
|
809
|
-
return code.join("\n");
|
|
954
|
+
return code.join(lineSep || "\n");
|
|
810
955
|
}
|
|
811
|
-
function getSelection() {
|
|
812
|
-
return getRange(sel.from, sel.to);
|
|
956
|
+
function getSelection(lineSep) {
|
|
957
|
+
return getRange(sel.from, sel.to, lineSep);
|
|
813
958
|
}
|
|
814
959
|
|
|
815
960
|
var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
|
|
@@ -853,7 +998,8 @@ var CodeMirror = (function() {
|
|
|
853
998
|
else if (overwrite && posEq(sel.from, sel.to))
|
|
854
999
|
sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
|
|
855
1000
|
replaceSelection(text.slice(same), "end");
|
|
856
|
-
prevInput =
|
|
1001
|
+
if (text.length > 1000) { input.value = prevInput = ""; }
|
|
1002
|
+
else prevInput = text;
|
|
857
1003
|
return true;
|
|
858
1004
|
}
|
|
859
1005
|
function resetInput(user) {
|
|
@@ -869,44 +1015,50 @@ var CodeMirror = (function() {
|
|
|
869
1015
|
}
|
|
870
1016
|
|
|
871
1017
|
function scrollEditorIntoView() {
|
|
872
|
-
if (!cursor.getBoundingClientRect) return;
|
|
873
1018
|
var rect = cursor.getBoundingClientRect();
|
|
874
1019
|
// IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
|
|
875
1020
|
if (ie && rect.top == rect.bottom) return;
|
|
876
1021
|
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
|
|
877
|
-
if (rect.top < 0 || rect.bottom > winH)
|
|
1022
|
+
if (rect.top < 0 || rect.bottom > winH) scrollCursorIntoView();
|
|
878
1023
|
}
|
|
879
1024
|
function scrollCursorIntoView() {
|
|
1025
|
+
var coords = calculateCursorCoords();
|
|
1026
|
+
return scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
|
|
1027
|
+
}
|
|
1028
|
+
function calculateCursorCoords() {
|
|
880
1029
|
var cursor = localCoords(sel.inverted ? sel.from : sel.to);
|
|
881
1030
|
var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
|
|
882
|
-
return
|
|
1031
|
+
return {x: x, y: cursor.y, yBot: cursor.yBot};
|
|
883
1032
|
}
|
|
884
1033
|
function scrollIntoView(x1, y1, x2, y2) {
|
|
1034
|
+
var scrollPos = calculateScrollPos(x1, y1, x2, y2), scrolled = false;
|
|
1035
|
+
if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft; scrolled = true;}
|
|
1036
|
+
if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scrollPos.scrollTop; scrolled = true;}
|
|
1037
|
+
if (scrolled && options.onScroll) options.onScroll(instance);
|
|
1038
|
+
}
|
|
1039
|
+
function calculateScrollPos(x1, y1, x2, y2) {
|
|
885
1040
|
var pl = paddingLeft(), pt = paddingTop();
|
|
886
1041
|
y1 += pt; y2 += pt; x1 += pl; x2 += pl;
|
|
887
|
-
var screen = scroller.clientHeight, screentop =
|
|
888
|
-
|
|
889
|
-
|
|
1042
|
+
var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {};
|
|
1043
|
+
var docBottom = scroller.scrollHeight;
|
|
1044
|
+
var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;;
|
|
1045
|
+
if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
|
|
1046
|
+
else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
|
|
890
1047
|
|
|
891
1048
|
var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
|
|
892
1049
|
var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
|
|
893
1050
|
var atLeft = x1 < gutterw + pl + 10;
|
|
894
1051
|
if (x1 < screenleft + gutterw || atLeft) {
|
|
895
1052
|
if (atLeft) x1 = 0;
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
else if (x2 > screenw + screenleft - 3) {
|
|
900
|
-
scroller.scrollLeft = x2 + 10 - screenw;
|
|
901
|
-
scrolled = true;
|
|
902
|
-
if (x2 > code.clientWidth) result = false;
|
|
1053
|
+
result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
|
|
1054
|
+
} else if (x2 > screenw + screenleft - 3) {
|
|
1055
|
+
result.scrollLeft = x2 + 10 - screenw;
|
|
903
1056
|
}
|
|
904
|
-
if (scrolled && options.onScroll) options.onScroll(instance);
|
|
905
1057
|
return result;
|
|
906
1058
|
}
|
|
907
1059
|
|
|
908
|
-
function visibleLines() {
|
|
909
|
-
var lh = textHeight(), top =
|
|
1060
|
+
function visibleLines(scrollTop) {
|
|
1061
|
+
var lh = textHeight(), top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop();
|
|
910
1062
|
var fromHeight = Math.max(0, Math.floor(top / lh));
|
|
911
1063
|
var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
|
|
912
1064
|
return {from: lineAtHeight(doc, fromHeight),
|
|
@@ -915,15 +1067,20 @@ var CodeMirror = (function() {
|
|
|
915
1067
|
// Uses a set of changes plus the current scroll position to
|
|
916
1068
|
// determine which DOM updates have to be made, and makes the
|
|
917
1069
|
// updates.
|
|
918
|
-
function updateDisplay(changes, suppressCallback) {
|
|
1070
|
+
function updateDisplay(changes, suppressCallback, scrollTop) {
|
|
919
1071
|
if (!scroller.clientWidth) {
|
|
920
1072
|
showingFrom = showingTo = displayOffset = 0;
|
|
921
1073
|
return;
|
|
922
1074
|
}
|
|
923
1075
|
// Compute the new visible window
|
|
924
|
-
|
|
1076
|
+
// If scrollTop is specified, use that to determine which lines
|
|
1077
|
+
// to render instead of the current scrollbar position.
|
|
1078
|
+
var visible = visibleLines(scrollTop);
|
|
925
1079
|
// Bail out if the visible area is already rendered and nothing changed.
|
|
926
|
-
if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo)
|
|
1080
|
+
if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) {
|
|
1081
|
+
updateVerticalScroll(scrollTop);
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
927
1084
|
var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
|
|
928
1085
|
if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
|
|
929
1086
|
if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
|
|
@@ -941,7 +1098,10 @@ var CodeMirror = (function() {
|
|
|
941
1098
|
if (range.from >= range.to) intact.splice(i--, 1);
|
|
942
1099
|
else intactLines += range.to - range.from;
|
|
943
1100
|
}
|
|
944
|
-
if (intactLines == to - from && from == showingFrom && to == showingTo)
|
|
1101
|
+
if (intactLines == to - from && from == showingFrom && to == showingTo) {
|
|
1102
|
+
updateVerticalScroll(scrollTop);
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
945
1105
|
intact.sort(function(a, b) {return a.domStart - b.domStart;});
|
|
946
1106
|
|
|
947
1107
|
var th = textHeight(), gutterDisplay = gutter.style.display;
|
|
@@ -949,17 +1109,12 @@ var CodeMirror = (function() {
|
|
|
949
1109
|
patchDisplay(from, to, intact);
|
|
950
1110
|
lineDiv.style.display = gutter.style.display = "";
|
|
951
1111
|
|
|
952
|
-
// Position the mover div to align with the lines it's supposed
|
|
953
|
-
// to be showing (which will cover the visible display)
|
|
954
1112
|
var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
|
|
955
1113
|
// This is just a bogus formula that detects when the editor is
|
|
956
1114
|
// resized or the font size changes.
|
|
957
1115
|
if (different) lastSizeC = scroller.clientHeight + th;
|
|
958
1116
|
showingFrom = from; showingTo = to;
|
|
959
1117
|
displayOffset = heightAtLine(doc, from);
|
|
960
|
-
mover.style.top = (displayOffset * th) + "px";
|
|
961
|
-
if (scroller.clientHeight)
|
|
962
|
-
code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
|
|
963
1118
|
|
|
964
1119
|
// Since this is all rather error prone, it is honoured with the
|
|
965
1120
|
// only assertion in the whole file.
|
|
@@ -968,7 +1123,6 @@ var CodeMirror = (function() {
|
|
|
968
1123
|
" nodes=" + lineDiv.childNodes.length);
|
|
969
1124
|
|
|
970
1125
|
function checkHeights() {
|
|
971
|
-
maxWidth = scroller.clientWidth;
|
|
972
1126
|
var curNode = lineDiv.firstChild, heightChanged = false;
|
|
973
1127
|
doc.iter(showingFrom, showingTo, function(line) {
|
|
974
1128
|
if (!line.hidden) {
|
|
@@ -980,22 +1134,17 @@ var CodeMirror = (function() {
|
|
|
980
1134
|
}
|
|
981
1135
|
curNode = curNode.nextSibling;
|
|
982
1136
|
});
|
|
983
|
-
if (heightChanged)
|
|
984
|
-
code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
|
|
985
1137
|
return heightChanged;
|
|
986
1138
|
}
|
|
987
1139
|
|
|
988
1140
|
if (options.lineWrapping) {
|
|
989
1141
|
checkHeights();
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
if (
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
code.style.width = scroller.scrollWidth + "px";
|
|
997
|
-
} else {
|
|
998
|
-
lineSpace.style.width = code.style.width = "";
|
|
1142
|
+
var scrollHeight = needsScrollbar();
|
|
1143
|
+
var shouldHaveScrollbar = scrollHeight ? "block" : "none";
|
|
1144
|
+
if (scrollbar.style.display != shouldHaveScrollbar) {
|
|
1145
|
+
scrollbar.style.display = shouldHaveScrollbar;
|
|
1146
|
+
if (scrollHeight) scrollbarInner.style.height = scrollHeight + "px";
|
|
1147
|
+
checkHeights();
|
|
999
1148
|
}
|
|
1000
1149
|
}
|
|
1001
1150
|
|
|
@@ -1004,6 +1153,7 @@ var CodeMirror = (function() {
|
|
|
1004
1153
|
// If the gutter grew in size, re-check heights. If those changed, re-draw gutter.
|
|
1005
1154
|
updateGutter() && options.lineWrapping && checkHeights() && updateGutter();
|
|
1006
1155
|
}
|
|
1156
|
+
updateVerticalScroll(scrollTop);
|
|
1007
1157
|
updateSelection();
|
|
1008
1158
|
if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
|
|
1009
1159
|
return true;
|
|
@@ -1083,7 +1233,7 @@ var CodeMirror = (function() {
|
|
|
1083
1233
|
html.push("<pre></pre>");
|
|
1084
1234
|
} else {
|
|
1085
1235
|
var marker = line.gutterMarker;
|
|
1086
|
-
var text = options.lineNumbers ? i + options.firstLineNumber : null;
|
|
1236
|
+
var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null;
|
|
1087
1237
|
if (marker && marker.text)
|
|
1088
1238
|
text = marker.text.replace("%N%", text != null ? text : "");
|
|
1089
1239
|
else if (text == null)
|
|
@@ -1098,9 +1248,9 @@ var CodeMirror = (function() {
|
|
|
1098
1248
|
gutter.style.display = "none";
|
|
1099
1249
|
gutterText.innerHTML = html.join("");
|
|
1100
1250
|
// Make sure scrolling doesn't cause number gutter size to pop
|
|
1101
|
-
if (normalNode != null) {
|
|
1251
|
+
if (normalNode != null && options.lineNumbers) {
|
|
1102
1252
|
var node = gutterText.childNodes[normalNode - showingFrom];
|
|
1103
|
-
var minwidth = String(doc.size).length, val = eltText(node), pad = "";
|
|
1253
|
+
var minwidth = String(doc.size).length, val = eltText(node.firstChild), pad = "";
|
|
1104
1254
|
while (val.length + pad.length < minwidth) pad += "\u00a0";
|
|
1105
1255
|
if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);
|
|
1106
1256
|
}
|
|
@@ -1282,17 +1432,19 @@ var CodeMirror = (function() {
|
|
|
1282
1432
|
if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
|
|
1283
1433
|
else if (unit == "line") dist = textHeight();
|
|
1284
1434
|
var target = coordsChar(pos.x, pos.y + dist * dir + 2);
|
|
1285
|
-
if (unit == "page")
|
|
1435
|
+
if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y;
|
|
1286
1436
|
setCursor(target.line, target.ch, true);
|
|
1287
1437
|
goalColumn = pos.x;
|
|
1288
1438
|
}
|
|
1289
1439
|
|
|
1290
|
-
function
|
|
1440
|
+
function findWordAt(pos) {
|
|
1291
1441
|
var line = getLine(pos.line).text;
|
|
1292
1442
|
var start = pos.ch, end = pos.ch;
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1443
|
+
var check = isWordChar(line.charAt(start < line.length ? start : start - 1)) ?
|
|
1444
|
+
isWordChar : function(ch) {return !isWordChar(ch);};
|
|
1445
|
+
while (start > 0 && check(line.charAt(start - 1))) --start;
|
|
1446
|
+
while (end < line.length && check(line.charAt(end))) ++end;
|
|
1447
|
+
return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
|
|
1296
1448
|
}
|
|
1297
1449
|
function selectLine(line) {
|
|
1298
1450
|
setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));
|
|
@@ -1312,26 +1464,23 @@ var CodeMirror = (function() {
|
|
|
1312
1464
|
|
|
1313
1465
|
var line = getLine(n), curSpace = line.indentation(options.tabSize),
|
|
1314
1466
|
curSpaceString = line.text.match(/^\s*/)[0], indentation;
|
|
1467
|
+
if (how == "smart") {
|
|
1468
|
+
indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
|
|
1469
|
+
if (indentation == Pass) how = "prev";
|
|
1470
|
+
}
|
|
1315
1471
|
if (how == "prev") {
|
|
1316
1472
|
if (n) indentation = getLine(n-1).indentation(options.tabSize);
|
|
1317
1473
|
else indentation = 0;
|
|
1318
1474
|
}
|
|
1319
|
-
else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
|
|
1320
1475
|
else if (how == "add") indentation = curSpace + options.indentUnit;
|
|
1321
1476
|
else if (how == "subtract") indentation = curSpace - options.indentUnit;
|
|
1322
1477
|
indentation = Math.max(0, indentation);
|
|
1323
1478
|
var diff = indentation - curSpace;
|
|
1324
1479
|
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
var
|
|
1328
|
-
}
|
|
1329
|
-
else {
|
|
1330
|
-
var indentString = "", pos = 0;
|
|
1331
|
-
if (options.indentWithTabs)
|
|
1332
|
-
for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
|
|
1333
|
-
while (pos < indentation) {++pos; indentString += " ";}
|
|
1334
|
-
}
|
|
1480
|
+
var indentString = "", pos = 0;
|
|
1481
|
+
if (options.indentWithTabs)
|
|
1482
|
+
for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
|
|
1483
|
+
while (pos < indentation) {++pos; indentString += " ";}
|
|
1335
1484
|
|
|
1336
1485
|
replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
|
|
1337
1486
|
}
|
|
@@ -1358,9 +1507,10 @@ var CodeMirror = (function() {
|
|
|
1358
1507
|
if (guess != 1) updateLineHeight(line, guess);
|
|
1359
1508
|
});
|
|
1360
1509
|
lineSpace.style.width = code.style.width = "";
|
|
1510
|
+
widthForcer.style.left = "";
|
|
1361
1511
|
} else {
|
|
1362
1512
|
wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
|
|
1363
|
-
|
|
1513
|
+
maxLine = ""; maxLineChanged = true;
|
|
1364
1514
|
doc.iter(0, doc.size, function(line) {
|
|
1365
1515
|
if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
|
|
1366
1516
|
if (line.text.length > maxLine.length) maxLine = line.text;
|
|
@@ -1378,6 +1528,11 @@ var CodeMirror = (function() {
|
|
|
1378
1528
|
scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
|
|
1379
1529
|
options.theme.replace(/(^|\s)\s*/g, " cm-s-");
|
|
1380
1530
|
}
|
|
1531
|
+
function keyMapChanged() {
|
|
1532
|
+
var style = keyMap[options.keyMap].style;
|
|
1533
|
+
wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
|
|
1534
|
+
(style ? " cm-keymap-" + style : "");
|
|
1535
|
+
}
|
|
1381
1536
|
|
|
1382
1537
|
function TextMarker() { this.set = []; }
|
|
1383
1538
|
TextMarker.prototype.clear = operation(function() {
|
|
@@ -1485,6 +1640,14 @@ var CodeMirror = (function() {
|
|
|
1485
1640
|
return changeLine(handle, function(line, no) {
|
|
1486
1641
|
if (line.hidden != hidden) {
|
|
1487
1642
|
line.hidden = hidden;
|
|
1643
|
+
if (!options.lineWrapping) {
|
|
1644
|
+
var l = line.text;
|
|
1645
|
+
if (hidden && l.length == maxLine.length) {
|
|
1646
|
+
updateMaxLine = true;
|
|
1647
|
+
} else if (!hidden && l.length > maxLine.length) {
|
|
1648
|
+
maxLine = l; updateMaxLine = false;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1488
1651
|
updateLineHeight(line, hidden ? 0 : 1);
|
|
1489
1652
|
var fline = sel.from.line, tline = sel.to.line;
|
|
1490
1653
|
if (hidden && (fline == no || tline == no)) {
|
|
@@ -1505,8 +1668,7 @@ var CodeMirror = (function() {
|
|
|
1505
1668
|
var n = line;
|
|
1506
1669
|
line = getLine(line);
|
|
1507
1670
|
if (!line) return null;
|
|
1508
|
-
}
|
|
1509
|
-
else {
|
|
1671
|
+
} else {
|
|
1510
1672
|
var n = lineNo(line);
|
|
1511
1673
|
if (n == null) return null;
|
|
1512
1674
|
}
|
|
@@ -1655,8 +1817,8 @@ var CodeMirror = (function() {
|
|
|
1655
1817
|
return coordsChar(x - offL.left, y - offL.top);
|
|
1656
1818
|
}
|
|
1657
1819
|
function onContextMenu(e) {
|
|
1658
|
-
var pos = posFromMouse(e), scrollPos =
|
|
1659
|
-
if (!pos ||
|
|
1820
|
+
var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop;
|
|
1821
|
+
if (!pos || opera) return; // Opera is difficult.
|
|
1660
1822
|
if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
|
|
1661
1823
|
operation(setCursor)(pos.line, pos.ch);
|
|
1662
1824
|
|
|
@@ -1671,10 +1833,10 @@ var CodeMirror = (function() {
|
|
|
1671
1833
|
selectInput(input);
|
|
1672
1834
|
function rehide() {
|
|
1673
1835
|
var newVal = splitLines(input.value).join("\n");
|
|
1674
|
-
if (newVal != val) operation(replaceSelection)(newVal, "end");
|
|
1836
|
+
if (newVal != val && !options.readOnly) operation(replaceSelection)(newVal, "end");
|
|
1675
1837
|
inputDiv.style.position = "relative";
|
|
1676
1838
|
input.style.cssText = oldCSS;
|
|
1677
|
-
if (ie_lt9)
|
|
1839
|
+
if (ie_lt9) scrollbar.scrollTop = scrollPos;
|
|
1678
1840
|
leaveInputAlone = false;
|
|
1679
1841
|
resetInput(true);
|
|
1680
1842
|
slowPoll();
|
|
@@ -1716,7 +1878,7 @@ var CodeMirror = (function() {
|
|
|
1716
1878
|
var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
|
|
1717
1879
|
for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
|
|
1718
1880
|
var text = st[i];
|
|
1719
|
-
if (st[i+1] !=
|
|
1881
|
+
if (st[i+1] != style) {pos += d * text.length; continue;}
|
|
1720
1882
|
for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
|
|
1721
1883
|
if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
|
|
1722
1884
|
var match = matching[cur];
|
|
@@ -1836,14 +1998,24 @@ var CodeMirror = (function() {
|
|
|
1836
1998
|
changes = []; selectionChanged = false; callbacks = [];
|
|
1837
1999
|
}
|
|
1838
2000
|
function endOperation() {
|
|
1839
|
-
|
|
1840
|
-
if (
|
|
1841
|
-
|
|
2001
|
+
if (updateMaxLine) computeMaxLength();
|
|
2002
|
+
if (maxLineChanged && !options.lineWrapping) {
|
|
2003
|
+
var cursorWidth = widthForcer.offsetWidth, left = stringWidth(maxLine);
|
|
2004
|
+
widthForcer.style.left = left + "px";
|
|
2005
|
+
lineSpace.style.minWidth = (left + cursorWidth) + "px";
|
|
2006
|
+
maxLineChanged = false;
|
|
2007
|
+
}
|
|
2008
|
+
var newScrollPos, updated;
|
|
2009
|
+
if (selectionChanged) {
|
|
2010
|
+
var coords = calculateCursorCoords();
|
|
2011
|
+
newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot);
|
|
2012
|
+
}
|
|
2013
|
+
if (changes.length) updated = updateDisplay(changes, true, (newScrollPos ? newScrollPos.scrollTop : null));
|
|
1842
2014
|
else {
|
|
1843
2015
|
if (selectionChanged) updateSelection();
|
|
1844
2016
|
if (gutterDirty) updateGutter();
|
|
1845
2017
|
}
|
|
1846
|
-
if (
|
|
2018
|
+
if (newScrollPos) scrollCursorIntoView();
|
|
1847
2019
|
if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
|
|
1848
2020
|
|
|
1849
2021
|
if (focused && !leaveInputAlone &&
|
|
@@ -1855,11 +2027,11 @@ var CodeMirror = (function() {
|
|
|
1855
2027
|
if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
|
|
1856
2028
|
if (posEq(sel.from, sel.to)) matchBrackets(false);
|
|
1857
2029
|
}), 20);
|
|
1858
|
-
var
|
|
1859
|
-
if (
|
|
2030
|
+
var sc = selectionChanged, cbs = callbacks; // these can be reset by callbacks
|
|
2031
|
+
if (textChanged && options.onChange && instance)
|
|
2032
|
+
options.onChange(instance, textChanged);
|
|
2033
|
+
if (sc && options.onCursorActivity)
|
|
1860
2034
|
options.onCursorActivity(instance);
|
|
1861
|
-
if (tc && options.onChange && instance)
|
|
1862
|
-
options.onChange(instance, tc);
|
|
1863
2035
|
for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
|
|
1864
2036
|
if (updated && options.onUpdate) options.onUpdate(instance);
|
|
1865
2037
|
}
|
|
@@ -1919,7 +2091,8 @@ var CodeMirror = (function() {
|
|
|
1919
2091
|
pollInterval: 100,
|
|
1920
2092
|
undoDepth: 40,
|
|
1921
2093
|
tabindex: null,
|
|
1922
|
-
autofocus: null
|
|
2094
|
+
autofocus: null,
|
|
2095
|
+
lineNumberFormatter: function(integer) { return integer; }
|
|
1923
2096
|
};
|
|
1924
2097
|
|
|
1925
2098
|
var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
|
|
@@ -2008,6 +2181,10 @@ var CodeMirror = (function() {
|
|
|
2008
2181
|
indentMore: function(cm) {cm.indentSelection("add");},
|
|
2009
2182
|
indentLess: function(cm) {cm.indentSelection("subtract");},
|
|
2010
2183
|
insertTab: function(cm) {cm.replaceSelection("\t", "end");},
|
|
2184
|
+
defaultTab: function(cm) {
|
|
2185
|
+
if (cm.somethingSelected()) cm.indentSelection("add");
|
|
2186
|
+
else cm.replaceSelection("\t", "end");
|
|
2187
|
+
},
|
|
2011
2188
|
transposeChars: function(cm) {
|
|
2012
2189
|
var cur = cm.getCursor(), line = cm.getLine(cur.line);
|
|
2013
2190
|
if (cur.ch > 0 && cur.ch < line.length - 1)
|
|
@@ -2025,7 +2202,7 @@ var CodeMirror = (function() {
|
|
|
2025
2202
|
keyMap.basic = {
|
|
2026
2203
|
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
|
|
2027
2204
|
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
|
|
2028
|
-
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "
|
|
2205
|
+
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
|
|
2029
2206
|
"Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
|
|
2030
2207
|
};
|
|
2031
2208
|
// Note that the save and find-related commands aren't defined by
|
|
@@ -2193,8 +2370,7 @@ var CodeMirror = (function() {
|
|
|
2193
2370
|
if (consume !== false) this.pos += pattern.length;
|
|
2194
2371
|
return true;
|
|
2195
2372
|
}
|
|
2196
|
-
}
|
|
2197
|
-
else {
|
|
2373
|
+
} else {
|
|
2198
2374
|
var match = this.string.slice(this.pos).match(pattern);
|
|
2199
2375
|
if (match && consume !== false) this.pos += match[0].length;
|
|
2200
2376
|
return match;
|
|
@@ -2361,11 +2537,20 @@ var CodeMirror = (function() {
|
|
|
2361
2537
|
fixMarkEnds: function(other) {
|
|
2362
2538
|
var mk = this.marked, omk = other.marked;
|
|
2363
2539
|
if (!mk) return;
|
|
2364
|
-
for (var i = 0; i < mk.length; ++i) {
|
|
2540
|
+
outer: for (var i = 0; i < mk.length; ++i) {
|
|
2365
2541
|
var mark = mk[i], close = mark.to == null;
|
|
2366
2542
|
if (close && omk) {
|
|
2367
|
-
for (var j = 0; j < omk.length; ++j)
|
|
2368
|
-
|
|
2543
|
+
for (var j = 0; j < omk.length; ++j) {
|
|
2544
|
+
var om = omk[j];
|
|
2545
|
+
if (!om.sameSet(mark) || om.from != null) continue
|
|
2546
|
+
if (mark.from == this.text.length && om.to == 0) {
|
|
2547
|
+
omk.splice(j, 1);
|
|
2548
|
+
mk.splice(i--, 1);
|
|
2549
|
+
continue outer;
|
|
2550
|
+
} else {
|
|
2551
|
+
close = false; break;
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2369
2554
|
}
|
|
2370
2555
|
if (close) mark.to = this.text.length;
|
|
2371
2556
|
}
|
|
@@ -2472,15 +2657,22 @@ var CodeMirror = (function() {
|
|
|
2472
2657
|
if (wrapWBR) html.push("<wbr>");
|
|
2473
2658
|
}
|
|
2474
2659
|
html.push(open);
|
|
2475
|
-
|
|
2660
|
+
var cut = wrapAt - outPos;
|
|
2661
|
+
span_(opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
|
|
2476
2662
|
html.push("</span>");
|
|
2663
|
+
if (opera) span_(text.slice(cut + 1), style);
|
|
2477
2664
|
wrapAt--;
|
|
2478
2665
|
outPos += l;
|
|
2479
2666
|
} else {
|
|
2480
2667
|
outPos += l;
|
|
2481
2668
|
span_(text, style);
|
|
2482
2669
|
// Output empty wrapper when at end of line
|
|
2483
|
-
|
|
2670
|
+
// (Gecko and IE8+ do strange wrapping when adding a space
|
|
2671
|
+
// to the end of the line. Other browsers don't react well
|
|
2672
|
+
// to zero-width spaces. So we do hideous browser sniffing
|
|
2673
|
+
// to determine which to use.)
|
|
2674
|
+
if (outPos == wrapAt && outPos == len)
|
|
2675
|
+
html.push(open + (gecko || (ie && !ie_lt8) ? "​" : " ") + "</span>");
|
|
2484
2676
|
// Stop outputting HTML when gone sufficiently far beyond measure
|
|
2485
2677
|
else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
|
|
2486
2678
|
}
|
|
@@ -2515,7 +2707,8 @@ var CodeMirror = (function() {
|
|
|
2515
2707
|
}
|
|
2516
2708
|
nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
|
|
2517
2709
|
for (var i = 0; i < marks.length; ++i) {
|
|
2518
|
-
var to = marks[i].to
|
|
2710
|
+
var to = marks[i].to;
|
|
2711
|
+
if (to == null) to = Infinity;
|
|
2519
2712
|
if (to == pos) marks.splice(i--, 1);
|
|
2520
2713
|
else nextChange = Math.min(to, nextChange);
|
|
2521
2714
|
}
|
|
@@ -2553,8 +2746,7 @@ var CodeMirror = (function() {
|
|
|
2553
2746
|
if (state == 0) {
|
|
2554
2747
|
if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
|
|
2555
2748
|
if (end >= from) state = 1;
|
|
2556
|
-
}
|
|
2557
|
-
else if (state == 1) {
|
|
2749
|
+
} else if (state == 1) {
|
|
2558
2750
|
if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
|
|
2559
2751
|
else dest.push(part, source[i+1]);
|
|
2560
2752
|
}
|
|
@@ -2589,11 +2781,7 @@ var CodeMirror = (function() {
|
|
|
2589
2781
|
},
|
|
2590
2782
|
insertHeight: function(at, lines, height) {
|
|
2591
2783
|
this.height += height;
|
|
2592
|
-
|
|
2593
|
-
// occasionally corrupts this.lines (duplicating elements) when
|
|
2594
|
-
// it is used.
|
|
2595
|
-
if (ie) this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
|
|
2596
|
-
else this.lines.splice.apply(this.lines, [at, 0].concat(lines));
|
|
2784
|
+
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
|
|
2597
2785
|
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
|
|
2598
2786
|
},
|
|
2599
2787
|
iterN: function(at, n, op) {
|
|
@@ -2814,10 +3002,14 @@ var CodeMirror = (function() {
|
|
|
2814
3002
|
|
|
2815
3003
|
function e_target(e) {return e.target || e.srcElement;}
|
|
2816
3004
|
function e_button(e) {
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
3005
|
+
var b = e.which;
|
|
3006
|
+
if (b == null) {
|
|
3007
|
+
if (e.button & 1) b = 1;
|
|
3008
|
+
else if (e.button & 2) b = 3;
|
|
3009
|
+
else if (e.button & 4) b = 2;
|
|
3010
|
+
}
|
|
3011
|
+
if (mac && e.ctrlKey && b == 1) b = 3;
|
|
3012
|
+
return b;
|
|
2821
3013
|
}
|
|
2822
3014
|
|
|
2823
3015
|
// Allow 3rd-party code to override event properties by adding an override
|
|
@@ -2833,8 +3025,7 @@ var CodeMirror = (function() {
|
|
|
2833
3025
|
if (typeof node.addEventListener == "function") {
|
|
2834
3026
|
node.addEventListener(type, handler, false);
|
|
2835
3027
|
if (disconnect) return function() {node.removeEventListener(type, handler, false);};
|
|
2836
|
-
}
|
|
2837
|
-
else {
|
|
3028
|
+
} else {
|
|
2838
3029
|
var wrapHandler = function(event) {handler(event || window.event);};
|
|
2839
3030
|
node.attachEvent("on" + type, wrapHandler);
|
|
2840
3031
|
if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
|
|
@@ -2849,12 +3040,15 @@ var CodeMirror = (function() {
|
|
|
2849
3040
|
|
|
2850
3041
|
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
|
|
2851
3042
|
var ie = /MSIE \d/.test(navigator.userAgent);
|
|
3043
|
+
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
|
|
2852
3044
|
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
|
|
2853
3045
|
var quirksMode = ie && document.documentMode == 5;
|
|
2854
3046
|
var webkit = /WebKit\//.test(navigator.userAgent);
|
|
2855
3047
|
var chrome = /Chrome\//.test(navigator.userAgent);
|
|
3048
|
+
var opera = /Opera\//.test(navigator.userAgent);
|
|
2856
3049
|
var safari = /Apple Computer/.test(navigator.vendor);
|
|
2857
3050
|
var khtml = /KHTML\//.test(navigator.userAgent);
|
|
3051
|
+
var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
|
|
2858
3052
|
|
|
2859
3053
|
// Detect drag-and-drop
|
|
2860
3054
|
var dragAndDrop = function() {
|
|
@@ -2904,26 +3098,7 @@ var CodeMirror = (function() {
|
|
|
2904
3098
|
return window.getComputedStyle(elt, null);
|
|
2905
3099
|
}
|
|
2906
3100
|
|
|
2907
|
-
// Find the position of an element by following the offsetParent chain.
|
|
2908
|
-
// If screen==true, it returns screen (rather than page) coordinates.
|
|
2909
3101
|
function eltOffset(node, screen) {
|
|
2910
|
-
var bod = node.ownerDocument.body;
|
|
2911
|
-
var x = 0, y = 0, skipBody = false;
|
|
2912
|
-
for (var n = node; n; n = n.offsetParent) {
|
|
2913
|
-
var ol = n.offsetLeft, ot = n.offsetTop;
|
|
2914
|
-
// Firefox reports weird inverted offsets when the body has a border.
|
|
2915
|
-
if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }
|
|
2916
|
-
else { x += ol, y += ot; }
|
|
2917
|
-
if (screen && computedStyle(n).position == "fixed")
|
|
2918
|
-
skipBody = true;
|
|
2919
|
-
}
|
|
2920
|
-
var e = screen && !skipBody ? null : bod;
|
|
2921
|
-
for (var n = node.parentNode; n != e; n = n.parentNode)
|
|
2922
|
-
if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}
|
|
2923
|
-
return {left: x, top: y};
|
|
2924
|
-
}
|
|
2925
|
-
// Use the faster and saner getBoundingClientRect method when possible.
|
|
2926
|
-
if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {
|
|
2927
3102
|
// Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
|
|
2928
3103
|
// since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
|
|
2929
3104
|
try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }
|
|
@@ -2939,7 +3114,7 @@ var CodeMirror = (function() {
|
|
|
2939
3114
|
}
|
|
2940
3115
|
}
|
|
2941
3116
|
return box;
|
|
2942
|
-
}
|
|
3117
|
+
}
|
|
2943
3118
|
|
|
2944
3119
|
// Get a node's text content.
|
|
2945
3120
|
function eltText(node) {
|
|
@@ -2964,18 +3139,19 @@ var CodeMirror = (function() {
|
|
|
2964
3139
|
}
|
|
2965
3140
|
// Recent (late 2011) Opera betas insert bogus newlines at the start
|
|
2966
3141
|
// of the textContent, so we strip those.
|
|
2967
|
-
if (htmlEscape("a") == "\na")
|
|
3142
|
+
if (htmlEscape("a") == "\na") {
|
|
2968
3143
|
htmlEscape = function(str) {
|
|
2969
3144
|
escapeElement.textContent = str;
|
|
2970
3145
|
return escapeElement.innerHTML.slice(1);
|
|
2971
3146
|
};
|
|
2972
3147
|
// Some IEs don't preserve tabs through innerHTML
|
|
2973
|
-
else if (htmlEscape("\t") != "\t")
|
|
3148
|
+
} else if (htmlEscape("\t") != "\t") {
|
|
2974
3149
|
htmlEscape = function(str) {
|
|
2975
3150
|
escapeElement.innerHTML = "";
|
|
2976
3151
|
escapeElement.appendChild(document.createTextNode(str));
|
|
2977
3152
|
return escapeElement.innerHTML;
|
|
2978
3153
|
};
|
|
3154
|
+
}
|
|
2979
3155
|
CodeMirror.htmlEscape = htmlEscape;
|
|
2980
3156
|
|
|
2981
3157
|
// Used to position the cursor after an undo/redo by finding the
|
|
@@ -3001,14 +3177,22 @@ var CodeMirror = (function() {
|
|
|
3001
3177
|
// See if "".split is the broken IE version, if so, provide an
|
|
3002
3178
|
// alternative way to split lines.
|
|
3003
3179
|
var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
|
|
3004
|
-
var pos = 0,
|
|
3005
|
-
while (
|
|
3006
|
-
|
|
3007
|
-
|
|
3180
|
+
var pos = 0, result = [], l = string.length;
|
|
3181
|
+
while (pos <= l) {
|
|
3182
|
+
var nl = string.indexOf("\n", pos);
|
|
3183
|
+
if (nl == -1) nl = string.length;
|
|
3184
|
+
var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
|
|
3185
|
+
var rt = line.indexOf("\r");
|
|
3186
|
+
if (rt != -1) {
|
|
3187
|
+
result.push(line.slice(0, rt));
|
|
3188
|
+
pos += rt + 1;
|
|
3189
|
+
} else {
|
|
3190
|
+
result.push(line);
|
|
3191
|
+
pos = nl + 1;
|
|
3192
|
+
}
|
|
3008
3193
|
}
|
|
3009
|
-
result.push(string.slice(pos));
|
|
3010
3194
|
return result;
|
|
3011
|
-
} : function(string){return string.split(/\r
|
|
3195
|
+
} : function(string){return string.split(/\r\n?|\n/);};
|
|
3012
3196
|
CodeMirror.splitLines = splitLines;
|
|
3013
3197
|
|
|
3014
3198
|
var hasSelection = window.getSelection ? function(te) {
|
|
@@ -3029,10 +3213,10 @@ var CodeMirror = (function() {
|
|
|
3029
3213
|
var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
|
|
3030
3214
|
19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
|
|
3031
3215
|
36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
|
|
3032
|
-
46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod",
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
63233: "Down", 63302: "Insert", 63272: "Delete"};
|
|
3216
|
+
46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
|
|
3217
|
+
186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
|
|
3218
|
+
221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
|
|
3219
|
+
63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
|
|
3036
3220
|
CodeMirror.keyNames = keyNames;
|
|
3037
3221
|
(function() {
|
|
3038
3222
|
// Number keys
|