Streamlined the libraries.
66
FindWinJS.ps1
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
查找 HTML 文件中引用了 "winjs" 的 link 或 script 标签行。
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
递归搜索指定目录下的所有 .html / .htm 文件,输出包含 "winjs" 字符串(不区分大小写)
|
||||||
|
的 <link href="..."> 或 <script src="..."> 标签所在的行。
|
||||||
|
|
||||||
|
.PARAMETER Path
|
||||||
|
要搜索的文件夹路径。默认为当前目录。
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Find-WinJSElements.ps1 -Path "C:\Projects\Web"
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Find-WinJSElements.ps1
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$false)]
|
||||||
|
[string]$Path = "."
|
||||||
|
)
|
||||||
|
|
||||||
|
# 检查路径是否存在
|
||||||
|
if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
|
||||||
|
Write-Error "指定的路径不存在或不是文件夹: $Path"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 正则表达式:匹配包含 "winjs" 的 link href 或 script src 标签
|
||||||
|
# 使用 (?i) 表示不区分大小写
|
||||||
|
$pattern = '(?i)<(link[^>]*?href\s*=\s*["''][^"'']*winjs[^"'']*["''][^>]*?)>|(script[^>]*?src\s*=\s*["''][^"'']*winjs[^"'']*["''][^>]*?)>'
|
||||||
|
|
||||||
|
Write-Host "正在搜索文件夹: $((Resolve-Path -LiteralPath $Path).Path)" -ForegroundColor Cyan
|
||||||
|
Write-Host "匹配模式: 包含 'winjs' 的 <link href> 或 <script src> 标签`n"
|
||||||
|
|
||||||
|
# 获取所有 .html 和 .htm 文件(不区分大小写)
|
||||||
|
$files = Get-ChildItem -LiteralPath $Path -Recurse -Include "*.html","*.htm" -File
|
||||||
|
|
||||||
|
if ($files.Count -eq 0) {
|
||||||
|
Write-Host "未找到 HTML 文件。" -ForegroundColor Yellow
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
$foundAny = $false
|
||||||
|
|
||||||
|
foreach ($file in $files) {
|
||||||
|
# 使用 Select-String 按行搜索,-CaseSensitive:$false 已隐含在 (?i) 中
|
||||||
|
$matches = Select-String -LiteralPath $file.FullName -Pattern $pattern -AllMatches
|
||||||
|
|
||||||
|
if ($matches) {
|
||||||
|
$foundAny = $true
|
||||||
|
Write-Host "`n文件: $($file.FullName)" -ForegroundColor Green
|
||||||
|
foreach ($match in $matches) {
|
||||||
|
# 输出行号和行内容(去除首尾空白)
|
||||||
|
$line = $match.Line.Trim()
|
||||||
|
Write-Host " 行 $($match.LineNumber): $line"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $foundAny) {
|
||||||
|
Write-Host "`n未找到包含 'winjs' 的 link/script 元素。" -ForegroundColor Yellow
|
||||||
|
} else {
|
||||||
|
Write-Host "`n搜索完成。" -ForegroundColor Cyan
|
||||||
|
}
|
||||||
BIN
Used Libraries/codemirror.7z
Normal file
3
Used Libraries/readme.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
The folder stores complete portions of some libraries.
|
||||||
|
|
||||||
|
Some libraries, due to their high extensibility, have unused parts. The approach taken in this case is to simplify them. However, for ease of maintenance, the complete libraries are retained.
|
||||||
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 707 B |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 707 B |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 570 B |
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,8 +0,0 @@
|
|||||||
*.txt text
|
|
||||||
*.js text
|
|
||||||
*.html text
|
|
||||||
*.md text
|
|
||||||
*.json text
|
|
||||||
*.yml text
|
|
||||||
*.css text
|
|
||||||
*.svg text
|
|
||||||
8
shared/html/libs/codemirror/5.0.0/.gitignore
vendored
@@ -1,8 +0,0 @@
|
|||||||
/node_modules
|
|
||||||
/npm-debug.log
|
|
||||||
/test*.html
|
|
||||||
.tern-*
|
|
||||||
*~
|
|
||||||
*.swp
|
|
||||||
.idea
|
|
||||||
*.iml
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.10
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
# How to contribute
|
|
||||||
|
|
||||||
- [Getting help](#getting-help-)
|
|
||||||
- [Submitting bug reports](#submitting-bug-reports-)
|
|
||||||
- [Contributing code](#contributing-code-)
|
|
||||||
|
|
||||||
## Getting help
|
|
||||||
|
|
||||||
Community discussion, questions, and informal bug reporting is done on the
|
|
||||||
[discuss.CodeMirror forum](http://discuss.codemirror.net).
|
|
||||||
|
|
||||||
## Submitting bug reports
|
|
||||||
|
|
||||||
The preferred way to report bugs is to use the
|
|
||||||
[GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before
|
|
||||||
reporting a bug, read these pointers.
|
|
||||||
|
|
||||||
**Note:** The issue tracker is for *bugs*, not requests for help. Questions
|
|
||||||
should be asked on the
|
|
||||||
[discuss.CodeMirror forum](http://discuss.codemirror.net) instead.
|
|
||||||
|
|
||||||
### Reporting bugs effectively
|
|
||||||
|
|
||||||
- CodeMirror is maintained by volunteers. They don't owe you anything, so be
|
|
||||||
polite. Reports with an indignant or belligerent tone tend to be moved to the
|
|
||||||
bottom of the pile.
|
|
||||||
|
|
||||||
- Include information about **the browser in which the problem occurred**. Even
|
|
||||||
if you tested several browsers, and the problem occurred in all of them,
|
|
||||||
mention this fact in the bug report. Also include browser version numbers and
|
|
||||||
the operating system that you're on.
|
|
||||||
|
|
||||||
- Mention which release of CodeMirror you're using. Preferably, try also with
|
|
||||||
the current development snapshot, to ensure the problem has not already been
|
|
||||||
fixed.
|
|
||||||
|
|
||||||
- Mention very precisely what went wrong. "X is broken" is not a good bug
|
|
||||||
report. What did you expect to happen? What happened instead? Describe the
|
|
||||||
exact steps a maintainer has to take to make the problem occur. We can not
|
|
||||||
fix something that we can not observe.
|
|
||||||
|
|
||||||
- If the problem can not be reproduced in any of the demos included in the
|
|
||||||
CodeMirror distribution, please provide an HTML document that demonstrates
|
|
||||||
the problem. The best way to do this is to go to
|
|
||||||
[jsbin.com](http://jsbin.com/ihunin/edit), enter it there, press save, and
|
|
||||||
include the resulting link in your bug report.
|
|
||||||
|
|
||||||
## Contributing code
|
|
||||||
|
|
||||||
- Make sure you have a [GitHub Account](https://github.com/signup/free)
|
|
||||||
- Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)
|
|
||||||
([how to fork a repo](https://help.github.com/articles/fork-a-repo))
|
|
||||||
- Make your changes
|
|
||||||
- If your changes are easy to test or likely to regress, add tests.
|
|
||||||
Tests for the core go into `test/test.js`, some modes have their own
|
|
||||||
test suite under `mode/XXX/test.js`. Feel free to add new test
|
|
||||||
suites to modes that don't have one yet (be sure to link the new
|
|
||||||
tests into `test/index.html`).
|
|
||||||
- Follow the general code style of the rest of the project (see
|
|
||||||
below). Run `bin/lint` to verify that the linter is happy.
|
|
||||||
- Make sure all tests pass. Visit `test/index.html` in your browser to
|
|
||||||
run them.
|
|
||||||
- Submit a pull request
|
|
||||||
([how to create a pull request](https://help.github.com/articles/fork-a-repo))
|
|
||||||
|
|
||||||
### Coding standards
|
|
||||||
|
|
||||||
- 2 spaces per indentation level, no tabs.
|
|
||||||
- Include semicolons after statements.
|
|
||||||
- Note that the linter (`bin/lint`) which is run after each commit
|
|
||||||
complains about unused variables and functions. Prefix their names
|
|
||||||
with an underscore to muffle it.
|
|
||||||
|
|
||||||
- CodeMirror does *not* follow JSHint or JSLint prescribed style.
|
|
||||||
Patches that try to 'fix' code to pass one of these linters will be
|
|
||||||
unceremoniously discarded.
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# CodeMirror
|
|
||||||
[](https://travis-ci.org/codemirror/CodeMirror)
|
|
||||||
[](https://www.npmjs.org/package/codemirror)
|
|
||||||
[Funding status: ](https://marijnhaverbeke.nl/fund/)
|
|
||||||
|
|
||||||
CodeMirror is a JavaScript component that provides a code editor in
|
|
||||||
the browser. When a mode is available for the language you are coding
|
|
||||||
in, it will color your code, and optionally help with indentation.
|
|
||||||
|
|
||||||
The project page is http://codemirror.net
|
|
||||||
The manual is at http://codemirror.net/doc/manual.html
|
|
||||||
The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
.CodeMirror-dialog {
|
|
||||||
position: absolute;
|
|
||||||
left: 0; right: 0;
|
|
||||||
background: white;
|
|
||||||
z-index: 15;
|
|
||||||
padding: .1em .8em;
|
|
||||||
overflow: hidden;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-dialog-top {
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-dialog-bottom {
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-dialog input {
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
background: transparent;
|
|
||||||
width: 20em;
|
|
||||||
color: inherit;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-dialog button {
|
|
||||||
font-size: 70%;
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// Open simple dialogs on top of an editor. Relies on dialog.css.
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
function dialogDiv(cm, template, bottom) {
|
|
||||||
var wrap = cm.getWrapperElement();
|
|
||||||
var dialog;
|
|
||||||
dialog = wrap.appendChild(document.createElement("div"));
|
|
||||||
if (bottom)
|
|
||||||
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
|
|
||||||
else
|
|
||||||
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
|
|
||||||
|
|
||||||
if (typeof template == "string") {
|
|
||||||
dialog.innerHTML = template;
|
|
||||||
} else { // Assuming it's a detached DOM element.
|
|
||||||
dialog.appendChild(template);
|
|
||||||
}
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeNotification(cm, newVal) {
|
|
||||||
if (cm.state.currentNotificationClose)
|
|
||||||
cm.state.currentNotificationClose();
|
|
||||||
cm.state.currentNotificationClose = newVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeMirror.defineExtension("openDialog", function(template, callback, options) {
|
|
||||||
if (!options) options = {};
|
|
||||||
|
|
||||||
closeNotification(this, null);
|
|
||||||
|
|
||||||
var dialog = dialogDiv(this, template, options.bottom);
|
|
||||||
var closed = false, me = this;
|
|
||||||
function close(newVal) {
|
|
||||||
if (typeof newVal == 'string') {
|
|
||||||
inp.value = newVal;
|
|
||||||
} else {
|
|
||||||
if (closed) return;
|
|
||||||
closed = true;
|
|
||||||
dialog.parentNode.removeChild(dialog);
|
|
||||||
me.focus();
|
|
||||||
|
|
||||||
if (options.onClose) options.onClose(dialog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var inp = dialog.getElementsByTagName("input")[0], button;
|
|
||||||
if (inp) {
|
|
||||||
if (options.value) {
|
|
||||||
inp.value = options.value;
|
|
||||||
inp.select();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.onInput)
|
|
||||||
CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
|
|
||||||
if (options.onKeyUp)
|
|
||||||
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
|
|
||||||
|
|
||||||
CodeMirror.on(inp, "keydown", function(e) {
|
|
||||||
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
|
|
||||||
if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
|
|
||||||
inp.blur();
|
|
||||||
CodeMirror.e_stop(e);
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
if (e.keyCode == 13) callback(inp.value, e);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
|
|
||||||
|
|
||||||
inp.focus();
|
|
||||||
} else if (button = dialog.getElementsByTagName("button")[0]) {
|
|
||||||
CodeMirror.on(button, "click", function() {
|
|
||||||
close();
|
|
||||||
me.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
|
|
||||||
|
|
||||||
button.focus();
|
|
||||||
}
|
|
||||||
return close;
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
|
|
||||||
closeNotification(this, null);
|
|
||||||
var dialog = dialogDiv(this, template, options && options.bottom);
|
|
||||||
var buttons = dialog.getElementsByTagName("button");
|
|
||||||
var closed = false, me = this, blurring = 1;
|
|
||||||
function close() {
|
|
||||||
if (closed) return;
|
|
||||||
closed = true;
|
|
||||||
dialog.parentNode.removeChild(dialog);
|
|
||||||
me.focus();
|
|
||||||
}
|
|
||||||
buttons[0].focus();
|
|
||||||
for (var i = 0; i < buttons.length; ++i) {
|
|
||||||
var b = buttons[i];
|
|
||||||
(function(callback) {
|
|
||||||
CodeMirror.on(b, "click", function(e) {
|
|
||||||
CodeMirror.e_preventDefault(e);
|
|
||||||
close();
|
|
||||||
if (callback) callback(me);
|
|
||||||
});
|
|
||||||
})(callbacks[i]);
|
|
||||||
CodeMirror.on(b, "blur", function() {
|
|
||||||
--blurring;
|
|
||||||
setTimeout(function() { if (blurring <= 0) close(); }, 200);
|
|
||||||
});
|
|
||||||
CodeMirror.on(b, "focus", function() { ++blurring; });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
* openNotification
|
|
||||||
* Opens a notification, that can be closed with an optional timer
|
|
||||||
* (default 5000ms timer) and always closes on click.
|
|
||||||
*
|
|
||||||
* If a notification is opened while another is opened, it will close the
|
|
||||||
* currently opened one and open the new one immediately.
|
|
||||||
*/
|
|
||||||
CodeMirror.defineExtension("openNotification", function(template, options) {
|
|
||||||
closeNotification(this, close);
|
|
||||||
var dialog = dialogDiv(this, template, options && options.bottom);
|
|
||||||
var closed = false, doneTimer;
|
|
||||||
var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
|
|
||||||
|
|
||||||
function close() {
|
|
||||||
if (closed) return;
|
|
||||||
closed = true;
|
|
||||||
clearTimeout(doneTimer);
|
|
||||||
dialog.parentNode.removeChild(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeMirror.on(dialog, 'click', function(e) {
|
|
||||||
CodeMirror.e_preventDefault(e);
|
|
||||||
close();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (duration)
|
|
||||||
doneTimer = setTimeout(close, duration);
|
|
||||||
|
|
||||||
return close;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
.CodeMirror-merge {
|
|
||||||
position: relative;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
|
|
||||||
height: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
|
|
||||||
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
|
|
||||||
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
|
|
||||||
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
|
|
||||||
|
|
||||||
.CodeMirror-merge-pane {
|
|
||||||
display: inline-block;
|
|
||||||
white-space: normal;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
.CodeMirror-merge-pane-rightmost {
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-gap {
|
|
||||||
z-index: 2;
|
|
||||||
display: inline-block;
|
|
||||||
height: 100%;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
border-left: 1px solid #ddd;
|
|
||||||
border-right: 1px solid #ddd;
|
|
||||||
position: relative;
|
|
||||||
background: #f8f8f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-scrolllock-wrap {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0; left: 50%;
|
|
||||||
}
|
|
||||||
.CodeMirror-merge-scrolllock {
|
|
||||||
position: relative;
|
|
||||||
left: -50%;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #555;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
|
|
||||||
position: absolute;
|
|
||||||
left: 0; top: 0;
|
|
||||||
right: 0; bottom: 0;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-copy {
|
|
||||||
position: absolute;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #44c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-copy-reverse {
|
|
||||||
position: absolute;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #44c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
|
|
||||||
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
|
|
||||||
|
|
||||||
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
|
|
||||||
background-position: bottom left;
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
|
|
||||||
background-position: bottom left;
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-merge-r-chunk { background: #ffffe0; }
|
|
||||||
.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
|
|
||||||
.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
|
|
||||||
.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
|
|
||||||
|
|
||||||
.CodeMirror-merge-l-chunk { background: #eef; }
|
|
||||||
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
|
|
||||||
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
|
|
||||||
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
|
|
||||||
|
|
||||||
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
|
|
||||||
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
|
|
||||||
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
|
|
||||||
|
|
||||||
.CodeMirror-merge-collapsed-widget:before {
|
|
||||||
content: "(...)";
|
|
||||||
}
|
|
||||||
.CodeMirror-merge-collapsed-widget {
|
|
||||||
cursor: pointer;
|
|
||||||
color: #88b;
|
|
||||||
background: #eef;
|
|
||||||
border: 1px solid #ddf;
|
|
||||||
font-size: 90%;
|
|
||||||
padding: 0 3px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
|
|
||||||
@@ -1,735 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"), require("diff_match_patch"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror", "diff_match_patch"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror, diff_match_patch);
|
|
||||||
})(function(CodeMirror, diff_match_patch) {
|
|
||||||
"use strict";
|
|
||||||
var Pos = CodeMirror.Pos;
|
|
||||||
var svgNS = "http://www.w3.org/2000/svg";
|
|
||||||
|
|
||||||
function DiffView(mv, type) {
|
|
||||||
this.mv = mv;
|
|
||||||
this.type = type;
|
|
||||||
this.classes = type == "left"
|
|
||||||
? {chunk: "CodeMirror-merge-l-chunk",
|
|
||||||
start: "CodeMirror-merge-l-chunk-start",
|
|
||||||
end: "CodeMirror-merge-l-chunk-end",
|
|
||||||
insert: "CodeMirror-merge-l-inserted",
|
|
||||||
del: "CodeMirror-merge-l-deleted",
|
|
||||||
connect: "CodeMirror-merge-l-connect"}
|
|
||||||
: {chunk: "CodeMirror-merge-r-chunk",
|
|
||||||
start: "CodeMirror-merge-r-chunk-start",
|
|
||||||
end: "CodeMirror-merge-r-chunk-end",
|
|
||||||
insert: "CodeMirror-merge-r-inserted",
|
|
||||||
del: "CodeMirror-merge-r-deleted",
|
|
||||||
connect: "CodeMirror-merge-r-connect"};
|
|
||||||
}
|
|
||||||
|
|
||||||
DiffView.prototype = {
|
|
||||||
constructor: DiffView,
|
|
||||||
init: function(pane, orig, options) {
|
|
||||||
this.edit = this.mv.edit;
|
|
||||||
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
|
|
||||||
|
|
||||||
this.diff = getDiff(asString(orig), asString(options.value));
|
|
||||||
this.chunks = getChunks(this.diff);
|
|
||||||
this.diffOutOfDate = this.dealigned = false;
|
|
||||||
|
|
||||||
this.showDifferences = options.showDifferences !== false;
|
|
||||||
this.forceUpdate = registerUpdate(this);
|
|
||||||
setScrollLock(this, true, false);
|
|
||||||
registerScroll(this);
|
|
||||||
},
|
|
||||||
setShowDifferences: function(val) {
|
|
||||||
val = val !== false;
|
|
||||||
if (val != this.showDifferences) {
|
|
||||||
this.showDifferences = val;
|
|
||||||
this.forceUpdate("full");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function ensureDiff(dv) {
|
|
||||||
if (dv.diffOutOfDate) {
|
|
||||||
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
|
|
||||||
dv.chunks = getChunks(dv.diff);
|
|
||||||
dv.diffOutOfDate = false;
|
|
||||||
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var updating = false;
|
|
||||||
function registerUpdate(dv) {
|
|
||||||
var edit = {from: 0, to: 0, marked: []};
|
|
||||||
var orig = {from: 0, to: 0, marked: []};
|
|
||||||
var debounceChange, updatingFast = false;
|
|
||||||
function update(mode) {
|
|
||||||
updating = true;
|
|
||||||
updatingFast = false;
|
|
||||||
if (mode == "full") {
|
|
||||||
if (dv.svg) clear(dv.svg);
|
|
||||||
if (dv.copyButtons) clear(dv.copyButtons);
|
|
||||||
clearMarks(dv.edit, edit.marked, dv.classes);
|
|
||||||
clearMarks(dv.orig, orig.marked, dv.classes);
|
|
||||||
edit.from = edit.to = orig.from = orig.to = 0;
|
|
||||||
}
|
|
||||||
ensureDiff(dv);
|
|
||||||
if (dv.showDifferences) {
|
|
||||||
updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
|
|
||||||
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
|
|
||||||
}
|
|
||||||
makeConnections(dv);
|
|
||||||
|
|
||||||
if (dv.mv.options.connect == "align")
|
|
||||||
alignChunks(dv);
|
|
||||||
updating = false;
|
|
||||||
}
|
|
||||||
function setDealign(fast) {
|
|
||||||
if (updating) return;
|
|
||||||
dv.dealigned = true;
|
|
||||||
set(fast);
|
|
||||||
}
|
|
||||||
function set(fast) {
|
|
||||||
if (updating || updatingFast) return;
|
|
||||||
clearTimeout(debounceChange);
|
|
||||||
if (fast === true) updatingFast = true;
|
|
||||||
debounceChange = setTimeout(update, fast === true ? 20 : 250);
|
|
||||||
}
|
|
||||||
function change(_cm, change) {
|
|
||||||
if (!dv.diffOutOfDate) {
|
|
||||||
dv.diffOutOfDate = true;
|
|
||||||
edit.from = edit.to = orig.from = orig.to = 0;
|
|
||||||
}
|
|
||||||
// Update faster when a line was added/removed
|
|
||||||
setDealign(change.text.length - 1 != change.to.line - change.from.line);
|
|
||||||
}
|
|
||||||
dv.edit.on("change", change);
|
|
||||||
dv.orig.on("change", change);
|
|
||||||
dv.edit.on("markerAdded", setDealign);
|
|
||||||
dv.edit.on("markerCleared", setDealign);
|
|
||||||
dv.orig.on("markerAdded", setDealign);
|
|
||||||
dv.orig.on("markerCleared", setDealign);
|
|
||||||
dv.edit.on("viewportChange", function() { set(false); });
|
|
||||||
dv.orig.on("viewportChange", function() { set(false); });
|
|
||||||
update();
|
|
||||||
return update;
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerScroll(dv) {
|
|
||||||
dv.edit.on("scroll", function() {
|
|
||||||
syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
|
|
||||||
});
|
|
||||||
dv.orig.on("scroll", function() {
|
|
||||||
syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncScroll(dv, type) {
|
|
||||||
// Change handler will do a refresh after a timeout when diff is out of date
|
|
||||||
if (dv.diffOutOfDate) return false;
|
|
||||||
if (!dv.lockScroll) return true;
|
|
||||||
var editor, other, now = +new Date;
|
|
||||||
if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
|
|
||||||
else { editor = dv.orig; other = dv.edit; }
|
|
||||||
// Don't take action if the position of this editor was recently set
|
|
||||||
// (to prevent feedback loops)
|
|
||||||
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
|
|
||||||
|
|
||||||
var sInfo = editor.getScrollInfo();
|
|
||||||
if (dv.mv.options.connect == "align") {
|
|
||||||
targetPos = sInfo.top;
|
|
||||||
} else {
|
|
||||||
var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
|
|
||||||
var mid = editor.lineAtHeight(midY, "local");
|
|
||||||
var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
|
|
||||||
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
|
|
||||||
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
|
|
||||||
var ratio = (midY - off.top) / (off.bot - off.top);
|
|
||||||
var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
|
|
||||||
|
|
||||||
var botDist, mix;
|
|
||||||
// Some careful tweaking to make sure no space is left out of view
|
|
||||||
// when scrolling to top or bottom.
|
|
||||||
if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
|
|
||||||
targetPos = targetPos * mix + sInfo.top * (1 - mix);
|
|
||||||
} else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
|
|
||||||
var otherInfo = other.getScrollInfo();
|
|
||||||
var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
|
|
||||||
if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
|
|
||||||
targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
other.scrollTo(sInfo.left, targetPos);
|
|
||||||
other.state.scrollSetAt = now;
|
|
||||||
other.state.scrollSetBy = dv;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOffsets(editor, around) {
|
|
||||||
var bot = around.after;
|
|
||||||
if (bot == null) bot = editor.lastLine() + 1;
|
|
||||||
return {top: editor.heightAtLine(around.before || 0, "local"),
|
|
||||||
bot: editor.heightAtLine(bot, "local")};
|
|
||||||
}
|
|
||||||
|
|
||||||
function setScrollLock(dv, val, action) {
|
|
||||||
dv.lockScroll = val;
|
|
||||||
if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
|
|
||||||
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db \u21da";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updating the marks for editor content
|
|
||||||
|
|
||||||
function clearMarks(editor, arr, classes) {
|
|
||||||
for (var i = 0; i < arr.length; ++i) {
|
|
||||||
var mark = arr[i];
|
|
||||||
if (mark instanceof CodeMirror.TextMarker) {
|
|
||||||
mark.clear();
|
|
||||||
} else if (mark.parent) {
|
|
||||||
editor.removeLineClass(mark, "background", classes.chunk);
|
|
||||||
editor.removeLineClass(mark, "background", classes.start);
|
|
||||||
editor.removeLineClass(mark, "background", classes.end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arr.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME maybe add a margin around viewport to prevent too many updates
|
|
||||||
function updateMarks(editor, diff, state, type, classes) {
|
|
||||||
var vp = editor.getViewport();
|
|
||||||
editor.operation(function() {
|
|
||||||
if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
|
|
||||||
clearMarks(editor, state.marked, classes);
|
|
||||||
markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);
|
|
||||||
state.from = vp.from; state.to = vp.to;
|
|
||||||
} else {
|
|
||||||
if (vp.from < state.from) {
|
|
||||||
markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);
|
|
||||||
state.from = vp.from;
|
|
||||||
}
|
|
||||||
if (vp.to > state.to) {
|
|
||||||
markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);
|
|
||||||
state.to = vp.to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function markChanges(editor, diff, type, marks, from, to, classes) {
|
|
||||||
var pos = Pos(0, 0);
|
|
||||||
var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
|
|
||||||
var cls = type == DIFF_DELETE ? classes.del : classes.insert;
|
|
||||||
function markChunk(start, end) {
|
|
||||||
var bfrom = Math.max(from, start), bto = Math.min(to, end);
|
|
||||||
for (var i = bfrom; i < bto; ++i) {
|
|
||||||
var line = editor.addLineClass(i, "background", classes.chunk);
|
|
||||||
if (i == start) editor.addLineClass(line, "background", classes.start);
|
|
||||||
if (i == end - 1) editor.addLineClass(line, "background", classes.end);
|
|
||||||
marks.push(line);
|
|
||||||
}
|
|
||||||
// When the chunk is empty, make sure a horizontal line shows up
|
|
||||||
if (start == end && bfrom == end && bto == end) {
|
|
||||||
if (bfrom)
|
|
||||||
marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
|
|
||||||
else
|
|
||||||
marks.push(editor.addLineClass(bfrom, "background", classes.start));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var chunkStart = 0;
|
|
||||||
for (var i = 0; i < diff.length; ++i) {
|
|
||||||
var part = diff[i], tp = part[0], str = part[1];
|
|
||||||
if (tp == DIFF_EQUAL) {
|
|
||||||
var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);
|
|
||||||
moveOver(pos, str);
|
|
||||||
var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
|
|
||||||
if (cleanTo > cleanFrom) {
|
|
||||||
if (i) markChunk(chunkStart, cleanFrom);
|
|
||||||
chunkStart = cleanTo;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tp == type) {
|
|
||||||
var end = moveOver(pos, str, true);
|
|
||||||
var a = posMax(top, pos), b = posMin(bot, end);
|
|
||||||
if (!posEq(a, b))
|
|
||||||
marks.push(editor.markText(a, b, {className: cls}));
|
|
||||||
pos = end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updating the gap between editor and original
|
|
||||||
|
|
||||||
function makeConnections(dv) {
|
|
||||||
if (!dv.showDifferences) return;
|
|
||||||
|
|
||||||
if (dv.svg) {
|
|
||||||
clear(dv.svg);
|
|
||||||
var w = dv.gap.offsetWidth;
|
|
||||||
attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
|
|
||||||
}
|
|
||||||
if (dv.copyButtons) clear(dv.copyButtons);
|
|
||||||
|
|
||||||
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
|
|
||||||
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
|
|
||||||
for (var i = 0; i < dv.chunks.length; i++) {
|
|
||||||
var ch = dv.chunks[i];
|
|
||||||
if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
|
|
||||||
ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)
|
|
||||||
drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMatchingOrigLine(editLine, chunks) {
|
|
||||||
var editStart = 0, origStart = 0;
|
|
||||||
for (var i = 0; i < chunks.length; i++) {
|
|
||||||
var chunk = chunks[i];
|
|
||||||
if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;
|
|
||||||
if (chunk.editFrom > editLine) break;
|
|
||||||
editStart = chunk.editTo;
|
|
||||||
origStart = chunk.origTo;
|
|
||||||
}
|
|
||||||
return origStart + (editLine - editStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
function findAlignedLines(dv, other) {
|
|
||||||
var linesToAlign = [];
|
|
||||||
for (var i = 0; i < dv.chunks.length; i++) {
|
|
||||||
var chunk = dv.chunks[i];
|
|
||||||
linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
|
|
||||||
}
|
|
||||||
if (other) {
|
|
||||||
for (var i = 0; i < other.chunks.length; i++) {
|
|
||||||
var chunk = other.chunks[i];
|
|
||||||
for (var j = 0; j < linesToAlign.length; j++) {
|
|
||||||
var align = linesToAlign[j];
|
|
||||||
if (align[1] == chunk.editTo) {
|
|
||||||
j = -1;
|
|
||||||
break;
|
|
||||||
} else if (align[1] > chunk.editTo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (j > -1)
|
|
||||||
linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return linesToAlign;
|
|
||||||
}
|
|
||||||
|
|
||||||
function alignChunks(dv, force) {
|
|
||||||
if (!dv.dealigned && !force) return;
|
|
||||||
if (!dv.orig.curOp) return dv.orig.operation(function() {
|
|
||||||
alignChunks(dv, force);
|
|
||||||
});
|
|
||||||
|
|
||||||
dv.dealigned = false;
|
|
||||||
var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;
|
|
||||||
if (other) {
|
|
||||||
ensureDiff(other);
|
|
||||||
other.dealigned = false;
|
|
||||||
}
|
|
||||||
var linesToAlign = findAlignedLines(dv, other);
|
|
||||||
|
|
||||||
// Clear old aligners
|
|
||||||
var aligners = dv.mv.aligners;
|
|
||||||
for (var i = 0; i < aligners.length; i++)
|
|
||||||
aligners[i].clear();
|
|
||||||
aligners.length = 0;
|
|
||||||
|
|
||||||
var cm = [dv.orig, dv.edit], scroll = [];
|
|
||||||
if (other) cm.push(other.orig);
|
|
||||||
for (var i = 0; i < cm.length; i++)
|
|
||||||
scroll.push(cm[i].getScrollInfo().top);
|
|
||||||
|
|
||||||
for (var ln = 0; ln < linesToAlign.length; ln++)
|
|
||||||
alignLines(cm, linesToAlign[ln], aligners);
|
|
||||||
|
|
||||||
for (var i = 0; i < cm.length; i++)
|
|
||||||
cm[i].scrollTo(null, scroll[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function alignLines(cm, lines, aligners) {
|
|
||||||
var maxOffset = 0, offset = [];
|
|
||||||
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
|
|
||||||
var off = cm[i].heightAtLine(lines[i], "local");
|
|
||||||
offset[i] = off;
|
|
||||||
maxOffset = Math.max(maxOffset, off);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
|
|
||||||
var diff = maxOffset - offset[i];
|
|
||||||
if (diff > 1)
|
|
||||||
aligners.push(padAbove(cm[i], lines[i], diff));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function padAbove(cm, line, size) {
|
|
||||||
var above = true;
|
|
||||||
if (line > cm.lastLine()) {
|
|
||||||
line--;
|
|
||||||
above = false;
|
|
||||||
}
|
|
||||||
var elt = document.createElement("div");
|
|
||||||
elt.className = "CodeMirror-merge-spacer";
|
|
||||||
elt.style.height = size + "px"; elt.style.minWidth = "1px";
|
|
||||||
return cm.addLineWidget(line, elt, {height: size, above: above});
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
|
|
||||||
var flip = dv.type == "left";
|
|
||||||
var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
|
|
||||||
if (dv.svg) {
|
|
||||||
var topLpx = top;
|
|
||||||
var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
|
|
||||||
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
|
|
||||||
var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
|
|
||||||
var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
|
|
||||||
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
|
|
||||||
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
|
|
||||||
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
|
|
||||||
attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
|
|
||||||
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
|
|
||||||
"class", dv.classes.connect);
|
|
||||||
}
|
|
||||||
if (dv.copyButtons) {
|
|
||||||
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
|
|
||||||
"CodeMirror-merge-copy"));
|
|
||||||
var editOriginals = dv.mv.options.allowEditingOriginals;
|
|
||||||
copy.title = editOriginals ? "Push to left" : "Revert chunk";
|
|
||||||
copy.chunk = chunk;
|
|
||||||
copy.style.top = top + "px";
|
|
||||||
|
|
||||||
if (editOriginals) {
|
|
||||||
var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
|
|
||||||
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
|
|
||||||
"CodeMirror-merge-copy-reverse"));
|
|
||||||
copyReverse.title = "Push to right";
|
|
||||||
copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,
|
|
||||||
origFrom: chunk.editFrom, origTo: chunk.editTo};
|
|
||||||
copyReverse.style.top = topReverse + "px";
|
|
||||||
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyChunk(dv, to, from, chunk) {
|
|
||||||
if (dv.diffOutOfDate) return;
|
|
||||||
to.replaceRange(from.getRange(Pos(chunk.origFrom, 0), Pos(chunk.origTo, 0)),
|
|
||||||
Pos(chunk.editFrom, 0), Pos(chunk.editTo, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge view, containing 0, 1, or 2 diff views.
|
|
||||||
|
|
||||||
var MergeView = CodeMirror.MergeView = function(node, options) {
|
|
||||||
if (!(this instanceof MergeView)) return new MergeView(node, options);
|
|
||||||
|
|
||||||
this.options = options;
|
|
||||||
var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
|
|
||||||
|
|
||||||
var hasLeft = origLeft != null, hasRight = origRight != null;
|
|
||||||
var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
|
|
||||||
var wrap = [], left = this.left = null, right = this.right = null;
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (hasLeft) {
|
|
||||||
left = this.left = new DiffView(this, "left");
|
|
||||||
var leftPane = elt("div", null, "CodeMirror-merge-pane");
|
|
||||||
wrap.push(leftPane);
|
|
||||||
wrap.push(buildGap(left));
|
|
||||||
}
|
|
||||||
|
|
||||||
var editPane = elt("div", null, "CodeMirror-merge-pane");
|
|
||||||
wrap.push(editPane);
|
|
||||||
|
|
||||||
if (hasRight) {
|
|
||||||
right = this.right = new DiffView(this, "right");
|
|
||||||
wrap.push(buildGap(right));
|
|
||||||
var rightPane = elt("div", null, "CodeMirror-merge-pane");
|
|
||||||
wrap.push(rightPane);
|
|
||||||
}
|
|
||||||
|
|
||||||
(hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
|
|
||||||
|
|
||||||
wrap.push(elt("div", null, null, "height: 0; clear: both;"));
|
|
||||||
|
|
||||||
var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
|
|
||||||
this.edit = CodeMirror(editPane, copyObj(options));
|
|
||||||
|
|
||||||
if (left) left.init(leftPane, origLeft, options);
|
|
||||||
if (right) right.init(rightPane, origRight, options);
|
|
||||||
|
|
||||||
if (options.collapseIdentical) {
|
|
||||||
updating = true;
|
|
||||||
this.editor().operation(function() {
|
|
||||||
collapseIdenticalStretches(self, options.collapseIdentical);
|
|
||||||
});
|
|
||||||
updating = false;
|
|
||||||
}
|
|
||||||
if (options.connect == "align") {
|
|
||||||
this.aligners = [];
|
|
||||||
alignChunks(this.left || this.right, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
var onResize = function() {
|
|
||||||
if (left) makeConnections(left);
|
|
||||||
if (right) makeConnections(right);
|
|
||||||
};
|
|
||||||
CodeMirror.on(window, "resize", onResize);
|
|
||||||
var resizeInterval = setInterval(function() {
|
|
||||||
for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}
|
|
||||||
if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }
|
|
||||||
}, 5000);
|
|
||||||
};
|
|
||||||
|
|
||||||
function buildGap(dv) {
|
|
||||||
var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
|
|
||||||
lock.title = "Toggle locked scrolling";
|
|
||||||
var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
|
|
||||||
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
|
|
||||||
var gapElts = [lockWrap];
|
|
||||||
if (dv.mv.options.revertButtons !== false) {
|
|
||||||
dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
|
|
||||||
CodeMirror.on(dv.copyButtons, "click", function(e) {
|
|
||||||
var node = e.target || e.srcElement;
|
|
||||||
if (!node.chunk) return;
|
|
||||||
if (node.className == "CodeMirror-merge-copy-reverse") {
|
|
||||||
copyChunk(dv, dv.orig, dv.edit, node.chunk);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
copyChunk(dv, dv.edit, dv.orig, node.chunk);
|
|
||||||
});
|
|
||||||
gapElts.unshift(dv.copyButtons);
|
|
||||||
}
|
|
||||||
if (dv.mv.options.connect != "align") {
|
|
||||||
var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
|
|
||||||
if (svg && !svg.createSVGRect) svg = null;
|
|
||||||
dv.svg = svg;
|
|
||||||
if (svg) gapElts.push(svg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
|
|
||||||
}
|
|
||||||
|
|
||||||
MergeView.prototype = {
|
|
||||||
constuctor: MergeView,
|
|
||||||
editor: function() { return this.edit; },
|
|
||||||
rightOriginal: function() { return this.right && this.right.orig; },
|
|
||||||
leftOriginal: function() { return this.left && this.left.orig; },
|
|
||||||
setShowDifferences: function(val) {
|
|
||||||
if (this.right) this.right.setShowDifferences(val);
|
|
||||||
if (this.left) this.left.setShowDifferences(val);
|
|
||||||
},
|
|
||||||
rightChunks: function() {
|
|
||||||
if (this.right) { ensureDiff(this.right); return this.right.chunks; }
|
|
||||||
},
|
|
||||||
leftChunks: function() {
|
|
||||||
if (this.left) { ensureDiff(this.left); return this.left.chunks; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function asString(obj) {
|
|
||||||
if (typeof obj == "string") return obj;
|
|
||||||
else return obj.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operations on diffs
|
|
||||||
|
|
||||||
var dmp = new diff_match_patch();
|
|
||||||
function getDiff(a, b) {
|
|
||||||
var diff = dmp.diff_main(a, b);
|
|
||||||
dmp.diff_cleanupSemantic(diff);
|
|
||||||
// The library sometimes leaves in empty parts, which confuse the algorithm
|
|
||||||
for (var i = 0; i < diff.length; ++i) {
|
|
||||||
var part = diff[i];
|
|
||||||
if (!part[1]) {
|
|
||||||
diff.splice(i--, 1);
|
|
||||||
} else if (i && diff[i - 1][0] == part[0]) {
|
|
||||||
diff.splice(i--, 1);
|
|
||||||
diff[i][1] += part[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChunks(diff) {
|
|
||||||
var chunks = [];
|
|
||||||
var startEdit = 0, startOrig = 0;
|
|
||||||
var edit = Pos(0, 0), orig = Pos(0, 0);
|
|
||||||
for (var i = 0; i < diff.length; ++i) {
|
|
||||||
var part = diff[i], tp = part[0];
|
|
||||||
if (tp == DIFF_EQUAL) {
|
|
||||||
var startOff = startOfLineClean(diff, i) ? 0 : 1;
|
|
||||||
var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
|
|
||||||
moveOver(edit, part[1], null, orig);
|
|
||||||
var endOff = endOfLineClean(diff, i) ? 1 : 0;
|
|
||||||
var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
|
|
||||||
if (cleanToEdit > cleanFromEdit) {
|
|
||||||
if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,
|
|
||||||
editFrom: startEdit, editTo: cleanFromEdit});
|
|
||||||
startEdit = cleanToEdit; startOrig = cleanToOrig;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (startEdit <= edit.line || startOrig <= orig.line)
|
|
||||||
chunks.push({origFrom: startOrig, origTo: orig.line + 1,
|
|
||||||
editFrom: startEdit, editTo: edit.line + 1});
|
|
||||||
return chunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
function endOfLineClean(diff, i) {
|
|
||||||
if (i == diff.length - 1) return true;
|
|
||||||
var next = diff[i + 1][1];
|
|
||||||
if (next.length == 1 || next.charCodeAt(0) != 10) return false;
|
|
||||||
if (i == diff.length - 2) return true;
|
|
||||||
next = diff[i + 2][1];
|
|
||||||
return next.length > 1 && next.charCodeAt(0) == 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
function startOfLineClean(diff, i) {
|
|
||||||
if (i == 0) return true;
|
|
||||||
var last = diff[i - 1][1];
|
|
||||||
if (last.charCodeAt(last.length - 1) != 10) return false;
|
|
||||||
if (i == 1) return true;
|
|
||||||
last = diff[i - 2][1];
|
|
||||||
return last.charCodeAt(last.length - 1) == 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
function chunkBoundariesAround(chunks, n, nInEdit) {
|
|
||||||
var beforeE, afterE, beforeO, afterO;
|
|
||||||
for (var i = 0; i < chunks.length; i++) {
|
|
||||||
var chunk = chunks[i];
|
|
||||||
var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;
|
|
||||||
var toLocal = nInEdit ? chunk.editTo : chunk.origTo;
|
|
||||||
if (afterE == null) {
|
|
||||||
if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }
|
|
||||||
else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }
|
|
||||||
}
|
|
||||||
if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }
|
|
||||||
else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }
|
|
||||||
}
|
|
||||||
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
|
|
||||||
}
|
|
||||||
|
|
||||||
function collapseSingle(cm, from, to) {
|
|
||||||
cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
|
|
||||||
var widget = document.createElement("span");
|
|
||||||
widget.className = "CodeMirror-merge-collapsed-widget";
|
|
||||||
widget.title = "Identical text collapsed. Click to expand.";
|
|
||||||
var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
|
|
||||||
inclusiveLeft: true,
|
|
||||||
inclusiveRight: true,
|
|
||||||
replacedWith: widget,
|
|
||||||
clearOnEnter: true
|
|
||||||
});
|
|
||||||
function clear() {
|
|
||||||
mark.clear();
|
|
||||||
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
|
|
||||||
}
|
|
||||||
widget.addEventListener("click", clear);
|
|
||||||
return {mark: mark, clear: clear};
|
|
||||||
}
|
|
||||||
|
|
||||||
function collapseStretch(size, editors) {
|
|
||||||
var marks = [];
|
|
||||||
function clear() {
|
|
||||||
for (var i = 0; i < marks.length; i++) marks[i].clear();
|
|
||||||
}
|
|
||||||
for (var i = 0; i < editors.length; i++) {
|
|
||||||
var editor = editors[i];
|
|
||||||
var mark = collapseSingle(editor.cm, editor.line, editor.line + size);
|
|
||||||
marks.push(mark);
|
|
||||||
mark.mark.on("clear", clear);
|
|
||||||
}
|
|
||||||
return marks[0].mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
function unclearNearChunks(dv, margin, off, clear) {
|
|
||||||
for (var i = 0; i < dv.chunks.length; i++) {
|
|
||||||
var chunk = dv.chunks[i];
|
|
||||||
for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {
|
|
||||||
var pos = l + off;
|
|
||||||
if (pos >= 0 && pos < clear.length) clear[pos] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function collapseIdenticalStretches(mv, margin) {
|
|
||||||
if (typeof margin != "number") margin = 2;
|
|
||||||
var clear = [], edit = mv.editor(), off = edit.firstLine();
|
|
||||||
for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);
|
|
||||||
if (mv.left) unclearNearChunks(mv.left, margin, off, clear);
|
|
||||||
if (mv.right) unclearNearChunks(mv.right, margin, off, clear);
|
|
||||||
|
|
||||||
for (var i = 0; i < clear.length; i++) {
|
|
||||||
if (clear[i]) {
|
|
||||||
var line = i + off;
|
|
||||||
for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}
|
|
||||||
if (size > margin) {
|
|
||||||
var editors = [{line: line, cm: edit}];
|
|
||||||
if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});
|
|
||||||
if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});
|
|
||||||
var mark = collapseStretch(size, editors);
|
|
||||||
if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// General utilities
|
|
||||||
|
|
||||||
function elt(tag, content, className, style) {
|
|
||||||
var e = document.createElement(tag);
|
|
||||||
if (className) e.className = className;
|
|
||||||
if (style) e.style.cssText = style;
|
|
||||||
if (typeof content == "string") e.appendChild(document.createTextNode(content));
|
|
||||||
else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear(node) {
|
|
||||||
for (var count = node.childNodes.length; count > 0; --count)
|
|
||||||
node.removeChild(node.firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
function attrs(elt) {
|
|
||||||
for (var i = 1; i < arguments.length; i += 2)
|
|
||||||
elt.setAttribute(arguments[i], arguments[i+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyObj(obj, target) {
|
|
||||||
if (!target) target = {};
|
|
||||||
for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveOver(pos, str, copy, other) {
|
|
||||||
var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;
|
|
||||||
for (;;) {
|
|
||||||
var nl = str.indexOf("\n", at);
|
|
||||||
if (nl == -1) break;
|
|
||||||
++out.line;
|
|
||||||
if (other) ++other.line;
|
|
||||||
at = nl + 1;
|
|
||||||
}
|
|
||||||
out.ch = (at ? 0 : out.ch) + (str.length - at);
|
|
||||||
if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
|
|
||||||
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
|
|
||||||
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
|
|
||||||
});
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"), "cjs");
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror, "plain");
|
|
||||||
})(function(CodeMirror, env) {
|
|
||||||
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
|
|
||||||
|
|
||||||
var loading = {};
|
|
||||||
function splitCallback(cont, n) {
|
|
||||||
var countDown = n;
|
|
||||||
return function() { if (--countDown == 0) cont(); };
|
|
||||||
}
|
|
||||||
function ensureDeps(mode, cont) {
|
|
||||||
var deps = CodeMirror.modes[mode].dependencies;
|
|
||||||
if (!deps) return cont();
|
|
||||||
var missing = [];
|
|
||||||
for (var i = 0; i < deps.length; ++i) {
|
|
||||||
if (!CodeMirror.modes.hasOwnProperty(deps[i]))
|
|
||||||
missing.push(deps[i]);
|
|
||||||
}
|
|
||||||
if (!missing.length) return cont();
|
|
||||||
var split = splitCallback(cont, missing.length);
|
|
||||||
for (var i = 0; i < missing.length; ++i)
|
|
||||||
CodeMirror.requireMode(missing[i], split);
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeMirror.requireMode = function(mode, cont) {
|
|
||||||
if (typeof mode != "string") mode = mode.name;
|
|
||||||
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
|
|
||||||
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
|
|
||||||
|
|
||||||
var file = CodeMirror.modeURL.replace(/%N/g, mode);
|
|
||||||
if (env == "plain") {
|
|
||||||
var script = document.createElement("script");
|
|
||||||
script.src = file;
|
|
||||||
var others = document.getElementsByTagName("script")[0];
|
|
||||||
var list = loading[mode] = [cont];
|
|
||||||
CodeMirror.on(script, "load", function() {
|
|
||||||
ensureDeps(mode, function() {
|
|
||||||
for (var i = 0; i < list.length; ++i) list[i]();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
others.parentNode.insertBefore(script, others);
|
|
||||||
} else if (env == "cjs") {
|
|
||||||
require(file);
|
|
||||||
cont();
|
|
||||||
} else if (env == "amd") {
|
|
||||||
requirejs([file], cont);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.autoLoadMode = function(instance, mode) {
|
|
||||||
if (!CodeMirror.modes.hasOwnProperty(mode))
|
|
||||||
CodeMirror.requireMode(mode, function() {
|
|
||||||
instance.setOption("mode", instance.getOption("mode"));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.multiplexingMode = function(outer /*, others */) {
|
|
||||||
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
|
|
||||||
var others = Array.prototype.slice.call(arguments, 1);
|
|
||||||
var n_others = others.length;
|
|
||||||
|
|
||||||
function indexOf(string, pattern, from) {
|
|
||||||
if (typeof pattern == "string") return string.indexOf(pattern, from);
|
|
||||||
var m = pattern.exec(from ? string.slice(from) : string);
|
|
||||||
return m ? m.index + from : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
startState: function() {
|
|
||||||
return {
|
|
||||||
outer: CodeMirror.startState(outer),
|
|
||||||
innerActive: null,
|
|
||||||
inner: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
copyState: function(state) {
|
|
||||||
return {
|
|
||||||
outer: CodeMirror.copyState(outer, state.outer),
|
|
||||||
innerActive: state.innerActive,
|
|
||||||
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
token: function(stream, state) {
|
|
||||||
if (!state.innerActive) {
|
|
||||||
var cutOff = Infinity, oldContent = stream.string;
|
|
||||||
for (var i = 0; i < n_others; ++i) {
|
|
||||||
var other = others[i];
|
|
||||||
var found = indexOf(oldContent, other.open, stream.pos);
|
|
||||||
if (found == stream.pos) {
|
|
||||||
stream.match(other.open);
|
|
||||||
state.innerActive = other;
|
|
||||||
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
|
|
||||||
return other.delimStyle;
|
|
||||||
} else if (found != -1 && found < cutOff) {
|
|
||||||
cutOff = found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
|
|
||||||
var outerToken = outer.token(stream, state.outer);
|
|
||||||
if (cutOff != Infinity) stream.string = oldContent;
|
|
||||||
return outerToken;
|
|
||||||
} else {
|
|
||||||
var curInner = state.innerActive, oldContent = stream.string;
|
|
||||||
if (!curInner.close && stream.sol()) {
|
|
||||||
state.innerActive = state.inner = null;
|
|
||||||
return this.token(stream, state);
|
|
||||||
}
|
|
||||||
var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
|
|
||||||
if (found == stream.pos) {
|
|
||||||
stream.match(curInner.close);
|
|
||||||
state.innerActive = state.inner = null;
|
|
||||||
return curInner.delimStyle;
|
|
||||||
}
|
|
||||||
if (found > -1) stream.string = oldContent.slice(0, found);
|
|
||||||
var innerToken = curInner.mode.token(stream, state.inner);
|
|
||||||
if (found > -1) stream.string = oldContent;
|
|
||||||
|
|
||||||
if (curInner.innerStyle) {
|
|
||||||
if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
|
|
||||||
else innerToken = curInner.innerStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return innerToken;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
indent: function(state, textAfter) {
|
|
||||||
var mode = state.innerActive ? state.innerActive.mode : outer;
|
|
||||||
if (!mode.indent) return CodeMirror.Pass;
|
|
||||||
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
|
|
||||||
},
|
|
||||||
|
|
||||||
blankLine: function(state) {
|
|
||||||
var mode = state.innerActive ? state.innerActive.mode : outer;
|
|
||||||
if (mode.blankLine) {
|
|
||||||
mode.blankLine(state.innerActive ? state.inner : state.outer);
|
|
||||||
}
|
|
||||||
if (!state.innerActive) {
|
|
||||||
for (var i = 0; i < n_others; ++i) {
|
|
||||||
var other = others[i];
|
|
||||||
if (other.open === "\n") {
|
|
||||||
state.innerActive = other;
|
|
||||||
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (state.innerActive.close === "\n") {
|
|
||||||
state.innerActive = state.inner = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
electricChars: outer.electricChars,
|
|
||||||
|
|
||||||
innerMode: function(state) {
|
|
||||||
return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
CodeMirror.defineMode("markdown_with_stex", function(){
|
|
||||||
var inner = CodeMirror.getMode({}, "stex");
|
|
||||||
var outer = CodeMirror.getMode({}, "markdown");
|
|
||||||
|
|
||||||
var innerOptions = {
|
|
||||||
open: '$',
|
|
||||||
close: '$',
|
|
||||||
mode: inner,
|
|
||||||
delimStyle: 'delim',
|
|
||||||
innerStyle: 'inner'
|
|
||||||
};
|
|
||||||
|
|
||||||
return CodeMirror.multiplexingMode(outer, innerOptions);
|
|
||||||
});
|
|
||||||
|
|
||||||
var mode = CodeMirror.getMode({}, "markdown_with_stex");
|
|
||||||
|
|
||||||
function MT(name) {
|
|
||||||
test.mode(
|
|
||||||
name,
|
|
||||||
mode,
|
|
||||||
Array.prototype.slice.call(arguments, 1),
|
|
||||||
'multiplexing');
|
|
||||||
}
|
|
||||||
|
|
||||||
MT(
|
|
||||||
"stexInsideMarkdown",
|
|
||||||
"[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
|
|
||||||
})();
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// 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 and not overridden,
|
|
||||||
// or state.overlay.combineTokens was true, in which case the styles are
|
|
||||||
// combined.
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.overlayMode = function(base, overlay, combine) {
|
|
||||||
return {
|
|
||||||
startState: function() {
|
|
||||||
return {
|
|
||||||
base: CodeMirror.startState(base),
|
|
||||||
overlay: CodeMirror.startState(overlay),
|
|
||||||
basePos: 0, baseCur: null,
|
|
||||||
overlayPos: 0, overlayCur: null,
|
|
||||||
streamSeen: 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 != state.streamSeen ||
|
|
||||||
Math.min(state.basePos, state.overlayPos) < stream.start) {
|
|
||||||
state.streamSeen = stream;
|
|
||||||
state.basePos = state.overlayPos = stream.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// state.overlay.combineTokens always takes precedence over combine,
|
|
||||||
// unless set to null
|
|
||||||
if (state.overlayCur == null) return state.baseCur;
|
|
||||||
else if (state.baseCur != null &&
|
|
||||||
state.overlay.combineTokens ||
|
|
||||||
combine && state.overlay.combineTokens == null)
|
|
||||||
return state.baseCur + " " + state.overlayCur;
|
|
||||||
else return state.overlayCur;
|
|
||||||
},
|
|
||||||
|
|
||||||
indent: base.indent && function(state, textAfter) {
|
|
||||||
return base.indent(state.base, textAfter);
|
|
||||||
},
|
|
||||||
electricChars: base.electricChars,
|
|
||||||
|
|
||||||
innerMode: function(state) { return {state: state.base, mode: base}; },
|
|
||||||
|
|
||||||
blankLine: function(state) {
|
|
||||||
if (base.blankLine) base.blankLine(state.base);
|
|
||||||
if (overlay.blankLine) overlay.blankLine(state.overlay);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.defineSimpleMode = function(name, states) {
|
|
||||||
CodeMirror.defineMode(name, function(config) {
|
|
||||||
return CodeMirror.simpleMode(config, states);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.simpleMode = function(config, states) {
|
|
||||||
ensureState(states, "start");
|
|
||||||
var states_ = {}, meta = states.meta || {}, hasIndentation = false;
|
|
||||||
for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
|
|
||||||
var list = states_[state] = [], orig = states[state];
|
|
||||||
for (var i = 0; i < orig.length; i++) {
|
|
||||||
var data = orig[i];
|
|
||||||
list.push(new Rule(data, states));
|
|
||||||
if (data.indent || data.dedent) hasIndentation = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var mode = {
|
|
||||||
startState: function() {
|
|
||||||
return {state: "start", pending: null,
|
|
||||||
local: null, localState: null,
|
|
||||||
indent: hasIndentation ? [] : null};
|
|
||||||
},
|
|
||||||
copyState: function(state) {
|
|
||||||
var s = {state: state.state, pending: state.pending,
|
|
||||||
local: state.local, localState: null,
|
|
||||||
indent: state.indent && state.indent.slice(0)};
|
|
||||||
if (state.localState)
|
|
||||||
s.localState = CodeMirror.copyState(state.local.mode, state.localState);
|
|
||||||
if (state.stack)
|
|
||||||
s.stack = state.stack.slice(0);
|
|
||||||
for (var pers = state.persistentStates; pers; pers = pers.next)
|
|
||||||
s.persistentStates = {mode: pers.mode,
|
|
||||||
spec: pers.spec,
|
|
||||||
state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
|
|
||||||
next: s.persistentStates};
|
|
||||||
return s;
|
|
||||||
},
|
|
||||||
token: tokenFunction(states_, config),
|
|
||||||
innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
|
|
||||||
indent: indentFunction(states_, meta)
|
|
||||||
};
|
|
||||||
if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
|
|
||||||
mode[prop] = meta[prop];
|
|
||||||
return mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
function ensureState(states, name) {
|
|
||||||
if (!states.hasOwnProperty(name))
|
|
||||||
throw new Error("Undefined state " + name + "in simple mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
function toRegex(val, caret) {
|
|
||||||
if (!val) return /(?:)/;
|
|
||||||
var flags = "";
|
|
||||||
if (val instanceof RegExp) {
|
|
||||||
if (val.ignoreCase) flags = "i";
|
|
||||||
val = val.source;
|
|
||||||
} else {
|
|
||||||
val = String(val);
|
|
||||||
}
|
|
||||||
return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
function asToken(val) {
|
|
||||||
if (!val) return null;
|
|
||||||
if (typeof val == "string") return val.replace(/\./g, " ");
|
|
||||||
var result = [];
|
|
||||||
for (var i = 0; i < val.length; i++)
|
|
||||||
result.push(val[i] && val[i].replace(/\./g, " "));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Rule(data, states) {
|
|
||||||
if (data.next || data.push) ensureState(states, data.next || data.push);
|
|
||||||
this.regex = toRegex(data.regex);
|
|
||||||
this.token = asToken(data.token);
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function tokenFunction(states, config) {
|
|
||||||
return function(stream, state) {
|
|
||||||
if (state.pending) {
|
|
||||||
var pend = state.pending.shift();
|
|
||||||
if (state.pending.length == 0) state.pending = null;
|
|
||||||
stream.pos += pend.text.length;
|
|
||||||
return pend.token;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.local) {
|
|
||||||
if (state.local.end && stream.match(state.local.end)) {
|
|
||||||
var tok = state.local.endToken || null;
|
|
||||||
state.local = state.localState = null;
|
|
||||||
return tok;
|
|
||||||
} else {
|
|
||||||
var tok = state.local.mode.token(stream, state.localState), m;
|
|
||||||
if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
|
|
||||||
stream.pos = stream.start + m.index;
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var curState = states[state.state];
|
|
||||||
for (var i = 0; i < curState.length; i++) {
|
|
||||||
var rule = curState[i];
|
|
||||||
var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
|
|
||||||
if (matches) {
|
|
||||||
if (rule.data.next) {
|
|
||||||
state.state = rule.data.next;
|
|
||||||
} else if (rule.data.push) {
|
|
||||||
(state.stack || (state.stack = [])).push(state.state);
|
|
||||||
state.state = rule.data.push;
|
|
||||||
} else if (rule.data.pop && state.stack && state.stack.length) {
|
|
||||||
state.state = state.stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule.data.mode)
|
|
||||||
enterLocalMode(config, state, rule.data.mode, rule.token);
|
|
||||||
if (rule.data.indent)
|
|
||||||
state.indent.push(stream.indentation() + config.indentUnit);
|
|
||||||
if (rule.data.dedent)
|
|
||||||
state.indent.pop();
|
|
||||||
if (matches.length > 2) {
|
|
||||||
state.pending = [];
|
|
||||||
for (var j = 2; j < matches.length; j++)
|
|
||||||
if (matches[j])
|
|
||||||
state.pending.push({text: matches[j], token: rule.token[j - 1]});
|
|
||||||
stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
|
|
||||||
return rule.token[0];
|
|
||||||
} else if (rule.token && rule.token.join) {
|
|
||||||
return rule.token[0];
|
|
||||||
} else {
|
|
||||||
return rule.token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stream.next();
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function cmp(a, b) {
|
|
||||||
if (a === b) return true;
|
|
||||||
if (!a || typeof a != "object" || !b || typeof b != "object") return false;
|
|
||||||
var props = 0;
|
|
||||||
for (var prop in a) if (a.hasOwnProperty(prop)) {
|
|
||||||
if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
|
|
||||||
props++;
|
|
||||||
}
|
|
||||||
for (var prop in b) if (b.hasOwnProperty(prop)) props--;
|
|
||||||
return props == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function enterLocalMode(config, state, spec, token) {
|
|
||||||
var pers;
|
|
||||||
if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
|
|
||||||
if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
|
|
||||||
var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
|
|
||||||
var lState = pers ? pers.state : CodeMirror.startState(mode);
|
|
||||||
if (spec.persistent && !pers)
|
|
||||||
state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
|
|
||||||
|
|
||||||
state.localState = lState;
|
|
||||||
state.local = {mode: mode,
|
|
||||||
end: spec.end && toRegex(spec.end),
|
|
||||||
endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
|
|
||||||
endToken: token && token.join ? token[token.length - 1] : token};
|
|
||||||
}
|
|
||||||
|
|
||||||
function indexOf(val, arr) {
|
|
||||||
for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function indentFunction(states, meta) {
|
|
||||||
return function(state, textAfter, line) {
|
|
||||||
if (state.local && state.local.mode.indent)
|
|
||||||
return state.local.mode.indent(state.localState, textAfter, line);
|
|
||||||
if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
|
|
||||||
return CodeMirror.Pass;
|
|
||||||
|
|
||||||
var pos = state.indent.length - 1, rules = states[state.state];
|
|
||||||
scan: for (;;) {
|
|
||||||
for (var i = 0; i < rules.length; i++) {
|
|
||||||
var rule = rules[i];
|
|
||||||
if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
|
|
||||||
var m = rule.regex.exec(textAfter);
|
|
||||||
if (m && m[0]) {
|
|
||||||
pos--;
|
|
||||||
if (rule.next || rule.push) rules = states[rule.next || rule.push];
|
|
||||||
textAfter = textAfter.slice(m[0].length);
|
|
||||||
continue scan;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return pos < 0 ? 0 : state.indent[pos];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"), require("./runmode"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror", "./runmode"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/;
|
|
||||||
|
|
||||||
function textContent(node, out) {
|
|
||||||
if (node.nodeType == 3) return out.push(node.nodeValue);
|
|
||||||
for (var ch = node.firstChild; ch; ch = ch.nextSibling) {
|
|
||||||
textContent(ch, out);
|
|
||||||
if (isBlock.test(node.nodeType)) out.push("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeMirror.colorize = function(collection, defaultMode) {
|
|
||||||
if (!collection) collection = document.body.getElementsByTagName("pre");
|
|
||||||
|
|
||||||
for (var i = 0; i < collection.length; ++i) {
|
|
||||||
var node = collection[i];
|
|
||||||
var mode = node.getAttribute("data-lang") || defaultMode;
|
|
||||||
if (!mode) continue;
|
|
||||||
|
|
||||||
var text = [];
|
|
||||||
textContent(node, text);
|
|
||||||
node.innerHTML = "";
|
|
||||||
CodeMirror.runMode(text.join(""), mode, node);
|
|
||||||
|
|
||||||
node.className += " cm-s-default";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
window.CodeMirror = {};
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function splitLines(string){ return string.split(/\r?\n|\r/); };
|
|
||||||
|
|
||||||
function StringStream(string) {
|
|
||||||
this.pos = this.start = 0;
|
|
||||||
this.string = string;
|
|
||||||
this.lineStart = 0;
|
|
||||||
}
|
|
||||||
StringStream.prototype = {
|
|
||||||
eol: function() {return this.pos >= this.string.length;},
|
|
||||||
sol: function() {return this.pos == 0;},
|
|
||||||
peek: function() {return this.string.charAt(this.pos) || null;},
|
|
||||||
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 this.start - this.lineStart;},
|
|
||||||
indentation: function() {return 0;},
|
|
||||||
match: function(pattern, consume, caseInsensitive) {
|
|
||||||
if (typeof pattern == "string") {
|
|
||||||
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
|
||||||
var substr = this.string.substr(this.pos, pattern.length);
|
|
||||||
if (cased(substr) == cased(pattern)) {
|
|
||||||
if (consume !== false) this.pos += pattern.length;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var match = this.string.slice(this.pos).match(pattern);
|
|
||||||
if (match && match.index > 0) return null;
|
|
||||||
if (match && consume !== false) this.pos += match[0].length;
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
current: function(){return this.string.slice(this.start, this.pos);},
|
|
||||||
hideFirstChars: function(n, inner) {
|
|
||||||
this.lineStart += n;
|
|
||||||
try { return inner(); }
|
|
||||||
finally { this.lineStart -= n; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
CodeMirror.StringStream = StringStream;
|
|
||||||
|
|
||||||
CodeMirror.startState = function (mode, a1, a2) {
|
|
||||||
return mode.startState ? mode.startState(a1, a2) : true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
|
|
||||||
CodeMirror.defineMode = function (name, mode) {
|
|
||||||
if (arguments.length > 2)
|
|
||||||
mode.dependencies = Array.prototype.slice.call(arguments, 2);
|
|
||||||
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 (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
|
|
||||||
spec = mimeModes[spec.name];
|
|
||||||
}
|
|
||||||
if (typeof spec == "string") return {name: spec};
|
|
||||||
else return spec || {name: "null"};
|
|
||||||
};
|
|
||||||
CodeMirror.getMode = function (options, spec) {
|
|
||||||
spec = CodeMirror.resolveMode(spec);
|
|
||||||
var mfactory = modes[spec.name];
|
|
||||||
if (!mfactory) throw new Error("Unknown mode: " + spec);
|
|
||||||
return mfactory(options, spec);
|
|
||||||
};
|
|
||||||
CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
|
|
||||||
CodeMirror.defineMode("null", function() {
|
|
||||||
return {token: function(stream) {stream.skipToEnd();}};
|
|
||||||
});
|
|
||||||
CodeMirror.defineMIME("text/plain", "null");
|
|
||||||
|
|
||||||
CodeMirror.runMode = function (string, modespec, callback, options) {
|
|
||||||
var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
|
|
||||||
|
|
||||||
if (callback.nodeType == 1) {
|
|
||||||
var tabSize = (options && options.tabSize) || 4;
|
|
||||||
var node = callback, col = 0;
|
|
||||||
node.innerHTML = "";
|
|
||||||
callback = function (text, style) {
|
|
||||||
if (text == "\n") {
|
|
||||||
node.appendChild(document.createElement("br"));
|
|
||||||
col = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var content = "";
|
|
||||||
// replace tabs
|
|
||||||
for (var pos = 0; ;) {
|
|
||||||
var idx = text.indexOf("\t", pos);
|
|
||||||
if (idx == -1) {
|
|
||||||
content += text.slice(pos);
|
|
||||||
col += text.length - pos;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
col += idx - pos;
|
|
||||||
content += text.slice(pos, idx);
|
|
||||||
var size = tabSize - col % tabSize;
|
|
||||||
col += size;
|
|
||||||
for (var i = 0; i < size; ++i) content += " ";
|
|
||||||
pos = idx + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style) {
|
|
||||||
var sp = node.appendChild(document.createElement("span"));
|
|
||||||
sp.className = "cm-" + style.replace(/ +/g, " cm-");
|
|
||||||
sp.appendChild(document.createTextNode(content));
|
|
||||||
} else {
|
|
||||||
node.appendChild(document.createTextNode(content));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var lines = splitLines(string), state = (options && options.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]);
|
|
||||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
|
||||||
while (!stream.eol()) {
|
|
||||||
var style = mode.token(stream, state);
|
|
||||||
callback(stream.current(), style, i, stream.start, state);
|
|
||||||
stream.start = stream.pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.runMode = function(string, modespec, callback, options) {
|
|
||||||
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
|
|
||||||
var ie = /MSIE \d/.test(navigator.userAgent);
|
|
||||||
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
|
|
||||||
|
|
||||||
if (callback.nodeType == 1) {
|
|
||||||
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
|
|
||||||
var node = callback, col = 0;
|
|
||||||
node.innerHTML = "";
|
|
||||||
callback = function(text, style) {
|
|
||||||
if (text == "\n") {
|
|
||||||
// Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
|
|
||||||
// Emitting a carriage return makes everything ok.
|
|
||||||
node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
|
|
||||||
col = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var content = "";
|
|
||||||
// replace tabs
|
|
||||||
for (var pos = 0;;) {
|
|
||||||
var idx = text.indexOf("\t", pos);
|
|
||||||
if (idx == -1) {
|
|
||||||
content += text.slice(pos);
|
|
||||||
col += text.length - pos;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
col += idx - pos;
|
|
||||||
content += text.slice(pos, idx);
|
|
||||||
var size = tabSize - col % tabSize;
|
|
||||||
col += size;
|
|
||||||
for (var i = 0; i < size; ++i) content += " ";
|
|
||||||
pos = idx + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style) {
|
|
||||||
var sp = node.appendChild(document.createElement("span"));
|
|
||||||
sp.className = "cm-" + style.replace(/ +/g, " cm-");
|
|
||||||
sp.appendChild(document.createTextNode(content));
|
|
||||||
} else {
|
|
||||||
node.appendChild(document.createTextNode(content));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var lines = CodeMirror.splitLines(string), state = (options && options.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]);
|
|
||||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
|
||||||
while (!stream.eol()) {
|
|
||||||
var style = mode.token(stream, state);
|
|
||||||
callback(stream.current(), style, i, stream.start, state);
|
|
||||||
stream.start = stream.pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
/* Just enough of CodeMirror to run runMode under node.js */
|
|
||||||
|
|
||||||
// declare global: StringStream
|
|
||||||
|
|
||||||
function splitLines(string){ return string.split(/\r?\n|\r/); };
|
|
||||||
|
|
||||||
function StringStream(string) {
|
|
||||||
this.pos = this.start = 0;
|
|
||||||
this.string = string;
|
|
||||||
this.lineStart = 0;
|
|
||||||
}
|
|
||||||
StringStream.prototype = {
|
|
||||||
eol: function() {return this.pos >= this.string.length;},
|
|
||||||
sol: function() {return this.pos == 0;},
|
|
||||||
peek: function() {return this.string.charAt(this.pos) || null;},
|
|
||||||
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 this.start - this.lineStart;},
|
|
||||||
indentation: function() {return 0;},
|
|
||||||
match: function(pattern, consume, caseInsensitive) {
|
|
||||||
if (typeof pattern == "string") {
|
|
||||||
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
|
||||||
var substr = this.string.substr(this.pos, pattern.length);
|
|
||||||
if (cased(substr) == cased(pattern)) {
|
|
||||||
if (consume !== false) this.pos += pattern.length;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var match = this.string.slice(this.pos).match(pattern);
|
|
||||||
if (match && match.index > 0) return null;
|
|
||||||
if (match && consume !== false) this.pos += match[0].length;
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
current: function(){return this.string.slice(this.start, this.pos);},
|
|
||||||
hideFirstChars: function(n, inner) {
|
|
||||||
this.lineStart += n;
|
|
||||||
try { return inner(); }
|
|
||||||
finally { this.lineStart -= n; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.StringStream = StringStream;
|
|
||||||
|
|
||||||
exports.startState = function(mode, a1, a2) {
|
|
||||||
return mode.startState ? mode.startState(a1, a2) : true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
|
|
||||||
exports.defineMode = function(name, mode) {
|
|
||||||
if (arguments.length > 2)
|
|
||||||
mode.dependencies = Array.prototype.slice.call(arguments, 2);
|
|
||||||
modes[name] = mode;
|
|
||||||
};
|
|
||||||
exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
|
|
||||||
|
|
||||||
exports.defineMode("null", function() {
|
|
||||||
return {token: function(stream) {stream.skipToEnd();}};
|
|
||||||
});
|
|
||||||
exports.defineMIME("text/plain", "null");
|
|
||||||
|
|
||||||
exports.resolveMode = function(spec) {
|
|
||||||
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
|
|
||||||
spec = mimeModes[spec];
|
|
||||||
} else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
|
|
||||||
spec = mimeModes[spec.name];
|
|
||||||
}
|
|
||||||
if (typeof spec == "string") return {name: spec};
|
|
||||||
else return spec || {name: "null"};
|
|
||||||
};
|
|
||||||
exports.getMode = function(options, spec) {
|
|
||||||
spec = exports.resolveMode(spec);
|
|
||||||
var mfactory = modes[spec.name];
|
|
||||||
if (!mfactory) throw new Error("Unknown mode: " + spec);
|
|
||||||
return mfactory(options, spec);
|
|
||||||
};
|
|
||||||
exports.registerHelper = exports.registerGlobalHelper = Math.min;
|
|
||||||
|
|
||||||
exports.runMode = function(string, modespec, callback, options) {
|
|
||||||
var mode = exports.getMode({indentUnit: 2}, modespec);
|
|
||||||
var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
|
|
||||||
for (var i = 0, e = lines.length; i < e; ++i) {
|
|
||||||
if (i) callback("\n");
|
|
||||||
var stream = new exports.StringStream(lines[i]);
|
|
||||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
|
||||||
while (!stream.eol()) {
|
|
||||||
var style = mode.token(stream, state);
|
|
||||||
callback(stream.current(), style, i, stream.start, state);
|
|
||||||
stream.start = stream.pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.defineExtension("annotateScrollbar", function(options) {
|
|
||||||
if (typeof options == "string") options = {className: options};
|
|
||||||
return new Annotation(this, options);
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.defineOption("scrollButtonHeight", 0);
|
|
||||||
|
|
||||||
function Annotation(cm, options) {
|
|
||||||
this.cm = cm;
|
|
||||||
this.options = options;
|
|
||||||
this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
|
|
||||||
this.annotations = [];
|
|
||||||
this.doRedraw = this.doUpdate = null;
|
|
||||||
this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
|
|
||||||
this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
|
|
||||||
this.computeScale();
|
|
||||||
|
|
||||||
function scheduleRedraw(delay) {
|
|
||||||
clearTimeout(self.doRedraw);
|
|
||||||
self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
cm.on("refresh", this.resizeHandler = function() {
|
|
||||||
clearTimeout(self.doUpdate);
|
|
||||||
self.doUpdate = setTimeout(function() {
|
|
||||||
if (self.computeScale()) scheduleRedraw(20);
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
cm.on("markerAdded", this.resizeHandler);
|
|
||||||
cm.on("markerCleared", this.resizeHandler);
|
|
||||||
if (options.listenForChanges !== false)
|
|
||||||
cm.on("change", this.changeHandler = function() {
|
|
||||||
scheduleRedraw(250);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Annotation.prototype.computeScale = function() {
|
|
||||||
var cm = this.cm;
|
|
||||||
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
|
|
||||||
cm.heightAtLine(cm.lastLine() + 1, "local");
|
|
||||||
if (hScale != this.hScale) {
|
|
||||||
this.hScale = hScale;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Annotation.prototype.update = function(annotations) {
|
|
||||||
this.annotations = annotations;
|
|
||||||
this.redraw();
|
|
||||||
};
|
|
||||||
|
|
||||||
Annotation.prototype.redraw = function(compute) {
|
|
||||||
if (compute !== false) this.computeScale();
|
|
||||||
var cm = this.cm, hScale = this.hScale;
|
|
||||||
|
|
||||||
var frag = document.createDocumentFragment(), anns = this.annotations;
|
|
||||||
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
|
|
||||||
var ann = anns[i];
|
|
||||||
var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
|
|
||||||
var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
|
|
||||||
while (i < anns.length - 1) {
|
|
||||||
nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
|
|
||||||
if (nextTop > bottom + .9) break;
|
|
||||||
ann = anns[++i];
|
|
||||||
bottom = cm.charCoords(ann.to, "local").bottom * hScale;
|
|
||||||
}
|
|
||||||
if (bottom == top) continue;
|
|
||||||
var height = Math.max(bottom - top, 3);
|
|
||||||
|
|
||||||
var elt = frag.appendChild(document.createElement("div"));
|
|
||||||
elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
|
|
||||||
+ (top + this.buttonHeight) + "px; height: " + height + "px";
|
|
||||||
elt.className = this.options.className;
|
|
||||||
}
|
|
||||||
this.div.textContent = "";
|
|
||||||
this.div.appendChild(frag);
|
|
||||||
};
|
|
||||||
|
|
||||||
Annotation.prototype.clear = function() {
|
|
||||||
this.cm.off("refresh", this.resizeHandler);
|
|
||||||
this.cm.off("markerAdded", this.resizeHandler);
|
|
||||||
this.cm.off("markerCleared", this.resizeHandler);
|
|
||||||
if (this.changeHandler) this.cm.off("change", this.changeHandler);
|
|
||||||
this.div.parentNode.removeChild(this.div);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {
|
|
||||||
if (old && old != CodeMirror.Init) {
|
|
||||||
cm.off("change", onChange);
|
|
||||||
cm.off("refresh", updateBottomMargin);
|
|
||||||
cm.display.lineSpace.parentNode.style.paddingBottom = "";
|
|
||||||
cm.state.scrollPastEndPadding = null;
|
|
||||||
}
|
|
||||||
if (val) {
|
|
||||||
cm.on("change", onChange);
|
|
||||||
cm.on("refresh", updateBottomMargin);
|
|
||||||
updateBottomMargin(cm);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function onChange(cm, change) {
|
|
||||||
if (CodeMirror.changeEnd(change).line == cm.lastLine())
|
|
||||||
updateBottomMargin(cm);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateBottomMargin(cm) {
|
|
||||||
var padding = "";
|
|
||||||
if (cm.lineCount() > 1) {
|
|
||||||
var totalH = cm.display.scroller.clientHeight - 30,
|
|
||||||
lastLineH = cm.getLineHandle(cm.lastLine()).height;
|
|
||||||
padding = (totalH - lastLineH) + "px";
|
|
||||||
}
|
|
||||||
if (cm.state.scrollPastEndPadding != padding) {
|
|
||||||
cm.state.scrollPastEndPadding = padding;
|
|
||||||
cm.display.lineSpace.parentNode.style.paddingBottom = padding;
|
|
||||||
cm.setSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
.CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div {
|
|
||||||
position: absolute;
|
|
||||||
background: #ccc;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border: 1px solid #bbb;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 6;
|
|
||||||
background: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-simplescroll-horizontal {
|
|
||||||
bottom: 0; left: 0;
|
|
||||||
height: 8px;
|
|
||||||
}
|
|
||||||
.CodeMirror-simplescroll-horizontal div {
|
|
||||||
bottom: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-simplescroll-vertical {
|
|
||||||
right: 0; top: 0;
|
|
||||||
width: 8px;
|
|
||||||
}
|
|
||||||
.CodeMirror-simplescroll-vertical div {
|
|
||||||
right: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
|
|
||||||
position: absolute;
|
|
||||||
background: #bcd;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-overlayscroll-horizontal {
|
|
||||||
bottom: 0; left: 0;
|
|
||||||
height: 6px;
|
|
||||||
}
|
|
||||||
.CodeMirror-overlayscroll-horizontal div {
|
|
||||||
bottom: 0;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-overlayscroll-vertical {
|
|
||||||
right: 0; top: 0;
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
.CodeMirror-overlayscroll-vertical div {
|
|
||||||
right: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function Bar(cls, orientation, scroll) {
|
|
||||||
this.orientation = orientation;
|
|
||||||
this.scroll = scroll;
|
|
||||||
this.screen = this.total = this.size = 1;
|
|
||||||
this.pos = 0;
|
|
||||||
|
|
||||||
this.node = document.createElement("div");
|
|
||||||
this.node.className = cls + "-" + orientation;
|
|
||||||
this.inner = this.node.appendChild(document.createElement("div"));
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
CodeMirror.on(this.inner, "mousedown", function(e) {
|
|
||||||
if (e.which != 1) return;
|
|
||||||
CodeMirror.e_preventDefault(e);
|
|
||||||
var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
|
|
||||||
var start = e[axis], startpos = self.pos;
|
|
||||||
function done() {
|
|
||||||
CodeMirror.off(document, "mousemove", move);
|
|
||||||
CodeMirror.off(document, "mouseup", done);
|
|
||||||
}
|
|
||||||
function move(e) {
|
|
||||||
if (e.which != 1) return done();
|
|
||||||
self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
|
|
||||||
}
|
|
||||||
CodeMirror.on(document, "mousemove", move);
|
|
||||||
CodeMirror.on(document, "mouseup", done);
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.on(this.node, "click", function(e) {
|
|
||||||
CodeMirror.e_preventDefault(e);
|
|
||||||
var innerBox = self.inner.getBoundingClientRect(), where;
|
|
||||||
if (self.orientation == "horizontal")
|
|
||||||
where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
|
|
||||||
else
|
|
||||||
where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
|
|
||||||
self.moveTo(self.pos + where * self.screen);
|
|
||||||
});
|
|
||||||
|
|
||||||
function onWheel(e) {
|
|
||||||
var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
|
|
||||||
var oldPos = self.pos;
|
|
||||||
self.moveTo(self.pos + moved);
|
|
||||||
if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
|
|
||||||
}
|
|
||||||
CodeMirror.on(this.node, "mousewheel", onWheel);
|
|
||||||
CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bar.prototype.moveTo = function(pos, update) {
|
|
||||||
if (pos < 0) pos = 0;
|
|
||||||
if (pos > this.total - this.screen) pos = this.total - this.screen;
|
|
||||||
if (pos == this.pos) return;
|
|
||||||
this.pos = pos;
|
|
||||||
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
|
||||||
(pos * (this.size / this.total)) + "px";
|
|
||||||
if (update !== false) this.scroll(pos, this.orientation);
|
|
||||||
};
|
|
||||||
|
|
||||||
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
|
|
||||||
this.screen = clientSize;
|
|
||||||
this.total = scrollSize;
|
|
||||||
this.size = barSize;
|
|
||||||
|
|
||||||
// FIXME clip to min size?
|
|
||||||
this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
|
|
||||||
this.screen * (this.size / this.total) + "px";
|
|
||||||
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
|
||||||
this.pos * (this.size / this.total) + "px";
|
|
||||||
};
|
|
||||||
|
|
||||||
function SimpleScrollbars(cls, place, scroll) {
|
|
||||||
this.addClass = cls;
|
|
||||||
this.horiz = new Bar(cls, "horizontal", scroll);
|
|
||||||
place(this.horiz.node);
|
|
||||||
this.vert = new Bar(cls, "vertical", scroll);
|
|
||||||
place(this.vert.node);
|
|
||||||
this.width = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleScrollbars.prototype.update = function(measure) {
|
|
||||||
if (this.width == null) {
|
|
||||||
var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
|
|
||||||
if (style) this.width = parseInt(style.height);
|
|
||||||
}
|
|
||||||
var width = this.width || 0;
|
|
||||||
|
|
||||||
var needsH = measure.scrollWidth > measure.clientWidth + 1;
|
|
||||||
var needsV = measure.scrollHeight > measure.clientHeight + 1;
|
|
||||||
this.vert.node.style.display = needsV ? "block" : "none";
|
|
||||||
this.horiz.node.style.display = needsH ? "block" : "none";
|
|
||||||
|
|
||||||
if (needsV) {
|
|
||||||
this.vert.update(measure.scrollHeight, measure.clientHeight,
|
|
||||||
measure.viewHeight - (needsH ? width : 0));
|
|
||||||
this.vert.node.style.display = "block";
|
|
||||||
this.vert.node.style.bottom = needsH ? width + "px" : "0";
|
|
||||||
}
|
|
||||||
if (needsH) {
|
|
||||||
this.horiz.update(measure.scrollWidth, measure.clientWidth,
|
|
||||||
measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
|
|
||||||
this.horiz.node.style.right = needsV ? width + "px" : "0";
|
|
||||||
this.horiz.node.style.left = measure.barLeft + "px";
|
|
||||||
}
|
|
||||||
|
|
||||||
return {right: needsV ? width : 0, bottom: needsH ? width : 0};
|
|
||||||
};
|
|
||||||
|
|
||||||
SimpleScrollbars.prototype.setScrollTop = function(pos) {
|
|
||||||
this.vert.moveTo(pos, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
SimpleScrollbars.prototype.setScrollLeft = function(pos) {
|
|
||||||
this.horiz.moveTo(pos, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
SimpleScrollbars.prototype.clear = function() {
|
|
||||||
var parent = this.horiz.node.parentNode;
|
|
||||||
parent.removeChild(this.horiz.node);
|
|
||||||
parent.removeChild(this.vert.node);
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.scrollbarModel.simple = function(place, scroll) {
|
|
||||||
return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
|
|
||||||
};
|
|
||||||
CodeMirror.scrollbarModel.overlay = function(place, scroll) {
|
|
||||||
return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// Because sometimes you need to style the cursor's line.
|
|
||||||
//
|
|
||||||
// Adds an option 'styleActiveLine' which, when enabled, gives the
|
|
||||||
// active line's wrapping <div> the CSS class "CodeMirror-activeline",
|
|
||||||
// and gives its background <div> the class "CodeMirror-activeline-background".
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
var WRAP_CLASS = "CodeMirror-activeline";
|
|
||||||
var BACK_CLASS = "CodeMirror-activeline-background";
|
|
||||||
|
|
||||||
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
|
|
||||||
var prev = old && old != CodeMirror.Init;
|
|
||||||
if (val && !prev) {
|
|
||||||
cm.state.activeLines = [];
|
|
||||||
updateActiveLines(cm, cm.listSelections());
|
|
||||||
cm.on("beforeSelectionChange", selectionChange);
|
|
||||||
} else if (!val && prev) {
|
|
||||||
cm.off("beforeSelectionChange", selectionChange);
|
|
||||||
clearActiveLines(cm);
|
|
||||||
delete cm.state.activeLines;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function clearActiveLines(cm) {
|
|
||||||
for (var i = 0; i < cm.state.activeLines.length; i++) {
|
|
||||||
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
|
|
||||||
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sameArray(a, b) {
|
|
||||||
if (a.length != b.length) return false;
|
|
||||||
for (var i = 0; i < a.length; i++)
|
|
||||||
if (a[i] != b[i]) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateActiveLines(cm, ranges) {
|
|
||||||
var active = [];
|
|
||||||
for (var i = 0; i < ranges.length; i++) {
|
|
||||||
var range = ranges[i];
|
|
||||||
if (!range.empty()) continue;
|
|
||||||
var line = cm.getLineHandleVisualStart(range.head.line);
|
|
||||||
if (active[active.length - 1] != line) active.push(line);
|
|
||||||
}
|
|
||||||
if (sameArray(cm.state.activeLines, active)) return;
|
|
||||||
cm.operation(function() {
|
|
||||||
clearActiveLines(cm);
|
|
||||||
for (var i = 0; i < active.length; i++) {
|
|
||||||
cm.addLineClass(active[i], "wrap", WRAP_CLASS);
|
|
||||||
cm.addLineClass(active[i], "background", BACK_CLASS);
|
|
||||||
}
|
|
||||||
cm.state.activeLines = active;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectionChange(cm, sel) {
|
|
||||||
updateActiveLines(cm, sel.ranges);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// Because sometimes you need to mark the selected *text*.
|
|
||||||
//
|
|
||||||
// Adds an option 'styleSelectedText' which, when enabled, gives
|
|
||||||
// selected text the CSS class given as option value, or
|
|
||||||
// "CodeMirror-selectedtext" when the value is not a string.
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
|
|
||||||
var prev = old && old != CodeMirror.Init;
|
|
||||||
if (val && !prev) {
|
|
||||||
cm.state.markedSelection = [];
|
|
||||||
cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
|
|
||||||
reset(cm);
|
|
||||||
cm.on("cursorActivity", onCursorActivity);
|
|
||||||
cm.on("change", onChange);
|
|
||||||
} else if (!val && prev) {
|
|
||||||
cm.off("cursorActivity", onCursorActivity);
|
|
||||||
cm.off("change", onChange);
|
|
||||||
clear(cm);
|
|
||||||
cm.state.markedSelection = cm.state.markedSelectionStyle = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function onCursorActivity(cm) {
|
|
||||||
cm.operation(function() { update(cm); });
|
|
||||||
}
|
|
||||||
|
|
||||||
function onChange(cm) {
|
|
||||||
if (cm.state.markedSelection.length)
|
|
||||||
cm.operation(function() { clear(cm); });
|
|
||||||
}
|
|
||||||
|
|
||||||
var CHUNK_SIZE = 8;
|
|
||||||
var Pos = CodeMirror.Pos;
|
|
||||||
var cmp = CodeMirror.cmpPos;
|
|
||||||
|
|
||||||
function coverRange(cm, from, to, addAt) {
|
|
||||||
if (cmp(from, to) == 0) return;
|
|
||||||
var array = cm.state.markedSelection;
|
|
||||||
var cls = cm.state.markedSelectionStyle;
|
|
||||||
for (var line = from.line;;) {
|
|
||||||
var start = line == from.line ? from : Pos(line, 0);
|
|
||||||
var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
|
|
||||||
var end = atEnd ? to : Pos(endLine, 0);
|
|
||||||
var mark = cm.markText(start, end, {className: cls});
|
|
||||||
if (addAt == null) array.push(mark);
|
|
||||||
else array.splice(addAt++, 0, mark);
|
|
||||||
if (atEnd) break;
|
|
||||||
line = endLine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear(cm) {
|
|
||||||
var array = cm.state.markedSelection;
|
|
||||||
for (var i = 0; i < array.length; ++i) array[i].clear();
|
|
||||||
array.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset(cm) {
|
|
||||||
clear(cm);
|
|
||||||
var ranges = cm.listSelections();
|
|
||||||
for (var i = 0; i < ranges.length; i++)
|
|
||||||
coverRange(cm, ranges[i].from(), ranges[i].to());
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(cm) {
|
|
||||||
if (!cm.somethingSelected()) return clear(cm);
|
|
||||||
if (cm.listSelections().length > 1) return reset(cm);
|
|
||||||
|
|
||||||
var from = cm.getCursor("start"), to = cm.getCursor("end");
|
|
||||||
|
|
||||||
var array = cm.state.markedSelection;
|
|
||||||
if (!array.length) return coverRange(cm, from, to);
|
|
||||||
|
|
||||||
var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
|
|
||||||
if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
|
|
||||||
cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
|
|
||||||
return reset(cm);
|
|
||||||
|
|
||||||
while (cmp(from, coverStart.from) > 0) {
|
|
||||||
array.shift().clear();
|
|
||||||
coverStart = array[0].find();
|
|
||||||
}
|
|
||||||
if (cmp(from, coverStart.from) < 0) {
|
|
||||||
if (coverStart.to.line - from.line < CHUNK_SIZE) {
|
|
||||||
array.shift().clear();
|
|
||||||
coverRange(cm, from, coverStart.to, 0);
|
|
||||||
} else {
|
|
||||||
coverRange(cm, from, coverStart.from, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (cmp(to, coverEnd.to) < 0) {
|
|
||||||
array.pop().clear();
|
|
||||||
coverEnd = array[array.length - 1].find();
|
|
||||||
}
|
|
||||||
if (cmp(to, coverEnd.to) > 0) {
|
|
||||||
if (to.line - coverEnd.from.line < CHUNK_SIZE) {
|
|
||||||
array.pop().clear();
|
|
||||||
coverRange(cm, coverEnd.from, to);
|
|
||||||
} else {
|
|
||||||
coverRange(cm, coverEnd.to, to);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
|
|
||||||
var data = cm.state.selectionPointer;
|
|
||||||
if (data) {
|
|
||||||
CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
|
|
||||||
CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
|
|
||||||
CodeMirror.off(window, "scroll", data.windowScroll);
|
|
||||||
cm.off("cursorActivity", reset);
|
|
||||||
cm.off("scroll", reset);
|
|
||||||
cm.state.selectionPointer = null;
|
|
||||||
cm.display.lineDiv.style.cursor = "";
|
|
||||||
}
|
|
||||||
if (val) {
|
|
||||||
data = cm.state.selectionPointer = {
|
|
||||||
value: typeof val == "string" ? val : "default",
|
|
||||||
mousemove: function(event) { mousemove(cm, event); },
|
|
||||||
mouseout: function(event) { mouseout(cm, event); },
|
|
||||||
windowScroll: function() { reset(cm); },
|
|
||||||
rects: null,
|
|
||||||
mouseX: null, mouseY: null,
|
|
||||||
willUpdate: false
|
|
||||||
};
|
|
||||||
CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
|
|
||||||
CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
|
|
||||||
CodeMirror.on(window, "scroll", data.windowScroll);
|
|
||||||
cm.on("cursorActivity", reset);
|
|
||||||
cm.on("scroll", reset);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function mousemove(cm, event) {
|
|
||||||
var data = cm.state.selectionPointer;
|
|
||||||
if (event.buttons == null ? event.which : event.buttons) {
|
|
||||||
data.mouseX = data.mouseY = null;
|
|
||||||
} else {
|
|
||||||
data.mouseX = event.clientX;
|
|
||||||
data.mouseY = event.clientY;
|
|
||||||
}
|
|
||||||
scheduleUpdate(cm);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mouseout(cm, event) {
|
|
||||||
if (!cm.getWrapperElement().contains(event.relatedTarget)) {
|
|
||||||
var data = cm.state.selectionPointer;
|
|
||||||
data.mouseX = data.mouseY = null;
|
|
||||||
scheduleUpdate(cm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset(cm) {
|
|
||||||
cm.state.selectionPointer.rects = null;
|
|
||||||
scheduleUpdate(cm);
|
|
||||||
}
|
|
||||||
|
|
||||||
function scheduleUpdate(cm) {
|
|
||||||
if (!cm.state.selectionPointer.willUpdate) {
|
|
||||||
cm.state.selectionPointer.willUpdate = true;
|
|
||||||
setTimeout(function() {
|
|
||||||
update(cm);
|
|
||||||
cm.state.selectionPointer.willUpdate = false;
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(cm) {
|
|
||||||
var data = cm.state.selectionPointer;
|
|
||||||
if (!data) return;
|
|
||||||
if (data.rects == null && data.mouseX != null) {
|
|
||||||
data.rects = [];
|
|
||||||
if (cm.somethingSelected()) {
|
|
||||||
for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
|
|
||||||
data.rects.push(sel.getBoundingClientRect());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var inside = false;
|
|
||||||
if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
|
|
||||||
var rect = data.rects[i];
|
|
||||||
if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
|
|
||||||
rect.top <= data.mouseY && rect.bottom >= data.mouseY)
|
|
||||||
inside = true;
|
|
||||||
}
|
|
||||||
var cursor = inside ? data.value : "";
|
|
||||||
if (cm.display.lineDiv.style.cursor != cursor)
|
|
||||||
cm.display.lineDiv.style.cursor = cursor;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
.CodeMirror-Tern-completion {
|
|
||||||
padding-left: 22px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion:before {
|
|
||||||
position: absolute;
|
|
||||||
left: 2px;
|
|
||||||
bottom: 2px;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
height: 15px;
|
|
||||||
width: 15px;
|
|
||||||
line-height: 16px;
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-unknown:before {
|
|
||||||
content: "?";
|
|
||||||
background: #4bb;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-object:before {
|
|
||||||
content: "O";
|
|
||||||
background: #77c;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-fn:before {
|
|
||||||
content: "F";
|
|
||||||
background: #7c7;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-array:before {
|
|
||||||
content: "A";
|
|
||||||
background: #c66;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-number:before {
|
|
||||||
content: "1";
|
|
||||||
background: #999;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-string:before {
|
|
||||||
content: "S";
|
|
||||||
background: #999;
|
|
||||||
}
|
|
||||||
.CodeMirror-Tern-completion-bool:before {
|
|
||||||
content: "B";
|
|
||||||
background: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-Tern-completion-guess {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-Tern-tooltip {
|
|
||||||
border: 1px solid silver;
|
|
||||||
border-radius: 3px;
|
|
||||||
color: #444;
|
|
||||||
padding: 2px 5px;
|
|
||||||
font-size: 90%;
|
|
||||||
font-family: monospace;
|
|
||||||
background-color: white;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
|
|
||||||
max-width: 40em;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 10;
|
|
||||||
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
|
||||||
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
|
||||||
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
|
||||||
|
|
||||||
transition: opacity 1s;
|
|
||||||
-moz-transition: opacity 1s;
|
|
||||||
-webkit-transition: opacity 1s;
|
|
||||||
-o-transition: opacity 1s;
|
|
||||||
-ms-transition: opacity 1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-Tern-hint-doc {
|
|
||||||
max-width: 25em;
|
|
||||||
margin-top: -3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.CodeMirror-Tern-fname { color: black; }
|
|
||||||
.CodeMirror-Tern-farg { color: #70a; }
|
|
||||||
.CodeMirror-Tern-farg-current { text-decoration: underline; }
|
|
||||||
.CodeMirror-Tern-type { color: #07c; }
|
|
||||||
.CodeMirror-Tern-fhint-guess { opacity: .7; }
|
|
||||||
@@ -1,697 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// Glue code between CodeMirror and Tern.
|
|
||||||
//
|
|
||||||
// Create a CodeMirror.TernServer to wrap an actual Tern server,
|
|
||||||
// register open documents (CodeMirror.Doc instances) with it, and
|
|
||||||
// call its methods to activate the assisting functions that Tern
|
|
||||||
// provides.
|
|
||||||
//
|
|
||||||
// Options supported (all optional):
|
|
||||||
// * defs: An array of JSON definition data structures.
|
|
||||||
// * plugins: An object mapping plugin names to configuration
|
|
||||||
// options.
|
|
||||||
// * getFile: A function(name, c) that can be used to access files in
|
|
||||||
// the project that haven't been loaded yet. Simply do c(null) to
|
|
||||||
// indicate that a file is not available.
|
|
||||||
// * fileFilter: A function(value, docName, doc) that will be applied
|
|
||||||
// to documents before passing them on to Tern.
|
|
||||||
// * switchToDoc: A function(name, doc) that should, when providing a
|
|
||||||
// multi-file view, switch the view or focus to the named file.
|
|
||||||
// * showError: A function(editor, message) that can be used to
|
|
||||||
// override the way errors are displayed.
|
|
||||||
// * completionTip: Customize the content in tooltips for completions.
|
|
||||||
// Is passed a single argument—the completion's data as returned by
|
|
||||||
// Tern—and may return a string, DOM node, or null to indicate that
|
|
||||||
// no tip should be shown. By default the docstring is shown.
|
|
||||||
// * typeTip: Like completionTip, but for the tooltips shown for type
|
|
||||||
// queries.
|
|
||||||
// * responseFilter: A function(doc, query, request, error, data) that
|
|
||||||
// will be applied to the Tern responses before treating them
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// It is possible to run the Tern server in a web worker by specifying
|
|
||||||
// these additional options:
|
|
||||||
// * useWorker: Set to true to enable web worker mode. You'll probably
|
|
||||||
// want to feature detect the actual value you use here, for example
|
|
||||||
// !!window.Worker.
|
|
||||||
// * workerScript: The main script of the worker. Point this to
|
|
||||||
// wherever you are hosting worker.js from this directory.
|
|
||||||
// * workerDeps: An array of paths pointing (relative to workerScript)
|
|
||||||
// to the Acorn and Tern libraries and any Tern plugins you want to
|
|
||||||
// load. Or, if you minified those into a single script and included
|
|
||||||
// them in the workerScript, simply leave this undefined.
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
// declare global: tern
|
|
||||||
|
|
||||||
CodeMirror.TernServer = function(options) {
|
|
||||||
var self = this;
|
|
||||||
this.options = options || {};
|
|
||||||
var plugins = this.options.plugins || (this.options.plugins = {});
|
|
||||||
if (!plugins.doc_comment) plugins.doc_comment = true;
|
|
||||||
if (this.options.useWorker) {
|
|
||||||
this.server = new WorkerServer(this);
|
|
||||||
} else {
|
|
||||||
this.server = new tern.Server({
|
|
||||||
getFile: function(name, c) { return getFile(self, name, c); },
|
|
||||||
async: true,
|
|
||||||
defs: this.options.defs || [],
|
|
||||||
plugins: plugins
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.docs = Object.create(null);
|
|
||||||
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
|
|
||||||
|
|
||||||
this.cachedArgHints = null;
|
|
||||||
this.activeArgHints = null;
|
|
||||||
this.jumpStack = [];
|
|
||||||
|
|
||||||
this.getHint = function(cm, c) { return hint(self, cm, c); };
|
|
||||||
this.getHint.async = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.TernServer.prototype = {
|
|
||||||
addDoc: function(name, doc) {
|
|
||||||
var data = {doc: doc, name: name, changed: null};
|
|
||||||
this.server.addFile(name, docValue(this, data));
|
|
||||||
CodeMirror.on(doc, "change", this.trackChange);
|
|
||||||
return this.docs[name] = data;
|
|
||||||
},
|
|
||||||
|
|
||||||
delDoc: function(id) {
|
|
||||||
var found = resolveDoc(this, id);
|
|
||||||
if (!found) return;
|
|
||||||
CodeMirror.off(found.doc, "change", this.trackChange);
|
|
||||||
delete this.docs[found.name];
|
|
||||||
this.server.delFile(found.name);
|
|
||||||
},
|
|
||||||
|
|
||||||
hideDoc: function(id) {
|
|
||||||
closeArgHints(this);
|
|
||||||
var found = resolveDoc(this, id);
|
|
||||||
if (found && found.changed) sendDoc(this, found);
|
|
||||||
},
|
|
||||||
|
|
||||||
complete: function(cm) {
|
|
||||||
cm.showHint({hint: this.getHint});
|
|
||||||
},
|
|
||||||
|
|
||||||
showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
|
|
||||||
|
|
||||||
showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
|
|
||||||
|
|
||||||
updateArgHints: function(cm) { updateArgHints(this, cm); },
|
|
||||||
|
|
||||||
jumpToDef: function(cm) { jumpToDef(this, cm); },
|
|
||||||
|
|
||||||
jumpBack: function(cm) { jumpBack(this, cm); },
|
|
||||||
|
|
||||||
rename: function(cm) { rename(this, cm); },
|
|
||||||
|
|
||||||
selectName: function(cm) { selectName(this, cm); },
|
|
||||||
|
|
||||||
request: function (cm, query, c, pos) {
|
|
||||||
var self = this;
|
|
||||||
var doc = findDoc(this, cm.getDoc());
|
|
||||||
var request = buildRequest(this, doc, query, pos);
|
|
||||||
|
|
||||||
this.server.request(request, function (error, data) {
|
|
||||||
if (!error && self.options.responseFilter)
|
|
||||||
data = self.options.responseFilter(doc, query, request, error, data);
|
|
||||||
c(error, data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function () {
|
|
||||||
if (this.worker) {
|
|
||||||
this.worker.terminate();
|
|
||||||
this.worker = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var Pos = CodeMirror.Pos;
|
|
||||||
var cls = "CodeMirror-Tern-";
|
|
||||||
var bigDoc = 250;
|
|
||||||
|
|
||||||
function getFile(ts, name, c) {
|
|
||||||
var buf = ts.docs[name];
|
|
||||||
if (buf)
|
|
||||||
c(docValue(ts, buf));
|
|
||||||
else if (ts.options.getFile)
|
|
||||||
ts.options.getFile(name, c);
|
|
||||||
else
|
|
||||||
c(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function findDoc(ts, doc, name) {
|
|
||||||
for (var n in ts.docs) {
|
|
||||||
var cur = ts.docs[n];
|
|
||||||
if (cur.doc == doc) return cur;
|
|
||||||
}
|
|
||||||
if (!name) for (var i = 0;; ++i) {
|
|
||||||
n = "[doc" + (i || "") + "]";
|
|
||||||
if (!ts.docs[n]) { name = n; break; }
|
|
||||||
}
|
|
||||||
return ts.addDoc(name, doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveDoc(ts, id) {
|
|
||||||
if (typeof id == "string") return ts.docs[id];
|
|
||||||
if (id instanceof CodeMirror) id = id.getDoc();
|
|
||||||
if (id instanceof CodeMirror.Doc) return findDoc(ts, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function trackChange(ts, doc, change) {
|
|
||||||
var data = findDoc(ts, doc);
|
|
||||||
|
|
||||||
var argHints = ts.cachedArgHints;
|
|
||||||
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
|
|
||||||
ts.cachedArgHints = null;
|
|
||||||
|
|
||||||
var changed = data.changed;
|
|
||||||
if (changed == null)
|
|
||||||
data.changed = changed = {from: change.from.line, to: change.from.line};
|
|
||||||
var end = change.from.line + (change.text.length - 1);
|
|
||||||
if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end);
|
|
||||||
if (end >= changed.to) changed.to = end + 1;
|
|
||||||
if (changed.from > change.from.line) changed.from = change.from.line;
|
|
||||||
|
|
||||||
if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() {
|
|
||||||
if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data);
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendDoc(ts, doc) {
|
|
||||||
ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {
|
|
||||||
if (error) window.console.error(error);
|
|
||||||
else doc.changed = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Completion
|
|
||||||
|
|
||||||
function hint(ts, cm, c) {
|
|
||||||
ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
|
|
||||||
if (error) return showError(ts, cm, error);
|
|
||||||
var completions = [], after = "";
|
|
||||||
var from = data.start, to = data.end;
|
|
||||||
if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
|
|
||||||
cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
|
|
||||||
after = "\"]";
|
|
||||||
|
|
||||||
for (var i = 0; i < data.completions.length; ++i) {
|
|
||||||
var completion = data.completions[i], className = typeToIcon(completion.type);
|
|
||||||
if (data.guess) className += " " + cls + "guess";
|
|
||||||
completions.push({text: completion.name + after,
|
|
||||||
displayText: completion.name,
|
|
||||||
className: className,
|
|
||||||
data: completion});
|
|
||||||
}
|
|
||||||
|
|
||||||
var obj = {from: from, to: to, list: completions};
|
|
||||||
var tooltip = null;
|
|
||||||
CodeMirror.on(obj, "close", function() { remove(tooltip); });
|
|
||||||
CodeMirror.on(obj, "update", function() { remove(tooltip); });
|
|
||||||
CodeMirror.on(obj, "select", function(cur, node) {
|
|
||||||
remove(tooltip);
|
|
||||||
var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
|
|
||||||
if (content) {
|
|
||||||
tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
|
|
||||||
node.getBoundingClientRect().top + window.pageYOffset, content);
|
|
||||||
tooltip.className += " " + cls + "hint-doc";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
c(obj);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function typeToIcon(type) {
|
|
||||||
var suffix;
|
|
||||||
if (type == "?") suffix = "unknown";
|
|
||||||
else if (type == "number" || type == "string" || type == "bool") suffix = type;
|
|
||||||
else if (/^fn\(/.test(type)) suffix = "fn";
|
|
||||||
else if (/^\[/.test(type)) suffix = "array";
|
|
||||||
else suffix = "object";
|
|
||||||
return cls + "completion " + cls + "completion-" + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type queries
|
|
||||||
|
|
||||||
function showContextInfo(ts, cm, pos, queryName, c) {
|
|
||||||
ts.request(cm, queryName, function(error, data) {
|
|
||||||
if (error) return showError(ts, cm, error);
|
|
||||||
if (ts.options.typeTip) {
|
|
||||||
var tip = ts.options.typeTip(data);
|
|
||||||
} else {
|
|
||||||
var tip = elt("span", null, elt("strong", null, data.type || "not found"));
|
|
||||||
if (data.doc)
|
|
||||||
tip.appendChild(document.createTextNode(" — " + data.doc));
|
|
||||||
if (data.url) {
|
|
||||||
tip.appendChild(document.createTextNode(" "));
|
|
||||||
var child = tip.appendChild(elt("a", null, "[docs]"));
|
|
||||||
child.href = data.url;
|
|
||||||
child.target = "_blank";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tempTooltip(cm, tip);
|
|
||||||
if (c) c();
|
|
||||||
}, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maintaining argument hints
|
|
||||||
|
|
||||||
function updateArgHints(ts, cm) {
|
|
||||||
closeArgHints(ts);
|
|
||||||
|
|
||||||
if (cm.somethingSelected()) return;
|
|
||||||
var state = cm.getTokenAt(cm.getCursor()).state;
|
|
||||||
var inner = CodeMirror.innerMode(cm.getMode(), state);
|
|
||||||
if (inner.mode.name != "javascript") return;
|
|
||||||
var lex = inner.state.lexical;
|
|
||||||
if (lex.info != "call") return;
|
|
||||||
|
|
||||||
var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize");
|
|
||||||
for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {
|
|
||||||
var str = cm.getLine(line), extra = 0;
|
|
||||||
for (var pos = 0;;) {
|
|
||||||
var tab = str.indexOf("\t", pos);
|
|
||||||
if (tab == -1) break;
|
|
||||||
extra += tabSize - (tab + extra) % tabSize - 1;
|
|
||||||
pos = tab + 1;
|
|
||||||
}
|
|
||||||
ch = lex.column - extra;
|
|
||||||
if (str.charAt(ch) == "(") {found = true; break;}
|
|
||||||
}
|
|
||||||
if (!found) return;
|
|
||||||
|
|
||||||
var start = Pos(line, ch);
|
|
||||||
var cache = ts.cachedArgHints;
|
|
||||||
if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
|
|
||||||
return showArgHints(ts, cm, argPos);
|
|
||||||
|
|
||||||
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
|
|
||||||
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
|
|
||||||
ts.cachedArgHints = {
|
|
||||||
start: pos,
|
|
||||||
type: parseFnType(data.type),
|
|
||||||
name: data.exprName || data.name || "fn",
|
|
||||||
guess: data.guess,
|
|
||||||
doc: cm.getDoc()
|
|
||||||
};
|
|
||||||
showArgHints(ts, cm, argPos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showArgHints(ts, cm, pos) {
|
|
||||||
closeArgHints(ts);
|
|
||||||
|
|
||||||
var cache = ts.cachedArgHints, tp = cache.type;
|
|
||||||
var tip = elt("span", cache.guess ? cls + "fhint-guess" : null,
|
|
||||||
elt("span", cls + "fname", cache.name), "(");
|
|
||||||
for (var i = 0; i < tp.args.length; ++i) {
|
|
||||||
if (i) tip.appendChild(document.createTextNode(", "));
|
|
||||||
var arg = tp.args[i];
|
|
||||||
tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?"));
|
|
||||||
if (arg.type != "?") {
|
|
||||||
tip.appendChild(document.createTextNode(":\u00a0"));
|
|
||||||
tip.appendChild(elt("span", cls + "type", arg.type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
|
|
||||||
if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
|
|
||||||
var place = cm.cursorCoords(null, "page");
|
|
||||||
ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseFnType(text) {
|
|
||||||
var args = [], pos = 3;
|
|
||||||
|
|
||||||
function skipMatching(upto) {
|
|
||||||
var depth = 0, start = pos;
|
|
||||||
for (;;) {
|
|
||||||
var next = text.charAt(pos);
|
|
||||||
if (upto.test(next) && !depth) return text.slice(start, pos);
|
|
||||||
if (/[{\[\(]/.test(next)) ++depth;
|
|
||||||
else if (/[}\]\)]/.test(next)) --depth;
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse arguments
|
|
||||||
if (text.charAt(pos) != ")") for (;;) {
|
|
||||||
var name = text.slice(pos).match(/^([^, \(\[\{]+): /);
|
|
||||||
if (name) {
|
|
||||||
pos += name[0].length;
|
|
||||||
name = name[1];
|
|
||||||
}
|
|
||||||
args.push({name: name, type: skipMatching(/[\),]/)});
|
|
||||||
if (text.charAt(pos) == ")") break;
|
|
||||||
pos += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rettype = text.slice(pos).match(/^\) -> (.*)$/);
|
|
||||||
|
|
||||||
return {args: args, rettype: rettype && rettype[1]};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moving to the definition of something
|
|
||||||
|
|
||||||
function jumpToDef(ts, cm) {
|
|
||||||
function inner(varName) {
|
|
||||||
var req = {type: "definition", variable: varName || null};
|
|
||||||
var doc = findDoc(ts, cm.getDoc());
|
|
||||||
ts.server.request(buildRequest(ts, doc, req), function(error, data) {
|
|
||||||
if (error) return showError(ts, cm, error);
|
|
||||||
if (!data.file && data.url) { window.open(data.url); return; }
|
|
||||||
|
|
||||||
if (data.file) {
|
|
||||||
var localDoc = ts.docs[data.file], found;
|
|
||||||
if (localDoc && (found = findContext(localDoc.doc, data))) {
|
|
||||||
ts.jumpStack.push({file: doc.name,
|
|
||||||
start: cm.getCursor("from"),
|
|
||||||
end: cm.getCursor("to")});
|
|
||||||
moveTo(ts, doc, localDoc, found.start, found.end);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showError(ts, cm, "Could not find a definition.");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!atInterestingExpression(cm))
|
|
||||||
dialog(cm, "Jump to variable", function(name) { if (name) inner(name); });
|
|
||||||
else
|
|
||||||
inner();
|
|
||||||
}
|
|
||||||
|
|
||||||
function jumpBack(ts, cm) {
|
|
||||||
var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file];
|
|
||||||
if (!doc) return;
|
|
||||||
moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveTo(ts, curDoc, doc, start, end) {
|
|
||||||
doc.doc.setSelection(start, end);
|
|
||||||
if (curDoc != doc && ts.options.switchToDoc) {
|
|
||||||
closeArgHints(ts);
|
|
||||||
ts.options.switchToDoc(doc.name, doc.doc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The {line,ch} representation of positions makes this rather awkward.
|
|
||||||
function findContext(doc, data) {
|
|
||||||
var before = data.context.slice(0, data.contextOffset).split("\n");
|
|
||||||
var startLine = data.start.line - (before.length - 1);
|
|
||||||
var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length);
|
|
||||||
|
|
||||||
var text = doc.getLine(startLine).slice(start.ch);
|
|
||||||
for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur)
|
|
||||||
text += "\n" + doc.getLine(cur);
|
|
||||||
if (text.slice(0, data.context.length) == data.context) return data;
|
|
||||||
|
|
||||||
var cursor = doc.getSearchCursor(data.context, 0, false);
|
|
||||||
var nearest, nearestDist = Infinity;
|
|
||||||
while (cursor.findNext()) {
|
|
||||||
var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000;
|
|
||||||
if (!dist) dist = Math.abs(from.ch - start.ch);
|
|
||||||
if (dist < nearestDist) { nearest = from; nearestDist = dist; }
|
|
||||||
}
|
|
||||||
if (!nearest) return null;
|
|
||||||
|
|
||||||
if (before.length == 1)
|
|
||||||
nearest.ch += before[0].length;
|
|
||||||
else
|
|
||||||
nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length);
|
|
||||||
if (data.start.line == data.end.line)
|
|
||||||
var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch));
|
|
||||||
else
|
|
||||||
var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch);
|
|
||||||
return {start: nearest, end: end};
|
|
||||||
}
|
|
||||||
|
|
||||||
function atInterestingExpression(cm) {
|
|
||||||
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
|
|
||||||
if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
|
|
||||||
return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variable renaming
|
|
||||||
|
|
||||||
function rename(ts, cm) {
|
|
||||||
var token = cm.getTokenAt(cm.getCursor());
|
|
||||||
if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable");
|
|
||||||
dialog(cm, "New name for " + token.string, function(newName) {
|
|
||||||
ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {
|
|
||||||
if (error) return showError(ts, cm, error);
|
|
||||||
applyChanges(ts, data.changes);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectName(ts, cm) {
|
|
||||||
var name = findDoc(ts, cm.doc).name;
|
|
||||||
ts.request(cm, {type: "refs"}, function(error, data) {
|
|
||||||
if (error) return showError(ts, cm, error);
|
|
||||||
var ranges = [], cur = 0;
|
|
||||||
for (var i = 0; i < data.refs.length; i++) {
|
|
||||||
var ref = data.refs[i];
|
|
||||||
if (ref.file == name) {
|
|
||||||
ranges.push({anchor: ref.start, head: ref.end});
|
|
||||||
if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
|
|
||||||
cur = ranges.length - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cm.setSelections(ranges, cur);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var nextChangeOrig = 0;
|
|
||||||
function applyChanges(ts, changes) {
|
|
||||||
var perFile = Object.create(null);
|
|
||||||
for (var i = 0; i < changes.length; ++i) {
|
|
||||||
var ch = changes[i];
|
|
||||||
(perFile[ch.file] || (perFile[ch.file] = [])).push(ch);
|
|
||||||
}
|
|
||||||
for (var file in perFile) {
|
|
||||||
var known = ts.docs[file], chs = perFile[file];;
|
|
||||||
if (!known) continue;
|
|
||||||
chs.sort(function(a, b) { return cmpPos(b.start, a.start); });
|
|
||||||
var origin = "*rename" + (++nextChangeOrig);
|
|
||||||
for (var i = 0; i < chs.length; ++i) {
|
|
||||||
var ch = chs[i];
|
|
||||||
known.doc.replaceRange(ch.text, ch.start, ch.end, origin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic request-building helper
|
|
||||||
|
|
||||||
function buildRequest(ts, doc, query, pos) {
|
|
||||||
var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
|
|
||||||
if (!allowFragments) delete query.fullDocs;
|
|
||||||
if (typeof query == "string") query = {type: query};
|
|
||||||
query.lineCharPositions = true;
|
|
||||||
if (query.end == null) {
|
|
||||||
query.end = pos || doc.doc.getCursor("end");
|
|
||||||
if (doc.doc.somethingSelected())
|
|
||||||
query.start = doc.doc.getCursor("start");
|
|
||||||
}
|
|
||||||
var startPos = query.start || query.end;
|
|
||||||
|
|
||||||
if (doc.changed) {
|
|
||||||
if (doc.doc.lineCount() > bigDoc && allowFragments !== false &&
|
|
||||||
doc.changed.to - doc.changed.from < 100 &&
|
|
||||||
doc.changed.from <= startPos.line && doc.changed.to > query.end.line) {
|
|
||||||
files.push(getFragmentAround(doc, startPos, query.end));
|
|
||||||
query.file = "#0";
|
|
||||||
var offsetLines = files[0].offsetLines;
|
|
||||||
if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch);
|
|
||||||
query.end = Pos(query.end.line - offsetLines, query.end.ch);
|
|
||||||
} else {
|
|
||||||
files.push({type: "full",
|
|
||||||
name: doc.name,
|
|
||||||
text: docValue(ts, doc)});
|
|
||||||
query.file = doc.name;
|
|
||||||
doc.changed = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
query.file = doc.name;
|
|
||||||
}
|
|
||||||
for (var name in ts.docs) {
|
|
||||||
var cur = ts.docs[name];
|
|
||||||
if (cur.changed && cur != doc) {
|
|
||||||
files.push({type: "full", name: cur.name, text: docValue(ts, cur)});
|
|
||||||
cur.changed = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {query: query, files: files};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFragmentAround(data, start, end) {
|
|
||||||
var doc = data.doc;
|
|
||||||
var minIndent = null, minLine = null, endLine, tabSize = 4;
|
|
||||||
for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) {
|
|
||||||
var line = doc.getLine(p), fn = line.search(/\bfunction\b/);
|
|
||||||
if (fn < 0) continue;
|
|
||||||
var indent = CodeMirror.countColumn(line, null, tabSize);
|
|
||||||
if (minIndent != null && minIndent <= indent) continue;
|
|
||||||
minIndent = indent;
|
|
||||||
minLine = p;
|
|
||||||
}
|
|
||||||
if (minLine == null) minLine = min;
|
|
||||||
var max = Math.min(doc.lastLine(), end.line + 20);
|
|
||||||
if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize))
|
|
||||||
endLine = max;
|
|
||||||
else for (endLine = end.line + 1; endLine < max; ++endLine) {
|
|
||||||
var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize);
|
|
||||||
if (indent <= minIndent) break;
|
|
||||||
}
|
|
||||||
var from = Pos(minLine, 0);
|
|
||||||
|
|
||||||
return {type: "part",
|
|
||||||
name: data.name,
|
|
||||||
offsetLines: from.line,
|
|
||||||
text: doc.getRange(from, Pos(endLine, 0))};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic utilities
|
|
||||||
|
|
||||||
var cmpPos = CodeMirror.cmpPos;
|
|
||||||
|
|
||||||
function elt(tagname, cls /*, ... elts*/) {
|
|
||||||
var e = document.createElement(tagname);
|
|
||||||
if (cls) e.className = cls;
|
|
||||||
for (var i = 2; i < arguments.length; ++i) {
|
|
||||||
var elt = arguments[i];
|
|
||||||
if (typeof elt == "string") elt = document.createTextNode(elt);
|
|
||||||
e.appendChild(elt);
|
|
||||||
}
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
function dialog(cm, text, f) {
|
|
||||||
if (cm.openDialog)
|
|
||||||
cm.openDialog(text + ": <input type=text>", f);
|
|
||||||
else
|
|
||||||
f(prompt(text, ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tooltips
|
|
||||||
|
|
||||||
function tempTooltip(cm, content) {
|
|
||||||
if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
|
|
||||||
var where = cm.cursorCoords();
|
|
||||||
var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
|
|
||||||
function maybeClear() {
|
|
||||||
old = true;
|
|
||||||
if (!mouseOnTip) clear();
|
|
||||||
}
|
|
||||||
function clear() {
|
|
||||||
cm.state.ternTooltip = null;
|
|
||||||
if (!tip.parentNode) return;
|
|
||||||
cm.off("cursorActivity", clear);
|
|
||||||
cm.off('blur', clear);
|
|
||||||
cm.off('scroll', clear);
|
|
||||||
fadeOut(tip);
|
|
||||||
}
|
|
||||||
var mouseOnTip = false, old = false;
|
|
||||||
CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
|
|
||||||
CodeMirror.on(tip, "mouseout", function(e) {
|
|
||||||
if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
|
|
||||||
if (old) clear();
|
|
||||||
else mouseOnTip = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setTimeout(maybeClear, 1700);
|
|
||||||
cm.on("cursorActivity", clear);
|
|
||||||
cm.on('blur', clear);
|
|
||||||
cm.on('scroll', clear);
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeTooltip(x, y, content) {
|
|
||||||
var node = elt("div", cls + "tooltip", content);
|
|
||||||
node.style.left = x + "px";
|
|
||||||
node.style.top = y + "px";
|
|
||||||
document.body.appendChild(node);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(node) {
|
|
||||||
var p = node && node.parentNode;
|
|
||||||
if (p) p.removeChild(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fadeOut(tooltip) {
|
|
||||||
tooltip.style.opacity = "0";
|
|
||||||
setTimeout(function() { remove(tooltip); }, 1100);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showError(ts, cm, msg) {
|
|
||||||
if (ts.options.showError)
|
|
||||||
ts.options.showError(cm, msg);
|
|
||||||
else
|
|
||||||
tempTooltip(cm, String(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeArgHints(ts) {
|
|
||||||
if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
function docValue(ts, doc) {
|
|
||||||
var val = doc.doc.getValue();
|
|
||||||
if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Worker wrapper
|
|
||||||
|
|
||||||
function WorkerServer(ts) {
|
|
||||||
var worker = ts.worker = new Worker(ts.options.workerScript);
|
|
||||||
worker.postMessage({type: "init",
|
|
||||||
defs: ts.options.defs,
|
|
||||||
plugins: ts.options.plugins,
|
|
||||||
scripts: ts.options.workerDeps});
|
|
||||||
var msgId = 0, pending = {};
|
|
||||||
|
|
||||||
function send(data, c) {
|
|
||||||
if (c) {
|
|
||||||
data.id = ++msgId;
|
|
||||||
pending[msgId] = c;
|
|
||||||
}
|
|
||||||
worker.postMessage(data);
|
|
||||||
}
|
|
||||||
worker.onmessage = function(e) {
|
|
||||||
var data = e.data;
|
|
||||||
if (data.type == "getFile") {
|
|
||||||
getFile(ts, data.name, function(err, text) {
|
|
||||||
send({type: "getFile", err: String(err), text: text, id: data.id});
|
|
||||||
});
|
|
||||||
} else if (data.type == "debug") {
|
|
||||||
window.console.log(data.message);
|
|
||||||
} else if (data.id && pending[data.id]) {
|
|
||||||
pending[data.id](data.err, data.body);
|
|
||||||
delete pending[data.id];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
worker.onerror = function(e) {
|
|
||||||
for (var id in pending) pending[id](e);
|
|
||||||
pending = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
this.addFile = function(name, text) { send({type: "add", name: name, text: text}); };
|
|
||||||
this.delFile = function(name) { send({type: "del", name: name}); };
|
|
||||||
this.request = function(body, c) { send({type: "req", body: body}, c); };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
// declare global: tern, server
|
|
||||||
|
|
||||||
var server;
|
|
||||||
|
|
||||||
this.onmessage = function(e) {
|
|
||||||
var data = e.data;
|
|
||||||
switch (data.type) {
|
|
||||||
case "init": return startServer(data.defs, data.plugins, data.scripts);
|
|
||||||
case "add": return server.addFile(data.name, data.text);
|
|
||||||
case "del": return server.delFile(data.name);
|
|
||||||
case "req": return server.request(data.body, function(err, reqData) {
|
|
||||||
postMessage({id: data.id, body: reqData, err: err && String(err)});
|
|
||||||
});
|
|
||||||
case "getFile":
|
|
||||||
var c = pending[data.id];
|
|
||||||
delete pending[data.id];
|
|
||||||
return c(data.err, data.text);
|
|
||||||
default: throw new Error("Unknown message type: " + data.type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var nextId = 0, pending = {};
|
|
||||||
function getFile(file, c) {
|
|
||||||
postMessage({type: "getFile", name: file, id: ++nextId});
|
|
||||||
pending[nextId] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
function startServer(defs, plugins, scripts) {
|
|
||||||
if (scripts) importScripts.apply(null, scripts);
|
|
||||||
|
|
||||||
server = new tern.Server({
|
|
||||||
getFile: getFile,
|
|
||||||
async: true,
|
|
||||||
defs: defs,
|
|
||||||
plugins: plugins
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var console = {
|
|
||||||
log: function(v) { postMessage({type: "debug", message: v}); }
|
|
||||||
};
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
||||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
||||||
|
|
||||||
(function(mod) {
|
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
||||||
mod(require("../../lib/codemirror"));
|
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
|
||||||
define(["../../lib/codemirror"], mod);
|
|
||||||
else // Plain browser env
|
|
||||||
mod(CodeMirror);
|
|
||||||
})(function(CodeMirror) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var Pos = CodeMirror.Pos;
|
|
||||||
|
|
||||||
function findParagraph(cm, pos, options) {
|
|
||||||
var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
|
|
||||||
for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
|
|
||||||
var line = cm.getLine(start);
|
|
||||||
if (startRE && startRE.test(line)) break;
|
|
||||||
if (!/\S/.test(line)) { ++start; break; }
|
|
||||||
}
|
|
||||||
var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
|
|
||||||
for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
|
|
||||||
var line = cm.getLine(end);
|
|
||||||
if (endRE && endRE.test(line)) { ++end; break; }
|
|
||||||
if (!/\S/.test(line)) break;
|
|
||||||
}
|
|
||||||
return {from: start, to: end};
|
|
||||||
}
|
|
||||||
|
|
||||||
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
|
|
||||||
for (var at = column; at > 0; --at)
|
|
||||||
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
|
|
||||||
if (at == 0) at = column;
|
|
||||||
var endOfText = at;
|
|
||||||
if (killTrailingSpace)
|
|
||||||
while (text.charAt(endOfText - 1) == " ") --endOfText;
|
|
||||||
return {from: endOfText, to: at};
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapRange(cm, from, to, options) {
|
|
||||||
from = cm.clipPos(from); to = cm.clipPos(to);
|
|
||||||
var column = options.column || 80;
|
|
||||||
var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
|
|
||||||
var killTrailing = options.killTrailingSpace !== false;
|
|
||||||
var changes = [], curLine = "", curNo = from.line;
|
|
||||||
var lines = cm.getRange(from, to, false);
|
|
||||||
if (!lines.length) return null;
|
|
||||||
var leadingSpace = lines[0].match(/^[ \t]*/)[0];
|
|
||||||
|
|
||||||
for (var i = 0; i < lines.length; ++i) {
|
|
||||||
var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
|
|
||||||
if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
|
|
||||||
curLine += " ";
|
|
||||||
spaceInserted = 1;
|
|
||||||
}
|
|
||||||
var spaceTrimmed = "";
|
|
||||||
if (i) {
|
|
||||||
spaceTrimmed = text.match(/^\s*/)[0];
|
|
||||||
text = text.slice(spaceTrimmed.length);
|
|
||||||
}
|
|
||||||
curLine += text;
|
|
||||||
if (i) {
|
|
||||||
var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
|
|
||||||
findBreakPoint(curLine, column, wrapOn, killTrailing);
|
|
||||||
// If this isn't broken, or is broken at a different point, remove old break
|
|
||||||
if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
|
|
||||||
changes.push({text: [spaceInserted ? " " : ""],
|
|
||||||
from: Pos(curNo, oldLen),
|
|
||||||
to: Pos(curNo + 1, spaceTrimmed.length)});
|
|
||||||
} else {
|
|
||||||
curLine = leadingSpace + text;
|
|
||||||
++curNo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (curLine.length > column) {
|
|
||||||
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
|
|
||||||
changes.push({text: ["", leadingSpace],
|
|
||||||
from: Pos(curNo, bp.from),
|
|
||||||
to: Pos(curNo, bp.to)});
|
|
||||||
curLine = leadingSpace + curLine.slice(bp.to);
|
|
||||||
++curNo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (changes.length) cm.operation(function() {
|
|
||||||
for (var i = 0; i < changes.length; ++i) {
|
|
||||||
var change = changes[i];
|
|
||||||
cm.replaceRange(change.text, change.from, change.to);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
|
|
||||||
options = options || {};
|
|
||||||
if (!pos) pos = this.getCursor();
|
|
||||||
var para = findParagraph(this, pos, options);
|
|
||||||
return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.commands.wrapLines = function(cm) {
|
|
||||||
cm.operation(function() {
|
|
||||||
var ranges = cm.listSelections(), at = cm.lastLine() + 1;
|
|
||||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
|
||||||
var range = ranges[i], span;
|
|
||||||
if (range.empty()) {
|
|
||||||
var para = findParagraph(cm, range.head, {});
|
|
||||||
span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
|
|
||||||
} else {
|
|
||||||
span = {from: range.from(), to: range.to()};
|
|
||||||
}
|
|
||||||
if (span.to.line >= at) continue;
|
|
||||||
at = span.from.line;
|
|
||||||
wrapRange(cm, span.from, span.to, {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeMirror.defineExtension("wrapRange", function(from, to, options) {
|
|
||||||
return wrapRange(this, from, to, options || {});
|
|
||||||
});
|
|
||||||
|
|
||||||
CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
|
|
||||||
options = options || {};
|
|
||||||
var cm = this, paras = [];
|
|
||||||
for (var line = from.line; line <= to.line;) {
|
|
||||||
var para = findParagraph(cm, Pos(line, 0), options);
|
|
||||||
paras.push(para);
|
|
||||||
line = para.to;
|
|
||||||
}
|
|
||||||
var madeChange = false;
|
|
||||||
if (paras.length) cm.operation(function() {
|
|
||||||
for (var i = paras.length - 1; i >= 0; --i)
|
|
||||||
madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
|
|
||||||
});
|
|
||||||
return madeChange;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "codemirror",
|
|
||||||
"version":"5.0.0",
|
|
||||||
"main": ["lib/codemirror.js", "lib/codemirror.css"],
|
|
||||||
"ignore": [
|
|
||||||
"**/.*",
|
|
||||||
"node_modules",
|
|
||||||
"components",
|
|
||||||
"bin",
|
|
||||||
"demo",
|
|
||||||
"doc",
|
|
||||||
"test",
|
|
||||||
"index.html",
|
|
||||||
"package.json"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Active Line Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../addon/selection/active-line.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Active Line</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Active Line Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
|
|
||||||
xmlns:georss="http://www.georss.org/georss"
|
|
||||||
xmlns:twitter="http://api.twitter.com">
|
|
||||||
<channel>
|
|
||||||
<title>Twitter / codemirror</title>
|
|
||||||
<link>http://twitter.com/codemirror</link>
|
|
||||||
<atom:link type="application/rss+xml"
|
|
||||||
href="http://twitter.com/statuses/user_timeline/242283288.rss" rel="self"/>
|
|
||||||
<description>Twitter updates from CodeMirror / codemirror.</description>
|
|
||||||
<language>en-us</language>
|
|
||||||
<ttl>40</ttl>
|
|
||||||
<item>
|
|
||||||
<title>codemirror: http://cloud-ide.com — they're springing up like mushrooms. This one
|
|
||||||
uses CodeMirror as its editor.</title>
|
|
||||||
<description>codemirror: http://cloud-ide.com — they're springing up like mushrooms. This
|
|
||||||
one uses CodeMirror as its editor.</description>
|
|
||||||
<pubDate>Thu, 17 Mar 2011 23:34:47 +0000</pubDate>
|
|
||||||
<guid>http://twitter.com/codemirror/statuses/48527733722058752</guid>
|
|
||||||
<link>http://twitter.com/codemirror/statuses/48527733722058752</link>
|
|
||||||
<twitter:source>web</twitter:source>
|
|
||||||
<twitter:place/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<title>codemirror: Posted a description of the CodeMirror 2 internals at
|
|
||||||
http://codemirror.net/2/internals.html</title>
|
|
||||||
<description>codemirror: Posted a description of the CodeMirror 2 internals at
|
|
||||||
http://codemirror.net/2/internals.html</description>
|
|
||||||
<pubDate>Wed, 02 Mar 2011 12:15:09 +0000</pubDate>
|
|
||||||
<guid>http://twitter.com/codemirror/statuses/42920879788789760</guid>
|
|
||||||
<link>http://twitter.com/codemirror/statuses/42920879788789760</link>
|
|
||||||
<twitter:source>web</twitter:source>
|
|
||||||
<twitter:place/>
|
|
||||||
</item>
|
|
||||||
</channel>
|
|
||||||
</rss></textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "application/xml",
|
|
||||||
styleActiveLine: true,
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Styling the current cursor line.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Any Word Completion Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/hint/show-hint.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/hint/show-hint.js"></script>
|
|
||||||
<script src="../addon/hint/anyword-hint.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Any Word Completion</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Any Word Completion Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
(function() {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var WORD = /[\w$]+/g, RANGE = 500;
|
|
||||||
|
|
||||||
CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
|
|
||||||
var word = options && options.word || WORD;
|
|
||||||
var range = options && options.range || RANGE;
|
|
||||||
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
|
|
||||||
var start = cur.ch, end = start;
|
|
||||||
while (end < curLine.length && word.test(curLine.charAt(end))) ++end;
|
|
||||||
while (start && word.test(curLine.charAt(start - 1))) --start;
|
|
||||||
var curWord = start != end && curLine.slice(start, end);
|
|
||||||
|
|
||||||
var list = [], seen = {};
|
|
||||||
function scan(dir) {
|
|
||||||
var line = cur.line, end = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
|
|
||||||
for (; line != end; line += dir) {
|
|
||||||
var text = editor.getLine(line), m;
|
|
||||||
word.lastIndex = 0;
|
|
||||||
while (m = word.exec(text)) {
|
|
||||||
if ((!curWord || m[0].indexOf(curWord) == 0) && !seen.hasOwnProperty(m[0])) {
|
|
||||||
seen[m[0]] = true;
|
|
||||||
list.push(m[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scan(-1);
|
|
||||||
scan(1);
|
|
||||||
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>Press <strong>ctrl-space</strong> to activate autocompletion. The
|
|
||||||
completion uses
|
|
||||||
the <a href="../doc/manual.html#addon_anyword-hint">anyword-hint.js</a>
|
|
||||||
module, which simply looks at nearby words in the buffer and completes
|
|
||||||
to those.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
CodeMirror.commands.autocomplete = function(cm) {
|
|
||||||
cm.showHint({hint: CodeMirror.hint.anyword});
|
|
||||||
}
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
extraKeys: {"Ctrl-Space": "autocomplete"}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Bi-directional Text Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Bi-directional Text</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Bi-directional Text Demo</h2>
|
|
||||||
<form><textarea id="code" name="code"><!-- Piece of the CodeMirror manual, 'translated' into Arabic by
|
|
||||||
Google Translate -->
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt id=option_value><code>value (string or Doc)</code></dt>
|
|
||||||
<dd>قيمة البداية المحرر. يمكن أن تكون سلسلة، أو. كائن مستند.</dd>
|
|
||||||
<dt id=option_mode><code>mode (string or object)</code></dt>
|
|
||||||
<dd>وضع الاستخدام. عندما لا تعطى، وهذا الافتراضي إلى الطريقة الاولى
|
|
||||||
التي تم تحميلها. قد يكون من سلسلة، والتي إما أسماء أو ببساطة هو وضع
|
|
||||||
MIME نوع المرتبطة اسطة. بدلا من ذلك، قد يكون من كائن يحتوي على
|
|
||||||
خيارات التكوين لواسطة، مع <code>name</code> الخاصية التي وضع أسماء
|
|
||||||
(على سبيل المثال <code>{name: "javascript", json: true}</code>).
|
|
||||||
صفحات التجريبي لكل وضع تحتوي على معلومات حول ما معلمات تكوين وضع
|
|
||||||
يدعمها. يمكنك أن تطلب CodeMirror التي تم تعريفها طرق وأنواع MIME
|
|
||||||
الكشف على <code>CodeMirror.modes</code>
|
|
||||||
و <code>CodeMirror.mimeModes</code> الكائنات. وضع خرائط الأسماء
|
|
||||||
الأولى لمنشئات الخاصة بهم، وخرائط لأنواع MIME 2 المواصفات
|
|
||||||
واسطة.</dd>
|
|
||||||
<dt id=option_theme><code>theme (string)</code></dt>
|
|
||||||
<dd>موضوع لنمط المحرر مع. يجب عليك التأكد من الملف CSS تحديد
|
|
||||||
المقابلة <code>.cm-s-[name]</code> يتم تحميل أنماط (انظر
|
|
||||||
<a href="../theme/"><code>theme</code></a> الدليل في التوزيع).
|
|
||||||
الافتراضي هو <code>"default"</code> ، والتي تم تضمينها في
|
|
||||||
الألوان <code>codemirror.css</code>. فمن الممكن استخدام فئات متعددة
|
|
||||||
في تطبيق السمات مرة واحدة على سبيل المثال <code>"foo bar"</code>
|
|
||||||
سيتم تعيين كل من <code>cm-s-foo</code> و <code>cm-s-bar</code>
|
|
||||||
الطبقات إلى المحرر.</dd>
|
|
||||||
</dl>
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "text/html",
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of bi-directional text support. See
|
|
||||||
the <a href="http://marijnhaverbeke.nl/blog/cursor-in-bidi-text.html">related
|
|
||||||
blog post</a> for more background.</p>
|
|
||||||
|
|
||||||
<p><strong>Note:</strong> There is
|
|
||||||
a <a href="https://github.com/codemirror/CodeMirror/issues/1757">known
|
|
||||||
bug</a> with cursor motion and mouse clicks in bi-directional lines
|
|
||||||
that are line wrapped.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: B-Tree visualization</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.lineblock { display: inline-block; margin: 1px; height: 5px; }
|
|
||||||
.CodeMirror {border: 1px solid #aaa; height: 400px}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">B-Tree visualization</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>B-Tree visualization</h2>
|
|
||||||
<form><textarea id="code" name="code">type here, see a summary of the document b-tree below</textarea></form>
|
|
||||||
</div>
|
|
||||||
<div style="display: inline-block; height: 402px; overflow-y: auto" id="output"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script id="me">
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true
|
|
||||||
});
|
|
||||||
var updateTimeout;
|
|
||||||
editor.on("change", function(cm) {
|
|
||||||
clearTimeout(updateTimeout);
|
|
||||||
updateTimeout = setTimeout(updateVisual, 200);
|
|
||||||
});
|
|
||||||
updateVisual();
|
|
||||||
|
|
||||||
function updateVisual() {
|
|
||||||
var out = document.getElementById("output");
|
|
||||||
out.innerHTML = "";
|
|
||||||
|
|
||||||
function drawTree(out, node) {
|
|
||||||
if (node.lines) {
|
|
||||||
out.appendChild(document.createElement("div")).innerHTML =
|
|
||||||
"<b>leaf</b>: " + node.lines.length + " lines, " + Math.round(node.height) + " px";
|
|
||||||
var lines = out.appendChild(document.createElement("div"));
|
|
||||||
lines.style.lineHeight = "6px"; lines.style.marginLeft = "10px";
|
|
||||||
for (var i = 0; i < node.lines.length; ++i) {
|
|
||||||
var line = node.lines[i], lineElt = lines.appendChild(document.createElement("div"));
|
|
||||||
lineElt.className = "lineblock";
|
|
||||||
var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16);
|
|
||||||
if (col.length == 1) col = "0" + col;
|
|
||||||
lineElt.style.background = "#" + col + col + col;
|
|
||||||
lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out.appendChild(document.createElement("div")).innerHTML =
|
|
||||||
"<b>node</b>: " + node.size + " lines, " + Math.round(node.height) + " px";
|
|
||||||
var sub = out.appendChild(document.createElement("div"));
|
|
||||||
sub.style.paddingLeft = "20px";
|
|
||||||
for (var i = 0; i < node.children.length; ++i)
|
|
||||||
drawTree(sub, node.children[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drawTree(out, editor.getDoc());
|
|
||||||
}
|
|
||||||
|
|
||||||
function fillEditor() {
|
|
||||||
var sc = document.getElementById("me");
|
|
||||||
var doc = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "") + "\n";
|
|
||||||
doc += doc; doc += doc; doc += doc; doc += doc; doc += doc; doc += doc;
|
|
||||||
editor.setValue(doc);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p><button onclick="fillEditor()">Add a lot of content</button></p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Multiple Buffer & Split View Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/css/css.js"></script>
|
|
||||||
<style type="text/css" id=style>
|
|
||||||
.CodeMirror {border: 1px solid black; height: 250px;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Multiple Buffer & Split View</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Multiple Buffer & Split View Demo</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<div id=code_top></div>
|
|
||||||
<div>
|
|
||||||
Select buffer: <select id=buffers_top></select>
|
|
||||||
<button onclick="newBuf('top')">New buffer</button>
|
|
||||||
</div>
|
|
||||||
<div id=code_bot></div>
|
|
||||||
<div>
|
|
||||||
Select buffer: <select id=buffers_bot></select>
|
|
||||||
<button onclick="newBuf('bot')">New buffer</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script id=script>
|
|
||||||
var sel_top = document.getElementById("buffers_top");
|
|
||||||
CodeMirror.on(sel_top, "change", function() {
|
|
||||||
selectBuffer(ed_top, sel_top.options[sel_top.selectedIndex].value);
|
|
||||||
});
|
|
||||||
|
|
||||||
var sel_bot = document.getElementById("buffers_bot");
|
|
||||||
CodeMirror.on(sel_bot, "change", function() {
|
|
||||||
selectBuffer(ed_bot, sel_bot.options[sel_bot.selectedIndex].value);
|
|
||||||
});
|
|
||||||
|
|
||||||
var buffers = {};
|
|
||||||
|
|
||||||
function openBuffer(name, text, mode) {
|
|
||||||
buffers[name] = CodeMirror.Doc(text, mode);
|
|
||||||
var opt = document.createElement("option");
|
|
||||||
opt.appendChild(document.createTextNode(name));
|
|
||||||
sel_top.appendChild(opt);
|
|
||||||
sel_bot.appendChild(opt.cloneNode(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
function newBuf(where) {
|
|
||||||
var name = prompt("Name for the buffer", "*scratch*");
|
|
||||||
if (name == null) return;
|
|
||||||
if (buffers.hasOwnProperty(name)) {
|
|
||||||
alert("There's already a buffer by that name.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
openBuffer(name, "", "javascript");
|
|
||||||
selectBuffer(where == "top" ? ed_top : ed_bot, name);
|
|
||||||
var sel = where == "top" ? sel_top : sel_bot;
|
|
||||||
sel.value = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectBuffer(editor, name) {
|
|
||||||
var buf = buffers[name];
|
|
||||||
if (buf.getEditor()) buf = buf.linkedDoc({sharedHist: true});
|
|
||||||
var old = editor.swapDoc(buf);
|
|
||||||
var linked = old.iterLinkedDocs(function(doc) {linked = doc;});
|
|
||||||
if (linked) {
|
|
||||||
// Make sure the document in buffers is the one the other view is looking at
|
|
||||||
for (var name in buffers) if (buffers[name] == old) buffers[name] = linked;
|
|
||||||
old.unlinkDoc(linked);
|
|
||||||
}
|
|
||||||
editor.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
function nodeContent(id) {
|
|
||||||
var node = document.getElementById(id), val = node.textContent || node.innerText;
|
|
||||||
val = val.slice(val.match(/^\s*/)[0].length, val.length - val.match(/\s*$/)[0].length) + "\n";
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
openBuffer("js", nodeContent("script"), "javascript");
|
|
||||||
openBuffer("css", nodeContent("style"), "css");
|
|
||||||
|
|
||||||
var ed_top = CodeMirror(document.getElementById("code_top"), {lineNumbers: true});
|
|
||||||
selectBuffer(ed_top, "js");
|
|
||||||
var ed_bot = CodeMirror(document.getElementById("code_bot"), {lineNumbers: true});
|
|
||||||
selectBuffer(ed_bot, "js");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of
|
|
||||||
using <a href="../doc/manual.html#linkedDoc">linked documents</a>
|
|
||||||
to provide a split view on a document, and
|
|
||||||
using <a href="../doc/manual.html#swapDoc"><code>swapDoc</code></a>
|
|
||||||
to use a single editor to display multiple documents.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Mode-Changing Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/scheme/scheme.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Mode-Changing</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Mode-Changing Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
;; If there is Scheme code in here, the editor will be in Scheme mode.
|
|
||||||
;; If you put in JS instead, it'll switch to JS mode.
|
|
||||||
|
|
||||||
(define (double x)
|
|
||||||
(* x x))
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>On changes to the content of the above editor, a (crude) script
|
|
||||||
tries to auto-detect the language used, and switches the editor to
|
|
||||||
either JavaScript or Scheme mode based on that.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "scheme",
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
var pending;
|
|
||||||
editor.on("change", function() {
|
|
||||||
clearTimeout(pending);
|
|
||||||
pending = setTimeout(update, 400);
|
|
||||||
});
|
|
||||||
function looksLikeScheme(code) {
|
|
||||||
return !/^\s*\(\s*function\b/.test(code) && /^\s*[;\(]/.test(code);
|
|
||||||
}
|
|
||||||
function update() {
|
|
||||||
editor.setOption("mode", looksLikeScheme(editor.getValue()) ? "scheme" : "javascript");
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Closebrackets Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/edit/closebrackets.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Closebrackets</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Closebrackets Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">function Grid(width, height) {
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
this.cells = new Array(width * height);
|
|
||||||
}
|
|
||||||
Grid.prototype.valueAt = function(point) {
|
|
||||||
return this.cells[point.y * this.width + point.x];
|
|
||||||
};
|
|
||||||
Grid.prototype.setValueAt = function(point, value) {
|
|
||||||
this.cells[point.y * this.width + point.x] = value;
|
|
||||||
};
|
|
||||||
Grid.prototype.isInside = function(point) {
|
|
||||||
return point.x >= 0 && point.y >= 0 &&
|
|
||||||
point.x < this.width && point.y < this.height;
|
|
||||||
};
|
|
||||||
Grid.prototype.moveValue = function(from, to) {
|
|
||||||
this.setValueAt(to, this.valueAt(from));
|
|
||||||
this.setValueAt(from, undefined);
|
|
||||||
};</textarea></form>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {autoCloseBrackets: true});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Close-Tag Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/edit/closetag.js"></script>
|
|
||||||
<script src="../addon/fold/xml-fold.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/css/css.js"></script>
|
|
||||||
<script src="../mode/htmlmixed/htmlmixed.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Close-Tag</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Close-Tag Demo</h2>
|
|
||||||
<form><textarea id="code" name="code"><html</textarea></form>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: 'text/html',
|
|
||||||
autoCloseTags: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Autocomplete Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/hint/show-hint.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/hint/show-hint.js"></script>
|
|
||||||
<script src="../addon/hint/javascript-hint.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Autocomplete</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Autocomplete Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
function getCompletions(token, context) {
|
|
||||||
var found = [], start = token.string;
|
|
||||||
function maybeAdd(str) {
|
|
||||||
if (str.indexOf(start) == 0) found.push(str);
|
|
||||||
}
|
|
||||||
function gatherCompletions(obj) {
|
|
||||||
if (typeof obj == "string") forEach(stringProps, maybeAdd);
|
|
||||||
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
|
|
||||||
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
|
|
||||||
for (var name in obj) maybeAdd(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context) {
|
|
||||||
// If this is a property, see if it belongs to some object we can
|
|
||||||
// find in the current environment.
|
|
||||||
var obj = context.pop(), base;
|
|
||||||
if (obj.className == "js-variable")
|
|
||||||
base = window[obj.string];
|
|
||||||
else if (obj.className == "js-string")
|
|
||||||
base = "";
|
|
||||||
else if (obj.className == "js-atom")
|
|
||||||
base = 1;
|
|
||||||
while (base != null && context.length)
|
|
||||||
base = base[context.pop().string];
|
|
||||||
if (base != null) gatherCompletions(base);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If not, just look in the window object and any local scope
|
|
||||||
// (reading into JS mode internals to get at the local variables)
|
|
||||||
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
|
|
||||||
gatherCompletions(window);
|
|
||||||
forEach(keywords, maybeAdd);
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>Press <strong>ctrl-space</strong> to activate autocompletion. Built
|
|
||||||
on top of the <a href="../doc/manual.html#addon_show-hint"><code>show-hint</code></a>
|
|
||||||
and <a href="../doc/manual.html#addon_javascript-hint"><code>javascript-hint</code></a>
|
|
||||||
addons.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
|
||||||
mode: {name: "javascript", globalVars: true}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Emacs bindings demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/dialog/dialog.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/clike/clike.js"></script>
|
|
||||||
<script src="../keymap/emacs.js"></script>
|
|
||||||
<script src="../addon/edit/matchbrackets.js"></script>
|
|
||||||
<script src="../addon/comment/comment.js"></script>
|
|
||||||
<script src="../addon/dialog/dialog.js"></script>
|
|
||||||
<script src="../addon/search/searchcursor.js"></script>
|
|
||||||
<script src="../addon/search/search.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Emacs bindings</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Emacs bindings demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
#include "syscalls.h"
|
|
||||||
/* getchar: simple buffered version */
|
|
||||||
int getchar(void)
|
|
||||||
{
|
|
||||||
static char buf[BUFSIZ];
|
|
||||||
static char *bufp = buf;
|
|
||||||
static int n = 0;
|
|
||||||
if (n == 0) { /* buffer is empty */
|
|
||||||
n = read(0, buf, sizeof buf);
|
|
||||||
bufp = buf;
|
|
||||||
}
|
|
||||||
return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
|
|
||||||
}
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>The emacs keybindings are enabled by
|
|
||||||
including <a href="../keymap/emacs.js">keymap/emacs.js</a> and setting
|
|
||||||
the <code>keyMap</code> option to <code>"emacs"</code>. Because
|
|
||||||
CodeMirror's internal API is quite different from Emacs, they are only
|
|
||||||
a loose approximation of actual emacs bindings, though.</p>
|
|
||||||
|
|
||||||
<p>Also note that a lot of browsers disallow certain keys from being
|
|
||||||
captured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the
|
|
||||||
result that idiomatic use of Emacs keys will constantly close your tab
|
|
||||||
or open a new window.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
CodeMirror.commands.save = function() {
|
|
||||||
var elt = editor.getWrapperElement();
|
|
||||||
elt.style.background = "#def";
|
|
||||||
setTimeout(function() { elt.style.background = ""; }, 300);
|
|
||||||
};
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "text/x-csrc",
|
|
||||||
keyMap: "emacs"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>CodeMirror: Code Folding Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/fold/foldgutter.css" />
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/fold/foldcode.js"></script>
|
|
||||||
<script src="../addon/fold/foldgutter.js"></script>
|
|
||||||
<script src="../addon/fold/brace-fold.js"></script>
|
|
||||||
<script src="../addon/fold/xml-fold.js"></script>
|
|
||||||
<script src="../addon/fold/markdown-fold.js"></script>
|
|
||||||
<script src="../addon/fold/comment-fold.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../mode/markdown/markdown.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Code Folding</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Code Folding Demo</h2>
|
|
||||||
<form>
|
|
||||||
<div style="max-width: 50em; margin-bottom: 1em">JavaScript:<br>
|
|
||||||
<textarea id="code" name="code"></textarea></div>
|
|
||||||
<div style="max-width: 50em; margin-bottom: 1em">HTML:<br>
|
|
||||||
<textarea id="code-html" name="code-html"></textarea></div>
|
|
||||||
<div style="max-width: 50em">Markdown:<br>
|
|
||||||
<textarea id="code-markdown" name="code"></textarea></div>
|
|
||||||
</form>
|
|
||||||
<script id="script">
|
|
||||||
/*
|
|
||||||
* Demonstration of code folding
|
|
||||||
*/
|
|
||||||
window.onload = function() {
|
|
||||||
var te = document.getElementById("code");
|
|
||||||
var sc = document.getElementById("script");
|
|
||||||
te.value = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "");
|
|
||||||
sc.innerHTML = "";
|
|
||||||
var te_html = document.getElementById("code-html");
|
|
||||||
te_html.value = document.documentElement.innerHTML;
|
|
||||||
var te_markdown = document.getElementById("code-markdown");
|
|
||||||
te_markdown.value = "# Foo\n## Bar\n\nblah blah\n\n## Baz\n\nblah blah\n\n# Quux\n\nblah blah\n"
|
|
||||||
|
|
||||||
window.editor = CodeMirror.fromTextArea(te, {
|
|
||||||
mode: "javascript",
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
|
|
||||||
foldGutter: true,
|
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
|
|
||||||
});
|
|
||||||
editor.foldCode(CodeMirror.Pos(13, 0));
|
|
||||||
|
|
||||||
window.editor_html = CodeMirror.fromTextArea(te_html, {
|
|
||||||
mode: "text/html",
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
|
|
||||||
foldGutter: true,
|
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
|
|
||||||
});
|
|
||||||
editor_html.foldCode(CodeMirror.Pos(0, 0));
|
|
||||||
editor_html.foldCode(CodeMirror.Pos(21, 0));
|
|
||||||
|
|
||||||
window.editor_markdown = CodeMirror.fromTextArea(te_markdown, {
|
|
||||||
mode: "markdown",
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
|
|
||||||
foldGutter: true,
|
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
</body>
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Full Screen Editing</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/display/fullscreen.css">
|
|
||||||
<link rel="stylesheet" href="../theme/night.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../addon/display/fullscreen.js"></script>
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Full Screen Editing</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Full Screen Editing</h2>
|
|
||||||
<form><textarea id="code" name="code" rows="5">
|
|
||||||
<dl>
|
|
||||||
<dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
|
|
||||||
<dd>Whether, when indenting, the first N*<code>tabSize</code>
|
|
||||||
spaces should be replaced by N tabs. Default is false.</dd>
|
|
||||||
|
|
||||||
<dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
|
|
||||||
<dd>Configures whether the editor should re-indent the current
|
|
||||||
line when a character is typed that might change its proper
|
|
||||||
indentation (only works if the mode supports indentation).
|
|
||||||
Default is true.</dd>
|
|
||||||
|
|
||||||
<dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
|
|
||||||
<dd>A regular expression used to determine which characters
|
|
||||||
should be replaced by a
|
|
||||||
special <a href="#option_specialCharPlaceholder">placeholder</a>.
|
|
||||||
Mostly useful for non-printing special characters. The default
|
|
||||||
is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
|
|
||||||
<dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
|
|
||||||
<dd>A function that, given a special character identified by
|
|
||||||
the <a href="#option_specialChars"><code>specialChars</code></a>
|
|
||||||
option, produces a DOM node that is used to represent the
|
|
||||||
character. By default, a red dot (<span style="color: red">•</span>)
|
|
||||||
is shown, with a title tooltip to indicate the character code.</dd>
|
|
||||||
|
|
||||||
<dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
|
|
||||||
<dd>Determines whether horizontal cursor movement through
|
|
||||||
right-to-left (Arabic, Hebrew) text is visual (pressing the left
|
|
||||||
arrow moves the cursor left) or logical (pressing the left arrow
|
|
||||||
moves to the next lower index in the string, which is visually
|
|
||||||
right in right-to-left text). The default is <code>false</code>
|
|
||||||
on Windows, and <code>true</code> on other platforms.</dd>
|
|
||||||
</dl>
|
|
||||||
</textarea></form>
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
theme: "night",
|
|
||||||
extraKeys: {
|
|
||||||
"F11": function(cm) {
|
|
||||||
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
|
|
||||||
},
|
|
||||||
"Esc": function(cm) {
|
|
||||||
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of
|
|
||||||
the <a href="../doc/manual.html#addon_fullscreen">fullscreen</a>
|
|
||||||
addon. Press <strong>F11</strong> when cursor is in the editor to
|
|
||||||
toggle full screen editing. <strong>Esc</strong> can also be used
|
|
||||||
to <i>exit</i> full screen editing.</p>
|
|
||||||
</article>
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Hard-wrapping Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/markdown/markdown.js"></script>
|
|
||||||
<script src="../addon/wrap/hardwrap.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Hard-wrapping</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Hard-wrapping Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">Lorem ipsum dolor sit amet, vim augue dictas constituto ex,
|
|
||||||
sit falli simul viderer te. Graeco scaevola maluisset sit
|
|
||||||
ut, in idque viris praesent sea. Ea sea eirmod indoctum
|
|
||||||
repudiare. Vel noluisse suscipit pericula ut. In ius nulla
|
|
||||||
alienum molestie. Mei essent discere democritum id.
|
|
||||||
|
|
||||||
Equidem ponderum expetendis ius in, mea an erroribus
|
|
||||||
constituto, congue timeam perfecto ad est. Ius ut primis
|
|
||||||
timeam, per in ullum mediocrem. An case vero labitur pri,
|
|
||||||
vel dicit laoreet et. An qui prompta conclusionemque, eam
|
|
||||||
timeam sapientem in, cum dictas epicurei eu.
|
|
||||||
|
|
||||||
Usu cu vide dictas deseruisse, eum choro graece adipiscing
|
|
||||||
ut. Cibo qualisque ius ad, et dicat scripta mea, eam nihil
|
|
||||||
mentitum aliquando cu. Debet aperiam splendide at quo, ad
|
|
||||||
paulo nostro commodo duo. Sea adhuc utinam conclusionemque
|
|
||||||
id, quas doming malorum nec ad. Tollit eruditi vivendum ad
|
|
||||||
ius, eos soleat ignota ad.
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>Demonstration of
|
|
||||||
the <a href="../doc/manual.html#addon_hardwrap">hardwrap</a> addon.
|
|
||||||
The above editor has its change event hooked up to
|
|
||||||
the <code>wrapParagraphsInRange</code> method, so that the paragraphs
|
|
||||||
are reflown as you are typing.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "markdown",
|
|
||||||
lineNumbers: true,
|
|
||||||
extraKeys: {
|
|
||||||
"Ctrl-Q": function(cm) { cm.wrapParagraph(cm.getCursor(), options); }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var wait, options = {column: 60};
|
|
||||||
editor.on("change", function(cm, change) {
|
|
||||||
clearTimeout(wait);
|
|
||||||
wait = setTimeout(function() {
|
|
||||||
console.log(cm.wrapParagraphsInRange(change.from, CodeMirror.changeEnd(change), options));
|
|
||||||
}, 200);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>CodeMirror: HTML completion demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/hint/show-hint.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/hint/show-hint.js"></script>
|
|
||||||
<script src="../addon/hint/xml-hint.js"></script>
|
|
||||||
<script src="../addon/hint/html-hint.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/css/css.js"></script>
|
|
||||||
<script src="../mode/htmlmixed/htmlmixed.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">HTML completion</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>HTML completion demo</h2>
|
|
||||||
|
|
||||||
<p>Shows the <a href="xmlcomplete.html">XML completer</a>
|
|
||||||
parameterized with information about the tags in HTML.
|
|
||||||
Press <strong>ctrl-space</strong> to activate completion.</p>
|
|
||||||
|
|
||||||
<div id="code"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
window.onload = function() {
|
|
||||||
editor = CodeMirror(document.getElementById("code"), {
|
|
||||||
mode: "text/html",
|
|
||||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
|
||||||
value: document.documentElement.innerHTML
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
</body>
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Indented wrapped line demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
.CodeMirror pre > * { text-indent: 0px; }
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Indented wrapped line</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Indented wrapped line demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
<!doctype html>
|
|
||||||
<body>
|
|
||||||
<h2 id="overview">Overview</h2>
|
|
||||||
|
|
||||||
<p>CodeMirror is a code-editor component that can be embedded in Web pages. The core library provides <em>only</em> the editor component, no accompanying buttons, auto-completion, or other IDE functionality. It does provide a rich API on top of which such functionality can be straightforwardly implemented. See the <a href="#addons">add-ons</a> included in the distribution, and the <a href="https://github.com/jagthedrummer/codemirror-ui">CodeMirror UI</a> project, for reusable implementations of extra features.</p>
|
|
||||||
|
|
||||||
<p>CodeMirror works with language-specific modes. Modes are JavaScript programs that help color (and optionally indent) text written in a given language. The distribution comes with a number of modes (see the <a href="../mode/"><code>mode/</code></a> directory), and it isn't hard to <a href="#modeapi">write new ones</a> for other languages.</p>
|
|
||||||
</body>
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>This page uses a hack on top of the <code>"renderLine"</code>
|
|
||||||
event to make wrapped text line up with the base indentation of
|
|
||||||
the line.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
mode: "text/html"
|
|
||||||
});
|
|
||||||
var charWidth = editor.defaultCharWidth(), basePadding = 4;
|
|
||||||
editor.on("renderLine", function(cm, line, elt) {
|
|
||||||
var off = CodeMirror.countColumn(line.text, null, cm.getOption("tabSize")) * charWidth;
|
|
||||||
elt.style.textIndent = "-" + off + "px";
|
|
||||||
elt.style.paddingLeft = (basePadding + off) + "px";
|
|
||||||
});
|
|
||||||
editor.refresh();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Linter Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/lint/lint.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/css/css.js"></script>
|
|
||||||
<script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>
|
|
||||||
<script src="https://rawgithub.com/zaach/jsonlint/79b553fb65c192add9066da64043458981b3972b/lib/jsonlint.js"></script>
|
|
||||||
<script src="https://rawgithub.com/stubbornella/csslint/master/release/csslint.js"></script>
|
|
||||||
<script src="../addon/lint/lint.js"></script>
|
|
||||||
<script src="../addon/lint/javascript-lint.js"></script>
|
|
||||||
<script src="../addon/lint/json-lint.js"></script>
|
|
||||||
<script src="../addon/lint/css-lint.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Linter</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Linter Demo</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<p><textarea id="code-js">var widgets = []
|
|
||||||
function updateHints() {
|
|
||||||
editor.operation(function(){
|
|
||||||
for (var i = 0; i < widgets.length; ++i)
|
|
||||||
editor.removeLineWidget(widgets[i]);
|
|
||||||
widgets.length = 0;
|
|
||||||
|
|
||||||
JSHINT(editor.getValue());
|
|
||||||
for (var i = 0; i < JSHINT.errors.length; ++i) {
|
|
||||||
var err = JSHINT.errors[i];
|
|
||||||
if (!err) continue;
|
|
||||||
var msg = document.createElement("div");
|
|
||||||
var icon = msg.appendChild(document.createElement("span"));
|
|
||||||
icon.innerHTML = "!!";
|
|
||||||
icon.className = "lint-error-icon";
|
|
||||||
msg.appendChild(document.createTextNode(err.reason));
|
|
||||||
msg.className = "lint-error";
|
|
||||||
widgets.push(editor.addLineWidget(err.line - 1, msg, {coverGutter: false, noHScroll: true}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var info = editor.getScrollInfo();
|
|
||||||
var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
|
|
||||||
if (info.top + info.clientHeight < after)
|
|
||||||
editor.scrollTo(null, after - info.clientHeight + 3);
|
|
||||||
}
|
|
||||||
</textarea></p>
|
|
||||||
|
|
||||||
<p><textarea id="code-json">[
|
|
||||||
{
|
|
||||||
_id: "post 1",
|
|
||||||
"author": "Bob",
|
|
||||||
"content": "...",
|
|
||||||
"page_views": 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": "post 2",
|
|
||||||
"author": "Bob",
|
|
||||||
"content": "...",
|
|
||||||
"page_views": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"_id": "post 3",
|
|
||||||
"author": "Bob",
|
|
||||||
"content": "...",
|
|
||||||
"page_views": 8
|
|
||||||
}
|
|
||||||
]
|
|
||||||
</textarea></p>
|
|
||||||
|
|
||||||
<p><textarea id="code-css">@charset "UTF-8";
|
|
||||||
|
|
||||||
@import url("booya.css") print, screen;
|
|
||||||
@import "whatup.css" screen;
|
|
||||||
@import "wicked.css";
|
|
||||||
|
|
||||||
/*Error*/
|
|
||||||
@charset "UTF-8";
|
|
||||||
|
|
||||||
|
|
||||||
@namespace "http://www.w3.org/1999/xhtml";
|
|
||||||
@namespace svg "http://www.w3.org/2000/svg";
|
|
||||||
|
|
||||||
/*Warning: empty ruleset */
|
|
||||||
.foo {
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Warning: qualified heading */
|
|
||||||
.foo h1 {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Warning: adjoining classes */
|
|
||||||
.foo.bar {
|
|
||||||
zoom: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
li.inline {
|
|
||||||
width: 100%; /*Warning: 100% can be problematic*/
|
|
||||||
}
|
|
||||||
|
|
||||||
li.last {
|
|
||||||
display: inline;
|
|
||||||
padding-left: 3px !important;
|
|
||||||
padding-right: 3px;
|
|
||||||
border-right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
li.inline {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@page {
|
|
||||||
margin: 10%;
|
|
||||||
counter-increment: page;
|
|
||||||
|
|
||||||
@top-center {
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 2em;
|
|
||||||
content: counter(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</textarea></p>
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code-js"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "javascript",
|
|
||||||
gutters: ["CodeMirror-lint-markers"],
|
|
||||||
lint: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var editor_json = CodeMirror.fromTextArea(document.getElementById("code-json"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "application/json",
|
|
||||||
gutters: ["CodeMirror-lint-markers"],
|
|
||||||
lint: true
|
|
||||||
});
|
|
||||||
|
|
||||||
var editor_css = CodeMirror.fromTextArea(document.getElementById("code-css"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "css",
|
|
||||||
gutters: ["CodeMirror-lint-markers"],
|
|
||||||
lint: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Lazy Mode Loading Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/mode/loadmode.js"></script>
|
|
||||||
<script src="../mode/meta.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Lazy Mode Loading</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Lazy Mode Loading Demo</h2>
|
|
||||||
<p style="color: gray">Current mode: <span id="modeinfo">text/plain</span></p>
|
|
||||||
<form><textarea id="code" name="code">This is the editor.
|
|
||||||
// It starts out in plain text mode,
|
|
||||||
# use the control below to load and apply a mode
|
|
||||||
"you'll see the highlighting of" this text /*change*/.
|
|
||||||
</textarea></form>
|
|
||||||
<p>Filename, mime, or mode name: <input type=text value=foo.js id=mode> <button type=button onclick="change()">change mode</button></p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
CodeMirror.modeURL = "../mode/%N/%N.js";
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
var modeInput = document.getElementById("mode");
|
|
||||||
CodeMirror.on(modeInput, "keypress", function(e) {
|
|
||||||
if (e.keyCode == 13) change();
|
|
||||||
});
|
|
||||||
function change() {
|
|
||||||
var val = modeInput.value, m, mode, spec;
|
|
||||||
if (m = /.+\.([^.]+)$/.exec(val)) {
|
|
||||||
var info = CodeMirror.findModeByExtension(m[1]);
|
|
||||||
if (info) {
|
|
||||||
mode = info.mode;
|
|
||||||
spec = info.mime;
|
|
||||||
}
|
|
||||||
} else if (/\//.test(val)) {
|
|
||||||
var info = CodeMirror.findModeByMIME(val);
|
|
||||||
if (info) {
|
|
||||||
mode = info.mode;
|
|
||||||
spec = val;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mode = spec = val;
|
|
||||||
}
|
|
||||||
if (mode) {
|
|
||||||
editor.setOption("mode", spec);
|
|
||||||
CodeMirror.autoLoadMode(editor, mode);
|
|
||||||
document.getElementById("modeinfo").textContent = spec;
|
|
||||||
} else {
|
|
||||||
alert("Could not find a mode corresponding to " + val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Breakpoint Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.breakpoints {width: .8em;}
|
|
||||||
.breakpoint { color: #822; }
|
|
||||||
.CodeMirror {border: 1px solid #aaa;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Breakpoint</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Breakpoint Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
gutters: ["CodeMirror-linenumbers", "breakpoints"]
|
|
||||||
});
|
|
||||||
editor.on("gutterClick", function(cm, n) {
|
|
||||||
var info = cm.lineInfo(n);
|
|
||||||
cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
|
|
||||||
});
|
|
||||||
|
|
||||||
function makeMarker() {
|
|
||||||
var marker = document.createElement("div");
|
|
||||||
marker.style.color = "#822";
|
|
||||||
marker.innerHTML = "●";
|
|
||||||
return marker;
|
|
||||||
}
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>Click the line-number gutter to add or remove 'breakpoints'.</p>
|
|
||||||
|
|
||||||
<script>eval(document.getElementById("code").value);</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Selection Marking Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/search/searchcursor.js"></script>
|
|
||||||
<script src="../addon/selection/mark-selection.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
.CodeMirror-selected { background-color: blue !important; }
|
|
||||||
.CodeMirror-selectedtext { color: white; }
|
|
||||||
.styled-background { background-color: #ff7; }
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Selection Marking</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Selection Marking Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
Select something from here. You'll see that the selection's foreground
|
|
||||||
color changes to white! Since, by default, CodeMirror only puts an
|
|
||||||
independent "marker" layer behind the text, you'll need something like
|
|
||||||
this to change its colour.
|
|
||||||
|
|
||||||
Also notice that turning this addon on (with the default style) allows
|
|
||||||
you to safely give text a background color without screwing up the
|
|
||||||
visibility of the selection.</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
styleSelectedText: true
|
|
||||||
});
|
|
||||||
editor.markText({line: 6, ch: 26}, {line: 6, ch: 42}, {className: "styled-background"});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Simple addon to easily mark (and style) selected text. <a href="../doc/manual.html#addon_mark-selection">Docs</a>.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Match Highlighter Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/search/searchcursor.js"></script>
|
|
||||||
<script src="../addon/search/match-highlighter.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
.CodeMirror-focused .cm-matchhighlight {
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
|
|
||||||
background-position: bottom;
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Match Highlighter</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Match Highlighter Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">Select this text: hardToSpotVar
|
|
||||||
And everywhere else in your code where hardToSpotVar appears will automatically illuminate.
|
|
||||||
Give it a try! No more hardToSpotVars.</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
highlightSelectionMatches: {showToken: /\w/}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Search and highlight occurences of the selected text.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Tag Matcher Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/fold/xml-fold.js"></script>
|
|
||||||
<script src="../addon/edit/matchtags.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Tag Matcher</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Tag Matcher Demo</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="editor"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
window.onload = function() {
|
|
||||||
editor = CodeMirror(document.getElementById("editor"), {
|
|
||||||
value: "<html>\n " + document.documentElement.innerHTML + "\n</html>",
|
|
||||||
mode: "text/html",
|
|
||||||
matchTags: {bothTags: true},
|
|
||||||
extraKeys: {"Ctrl-J": "toMatchingTag"}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Put the cursor on or inside a pair of tags to highlight them.
|
|
||||||
Press Ctrl-J to jump to the tag that matches the one under the
|
|
||||||
cursor.</p>
|
|
||||||
</article>
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: merge view demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel=stylesheet href="../lib/codemirror.css">
|
|
||||||
<link rel=stylesheet href="../addon/merge/merge.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../mode/css/css.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../mode/htmlmixed/htmlmixed.js"></script>
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"></script>
|
|
||||||
<script src="../addon/merge/merge.js"></script>
|
|
||||||
<style>
|
|
||||||
.CodeMirror { line-height: 1.2; }
|
|
||||||
@media screen and (min-width: 1300px) {
|
|
||||||
article { max-width: 1000px; }
|
|
||||||
#nav { border-right: 499px solid transparent; }
|
|
||||||
}
|
|
||||||
span.clicky {
|
|
||||||
cursor: pointer;
|
|
||||||
background: #d70;
|
|
||||||
color: white;
|
|
||||||
padding: 0 3px;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">merge view</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>merge view demo</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<div id=view></div>
|
|
||||||
|
|
||||||
<p>The <a href="../doc/manual.html#addon_merge"><code>merge</code></a>
|
|
||||||
addon provides an interface for displaying and merging diffs,
|
|
||||||
either <span class=clicky onclick="panes = 2; initUI()">two-way</span>
|
|
||||||
or <span class=clicky onclick="panes = 3; initUI()">three-way</span>.
|
|
||||||
The left (or center) pane is editable, and the differences with the
|
|
||||||
other pane(s) are <span class=clicky
|
|
||||||
onclick="toggleDifferences()">optionally</span> shown live as you edit
|
|
||||||
it. In the two-way configuration, there are also options to pad changed
|
|
||||||
sections to <span class=clicky onclick="connect = connect ? null :
|
|
||||||
'align'; initUI()">align</span> them, and to <span class=clicky
|
|
||||||
onclick="collapse = !collapse; initUI()">collapse</span> unchanged
|
|
||||||
stretches of text.</p>
|
|
||||||
|
|
||||||
<p>This addon depends on
|
|
||||||
the <a href="https://code.google.com/p/google-diff-match-patch/">google-diff-match-patch</a>
|
|
||||||
library to compute the diffs.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var value, orig1, orig2, dv, panes = 2, highlight = true, connect = null, collapse = false;
|
|
||||||
function initUI() {
|
|
||||||
if (value == null) return;
|
|
||||||
var target = document.getElementById("view");
|
|
||||||
target.innerHTML = "";
|
|
||||||
dv = CodeMirror.MergeView(target, {
|
|
||||||
value: value,
|
|
||||||
origLeft: panes == 3 ? orig1 : null,
|
|
||||||
orig: orig2,
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "text/html",
|
|
||||||
highlightDifferences: highlight,
|
|
||||||
connect: connect,
|
|
||||||
collapseIdentical: collapse
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleDifferences() {
|
|
||||||
dv.setShowDifferences(highlight = !highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
value = document.documentElement.innerHTML;
|
|
||||||
orig1 = "<!doctype html>\n\n" + value.replace(/\.\.\//g, "codemirror/").replace("yellow", "orange");
|
|
||||||
orig2 = value.replace(/\u003cscript/g, "\u003cscript type=text/javascript ")
|
|
||||||
.replace("white", "purple;\n font: comic sans;\n text-decoration: underline;\n height: 15em");
|
|
||||||
initUI();
|
|
||||||
};
|
|
||||||
|
|
||||||
function mergeViewHeight(mergeView) {
|
|
||||||
function editorHeight(editor) {
|
|
||||||
if (!editor) return 0;
|
|
||||||
return editor.getScrollInfo().height;
|
|
||||||
}
|
|
||||||
return Math.max(editorHeight(mergeView.leftOriginal()),
|
|
||||||
editorHeight(mergeView.editor()),
|
|
||||||
editorHeight(mergeView.rightOriginal()));
|
|
||||||
}
|
|
||||||
|
|
||||||
function resize(mergeView) {
|
|
||||||
var height = mergeViewHeight(mergeView);
|
|
||||||
for(;;) {
|
|
||||||
if (mergeView.leftOriginal())
|
|
||||||
mergeView.leftOriginal().setSize(null, height);
|
|
||||||
mergeView.editor().setSize(null, height);
|
|
||||||
if (mergeView.rightOriginal())
|
|
||||||
mergeView.rightOriginal().setSize(null, height);
|
|
||||||
|
|
||||||
var newHeight = mergeViewHeight(mergeView);
|
|
||||||
if (newHeight >= height) break;
|
|
||||||
else height = newHeight;
|
|
||||||
}
|
|
||||||
mergeView.wrap.style.height = height + "px";
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Multiplexing Parser Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/mode/multiplex.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid black;}
|
|
||||||
.cm-delimit {color: #fa4;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Multiplexing Parser</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Multiplexing Parser Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
<html>
|
|
||||||
<body style="<<magic>>">
|
|
||||||
<h1><< this is not <html >></h1>
|
|
||||||
<<
|
|
||||||
multiline
|
|
||||||
not html
|
|
||||||
at all : &amp; <link/>
|
|
||||||
>>
|
|
||||||
<p>this is html again</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
CodeMirror.defineMode("demo", function(config) {
|
|
||||||
return CodeMirror.multiplexingMode(
|
|
||||||
CodeMirror.getMode(config, "text/html"),
|
|
||||||
{open: "<<", close: ">>",
|
|
||||||
mode: CodeMirror.getMode(config, "text/plain"),
|
|
||||||
delimStyle: "delimit"}
|
|
||||||
// .. more multiplexed styles can follow here
|
|
||||||
);
|
|
||||||
});
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "demo",
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of a multiplexing mode, which, at certain
|
|
||||||
boundary strings, switches to one or more inner modes. The out
|
|
||||||
(HTML) mode does not get fed the content of the <code><<
|
|
||||||
>></code> blocks. See
|
|
||||||
the <a href="../doc/manual.html#addon_multiplex">manual</a> and
|
|
||||||
the <a href="../addon/mode/multiplex.js">source</a> for more
|
|
||||||
information.</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<strong>Parsing/Highlighting Tests:</strong>
|
|
||||||
<a href="../test/index.html#multiplexing_*">normal</a>,
|
|
||||||
<a href="../test/index.html#verbose,multiplexing_*">verbose</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Overlay Parser Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/mode/overlay.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid black;}
|
|
||||||
.cm-mustache {color: #0ca;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Overlay Parser</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Overlay Parser Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<h1>{{title}}</h1>
|
|
||||||
<p>These are links to {{things}}:</p>
|
|
||||||
<ul>{{#links}}
|
|
||||||
<li><a href="{{url}}">{{text}}</a></li>
|
|
||||||
{{/links}}</ul>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
CodeMirror.defineMode("mustache", function(config, parserConfig) {
|
|
||||||
var mustacheOverlay = {
|
|
||||||
token: function(stream, state) {
|
|
||||||
var ch;
|
|
||||||
if (stream.match("{{")) {
|
|
||||||
while ((ch = stream.next()) != null)
|
|
||||||
if (ch == "}" && stream.next() == "}") {
|
|
||||||
stream.eat("}");
|
|
||||||
return "mustache";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (stream.next() != null && !stream.match("{{", false)) {}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), mustacheOverlay);
|
|
||||||
});
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: "mustache"});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of a mode that parses HTML, highlighting
|
|
||||||
the <a href="http://mustache.github.com/">Mustache</a> templating
|
|
||||||
directives inside of it by using the code
|
|
||||||
in <a href="../addon/mode/overlay.js"><code>overlay.js</code></a>. View
|
|
||||||
source to see the 15 lines of code needed to accomplish this.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Panel Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../addon/display/panel.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.border {border: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
.add { background: orange; padding: 1px 3px; color: white !important; border-radius: 4px; }
|
|
||||||
.panel {
|
|
||||||
background-image: linear-gradient(to bottom, #ffffaa, #ffffdd);
|
|
||||||
padding: 3px 7px;
|
|
||||||
}
|
|
||||||
.panel.top { border-bottom: 1px solid #dd6; }
|
|
||||||
.panel.bottom { border-top: 1px solid #dd6; }
|
|
||||||
.panel span { cursor: pointer; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Panel</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Panel Demo</h2>
|
|
||||||
<form><div class="border"><textarea id="code" name="code"></textarea></div></form>
|
|
||||||
|
|
||||||
<script id="localscript">var textarea = document.getElementById("code");
|
|
||||||
var script = document.getElementById("localscript");
|
|
||||||
textarea.value = (script.textContent ||
|
|
||||||
script.innerText ||
|
|
||||||
script.innerHTML);
|
|
||||||
editor = CodeMirror.fromTextArea(textarea, {
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
|
|
||||||
function addPanel(where) {
|
|
||||||
var node = document.createElement("div");
|
|
||||||
node.className = "panel " + where;
|
|
||||||
var close = node.appendChild(document.createElement("span"));
|
|
||||||
close.textContent = "✖ Remove this panel";
|
|
||||||
var widget = editor.addPanel(node, {position: where});
|
|
||||||
CodeMirror.on(close, "click", function() { widget.clear(); });
|
|
||||||
}</script>
|
|
||||||
|
|
||||||
<p>The <a href="../doc/manual.html#addon_panel"><code>panel</code></a>
|
|
||||||
addon allows you to display panels <a class=add
|
|
||||||
href="javascript:addPanel('top')">above</a> or <a class=add
|
|
||||||
href="javascript:addPanel('bottom')">below</a> an editor. Click the
|
|
||||||
links in the previous paragraph to add panels to the editor.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Placeholder demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/display/placeholder.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror { border: 1px solid silver; }
|
|
||||||
.CodeMirror-empty { outline: 1px solid #c22; }
|
|
||||||
.CodeMirror-empty.CodeMirror-focused { outline: none; }
|
|
||||||
.CodeMirror pre.CodeMirror-placeholder { color: #999; }
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Placeholder</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Placeholder demo</h2>
|
|
||||||
<form><textarea id="code" name="code" placeholder="Code goes here..."></textarea></form>
|
|
||||||
|
|
||||||
<p>The <a href="../doc/manual.html#addon_placeholder">placeholder</a>
|
|
||||||
plug-in adds an option <code>placeholder</code> that can be set to
|
|
||||||
make text appear in the editor when it is empty and not focused.
|
|
||||||
If the source textarea has a <code>placeholder</code> attribute,
|
|
||||||
it will automatically be inherited.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: HTML5 preview</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel=stylesheet href=../lib/codemirror.css>
|
|
||||||
<script src=../lib/codemirror.js></script>
|
|
||||||
<script src=../mode/xml/xml.js></script>
|
|
||||||
<script src=../mode/javascript/javascript.js></script>
|
|
||||||
<script src=../mode/css/css.js></script>
|
|
||||||
<script src=../mode/htmlmixed/htmlmixed.js></script>
|
|
||||||
<style type=text/css>
|
|
||||||
.CodeMirror {
|
|
||||||
float: left;
|
|
||||||
width: 50%;
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
iframe {
|
|
||||||
width: 49%;
|
|
||||||
float: left;
|
|
||||||
height: 300px;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-left: 0px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">HTML5 preview</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>HTML5 preview</h2>
|
|
||||||
|
|
||||||
<textarea id=code name=code>
|
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset=utf-8>
|
|
||||||
<title>HTML5 canvas demo</title>
|
|
||||||
<style>p {font-family: monospace;}</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>Canvas pane goes here:</p>
|
|
||||||
<canvas id=pane width=300 height=200></canvas>
|
|
||||||
<script>
|
|
||||||
var canvas = document.getElementById('pane');
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
|
|
||||||
context.fillStyle = 'rgb(250,0,0)';
|
|
||||||
context.fillRect(10, 10, 55, 50);
|
|
||||||
|
|
||||||
context.fillStyle = 'rgba(0, 0, 250, 0.5)';
|
|
||||||
context.fillRect(30, 30, 55, 50);
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html></textarea>
|
|
||||||
<iframe id=preview></iframe>
|
|
||||||
<script>
|
|
||||||
var delay;
|
|
||||||
// Initialize CodeMirror editor with a nice html5 canvas demo.
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
|
|
||||||
mode: 'text/html'
|
|
||||||
});
|
|
||||||
editor.on("change", function() {
|
|
||||||
clearTimeout(delay);
|
|
||||||
delay = setTimeout(updatePreview, 300);
|
|
||||||
});
|
|
||||||
|
|
||||||
function updatePreview() {
|
|
||||||
var previewFrame = document.getElementById('preview');
|
|
||||||
var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
|
|
||||||
preview.open();
|
|
||||||
preview.write(editor.getValue());
|
|
||||||
preview.close();
|
|
||||||
}
|
|
||||||
setTimeout(updatePreview, 300);
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>CodeMirror: HTML completion demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/hint/show-hint.css">
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.min.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">HTML completion</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>RequireJS module loading demo</h2>
|
|
||||||
|
|
||||||
<p>This demo does the same thing as
|
|
||||||
the <a href="html5complete.html">HTML5 completion demo</a>, but
|
|
||||||
loads its dependencies
|
|
||||||
with <a href="http://requirejs.org/">Require.js</a>, rather than
|
|
||||||
explicitly. Press <strong>ctrl-space</strong> to activate
|
|
||||||
completion.</p>
|
|
||||||
|
|
||||||
<div id="code"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
require(["../lib/codemirror", "../mode/htmlmixed/htmlmixed",
|
|
||||||
"../addon/hint/show-hint", "../addon/hint/html-hint"], function(CodeMirror) {
|
|
||||||
editor = CodeMirror(document.getElementById("code"), {
|
|
||||||
mode: "text/html",
|
|
||||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
|
||||||
value: document.documentElement.innerHTML
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
</body>
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Autoresize Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/css/css.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Autoresize</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Autoresize Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
.CodeMirror {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>By setting an editor's <code>height</code> style
|
|
||||||
to <code>auto</code> and giving
|
|
||||||
the <a href="../doc/manual.html#option_viewportMargin"><code>viewportMargin</code></a>
|
|
||||||
a value of <code>Infinity</code>, CodeMirror can be made to
|
|
||||||
automatically resize to fit its content.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
viewportMargin: Infinity
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Ruler Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/display/rulers.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Ruler demo</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Ruler Demo</h2>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var nums = "0123456789", space = " ";
|
|
||||||
var colors = ["#fcc", "#f5f577", "#cfc", "#aff", "#ccf", "#fcf"];
|
|
||||||
var rulers = [], value = "";
|
|
||||||
for (var i = 1; i <= 6; i++) {
|
|
||||||
rulers.push({color: colors[i], column: i * 10, lineStyle: "dashed"});
|
|
||||||
for (var j = 1; j < i; j++) value += space;
|
|
||||||
value += nums + "\n";
|
|
||||||
}
|
|
||||||
var editor = CodeMirror(document.body.lastChild, {
|
|
||||||
rulers: rulers,
|
|
||||||
value: value + value + value,
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of
|
|
||||||
the <a href="../doc/manual.html#addon_rulers">rulers</a> addon, which
|
|
||||||
displays vertical lines at given column offsets.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Mode Runner Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/runmode/runmode.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Mode Runner</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Mode Runner Demo</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<textarea id="code" style="width: 90%; height: 7em; border: 1px solid black; padding: .2em .4em;">
|
|
||||||
<foobar>
|
|
||||||
<blah>Enter your xml here and press the button below to display
|
|
||||||
it as highlighted by the CodeMirror XML mode</blah>
|
|
||||||
<tag2 foo="2" bar="&quot;bar&quot;"/>
|
|
||||||
</foobar></textarea><br>
|
|
||||||
<button onclick="doHighlight();">Highlight!</button>
|
|
||||||
<pre id="output" class="cm-s-default"></pre>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function doHighlight() {
|
|
||||||
CodeMirror.runMode(document.getElementById("code").value, "application/xml",
|
|
||||||
document.getElementById("output"));
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Running a CodeMirror mode outside of the editor.
|
|
||||||
The <code>CodeMirror.runMode</code> function, defined
|
|
||||||
in <code><a href="../addon/runmode/runmode.js">lib/runmode.js</a></code> takes the following arguments:</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><code>text (string)</code></dt>
|
|
||||||
<dd>The document to run through the highlighter.</dd>
|
|
||||||
<dt><code>mode (<a href="../doc/manual.html#option_mode">mode spec</a>)</code></dt>
|
|
||||||
<dd>The mode to use (must be loaded as normal).</dd>
|
|
||||||
<dt><code>output (function or DOM node)</code></dt>
|
|
||||||
<dd>If this is a function, it will be called for each token with
|
|
||||||
two arguments, the token's text and the token's style class (may
|
|
||||||
be <code>null</code> for unstyled tokens). If it is a DOM node,
|
|
||||||
the tokens will be converted to <code>span</code> elements as in
|
|
||||||
an editor, and inserted into the node
|
|
||||||
(through <code>innerHTML</code>).</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Search/Replace Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/dialog/dialog.css">
|
|
||||||
<link rel="stylesheet" href="../addon/search/matchesonscrollbar.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../addon/dialog/dialog.js"></script>
|
|
||||||
<script src="../addon/search/searchcursor.js"></script>
|
|
||||||
<script src="../addon/search/search.js"></script>
|
|
||||||
<script src="../addon/scroll/annotatescrollbar.js"></script>
|
|
||||||
<script src="../addon/search/matchesonscrollbar.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
dt {font-family: monospace; color: #666;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Search/Replace</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Search/Replace Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
<dl>
|
|
||||||
<dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
|
|
||||||
<dd>Whether, when indenting, the first N*<code>tabSize</code>
|
|
||||||
spaces should be replaced by N tabs. Default is false.</dd>
|
|
||||||
|
|
||||||
<dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
|
|
||||||
<dd>Configures whether the editor should re-indent the current
|
|
||||||
line when a character is typed that might change its proper
|
|
||||||
indentation (only works if the mode supports indentation).
|
|
||||||
Default is true.</dd>
|
|
||||||
|
|
||||||
<dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
|
|
||||||
<dd>A regular expression used to determine which characters
|
|
||||||
should be replaced by a
|
|
||||||
special <a href="#option_specialCharPlaceholder">placeholder</a>.
|
|
||||||
Mostly useful for non-printing special characters. The default
|
|
||||||
is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
|
|
||||||
<dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
|
|
||||||
<dd>A function that, given a special character identified by
|
|
||||||
the <a href="#option_specialChars"><code>specialChars</code></a>
|
|
||||||
option, produces a DOM node that is used to represent the
|
|
||||||
character. By default, a red dot (<span style="color: red">•</span>)
|
|
||||||
is shown, with a title tooltip to indicate the character code.</dd>
|
|
||||||
|
|
||||||
<dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
|
|
||||||
<dd>Determines whether horizontal cursor movement through
|
|
||||||
right-to-left (Arabic, Hebrew) text is visual (pressing the left
|
|
||||||
arrow moves the cursor left) or logical (pressing the left arrow
|
|
||||||
moves to the next lower index in the string, which is visually
|
|
||||||
right in right-to-left text). The default is <code>false</code>
|
|
||||||
on Windows, and <code>true</code> on other platforms.</dd>
|
|
||||||
</dl>
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "text/html",
|
|
||||||
lineNumbers: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Demonstration of primitive search/replace functionality. The
|
|
||||||
keybindings (which can be overridden by custom keymaps) are:</p>
|
|
||||||
<dl>
|
|
||||||
<dt>Ctrl-F / Cmd-F</dt><dd>Start searching</dd>
|
|
||||||
<dt>Ctrl-G / Cmd-G</dt><dd>Find next</dd>
|
|
||||||
<dt>Shift-Ctrl-G / Shift-Cmd-G</dt><dd>Find previous</dd>
|
|
||||||
<dt>Shift-Ctrl-F / Cmd-Option-F</dt><dd>Replace</dd>
|
|
||||||
<dt>Shift-Ctrl-R / Shift-Cmd-Option-F</dt><dd>Replace all</dd>
|
|
||||||
</dl>
|
|
||||||
<p>Searching is enabled by
|
|
||||||
including <a href="../addon/search/search.js">addon/search/search.js</a>
|
|
||||||
and <a href="../addon/search/searchcursor.js">addon/search/searchcursor.js</a>.
|
|
||||||
For good-looking input dialogs, you also want to include
|
|
||||||
<a href="../addon/dialog/dialog.js">addon/dialog/dialog.js</a>
|
|
||||||
and <a href="../addon/dialog/dialog.css">addon/dialog/dialog.css</a>.</p>
|
|
||||||
</article>
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Simple Mode Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/mode/simple.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid silver; margin-bottom: 1em; }
|
|
||||||
dt { text-indent: -2em; padding-left: 2em; margin-top: 1em; }
|
|
||||||
dd { margin-left: 1.5em; margin-bottom: 1em; }
|
|
||||||
dt {margin-top: 1em;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Simple Mode</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Simple Mode Demo</h2>
|
|
||||||
|
|
||||||
<p>The <a href="../addon/mode/simple.js"><code>mode/simple</code></a>
|
|
||||||
addon allows CodeMirror modes to be specified using a relatively simple
|
|
||||||
declarative format. This format is not as powerful as writing code
|
|
||||||
directly against the <a href="../doc/manual.html#modeapi">mode
|
|
||||||
interface</a>, but is a lot easier to get started with, and
|
|
||||||
sufficiently expressive for many simple language modes.</p>
|
|
||||||
|
|
||||||
<p>This interface is still in flux. It is unlikely to be scrapped or
|
|
||||||
overhauled completely, so do start writing code against it, but
|
|
||||||
details might change as it stabilizes, and you might have to tweak
|
|
||||||
your code when upgrading.</p>
|
|
||||||
|
|
||||||
<p>Simple modes (loosely based on
|
|
||||||
the <a href="https://github.com/mozilla/skywriter/wiki/Common-JavaScript-Syntax-Highlighting-Specification">Common
|
|
||||||
JavaScript Syntax Highlighting Specification</a>, which never took
|
|
||||||
off), are state machines, where each state has a number of rules that
|
|
||||||
match tokens. A rule describes a type of token that may occur in the
|
|
||||||
current state, and possibly a transition to another state caused by
|
|
||||||
that token.</p>
|
|
||||||
|
|
||||||
<p>The <code>CodeMirror.defineSimpleMode(name, states)</code> method
|
|
||||||
takes a mode name and an object that describes the mode's states. The
|
|
||||||
editor below shows an example of such a mode (and is itself
|
|
||||||
highlighted by the mode shown in it).</p>
|
|
||||||
|
|
||||||
<div id="code"></div>
|
|
||||||
|
|
||||||
<p>Each state is an array of rules. A rule may have the following properties:</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><code><strong>regex</strong>: string | RegExp</code></dt>
|
|
||||||
<dd>The regular expression that matches the token. May be a string
|
|
||||||
or a regex object. When a regex, the <code>ignoreCase</code> flag
|
|
||||||
will be taken into account when matching the token. This regex
|
|
||||||
should only capture groups when the <code>token</code> property is
|
|
||||||
an array.</dd>
|
|
||||||
<dt><code><strong>token</strong></code>: string | null</dt>
|
|
||||||
<dd>An optional token style. Multiple styles can be specified by
|
|
||||||
separating them with dots or spaces. When the <code>regex</code> for
|
|
||||||
this rule captures groups, it must capture <em>all</em> of the
|
|
||||||
string (since JS provides no way to find out where a group matched),
|
|
||||||
and this property must hold an array of token styles that has one
|
|
||||||
style for each matched group.</dd>
|
|
||||||
<dt><code><strong>sol</strong></code>: boolean</dt>
|
|
||||||
<dd>When true, this token will only match at the start of the line.
|
|
||||||
(The <code>^</code> regexp marker doesn't work as you'd expect in
|
|
||||||
this context because of limitations in JavaScript's RegExp
|
|
||||||
API.)</dd>
|
|
||||||
<dt><code><strong>next</strong>: string</code></dt>
|
|
||||||
<dd>When a <code>next</code> property is present, the mode will
|
|
||||||
transfer to the state named by the property when the token is
|
|
||||||
encountered.</dd>
|
|
||||||
<dt><code><strong>push</strong>: string</code></dt>
|
|
||||||
<dd>Like <code>next</code>, but instead replacing the current state
|
|
||||||
by the new state, the current state is kept on a stack, and can be
|
|
||||||
returned to with the <code>pop</code> directive.</dd>
|
|
||||||
<dt><code><strong>pop</strong>: bool</code></dt>
|
|
||||||
<dd>When true, and there is another state on the state stack, will
|
|
||||||
cause the mode to pop that state off the stack and transition to
|
|
||||||
it.</dd>
|
|
||||||
<dt><code><strong>mode</strong>: {spec, end, persistent}</code></dt>
|
|
||||||
<dd>Can be used to embed another mode inside a mode. When present,
|
|
||||||
must hold an object with a <code>spec</code> property that describes
|
|
||||||
the embedded mode, and an optional <code>end</code> end property
|
|
||||||
that specifies the regexp that will end the extent of the mode. When
|
|
||||||
a <code>persistent</code> property is set (and true), the nested
|
|
||||||
mode's state will be preserved between occurrences of the mode.</dd>
|
|
||||||
<dt><code><strong>indent</strong>: bool</code></dt>
|
|
||||||
<dd>When true, this token changes the indentation to be one unit
|
|
||||||
more than the current line's indentation.</dd>
|
|
||||||
<dt><code><strong>dedent</strong>: bool</code></dt>
|
|
||||||
<dd>When true, this token will pop one scope off the indentation
|
|
||||||
stack.</dd>
|
|
||||||
<dt><code><strong>dedentIfLineStart</strong>: bool</code></dt>
|
|
||||||
<dd>If a token has its <code>dedent</code> property set, it will, by
|
|
||||||
default, cause lines where it appears at the start to be dedented.
|
|
||||||
Set this property to false to prevent that behavior.</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<p>The <code>meta</code> property of the states object is special, and
|
|
||||||
will not be interpreted as a state. Instead, properties set on it will
|
|
||||||
be set on the mode, which is useful for properties
|
|
||||||
like <a href="../doc/manual.html#addon_comment"><code>lineComment</code></a>,
|
|
||||||
which sets the comment style for a mode. The simple mode addon also
|
|
||||||
recognizes a few such properties:</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><code><strong>dontIndentStates</strong>: array<string></code></dt>
|
|
||||||
<dd>An array of states in which the mode's auto-indentation should
|
|
||||||
not take effect. Usually used for multi-line comment and string
|
|
||||||
states.</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<script id="modecode">/* Example definition of a simple mode that understands a subset of
|
|
||||||
* JavaScript:
|
|
||||||
*/
|
|
||||||
|
|
||||||
CodeMirror.defineSimpleMode("simplemode", {
|
|
||||||
// The start state contains the rules that are intially used
|
|
||||||
start: [
|
|
||||||
// The regex matches the token, the token property contains the type
|
|
||||||
{regex: /"(?:[^\\]|\\.)*?"/, token: "string"},
|
|
||||||
// You can match multiple tokens at once. Note that the captured
|
|
||||||
// groups must span the whole string in this case
|
|
||||||
{regex: /(function)(\s+)([a-z$][\w$]*)/,
|
|
||||||
token: ["keyword", null, "variable-2"]},
|
|
||||||
// Rules are matched in the order in which they appear, so there is
|
|
||||||
// no ambiguity between this one and the one above
|
|
||||||
{regex: /(?:function|var|return|if|for|while|else|do|this)\b/,
|
|
||||||
token: "keyword"},
|
|
||||||
{regex: /true|false|null|undefined/, token: "atom"},
|
|
||||||
{regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
|
|
||||||
token: "number"},
|
|
||||||
{regex: /\/\/.*/, token: "comment"},
|
|
||||||
{regex: /\/(?:[^\\]|\\.)*?\//, token: "variable-3"},
|
|
||||||
// A next property will cause the mode to move to a different state
|
|
||||||
{regex: /\/\*/, token: "comment", next: "comment"},
|
|
||||||
{regex: /[-+\/*=<>!]+/, token: "operator"},
|
|
||||||
// indent and dedent properties guide autoindentation
|
|
||||||
{regex: /[\{\[\(]/, indent: true},
|
|
||||||
{regex: /[\}\]\)]/, dedent: true},
|
|
||||||
{regex: /[a-z$][\w$]*/, token: "variable"},
|
|
||||||
// You can embed other modes with the mode property. This rule
|
|
||||||
// causes all code between << and >> to be highlighted with the XML
|
|
||||||
// mode.
|
|
||||||
{regex: /<</, token: "meta", mode: {spec: "xml", end: />>/}}
|
|
||||||
],
|
|
||||||
// The multi-line comment state.
|
|
||||||
comment: [
|
|
||||||
{regex: /.*?\*\//, token: "comment", next: "start"},
|
|
||||||
{regex: /.*/, token: "comment"}
|
|
||||||
],
|
|
||||||
// The meta property contains global information about the mode. It
|
|
||||||
// can contain properties like lineComment, which are supported by
|
|
||||||
// all modes, and also directives like dontIndentStates, which are
|
|
||||||
// specific to simple modes.
|
|
||||||
meta: {
|
|
||||||
dontIndentStates: ["comment"],
|
|
||||||
lineComment: "//"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var sc = document.getElementById("modecode");
|
|
||||||
var code = document.getElementById("code");
|
|
||||||
var editor = CodeMirror(code, {
|
|
||||||
value: (sc.textContent || sc.innerText || sc.innerHTML),
|
|
||||||
mode: "simplemode"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Simple Scrollbar Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/scroll/simplescrollbars.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/markdown/markdown.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<script src="../addon/scroll/simplescrollbars.js"></script>
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Simple Scrollbar</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Simple Scrollbar Demo</h2>
|
|
||||||
<form><textarea id="code" name="code"># Custom Scrollbars
|
|
||||||
|
|
||||||
This is a piece of text that creates scrollbars
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, turpis nec facilisis neque vestibulum adipiscing, magna nunc est luctus orci a,
|
|
||||||
aliquam duis ad volutpat nostra. Vestibulum ultricies suspendisse commodo volutpat pede sed. Bibendum odio
|
|
||||||
dignissim, ad vitae mollis ac sed nibh quis, suspendisse diam, risus quas blandit phasellus luctus nec,
|
|
||||||
integer nunc vitae posuere scelerisque. Lobortis quam porta conubia nulla. Et nisl ac, imperdiet vitae ac.
|
|
||||||
Parturient sit. Et vestibulum euismod, rutrum nunc libero mauris purus convallis. Cum id adipiscing et eget
|
|
||||||
pretium rutrum, ultrices sapien magnis fringilla sit lorem, eu vitae scelerisque ipsum aliquet, magna sed
|
|
||||||
fusce vel.
|
|
||||||
|
|
||||||
Lectus ultricies libero dolor convallis, sed etiam vel hendrerit egestas viverra, at urna mauris, eget
|
|
||||||
vulputate dolor voluptatem, nulla eget sollicitudin. Sed tincidunt, elit sociis. Mattis mi tortor dui id
|
|
||||||
sodales mi, maecenas nam fringilla risus turpis mauris praesent, imperdiet maecenas ultrices nonummy tellus
|
|
||||||
quis est. Scelerisque nec pharetra quis varius fringilla. Varius vestibulum non dictum pharetra, tincidunt in
|
|
||||||
vestibulum iaculis molestie, id condimentum blandit elit urna magna pulvinar, quam suspendisse pellentesque
|
|
||||||
donec. Vel amet ad ac. Nec aut viverra, morbi mi neque massa, turpis enim proin. Tellus eu, fermentum velit
|
|
||||||
est convallis aliquam velit, rutrum in diam lacus, praesent tempor pellentesque dictum semper augue. Felis
|
|
||||||
explicabo massa amet lectus phasellus dolor. Ut lorem quis arcu neque felis ultricies, senectus vitae
|
|
||||||
curabitur sed pellentesque et, id sed risus in sed ac accumsan, blandit arcu quam duis nunc.
|
|
||||||
|
|
||||||
Sed leo sollicitudin odio vitae, purus sit egestas, justo eros inceptos auctor fermentum lectus. Ligula luctus
|
|
||||||
turpis, quod massa vitae elementum orci, nullam fringilla elit tortor. Justo ante tempor amet quam posuere
|
|
||||||
volutpat. Facilisis pede erat ut hac ultrices ipsum, wisi duis sit metus. Dolor vitae est sed sed vitae. Sed
|
|
||||||
eu ligula, morbi vestibulum nunc nibh velit ut taciti, ligula elit semper sagittis in, auctor arcu vel eget.
|
|
||||||
Mauris at vitae nec suspendisse et, aenean proin blandit suscipit. Morbi quam, dolor ultricies. Viverra
|
|
||||||
tempus. Suspendisse sit dapibus, ac fuga aenean, magna nisl nonummy augue posuere, dictum ut fuga velit
|
|
||||||
parturient augue interdum, mattis sit tellus.
|
|
||||||
|
|
||||||
Vehicula commodo tempus curabitur eros, lacinia erat vulputate lorem vel fermentum donec, lectus sed conubia
|
|
||||||
id pellentesque. Vel senectus donec pede aliquet dolor sit, nec vivamus justo placerat interdum maecenas,
|
|
||||||
sodales euismod. Quis netus sapien amet, vestibulum quam nec amet lacinia, quis aliquet, tempor vivamus tellus
|
|
||||||
enim, suscipit quis eleifend. Amet class phasellus orci pretium, risus in nulla. Neque sit ullamcorper,
|
|
||||||
ultricies platea id nec suspendisse ac. Et elementum. Dictum nam, ut dui fermentum egestas facilisis elit
|
|
||||||
augue, adipiscing donec ipsum erat nam pellentesque convallis, vestibulum vestibulum risus id nulla ut mauris,
|
|
||||||
curabitur aute aptent. Ultrices orci wisi dui ipsum praesent, pharetra felis eu quis. Est fringilla etiam,
|
|
||||||
maxime sem dapibus et eget, mi enim dignissim nec pretium, augue vehicula, volutpat proin. Et occaecati
|
|
||||||
lobortis viverra, cum in sed, vivamus tellus. Libero at malesuada est vivamus leo tortor.
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>The <a href="../doc/manual.html#addon_simplescrollbars"><code>simplescrollbars</code></a> addon defines two
|
|
||||||
styles of non-native scrollbars: <a href="javascript:editor.setOption('scrollbarStyle', 'simple')"><code>"simple"</code></a> and <a href="javascript:editor.setOption('scrollbarStyle', 'overlay')"><code>"overlay"</code></a> (click to try), which can be passed to
|
|
||||||
the <a href="../doc/manual.html#option_scrollbarStyle"><code>scrollbarStyle</code></a> option. These implement
|
|
||||||
the scrollbar using DOM elements, allowing more control over
|
|
||||||
its <a href="../addon/scroll/simplescrollbars.css">appearance</a>.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
scrollbarStyle: "simple"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Automatically derive odd wrapping behavior for your browser</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Automatically derive odd wrapping behavior for your browser</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Automatically derive odd wrapping behavior for your browser</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<p>This is a hack to automatically derive
|
|
||||||
a <code>spanAffectsWrapping</code> regexp for a browser. See the
|
|
||||||
comments above that variable
|
|
||||||
in <a href="../lib/codemirror.js"><code>lib/codemirror.js</code></a>
|
|
||||||
for some more details.</p>
|
|
||||||
|
|
||||||
<div style="white-space: pre-wrap; width: 50px;" id="area"></div>
|
|
||||||
<pre id="output"></pre>
|
|
||||||
|
|
||||||
<script id="script">
|
|
||||||
var a = document.getElementById("area"), bad = Object.create(null);
|
|
||||||
var chars = "a~`!@#$%^&*()-_=+}{[]\\|'\"/?.>,<:;", l = chars.length;
|
|
||||||
for (var x = 0; x < l; ++x) for (var y = 0; y < l; ++y) {
|
|
||||||
var s1 = "foooo" + chars.charAt(x), s2 = chars.charAt(y) + "br";
|
|
||||||
a.appendChild(document.createTextNode(s1 + s2));
|
|
||||||
var h1 = a.offsetHeight;
|
|
||||||
a.innerHTML = "";
|
|
||||||
a.appendChild(document.createElement("span")).appendChild(document.createTextNode(s1));
|
|
||||||
a.appendChild(document.createElement("span")).appendChild(document.createTextNode(s2));
|
|
||||||
if (a.offsetHeight != h1)
|
|
||||||
bad[chars.charAt(x)] = (bad[chars.charAt(x)] || "") + chars.charAt(y);
|
|
||||||
a.innerHTML = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
var re = "";
|
|
||||||
function toREElt(str) {
|
|
||||||
if (str.length > 1) {
|
|
||||||
var invert = false;
|
|
||||||
if (str.length > chars.length * .6) {
|
|
||||||
invert = true;
|
|
||||||
var newStr = "";
|
|
||||||
for (var i = 0; i < l; ++i) if (str.indexOf(chars.charAt(i)) == -1) newStr += chars.charAt(i);
|
|
||||||
str = newStr;
|
|
||||||
}
|
|
||||||
str = str.replace(/[\-\.\]\"\'\\\/\^a]/g, function(orig) { return orig == "a" ? "\\w" : "\\" + orig; });
|
|
||||||
return "[" + (invert ? "^" : "") + str + "]";
|
|
||||||
} else if (str == "a") {
|
|
||||||
return "\\w";
|
|
||||||
} else if (/[?$*()+{}[\]\.|/\'\"]/.test(str)) {
|
|
||||||
return "\\" + str;
|
|
||||||
} else {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var newRE = "";
|
|
||||||
for (;;) {
|
|
||||||
var left = null;
|
|
||||||
for (var left in bad) break;
|
|
||||||
if (left == null) break;
|
|
||||||
var right = bad[left];
|
|
||||||
delete bad[left];
|
|
||||||
for (var other in bad) if (bad[other] == right) {
|
|
||||||
left += other;
|
|
||||||
delete bad[other];
|
|
||||||
}
|
|
||||||
newRE += (newRE ? "|" : "") + toREElt(left) + toREElt(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("output").appendChild(document.createTextNode("Your regexp is: " + (newRE || "^$")));
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Sublime Text bindings demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/fold/foldgutter.css">
|
|
||||||
<link rel="stylesheet" href="../addon/dialog/dialog.css">
|
|
||||||
<link rel="stylesheet" href="../theme/monokai.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/search/searchcursor.js"></script>
|
|
||||||
<script src="../addon/search/search.js"></script>
|
|
||||||
<script src="../addon/dialog/dialog.js"></script>
|
|
||||||
<script src="../addon/edit/matchbrackets.js"></script>
|
|
||||||
<script src="../addon/edit/closebrackets.js"></script>
|
|
||||||
<script src="../addon/comment/comment.js"></script>
|
|
||||||
<script src="../addon/wrap/hardwrap.js"></script>
|
|
||||||
<script src="../addon/fold/foldcode.js"></script>
|
|
||||||
<script src="../addon/fold/brace-fold.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../keymap/sublime.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee; line-height: 1.3; height: 500px}
|
|
||||||
.CodeMirror-linenumbers { padding: 0 8px; }
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Sublime bindings</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Sublime Text bindings demo</h2>
|
|
||||||
|
|
||||||
<p>The <code>sublime</code> keymap defines many Sublime Text-specific
|
|
||||||
bindings for CodeMirror. See the code below for an overview.</p>
|
|
||||||
|
|
||||||
<p>Enable the keymap by
|
|
||||||
loading <a href="../keymap/sublime.js"><code>keymap/sublime.js</code></a>
|
|
||||||
and setting
|
|
||||||
the <a href="../doc/manual.html#option_keyMap"><code>keyMap</code></a>
|
|
||||||
option to <code>"sublime"</code>.</p>
|
|
||||||
|
|
||||||
<p>(A lot of the search functionality is still missing.)
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var value = "// The bindings defined specifically in the Sublime Text mode\nvar bindings = {\n";
|
|
||||||
var map = CodeMirror.keyMap.sublime;
|
|
||||||
for (var key in map) {
|
|
||||||
var val = map[key];
|
|
||||||
if (key != "fallthrough" && val != "..." && (!/find/.test(val) || /findUnder/.test(val)))
|
|
||||||
value += " \"" + key + "\": \"" + val + "\",\n";
|
|
||||||
}
|
|
||||||
value += "}\n\n// The implementation of joinLines\n";
|
|
||||||
value += CodeMirror.commands.joinLines.toString().replace(/^function\s*\(/, "function joinLines(").replace(/\n /g, "\n") + "\n";
|
|
||||||
var editor = CodeMirror(document.body.getElementsByTagName("article")[0], {
|
|
||||||
value: value,
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "javascript",
|
|
||||||
keyMap: "sublime",
|
|
||||||
autoCloseBrackets: true,
|
|
||||||
matchBrackets: true,
|
|
||||||
showCursorWhenSelecting: true,
|
|
||||||
theme: "monokai"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Tern Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/dialog/dialog.css">
|
|
||||||
<link rel="stylesheet" href="../addon/hint/show-hint.css">
|
|
||||||
<link rel="stylesheet" href="../addon/tern/tern.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../addon/dialog/dialog.js"></script>
|
|
||||||
<script src="../addon/hint/show-hint.js"></script>
|
|
||||||
<script src="../addon/tern/tern.js"></script>
|
|
||||||
<script src="http://marijnhaverbeke.nl/acorn/acorn.js"></script>
|
|
||||||
<script src="http://marijnhaverbeke.nl/acorn/acorn_loose.js"></script>
|
|
||||||
<script src="http://marijnhaverbeke.nl/acorn/util/walk.js"></script>
|
|
||||||
<script src="http://ternjs.net/doc/demo/polyfill.js"></script>
|
|
||||||
<script src="http://ternjs.net/lib/signal.js"></script>
|
|
||||||
<script src="http://ternjs.net/lib/tern.js"></script>
|
|
||||||
<script src="http://ternjs.net/lib/def.js"></script>
|
|
||||||
<script src="http://ternjs.net/lib/comment.js"></script>
|
|
||||||
<script src="http://ternjs.net/lib/infer.js"></script>
|
|
||||||
<script src="http://ternjs.net/plugin/doc_comment.js"></script>
|
|
||||||
<style>
|
|
||||||
.CodeMirror {border: 1px solid #ddd;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Tern</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Tern Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">// Use ctrl-space to complete something
|
|
||||||
// Put the cursor in or after an expression, press ctrl-o to
|
|
||||||
// find its type
|
|
||||||
|
|
||||||
var foo = ["array", "of", "strings"];
|
|
||||||
var bar = foo.slice(0, 2).join("").split("a")[0];
|
|
||||||
|
|
||||||
// Works for locally defined types too.
|
|
||||||
|
|
||||||
function CTor() { this.size = 10; }
|
|
||||||
CTor.prototype.hallo = "hallo";
|
|
||||||
|
|
||||||
var baz = new CTor;
|
|
||||||
baz.
|
|
||||||
|
|
||||||
// You can press ctrl-q when the cursor is on a variable name to
|
|
||||||
// rename it. Try it with CTor...
|
|
||||||
|
|
||||||
// When the cursor is in an argument list, the arguments are
|
|
||||||
// shown below the editor.
|
|
||||||
|
|
||||||
[1].reduce( );
|
|
||||||
|
|
||||||
// And a little more advanced code...
|
|
||||||
|
|
||||||
(function(exports) {
|
|
||||||
exports.randomElt = function(arr) {
|
|
||||||
return arr[Math.floor(arr.length * Math.random())];
|
|
||||||
};
|
|
||||||
exports.strList = "foo".split("");
|
|
||||||
exports.intList = exports.strList.map(function(s) { return s.charCodeAt(0); });
|
|
||||||
})(window.myMod = {});
|
|
||||||
|
|
||||||
var randomStr = myMod.randomElt(myMod.strList);
|
|
||||||
var randomInt = myMod.randomElt(myMod.intList);
|
|
||||||
</textarea></p>
|
|
||||||
|
|
||||||
<p>Demonstrates integration of <a href="http://ternjs.net/">Tern</a>
|
|
||||||
and CodeMirror. The following keys are bound:</p>
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt>Ctrl-Space</dt><dd>Autocomplete</dd>
|
|
||||||
<dt>Ctrl-O</dt><dd>Find docs for the expression at the cursor</dd>
|
|
||||||
<dt>Ctrl-I</dt><dd>Find type at cursor</dd>
|
|
||||||
<dt>Alt-.</dt><dd>Jump to definition (Alt-, to jump back)</dd>
|
|
||||||
<dt>Ctrl-Q</dt><dd>Rename variable</dd>
|
|
||||||
<dt>Ctrl-.</dt><dd>Select all occurrences of a variable</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<p>Documentation is sparse for now. See the top of
|
|
||||||
the <a href="../addon/tern/tern.js">script</a> for a rough API
|
|
||||||
overview.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function getURL(url, c) {
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open("get", url, true);
|
|
||||||
xhr.send();
|
|
||||||
xhr.onreadystatechange = function() {
|
|
||||||
if (xhr.readyState != 4) return;
|
|
||||||
if (xhr.status < 400) return c(null, xhr.responseText);
|
|
||||||
var e = new Error(xhr.responseText || "No response");
|
|
||||||
e.status = xhr.status;
|
|
||||||
c(e);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var server;
|
|
||||||
getURL("http://ternjs.net/defs/ecma5.json", function(err, code) {
|
|
||||||
if (err) throw new Error("Request for ecma5.json: " + err);
|
|
||||||
server = new CodeMirror.TernServer({defs: [JSON.parse(code)]});
|
|
||||||
editor.setOption("extraKeys", {
|
|
||||||
"Ctrl-Space": function(cm) { server.complete(cm); },
|
|
||||||
"Ctrl-I": function(cm) { server.showType(cm); },
|
|
||||||
"Ctrl-O": function(cm) { server.showDocs(cm); },
|
|
||||||
"Alt-.": function(cm) { server.jumpToDef(cm); },
|
|
||||||
"Alt-,": function(cm) { server.jumpBack(cm); },
|
|
||||||
"Ctrl-Q": function(cm) { server.rename(cm); },
|
|
||||||
"Ctrl-.": function(cm) { server.selectName(cm); }
|
|
||||||
})
|
|
||||||
editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); });
|
|
||||||
});
|
|
||||||
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "javascript"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Theme Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../theme/3024-day.css">
|
|
||||||
<link rel="stylesheet" href="../theme/3024-night.css">
|
|
||||||
<link rel="stylesheet" href="../theme/ambiance.css">
|
|
||||||
<link rel="stylesheet" href="../theme/base16-dark.css">
|
|
||||||
<link rel="stylesheet" href="../theme/base16-light.css">
|
|
||||||
<link rel="stylesheet" href="../theme/blackboard.css">
|
|
||||||
<link rel="stylesheet" href="../theme/cobalt.css">
|
|
||||||
<link rel="stylesheet" href="../theme/colorforth.css">
|
|
||||||
<link rel="stylesheet" href="../theme/eclipse.css">
|
|
||||||
<link rel="stylesheet" href="../theme/elegant.css">
|
|
||||||
<link rel="stylesheet" href="../theme/erlang-dark.css">
|
|
||||||
<link rel="stylesheet" href="../theme/lesser-dark.css">
|
|
||||||
<link rel="stylesheet" href="../theme/mbo.css">
|
|
||||||
<link rel="stylesheet" href="../theme/mdn-like.css">
|
|
||||||
<link rel="stylesheet" href="../theme/midnight.css">
|
|
||||||
<link rel="stylesheet" href="../theme/monokai.css">
|
|
||||||
<link rel="stylesheet" href="../theme/neat.css">
|
|
||||||
<link rel="stylesheet" href="../theme/neo.css">
|
|
||||||
<link rel="stylesheet" href="../theme/night.css">
|
|
||||||
<link rel="stylesheet" href="../theme/paraiso-dark.css">
|
|
||||||
<link rel="stylesheet" href="../theme/paraiso-light.css">
|
|
||||||
<link rel="stylesheet" href="../theme/pastel-on-dark.css">
|
|
||||||
<link rel="stylesheet" href="../theme/rubyblue.css">
|
|
||||||
<link rel="stylesheet" href="../theme/solarized.css">
|
|
||||||
<link rel="stylesheet" href="../theme/the-matrix.css">
|
|
||||||
<link rel="stylesheet" href="../theme/tomorrow-night-bright.css">
|
|
||||||
<link rel="stylesheet" href="../theme/tomorrow-night-eighties.css">
|
|
||||||
<link rel="stylesheet" href="../theme/twilight.css">
|
|
||||||
<link rel="stylesheet" href="../theme/vibrant-ink.css">
|
|
||||||
<link rel="stylesheet" href="../theme/xq-dark.css">
|
|
||||||
<link rel="stylesheet" href="../theme/xq-light.css">
|
|
||||||
<link rel="stylesheet" href="../theme/zenburn.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="../addon/selection/active-line.js"></script>
|
|
||||||
<script src="../addon/edit/matchbrackets.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid black; font-size:13px}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Theme</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Theme Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
function findSequence(goal) {
|
|
||||||
function find(start, history) {
|
|
||||||
if (start == goal)
|
|
||||||
return history;
|
|
||||||
else if (start > goal)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
return find(start + 5, "(" + history + " + 5)") ||
|
|
||||||
find(start * 3, "(" + history + " * 3)");
|
|
||||||
}
|
|
||||||
return find(1, "1");
|
|
||||||
}</textarea></form>
|
|
||||||
|
|
||||||
<p>Select a theme: <select onchange="selectTheme()" id=select>
|
|
||||||
<option selected>default</option>
|
|
||||||
<option>3024-day</option>
|
|
||||||
<option>3024-night</option>
|
|
||||||
<option>ambiance</option>
|
|
||||||
<option>base16-dark</option>
|
|
||||||
<option>base16-light</option>
|
|
||||||
<option>blackboard</option>
|
|
||||||
<option>cobalt</option>
|
|
||||||
<option>colorforth</option>
|
|
||||||
<option>eclipse</option>
|
|
||||||
<option>elegant</option>
|
|
||||||
<option>erlang-dark</option>
|
|
||||||
<option>lesser-dark</option>
|
|
||||||
<option>mbo</option>
|
|
||||||
<option>mdn-like</option>
|
|
||||||
<option>midnight</option>
|
|
||||||
<option>monokai</option>
|
|
||||||
<option>neat</option>
|
|
||||||
<option>neo</option>
|
|
||||||
<option>night</option>
|
|
||||||
<option>paraiso-dark</option>
|
|
||||||
<option>paraiso-light</option>
|
|
||||||
<option>pastel-on-dark</option>
|
|
||||||
<option>rubyblue</option>
|
|
||||||
<option>solarized dark</option>
|
|
||||||
<option>solarized light</option>
|
|
||||||
<option>the-matrix</option>
|
|
||||||
<option>tomorrow-night-bright</option>
|
|
||||||
<option>tomorrow-night-eighties</option>
|
|
||||||
<option>twilight</option>
|
|
||||||
<option>vibrant-ink</option>
|
|
||||||
<option>xq-dark</option>
|
|
||||||
<option>xq-light</option>
|
|
||||||
<option>zenburn</option>
|
|
||||||
</select>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
styleActiveLine: true,
|
|
||||||
matchBrackets: true
|
|
||||||
});
|
|
||||||
var input = document.getElementById("select");
|
|
||||||
function selectTheme() {
|
|
||||||
var theme = input.options[input.selectedIndex].innerHTML;
|
|
||||||
editor.setOption("theme", theme);
|
|
||||||
}
|
|
||||||
var choice = document.location.search &&
|
|
||||||
decodeURIComponent(document.location.search.slice(1));
|
|
||||||
if (choice) {
|
|
||||||
input.value = choice;
|
|
||||||
editor.setOption("theme", choice);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Trailing Whitespace Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/edit/trailingspace.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
|
||||||
.cm-trailingspace {
|
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==);
|
|
||||||
background-position: bottom left;
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Trailing Whitespace</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Trailing Whitespace Demo</h2>
|
|
||||||
<form><textarea id="code" name="code">This text
|
|
||||||
has some
|
|
||||||
trailing whitespace!</textarea></form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
showTrailingSpace: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<p>Uses
|
|
||||||
the <a href="../doc/manual.html#addon_trailingspace">trailingspace</a>
|
|
||||||
addon to highlight trailing whitespace.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Variable Height Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/markdown/markdown.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid silver; border-width: 1px 2px; }
|
|
||||||
.cm-header { font-family: arial; }
|
|
||||||
.cm-header-1 { font-size: 150%; }
|
|
||||||
.cm-header-2 { font-size: 130%; }
|
|
||||||
.cm-header-3 { font-size: 120%; }
|
|
||||||
.cm-header-4 { font-size: 110%; }
|
|
||||||
.cm-header-5 { font-size: 100%; }
|
|
||||||
.cm-header-6 { font-size: 90%; }
|
|
||||||
.cm-strong { font-size: 140%; }
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Variable Height</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Variable Height Demo</h2>
|
|
||||||
<form><textarea id="code" name="code"># A First Level Header
|
|
||||||
|
|
||||||
**Bold** text in a normal-size paragraph.
|
|
||||||
|
|
||||||
And a very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long, wrapped line with a piece of **big** text inside of it.
|
|
||||||
|
|
||||||
## A Second Level Header
|
|
||||||
|
|
||||||
Now is the time for all good men to come to
|
|
||||||
the aid of their country. This is just a
|
|
||||||
regular paragraph.
|
|
||||||
|
|
||||||
The quick brown fox jumped over the lazy
|
|
||||||
dog's back.
|
|
||||||
|
|
||||||
### Header 3
|
|
||||||
|
|
||||||
> This is a blockquote.
|
|
||||||
>
|
|
||||||
> This is the second paragraph in the blockquote.
|
|
||||||
>
|
|
||||||
> ## This is an H2 in a blockquote
|
|
||||||
</textarea></form>
|
|
||||||
<script id="script">
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
lineWrapping: true,
|
|
||||||
mode: "markdown"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Vim bindings demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/dialog/dialog.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/dialog/dialog.js"></script>
|
|
||||||
<script src="../addon/search/searchcursor.js"></script>
|
|
||||||
<script src="../mode/clike/clike.js"></script>
|
|
||||||
<script src="../addon/edit/matchbrackets.js"></script>
|
|
||||||
<script src="../keymap/vim.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Vim bindings</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Vim bindings demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
#include "syscalls.h"
|
|
||||||
/* getchar: simple buffered version */
|
|
||||||
int getchar(void)
|
|
||||||
{
|
|
||||||
static char buf[BUFSIZ];
|
|
||||||
static char *bufp = buf;
|
|
||||||
static int n = 0;
|
|
||||||
if (n == 0) { /* buffer is empty */
|
|
||||||
n = read(0, buf, sizeof buf);
|
|
||||||
bufp = buf;
|
|
||||||
}
|
|
||||||
return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
|
|
||||||
}
|
|
||||||
</textarea></form>
|
|
||||||
<div style="font-size: 13px; width: 300px; height: 30px;">Key buffer: <span id="command-display"></span></div>
|
|
||||||
|
|
||||||
<p>The vim keybindings are enabled by
|
|
||||||
including <a href="../keymap/vim.js">keymap/vim.js</a> and setting
|
|
||||||
the <code>vimMode</code> option to <code>true</code>. This will also
|
|
||||||
automatically change the <code>keyMap</code> option to <code>"vim"</code>.</p>
|
|
||||||
|
|
||||||
<p><strong>Features</strong></p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>All common motions and operators, including text objects</li>
|
|
||||||
<li>Operator motion orthogonality</li>
|
|
||||||
<li>Visual mode - characterwise, linewise, partial support for blockwise</li>
|
|
||||||
<li>Full macro support (q, @)</li>
|
|
||||||
<li>Incremental highlighted search (/, ?, #, *, g#, g*)</li>
|
|
||||||
<li>Search/replace with confirm (:substitute, :%s)</li>
|
|
||||||
<li>Search history</li>
|
|
||||||
<li>Jump lists (Ctrl-o, Ctrl-i)</li>
|
|
||||||
<li>Key/command mapping with API (:map, :nmap, :vmap)</li>
|
|
||||||
<li>Sort (:sort)</li>
|
|
||||||
<li>Marks (`, ')</li>
|
|
||||||
<li>:global</li>
|
|
||||||
<li>Insert mode behaves identical to base CodeMirror</li>
|
|
||||||
<li>Cross-buffer yank/paste</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Note that while the vim mode tries to emulate the most useful features of
|
|
||||||
vim as faithfully as possible, it does not strive to become a complete vim
|
|
||||||
implementation</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
CodeMirror.commands.save = function(){ alert("Saving"); };
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "text/x-csrc",
|
|
||||||
keyMap: "vim",
|
|
||||||
matchBrackets: true,
|
|
||||||
showCursorWhenSelecting: true
|
|
||||||
});
|
|
||||||
var commandDisplay = document.getElementById('command-display');
|
|
||||||
var keys = '';
|
|
||||||
CodeMirror.on(editor, 'vim-keypress', function(key) {
|
|
||||||
keys = keys + key;
|
|
||||||
commandDisplay.innerHTML = keys;
|
|
||||||
});
|
|
||||||
CodeMirror.on(editor, 'vim-command-done', function(e) {
|
|
||||||
keys = '';
|
|
||||||
commandDisplay.innerHTML = keys;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Visible tabs demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/clike/clike.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
|
|
||||||
.cm-tab {
|
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
|
|
||||||
background-position: right;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Visible tabs</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Visible tabs demo</h2>
|
|
||||||
<form><textarea id="code" name="code">
|
|
||||||
#include "syscalls.h"
|
|
||||||
/* getchar: simple buffered version */
|
|
||||||
int getchar(void)
|
|
||||||
{
|
|
||||||
static char buf[BUFSIZ];
|
|
||||||
static char *bufp = buf;
|
|
||||||
static int n = 0;
|
|
||||||
if (n == 0) { /* buffer is empty */
|
|
||||||
n = read(0, buf, sizeof buf);
|
|
||||||
bufp = buf;
|
|
||||||
}
|
|
||||||
return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
|
|
||||||
}
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>Tabs inside the editor are spans with the
|
|
||||||
class <code>cm-tab</code>, and can be styled.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
tabSize: 4,
|
|
||||||
indentUnit: 4,
|
|
||||||
indentWithTabs: true,
|
|
||||||
mode: "text/x-csrc"
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Inline Widget Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<script src="//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror {border: 1px solid black;}
|
|
||||||
.lint-error {font-family: arial; font-size: 70%; background: #ffa; color: #a00; padding: 2px 5px 3px; }
|
|
||||||
.lint-error-icon {color: white; background-color: red; font-weight: bold; border-radius: 50%; padding: 0 3px; margin-right: 7px;}
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Inline Widget</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>Inline Widget Demo</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<div id=code></div>
|
|
||||||
<script id="script">var widgets = []
|
|
||||||
function updateHints() {
|
|
||||||
editor.operation(function(){
|
|
||||||
for (var i = 0; i < widgets.length; ++i)
|
|
||||||
editor.removeLineWidget(widgets[i]);
|
|
||||||
widgets.length = 0;
|
|
||||||
|
|
||||||
JSHINT(editor.getValue());
|
|
||||||
for (var i = 0; i < JSHINT.errors.length; ++i) {
|
|
||||||
var err = JSHINT.errors[i];
|
|
||||||
if (!err) continue;
|
|
||||||
var msg = document.createElement("div");
|
|
||||||
var icon = msg.appendChild(document.createElement("span"));
|
|
||||||
icon.innerHTML = "!!";
|
|
||||||
icon.className = "lint-error-icon";
|
|
||||||
msg.appendChild(document.createTextNode(err.reason));
|
|
||||||
msg.className = "lint-error";
|
|
||||||
widgets.push(editor.addLineWidget(err.line - 1, msg, {coverGutter: false, noHScroll: true}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var info = editor.getScrollInfo();
|
|
||||||
var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
|
|
||||||
if (info.top + info.clientHeight < after)
|
|
||||||
editor.scrollTo(null, after - info.clientHeight + 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function() {
|
|
||||||
var sc = document.getElementById("script");
|
|
||||||
var content = sc.textContent || sc.innerText || sc.innerHTML;
|
|
||||||
|
|
||||||
window.editor = CodeMirror(document.getElementById("code"), {
|
|
||||||
lineNumbers: true,
|
|
||||||
mode: "javascript",
|
|
||||||
value: content
|
|
||||||
});
|
|
||||||
|
|
||||||
var waiting;
|
|
||||||
editor.on("change", function() {
|
|
||||||
clearTimeout(waiting);
|
|
||||||
waiting = setTimeout(updateHints, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(updateHints, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
"long line to create a horizontal scrollbar, in order to test whether the (non-inline) widgets stay in place when scrolling to the right";
|
|
||||||
</script>
|
|
||||||
<p>This demo runs <a href="http://jshint.com">JSHint</a> over the code
|
|
||||||
in the editor (which is the script used on this page), and
|
|
||||||
inserts <a href="../doc/manual.html#addLineWidget">line widgets</a> to
|
|
||||||
display the warnings that JSHint comes up with.</p>
|
|
||||||
</article>
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: XML Autocomplete Demo</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="../doc/docs.css">
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../lib/codemirror.css">
|
|
||||||
<link rel="stylesheet" href="../addon/hint/show-hint.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../addon/hint/show-hint.js"></script>
|
|
||||||
<script src="../addon/hint/xml-hint.js"></script>
|
|
||||||
<script src="../mode/xml/xml.js"></script>
|
|
||||||
<style type="text/css">
|
|
||||||
.CodeMirror { border: 1px solid #eee; }
|
|
||||||
</style>
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="../doc/manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">XML Autocomplete</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h2>XML Autocomplete Demo</h2>
|
|
||||||
<form><textarea id="code" name="code"><!-- write some xml below -->
|
|
||||||
</textarea></form>
|
|
||||||
|
|
||||||
<p>Press <strong>ctrl-space</strong>, or type a '<' character to
|
|
||||||
activate autocompletion. This demo defines a simple schema that
|
|
||||||
guides completion. The schema can be customized—see
|
|
||||||
the <a href="../doc/manual.html#addon_xml-hint">manual</a>.</p>
|
|
||||||
|
|
||||||
<p>Development of the <code>xml-hint</code> addon was kindly
|
|
||||||
sponsored
|
|
||||||
by <a href="http://www.xperiment.mobi">www.xperiment.mobi</a>.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var dummy = {
|
|
||||||
attrs: {
|
|
||||||
color: ["red", "green", "blue", "purple", "white", "black", "yellow"],
|
|
||||||
size: ["large", "medium", "small"],
|
|
||||||
description: null
|
|
||||||
},
|
|
||||||
children: []
|
|
||||||
};
|
|
||||||
|
|
||||||
var tags = {
|
|
||||||
"!top": ["top"],
|
|
||||||
"!attrs": {
|
|
||||||
id: null,
|
|
||||||
class: ["A", "B", "C"]
|
|
||||||
},
|
|
||||||
top: {
|
|
||||||
attrs: {
|
|
||||||
lang: ["en", "de", "fr", "nl"],
|
|
||||||
freeform: null
|
|
||||||
},
|
|
||||||
children: ["animal", "plant"]
|
|
||||||
},
|
|
||||||
animal: {
|
|
||||||
attrs: {
|
|
||||||
name: null,
|
|
||||||
isduck: ["yes", "no"]
|
|
||||||
},
|
|
||||||
children: ["wings", "feet", "body", "head", "tail"]
|
|
||||||
},
|
|
||||||
plant: {
|
|
||||||
attrs: {name: null},
|
|
||||||
children: ["leaves", "stem", "flowers"]
|
|
||||||
},
|
|
||||||
wings: dummy, feet: dummy, body: dummy, head: dummy, tail: dummy,
|
|
||||||
leaves: dummy, stem: dummy, flowers: dummy
|
|
||||||
};
|
|
||||||
|
|
||||||
function completeAfter(cm, pred) {
|
|
||||||
var cur = cm.getCursor();
|
|
||||||
if (!pred || pred()) setTimeout(function() {
|
|
||||||
if (!cm.state.completionActive)
|
|
||||||
cm.showHint({completeSingle: false});
|
|
||||||
}, 100);
|
|
||||||
return CodeMirror.Pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
function completeIfAfterLt(cm) {
|
|
||||||
return completeAfter(cm, function() {
|
|
||||||
var cur = cm.getCursor();
|
|
||||||
return cm.getRange(CodeMirror.Pos(cur.line, cur.ch - 1), cur) == "<";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function completeIfInTag(cm) {
|
|
||||||
return completeAfter(cm, function() {
|
|
||||||
var tok = cm.getTokenAt(cm.getCursor());
|
|
||||||
if (tok.type == "string" && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1)) return false;
|
|
||||||
var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state;
|
|
||||||
return inner.tagName;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
||||||
mode: "xml",
|
|
||||||
lineNumbers: true,
|
|
||||||
extraKeys: {
|
|
||||||
"'<'": completeAfter,
|
|
||||||
"'/'": completeIfAfterLt,
|
|
||||||
"' '": completeIfInTag,
|
|
||||||
"'='": completeIfInTag,
|
|
||||||
"Ctrl-Space": "autocomplete"
|
|
||||||
},
|
|
||||||
hintOptions: {schemaInfo: tags}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</article>
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
// Kludge in HTML5 tag recognition in IE8
|
|
||||||
document.createElement("section");
|
|
||||||
document.createElement("article");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
if (!window.addEventListener) return;
|
|
||||||
var pending = false, prevVal = null;
|
|
||||||
|
|
||||||
function updateSoon() {
|
|
||||||
if (!pending) {
|
|
||||||
pending = true;
|
|
||||||
setTimeout(update, 250);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
|
||||||
pending = false;
|
|
||||||
var marks = document.getElementById("nav").getElementsByTagName("a"), found;
|
|
||||||
for (var i = 0; i < marks.length; ++i) {
|
|
||||||
var mark = marks[i], m;
|
|
||||||
if (mark.getAttribute("data-default")) {
|
|
||||||
if (found == null) found = i;
|
|
||||||
} else if (m = mark.href.match(/#(.*)/)) {
|
|
||||||
var ref = document.getElementById(m[1]);
|
|
||||||
if (ref && ref.getBoundingClientRect().top < 50)
|
|
||||||
found = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found != null && found != prevVal) {
|
|
||||||
prevVal = found;
|
|
||||||
var lis = document.getElementById("nav").getElementsByTagName("li");
|
|
||||||
for (var i = 0; i < lis.length; ++i) lis[i].className = "";
|
|
||||||
for (var i = 0; i < marks.length; ++i) {
|
|
||||||
if (found == i) {
|
|
||||||
marks[i].className = "active";
|
|
||||||
for (var n = marks[i]; n; n = n.parentNode)
|
|
||||||
if (n.nodeName == "LI") n.className = "active";
|
|
||||||
} else {
|
|
||||||
marks[i].className = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("scroll", updateSoon);
|
|
||||||
window.addEventListener("load", updateSoon);
|
|
||||||
window.addEventListener("hashchange", function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
var hash = document.location.hash, found = null, m;
|
|
||||||
var marks = document.getElementById("nav").getElementsByTagName("a");
|
|
||||||
for (var i = 0; i < marks.length; i++)
|
|
||||||
if ((m = marks[i].href.match(/(#.*)/)) && m[1] == hash) { found = i; break; }
|
|
||||||
if (found != null) for (var i = 0; i < marks.length; i++)
|
|
||||||
marks[i].className = i == found ? "active" : "";
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
@@ -1,309 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Compression Helper</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="docs.css">
|
|
||||||
<script src="../lib/codemirror.js"></script>
|
|
||||||
<script src="../mode/javascript/javascript.js"></script>
|
|
||||||
<link rel=stylesheet href="../lib/codemirror.css">
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a class=active href="#">Compression helper</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
|
|
||||||
<h2>Script compression helper</h2>
|
|
||||||
|
|
||||||
<p>To optimize loading CodeMirror, especially when including a
|
|
||||||
bunch of different modes, it is recommended that you combine and
|
|
||||||
minify (and preferably also gzip) the scripts. This page makes
|
|
||||||
those first two steps very easy. Simply select the version and
|
|
||||||
scripts you need in the form below, and
|
|
||||||
click <strong>Compress</strong> to download the minified script
|
|
||||||
file.</p>
|
|
||||||
|
|
||||||
<form id="form" action="http://marijnhaverbeke.nl/uglifyjs" method="post" onsubmit="generateHeader();">
|
|
||||||
<input type="hidden" id="download" name="download" value="codemirror-compressed.js"/>
|
|
||||||
<p>Version: <select id="version" onchange="setVersion(this);" style="padding: 1px;">
|
|
||||||
<option value="http://codemirror.net/">HEAD</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.0.0;f=">5.0</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.13.0;f=">4.13</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.12.0;f=">4.12</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.11.0;f=">4.11</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.10.0;f=">4.10</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.9.0;f=">4.9</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.8.0;f=">4.8</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.7.0;f=">4.7</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.6.0;f=">4.6</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.5.0;f=">4.5</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.4.0;f=">4.4</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.3.0;f=">4.3</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.1;f=">4.2</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.2.0;f=">4.2</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.1.0;f=">4.1</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=4.0.3;f=">4.0</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.23.0;f=">3.23</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.22.0;f=">3.22</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.21.0;f=">3.21</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.20.0;f=">3.20</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.19.0;f=">3.19</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.18.0;f=">3.18</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.16.0;f=">3.16</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.15.0;f=">3.15</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.14.0;f=">3.14</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=3.13.0;f=">3.13</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.12;f=">3.12</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.11;f=">3.11</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.1;f=">3.1</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.02;f=">3.02</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.01;f=">3.01</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.0;f=">3.0</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.38;f=">2.38</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.37;f=">2.37</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.36;f=">2.36</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.35;f=">2.35</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.34;f=">2.34</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.33;f=">2.33</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.32;f=">2.32</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.31;f=">2.31</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.3;f=">2.3</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.25;f=">2.25</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.24;f=">2.24</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.23;f=">2.23</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.22;f=">2.22</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.21;f=">2.21</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.2;f=">2.2</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.18;f=">2.18</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.16;f=">2.16</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.15;f=">2.15</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.13;f=">2.13</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.12;f=">2.12</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.11;f=">2.11</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.1;f=">2.1</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.02;f=">2.02</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.01;f=">2.01</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v2.0;f=">2.0</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=beta2;f=">beta2</option>
|
|
||||||
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=beta1;f=">beta1</option>
|
|
||||||
</select></p>
|
|
||||||
|
|
||||||
<select multiple="multiple" size="20" name="code_url" style="width: 40em;" class="field" id="files">
|
|
||||||
<optgroup label="CodeMirror Library">
|
|
||||||
<option value="http://codemirror.net/lib/codemirror.js" selected>codemirror.js</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Modes">
|
|
||||||
<option value="http://codemirror.net/mode/apl/apl.js">apl.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/clike/clike.js">clike.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/clojure/clojure.js">clojure.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/cobol/cobol.js">cobol.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/coffeescript/coffeescript.js">coffeescript.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/commonlisp/commonlisp.js">commonlisp.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/css/css.js">css.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/cypher/cypher.js">cypher.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/d/d.js">d.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/dart/dart.js">dart.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/diff/diff.js">diff.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/django/django.js">django.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/dockerfile/dockerfile.js">dockerfile.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/dtd/dtd.js">dtd.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/dylan/dylan.js">dylan.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/ebnf/ebnf.js">ebnf.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/ecl/ecl.js">ecl.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/eiffel/eiffel.js">eiffel.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/erlang/erlang.js">erlang.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/forth/forth.js">forth.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/fortran/fortran.js">fortran.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/gfm/gfm.js">gfm.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/gas/gas.js">gas.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/gherkin/gherkin.js">gherkin.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/go/go.js">go.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/groovy/groovy.js">groovy.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/haml/haml.js">haml.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/haskell/haskell.js">haskell.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/haxe/haxe.js">haxe.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/htmlembedded/htmlembedded.js">htmlembedded.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/htmlmixed/htmlmixed.js">htmlmixed.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/http/http.js">http.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/idl/idl.js">idl.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/jade/jade.js">jade.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/javascript/javascript.js">javascript.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/jinja2/jinja2.js">jinja2.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/julia/julia.js">julia.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/kotlin/kotlin.js">kotlin.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/livescript/livescript.js">livescript.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/markdown/markdown.js">markdown.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/mirc/mirc.js">mirc.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/mllike/mllike.js">mllike.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/modelica/modelica.js">modelica.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/nginx/nginx.js">nginx.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/ntriples/ntriples.js">ntriples.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/octave/octave.js">octave.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/pascal/pascal.js">pascal.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/pegjs/pegjs.js">pegjs.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/perl/perl.js">perl.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/php/php.js">php.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/pig/pig.js">pig.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/properties/properties.js">properties.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/python/python.js">python.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/puppet/puppet.js">puppet.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/q/q.js">q.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/r/r.js">r.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/rpm/rpm.js">rpm.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/rst/rst.js">rst.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/ruby/ruby.js">ruby.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/rust/rust.js">rust.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/sass/sass.js">sass.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/scala/scala.js">scala.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/scheme/scheme.js">scheme.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/shell/shell.js">shell.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/sieve/sieve.js">sieve.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/slim/slim.js">slim.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/smalltalk/smalltalk.js">smalltalk.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/smarty/smarty.js">smarty.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/smartymixed/smartymixed.js">smartymixed.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/solr/solr.js">solr.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/soy/soy.js">soy.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/sparql/sparql.js">sparql.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/spreadsheet/spreadsheet.js">spreadsheet.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/stylus/stylus.js">stylus.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/sql/sql.js">sql.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/stex/stex.js">stex.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/tcl/tcl.js">tcl.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/textile/textile.js">textile.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/tiddlywiki/tiddlywiki.js">tiddlywiki.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/tiki/tiki.js">tiki.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/toml/toml.js">toml.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/tornado/tornado.js">tornado.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/turtle/turtle.js">turtle.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/vb/vb.js">vb.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/vbscript/vbscript.js">vbscript.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/velocity/velocity.js">velocity.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/verilog/verilog.js">verilog.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/xml/xml.js">xml.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/xquery/xquery.js">xquery.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/yaml/yaml.js">yaml.js</option>
|
|
||||||
<option value="http://codemirror.net/mode/z80/z80.js">z80.js</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Add-ons">
|
|
||||||
<option value="http://codemirror.net/addon/selection/active-line.js">active-line.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/anyword-hint.js">anyword-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/brace-fold.js">brace-fold.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/edit/closebrackets.js">closebrackets.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/edit/closetag.js">closetag.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/runmode/colorize.js">colorize.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/comment/comment.js">comment.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/comment-fold.js">comment-fold.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/comment/continuecomment.js">continuecomment.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/edit/continuelist.js">continuelist.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/css-hint.js">css-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/dialog/dialog.js">dialog.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/foldcode.js">foldcode.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/foldgutter.js">foldgutter.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/display/fullscreen.js">fullscreen.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/wrap/hardwrap.js">hardwrap.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/html-hint.js">html-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/indent-fold.js">indent-fold.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/javascript-hint.js">javascript-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/lint/javascript-lint.js">javascript-lint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/lint/json-lint.js">json-lint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/lint/lint.js">lint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/mode/loadmode.js">loadmode.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/markdown-fold.js">markdown-fold.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/selection/mark-selection.js">mark-selection.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/search/match-highlighter.js">match-highlighter.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/edit/matchbrackets.js">matchbrackets.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/edit/matchtags.js">matchtags.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/merge/merge.js">merge.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/mode/multiplex.js">multiplex.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/mode/overlay.js">overlay.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/display/placeholder.js">placeholder.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/display/rulers.js">rulers.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/runmode/runmode.js">runmode.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/runmode/runmode.node.js">runmode.node.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/runmode/runmode-standalone.js">runmode-standalone.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/search/search.js">search.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/search/searchcursor.js">searchcursor.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/show-hint.js">show-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/mode/simple.js">simple.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/scroll/simplescrollbars.js">simplescrollbars.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/sql-hint.js">sql-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/edit/trailingspace.js">trailingspace.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/tern/tern.js">tern.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/fold/xml-fold.js">xml-fold.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/xml-hint.js">xml-hint.js</option>
|
|
||||||
<option value="http://codemirror.net/addon/hint/yaml-lint.js">yaml-lint.js</option>
|
|
||||||
</optgroup>
|
|
||||||
<optgroup label="Keymaps">
|
|
||||||
<option value="http://codemirror.net/keymap/emacs.js">emacs.js</option>
|
|
||||||
<option value="http://codemirror.net/keymap/sublime.js">sublime.js</option>
|
|
||||||
<option value="http://codemirror.net/keymap/vim.js">vim.js</option>
|
|
||||||
</optgroup>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<button type="submit">Compress</button> with <a href="http://github.com/mishoo/UglifyJS/">UglifyJS</a>
|
|
||||||
</p>
|
|
||||||
<input type="hidden" id="header" name="header">
|
|
||||||
<p>Custom code to add to the compressed file:<textarea name="js_code" style="width: 100%; height: 15em;" class="field" id="js_code"></textarea></p>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
CodeMirror.fromTextArea(document.getElementById("js_code")).getWrapperElement().className += " field";
|
|
||||||
|
|
||||||
function setVersion(ver) {
|
|
||||||
var urlprefix = ver.options[ver.selectedIndex].value;
|
|
||||||
var select = document.getElementById("files"), m;
|
|
||||||
for (var optgr = select.firstChild; optgr; optgr = optgr.nextSibling)
|
|
||||||
for (var opt = optgr.firstChild; opt; opt = opt.nextSibling) {
|
|
||||||
if (opt.nodeName != "OPTION")
|
|
||||||
continue;
|
|
||||||
else if (m = opt.value.match(/^http:\/\/codemirror.net\/(.*)$/))
|
|
||||||
opt.value = urlprefix + m[1];
|
|
||||||
else if (m = opt.value.match(/http:\/\/marijnhaverbeke.nl\/git\/codemirror\?a=blob_plain;hb=[^;]+;f=(.*)$/))
|
|
||||||
opt.value = urlprefix + m[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateHeader() {
|
|
||||||
var versionNode = document.getElementById("version");
|
|
||||||
var version = versionNode.options[versionNode.selectedIndex].label
|
|
||||||
var filesNode = document.getElementById("files");
|
|
||||||
var optGroupHeaderIncluded;
|
|
||||||
|
|
||||||
// Generate the comment
|
|
||||||
var str = "/* CodeMirror - Minified & Bundled\n";
|
|
||||||
str += " Generated on " + new Date().toLocaleDateString() + " with http://codemirror.net/doc/compress.html\n";
|
|
||||||
str += " Version: " + version + "\n\n";
|
|
||||||
|
|
||||||
for (var group = filesNode.firstChild; group; group = group.nextSibling) {
|
|
||||||
optGroupHeaderIncluded = false;
|
|
||||||
for (var option = group.firstChild; option; option = option.nextSibling) {
|
|
||||||
if (option.nodeName !== "OPTION") {
|
|
||||||
continue;
|
|
||||||
} else if (option.selected) {
|
|
||||||
if (!optGroupHeaderIncluded) {
|
|
||||||
str += " " + group.label + ":\n";
|
|
||||||
optGroupHeaderIncluded = true;
|
|
||||||
}
|
|
||||||
str += " - " + option.label + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str += " */\n\n";
|
|
||||||
|
|
||||||
document.getElementById("header").value = str;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
@font-face {
|
|
||||||
font-family: 'Source Sans Pro';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url(//themes.googleusercontent.com/static/fonts/sourcesanspro/v5/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff');
|
|
||||||
}
|
|
||||||
|
|
||||||
body, html { margin: 0; padding: 0; height: 100%; }
|
|
||||||
section, article { display: block; padding: 0; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: #f8f8f8;
|
|
||||||
font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
p { margin-top: 0; }
|
|
||||||
|
|
||||||
h2, h3, h1 {
|
|
||||||
font-weight: normal;
|
|
||||||
margin-bottom: .7em;
|
|
||||||
}
|
|
||||||
h1 { font-size: 140%; }
|
|
||||||
h2 { font-size: 120%; }
|
|
||||||
h3 { font-size: 110%; }
|
|
||||||
article > h2:first-child, section:first-child > h2 { margin-top: 0; }
|
|
||||||
|
|
||||||
#nav h1 {
|
|
||||||
margin-right: 12px;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
color: #d30707;
|
|
||||||
letter-spacing: .5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a, a:visited, a:link, .quasilink {
|
|
||||||
color: #A21313;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
em {
|
|
||||||
padding-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quasilink {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
article {
|
|
||||||
max-width: 700px;
|
|
||||||
margin: 0 0 0 160px;
|
|
||||||
border-left: 2px solid #E30808;
|
|
||||||
border-right: 1px solid #ddd;
|
|
||||||
padding: 30px 50px 100px 50px;
|
|
||||||
background: white;
|
|
||||||
z-index: 2;
|
|
||||||
position: relative;
|
|
||||||
min-height: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav {
|
|
||||||
position: fixed;
|
|
||||||
padding-top: 30px;
|
|
||||||
max-height: 100%;
|
|
||||||
box-sizing: -moz-border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow-y: auto;
|
|
||||||
left: 0; right: none;
|
|
||||||
width: 160px;
|
|
||||||
text-align: right;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 1000px) {
|
|
||||||
article {
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
#nav {
|
|
||||||
right: 50%;
|
|
||||||
width: auto;
|
|
||||||
border-right: 349px solid transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav ul {
|
|
||||||
display: block;
|
|
||||||
margin: 0; padding: 0;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav li {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav li ul {
|
|
||||||
font-size: 80%;
|
|
||||||
margin-bottom: 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav li.active ul {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav li li a {
|
|
||||||
padding-right: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav ul a {
|
|
||||||
color: black;
|
|
||||||
padding: 0 7px 1px 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nav ul a.active, #nav ul a:hover {
|
|
||||||
border-bottom: 1px solid #E30808;
|
|
||||||
margin-bottom: -1px;
|
|
||||||
color: #E30808;
|
|
||||||
}
|
|
||||||
|
|
||||||
#logo {
|
|
||||||
border: 0;
|
|
||||||
margin-right: 12px;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
border-top: 1px solid #E30808;
|
|
||||||
margin: 1.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.first {
|
|
||||||
border: none;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#demo {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#demolist {
|
|
||||||
position: absolute;
|
|
||||||
right: 5px;
|
|
||||||
top: 5px;
|
|
||||||
z-index: 25;
|
|
||||||
}
|
|
||||||
|
|
||||||
.yinyang {
|
|
||||||
position: absolute;
|
|
||||||
top: -10px;
|
|
||||||
left: 0; right: 0;
|
|
||||||
margin: auto;
|
|
||||||
display: block;
|
|
||||||
height: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
margin: 1em 0 0;
|
|
||||||
min-height: 100px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionspicture {
|
|
||||||
pointer-events: none;
|
|
||||||
position: absolute;
|
|
||||||
height: 100px;
|
|
||||||
top: 0; left: 0; right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionlink {
|
|
||||||
pointer-events: auto;
|
|
||||||
font-family: arial;
|
|
||||||
font-size: 80%;
|
|
||||||
font-weight: bold;
|
|
||||||
position: absolute;
|
|
||||||
top: 0; bottom: 0;
|
|
||||||
line-height: 1;
|
|
||||||
height: 1em;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionlink.download {
|
|
||||||
color: white;
|
|
||||||
right: 50%;
|
|
||||||
margin-right: 13px;
|
|
||||||
text-shadow: -1px 1px 3px #b00, -1px -1px 3px #b00, 1px 0px 3px #b00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionlink.fund {
|
|
||||||
color: #b00;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionlink:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionlink a {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionsleft {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actionsright {
|
|
||||||
float: right;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 800px) {
|
|
||||||
.actions {
|
|
||||||
padding-top: 120px;
|
|
||||||
}
|
|
||||||
.actionsleft, .actionsright {
|
|
||||||
float: none;
|
|
||||||
text-align: left;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-decoration: underline;
|
|
||||||
font-weight: normal;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
#features ul {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0 0 1em;
|
|
||||||
padding: 0 0 0 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#features li:before {
|
|
||||||
content: "-";
|
|
||||||
width: 1em;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
margin-left: -1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rel {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.rel-note {
|
|
||||||
margin-top: 0;
|
|
||||||
color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
padding-left: 15px;
|
|
||||||
border-left: 2px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
text-decoration: underline;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field {
|
|
||||||
border: 1px solid #A21313;
|
|
||||||
}
|
|
||||||
@@ -1,503 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
|
|
||||||
<title>CodeMirror: Internals</title>
|
|
||||||
<meta charset="utf-8"/>
|
|
||||||
<link rel=stylesheet href="docs.css">
|
|
||||||
<style>dl dl {margin: 0;} .update {color: #d40 !important}</style>
|
|
||||||
<script src="activebookmark.js"></script>
|
|
||||||
|
|
||||||
<div id=nav>
|
|
||||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="logo.png"></a>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="../index.html">Home</a>
|
|
||||||
<li><a href="manual.html">Manual</a>
|
|
||||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#top">Introduction</a></li>
|
|
||||||
<li><a href="#approach">General Approach</a></li>
|
|
||||||
<li><a href="#input">Input</a></li>
|
|
||||||
<li><a href="#selection">Selection</a></li>
|
|
||||||
<li><a href="#update">Intelligent Updating</a></li>
|
|
||||||
<li><a href="#parse">Parsing</a></li>
|
|
||||||
<li><a href="#summary">What Gives?</a></li>
|
|
||||||
<li><a href="#btree">Content Representation</a></li>
|
|
||||||
<li><a href="#keymap">Key Maps</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
|
|
||||||
<h2 id=top>(Re-) Implementing A Syntax-Highlighting Editor in JavaScript</h2>
|
|
||||||
|
|
||||||
<p style="font-size: 85%" id="intro">
|
|
||||||
<strong>Topic:</strong> JavaScript, code editor implementation<br>
|
|
||||||
<strong>Author:</strong> Marijn Haverbeke<br>
|
|
||||||
<strong>Date:</strong> March 2nd 2011 (updated November 13th 2011)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="padding: 0 3em 0 2em"><strong>Caution</strong>: this text was written briefly after
|
|
||||||
version 2 was initially written. It no longer (even including the
|
|
||||||
update at the bottom) fully represents the current implementation. I'm
|
|
||||||
leaving it here as a historic document. For more up-to-date
|
|
||||||
information, look at the entries
|
|
||||||
tagged <a href="http://marijnhaverbeke.nl/blog/#cm-internals">cm-internals</a>
|
|
||||||
on my blog.</p>
|
|
||||||
|
|
||||||
<p>This is a followup to
|
|
||||||
my <a href="http://codemirror.net/story.html">Brutal Odyssey to the
|
|
||||||
Dark Side of the DOM Tree</a> story. That one describes the
|
|
||||||
mind-bending process of implementing (what would become) CodeMirror 1.
|
|
||||||
This one describes the internals of CodeMirror 2, a complete rewrite
|
|
||||||
and rethink of the old code base. I wanted to give this piece another
|
|
||||||
Hunter Thompson copycat subtitle, but somehow that would be out of
|
|
||||||
place—the process this time around was one of straightforward
|
|
||||||
engineering, requiring no serious mind-bending whatsoever.</p>
|
|
||||||
|
|
||||||
<p>So, what is wrong with CodeMirror 1? I'd estimate, by mailing list
|
|
||||||
activity and general search-engine presence, that it has been
|
|
||||||
integrated into about a thousand systems by now. The most prominent
|
|
||||||
one, since a few weeks,
|
|
||||||
being <a href="http://googlecode.blogspot.com/2011/01/make-quick-fixes-quicker-on-google.html">Google
|
|
||||||
code's project hosting</a>. It works, and it's being used widely.</p>
|
|
||||||
|
|
||||||
<p>Still, I did not start replacing it because I was bored. CodeMirror
|
|
||||||
1 was heavily reliant on <code>designMode</code>
|
|
||||||
or <code>contentEditable</code> (depending on the browser). Neither of
|
|
||||||
these are well specified (HTML5 tries
|
|
||||||
to <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">specify</a>
|
|
||||||
their basics), and, more importantly, they tend to be one of the more
|
|
||||||
obscure and buggy areas of browser functionality—CodeMirror, by using
|
|
||||||
this functionality in a non-typical way, was constantly running up
|
|
||||||
against browser bugs. WebKit wouldn't show an empty line at the end of
|
|
||||||
the document, and in some releases would suddenly get unbearably slow.
|
|
||||||
Firefox would show the cursor in the wrong place. Internet Explorer
|
|
||||||
would insist on linkifying everything that looked like a URL or email
|
|
||||||
address, a behaviour that can't be turned off. Some bugs I managed to
|
|
||||||
work around (which was often a frustrating, painful process), others,
|
|
||||||
such as the Firefox cursor placement, I gave up on, and had to tell
|
|
||||||
user after user that they were known problems, but not something I
|
|
||||||
could help.</p>
|
|
||||||
|
|
||||||
<p>Also, there is the fact that <code>designMode</code> (which seemed
|
|
||||||
to be less buggy than <code>contentEditable</code> in Webkit and
|
|
||||||
Firefox, and was thus used by CodeMirror 1 in those browsers) requires
|
|
||||||
a frame. Frames are another tricky area. It takes some effort to
|
|
||||||
prevent getting tripped up by domain restrictions, they don't
|
|
||||||
initialize synchronously, behave strangely in response to the back
|
|
||||||
button, and, on several browsers, can't be moved around the DOM
|
|
||||||
without having them re-initialize. They did provide a very nice way to
|
|
||||||
namespace the library, though—CodeMirror 1 could freely pollute the
|
|
||||||
namespace inside the frame.</p>
|
|
||||||
|
|
||||||
<p>Finally, working with an editable document means working with
|
|
||||||
selection in arbitrary DOM structures. Internet Explorer (8 and
|
|
||||||
before) has an utterly different (and awkward) selection API than all
|
|
||||||
of the other browsers, and even among the different implementations of
|
|
||||||
<code>document.selection</code>, details about how exactly a selection
|
|
||||||
is represented vary quite a bit. Add to that the fact that Opera's
|
|
||||||
selection support tended to be very buggy until recently, and you can
|
|
||||||
imagine why CodeMirror 1 contains 700 lines of selection-handling
|
|
||||||
code.</p>
|
|
||||||
|
|
||||||
<p>And that brings us to the main issue with the CodeMirror 1
|
|
||||||
code base: The proportion of browser-bug-workarounds to real
|
|
||||||
application code was getting dangerously high. By building on top of a
|
|
||||||
few dodgy features, I put the system in a vulnerable position—any
|
|
||||||
incompatibility and bugginess in these features, I had to paper over
|
|
||||||
with my own code. Not only did I have to do some serious stunt-work to
|
|
||||||
get it to work on older browsers (as detailed in the
|
|
||||||
previous <a href="http://codemirror.net/story.html">story</a>), things
|
|
||||||
also kept breaking in newly released versions, requiring me to come up
|
|
||||||
with <em>new</em> scary hacks in order to keep up. This was starting
|
|
||||||
to lose its appeal.</p>
|
|
||||||
|
|
||||||
<section id=approach>
|
|
||||||
<h2>General Approach</h2>
|
|
||||||
|
|
||||||
<p>What CodeMirror 2 does is try to sidestep most of the hairy hacks
|
|
||||||
that came up in version 1. I owe a lot to the
|
|
||||||
<a href="http://ace.ajax.org">ACE</a> editor for inspiration on how to
|
|
||||||
approach this.</p>
|
|
||||||
|
|
||||||
<p>I absolutely did not want to be completely reliant on key events to
|
|
||||||
generate my input. Every JavaScript programmer knows that key event
|
|
||||||
information is horrible and incomplete. Some people (most awesomely
|
|
||||||
Mihai Bazon with <a href="http://ymacs.org">Ymacs</a>) have been able
|
|
||||||
to build more or less functioning editors by directly reading key
|
|
||||||
events, but it takes a lot of work (the kind of never-ending, fragile
|
|
||||||
work I described earlier), and will never be able to properly support
|
|
||||||
things like multi-keystoke international character
|
|
||||||
input. <a href="#keymap" class="update">[see below for caveat]</a></p>
|
|
||||||
|
|
||||||
<p>So what I do is focus a hidden textarea, and let the browser
|
|
||||||
believe that the user is typing into that. What we show to the user is
|
|
||||||
a DOM structure we built to represent his document. If this is updated
|
|
||||||
quickly enough, and shows some kind of believable cursor, it feels
|
|
||||||
like a real text-input control.</p>
|
|
||||||
|
|
||||||
<p>Another big win is that this DOM representation does not have to
|
|
||||||
span the whole document. Some CodeMirror 1 users insisted that they
|
|
||||||
needed to put a 30 thousand line XML document into CodeMirror. Putting
|
|
||||||
all that into the DOM takes a while, especially since, for some
|
|
||||||
reason, an editable DOM tree is slower than a normal one on most
|
|
||||||
browsers. If we have full control over what we show, we must only
|
|
||||||
ensure that the visible part of the document has been added, and can
|
|
||||||
do the rest only when needed. (Fortunately, the <code>onscroll</code>
|
|
||||||
event works almost the same on all browsers, and lends itself well to
|
|
||||||
displaying things only as they are scrolled into view.)</p>
|
|
||||||
</section>
|
|
||||||
<section id="input">
|
|
||||||
<h2>Input</h2>
|
|
||||||
|
|
||||||
<p>ACE uses its hidden textarea only as a text input shim, and does
|
|
||||||
all cursor movement and things like text deletion itself by directly
|
|
||||||
handling key events. CodeMirror's way is to let the browser do its
|
|
||||||
thing as much as possible, and not, for example, define its own set of
|
|
||||||
key bindings. One way to do this would have been to have the whole
|
|
||||||
document inside the hidden textarea, and after each key event update
|
|
||||||
the display DOM to reflect what's in that textarea.</p>
|
|
||||||
|
|
||||||
<p>That'd be simple, but it is not realistic. For even medium-sized
|
|
||||||
document the editor would be constantly munging huge strings, and get
|
|
||||||
terribly slow. What CodeMirror 2 does is put the current selection,
|
|
||||||
along with an extra line on the top and on the bottom, into the
|
|
||||||
textarea.</p>
|
|
||||||
|
|
||||||
<p>This means that the arrow keys (and their ctrl-variations), home,
|
|
||||||
end, etcetera, do not have to be handled specially. We just read the
|
|
||||||
cursor position in the textarea, and update our cursor to match it.
|
|
||||||
Also, copy and paste work pretty much for free, and people get their
|
|
||||||
native key bindings, without any special work on my part. For example,
|
|
||||||
I have emacs key bindings configured for Chrome and Firefox. There is
|
|
||||||
no way for a script to detect this. <a class="update"
|
|
||||||
href="#keymap">[no longer the case]</a></p>
|
|
||||||
|
|
||||||
<p>Of course, since only a small part of the document sits in the
|
|
||||||
textarea, keys like page up and ctrl-end won't do the right thing.
|
|
||||||
CodeMirror is catching those events and handling them itself.</p>
|
|
||||||
</section>
|
|
||||||
<section id="selection">
|
|
||||||
<h2>Selection</h2>
|
|
||||||
|
|
||||||
<p>Getting and setting the selection range of a textarea in modern
|
|
||||||
browsers is trivial—you just use the <code>selectionStart</code>
|
|
||||||
and <code>selectionEnd</code> properties. On IE you have to do some
|
|
||||||
insane stuff with temporary ranges and compensating for the fact that
|
|
||||||
moving the selection by a 'character' will treat \r\n as a single
|
|
||||||
character, but even there it is possible to build functions that
|
|
||||||
reliably set and get the selection range.</p>
|
|
||||||
|
|
||||||
<p>But consider this typical case: When I'm somewhere in my document,
|
|
||||||
press shift, and press the up arrow, something gets selected. Then, if
|
|
||||||
I, still holding shift, press the up arrow again, the top of my
|
|
||||||
selection is adjusted. The selection remembers where its <em>head</em>
|
|
||||||
and its <em>anchor</em> are, and moves the head when we shift-move.
|
|
||||||
This is a generally accepted property of selections, and done right by
|
|
||||||
every editing component built in the past twenty years.</p>
|
|
||||||
|
|
||||||
<p>But not something that the browser selection APIs expose.</p>
|
|
||||||
|
|
||||||
<p>Great. So when someone creates an 'upside-down' selection, the next
|
|
||||||
time CodeMirror has to update the textarea, it'll re-create the
|
|
||||||
selection as an 'upside-up' selection, with the anchor at the top, and
|
|
||||||
the next cursor motion will behave in an unexpected way—our second
|
|
||||||
up-arrow press in the example above will not do anything, since it is
|
|
||||||
interpreted in exactly the same way as the first.</p>
|
|
||||||
|
|
||||||
<p>No problem. We'll just, ehm, detect that the selection is
|
|
||||||
upside-down (you can tell by the way it was created), and then, when
|
|
||||||
an upside-down selection is present, and a cursor-moving key is
|
|
||||||
pressed in combination with shift, we quickly collapse the selection
|
|
||||||
in the textarea to its start, allow the key to take effect, and then
|
|
||||||
combine its new head with its old anchor to get the <em>real</em>
|
|
||||||
selection.</p>
|
|
||||||
|
|
||||||
<p>In short, scary hacks could not be avoided entirely in CodeMirror
|
|
||||||
2.</p>
|
|
||||||
|
|
||||||
<p>And, the observant reader might ask, how do you even know that a
|
|
||||||
key combo is a cursor-moving combo, if you claim you support any
|
|
||||||
native key bindings? Well, we don't, but we can learn. The editor
|
|
||||||
keeps a set known cursor-movement combos (initialized to the
|
|
||||||
predictable defaults), and updates this set when it observes that
|
|
||||||
pressing a certain key had (only) the effect of moving the cursor.
|
|
||||||
This, of course, doesn't work if the first time the key is used was
|
|
||||||
for extending an inverted selection, but it works most of the
|
|
||||||
time.</p>
|
|
||||||
</section>
|
|
||||||
<section id="update">
|
|
||||||
<h2>Intelligent Updating</h2>
|
|
||||||
|
|
||||||
<p>One thing that always comes up when you have a complicated internal
|
|
||||||
state that's reflected in some user-visible external representation
|
|
||||||
(in this case, the displayed code and the textarea's content) is
|
|
||||||
keeping the two in sync. The naive way is to just update the display
|
|
||||||
every time you change your state, but this is not only error prone
|
|
||||||
(you'll forget), it also easily leads to duplicate work on big,
|
|
||||||
composite operations. Then you start passing around flags indicating
|
|
||||||
whether the display should be updated in an attempt to be efficient
|
|
||||||
again and, well, at that point you might as well give up completely.</p>
|
|
||||||
|
|
||||||
<p>I did go down that road, but then switched to a much simpler model:
|
|
||||||
simply keep track of all the things that have been changed during an
|
|
||||||
action, and then, only at the end, use this information to update the
|
|
||||||
user-visible display.</p>
|
|
||||||
|
|
||||||
<p>CodeMirror uses a concept of <em>operations</em>, which start by
|
|
||||||
calling a specific set-up function that clears the state and end by
|
|
||||||
calling another function that reads this state and does the required
|
|
||||||
updating. Most event handlers, and all the user-visible methods that
|
|
||||||
change state are wrapped like this. There's a method
|
|
||||||
called <code>operation</code> that accepts a function, and returns
|
|
||||||
another function that wraps the given function as an operation.</p>
|
|
||||||
|
|
||||||
<p>It's trivial to extend this (as CodeMirror does) to detect nesting,
|
|
||||||
and, when an operation is started inside an operation, simply
|
|
||||||
increment the nesting count, and only do the updating when this count
|
|
||||||
reaches zero again.</p>
|
|
||||||
|
|
||||||
<p>If we have a set of changed ranges and know the currently shown
|
|
||||||
range, we can (with some awkward code to deal with the fact that
|
|
||||||
changes can add and remove lines, so we're dealing with a changing
|
|
||||||
coordinate system) construct a map of the ranges that were left
|
|
||||||
intact. We can then compare this map with the part of the document
|
|
||||||
that's currently visible (based on scroll offset and editor height) to
|
|
||||||
determine whether something needs to be updated.</p>
|
|
||||||
|
|
||||||
<p>CodeMirror uses two update algorithms—a full refresh, where it just
|
|
||||||
discards the whole part of the DOM that contains the edited text and
|
|
||||||
rebuilds it, and a patch algorithm, where it uses the information
|
|
||||||
about changed and intact ranges to update only the out-of-date parts
|
|
||||||
of the DOM. When more than 30 percent (which is the current heuristic,
|
|
||||||
might change) of the lines need to be updated, the full refresh is
|
|
||||||
chosen (since it's faster to do than painstakingly finding and
|
|
||||||
updating all the changed lines), in the other case it does the
|
|
||||||
patching (so that, if you scroll a line or select another character,
|
|
||||||
the whole screen doesn't have to be
|
|
||||||
re-rendered). <span class="update">[the full-refresh
|
|
||||||
algorithm was dropped, it wasn't really faster than the patching
|
|
||||||
one]</span></p>
|
|
||||||
|
|
||||||
<p>All updating uses <code>innerHTML</code> rather than direct DOM
|
|
||||||
manipulation, since that still seems to be by far the fastest way to
|
|
||||||
build documents. There's a per-line function that combines the
|
|
||||||
highlighting, <a href="manual.html#markText">marking</a>, and
|
|
||||||
selection info for that line into a snippet of HTML. The patch updater
|
|
||||||
uses this to reset individual lines, the refresh updater builds an
|
|
||||||
HTML chunk for the whole visible document at once, and then uses a
|
|
||||||
single <code>innerHTML</code> update to do the refresh.</p>
|
|
||||||
</section>
|
|
||||||
<section id="parse">
|
|
||||||
<h2>Parsers can be Simple</h2>
|
|
||||||
|
|
||||||
<p>When I wrote CodeMirror 1, I
|
|
||||||
thought <a href="http://codemirror.net/story.html#parser">interruptable
|
|
||||||
parsers</a> were a hugely scary and complicated thing, and I used a
|
|
||||||
bunch of heavyweight abstractions to keep this supposed complexity
|
|
||||||
under control: parsers
|
|
||||||
were <a href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">iterators</a>
|
|
||||||
that consumed input from another iterator, and used funny
|
|
||||||
closure-resetting tricks to copy and resume themselves.</p>
|
|
||||||
|
|
||||||
<p>This made for a rather nice system, in that parsers formed strictly
|
|
||||||
separate modules, and could be composed in predictable ways.
|
|
||||||
Unfortunately, it was quite slow (stacking three or four iterators on
|
|
||||||
top of each other), and extremely intimidating to people not used to a
|
|
||||||
functional programming style.</p>
|
|
||||||
|
|
||||||
<p>With a few small changes, however, we can keep all those
|
|
||||||
advantages, but simplify the API and make the whole thing less
|
|
||||||
indirect and inefficient. CodeMirror
|
|
||||||
2's <a href="manual.html#modeapi">mode API</a> uses explicit state
|
|
||||||
objects, and makes the parser/tokenizer a function that simply takes a
|
|
||||||
state and a character stream abstraction, advances the stream one
|
|
||||||
token, and returns the way the token should be styled. This state may
|
|
||||||
be copied, optionally in a mode-defined way, in order to be able to
|
|
||||||
continue a parse at a given point. Even someone who's never touched a
|
|
||||||
lambda in his life can understand this approach. Additionally, far
|
|
||||||
fewer objects are allocated in the course of parsing now.</p>
|
|
||||||
|
|
||||||
<p>The biggest speedup comes from the fact that the parsing no longer
|
|
||||||
has to touch the DOM though. In CodeMirror 1, on an older browser, you
|
|
||||||
could <em>see</em> the parser work its way through the document,
|
|
||||||
managing some twenty lines in each 50-millisecond time slice it got. It
|
|
||||||
was reading its input from the DOM, and updating the DOM as it went
|
|
||||||
along, which any experienced JavaScript programmer will immediately
|
|
||||||
spot as a recipe for slowness. In CodeMirror 2, the parser usually
|
|
||||||
finishes the whole document in a single 100-millisecond time slice—it
|
|
||||||
manages some 1500 lines during that time on Chrome. All it has to do
|
|
||||||
is munge strings, so there is no real reason for it to be slow
|
|
||||||
anymore.</p>
|
|
||||||
</section>
|
|
||||||
<section id="summary">
|
|
||||||
<h2>What Gives?</h2>
|
|
||||||
|
|
||||||
<p>Given all this, what can you expect from CodeMirror 2?</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
|
|
||||||
<li><strong>Small.</strong> the base library is
|
|
||||||
some <span class="update">45k</span> when minified
|
|
||||||
now, <span class="update">17k</span> when gzipped. It's smaller than
|
|
||||||
its own logo.</li>
|
|
||||||
|
|
||||||
<li><strong>Lightweight.</strong> CodeMirror 2 initializes very
|
|
||||||
quickly, and does almost no work when it is not focused. This means
|
|
||||||
you can treat it almost like a textarea, have multiple instances on a
|
|
||||||
page without trouble.</li>
|
|
||||||
|
|
||||||
<li><strong>Huge document support.</strong> Since highlighting is
|
|
||||||
really fast, and no DOM structure is being built for non-visible
|
|
||||||
content, you don't have to worry about locking up your browser when a
|
|
||||||
user enters a megabyte-sized document.</li>
|
|
||||||
|
|
||||||
<li><strong>Extended API.</strong> Some things kept coming up in the
|
|
||||||
mailing list, such as marking pieces of text or lines, which were
|
|
||||||
extremely hard to do with CodeMirror 1. The new version has proper
|
|
||||||
support for these built in.</li>
|
|
||||||
|
|
||||||
<li><strong>Tab support.</strong> Tabs inside editable documents were,
|
|
||||||
for some reason, a no-go. At least six different people announced they
|
|
||||||
were going to add tab support to CodeMirror 1, none survived (I mean,
|
|
||||||
none delivered a working version). CodeMirror 2 no longer removes tabs
|
|
||||||
from your document.</li>
|
|
||||||
|
|
||||||
<li><strong>Sane styling.</strong> <code>iframe</code> nodes aren't
|
|
||||||
really known for respecting document flow. Now that an editor instance
|
|
||||||
is a plain <code>div</code> element, it is much easier to size it to
|
|
||||||
fit the surrounding elements. You don't even have to make it scroll if
|
|
||||||
you do not <a href="../demo/resize.html">want to</a>.</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>On the downside, a CodeMirror 2 instance is <em>not</em> a native
|
|
||||||
editable component. Though it does its best to emulate such a
|
|
||||||
component as much as possible, there is functionality that browsers
|
|
||||||
just do not allow us to hook into. Doing select-all from the context
|
|
||||||
menu, for example, is not currently detected by CodeMirror.</p>
|
|
||||||
|
|
||||||
<p id="changes" style="margin-top: 2em;"><span style="font-weight:
|
|
||||||
bold">[Updates from November 13th 2011]</span> Recently, I've made
|
|
||||||
some changes to the codebase that cause some of the text above to no
|
|
||||||
longer be current. I've left the text intact, but added markers at the
|
|
||||||
passages that are now inaccurate. The new situation is described
|
|
||||||
below.</p>
|
|
||||||
</section>
|
|
||||||
<section id="btree">
|
|
||||||
<h2>Content Representation</h2>
|
|
||||||
|
|
||||||
<p>The original implementation of CodeMirror 2 represented the
|
|
||||||
document as a flat array of line objects. This worked well—splicing
|
|
||||||
arrays will require the part of the array after the splice to be
|
|
||||||
moved, but this is basically just a simple <code>memmove</code> of a
|
|
||||||
bunch of pointers, so it is cheap even for huge documents.</p>
|
|
||||||
|
|
||||||
<p>However, I recently added line wrapping and code folding (line
|
|
||||||
collapsing, basically). Once lines start taking up a non-constant
|
|
||||||
amount of vertical space, looking up a line by vertical position
|
|
||||||
(which is needed when someone clicks the document, and to determine
|
|
||||||
the visible part of the document during scrolling) can only be done
|
|
||||||
with a linear scan through the whole array, summing up line heights as
|
|
||||||
you go. Seeing how I've been going out of my way to make big documents
|
|
||||||
fast, this is not acceptable.</p>
|
|
||||||
|
|
||||||
<p>The new representation is based on a B-tree. The leaves of the tree
|
|
||||||
contain arrays of line objects, with a fixed minimum and maximum size,
|
|
||||||
and the non-leaf nodes simply hold arrays of child nodes. Each node
|
|
||||||
stores both the amount of lines that live below them and the vertical
|
|
||||||
space taken up by these lines. This allows the tree to be indexed both
|
|
||||||
by line number and by vertical position, and all access has
|
|
||||||
logarithmic complexity in relation to the document size.</p>
|
|
||||||
|
|
||||||
<p>I gave line objects and tree nodes parent pointers, to the node
|
|
||||||
above them. When a line has to update its height, it can simply walk
|
|
||||||
these pointers to the top of the tree, adding or subtracting the
|
|
||||||
difference in height from each node it encounters. The parent pointers
|
|
||||||
also make it cheaper (in complexity terms, the difference is probably
|
|
||||||
tiny in normal-sized documents) to find the current line number when
|
|
||||||
given a line object. In the old approach, the whole document array had
|
|
||||||
to be searched. Now, we can just walk up the tree and count the sizes
|
|
||||||
of the nodes coming before us at each level.</p>
|
|
||||||
|
|
||||||
<p>I chose B-trees, not regular binary trees, mostly because they
|
|
||||||
allow for very fast bulk insertions and deletions. When there is a big
|
|
||||||
change to a document, it typically involves adding, deleting, or
|
|
||||||
replacing a chunk of subsequent lines. In a regular balanced tree, all
|
|
||||||
these inserts or deletes would have to be done separately, which could
|
|
||||||
be really expensive. In a B-tree, to insert a chunk, you just walk
|
|
||||||
down the tree once to find where it should go, insert them all in one
|
|
||||||
shot, and then break up the node if needed. This breaking up might
|
|
||||||
involve breaking up nodes further up, but only requires a single pass
|
|
||||||
back up the tree. For deletion, I'm somewhat lax in keeping things
|
|
||||||
balanced—I just collapse nodes into a leaf when their child count goes
|
|
||||||
below a given number. This means that there are some weird editing
|
|
||||||
patterns that may result in a seriously unbalanced tree, but even such
|
|
||||||
an unbalanced tree will perform well, unless you spend a day making
|
|
||||||
strangely repeating edits to a really big document.</p>
|
|
||||||
</section>
|
|
||||||
<section id="keymap">
|
|
||||||
<h2>Keymaps</h2>
|
|
||||||
|
|
||||||
<p><a href="#approach">Above</a>, I claimed that directly catching key
|
|
||||||
events for things like cursor movement is impractical because it
|
|
||||||
requires some browser-specific kludges. I then proceeded to explain
|
|
||||||
some awful <a href="#selection">hacks</a> that were needed to make it
|
|
||||||
possible for the selection changes to be detected through the
|
|
||||||
textarea. In fact, the second hack is about as bad as the first.</p>
|
|
||||||
|
|
||||||
<p>On top of that, in the presence of user-configurable tab sizes and
|
|
||||||
collapsed and wrapped lines, lining up cursor movement in the textarea
|
|
||||||
with what's visible on the screen becomes a nightmare. Thus, I've
|
|
||||||
decided to move to a model where the textarea's selection is no longer
|
|
||||||
depended on.</p>
|
|
||||||
|
|
||||||
<p>So I moved to a model where all cursor movement is handled by my
|
|
||||||
own code. This adds support for a goal column, proper interaction of
|
|
||||||
cursor movement with collapsed lines, and makes it possible for
|
|
||||||
vertical movement to move through wrapped lines properly, instead of
|
|
||||||
just treating them like non-wrapped lines.</p>
|
|
||||||
|
|
||||||
<p>The key event handlers now translate the key event into a string,
|
|
||||||
something like <code>Ctrl-Home</code> or <code>Shift-Cmd-R</code>, and
|
|
||||||
use that string to look up an action to perform. To make keybinding
|
|
||||||
customizable, this lookup goes through
|
|
||||||
a <a href="manual.html#option_keyMap">table</a>, using a scheme that
|
|
||||||
allows such tables to be chained together (for example, the default
|
|
||||||
Mac bindings fall through to a table named 'emacsy', which defines
|
|
||||||
basic Emacs-style bindings like <code>Ctrl-F</code>, and which is also
|
|
||||||
used by the custom Emacs bindings).</p>
|
|
||||||
|
|
||||||
<p>A new
|
|
||||||
option <a href="manual.html#option_extraKeys"><code>extraKeys</code></a>
|
|
||||||
allows ad-hoc keybindings to be defined in a much nicer way than what
|
|
||||||
was possible with the
|
|
||||||
old <a href="manual.html#option_onKeyEvent"><code>onKeyEvent</code></a>
|
|
||||||
callback. You simply provide an object mapping key identifiers to
|
|
||||||
functions, instead of painstakingly looking at raw key events.</p>
|
|
||||||
|
|
||||||
<p>Built-in commands map to strings, rather than functions, for
|
|
||||||
example <code>"goLineUp"</code> is the default action bound to the up
|
|
||||||
arrow key. This allows new keymaps to refer to them without
|
|
||||||
duplicating any code. New commands can be defined by assigning to
|
|
||||||
the <code>CodeMirror.commands</code> object, which maps such commands
|
|
||||||
to functions.</p>
|
|
||||||
|
|
||||||
<p>The hidden textarea now only holds the current selection, with no
|
|
||||||
extra characters around it. This has a nice advantage: polling for
|
|
||||||
input becomes much, much faster. If there's a big selection, this text
|
|
||||||
does not have to be read from the textarea every time—when we poll,
|
|
||||||
just noticing that something is still selected is enough to tell us
|
|
||||||
that no new text was typed.</p>
|
|
||||||
|
|
||||||
<p>The reason that cheap polling is important is that many browsers do
|
|
||||||
not fire useful events on IME (input method engine) input, which is
|
|
||||||
the thing where people inputting a language like Japanese or Chinese
|
|
||||||
use multiple keystrokes to create a character or sequence of
|
|
||||||
characters. Most modern browsers fire <code>input</code> when the
|
|
||||||
composing is finished, but many don't fire anything when the character
|
|
||||||
is updated <em>during</em> composition. So we poll, whenever the
|
|
||||||
editor is focused, to provide immediate updates of the display.</p>
|
|
||||||
|
|
||||||
</article>
|
|
||||||
|
Before Width: | Height: | Size: 9.1 KiB |
@@ -1,181 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
id="svg2"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.4 r9939"
|
|
||||||
width="640"
|
|
||||||
height="640"
|
|
||||||
xml:space="preserve"
|
|
||||||
sodipodi:docname="logo.svg"
|
|
||||||
inkscape:export-filename="/home/marijn/src/js/codemirror/doc/logo.png"
|
|
||||||
inkscape:export-xdpi="16.601332"
|
|
||||||
inkscape:export-ydpi="16.601332"><metadata
|
|
||||||
id="metadata8"><rdf:RDF><cc:Work
|
|
||||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
|
||||||
id="defs6"><clipPath
|
|
||||||
clipPathUnits="userSpaceOnUse"
|
|
||||||
id="clipPath16"><path
|
|
||||||
d="M 0,512 512,512 512,0 0,0 0,512 z"
|
|
||||||
id="path18" /></clipPath><clipPath
|
|
||||||
clipPathUnits="userSpaceOnUse"
|
|
||||||
id="clipPath40"><path
|
|
||||||
d="m 435.607,369.899 31.242,0 0,-64.782 -31.242,0 0,64.782 z"
|
|
||||||
id="path42" /></clipPath><clipPath
|
|
||||||
clipPathUnits="userSpaceOnUse"
|
|
||||||
id="clipPath56"><path
|
|
||||||
d="m 421.796,349.477 39.074,0 0,-88.423 -39.074,0 0,88.423 z"
|
|
||||||
id="path58" /></clipPath></defs><sodipodi:namedview
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1"
|
|
||||||
objecttolerance="10"
|
|
||||||
gridtolerance="10"
|
|
||||||
guidetolerance="10"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:window-width="1600"
|
|
||||||
inkscape:window-height="875"
|
|
||||||
id="namedview4"
|
|
||||||
showgrid="false"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:guide-bbox="true"
|
|
||||||
inkscape:zoom="0.52149125"
|
|
||||||
inkscape:cx="303.572"
|
|
||||||
inkscape:cy="574.48012"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="25"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="g10" /><g
|
|
||||||
id="g10"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
inkscape:label="2014-10_codeMirror_logo_vectors"
|
|
||||||
transform="matrix(1.25,0,0,-1.25,0,640)"><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path22"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 233.97976,469.37438 c 0,0 7.01353,-14.94848 -2.94916,-31.42373 -4.97925,-8.23417 -130.50847,-34.94915 -179.50847,-102.94915 -30,-47 -76,-183 71,-273 66,-34 94,-33 94,-33 0,0 -44,31 -16,52 28,21 69,31 80,60 13,-10 34,-31 54,-29 -2,13 -7,18 9,20 16,2 24,2 24,2 0,0 -15,12 -32,13 -17,1 -49,34 -48,48 21,12 48,32 64,26 16,-6 32,-16 35,-25 0,-6 -3,-16 10,-8 13,8 10,13 15,24 5,11 6,13 -5,22 -11,9 -37,30 -58,24 -21,-6 -65,-23 -87,-2 9,20 23,52 16,74 13,10 28,21 30,39 15,2 47,11 41,27 -6,16 -48.59322,87.16949 -113.59322,73.16949"
|
|
||||||
sodipodi:nodetypes="cscccsccscscscsssscccsc" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path26"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 441.52213,306.0015 c 11,29 29,78 12,80 -17,2 -36,-44 -41,-56 -5,-12 -25,-72 -14,-80 11,-8 43,56 43,56" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path30"
|
|
||||||
style="fill:#da687d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 348.52213,384.0015 c 3.13,4.919 5.82086,0.64508 -7.67914,-0.35492 -13.5,-1 -29.62196,-5.18461 -32.38899,-11.04836 -5.19174,-11.00208 -6.93187,-38.09672 -26.43187,-44.09672 -1,-7 0,-23 27.5,-26 27.5,-3 28.5,15 44.5,14.5 16,-0.5 14.5,5.5 9,10 -5.5,4.5 -24.5,35 -24.5,45 0,10 6.5,6.5 10,12"
|
|
||||||
sodipodi:nodetypes="csscssssc" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path34"
|
|
||||||
style="fill:#da687d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 103.02213,82.502 c 0,0 -8.5,22.5 16.5,34.5 25,12 47.5,2.5 52,-6 4.5,-8.5 -7.5,-42.5 -50.5,-43 -10.5,8.5 -18,14.5 -18,14.5" /><g
|
|
||||||
id="g38"
|
|
||||||
transform="translate(-21.47687,0)" /><g
|
|
||||||
id="g44"
|
|
||||||
transform="translate(-21.47687,0)"><g
|
|
||||||
style="opacity:0.69999701"
|
|
||||||
id="g46"
|
|
||||||
clip-path="url(#clipPath40)"><g
|
|
||||||
id="g48"
|
|
||||||
transform="translate(466.2583,369.8384)"><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path50"
|
|
||||||
style="fill:#da687d;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
|
||||||
d="M 0,0 C 0.423,-1.569 0.298,-3.199 0.255,-4.838 0.213,-6.452 0.062,-8.15 -0.349,-9.801 c 0.106,-0.377 -0.082,-0.814 -0.018,-1.201 -0.41,-0.515 -0.194,-0.903 -0.284,-1.354 0.661,-0.674 1.522,-1.313 1.152,-2.162 -0.259,-0.596 -0.874,-0.706 -1.464,-0.995 -0.389,-1.403 -0.709,-3.099 -1.028,-4.649 -0.097,-0.476 -0.044,-1.051 -0.187,-1.485 -0.334,-1.01 -0.691,-1.978 -0.971,-3.09 -0.237,-0.945 0.034,-2.689 -1.063,-2.811 -0.423,-1.049 -0.663,-1.841 -1.165,-2.83 -0.286,-0.163 -0.452,0.106 -0.692,0.009 -0.305,-0.348 -0.294,-0.823 -0.577,-1.114 -0.222,-0.229 -0.503,-0.163 -0.665,-0.385 -0.363,-0.5 -0.266,-1.24 -0.523,-1.902 -0.468,-0.4 -0.862,-0.905 -1.147,-1.478 -0.588,-1.179 -0.698,-2.681 -1.591,-3.593 -0.28,-0.286 -0.761,-0.365 -1.011,-0.647 -0.238,-0.269 -0.455,-0.665 -0.689,-0.98 -0.338,-0.452 -0.669,-1.045 -0.972,-1.583 -1.004,-1.787 -2.383,-3.71 -3.301,-5.664 -0.173,-0.369 -0.199,-0.805 -0.364,-1.165 -0.381,-0.827 -0.943,-1.579 -1.257,-2.333 -0.516,-1.239 -1.31,-3.339 -2.538,-4.42 -0.149,-0.131 -0.473,-0.254 -0.606,-0.414 -0.179,-0.215 -0.136,-0.568 -0.32,-0.808 -0.086,-0.113 -0.4,-0.164 -0.537,-0.302 -0.208,-0.211 -0.306,-0.481 -0.479,-0.639 -0.426,-0.388 -1.015,-0.555 -1.381,-0.959 -0.277,-0.306 -0.397,-0.743 -0.692,-1.127 -0.318,-0.413 -0.761,-0.784 -1.09,-1.202 -0.994,-1.264 -1.38,-2.8 -2.702,-3.396 -0.393,-0.178 -0.88,-0.12 -1.291,-0.241 -0.374,0.344 -0.078,0.818 -0.163,1.164 -0.055,0.222 -0.285,0.382 -0.346,0.583 -0.143,0.474 -0.347,1.336 -0.34,1.878 0.007,0.538 0.305,0.971 0.375,1.612 0.061,0.549 -0.137,1.246 -0.177,1.856 -0.021,0.306 0.064,0.624 0.059,0.956 -0.008,0.533 -0.066,0.801 0.008,1.442 0.086,0.743 -0.074,1.462 -0.171,2.152 0.342,1.705 0.531,3.008 1.09,4.919 0.258,0.881 0.721,2.367 1.18,3.346 0.886,1.895 1.64,3.964 2.6,5.945 0.319,0.656 0.825,1.196 1.139,1.852 0.182,0.381 0.211,0.828 0.395,1.215 1.617,3.398 3.877,6.233 5.565,9.731 1.399,2.859 2.88,5.418 4.745,8.545 0.842,1.415 1.568,2.917 2.434,4.086 0.66,0.891 1.632,2.413 2.334,3.916 0.278,0.596 0.269,1.073 1.005,1.102 0.758,0.948 1.326,2.018 2.119,2.824 0.2,0.202 0.51,0.303 0.733,0.498 0.26,0.228 0.383,0.57 0.638,0.778 0.541,0.441 1.432,0.832 2.035,1.659 0.16,0.22 0.229,0.451 0.406,0.682 0.414,0.539 1.191,1.866 1.81,2.013 C -0.241,0.085 -0.126,0.061 0,0" /></g></g></g><g
|
|
||||||
id="g54"
|
|
||||||
transform="translate(-21.47687,0)" /><g
|
|
||||||
id="g60"
|
|
||||||
transform="translate(-21.47687,0)"><g
|
|
||||||
style="opacity:0.69999701"
|
|
||||||
id="g62"
|
|
||||||
clip-path="url(#clipPath56)"><g
|
|
||||||
id="g64"
|
|
||||||
transform="translate(459.8965,349.4487)"><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path66"
|
|
||||||
style="fill:#da687d;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
|
||||||
d="m 0,0 c 0.688,-1.936 0.765,-4.106 0.935,-6.266 -0.019,-2.14 -0.168,-4.579 -0.715,-6.943 0.098,-0.492 -0.155,-1.108 -0.109,-1.623 -0.519,-0.752 -0.295,-1.25 -0.438,-1.876 0.718,-0.835 1.666,-1.609 1.155,-2.836 -0.37,-0.846 -1.118,-1.037 -1.845,-1.479 -0.64,-1.905 -1.226,-4.263 -1.846,-6.305 -0.187,-0.635 -0.212,-1.395 -0.447,-1.977 -0.547,-1.362 -1.111,-2.656 -1.597,-4.101 -0.416,-1.238 -0.356,-3.498 -1.652,-3.689 -0.61,-1.355 -0.978,-2.373 -1.674,-3.651 -0.35,-0.217 -0.512,0.119 -0.801,-0.013 -0.392,-0.456 -0.442,-1.063 -0.795,-1.445 -0.269,-0.298 -0.585,-0.226 -0.785,-0.514 -0.449,-0.651 -0.386,-1.58 -0.723,-2.425 -0.282,-0.266 -0.546,-0.564 -0.784,-0.888 -0.119,-0.162 -0.233,-0.33 -0.337,-0.505 l -0.153,-0.266 -0.072,-0.136 -0.034,-0.069 -0.003,-0.004 0,-10e-4 c 0.099,0.238 0.028,0.066 0.05,0.119 l -10e-4,-0.002 -0.001,-10e-4 -0.004,-0.01 -0.008,-0.019 -0.016,-0.037 c -0.697,-1.635 -0.851,-3.63 -1.895,-4.955 -0.335,-0.421 -0.872,-0.577 -1.142,-0.971 -0.259,-0.375 -0.491,-0.912 -0.746,-1.347 -0.366,-0.625 -0.722,-1.432 -1.046,-2.164 -1.085,-2.456 -2.571,-5.274 -3.572,-8.03 -0.188,-0.523 -0.205,-1.106 -0.385,-1.617 -0.422,-1.173 -1.022,-2.273 -1.394,-3.342 -0.626,-1.753 -1.474,-4.727 -3.01,-6.377 -0.182,-0.2 -0.567,-0.415 -0.732,-0.65 -0.22,-0.315 -0.191,-0.786 -0.42,-1.137 -0.106,-0.164 -0.475,-0.275 -0.642,-0.48 -0.254,-0.313 -0.383,-0.69 -0.594,-0.926 -0.503,-0.581 -1.23,-0.865 -1.714,-1.438 -0.365,-0.435 -0.562,-1.029 -0.958,-1.568 -0.426,-0.578 -0.991,-1.104 -1.428,-1.683 -0.65,-0.928 -1.251,-1.786 -1.828,-2.608 -0.592,-0.813 -1.215,-1.514 -2.047,-1.884 -0.495,-0.219 -1.042,-0.12 -1.539,-0.256 -0.353,0.473 0.086,1.071 0.061,1.524 -0.018,0.288 -0.25,0.504 -0.28,0.766 -0.07,0.615 -0.141,1.712 -0.035,2.387 0.099,0.676 0.548,1.191 0.712,2.005 0.125,0.708 -0.034,1.591 -0.025,2.359 0.004,0.387 0.13,0.791 0.153,1.206 0.038,0.668 -0.008,0.999 0.13,1.795 0.163,0.922 -0.034,1.854 -0.121,2.709 0.426,2.191 0.686,3.806 1.265,6.362 0.273,1.176 0.786,3.104 1.265,4.488 0.472,1.315 0.904,2.681 1.347,4.063 0.445,1.4 0.906,2.841 1.424,4.249 0.347,0.939 0.896,1.734 1.274,2.728 0.213,0.565 0.249,1.192 0.465,1.767 0.475,1.25 0.99,2.514 1.541,3.656 0.553,1.123 1.13,2.228 1.711,3.336 l 0.938,1.807 c 0.326,0.58 0.653,1.161 0.981,1.745 0.649,1.172 1.283,2.367 1.886,3.609 1.027,1.966 2.073,3.828 3.188,5.725 1.116,1.844 2.324,3.757 3.629,5.817 1.158,1.853 2.248,3.825 3.357,5.355 0.827,1.167 2.173,3.163 3.042,5.126 0.342,0.78 0.349,1.38 1.197,1.482 0.907,1.274 1.649,2.697 2.452,3.773 0.214,0.276 0.563,0.445 0.808,0.722 0.286,0.323 0.408,0.762 0.693,1.065 0.582,0.653 1.672,1.277 2.21,2.569 0.151,0.332 0.198,0.653 0.368,1.006 0.397,0.822 1.098,2.779 1.78,3.145 C -0.284,0.044 -0.151,0.044 0,0" /></g></g></g><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path70"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 416.68863,327.0015 c 0,0 -8,-30.667 -4.667,-56 0.667,8 4.667,56 4.667,56" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path74"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 426.18913,347.7256 c -0.61,2.147 -4.597,-59.478 -3.432,-61.636 1.166,-2.159 7.147,48.575 3.432,61.636" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path78"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 235.24913,465.60369 c 0,0 4.667,-26.6198 -38.667,-40.6198 -43.333,-14 -103.0605,-25.98239 -147.0605,-78.64939 -44.0000004,-52.666 -52.0000004,-139.999 -22,-197.333 30,-57.333 103.333,-128.667 235.333,-128.667 132,0 236.85312,101.50582 236.85312,171.50582 0,36.667 -20.1469,28.4918 -27.11433,-5.90828 C 466.30468,154.88286 408.18863,39.0015 262.18863,39.0015 c -146,0 -220.667,88.667 -230,164.667 -9.334,76 11.898969,141.46925 88.56597,180.80225 76.667,39.334 125.32039,23.66435 114.65339,80.99735"
|
|
||||||
sodipodi:nodetypes="cssssssscsc" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path82"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 198.85713,260.335 c 0,0 -8.667,-40.001 -50.667,-59.333 -42,-19.334 -60,-30 -66,-63.334 16,26.666 62.667,32 88.667,58 26,26 28,64.667 28,64.667" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path86"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 210.19013,353.0015 c 0,0 36,-46.667 78.667,-24 42.666,22.667 20.667,75.333 20,78.667 -0.667,3.333 4.666,-58.667 -27.334,-69.334 -32,-10.666 -71.333,14.667 -71.333,14.667" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path90"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 116.18913,74.3359 c 0,0 22.666,-1.334 39.333,17.332 16.667,18.668 7.334,48 34.667,58.668 27.333,10.666 46,4 46,4 0,0 -48.667,-6.668 -52.667,-34.668 -4,-28 -10.666,-40.666 -21.333,-49.332 -10.667,-8.668 -24.667,-10 -24.667,-10 l -21.333,14 z" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path94"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 219.02213,219.502 c 0,0 40.523,6.783 59,48 15.167,33.833 5,63 5,63 l -20.5,-3 c 0,0 8.5,-24.5 2,-46.5 -6.5,-22 -21.5,-47.5 -45.5,-61.5" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path98"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 437.13303,313.1621 c -14.461,-36.13 -35.773,-62.068 -38.265,-60.674 -4.494,2.513 -0.358,34.036 14.104,70.166 14.46,36.13 32.432,63.635 39.104,61.014 6.672,-2.621 -0.483,-34.376 -14.943,-70.506 m 20.999,72.506 c -16.442,8.934 -36.644,-24.449 -53.276,-63.334 -16.633,-38.885 -18.542,-70.229 -5.759,-75.836 17.092,-7.496 33.127,22.285 49.759,61.17 16.632,38.885 24,70 9.276,78" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path102"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 159.52163,189.668 c 0,0 10.331,-31.037 62,-24.666 48.667,6 69.59,24.744 99.333,43.334 21.334,13.332 20,7.332 22.667,6.666 2.667,-0.666 14.667,-8 27.333,-6.666 0.667,-6.668 -5.999,-1.334 -8.666,-7.334 -1.333,-4 10.12,-22.824 26.666,-20 27.334,4.666 19.667,16 25.001,28.666 5.333,12.666 9,19.334 -17.667,37.334 -20.667,18.666 -32,13.999 -42,13.999 -10,0 -36,-13.999 -54,-10.666 -18,3.333 -29.334,10 -29.334,10 l -11.999,-13.333 c 0,0 21.999,-16.666 47.333,-10.666 25.333,6 44.001,25.332 66.001,15.332 22,-10 26.282,-16.701 32.999,-21.666 7.667,-5.668 8.333,-11.666 3,-17 -5.334,-5.334 0.001,-9.334 -3.332,-15.334 -3.334,-6 -20,-8.666 -20,-8.666 0,0 18.273,23.477 -4,25.332 -16,1.334 -26,22.668 -48.667,11.334 -32.55,-16.277 -78.668,-44 -110.668,-47.332 -31.193,-3.248 -42.667,6.666 -50.667,25.332 -9.333,-8 -11.333,-14 -11.333,-14" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path106"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 274.18863,183.002 c 0,0 22.667,-12 16,-38 -6.667,-26 -36.667,-44 -56,-52.668 -19.333,-8.666 -33.743,-20.127 -19.333,-27.332 12,-6 18.667,9.334 36,12 17.333,2.666 32.667,-4 34,-14 -7.334,4 -12.667,4 -12.667,4 0,0 6,-4 6.667,-10.668 0.666,-6.666 -0.667,-3.332 -4.667,-3.332 -10,0 -11.333,8.666 -20,7.332 -22,-2 -23.333,-11.334 -35.333,-12.666 -12,-1.334 -32,5.334 -29.334,20.666 2.667,15.334 23.334,26 42.667,34 19.333,8 48.667,33.334 44.667,56 -4,22.668 -21.334,18 -21.334,18 l 18.667,6.668 z" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path110"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 331.02213,371.7515 c 0,0 9.5,-4.75 15.5,-28.75 4,-8.667 9.333,-15.667 14,-17.667 4.667,-2 -2,-4 -5.333,-3.333 -3.334,0.667 -10.334,3.667 -15,-0.333 -4.667,-4 -16,-14.667 -32,-12 -16,2.666 -29.667,12.833 -29.667,12.833 0,0 6,-26.5 41.667,-24.833 24.721,1.155 19.333,14 36,16.666 16.666,2.667 14.893,11.089 11.333,18 -5.667,11 -23.333,13.667 -25.333,45.834 -2,3.333 -14.5,-0.417 -11.167,-6.417" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path114"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 388.01383,204.4707 c 1.506,-1.477 -11.825,-31.469 -11.825,-31.469 0,0 -2.667,-7.334 -9.814,-4.75 -7.311,2.645 -5.413,7.948 -5.413,7.948 l 17.026,30.837 c 0,0 9.353,-1.906 10.026,-2.566" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path118"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 406.74623,247.168 c -0.667,-2 -3.333,-10 -3.333,-10 l -10.891,8.334 2.891,6.332 11.333,-4.666 z" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path122"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 284.85563,189.002 c -2,-7.334 23.333,-50.002 40.667,-47.334 17.333,2.666 19.999,-2.668 14.666,-6 -5.333,-3.334 -14.666,-4.668 -13.333,-9.334 1.333,-4.666 5,-9.334 -3.667,-8 -8.666,1.334 -26.333,10.668 -37,28.668 -3.333,-10.668 -4.666,-14 -4.666,-14 0,0 34,-35.334 68.666,-20.668 -6,4.668 -22.666,3.334 -8.666,11.334 14,8 24.666,10.666 31.333,-2 3.333,0.666 3.333,30 -40.667,28 -15.333,2 -36,32 -36,47.334 -4,-4 -9.333,-0.666 -11.333,-8" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path126"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 420.44553,336.5015 c 0,0 -8.75,-26.286 -5.104,-48 0.729,6.857 5.104,48 5.104,48" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path130"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 429.40543,352.0503 c -0.444,1.66 -4.07,-45.761 -3.203,-47.435 0.868,-1.673 5.909,37.339 3.203,47.435" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path134"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 312.85513,378.335 c 0,0 37.667,3.333 31,18.333 -20.105,45.239 -58.333,71.667 -129,69 40,16 74.00021,14.00025 106.667,-14 16.33311,-13.99988 23.89324,-31.04069 29.74979,-44.08296 9.34044,-20.80074 6.58914,-22.74696 -3.74979,-28.58304 -12.56847,-7.0946 -34.191,-2.57 -34.667,-0.667"
|
|
||||||
sodipodi:nodetypes="cccsssc" /><path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path138"
|
|
||||||
style="fill:#2d2b2c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
|
||||||
d="m 316.7084,372.58242 c 0,0 10.36415,-7.13802 18.50215,-1.32602 3.74086,3.84884 6.23323,5.95026 -4.37137,5.51213 l -12.90479,0.52875 c -8.94116,1.82452 -8.7647,-0.93753 -1.22599,-4.71486 z"
|
|
||||||
sodipodi:nodetypes="ccccc" /></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 17 KiB |