Streamlined the libraries.

This commit is contained in:
Bruce
2026-04-14 16:09:13 +08:00
parent 3b790c3503
commit 686e08199c
378 changed files with 72 additions and 135793 deletions

66
FindWinJS.ps1 Normal file
View 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
}

Binary file not shown.

View 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,8 +0,0 @@
*.txt text
*.js text
*.html text
*.md text
*.json text
*.yml text
*.css text
*.svg text

View File

@@ -1,8 +0,0 @@
/node_modules
/npm-debug.log
/test*.html
.tern-*
*~
*.swp
.idea
*.iml

View File

@@ -1,3 +0,0 @@
language: node_js
node_js:
- 0.10

View File

@@ -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.

View File

@@ -1,12 +0,0 @@
# CodeMirror
[![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
[![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)
[Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png)](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)

View File

@@ -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%;
}

View File

@@ -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;
});
});

View File

@@ -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; }

View File

@@ -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&nbsp;&nbsp;\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; }
});

View File

@@ -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"));
});
};
});

View File

@@ -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};
}
};
};
});

View File

@@ -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 $]");
})();

View File

@@ -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);
}
};
};
});

View File

@@ -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];
};
}
});

View File

@@ -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";
}
};
});

View File

@@ -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;
}
}
};
})();

View File

@@ -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;
}
}
};
});

View File

@@ -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")];

View File

@@ -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);
};
});

View File

@@ -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();
}
}
});

View File

@@ -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%;
}

View File

@@ -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);
};
});

View File

@@ -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);
}
});

View File

@@ -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);
}
}
}
});

View File

@@ -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;
}
});

View File

@@ -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; }

View File

@@ -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); };
}
});

View File

@@ -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}); }
};

View File

@@ -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;
});
});

View File

@@ -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"
]
}

View File

@@ -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 &#8212; they're springing up like mushrooms. This one
uses CodeMirror as its editor.</title>
<description>codemirror: http://cloud-ide.com &#8212; 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>
&nbsp; &nbsp; <button onclick="newBuf('top')">New buffer</button>
</div>
<div id=code_bot></div>
<div>
Select buffer: <select id=buffers_bot></select>
&nbsp; &nbsp; <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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;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>&lt;&lt;
>></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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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="&amp;quot;bar&amp;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>

View File

@@ -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>

View File

@@ -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&lt;string&gt;</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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
});
})();

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More