You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by je...@apache.org on 2015/07/08 11:58:36 UTC
[01/21] allura git commit: [#7897] ticket:804 Show preview using
Allura's syntax
Repository: allura
Updated Branches:
refs/heads/ib/7897 [created] 022cd7a7e
[#7897] ticket:804 Show preview using Allura's syntax
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/f9d0f807
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/f9d0f807
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/f9d0f807
Branch: refs/heads/ib/7897
Commit: f9d0f807abf71f3bc31e2fedd2734d6f1114fec9
Parents: 677cb54
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jun 18 17:47:38 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 10:26:09 2015 +0300
----------------------------------------------------------------------
.../lib/widgets/resources/js/sf_markitup.js | 55 +++++++++++++++++---
1 file changed, 49 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/f9d0f807/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index f57fb4b..b10e331 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -28,12 +28,13 @@ $(window).load(function() {
var $help_contents = $('div.markdown_help_contents', $container);
var toolbar = Editor.toolbar;
- toolbar[11] = {name: 'info', action: show_help},
- toolbar[12] = {name: 'preview', action: show_preview},
- new Editor({
+ toolbar[11] = {name: 'info', action: show_help};
+ toolbar[12] = {name: 'preview', action: show_preview};
+ var editor = new Editor({
element: $textarea[0],
toolbar: toolbar
- }).render();
+ });
+ editor.render();
function show_help() {
$help_contents.html('Loading...');
@@ -42,7 +43,7 @@ $(window).load(function() {
var display_section = function(evt) {
var $all_sections = $('.markdown_syntax_section', $help_contents);
var $this_section = $(location.hash.replace('#', '.'), $help_contents);
- if ($this_section.length == 0) {
+ if ($this_section.length === 0) {
$this_section = $('.md_ex_toc', $help_contents);
}
$all_sections.addClass('hidden_in_modal');
@@ -56,7 +57,49 @@ $(window).load(function() {
}
function show_preview() {
- console.log('preview');
+ /*
+ * This is pretty much the same as original Editor.togglePreview,
+ * but rendered text is fetched from the server.
+ * https://github.com/lepture/editor/blob/0f493bfdc7c3014ee7ac656f41b5b52f8955b2e9/src/intro.js#L216-L242
+ */
+ var toolbar = editor.toolbar.preview;
+ var cm = editor.codemirror;
+ var wrapper = cm.getWrapperElement();
+ var preview = wrapper.lastChild;
+ if (!/editor-preview/.test(preview.className)) {
+ preview = document.createElement('div');
+ preview.className = 'editor-preview';
+ wrapper.appendChild(preview);
+ }
+ if (/editor-preview-active/.test(preview.className)) {
+ preview.className = preview.className.replace(
+ /\s*editor-preview-active\s*/g, ''
+ );
+ toolbar.className = toolbar.className.replace(/\s*active\s*/g, '');
+ } else {
+ /* When the preview button is clicked for the first time,
+ * give some time for the transition from editor.css to fire and the view to slide from right to left,
+ * instead of just appearing.
+ */
+ setTimeout(function() {preview.className += ' editor-preview-active';}, 1);
+ toolbar.className += ' active';
+ }
+ get_rendered_text(preview, cm.getValue());
+ }
+
+ function get_rendered_text(preview, text) {
+ preview.innerHTML = 'Loading...';
+ var cval = $.cookie('_session_id');
+ $.post('/nf/markdown_to_html', {
+ markdown: text,
+ project: $('input.markdown_project', $container).val(),
+ neighborhood: $('input.markdown_neighborhood', $container).val(),
+ app: $('input.markdown_app', $container).val(),
+ _session_id: cval
+ },
+ function(resp) {
+ preview.innerHTML = resp;
+ });
}
$('.close', $help_area).bind('click', function() {
[20/21] allura git commit: [#7897] ticket:814 Resize editor container
immediately after render
Posted by je...@apache.org.
[#7897] ticket:814 Resize editor container immediately after render
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/f6dae268
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/f6dae268
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/f6dae268
Branch: refs/heads/ib/7897
Commit: f6dae2688cd0bcb20c23dea1e7c561d0f00851e6
Parents: da510f2
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 18:47:59 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 18:47:59 2015 +0300
----------------------------------------------------------------------
.../allura/lib/widgets/resources/js/sf_markitup.js | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/f6dae268/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index f3466bc..91d63ca 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -51,17 +51,21 @@ $(window).load(function() {
toolbar: toolbar
});
var cm = editor.codemirror;
- cm.on('viewportChange', function(cm, from, to) {
+ cm.on('viewportChange', resize);
+ editor.render();
+ // trigger resize to properly display editor in case of a lot of text in the textarea
+ resize(cm);
+
+ // focus editor by clicking anywhere on it, not only on the first few lines
+ $('.CodeMirror').click(function () { this.CodeMirror.focus(); });
+
+ function resize(cm) {
var toolbar_h = $('.editor-toolbar', $container).outerHeight();
var statusbar_h = $('.editor-statusbar', $container).outerHeight();
var cm_h = cm.getScrollInfo().clientHeight;
var h = toolbar_h + statusbar_h + cm_h;
$container.height(h);
- });
- editor.render();
-
- // focus editor by clicking anywhere on it, not only on the first few lines
- $('.CodeMirror').click(function () { this.CodeMirror.focus(); });
+ }
function show_help(editor) {
$help_contents.html('Loading...');
[14/21] allura git commit: [#7897] ticket:814 Fix editor styles for
wiki
Posted by je...@apache.org.
[#7897] ticket:814 Fix editor styles for wiki
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/92b65360
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/92b65360
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/92b65360
Branch: refs/heads/ib/7897
Commit: 92b65360d795979504db7048d13d0335b3bb4780
Parents: 5e07e7a
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 17:16:58 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 17:16:58 2015 +0300
----------------------------------------------------------------------
ForgeWiki/forgewiki/templates/wiki/page_edit.html | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/92b65360/ForgeWiki/forgewiki/templates/wiki/page_edit.html
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/templates/wiki/page_edit.html b/ForgeWiki/forgewiki/templates/wiki/page_edit.html
index bdd35c6..c9596b7 100644
--- a/ForgeWiki/forgewiki/templates/wiki/page_edit.html
+++ b/ForgeWiki/forgewiki/templates/wiki/page_edit.html
@@ -25,8 +25,13 @@
{% block extra_css %}
<style type="text/css">
- textarea[name="text"]{
+ .markdown_edit {
height: 600px;
+ min-height: 600px;
+ }
+ .markdown_edit .CodeMirror {
+ height: auto;
+ min-height: 520px;
}
</style>
{% endblock %}
@@ -85,7 +90,6 @@
{% block wiki_extra_js %}
<script type="text/javascript">
/*<![CDATA[*/
- $('textarea.auto_resize').autosize();
$('span.removable').click(function(e){
var vals = $('#page_edit_form').serialize();
var del_name = $('input', this)[0].name.replace('.id','.delete');
[16/21] allura git commit: [#7897] ticket:814 Make editor background
white by default
Posted by je...@apache.org.
[#7897] ticket:814 Make editor background white by default
It's transparent by default, and some pages are displaying it on grey
background (e.g. ticket edit/create)
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/9b515adc
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/9b515adc
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/9b515adc
Branch: refs/heads/ib/7897
Commit: 9b515adc475e5cb49e2825c81747ed1bbcfb6549
Parents: eb627a9
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 17:36:08 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 17:36:08 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/resources/css/markitup_sf.css | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/9b515adc/Allura/allura/lib/widgets/resources/css/markitup_sf.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markitup_sf.css b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
index 5310c69..5e85697 100644
--- a/Allura/allura/lib/widgets/resources/css/markitup_sf.css
+++ b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
@@ -36,6 +36,7 @@
margin-bottom: 5px;
margin-left: 2px;
border: 1px solid #aaaaaa;
+ background: white;
}
.markdown_edit .CodeMirror {
[06/21] allura git commit: [#7897] ticket:804 Add lepture/editor to
MarkdownEdit
Posted by je...@apache.org.
[#7897] ticket:804 Add lepture/editor to MarkdownEdit
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ab2b11e0
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ab2b11e0
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ab2b11e0
Branch: refs/heads/ib/7897
Commit: ab2b11e0c95222242c981265826abe455a144be8
Parents: ffba721
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jun 18 15:16:54 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 10:26:09 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/form_fields.py | 3 +
.../resources/css/markdown_editor/editor.css | 421 +
.../css/markdown_editor/fonts/icomoon.dev.svg | 56 +
.../css/markdown_editor/fonts/icomoon.eot | Bin 0 -> 3440 bytes
.../css/markdown_editor/fonts/icomoon.svg | 56 +
.../css/markdown_editor/fonts/icomoon.ttf | Bin 0 -> 3276 bytes
.../css/markdown_editor/fonts/icomoon.woff | Bin 0 -> 3540 bytes
.../resources/js/markdown_editor/editor.js | 7395 ++++++++++++++++++
.../resources/js/markdown_editor/marked.js | 1165 +++
.../lib/widgets/resources/js/sf_markitup.js | 3 +
10 files changed, 9099 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/form_fields.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index da4d98a..b201f6a 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -275,6 +275,9 @@ class MarkdownEdit(AutoResizeTextarea):
yield ew.JSLink('js/jquery.textarea.js')
yield ew.JSLink('js/sf_markitup.js')
yield ew.CSSLink('css/markitup_sf.css')
+ yield ew.CSSLink('css/markdown_editor/editor.css')
+ yield ew.JSLink('js/markdown_editor/editor.js')
+ yield ew.JSLink('js/markdown_editor/marked.js')
class PageList(ew_core.Widget):
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/css/markdown_editor/editor.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markdown_editor/editor.css b/Allura/allura/lib/widgets/resources/css/markdown_editor/editor.css
new file mode 100644
index 0000000..7ca5dd9
--- /dev/null
+++ b/Allura/allura/lib/widgets/resources/css/markdown_editor/editor.css
@@ -0,0 +1,421 @@
+@font-face {
+ font-family: 'icomoon';
+ src:url('fonts/icomoon.eot');
+ src:url('fonts/icomoon.eot?#iefix') format('embedded-opentype'),
+ url('fonts/icomoon.woff') format('woff'),
+ url('fonts/icomoon.ttf') format('truetype'),
+ url('fonts/icomoon.svg#icomoon') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+
+/* Use the following CSS code if you want to use data attributes for inserting your icons */
+[data-icon]:before {
+ font-family: 'icomoon';
+ content: attr(data-icon);
+ speak: none;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+}
+
+/* Use the following CSS code if you want to have a class per icon */
+/*
+Instead of a list of all class selectors,
+you can use the generic selector below, but it's slower:
+[class*="icon-"] {
+*/
+.icon-bold, .icon-italic, .icon-quote, .icon-unordered-list, .icon-ordered-list, .icon-link, .icon-image, .icon-play, .icon-music, .icon-contract, .icon-fullscreen, .icon-question, .icon-info, .icon-undo, .icon-redo, .icon-code, .icon-preview {
+ font-family: 'icomoon';
+ speak: none;
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+}
+.icon-bold:before {
+ content: "\e000";
+}
+.icon-italic:before {
+ content: "\e001";
+}
+.icon-quote:before {
+ content: "\e003";
+}
+.icon-unordered-list:before {
+ content: "\e004";
+}
+.icon-ordered-list:before {
+ content: "\e005";
+}
+.icon-link:before {
+ content: "\e006";
+}
+.icon-image:before {
+ content: "\e007";
+}
+.icon-play:before {
+ content: "\e008";
+}
+.icon-music:before {
+ content: "\e009";
+}
+.icon-contract:before {
+ content: "\e00a";
+}
+.icon-fullscreen:before {
+ content: "\e00b";
+}
+.icon-question:before {
+ content: "\e00c";
+}
+.icon-info:before {
+ content: "\e00d";
+}
+.icon-undo:before {
+ content: "\e00e";
+}
+.icon-redo:before {
+ content: "\e00f";
+}
+.icon-code:before {
+ content: "\e011";
+}
+.icon-preview:before {
+ content: "\e002";
+}
+/* BASICS */
+
+.CodeMirror {
+ height: 300px;
+}
+.CodeMirror-scroll {
+ /* Set scrolling behaviour here */
+ overflow: auto;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+ padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre {
+ padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler {
+ background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* CURSOR */
+.CodeMirror div.CodeMirror-cursor {
+ border-left: 1px solid black;
+ z-index: 3;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+ border-left: 1px solid silver;
+}
+.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
+ width: auto;
+ border: 0;
+ background: #7e7;
+ z-index: 1;
+}
+/* Can style cursor different in overwrite (non-insert) mode */
+.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
+
+/* DEFAULT THEME */
+
+.cm-s-paper .cm-keyword {color: #555;}
+.cm-s-paper .cm-atom {color: #7f8c8d;}
+.cm-s-paper .cm-number {color: #7f8c8d;}
+.cm-s-paper .cm-def {color: #00f;}
+.cm-s-paper .cm-variable {color: black;}
+.cm-s-paper .cm-variable-2 {color: #555;}
+.cm-s-paper .cm-variable-3 {color: #085;}
+.cm-s-paper .cm-property {color: black;}
+.cm-s-paper .cm-operator {color: black;}
+.cm-s-paper .cm-comment {color: #959595;}
+.cm-s-paper .cm-string {color: #7f8c8d;}
+.cm-s-paper .cm-string-2 {color: #f50;}
+.cm-s-paper .cm-meta {color: #555;}
+.cm-s-paper .cm-error {color: #f00;}
+.cm-s-paper .cm-qualifier {color: #555;}
+.cm-s-paper .cm-builtin {color: #555;}
+.cm-s-paper .cm-bracket {color: #997;}
+.cm-s-paper .cm-tag {color: #7f8c8d;}
+.cm-s-paper .cm-attribute {color: #7f8c8d;}
+.cm-s-paper .cm-header {color: #000;}
+.cm-s-paper .cm-quote {color: #888;}
+.cm-s-paper .cm-hr {color: #999;}
+.cm-s-paper .cm-link {color: #7f8c8d;}
+
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+
+.cm-invalidchar {color: #f00;}
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+ the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+ position: relative;
+ overflow: hidden;
+}
+
+.CodeMirror-scroll {
+ /* 30px is the magic margin used to hide the element's real scrollbars */
+ /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
+ margin-bottom: -30px; margin-right: -30px;
+ padding-bottom: 30px; padding-right: 30px;
+ height: 100%;
+ outline: none; /* Prevent dragging from highlighting the element */
+ position: relative;
+}
+.CodeMirror-sizer {
+ position: relative;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+ before actuall scrolling happens, thus preventing shaking and
+ flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
+ position: absolute;
+ z-index: 6;
+ display: none;
+}
+.CodeMirror-vscrollbar {
+ right: 0; top: 0;
+ overflow-x: hidden;
+ overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+ bottom: 0; left: 0;
+ overflow-y: hidden;
+ overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+ right: 0; bottom: 0;
+ z-index: 6;
+}
+
+.CodeMirror-lines {
+ cursor: text;
+}
+.CodeMirror pre {
+ /* Reset some styles that the rest of the page might have set */
+ -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
+ border-width: 0;
+ background: transparent;
+ font-family: inherit;
+ font-size: inherit;
+ margin: 0;
+ white-space: pre-wrap;
+ word-wrap: normal;
+ line-height: inherit;
+ color: inherit;
+ z-index: 2;
+ position: relative;
+ overflow: visible;
+}
+.CodeMirror-wrap pre {
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ word-break: normal;
+}
+.CodeMirror-linebackground {
+ position: absolute;
+ left: 0; right: 0; top: 0; bottom: 0;
+ z-index: 0;
+}
+
+.CodeMirror-linewidget {
+ position: relative;
+ z-index: 2;
+ overflow: auto;
+}
+
+.CodeMirror-widget {
+ display: inline-block;
+}
+
+.CodeMirror-wrap .CodeMirror-scroll {
+ overflow-x: hidden;
+}
+
+.CodeMirror-measure {
+ position: absolute;
+ width: 100%; height: 0px;
+ overflow: hidden;
+ visibility: hidden;
+}
+.CodeMirror-measure pre { position: static; }
+
+.CodeMirror div.CodeMirror-cursor {
+ position: absolute;
+ visibility: hidden;
+ border-right: none;
+ width: 0;
+}
+.CodeMirror-focused div.CodeMirror-cursor {
+ visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #BDC3C7; }
+
+.cm-searching {
+ background: #ffa;
+ background: rgba(255, 255, 0, .4);
+}
+
+/* IE7 hack to prevent it from returning funny offsetTops on the spans */
+.CodeMirror span { *vertical-align: text-bottom; }
+
+@media print {
+ /* Hide the cursor when printing */
+ .CodeMirror div.CodeMirror-cursor {
+ visibility: hidden;
+ }
+}
+.CodeMirror {
+ height: 450px;
+}
+:-webkit-full-screen {
+ background: #f9f9f5;
+ padding: 0.5em 1em;
+ width: 100%;
+ height: 100%;
+}
+:-moz-full-screen {
+ padding: 0.5em 1em;
+ background: #f9f9f5;
+ width: 100%;
+ height: 100%;
+}
+.editor-wrapper {
+ font: 16px/1.62 "Helvetica Neue", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", sans-serif;
+ color: #2c3e50;
+}
+/* this is the title */
+.editor-wrapper input.title {
+ font: 18px "Helvetica Neue", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", sans-serif;
+ background: transparent;
+ padding: 4px;
+ width: 100%;
+ border: none;
+ outline: none;
+ opacity: 0.6;
+}
+.editor-toolbar {
+ position: relative;
+ opacity: 0.6;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+}
+.editor-toolbar:before, .editor-toolbar:after {
+ display: block;
+ content: ' ';
+ height: 1px;
+ background-color: #bdc3c7;
+ background: -moz-linear-gradient(45deg, #f9f9f9, #bdc3c7, #f9f9f9);
+ background: -webkit-linear-gradient(45deg, #f9f9f9, #bdc3c7, #f9f9f9);
+ background: -ms-linear-gradient(45deg, #f9f9f9, #bdc3c7, #f9f9f9);
+ background: linear-gradient(45deg, #f9f9f9, #bdc3c7, #f9f9f9);
+}
+.editor-toolbar:before {
+ margin-bottom: 8px;
+}
+.editor-toolbar:after {
+ margin-top: 8px;
+}
+.editor-wrapper input.title:hover, .editor-wrapper input.title:focus, .editor-toolbar:hover {
+ opacity: 0.8;
+}
+.editor-toolbar a {
+ display: inline-block;
+ text-align: center;
+ text-decoration: none !important;
+ color: #2c3e50 !important;
+ width: 24px;
+ height: 24px;
+ margin: 2px;
+ border: 1px solid transparent;
+ border-radius: 3px;
+ cursor: pointer;
+}
+.editor-toolbar a:hover, .editor-toolbar a.active {
+ background: #fcfcfc;
+ border-color: #95a5a6;
+}
+.editor-toolbar a:before {
+ line-height: 24px;
+}
+.editor-toolbar i.separator {
+ display: inline-block;
+ width: 0;
+ border-left: 1px solid #d9d9d9;
+ border-right: 1px solid white;
+ color: transparent;
+ text-indent: -10px;
+ margin: 0 6px;
+}
+.editor-toolbar a.icon-fullscreen {
+ position: absolute;
+ right: 0;
+}
+.editor-statusbar {
+ border-top: 1px solid #ece9e9;
+ padding: 8px 10px;
+ font-size: 12px;
+ color: #959694;
+ text-align: right;
+}
+.editor-statusbar span {
+ display: inline-block;
+ min-width: 4em;
+ margin-left: 1em;
+}
+.editor-statusbar .lines:before {
+ content: 'lines: ';
+}
+.editor-statusbar .words:before {
+ content: 'words: ';
+}
+.editor-preview {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 100%;
+ background: #f9f9f5;
+ z-index: 9999;
+ overflow: auto;
+ -webkit-transition: left 0.2s ease;
+ -moz-transition: left 0.2s ease;
+ -ms-transition: left 0.2s ease;
+ transition: left 0.2s ease;
+}
+.editor-preview-active {
+ left: 0;
+}
+.editor-preview > p {
+ margin-top: 0;
+}
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.dev.svg
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.dev.svg b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.dev.svg
new file mode 100644
index 0000000..ee61a97
--- /dev/null
+++ b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.dev.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="16"></iconset>
+</metadata>
+<defs>
+<font id="icomoon" horiz-adv-x="512" >
+<font-face units-per-em="512" ascent="480" descent="-32" />
+<missing-glyph horiz-adv-x="512" />
+<glyph unicode="" d="M 353.94,237.674C 372.689,259.945, 384.00,288.678, 384.00,320.00c0.00,70.58-57.421,128.00-128.00,128.00l-64.00,0.00 l-64.00,0.00 L 96.00,448.00 l0.00-448.00 l 32.00,0.00 l 64.00,0.00 l 96.00,0.00
+ c 70.579,0.00, 128.00,57.421, 128.00,128.00C 416.00,174.478, 391.101,215.248, 353.94,237.674z M 192.00,384.00l 50.75,0.00 c 27.984,0.00, 50.75-28.71, 50.75-64.00
+ s-22.766-64.00-50.75-64.00L 192.00,256.00 L 192.00,384.00 z M 271.50,64.00L 192.00,64.00 L 192.00,192.00 l 79.50,0.00 c 29.225,0.00, 53.00-28.71, 53.00-64.00S 300.725,64.00, 271.50,64.00z" data-tags="bold, wysiwyg" />
+<glyph unicode="" d="M 448.00,448.00 L 448.00,416.00 L 384.00,416.00 L 224.00,32.00 L 288.00,32.00 L 288.00,0.00 L 64.00,0.00 L 64.00,32.00 L 128.00,32.00 L 288.00,416.00 L 224.00,416.00 L 224.00,448.00 Z" data-tags="italic, wysiwyg" />
+<glyph unicode="" d="M 112.50,256.00 C 174.356,256.00 224.50,205.855 224.50,144.00 C 224.50,82.144 174.356,32.00 112.50,32.00 C 50.644,32.00 0.50,82.144 0.50,144.00 L 0.00,160.00 C 0.00,283.712 100.288,384.00 224.00,384.00 L 224.00,320.00 C 181.263,320.00 141.083,303.357 110.863,273.137 C 105.046,267.319 99.737,261.129 94.948,254.627 C 100.667,255.527 106.528,256.00 112.50,256.00 ZM 400.50,256.00 C 462.355,256.00 512.50,205.855 512.50,144.00 C 512.50,82.144 462.355,32.00 400.50,32.00 C 338.645,32.00 288.50,82.144 288.50,144.00 L 288.00,160.00 C 288.00,283.712 388.288,384.00 512.00,384.00 L 512.00,320.00 C 469.263,320.00 429.083,303.357 398.863,273.137 C 393.045,267.319 387.736,261.129 382.947,254.627 C 388.667,255.527 394.527,256.00 400.50,256.00 Z" data-tags="quotes-left, ldquo" />
+<glyph unicode="" d="M 192.00,448.00l 320.00,0.00 l0.00-64.00 L 192.00,384.00 L 192.00,448.00 z M 192.00,256.00l 320.00,0.00 l0.00-64.00 L 192.00,192.00 L 192.00,256.00 z M 192.00,64.00l 320.00,0.00 l0.00-64.00 L 192.00,0.00 L 192.00,64.00 zM0.00,416.00A64.00,64.00 2700.00 1 1 128.00,416A64.00,64.00 2700.00 1 1 0.00,416zM0.00,224.00A64.00,64.00 2700.00 1 1 128.00,224A64.00,64.00 2700.00 1 1 0.00,224zM0.00,32.00A64.00,64.00 2700.00 1 1 128.00,32A64.00,64.00 2700.00 1 1 0.00,32z" data-tags="list, bullet, ul, todo, menu" />
+<glyph unicode="" d="M 192.00,64.00L 512.00,64.00L 512.00,0.00L 192.00,0.00zM 192.00,256.00L 512.00,256.00L 512.00,192.00L 192.00,192.00zM 192.00,448.00L 512.00,448.00L 512.00,384.00L 192.00,384.00zM 96.00,480.00 L 96.00,352.00 L 64.00,352.00 L 64.00,448.00 L 32.00,448.00 L 32.00,480.00 ZM 64.00,217.00 L 64.00,192.00 L 128.00,192.00 L 128.00,160.00 L 32.00,160.00 L 32.00,233.00 L 96.00,263.00 L 96.00,288.00 L 32.00,288.00 L 32.00,320.00 L 128.00,320.00 L 128.00,247.00 ZM 128.00,128.00 L 128.00-32.00 L 32.00-32.00 L 32.00,0.00 L 96.00,0.00 L 96.00,32.00 L 32.00,32.00 L 32.00,64.00 L 96.00,64.00 L 96.00,96.00 L 32.00,96.00 L 32.00,128.00 Z" data-tags="numbered-list, list, items, nl" />
+<glyph unicode="" d="M 476.698,442.679l-2.014,2.021c-47.074,47.067-124.097,47.067-171.163,0.00L 194.468,335.632
+ c-47.067-47.066-47.067-124.088,0.00-171.155l 2.013-2.013c 3.916-3.924, 8.073-7.462, 12.368-10.729l 39.924,39.925
+ c-4.651,2.747-9.063,6.036-13.058,10.03l-2.021,2.021c-25.557,25.549-25.557,67.136,0.00,92.695L 342.758,405.462
+ c 25.558,25.559, 67.137,25.559, 92.693,0.00l 2.021-2.012c 25.55-25.558, 25.55-67.146,0.00-92.695l-49.343-49.343
+ c 8.566-21.154, 12.624-43.70, 12.269-66.193l 76.302,76.302C 523.767,318.589, 523.767,395.61, 476.698,442.679zM 315.521,285.533c-3.916,3.916-8.073,7.461-12.368,10.72l-39.924-39.916c 4.652-2.748, 9.063-6.037, 13.058-10.031l 2.021-2.02
+ c 25.558-25.558, 25.558-67.136,0.00-92.694L 169.243,42.525c-25.559-25.551-67.138-25.551-92.694,0.00l-2.021,2.021
+ c-25.549,25.56-25.549,67.138,0.00,92.694l 49.344,49.343c-8.567,21.153-12.623,43.701-12.269,66.193l-76.301-76.299
+ c-47.068-47.066-47.068-124.089,0.00-171.162l 2.013-2.016c 47.076-47.064, 124.096-47.064, 171.164,0.00l 109.055,109.059
+ c 47.067,47.066, 47.067,124.097,0.00,171.163L 315.521,285.533z" data-tags="link, chain, url, uri, anchor" />
+<glyph unicode="" d="M 448.00,384.00 L 64.00,384.00 L 64.00,64.00 L 448.00,64.00 L 448.00,384.00 Z M 512.00,448.00 L 512.00,448.00 L 512.00,0.00 L 0.00,0.00 L 0.00,448.00 L 512.00,448.00 ZM 416.00,96.00 L 96.00,96.00 L 96.00,160.00 L 192.00,320.00 L 323.50,160.00 L 416.00,224.00 L 416.00,192.00 ZM 320.00,304.00A48.00,48.00 2700.00 1 1 416.00,304A48.00,48.00 2700.00 1 1 320.00,304z" data-tags="image, picture, photo, graphic" />
+<glyph unicode="" d="M 490.594,399.946C 418.778,410.271, 339.428,416.00, 256.001,416.00c-83.43,0.00-162.778-5.729-234.597-16.054
+ C 7.639,346.083,0.00,286.571,0.00,224.00c0.00-62.57, 7.639-122.083, 21.404-175.945C 93.223,37.729, 172.572,32.00, 256.001,32.00
+ c 83.427,0.00, 162.776,5.729, 234.593,16.055C 504.36,101.917, 512.00,161.43, 512.00,224.00C 512.00,286.571, 504.36,346.083, 490.594,399.946z
+ M 192.001,128.00L 192.001,320.00 l 160.00-96.00L 192.001,128.00z" data-tags="play, video, movie" />
+<glyph unicode="" d="M 160.00,384.00 L 512.00,480.00 L 512.00,448.00 L 512.00,384.00 L 512.00,112.00 C 512.00,67.817 461.855,32.00 400.00,32.00 C 338.145,32.00 288.00,67.817 288.00,112.00 C 288.00,156.183 338.145,192.00 400.00,192.00 C 417.179,192.00 433.451,189.234 448.00,184.297 L 448.00,349.091 L 224.00,288.00 L 224.00,48.00 C 224.00,3.817 173.856-32.00 112.00-32.00 C 50.144-32.00 0.00,3.817 0.00,48.00 C 0.00,92.183 50.144,128.00 112.00,128.00 C 129.179,128.00 145.451,125.234 160.00,120.297 L 160.00,288.00 L 160.00,384.00 Z" data-tags="music, song, audio, sound" />
+<glyph unicode="" d="M 224.00,192.00 L 224.00-16.00 L 144.00,64.00 L 48.00-32.00 L 0.00,16.00 L 96.00,112.00 L 16.00,192.00 ZM 512.00,432.00 L 416.00,336.00 L 496.00,256.00 L 288.00,256.00 L 288.00,464.00 L 368.00,384.00 L 464.00,480.00 Z" data-tags="contract, minimize, shrink, collapse" />
+<glyph unicode="" d="M 512.00,480.00 L 512.00,272.00 L 432.00,352.00 L 336.00,256.00 L 288.00,304.00 L 384.00,400.00 L 304.00,480.00 ZM 224.00,144.00 L 128.00,48.00 L 208.00-32.00 L 0.00-32.00 L 0.00,176.00 L 80.00,96.00 L 176.00,192.00 Z" data-tags="expand, enlarge, maximize, fullscreen" />
+<glyph unicode="" d="M 224.00,128.00L 288.00,128.00L 288.00,64.00L 224.00,64.00zM 352.00,352.00 C 369.673,352.00 384.00,337.673 384.00,320.00 L 384.00,224.00 L 288.00,160.00 L 224.00,160.00 L 224.00,192.00 L 320.00,256.00 L 320.00,288.00 L 160.00,288.00 L 160.00,352.00 L 352.00,352.00 ZM 256.00,432.00 C 200.441,432.00 148.208,410.364 108.922,371.078 C 69.636,331.792 48.00,279.559 48.00,224.00 C 48.00,168.441 69.636,116.208 108.922,76.922 C 148.208,37.636 200.441,16.00 256.00,16.00 C 311.559,16.00 363.792,37.636 403.078,76.922 C 442.364,116.208 464.00,168.441 464.00,224.00 C 464.00,279.559 442.364,331.792 403.078,371.078 C 363.792,410.364 311.559,432.00 256.00,432.00 Z M 256.00,480.00 L 256.00,480.00 C 397.385,480.00 512.00,365.385 512.00,224.00 C 512.00,82.615 397.385-32.00 256.00-32.00 C 114.615-32.00 0.00,82.615 0.00,224.00 C 0.00,365.385 114.615,480.00 256.00,480.00 Z" data-tags="question, help, support" />
+<glyph unicode="" d="M 256.00,480.00C 114.615,480.00,0.00,365.385,0.00,224.00s 114.615-256.00, 256.00-256.00s 256.00,114.615, 256.00,256.00S 397.385,480.00, 256.00,480.00z M 256.00,16.00
+ c-114.875,0.00-208.00,93.125-208.00,208.00S 141.125,432.00, 256.00,432.00s 208.00-93.125, 208.00-208.00S 370.875,16.00, 256.00,16.00zM 224.00,352.00L 288.00,352.00L 288.00,288.00L 224.00,288.00zM 320.00,96.00L 192.00,96.00L 192.00,128.00L 224.00,128.00L 224.00,224.00L 192.00,224.00L 192.00,256.00L 288.00,256.00L 288.00,128.00L 320.00,128.00 z" data-tags="info, information" />
+<glyph unicode="" d="M 380.931-32.00C 437.794,71.016, 447.375,228.153, 224.00,222.912L 224.00,96.00 L 32.00,288.00L 224.00,480.00l0.00-124.186
+ C 491.481,362.785, 521.285,119.707, 380.931-32.00z" data-tags="undo, arrow, left" />
+<glyph unicode="" d="M 288.00,355.814L 288.00,480.00 l 192.00-192.00L 288.00,96.00L 288.00,222.912 C 64.625,228.153, 74.206,71.016, 131.07-32.00
+ C-9.286,119.707, 20.52,362.785, 288.00,355.814z" data-tags="redo, arrow, right" />
+<glyph unicode="" d="M 64.00,224.00L 192.00,352.00L 128.00,352.00L0.00,224.00L 128.00,96.00L 192.00,96.00 zM 384.00,352.00L 320.00,352.00L 448.00,224.00L 320.00,96.00L 384.00,96.00L 512.00,224.00 zM 272.00,416.00L 192.00,32.00L 240.00,32.00L 320.00,416.00 z" data-tags="code, embed" />
+<glyph unicode="" d="M 256.00,320.00C 151.316,320.00, 58.378,269.722,0.00,192.00c 58.378-77.723, 151.316-128.00, 256.00-128.00c 104.684,0.00, 197.622,50.277, 256.00,128.00
+ C 453.622,269.722, 360.684,320.00, 256.00,320.00z M 224.00,256.00c 17.673,0.00, 32.00-14.327, 32.00-32.00s-14.327-32.00-32.00-32.00s-32.00,14.327-32.00,32.00S 206.327,256.00, 224.00,256.00z
+ M 386.808,127.352c-19.824-10.129-40.826-17.931-62.423-23.188C 302.141,98.746, 279.134,96.00, 256.00,96.00
+ c-23.133,0.00-46.141,2.746-68.384,8.162c-21.597,5.259-42.599,13.061-62.423,23.188c-31.51,16.101-60.111,38.205-83.82,64.649
+ c 23.709,26.444, 52.31,48.55, 83.82,64.649c 16.168,8.261, 33.121,14.973, 50.541,20.02C 165.79,261.547, 160.00,243.451, 160.00,224.00
+ c0.00-53.02, 42.981-96.00, 96.00-96.00c 53.019,0.00, 96.00,42.98, 96.00,96.00c0.00,19.451-5.791,37.547-15.733,52.67c 17.419-5.048, 34.372-11.76, 50.541-20.021
+ c 31.511-16.099, 60.109-38.204, 83.819-64.649C 446.917,165.557, 418.318,143.45, 386.808,127.352z M 430.459,358.139
+ C 376.099,385.916, 317.403,400.00, 256.00,400.00c-61.403,0.00-120.099-14.084-174.459-41.861C 52.155,343.123, 24.675,324.187,0.00,302.101l0.00-54.603
+ c 27.669,29.283, 60.347,53.877, 96.097,72.145C 145.907,345.095, 199.706,358.00, 256.00,358.00s 110.093-12.905, 159.902-38.358
+ c 35.751-18.268, 68.429-42.862, 96.098-72.145L 512.00,302.10 C 487.325,324.187, 459.846,343.123, 430.459,358.139z" data-tags="eye, views, vision, visit" />
+<glyph unicode=" " horiz-adv-x="256" />
+<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
+</font></defs></svg>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.eot
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.eot b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.eot
new file mode 100644
index 0000000..35489e5
Binary files /dev/null and b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.eot differ
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.svg
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.svg b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.svg
new file mode 100644
index 0000000..a5b3c9c
--- /dev/null
+++ b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="16"></iconset>
+</metadata>
+<defs>
+<font id="icomoon" horiz-adv-x="512" >
+<font-face units-per-em="512" ascent="480" descent="-32" />
+<missing-glyph horiz-adv-x="512" />
+<glyph unicode="" d="M 353.94,237.674C 372.689,259.945, 384.00,288.678, 384.00,320.00c0.00,70.58-57.421,128.00-128.00,128.00l-64.00,0.00 l-64.00,0.00 L 96.00,448.00 l0.00-448.00 l 32.00,0.00 l 64.00,0.00 l 96.00,0.00
+ c 70.579,0.00, 128.00,57.421, 128.00,128.00C 416.00,174.478, 391.101,215.248, 353.94,237.674z M 192.00,384.00l 50.75,0.00 c 27.984,0.00, 50.75-28.71, 50.75-64.00
+ s-22.766-64.00-50.75-64.00L 192.00,256.00 L 192.00,384.00 z M 271.50,64.00L 192.00,64.00 L 192.00,192.00 l 79.50,0.00 c 29.225,0.00, 53.00-28.71, 53.00-64.00S 300.725,64.00, 271.50,64.00z" />
+<glyph unicode="" d="M 448.00,448.00 L 448.00,416.00 L 384.00,416.00 L 224.00,32.00 L 288.00,32.00 L 288.00,0.00 L 64.00,0.00 L 64.00,32.00 L 128.00,32.00 L 288.00,416.00 L 224.00,416.00 L 224.00,448.00 Z" />
+<glyph unicode="" d="M 112.50,256.00 C 174.356,256.00 224.50,205.855 224.50,144.00 C 224.50,82.144 174.356,32.00 112.50,32.00 C 50.644,32.00 0.50,82.144 0.50,144.00 L 0.00,160.00 C 0.00,283.712 100.288,384.00 224.00,384.00 L 224.00,320.00 C 181.263,320.00 141.083,303.357 110.863,273.137 C 105.046,267.319 99.737,261.129 94.948,254.627 C 100.667,255.527 106.528,256.00 112.50,256.00 ZM 400.50,256.00 C 462.355,256.00 512.50,205.855 512.50,144.00 C 512.50,82.144 462.355,32.00 400.50,32.00 C 338.645,32.00 288.50,82.144 288.50,144.00 L 288.00,160.00 C 288.00,283.712 388.288,384.00 512.00,384.00 L 512.00,320.00 C 469.263,320.00 429.083,303.357 398.863,273.137 C 393.045,267.319 387.736,261.129 382.947,254.627 C 388.667,255.527 394.527,256.00 400.50,256.00 Z" />
+<glyph unicode="" d="M 192.00,448.00l 320.00,0.00 l0.00-64.00 L 192.00,384.00 L 192.00,448.00 z M 192.00,256.00l 320.00,0.00 l0.00-64.00 L 192.00,192.00 L 192.00,256.00 z M 192.00,64.00l 320.00,0.00 l0.00-64.00 L 192.00,0.00 L 192.00,64.00 zM0.00,416.00A64.00,64.00 2700.00 1 1 128.00,416A64.00,64.00 2700.00 1 1 0.00,416zM0.00,224.00A64.00,64.00 2700.00 1 1 128.00,224A64.00,64.00 2700.00 1 1 0.00,224zM0.00,32.00A64.00,64.00 2700.00 1 1 128.00,32A64.00,64.00 2700.00 1 1 0.00,32z" />
+<glyph unicode="" d="M 192.00,64.00L 512.00,64.00L 512.00,0.00L 192.00,0.00zM 192.00,256.00L 512.00,256.00L 512.00,192.00L 192.00,192.00zM 192.00,448.00L 512.00,448.00L 512.00,384.00L 192.00,384.00zM 96.00,480.00 L 96.00,352.00 L 64.00,352.00 L 64.00,448.00 L 32.00,448.00 L 32.00,480.00 ZM 64.00,217.00 L 64.00,192.00 L 128.00,192.00 L 128.00,160.00 L 32.00,160.00 L 32.00,233.00 L 96.00,263.00 L 96.00,288.00 L 32.00,288.00 L 32.00,320.00 L 128.00,320.00 L 128.00,247.00 ZM 128.00,128.00 L 128.00-32.00 L 32.00-32.00 L 32.00,0.00 L 96.00,0.00 L 96.00,32.00 L 32.00,32.00 L 32.00,64.00 L 96.00,64.00 L 96.00,96.00 L 32.00,96.00 L 32.00,128.00 Z" />
+<glyph unicode="" d="M 476.698,442.679l-2.014,2.021c-47.074,47.067-124.097,47.067-171.163,0.00L 194.468,335.632
+ c-47.067-47.066-47.067-124.088,0.00-171.155l 2.013-2.013c 3.916-3.924, 8.073-7.462, 12.368-10.729l 39.924,39.925
+ c-4.651,2.747-9.063,6.036-13.058,10.03l-2.021,2.021c-25.557,25.549-25.557,67.136,0.00,92.695L 342.758,405.462
+ c 25.558,25.559, 67.137,25.559, 92.693,0.00l 2.021-2.012c 25.55-25.558, 25.55-67.146,0.00-92.695l-49.343-49.343
+ c 8.566-21.154, 12.624-43.70, 12.269-66.193l 76.302,76.302C 523.767,318.589, 523.767,395.61, 476.698,442.679zM 315.521,285.533c-3.916,3.916-8.073,7.461-12.368,10.72l-39.924-39.916c 4.652-2.748, 9.063-6.037, 13.058-10.031l 2.021-2.02
+ c 25.558-25.558, 25.558-67.136,0.00-92.694L 169.243,42.525c-25.559-25.551-67.138-25.551-92.694,0.00l-2.021,2.021
+ c-25.549,25.56-25.549,67.138,0.00,92.694l 49.344,49.343c-8.567,21.153-12.623,43.701-12.269,66.193l-76.301-76.299
+ c-47.068-47.066-47.068-124.089,0.00-171.162l 2.013-2.016c 47.076-47.064, 124.096-47.064, 171.164,0.00l 109.055,109.059
+ c 47.067,47.066, 47.067,124.097,0.00,171.163L 315.521,285.533z" />
+<glyph unicode="" d="M 448.00,384.00 L 64.00,384.00 L 64.00,64.00 L 448.00,64.00 L 448.00,384.00 Z M 512.00,448.00 L 512.00,448.00 L 512.00,0.00 L 0.00,0.00 L 0.00,448.00 L 512.00,448.00 ZM 416.00,96.00 L 96.00,96.00 L 96.00,160.00 L 192.00,320.00 L 323.50,160.00 L 416.00,224.00 L 416.00,192.00 ZM 320.00,304.00A48.00,48.00 2700.00 1 1 416.00,304A48.00,48.00 2700.00 1 1 320.00,304z" />
+<glyph unicode="" d="M 490.594,399.946C 418.778,410.271, 339.428,416.00, 256.001,416.00c-83.43,0.00-162.778-5.729-234.597-16.054
+ C 7.639,346.083,0.00,286.571,0.00,224.00c0.00-62.57, 7.639-122.083, 21.404-175.945C 93.223,37.729, 172.572,32.00, 256.001,32.00
+ c 83.427,0.00, 162.776,5.729, 234.593,16.055C 504.36,101.917, 512.00,161.43, 512.00,224.00C 512.00,286.571, 504.36,346.083, 490.594,399.946z
+ M 192.001,128.00L 192.001,320.00 l 160.00-96.00L 192.001,128.00z" />
+<glyph unicode="" d="M 160.00,384.00 L 512.00,480.00 L 512.00,448.00 L 512.00,384.00 L 512.00,112.00 C 512.00,67.817 461.855,32.00 400.00,32.00 C 338.145,32.00 288.00,67.817 288.00,112.00 C 288.00,156.183 338.145,192.00 400.00,192.00 C 417.179,192.00 433.451,189.234 448.00,184.297 L 448.00,349.091 L 224.00,288.00 L 224.00,48.00 C 224.00,3.817 173.856-32.00 112.00-32.00 C 50.144-32.00 0.00,3.817 0.00,48.00 C 0.00,92.183 50.144,128.00 112.00,128.00 C 129.179,128.00 145.451,125.234 160.00,120.297 L 160.00,288.00 L 160.00,384.00 Z" />
+<glyph unicode="" d="M 224.00,192.00 L 224.00-16.00 L 144.00,64.00 L 48.00-32.00 L 0.00,16.00 L 96.00,112.00 L 16.00,192.00 ZM 512.00,432.00 L 416.00,336.00 L 496.00,256.00 L 288.00,256.00 L 288.00,464.00 L 368.00,384.00 L 464.00,480.00 Z" />
+<glyph unicode="" d="M 512.00,480.00 L 512.00,272.00 L 432.00,352.00 L 336.00,256.00 L 288.00,304.00 L 384.00,400.00 L 304.00,480.00 ZM 224.00,144.00 L 128.00,48.00 L 208.00-32.00 L 0.00-32.00 L 0.00,176.00 L 80.00,96.00 L 176.00,192.00 Z" />
+<glyph unicode="" d="M 224.00,128.00L 288.00,128.00L 288.00,64.00L 224.00,64.00zM 352.00,352.00 C 369.673,352.00 384.00,337.673 384.00,320.00 L 384.00,224.00 L 288.00,160.00 L 224.00,160.00 L 224.00,192.00 L 320.00,256.00 L 320.00,288.00 L 160.00,288.00 L 160.00,352.00 L 352.00,352.00 ZM 256.00,432.00 C 200.441,432.00 148.208,410.364 108.922,371.078 C 69.636,331.792 48.00,279.559 48.00,224.00 C 48.00,168.441 69.636,116.208 108.922,76.922 C 148.208,37.636 200.441,16.00 256.00,16.00 C 311.559,16.00 363.792,37.636 403.078,76.922 C 442.364,116.208 464.00,168.441 464.00,224.00 C 464.00,279.559 442.364,331.792 403.078,371.078 C 363.792,410.364 311.559,432.00 256.00,432.00 Z M 256.00,480.00 L 256.00,480.00 C 397.385,480.00 512.00,365.385 512.00,224.00 C 512.00,82.615 397.385-32.00 256.00-32.00 C 114.615-32.00 0.00,82.615 0.00,224.00 C 0.00,365.385 114.615,480.00 256.00,480.00 Z" />
+<glyph unicode="" d="M 256.00,480.00C 114.615,480.00,0.00,365.385,0.00,224.00s 114.615-256.00, 256.00-256.00s 256.00,114.615, 256.00,256.00S 397.385,480.00, 256.00,480.00z M 256.00,16.00
+ c-114.875,0.00-208.00,93.125-208.00,208.00S 141.125,432.00, 256.00,432.00s 208.00-93.125, 208.00-208.00S 370.875,16.00, 256.00,16.00zM 224.00,352.00L 288.00,352.00L 288.00,288.00L 224.00,288.00zM 320.00,96.00L 192.00,96.00L 192.00,128.00L 224.00,128.00L 224.00,224.00L 192.00,224.00L 192.00,256.00L 288.00,256.00L 288.00,128.00L 320.00,128.00 z" />
+<glyph unicode="" d="M 380.931-32.00C 437.794,71.016, 447.375,228.153, 224.00,222.912L 224.00,96.00 L 32.00,288.00L 224.00,480.00l0.00-124.186
+ C 491.481,362.785, 521.285,119.707, 380.931-32.00z" />
+<glyph unicode="" d="M 288.00,355.814L 288.00,480.00 l 192.00-192.00L 288.00,96.00L 288.00,222.912 C 64.625,228.153, 74.206,71.016, 131.07-32.00
+ C-9.286,119.707, 20.52,362.785, 288.00,355.814z" />
+<glyph unicode="" d="M 64.00,224.00L 192.00,352.00L 128.00,352.00L0.00,224.00L 128.00,96.00L 192.00,96.00 zM 384.00,352.00L 320.00,352.00L 448.00,224.00L 320.00,96.00L 384.00,96.00L 512.00,224.00 zM 272.00,416.00L 192.00,32.00L 240.00,32.00L 320.00,416.00 z" />
+<glyph unicode="" d="M 256.00,320.00C 151.316,320.00, 58.378,269.722,0.00,192.00c 58.378-77.723, 151.316-128.00, 256.00-128.00c 104.684,0.00, 197.622,50.277, 256.00,128.00
+ C 453.622,269.722, 360.684,320.00, 256.00,320.00z M 224.00,256.00c 17.673,0.00, 32.00-14.327, 32.00-32.00s-14.327-32.00-32.00-32.00s-32.00,14.327-32.00,32.00S 206.327,256.00, 224.00,256.00z
+ M 386.808,127.352c-19.824-10.129-40.826-17.931-62.423-23.188C 302.141,98.746, 279.134,96.00, 256.00,96.00
+ c-23.133,0.00-46.141,2.746-68.384,8.162c-21.597,5.259-42.599,13.061-62.423,23.188c-31.51,16.101-60.111,38.205-83.82,64.649
+ c 23.709,26.444, 52.31,48.55, 83.82,64.649c 16.168,8.261, 33.121,14.973, 50.541,20.02C 165.79,261.547, 160.00,243.451, 160.00,224.00
+ c0.00-53.02, 42.981-96.00, 96.00-96.00c 53.019,0.00, 96.00,42.98, 96.00,96.00c0.00,19.451-5.791,37.547-15.733,52.67c 17.419-5.048, 34.372-11.76, 50.541-20.021
+ c 31.511-16.099, 60.109-38.204, 83.819-64.649C 446.917,165.557, 418.318,143.45, 386.808,127.352z M 430.459,358.139
+ C 376.099,385.916, 317.403,400.00, 256.00,400.00c-61.403,0.00-120.099-14.084-174.459-41.861C 52.155,343.123, 24.675,324.187,0.00,302.101l0.00-54.603
+ c 27.669,29.283, 60.347,53.877, 96.097,72.145C 145.907,345.095, 199.706,358.00, 256.00,358.00s 110.093-12.905, 159.902-38.358
+ c 35.751-18.268, 68.429-42.862, 96.098-72.145L 512.00,302.10 C 487.325,324.187, 459.846,343.123, 430.459,358.139z" />
+<glyph unicode=" " horiz-adv-x="256" />
+<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
+</font></defs></svg>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.ttf
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.ttf b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.ttf
new file mode 100644
index 0000000..68a1d2a
Binary files /dev/null and b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.ttf differ
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.woff
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.woff b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.woff
new file mode 100644
index 0000000..ea9e6bb
Binary files /dev/null and b/Allura/allura/lib/widgets/resources/css/markdown_editor/fonts/icomoon.woff differ
[13/21] allura git commit: [#7897] ticket:804 Add new files to
LICENSE and excludes
Posted by je...@apache.org.
[#7897] ticket:804 Add new files to LICENSE and excludes
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5e07e7a5
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5e07e7a5
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5e07e7a5
Branch: refs/heads/ib/7897
Commit: 5e07e7a57808478cfc1c894110e1bb19ba928dfc
Parents: c5ed785
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 14:25:51 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 14:25:55 2015 +0300
----------------------------------------------------------------------
Allura/LICENSE | 7 ++++++-
LICENSE | 5 +++++
rat-excludes.txt | 2 ++
3 files changed, 13 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/5e07e7a5/Allura/LICENSE
----------------------------------------------------------------------
diff --git a/Allura/LICENSE b/Allura/LICENSE
index 9823dc6..32f25bf 100644
--- a/Allura/LICENSE
+++ b/Allura/LICENSE
@@ -245,4 +245,9 @@ Modernizr, which is available under the MIT license.
For details, see allura/public/nf/js/modernizr.js
React.js, which is available under the BSD license.
-For details, see Allura/allura/public/nf/js/react.min.js
+For details, see allura/public/nf/js/react.min.js
+
+Markdown editor (https://github.com/lepture/editor) is available under the MIT
+license. For details, see:
+ allura/lib/widgets/resources/js/markdown_editor/
+ allura/lib/widgets/resources/css/markdown_editor/
http://git-wip-us.apache.org/repos/asf/allura/blob/5e07e7a5/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index d371ff5..8cb0dbe 100644
--- a/LICENSE
+++ b/LICENSE
@@ -252,3 +252,8 @@ For details, see Allura/allura/public/nf/js/modernizr.js
React.js, which is available under the BSD license.
For details, see Allura/allura/public/nf/js/react.min.js
+
+Markdown editor (https://github.com/lepture/editor) is available under the MIT
+license. For details, see:
+ Allura/allura/lib/widgets/resources/js/markdown_editor/
+ Allura/allura/lib/widgets/resources/css/markdown_editor/
http://git-wip-us.apache.org/repos/asf/allura/blob/5e07e7a5/rat-excludes.txt
----------------------------------------------------------------------
diff --git a/rat-excludes.txt b/rat-excludes.txt
index 95c2eaf..d6c8ca0 100644
--- a/rat-excludes.txt
+++ b/rat-excludes.txt
@@ -32,6 +32,8 @@ Allura/allura/public/nf/css/blueprint/
Allura/allura/public/nf/js/sylvester.js
Allura/allura/public/nf/js/modernizr.js
Allura/allura/public/nf/js/react.min.js
+Allura/allura/lib/widgets/resources/js/markdown_editor/
+Allura/allura/lib/widgets/resources/css/markdown_editor/
Allura/allura/tests/data/genshi_hello_tmpl
Allura/allura/tests/data/test_mime/text_file.txt
AlluraTest/jslint/
[15/21] allura git commit: [#7897] ticket:814 Focus editor by click &
fix z-index for help & preview
Posted by je...@apache.org.
[#7897] ticket:814 Focus editor by click & fix z-index for help & preview
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/eb627a91
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/eb627a91
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/eb627a91
Branch: refs/heads/ib/7897
Commit: eb627a9106337922c61042f00e3effc2ad2224ac
Parents: 92b6536
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 17:26:09 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 17:26:09 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/resources/css/markitup_sf.css | 5 +++++
Allura/allura/lib/widgets/resources/js/sf_markitup.js | 3 +++
2 files changed, 8 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/eb627a91/Allura/allura/lib/widgets/resources/css/markitup_sf.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markitup_sf.css b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
index 2c12807..5310c69 100644
--- a/Allura/allura/lib/widgets/resources/css/markitup_sf.css
+++ b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
@@ -51,3 +51,8 @@
.markdown_edit .editor-preview {
padding: 5px;
}
+
+
+.markdown_edit .editor-preview {
+ z-index: 1001; /* should always be under help modal */
+}
http://git-wip-us.apache.org/repos/asf/allura/blob/eb627a91/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index f3f2c44..4c0cd20 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -60,6 +60,9 @@ $(window).load(function() {
});
editor.render();
+ // focus editor by clicking anywhere on it, not only on the first few lines
+ $('.CodeMirror').click(function () { cm.focus(); });
+
function show_help(editor) {
$help_contents.html('Loading...');
$.get($help_contents.attr('data-url'), function (data) {
[17/21] allura git commit: [#7897] ticket:814 Preserve ticket comment
on edit & focus description field to show content
Posted by je...@apache.org.
[#7897] ticket:814 Preserve ticket comment on edit & focus description field to show content
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/23eb07e6
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/23eb07e6
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/23eb07e6
Branch: refs/heads/ib/7897
Commit: 23eb07e67729a62d0f3441fec38d392a1061e55a
Parents: 9b515ad
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 17:50:30 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 17:51:45 2015 +0300
----------------------------------------------------------------------
.../forgetracker/templates/tracker/new_ticket.html | 4 ----
.../forgetracker/templates/tracker/ticket.html | 15 +++++++++++----
2 files changed, 11 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/23eb07e6/ForgeTracker/forgetracker/templates/tracker/new_ticket.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker/new_ticket.html b/ForgeTracker/forgetracker/templates/tracker/new_ticket.html
index dd9f5e9..24141a4 100644
--- a/ForgeTracker/forgetracker/templates/tracker/new_ticket.html
+++ b/ForgeTracker/forgetracker/templates/tracker/new_ticket.html
@@ -33,10 +33,6 @@
{% block extra_css %}
<style type="text/css">
- .markdown_edit textarea {
- height: 100px;
- }
-
.new-ticket-title {
top: 7px;
position: absolute;
http://git-wip-us.apache.org/repos/asf/allura/blob/23eb07e6/ForgeTracker/forgetracker/templates/tracker/ticket.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker/ticket.html b/ForgeTracker/forgetracker/templates/tracker/ticket.html
index 5f9f534..a68e723 100644
--- a/ForgeTracker/forgetracker/templates/tracker/ticket.html
+++ b/ForgeTracker/forgetracker/templates/tracker/ticket.html
@@ -192,10 +192,13 @@
var original_title = title_holder.text();
var title_actions = title_holder.find('small');
var vote = $('#vote');
- var discussion_comment_textarea = $('#new_post_holder').find('form').find('textarea');
+
+ function get_cm($elem) { return $('.CodeMirror', $elem)[0].CodeMirror; }
+
+ var discussion_comment_cm = get_cm($('#new_post_holder'));
$('a.edit_ticket').click(function () {
- var not_posted_comment = discussion_comment_textarea.val();
+ var not_posted_comment = discussion_comment_cm.getValue();
form_holder.show();
view_holder.hide();
discussion_holder.hide();
@@ -206,8 +209,12 @@
vote.hide();
$('div.new-ticket-title label').hide();
$('a.edit_ticket').addClass('btn_activate');
- $('textarea[name="ticket_form.description"]').trigger('editticket.forgetracker').focus();
- $('textarea[name="ticket_form.comment"]').val(not_posted_comment);
+ var cm = get_cm(form_holder);
+ cm.refresh();
+ cm.focus();
+ var comment_cm = get_cm($('textarea[name="ticket_form.comment"]').parent());
+ comment_cm.setValue(not_posted_comment);
+ $('textarea[name="ticket_form.description"]').trigger('editticket.forgetracker');
$(this).trigger('editTicket');
return false;
});
[18/21] allura git commit: [#7897] ticket:814 Fix focus when there
are more than one editor on a page
Posted by je...@apache.org.
[#7897] ticket:814 Fix focus when there are more than one editor on a page
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/81bb02ac
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/81bb02ac
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/81bb02ac
Branch: refs/heads/ib/7897
Commit: 81bb02ac3c5f439e7039a8f2ca2f07983c4e8ddc
Parents: 23eb07e
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 17:54:50 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 17:54:50 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/resources/js/sf_markitup.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/81bb02ac/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index 4c0cd20..f3466bc 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -61,7 +61,7 @@ $(window).load(function() {
editor.render();
// focus editor by clicking anywhere on it, not only on the first few lines
- $('.CodeMirror').click(function () { cm.focus(); });
+ $('.CodeMirror').click(function () { this.CodeMirror.focus(); });
function show_help(editor) {
$help_contents.html('Loading...');
[21/21] allura git commit: [#7897] ticket:814 Fix tests failing due
to new widget layout
Posted by je...@apache.org.
[#7897] ticket:814 Fix tests failing due to new widget layout
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/022cd7a7
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/022cd7a7
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/022cd7a7
Branch: refs/heads/ib/7897
Commit: 022cd7a7e112fc48985c3bebdf5baa73c1ac1550
Parents: f6dae26
Author: Igor Bondarenko <je...@gmail.com>
Authored: Wed Jul 8 12:10:12 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Jul 8 12:10:12 2015 +0300
----------------------------------------------------------------------
ForgeGit/forgegit/tests/functional/test_controllers.py | 8 --------
ForgeTracker/forgetracker/tests/functional/test_root.py | 4 ++--
2 files changed, 2 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/022cd7a7/ForgeGit/forgegit/tests/functional/test_controllers.py
----------------------------------------------------------------------
diff --git a/ForgeGit/forgegit/tests/functional/test_controllers.py b/ForgeGit/forgegit/tests/functional/test_controllers.py
index b84cd5a..0affb8c 100644
--- a/ForgeGit/forgegit/tests/functional/test_controllers.py
+++ b/ForgeGit/forgegit/tests/functional/test_controllers.py
@@ -721,14 +721,6 @@ class TestFork(_TestCase):
assert '<option selected value="zz">zz</option>' in r
md_edit = r.html.find('div', {'class': 'markdown_edit'})
assert md_edit is not None, 'MarkdownEdit widget not found'
- description = md_edit.find('textarea')
- assert_equal(description['name'], 'description')
- assert_equal(description['class'], 'auto_resize description')
- help_btn = md_edit.find('a', {'class': 'markdown_help btn'})
- preview_btn = md_edit.find('a', {'class': 'markdown_preview btn'})
- assert_equal(help_btn['href'], '/p/test/src-git/markdown_syntax_dialog')
- assert_equal(help_btn['title'], 'Formatting Help')
- assert_equal(preview_btn['title'], 'Preview')
r = self.app.post('/p/test/src-git/merge-requests/1/do_request_merge_edit',
params={
http://git-wip-us.apache.org/repos/asf/allura/blob/022cd7a7/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 122d707..daebaa3 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -840,7 +840,7 @@ class TestFunctionalController(TrackerTestController):
}, upload_files=[upload]).follow()
assert file_name in ticket_editor, ticket_editor.showbrowser()
req = self.app.get('/bugs/1/')
- file_link = req.html.findAll('form')[1].findAll('a')[6]
+ file_link = req.html.findAll('form')[1].findAll('a')[1]
assert_equal(file_link.string, file_name)
self.app.post(str(file_link['href']), {
'delete': 'True'
@@ -882,7 +882,7 @@ class TestFunctionalController(TrackerTestController):
ticket_editor = self.app.post('/bugs/1/update_ticket', {
'summary': 'zzz'
}, upload_files=[upload]).follow()
- download = self.app.get(str(ticket_editor.html.findAll('form')[1].findAll('a')[7]['href']))
+ download = self.app.get(str(ticket_editor.html.findAll('form')[1].findAll('a')[1]['href']))
assert_equal(download.body, file_data)
def test_two_attachments(self):
[02/21] allura git commit: [#7897] ticket:804 Show help modal on
"info" click
Posted by je...@apache.org.
[#7897] ticket:804 Show help modal on "info" click
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/677cb547
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/677cb547
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/677cb547
Branch: refs/heads/ib/7897
Commit: 677cb5471c280a4decf6dd0f47e7ee2cb2296680
Parents: e21a3cb
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jun 18 17:25:45 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 10:26:09 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/form_fields.py | 1 +
.../lib/widgets/resources/js/sf_markitup.js | 40 +++++++++++++++++++-
.../allura/templates/widgets/markdown_edit.html | 2 +-
3 files changed, 41 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/677cb547/Allura/allura/lib/widgets/form_fields.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index 40efd03..e6be401 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -271,6 +271,7 @@ class MarkdownEdit(ew.TextArea):
def resources(self):
for r in super(MarkdownEdit, self).resources():
yield r
+ yield ew.JSLink('js/jquery.lightbox_me.js')
yield ew.CSSLink('css/markdown_editor/editor.css')
yield ew.JSLink('js/markdown_editor/editor.js')
yield ew.JSLink('js/markdown_editor/marked.js')
http://git-wip-us.apache.org/repos/asf/allura/blob/677cb547/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index fd69c66..f57fb4b 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -23,7 +23,45 @@ $(window).load(function() {
$('div.markdown_edit').each(function(){
var $container = $(this);
var $textarea = $('textarea', $container);
- new Editor({element: $textarea[0]}).render();
+
+ var $help_area = $('div.markdown_help', $container);
+ var $help_contents = $('div.markdown_help_contents', $container);
+
+ var toolbar = Editor.toolbar;
+ toolbar[11] = {name: 'info', action: show_help},
+ toolbar[12] = {name: 'preview', action: show_preview},
+ new Editor({
+ element: $textarea[0],
+ toolbar: toolbar
+ }).render();
+
+ function show_help() {
+ $help_contents.html('Loading...');
+ $.get($help_contents.attr('data-url'), function (data) {
+ $help_contents.html(data);
+ var display_section = function(evt) {
+ var $all_sections = $('.markdown_syntax_section', $help_contents);
+ var $this_section = $(location.hash.replace('#', '.'), $help_contents);
+ if ($this_section.length == 0) {
+ $this_section = $('.md_ex_toc', $help_contents);
+ }
+ $all_sections.addClass('hidden_in_modal');
+ $this_section.removeClass('hidden_in_modal');
+ $('.markdown_syntax_toc_crumb').toggle(!$this_section.is('.md_ex_toc'));
+ };
+ $('.markdown_syntax_toc a', $help_contents).click(display_section);
+ $(window).bind('hashchange', display_section); // handle back button
+ });
+ $help_area.lightbox_me();
+ }
+
+ function show_preview() {
+ console.log('preview');
+ }
+
+ $('.close', $help_area).bind('click', function() {
+ $help_area.hide();
+ });
});
}
});
http://git-wip-us.apache.org/repos/asf/allura/blob/677cb547/Allura/allura/templates/widgets/markdown_edit.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/markdown_edit.html b/Allura/allura/templates/widgets/markdown_edit.html
index 8339bc7..773ea09 100644
--- a/Allura/allura/templates/widgets/markdown_edit.html
+++ b/Allura/allura/templates/widgets/markdown_edit.html
@@ -21,7 +21,7 @@
<textarea id="{{id or rendered_name}}" name="{{rendered_name}}" class="{{widget.css_class}}" {{widget.j2_attrs(attrs)}}>{{value or ''}}</textarea>
<div class="modal markdown_help" style="display:none">
<b data-icon="{{g.icons['close'].char}}" class="ico {{g.icons['close'].css}} close"></b>
- <div class="markdown_help_contents"></div>
+ <div class="markdown_help_contents" data-url="{{c.app.url}}markdown_syntax_dialog"></div>
</div>
<input type="hidden" class="markdown_project" value="{{c.project.shortname}}">
<input type="hidden" class="markdown_neighborhood" value="{{c.project.neighborhood._id}}">
[08/21] allura git commit: [#7897] ticket:804 Show text & focus
editor on the "Edit" and "Reply"
Posted by je...@apache.org.
[#7897] ticket:804 Show text & focus editor on the "Edit" and "Reply"
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/892d8844
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/892d8844
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/892d8844
Branch: refs/heads/ib/7897
Commit: 892d88443d9ea5f4d1051a0ea264e5f6603d3879
Parents: 390e933
Author: Igor Bondarenko <je...@gmail.com>
Authored: Fri Jun 19 15:57:01 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 10:26:10 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/discuss.py | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/892d8844/Allura/allura/lib/widgets/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index 3fe8f6c..db9342c 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -347,13 +347,16 @@ class Post(HierWidget):
});
});
+ function get_cm($elem) { return $('.CodeMirror', $elem)[0].CodeMirror; }
+
if($('a.edit_post', post)){
$('a.edit_post', post).click(function (ele) {
$('.display_post', post).hide();
- $('.edit_post_form', post).show();
- // Calling jQuery's ".focus()" forces browser to reload page
- // while using IE11 with sourceforge theme
- $('.edit_post_form textarea', post)[0].focus();
+ var $edit_post_form = $('.edit_post_form', post);
+ var cm = get_cm($edit_post_form);
+ $edit_post_form.show();
+ cm.refresh();
+ cm.focus();
return false;
});
$("a.cancel_edit_post", post).click(function(evt){
@@ -363,10 +366,10 @@ class Post(HierWidget):
}
if($('.reply_post', post)){
$('.reply_post', post).click(function (ele) {
- $('.reply_post_form', post).show();
- // Calling jQuery's ".focus()" forces browser to reload page
- // while using IE11 with sourceforge theme
- $('.reply_post_form textarea', post)[0].focus();
+ var $reply_post_form = $('.reply_post_form', post);
+ var cm = get_cm($reply_post_form);
+ $reply_post_form.show();
+ cm.focus();
return false;
});
$('.reply_post', post).button();
[19/21] allura git commit: [#7897] ticket:814 Fix styles for merge
request edit page
Posted by je...@apache.org.
[#7897] ticket:814 Fix styles for merge request edit page
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/da510f27
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/da510f27
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/da510f27
Branch: refs/heads/ib/7897
Commit: da510f2735f09176e075fac00948cf238009e3c8
Parents: 81bb02a
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 18:17:50 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 18:17:50 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/repo.py | 11 ++++-----
.../lib/widgets/resources/css/merge_request.css | 25 --------------------
2 files changed, 4 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/da510f27/Allura/allura/lib/widgets/repo.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/repo.py b/Allura/allura/lib/widgets/repo.py
index b3cb8dd..a43aa60 100644
--- a/Allura/allura/lib/widgets/repo.py
+++ b/Allura/allura/lib/widgets/repo.py
@@ -67,7 +67,9 @@ class SCMMergeRequestWidget(ff.ForgeForm):
@property
def fields(self):
result = [
- ew.TextField(name='summary', css_class='summary'),
+ ew.TextField(
+ name='summary',
+ attrs={'style': 'width: 93.5%;'}),
ew.SingleSelectField(
name='source_branch',
label='Source Branch',
@@ -76,14 +78,9 @@ class SCMMergeRequestWidget(ff.ForgeForm):
name='target_branch',
label='Target Branch',
options=self.target_branches),
- ffw.MarkdownEdit(
- name='description',
- css_class='auto_resize description')]
+ ffw.MarkdownEdit(name='description')]
return result
- def resources(self):
- yield ew.CSSLink('css/merge_request.css')
-
class SCMMergeRequestFilterWidget(ff.ForgeForm):
defaults = dict(
http://git-wip-us.apache.org/repos/asf/allura/blob/da510f27/Allura/allura/lib/widgets/resources/css/merge_request.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/merge_request.css b/Allura/allura/lib/widgets/resources/css/merge_request.css
deleted file mode 100644
index 839e3ac..0000000
--- a/Allura/allura/lib/widgets/resources/css/merge_request.css
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-.summary {
- width: 97%;
-}
-.description {
- width: 97%;
- height: 10em;
-}
[12/21] allura git commit: [#7897] ticket:804 Remove marked.js,
it's used only for preview and we have our own code for that
Posted by je...@apache.org.
[#7897] ticket:804 Remove marked.js, it's used only for preview and we have our own code for that
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/c5ed7851
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/c5ed7851
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/c5ed7851
Branch: refs/heads/ib/7897
Commit: c5ed785108f145911598e38de3e386e26183558f
Parents: 2008f8d
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 12:35:57 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 12:35:57 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/form_fields.py | 1 -
.../resources/js/markdown_editor/marked.js | 1165 ------------------
2 files changed, 1166 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/c5ed7851/Allura/allura/lib/widgets/form_fields.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index df928d2..c2a5ceb 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -275,7 +275,6 @@ class MarkdownEdit(ew.TextArea):
yield ew.CSSLink('css/markdown_editor/editor.css')
yield ew.CSSLink('css/markitup_sf.css')
yield ew.JSLink('js/markdown_editor/editor.js')
- yield ew.JSLink('js/markdown_editor/marked.js')
yield ew.JSLink('js/sf_markitup.js')
http://git-wip-us.apache.org/repos/asf/allura/blob/c5ed7851/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js b/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js
deleted file mode 100644
index 7a07c8a..0000000
--- a/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js
+++ /dev/null
@@ -1,1165 +0,0 @@
-/**
- * marked - a markdown parser
- * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/chjj/marked
- */
-
-;(function() {
-
-/**
- * Block-Level Grammar
- */
-
-var block = {
- newline: /^\n+/,
- code: /^( {4}[^\n]+\n*)+/,
- fences: noop,
- hr: /^( *[-*_]){3,} *(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
- nptable: noop,
- lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
- blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
- list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
- html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
- table: noop,
- paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
- text: /^[^\n]+/
-};
-
-block.bullet = /(?:[*+-]|\d+\.)/;
-block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
-block.item = replace(block.item, 'gm')
- (/bull/g, block.bullet)
- ();
-
-block.list = replace(block.list)
- (/bull/g, block.bullet)
- ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
- ();
-
-block._tag = '(?!(?:'
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
- + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
- + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
-
-block.html = replace(block.html)
- ('comment', /<!--[\s\S]*?-->/)
- ('closed', /<(tag)[\s\S]+?<\/\1>/)
- ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
- (/tag/g, block._tag)
- ();
-
-block.paragraph = replace(block.paragraph)
- ('hr', block.hr)
- ('heading', block.heading)
- ('lheading', block.lheading)
- ('blockquote', block.blockquote)
- ('tag', '<' + block._tag)
- ('def', block.def)
- ();
-
-/**
- * Normal Block Grammar
- */
-
-block.normal = merge({}, block);
-
-/**
- * GFM Block Grammar
- */
-
-block.gfm = merge({}, block.normal, {
- fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
- paragraph: /^/
-});
-
-block.gfm.paragraph = replace(block.paragraph)
- ('(?!', '(?!'
- + block.gfm.fences.source.replace('\\1', '\\2') + '|'
- + block.list.source.replace('\\1', '\\3') + '|')
- ();
-
-/**
- * GFM + Tables Block Grammar
- */
-
-block.tables = merge({}, block.gfm, {
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
-});
-
-/**
- * Block Lexer
- */
-
-function Lexer(options) {
- this.tokens = [];
- this.tokens.links = {};
- this.options = options || marked.defaults;
- this.rules = block.normal;
-
- if (this.options.gfm) {
- if (this.options.tables) {
- this.rules = block.tables;
- } else {
- this.rules = block.gfm;
- }
- }
-}
-
-/**
- * Expose Block Rules
- */
-
-Lexer.rules = block;
-
-/**
- * Static Lex Method
- */
-
-Lexer.lex = function(src, options) {
- var lexer = new Lexer(options);
- return lexer.lex(src);
-};
-
-/**
- * Preprocessing
- */
-
-Lexer.prototype.lex = function(src) {
- src = src
- .replace(/\r\n|\r/g, '\n')
- .replace(/\t/g, ' ')
- .replace(/\u00a0/g, ' ')
- .replace(/\u2424/g, '\n');
-
- return this.token(src, true);
-};
-
-/**
- * Lexing
- */
-
-Lexer.prototype.token = function(src, top) {
- var src = src.replace(/^ +$/gm, '')
- , next
- , loose
- , cap
- , bull
- , b
- , item
- , space
- , i
- , l;
-
- while (src) {
- // newline
- if (cap = this.rules.newline.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[0].length > 1) {
- this.tokens.push({
- type: 'space'
- });
- }
- }
-
- // code
- if (cap = this.rules.code.exec(src)) {
- src = src.substring(cap[0].length);
- cap = cap[0].replace(/^ {4}/gm, '');
- this.tokens.push({
- type: 'code',
- text: !this.options.pedantic
- ? cap.replace(/\n+$/, '')
- : cap
- });
- continue;
- }
-
- // fences (gfm)
- if (cap = this.rules.fences.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'code',
- lang: cap[2],
- text: cap[3]
- });
- continue;
- }
-
- // heading
- if (cap = this.rules.heading.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'heading',
- depth: cap[1].length,
- text: cap[2]
- });
- continue;
- }
-
- // table no leading pipe (gfm)
- if (top && (cap = this.rules.nptable.exec(src))) {
- src = src.substring(cap[0].length);
-
- item = {
- type: 'table',
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3].replace(/\n$/, '').split('\n')
- };
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = 'right';
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = 'center';
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = 'left';
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i].split(/ *\| */);
- }
-
- this.tokens.push(item);
-
- continue;
- }
-
- // lheading
- if (cap = this.rules.lheading.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'heading',
- depth: cap[2] === '=' ? 1 : 2,
- text: cap[1]
- });
- continue;
- }
-
- // hr
- if (cap = this.rules.hr.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'hr'
- });
- continue;
- }
-
- // blockquote
- if (cap = this.rules.blockquote.exec(src)) {
- src = src.substring(cap[0].length);
-
- this.tokens.push({
- type: 'blockquote_start'
- });
-
- cap = cap[0].replace(/^ *> ?/gm, '');
-
- // Pass `top` to keep the current
- // "toplevel" state. This is exactly
- // how markdown.pl works.
- this.token(cap, top);
-
- this.tokens.push({
- type: 'blockquote_end'
- });
-
- continue;
- }
-
- // list
- if (cap = this.rules.list.exec(src)) {
- src = src.substring(cap[0].length);
- bull = cap[2];
-
- this.tokens.push({
- type: 'list_start',
- ordered: bull.length > 1
- });
-
- // Get each top-level item.
- cap = cap[0].match(this.rules.item);
-
- next = false;
- l = cap.length;
- i = 0;
-
- for (; i < l; i++) {
- item = cap[i];
-
- // Remove the list item's bullet
- // so it is seen as the next token.
- space = item.length;
- item = item.replace(/^ *([*+-]|\d+\.) +/, '');
-
- // Outdent whatever the
- // list item contains. Hacky.
- if (~item.indexOf('\n ')) {
- space -= item.length;
- item = !this.options.pedantic
- ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
- : item.replace(/^ {1,4}/gm, '');
- }
-
- // Determine whether the next list item belongs here.
- // Backpedal if it does not belong in this list.
- if (this.options.smartLists && i !== l - 1) {
- b = block.bullet.exec(cap[i + 1])[0];
- if (bull !== b && !(bull.length > 1 && b.length > 1)) {
- src = cap.slice(i + 1).join('\n') + src;
- i = l - 1;
- }
- }
-
- // Determine whether item is loose or not.
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
- // for discount behavior.
- loose = next || /\n\n(?!\s*$)/.test(item);
- if (i !== l - 1) {
- next = item.charAt(item.length - 1) === '\n';
- if (!loose) loose = next;
- }
-
- this.tokens.push({
- type: loose
- ? 'loose_item_start'
- : 'list_item_start'
- });
-
- // Recurse.
- this.token(item, false);
-
- this.tokens.push({
- type: 'list_item_end'
- });
- }
-
- this.tokens.push({
- type: 'list_end'
- });
-
- continue;
- }
-
- // html
- if (cap = this.rules.html.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: this.options.sanitize
- ? 'paragraph'
- : 'html',
- pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
- text: cap[0]
- });
- continue;
- }
-
- // def
- if (top && (cap = this.rules.def.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.links[cap[1].toLowerCase()] = {
- href: cap[2],
- title: cap[3]
- };
- continue;
- }
-
- // table (gfm)
- if (top && (cap = this.rules.table.exec(src))) {
- src = src.substring(cap[0].length);
-
- item = {
- type: 'table',
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
- };
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = 'right';
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = 'center';
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = 'left';
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i]
- .replace(/^ *\| *| *\| *$/g, '')
- .split(/ *\| */);
- }
-
- this.tokens.push(item);
-
- continue;
- }
-
- // top-level paragraph
- if (top && (cap = this.rules.paragraph.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'paragraph',
- text: cap[1].charAt(cap[1].length - 1) === '\n'
- ? cap[1].slice(0, -1)
- : cap[1]
- });
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- // Top-level should never reach here.
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'text',
- text: cap[0]
- });
- continue;
- }
-
- if (src) {
- throw new
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return this.tokens;
-};
-
-/**
- * Inline-Level Grammar
- */
-
-var inline = {
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
- autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
- url: noop,
- tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
- link: /^!?\[(inside)\]\(href\)/,
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
- nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
- em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
- code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
- br: /^ {2,}\n(?!\s*$)/,
- del: noop,
- text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
-};
-
-inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
-inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
-
-inline.link = replace(inline.link)
- ('inside', inline._inside)
- ('href', inline._href)
- ();
-
-inline.reflink = replace(inline.reflink)
- ('inside', inline._inside)
- ();
-
-/**
- * Normal Inline Grammar
- */
-
-inline.normal = merge({}, inline);
-
-/**
- * Pedantic Inline Grammar
- */
-
-inline.pedantic = merge({}, inline.normal, {
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
-});
-
-/**
- * GFM Inline Grammar
- */
-
-inline.gfm = merge({}, inline.normal, {
- escape: replace(inline.escape)('])', '~|])')(),
- url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
- del: /^~~(?=\S)([\s\S]*?\S)~~/,
- text: replace(inline.text)
- (']|', '~]|')
- ('|', '|https?://|')
- ()
-});
-
-/**
- * GFM + Line Breaks Inline Grammar
- */
-
-inline.breaks = merge({}, inline.gfm, {
- br: replace(inline.br)('{2,}', '*')(),
- text: replace(inline.gfm.text)('{2,}', '*')()
-});
-
-/**
- * Inline Lexer & Compiler
- */
-
-function InlineLexer(links, options) {
- this.options = options || marked.defaults;
- this.links = links;
- this.rules = inline.normal;
-
- if (!this.links) {
- throw new
- Error('Tokens array requires a `links` property.');
- }
-
- if (this.options.gfm) {
- if (this.options.breaks) {
- this.rules = inline.breaks;
- } else {
- this.rules = inline.gfm;
- }
- } else if (this.options.pedantic) {
- this.rules = inline.pedantic;
- }
-}
-
-/**
- * Expose Inline Rules
- */
-
-InlineLexer.rules = inline;
-
-/**
- * Static Lexing/Compiling Method
- */
-
-InlineLexer.output = function(src, links, options) {
- var inline = new InlineLexer(links, options);
- return inline.output(src);
-};
-
-/**
- * Lexing/Compiling
- */
-
-InlineLexer.prototype.output = function(src) {
- var out = ''
- , link
- , text
- , href
- , cap;
-
- while (src) {
- // escape
- if (cap = this.rules.escape.exec(src)) {
- src = src.substring(cap[0].length);
- out += cap[1];
- continue;
- }
-
- // autolink
- if (cap = this.rules.autolink.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[2] === '@') {
- text = cap[1].charAt(6) === ':'
- ? this.mangle(cap[1].substring(7))
- : this.mangle(cap[1]);
- href = this.mangle('mailto:') + text;
- } else {
- text = escape(cap[1]);
- href = text;
- }
- out += '<a href="'
- + href
- + '">'
- + text
- + '</a>';
- continue;
- }
-
- // url (gfm)
- if (cap = this.rules.url.exec(src)) {
- src = src.substring(cap[0].length);
- text = escape(cap[1]);
- href = text;
- out += '<a href="'
- + href
- + '">'
- + text
- + '</a>';
- continue;
- }
-
- // tag
- if (cap = this.rules.tag.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.options.sanitize
- ? escape(cap[0])
- : cap[0];
- continue;
- }
-
- // link
- if (cap = this.rules.link.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.outputLink(cap, {
- href: cap[2],
- title: cap[3]
- });
- continue;
- }
-
- // reflink, nolink
- if ((cap = this.rules.reflink.exec(src))
- || (cap = this.rules.nolink.exec(src))) {
- src = src.substring(cap[0].length);
- link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
- link = this.links[link.toLowerCase()];
- if (!link || !link.href) {
- out += cap[0].charAt(0);
- src = cap[0].substring(1) + src;
- continue;
- }
- out += this.outputLink(cap, link);
- continue;
- }
-
- // strong
- if (cap = this.rules.strong.exec(src)) {
- src = src.substring(cap[0].length);
- out += '<strong>'
- + this.output(cap[2] || cap[1])
- + '</strong>';
- continue;
- }
-
- // em
- if (cap = this.rules.em.exec(src)) {
- src = src.substring(cap[0].length);
- out += '<em>'
- + this.output(cap[2] || cap[1])
- + '</em>';
- continue;
- }
-
- // code
- if (cap = this.rules.code.exec(src)) {
- src = src.substring(cap[0].length);
- out += '<code>'
- + escape(cap[2], true)
- + '</code>';
- continue;
- }
-
- // br
- if (cap = this.rules.br.exec(src)) {
- src = src.substring(cap[0].length);
- out += '<br>';
- continue;
- }
-
- // del (gfm)
- if (cap = this.rules.del.exec(src)) {
- src = src.substring(cap[0].length);
- out += '<del>'
- + this.output(cap[1])
- + '</del>';
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- src = src.substring(cap[0].length);
- out += escape(this.smartypants(cap[0]));
- continue;
- }
-
- if (src) {
- throw new
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return out;
-};
-
-/**
- * Compile Link
- */
-
-InlineLexer.prototype.outputLink = function(cap, link) {
- if (cap[0].charAt(0) !== '!') {
- return '<a href="'
- + escape(link.href)
- + '"'
- + (link.title
- ? ' title="'
- + escape(link.title)
- + '"'
- : '')
- + '>'
- + this.output(cap[1])
- + '</a>';
- } else {
- return '<img src="'
- + escape(link.href)
- + '" alt="'
- + escape(cap[1])
- + '"'
- + (link.title
- ? ' title="'
- + escape(link.title)
- + '"'
- : '')
- + '>';
- }
-};
-
-/**
- * Smartypants Transformations
- */
-
-InlineLexer.prototype.smartypants = function(text) {
- if (!this.options.smartypants) return text;
- return text
- // em-dashes
- .replace(/--/g, '\u2014')
- // opening singles
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
- // closing singles & apostrophes
- .replace(/'/g, '\u2019')
- // opening doubles
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
- // closing doubles
- .replace(/"/g, '\u201d')
- // ellipses
- .replace(/\.{3}/g, '\u2026');
-};
-
-/**
- * Mangle Links
- */
-
-InlineLexer.prototype.mangle = function(text) {
- var out = ''
- , l = text.length
- , i = 0
- , ch;
-
- for (; i < l; i++) {
- ch = text.charCodeAt(i);
- if (Math.random() > 0.5) {
- ch = 'x' + ch.toString(16);
- }
- out += '&#' + ch + ';';
- }
-
- return out;
-};
-
-/**
- * Parsing & Compiling
- */
-
-function Parser(options) {
- this.tokens = [];
- this.token = null;
- this.options = options || marked.defaults;
-}
-
-/**
- * Static Parse Method
- */
-
-Parser.parse = function(src, options) {
- var parser = new Parser(options);
- return parser.parse(src);
-};
-
-/**
- * Parse Loop
- */
-
-Parser.prototype.parse = function(src) {
- this.inline = new InlineLexer(src.links, this.options);
- this.tokens = src.reverse();
-
- var out = '';
- while (this.next()) {
- out += this.tok();
- }
-
- return out;
-};
-
-/**
- * Next Token
- */
-
-Parser.prototype.next = function() {
- return this.token = this.tokens.pop();
-};
-
-/**
- * Preview Next Token
- */
-
-Parser.prototype.peek = function() {
- return this.tokens[this.tokens.length - 1] || 0;
-};
-
-/**
- * Parse Text Tokens
- */
-
-Parser.prototype.parseText = function() {
- var body = this.token.text;
-
- while (this.peek().type === 'text') {
- body += '\n' + this.next().text;
- }
-
- return this.inline.output(body);
-};
-
-/**
- * Parse Current Token
- */
-
-Parser.prototype.tok = function() {
- switch (this.token.type) {
- case 'space': {
- return '';
- }
- case 'hr': {
- return '<hr>\n';
- }
- case 'heading': {
- return '<h'
- + this.token.depth
- + ' id="'
- + this.token.text.toLowerCase().replace(/[^\w]+/g, '-')
- + '">'
- + this.inline.output(this.token.text)
- + '</h'
- + this.token.depth
- + '>\n';
- }
- case 'code': {
- if (this.options.highlight) {
- var code = this.options.highlight(this.token.text, this.token.lang);
- if (code != null && code !== this.token.text) {
- this.token.escaped = true;
- this.token.text = code;
- }
- }
-
- if (!this.token.escaped) {
- this.token.text = escape(this.token.text, true);
- }
-
- return '<pre><code'
- + (this.token.lang
- ? ' class="'
- + this.options.langPrefix
- + this.token.lang
- + '"'
- : '')
- + '>'
- + this.token.text
- + '</code></pre>\n';
- }
- case 'table': {
- var body = ''
- , heading
- , i
- , row
- , cell
- , j;
-
- // header
- body += '<thead>\n<tr>\n';
- for (i = 0; i < this.token.header.length; i++) {
- heading = this.inline.output(this.token.header[i]);
- body += '<th';
- if (this.token.align[i]) {
- body += ' style="text-align:' + this.token.align[i] + '"';
- }
- body += '>' + heading + '</th>\n';
- }
- body += '</tr>\n</thead>\n';
-
- // body
- body += '<tbody>\n'
- for (i = 0; i < this.token.cells.length; i++) {
- row = this.token.cells[i];
- body += '<tr>\n';
- for (j = 0; j < row.length; j++) {
- cell = this.inline.output(row[j]);
- body += '<td';
- if (this.token.align[j]) {
- body += ' style="text-align:' + this.token.align[j] + '"';
- }
- body += '>' + cell + '</td>\n';
- }
- body += '</tr>\n';
- }
- body += '</tbody>\n';
-
- return '<table>\n'
- + body
- + '</table>\n';
- }
- case 'blockquote_start': {
- var body = '';
-
- while (this.next().type !== 'blockquote_end') {
- body += this.tok();
- }
-
- return '<blockquote>\n'
- + body
- + '</blockquote>\n';
- }
- case 'list_start': {
- var type = this.token.ordered ? 'ol' : 'ul'
- , body = '';
-
- while (this.next().type !== 'list_end') {
- body += this.tok();
- }
-
- return '<'
- + type
- + '>\n'
- + body
- + '</'
- + type
- + '>\n';
- }
- case 'list_item_start': {
- var body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.token.type === 'text'
- ? this.parseText()
- : this.tok();
- }
-
- return '<li>'
- + body
- + '</li>\n';
- }
- case 'loose_item_start': {
- var body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.tok();
- }
-
- return '<li>'
- + body
- + '</li>\n';
- }
- case 'html': {
- return !this.token.pre && !this.options.pedantic
- ? this.inline.output(this.token.text)
- : this.token.text;
- }
- case 'paragraph': {
- return '<p>'
- + this.inline.output(this.token.text)
- + '</p>\n';
- }
- case 'text': {
- return '<p>'
- + this.parseText()
- + '</p>\n';
- }
- }
-};
-
-/**
- * Helpers
- */
-
-function escape(html, encode) {
- return html
- .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/'/g, ''');
-}
-
-function replace(regex, opt) {
- regex = regex.source;
- opt = opt || '';
- return function self(name, val) {
- if (!name) return new RegExp(regex, opt);
- val = val.source || val;
- val = val.replace(/(^|[^\[])\^/g, '$1');
- regex = regex.replace(name, val);
- return self;
- };
-}
-
-function noop() {}
-noop.exec = noop;
-
-function merge(obj) {
- var i = 1
- , target
- , key;
-
- for (; i < arguments.length; i++) {
- target = arguments[i];
- for (key in target) {
- if (Object.prototype.hasOwnProperty.call(target, key)) {
- obj[key] = target[key];
- }
- }
- }
-
- return obj;
-}
-
-/**
- * Marked
- */
-
-function marked(src, opt, callback) {
- if (callback || typeof opt === 'function') {
- if (!callback) {
- callback = opt;
- opt = null;
- }
-
- opt = merge({}, marked.defaults, opt || {});
-
- var highlight = opt.highlight
- , tokens
- , pending
- , i = 0;
-
- try {
- tokens = Lexer.lex(src, opt)
- } catch (e) {
- return callback(e);
- }
-
- pending = tokens.length;
-
- var done = function() {
- var out, err;
-
- try {
- out = Parser.parse(tokens, opt);
- } catch (e) {
- err = e;
- }
-
- opt.highlight = highlight;
-
- return err
- ? callback(err)
- : callback(null, out);
- };
-
- if (!highlight || highlight.length < 3) {
- return done();
- }
-
- delete opt.highlight;
-
- if (!pending) return done();
-
- for (; i < tokens.length; i++) {
- (function(token) {
- if (token.type !== 'code') {
- return --pending || done();
- }
- return highlight(token.text, token.lang, function(err, code) {
- if (code == null || code === token.text) {
- return --pending || done();
- }
- token.text = code;
- token.escaped = true;
- --pending || done();
- });
- })(tokens[i]);
- }
-
- return;
- }
- try {
- if (opt) opt = merge({}, marked.defaults, opt);
- return Parser.parse(Lexer.lex(src, opt), opt);
- } catch (e) {
- e.message += '\nPlease report this to https://github.com/chjj/marked.';
- if ((opt || marked.defaults).silent) {
- return '<p>An error occured:</p><pre>'
- + escape(e.message + '', true)
- + '</pre>';
- }
- throw e;
- }
-}
-
-/**
- * Options
- */
-
-marked.options =
-marked.setOptions = function(opt) {
- merge(marked.defaults, opt);
- return marked;
-};
-
-marked.defaults = {
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- smartLists: false,
- silent: false,
- highlight: null,
- langPrefix: 'lang-',
- smartypants: false
-};
-
-/**
- * Expose
- */
-
-marked.Parser = Parser;
-marked.parser = Parser.parse;
-
-marked.Lexer = Lexer;
-marked.lexer = Lexer.lex;
-
-marked.InlineLexer = InlineLexer;
-marked.inlineLexer = InlineLexer.output;
-
-marked.parse = marked;
-
-if (typeof exports === 'object') {
- module.exports = marked;
-} else if (typeof define === 'function' && define.amd) {
- define(function() { return marked; });
-} else {
- this.marked = marked;
-}
-
-}).call(function() {
- return this || (typeof window !== 'undefined' ? window : global);
-}());
[09/21] allura git commit: [#7897] ticket:804 Add basic styles for
new editor
Posted by je...@apache.org.
[#7897] ticket:804 Add basic styles for new editor
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d4d6225f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d4d6225f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d4d6225f
Branch: refs/heads/ib/7897
Commit: d4d6225f7dea1314ba7de436626f2a08824218ef
Parents: 892d884
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 11:38:29 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 11:38:29 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/form_fields.py | 1 +
.../lib/widgets/resources/css/markitup_sf.css | 46 ++++++++++++++++++++
2 files changed, 47 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/d4d6225f/Allura/allura/lib/widgets/form_fields.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index e6be401..df928d2 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -273,6 +273,7 @@ class MarkdownEdit(ew.TextArea):
yield r
yield ew.JSLink('js/jquery.lightbox_me.js')
yield ew.CSSLink('css/markdown_editor/editor.css')
+ yield ew.CSSLink('css/markitup_sf.css')
yield ew.JSLink('js/markdown_editor/editor.js')
yield ew.JSLink('js/markdown_editor/marked.js')
yield ew.JSLink('js/sf_markitup.js')
http://git-wip-us.apache.org/repos/asf/allura/blob/d4d6225f/Allura/allura/lib/widgets/resources/css/markitup_sf.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markitup_sf.css b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
new file mode 100644
index 0000000..7ac5814
--- /dev/null
+++ b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
@@ -0,0 +1,46 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+.markdown_edit {
+ height: 200px;
+ width: 95%;
+ font-family: Consolas, "Andale Mono", "Lucida Console", monospace;
+
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ -o-border-radius: 4px;
+ -ms-border-radius: 4px;
+ -khtml-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
+ -o-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) inset,0 1px 0 rgba(255, 255, 255, 0.9);
+ border: medium none;
+ margin-bottom: 5px;
+ margin-left: 2px;
+ border: 1px solid #aaaaaa;
+}
+
+.markdown_edit .editor-toolbar:before {
+ background: none; /* hide toolbar's top border */
+}
+
+.markdown_edit .CodeMirror-scroll {
+ padding: 5px;
+}
[03/21] allura git commit: [#7897] ticket:804 Get rid of all the
stuff which does not needed with a new widget
Posted by je...@apache.org.
[#7897] ticket:804 Get rid of all the stuff which does not needed with a new widget
- Textarea tabby plugin (jquery.textarea.js). New plugin handles tabs by
itself
- help/preview buttons
- old css/js
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e21a3cb5
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e21a3cb5
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e21a3cb5
Branch: refs/heads/ib/7897
Commit: e21a3cb5d05aca0930c22a34c698b4ff226be5d1
Parents: ab2b11e
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jun 18 16:55:24 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 10:26:09 2015 +0300
----------------------------------------------------------------------
Allura/LICENSE | 1 -
Allura/allura/lib/widgets/form_fields.py | 9 +-
.../lib/widgets/resources/css/markitup_sf.css | 27 --
.../lib/widgets/resources/js/jquery.textarea.js | 267 -------------------
.../lib/widgets/resources/js/sf_markitup.js | 59 +---
.../allura/templates/widgets/markdown_edit.html | 7 -
LICENSE | 1 -
rat-excludes.txt | 1 -
8 files changed, 4 insertions(+), 368 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/Allura/LICENSE
----------------------------------------------------------------------
diff --git a/Allura/LICENSE b/Allura/LICENSE
index 452064c..9823dc6 100644
--- a/Allura/LICENSE
+++ b/Allura/LICENSE
@@ -228,7 +228,6 @@ under the MIT license. For details, see the individual files:
allura/lib/widgets/resources/js/jquery.autosize-min.js
allura/lib/widgets/resources/js/jquery.colorPicker.js
allura/lib/widgets/resources/js/jquery.tagsinput.js
- allura/lib/widgets/resources/js/jquery.textarea.js
allura/public/nf/js/jquery.flot.js
allura/public/nf/js/jquery.maxlength.min.js
allura/public/nf/js/jquery.viewport.js
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/Allura/allura/lib/widgets/form_fields.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/form_fields.py b/Allura/allura/lib/widgets/form_fields.py
index b201f6a..40efd03 100644
--- a/Allura/allura/lib/widgets/form_fields.py
+++ b/Allura/allura/lib/widgets/form_fields.py
@@ -256,11 +256,11 @@ class AutoResizeTextarea(ew.TextArea):
''')
-class MarkdownEdit(AutoResizeTextarea):
+class MarkdownEdit(ew.TextArea):
template = 'jinja:allura:templates/widgets/markdown_edit.html'
validator = fev.UnicodeString()
defaults = dict(
- AutoResizeTextarea.defaults,
+ ew.TextArea.defaults,
name=None,
value=None,
show_label=True)
@@ -271,13 +271,10 @@ class MarkdownEdit(AutoResizeTextarea):
def resources(self):
for r in super(MarkdownEdit, self).resources():
yield r
- yield ew.JSLink('js/jquery.lightbox_me.js')
- yield ew.JSLink('js/jquery.textarea.js')
- yield ew.JSLink('js/sf_markitup.js')
- yield ew.CSSLink('css/markitup_sf.css')
yield ew.CSSLink('css/markdown_editor/editor.css')
yield ew.JSLink('js/markdown_editor/editor.js')
yield ew.JSLink('js/markdown_editor/marked.js')
+ yield ew.JSLink('js/sf_markitup.js')
class PageList(ew_core.Widget):
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/Allura/allura/lib/widgets/resources/css/markitup_sf.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markitup_sf.css b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
deleted file mode 100644
index f8d4cba..0000000
--- a/Allura/allura/lib/widgets/resources/css/markitup_sf.css
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-.markdown_edit textarea{
- height: 200px;
- width: 95%;
- font-family: Consolas, "Andale Mono", "Lucida Console", monospace;
-}
-.markdown_edit .btn{
- margin: 5px 5px 5px 0;
- display: inline-block;
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/Allura/allura/lib/widgets/resources/js/jquery.textarea.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/jquery.textarea.js b/Allura/allura/lib/widgets/resources/js/jquery.textarea.js
deleted file mode 100644
index af572ba..0000000
--- a/Allura/allura/lib/widgets/resources/js/jquery.textarea.js
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Tabby jQuery plugin version 0.12
- *
- * Ted Devito - http://teddevito.com/demos/textarea.html
- *
- * Copyright (c) 2009 Ted Devito
- *
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-// create closure
-
-(function($) {
-
- // plugin definition
-
- $.fn.tabby = function(options) {
- //debug(this);
- // build main options before element iteration
- var opts = $.extend({}, $.fn.tabby.defaults, options);
- var pressed = $.fn.tabby.pressed;
-
- // iterate and reformat each matched element
- return this.each(function() {
- $this = $(this);
-
- // build element specific options
- var options = $.meta ? $.extend({}, opts, $this.data()) : opts;
-
- $this.bind('keydown',function (e) {
- var kc = $.fn.tabby.catch_kc(e);
- if (16 == kc) pressed.shft = true;
- /*
- because both CTRL+TAB and ALT+TAB default to an event (changing tab/window) that
- will prevent js from capturing the keyup event, we'll set a timer on releasing them.
- */
- if (17 == kc) {pressed.ctrl = true; setTimeout("$.fn.tabby.pressed.ctrl = false;",1000);}
- if (18 == kc) {pressed.alt = true; setTimeout("$.fn.tabby.pressed.alt = false;",1000);}
-
- if (9 == kc && !pressed.ctrl && !pressed.alt) {
- e.preventDefault; // does not work in O9.63 ??
- pressed.last = kc; setTimeout("$.fn.tabby.pressed.last = null;",0);
- process_keypress ($(e.target).get(0), pressed.shft, options);
- return false;
- }
-
- }).bind('keyup',function (e) {
- if (16 == $.fn.tabby.catch_kc(e)) pressed.shft = false;
- }).bind('blur',function (e) { // workaround for Opera -- http://www.webdeveloper.com/forum/showthread.php?p=806588
- if (9 == pressed.last) $(e.target).one('focus',function (e) {pressed.last = null;}).get(0).focus();
- });
-
- });
- };
-
- // define and expose any extra methods
- $.fn.tabby.catch_kc = function(e) { return e.keyCode ? e.keyCode : e.charCode ? e.charCode : e.which; };
- $.fn.tabby.pressed = {shft : false, ctrl : false, alt : false, last: null};
-
- // private function for debugging
- function debug($obj) {
- if (window.console && window.console.log)
- window.console.log('textarea count: ' + $obj.size());
- };
-
- function process_keypress (o,shft,options) {
- var scrollTo = o.scrollTop;
- //var tabString = String.fromCharCode(9);
-
- // gecko; o.setSelectionRange is only available when the text box has focus
- if (o.setSelectionRange) gecko_tab (o, shft, options);
-
- // ie; document.selection is always available
- else if (document.selection) ie_tab (o, shft, options);
-
- o.scrollTop = scrollTo;
- }
-
- // plugin defaults
- $.fn.tabby.defaults = {tabString : String.fromCharCode(9)};
-
- function gecko_tab (o, shft, options) {
- var ss = o.selectionStart;
- var es = o.selectionEnd;
-
- // when there's no selection and we're just working with the caret, we'll add/remove the tabs at the caret, providing more control
- if(ss == es) {
- // SHIFT+TAB
- if (shft) {
- // check to the left of the caret first
- if ("\t" == o.value.substring(ss-options.tabString.length, ss)) {
- o.value = o.value.substring(0, ss-options.tabString.length) + o.value.substring(ss); // put it back together omitting one character to the left
- o.focus();
- o.setSelectionRange(ss - options.tabString.length, ss - options.tabString.length);
- }
- // then check to the right of the caret
- else if ("\t" == o.value.substring(ss, ss + options.tabString.length)) {
- o.value = o.value.substring(0, ss) + o.value.substring(ss + options.tabString.length); // put it back together omitting one character to the right
- o.focus();
- o.setSelectionRange(ss,ss);
- }
- }
- // TAB
- else {
- o.value = o.value.substring(0, ss) + options.tabString + o.value.substring(ss);
- o.focus();
- o.setSelectionRange(ss + options.tabString.length, ss + options.tabString.length);
- }
- }
- // selections will always add/remove tabs from the start of the line
- else {
- // split the textarea up into lines and figure out which lines are included in the selection
- var lines = o.value.split("\n");
- var indices = new Array();
- var sl = 0; // start of the line
- var el = 0; // end of the line
- var sel = false;
- for (var i in lines) {
- el = sl + lines[i].length;
- indices.push({start: sl, end: el, selected: (sl <= ss && el > ss) || (el >= es && sl < es) || (sl > ss && el < es)});
- sl = el + 1;// for "\n"
- }
-
- // walk through the array of lines (indices) and add tabs where appropriate
- var modifier = 0;
- for (var i in indices) {
- if (indices[i].selected) {
- var pos = indices[i].start + modifier; // adjust for tabs already inserted/removed
- // SHIFT+TAB
- if (shft && options.tabString == o.value.substring(pos,pos+options.tabString.length)) { // only SHIFT+TAB if there's a tab at the start of the line
- o.value = o.value.substring(0,pos) + o.value.substring(pos + options.tabString.length); // omit the tabstring to the right
- modifier -= options.tabString.length;
- }
- // TAB
- else if (!shft) {
- o.value = o.value.substring(0,pos) + options.tabString + o.value.substring(pos); // insert the tabstring
- modifier += options.tabString.length;
- }
- }
- }
- o.focus();
- var ns = ss + ((modifier > 0) ? options.tabString.length : (modifier < 0) ? -options.tabString.length : 0);
- var ne = es + modifier;
- o.setSelectionRange(ns,ne);
- }
- }
-
- function ie_tab (o, shft, options) {
- var range = document.selection.createRange();
-
- if (o == range.parentElement()) {
- // when there's no selection and we're just working with the caret, we'll add/remove the tabs at the caret, providing more control
- if ('' == range.text) {
- // SHIFT+TAB
- if (shft) {
- var bookmark = range.getBookmark();
- //first try to the left by moving opening up our empty range to the left
- range.moveStart('character', -options.tabString.length);
- if (options.tabString == range.text) {
- range.text = '';
- } else {
- // if that didn't work then reset the range and try opening it to the right
- range.moveToBookmark(bookmark);
- range.moveEnd('character', options.tabString.length);
- if (options.tabString == range.text)
- range.text = '';
- }
- // move the pointer to the start of them empty range and select it
- range.collapse(true);
- range.select();
- }
-
- else {
- // very simple here. just insert the tab into the range and put the pointer at the end
- range.text = options.tabString;
- range.collapse(false);
- range.select();
- }
- }
- // selections will always add/remove tabs from the start of the line
- else {
-
- var selection_text = range.text;
- var selection_len = selection_text.length;
- var selection_arr = selection_text.split("\r\n");
-
- var before_range = document.body.createTextRange();
- before_range.moveToElementText(o);
- before_range.setEndPoint("EndToStart", range);
- var before_text = before_range.text;
- var before_arr = before_text.split("\r\n");
- var before_len = before_text.length; // - before_arr.length + 1;
-
- var after_range = document.body.createTextRange();
- after_range.moveToElementText(o);
- after_range.setEndPoint("StartToEnd", range);
- var after_text = after_range.text; // we can accurately calculate distance to the end because we're not worried about MSIE trimming a \r\n
-
- var end_range = document.body.createTextRange();
- end_range.moveToElementText(o);
- end_range.setEndPoint("StartToEnd", before_range);
- var end_text = end_range.text; // we can accurately calculate distance to the end because we're not worried about MSIE trimming a \r\n
-
- var check_html = $(o).html();
- $("#r3").text(before_len + " + " + selection_len + " + " + after_text.length + " = " + check_html.length);
- if((before_len + end_text.length) < check_html.length) {
- before_arr.push("");
- before_len += 2; // for the \r\n that was trimmed
- if (shft && options.tabString == selection_arr[0].substring(0,options.tabString.length))
- selection_arr[0] = selection_arr[0].substring(options.tabString.length);
- else if (!shft) selection_arr[0] = options.tabString + selection_arr[0];
- } else {
- if (shft && options.tabString == before_arr[before_arr.length-1].substring(0,options.tabString.length))
- before_arr[before_arr.length-1] = before_arr[before_arr.length-1].substring(options.tabString.length);
- else if (!shft) before_arr[before_arr.length-1] = options.tabString + before_arr[before_arr.length-1];
- }
-
- for (var i = 1; i < selection_arr.length; i++) {
- if (shft && options.tabString == selection_arr[i].substring(0,options.tabString.length))
- selection_arr[i] = selection_arr[i].substring(options.tabString.length);
- else if (!shft) selection_arr[i] = options.tabString + selection_arr[i];
- }
-
- if (1 == before_arr.length && 0 == before_len) {
- if (shft && options.tabString == selection_arr[0].substring(0,options.tabString.length))
- selection_arr[0] = selection_arr[0].substring(options.tabString.length);
- else if (!shft) selection_arr[0] = options.tabString + selection_arr[0];
- }
-
- if ((before_len + selection_len + after_text.length) < check_html.length) {
- selection_arr.push("");
- selection_len += 2; // for the \r\n that was trimmed
- }
-
- before_range.text = before_arr.join("\r\n");
- range.text = selection_arr.join("\r\n");
-
- var new_range = document.body.createTextRange();
- new_range.moveToElementText(o);
-
- if (0 < before_len) new_range.setEndPoint("StartToEnd", before_range);
- else new_range.setEndPoint("StartToStart", before_range);
- new_range.setEndPoint("EndToEnd", range);
-
- new_range.select();
-
- }
- }
- }
-
-// end of closure
-})(jQuery);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index ecb84db..fd69c66 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -23,64 +23,7 @@ $(window).load(function() {
$('div.markdown_edit').each(function(){
var $container = $(this);
var $textarea = $('textarea', $container);
- new Editor({
- element: $textarea[0]
- }).render();
- $textarea.tabby({tabString : " "});
- var $preview = $('a.markdown_preview', $container);
- var $edit = $('a.markdown_edit', $container);
- var $help = $('a.markdown_help', $container);
- var $preview_area = $('div.markdown_preview', $container);
- var $help_area = $('div.markdown_help', $container);
- var $help_contents = $('div.markdown_help_contents', $container);
- $preview.click(function(evt){
- evt.preventDefault();
- var cval = $.cookie('_session_id');
- $.post('/nf/markdown_to_html', {
- markdown:$textarea.val(),
- project:$('input.markdown_project', $container).val(),
- neighborhood:$('input.markdown_neighborhood', $container).val(),
- app:$('input.markdown_app', $container).val(),
- _session_id:cval
- },
- function(resp){
- $preview_area.html(resp);
- $preview_area.show();
- $textarea.hide();
- $preview.hide();
- $edit.show();
- });
- });
- $edit.click(function(evt){
- evt.preventDefault();
- $preview_area.hide();
- $textarea.show();
- $preview.show();
- $edit.hide();
- });
- $help.click(function(evt){
- evt.preventDefault();
- $help_contents.html('Loading...');
- $.get($help.attr('href'), function (data) {
- $help_contents.html(data);
- var display_section = function(evt) {
- var $all_sections = $('.markdown_syntax_section', $help_contents);
- var $this_section = $(location.hash.replace('#', '.'), $help_contents);
- if ($this_section.length == 0) {
- $this_section = $('.md_ex_toc', $help_contents);
- }
- $all_sections.addClass('hidden_in_modal');
- $this_section.removeClass('hidden_in_modal');
- $('.markdown_syntax_toc_crumb').toggle(!$this_section.is('.md_ex_toc'));
- };
- $('.markdown_syntax_toc a', $help_contents).click(display_section);
- $(window).bind('hashchange', display_section); // handle back button
- });
- $help_area.lightbox_me();
- });
- $('.close', $help_area).bind('click', function() {
- $help_area.hide();
- });
+ new Editor({element: $textarea[0]}).render();
});
}
});
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/Allura/allura/templates/widgets/markdown_edit.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/markdown_edit.html b/Allura/allura/templates/widgets/markdown_edit.html
index b134558..8339bc7 100644
--- a/Allura/allura/templates/widgets/markdown_edit.html
+++ b/Allura/allura/templates/widgets/markdown_edit.html
@@ -18,14 +18,7 @@
-#}
{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
<div class="markdown_edit">
- <a href="#" class="markdown_preview btn" title="Preview"><b data-icon="{{g.icons['search'].char}}" class="ico {{g.icons['search'].css}}"></b> Preview</a>
- <a href="#" class="markdown_edit btn" style="display:none" title="Edit"><b data-icon="{{g.icons['pencil'].char}}" class="ico {{g.icons['pencil'].css}}"></b> Edit</a>
- <a href="{{c.app.url}}markdown_syntax_dialog" class="markdown_help btn" title="Formatting Help"><b data-icon="{{g.icons['help'].char}}" class="ico {{g.icons['help'].css}}"></b> Formatting Help</a>
- <div style="clear:both"></div>
<textarea id="{{id or rendered_name}}" name="{{rendered_name}}" class="{{widget.css_class}}" {{widget.j2_attrs(attrs)}}>{{value or ''}}</textarea>
- <div class="markdown_preview" style="display:none"></div>
- <a href="#" class="markdown_preview btn" title="Preview"><b data-icon="{{g.icons['search'].char}}" class="ico {{g.icons['search'].css}}"></b> Preview</a>
- <a href="#" class="markdown_edit btn" style="display:none" title="Edit"><b data-icon="{{g.icons['pencil'].char}}" class="ico {{g.icons['pencil'].css}}"></b> Edit</a>
<div class="modal markdown_help" style="display:none">
<b data-icon="{{g.icons['close'].char}}" class="ico {{g.icons['close'].css}} close"></b>
<div class="markdown_help_contents"></div>
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index d36ef6e..d371ff5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -229,7 +229,6 @@ under the MIT license. For details, see the individual files:
Allura/allura/lib/widgets/resources/js/jquery.autosize-min.js
Allura/allura/lib/widgets/resources/js/jquery.colorPicker.js
Allura/allura/lib/widgets/resources/js/jquery.tagsinput.js
- Allura/allura/lib/widgets/resources/js/jquery.textarea.js
Allura/allura/public/nf/js/jquery.flot.js
Allura/allura/public/nf/js/jquery.maxlength.min.js
allura/public/nf/js/jquery.viewport.js
http://git-wip-us.apache.org/repos/asf/allura/blob/e21a3cb5/rat-excludes.txt
----------------------------------------------------------------------
diff --git a/rat-excludes.txt b/rat-excludes.txt
index ee547eb..95c2eaf 100644
--- a/rat-excludes.txt
+++ b/rat-excludes.txt
@@ -22,7 +22,6 @@ Allura/allura/lib/widgets/resources/js/jqfontselector.js
Allura/allura/lib/widgets/resources/js/jquery.autosize-min.js
Allura/allura/lib/widgets/resources/js/jquery.colorPicker.js
Allura/allura/lib/widgets/resources/js/jquery.tagsinput.js
-Allura/allura/lib/widgets/resources/js/jquery.textarea.js
Allura/allura/public/nf/js/jquery.flot.js
Allura/allura/public/nf/js/jquery.maxlength.min.js
Allura/allura/public/nf/js/jquery.tablesorter.js
[10/21] allura git commit: [#7897] ticket:804 Autoresize editor
Posted by je...@apache.org.
[#7897] ticket:804 Autoresize editor
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/6556bcff
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/6556bcff
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/6556bcff
Branch: refs/heads/ib/7897
Commit: 6556bcffaefbc2266f856a06736943c242c8da97
Parents: d4d6225
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 11:41:30 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 11:41:30 2015 +0300
----------------------------------------------------------------------
.../allura/lib/widgets/resources/css/markitup_sf.css | 9 ++++++++-
Allura/allura/lib/widgets/resources/js/sf_markitup.js | 13 +++++++++++--
2 files changed, 19 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/6556bcff/Allura/allura/lib/widgets/resources/css/markitup_sf.css
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/css/markitup_sf.css b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
index 7ac5814..2c12807 100644
--- a/Allura/allura/lib/widgets/resources/css/markitup_sf.css
+++ b/Allura/allura/lib/widgets/resources/css/markitup_sf.css
@@ -18,6 +18,7 @@
*/
.markdown_edit {
height: 200px;
+ min-height: 200px;
width: 95%;
font-family: Consolas, "Andale Mono", "Lucida Console", monospace;
@@ -37,10 +38,16 @@
border: 1px solid #aaaaaa;
}
+.markdown_edit .CodeMirror {
+ height: auto;
+ min-height: 120px;
+}
+
.markdown_edit .editor-toolbar:before {
background: none; /* hide toolbar's top border */
}
-.markdown_edit .CodeMirror-scroll {
+.markdown_edit .CodeMirror-sizer,
+.markdown_edit .editor-preview {
padding: 5px;
}
http://git-wip-us.apache.org/repos/asf/allura/blob/6556bcff/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index 266d77a..f3f2c44 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -46,10 +46,19 @@ $(window).load(function() {
}
toolbar.push(tool);
}
- new Editor({
+ var editor = new Editor({
element: $textarea[0],
toolbar: toolbar
- }).render();
+ });
+ var cm = editor.codemirror;
+ cm.on('viewportChange', function(cm, from, to) {
+ var toolbar_h = $('.editor-toolbar', $container).outerHeight();
+ var statusbar_h = $('.editor-statusbar', $container).outerHeight();
+ var cm_h = cm.getScrollInfo().clientHeight;
+ var h = toolbar_h + statusbar_h + cm_h;
+ $container.height(h);
+ });
+ editor.render();
function show_help(editor) {
$help_contents.html('Loading...');
[11/21] allura git commit: [#7897] ticket:804 Don't focus editor on
render
Posted by je...@apache.org.
[#7897] ticket:804 Don't focus editor on render
It is a bit hacky, because we change it in the library code, but it does
not give us any options here. We probably should fork the library and
make the following changes:
- allow custom options to be passed to CodeMirror
- allow custom code to render preview (saves us from copy&pasting some
code)
- allow override toolbar buttons with custom actions (we can redefine
code block button, instead of hiding it)
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2008f8d4
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2008f8d4
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2008f8d4
Branch: refs/heads/ib/7897
Commit: 2008f8d4cac6b0798897831486716f76b102122b
Parents: 6556bcf
Author: Igor Bondarenko <je...@gmail.com>
Authored: Tue Jul 7 12:27:38 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 12:27:38 2015 +0300
----------------------------------------------------------------------
Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/2008f8d4/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js b/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
index 7fbeede..435a7a8 100644
--- a/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
+++ b/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
@@ -7211,7 +7211,7 @@ Editor.prototype.render = function(el) {
tabSize: '2',
indentWithTabs: true,
lineNumbers: false,
- autofocus: true,
+ autofocus: false,
extraKeys: keyMaps
});
@@ -7392,4 +7392,4 @@ Editor.prototype.toggleFullScreen = function() {
};
global.Editor = Editor;
-})(this);
\ No newline at end of file
+})(this);
[07/21] allura git commit: [#7897] ticket:804 Hide "code" from
toolbar, since it's syntax is not matching Allura's
Posted by je...@apache.org.
[#7897] ticket:804 Hide "code" from toolbar, since it's syntax is not matching Allura's
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/390e9338
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/390e9338
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/390e9338
Branch: refs/heads/ib/7897
Commit: 390e9338e106fc9688c3c507b3ebfa7eae4214db
Parents: f9d0f80
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Jun 18 18:10:41 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Tue Jul 7 10:26:10 2015 +0300
----------------------------------------------------------------------
.../lib/widgets/resources/js/sf_markitup.js | 31 +++++++++++++++-----
1 file changed, 23 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/390e9338/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index b10e331..266d77a 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -27,16 +27,31 @@ $(window).load(function() {
var $help_area = $('div.markdown_help', $container);
var $help_contents = $('div.markdown_help_contents', $container);
- var toolbar = Editor.toolbar;
- toolbar[11] = {name: 'info', action: show_help};
- toolbar[12] = {name: 'preview', action: show_preview};
- var editor = new Editor({
+ var toolbar = [];
+ // Exclude "code" tool from toolbar, since it's syntax not matching Allura's
+ // Override actions for "info" & "preview" tools
+ for (var i in Editor.toolbar) {
+ var tool = Editor.toolbar[i];
+ if (tool !== null && typeof tool === 'object') {
+ switch(tool.name) {
+ case 'code':
+ continue;
+ case 'info':
+ tool = {name: 'info', action: show_help};
+ break;
+ case 'preview':
+ tool = {name: 'preview', action: show_preview};
+ break;
+ }
+ }
+ toolbar.push(tool);
+ }
+ new Editor({
element: $textarea[0],
toolbar: toolbar
- });
- editor.render();
+ }).render();
- function show_help() {
+ function show_help(editor) {
$help_contents.html('Loading...');
$.get($help_contents.attr('data-url'), function (data) {
$help_contents.html(data);
@@ -56,7 +71,7 @@ $(window).load(function() {
$help_area.lightbox_me();
}
- function show_preview() {
+ function show_preview(editor) {
/*
* This is pretty much the same as original Editor.togglePreview,
* but rendered text is fetched from the server.
[04/21] allura git commit: [#7897] ticket:804 Add lepture/editor to
MarkdownEdit
Posted by je...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js b/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js
new file mode 100644
index 0000000..7a07c8a
--- /dev/null
+++ b/Allura/allura/lib/widgets/resources/js/markdown_editor/marked.js
@@ -0,0 +1,1165 @@
+/**
+ * marked - a markdown parser
+ * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/chjj/marked
+ */
+
+;(function() {
+
+/**
+ * Block-Level Grammar
+ */
+
+var block = {
+ newline: /^\n+/,
+ code: /^( {4}[^\n]+\n*)+/,
+ fences: noop,
+ hr: /^( *[-*_]){3,} *(?:\n+|$)/,
+ heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
+ nptable: noop,
+ lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
+ blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
+ list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
+ html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
+ def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
+ table: noop,
+ paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
+ text: /^[^\n]+/
+};
+
+block.bullet = /(?:[*+-]|\d+\.)/;
+block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
+block.item = replace(block.item, 'gm')
+ (/bull/g, block.bullet)
+ ();
+
+block.list = replace(block.list)
+ (/bull/g, block.bullet)
+ ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
+ ();
+
+block._tag = '(?!(?:'
+ + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
+ + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
+ + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
+
+block.html = replace(block.html)
+ ('comment', /<!--[\s\S]*?-->/)
+ ('closed', /<(tag)[\s\S]+?<\/\1>/)
+ ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
+ (/tag/g, block._tag)
+ ();
+
+block.paragraph = replace(block.paragraph)
+ ('hr', block.hr)
+ ('heading', block.heading)
+ ('lheading', block.lheading)
+ ('blockquote', block.blockquote)
+ ('tag', '<' + block._tag)
+ ('def', block.def)
+ ();
+
+/**
+ * Normal Block Grammar
+ */
+
+block.normal = merge({}, block);
+
+/**
+ * GFM Block Grammar
+ */
+
+block.gfm = merge({}, block.normal, {
+ fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
+ paragraph: /^/
+});
+
+block.gfm.paragraph = replace(block.paragraph)
+ ('(?!', '(?!'
+ + block.gfm.fences.source.replace('\\1', '\\2') + '|'
+ + block.list.source.replace('\\1', '\\3') + '|')
+ ();
+
+/**
+ * GFM + Tables Block Grammar
+ */
+
+block.tables = merge({}, block.gfm, {
+ nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
+ table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
+});
+
+/**
+ * Block Lexer
+ */
+
+function Lexer(options) {
+ this.tokens = [];
+ this.tokens.links = {};
+ this.options = options || marked.defaults;
+ this.rules = block.normal;
+
+ if (this.options.gfm) {
+ if (this.options.tables) {
+ this.rules = block.tables;
+ } else {
+ this.rules = block.gfm;
+ }
+ }
+}
+
+/**
+ * Expose Block Rules
+ */
+
+Lexer.rules = block;
+
+/**
+ * Static Lex Method
+ */
+
+Lexer.lex = function(src, options) {
+ var lexer = new Lexer(options);
+ return lexer.lex(src);
+};
+
+/**
+ * Preprocessing
+ */
+
+Lexer.prototype.lex = function(src) {
+ src = src
+ .replace(/\r\n|\r/g, '\n')
+ .replace(/\t/g, ' ')
+ .replace(/\u00a0/g, ' ')
+ .replace(/\u2424/g, '\n');
+
+ return this.token(src, true);
+};
+
+/**
+ * Lexing
+ */
+
+Lexer.prototype.token = function(src, top) {
+ var src = src.replace(/^ +$/gm, '')
+ , next
+ , loose
+ , cap
+ , bull
+ , b
+ , item
+ , space
+ , i
+ , l;
+
+ while (src) {
+ // newline
+ if (cap = this.rules.newline.exec(src)) {
+ src = src.substring(cap[0].length);
+ if (cap[0].length > 1) {
+ this.tokens.push({
+ type: 'space'
+ });
+ }
+ }
+
+ // code
+ if (cap = this.rules.code.exec(src)) {
+ src = src.substring(cap[0].length);
+ cap = cap[0].replace(/^ {4}/gm, '');
+ this.tokens.push({
+ type: 'code',
+ text: !this.options.pedantic
+ ? cap.replace(/\n+$/, '')
+ : cap
+ });
+ continue;
+ }
+
+ // fences (gfm)
+ if (cap = this.rules.fences.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'code',
+ lang: cap[2],
+ text: cap[3]
+ });
+ continue;
+ }
+
+ // heading
+ if (cap = this.rules.heading.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'heading',
+ depth: cap[1].length,
+ text: cap[2]
+ });
+ continue;
+ }
+
+ // table no leading pipe (gfm)
+ if (top && (cap = this.rules.nptable.exec(src))) {
+ src = src.substring(cap[0].length);
+
+ item = {
+ type: 'table',
+ header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
+ cells: cap[3].replace(/\n$/, '').split('\n')
+ };
+
+ for (i = 0; i < item.align.length; i++) {
+ if (/^ *-+: *$/.test(item.align[i])) {
+ item.align[i] = 'right';
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
+ item.align[i] = 'center';
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
+ item.align[i] = 'left';
+ } else {
+ item.align[i] = null;
+ }
+ }
+
+ for (i = 0; i < item.cells.length; i++) {
+ item.cells[i] = item.cells[i].split(/ *\| */);
+ }
+
+ this.tokens.push(item);
+
+ continue;
+ }
+
+ // lheading
+ if (cap = this.rules.lheading.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'heading',
+ depth: cap[2] === '=' ? 1 : 2,
+ text: cap[1]
+ });
+ continue;
+ }
+
+ // hr
+ if (cap = this.rules.hr.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'hr'
+ });
+ continue;
+ }
+
+ // blockquote
+ if (cap = this.rules.blockquote.exec(src)) {
+ src = src.substring(cap[0].length);
+
+ this.tokens.push({
+ type: 'blockquote_start'
+ });
+
+ cap = cap[0].replace(/^ *> ?/gm, '');
+
+ // Pass `top` to keep the current
+ // "toplevel" state. This is exactly
+ // how markdown.pl works.
+ this.token(cap, top);
+
+ this.tokens.push({
+ type: 'blockquote_end'
+ });
+
+ continue;
+ }
+
+ // list
+ if (cap = this.rules.list.exec(src)) {
+ src = src.substring(cap[0].length);
+ bull = cap[2];
+
+ this.tokens.push({
+ type: 'list_start',
+ ordered: bull.length > 1
+ });
+
+ // Get each top-level item.
+ cap = cap[0].match(this.rules.item);
+
+ next = false;
+ l = cap.length;
+ i = 0;
+
+ for (; i < l; i++) {
+ item = cap[i];
+
+ // Remove the list item's bullet
+ // so it is seen as the next token.
+ space = item.length;
+ item = item.replace(/^ *([*+-]|\d+\.) +/, '');
+
+ // Outdent whatever the
+ // list item contains. Hacky.
+ if (~item.indexOf('\n ')) {
+ space -= item.length;
+ item = !this.options.pedantic
+ ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
+ : item.replace(/^ {1,4}/gm, '');
+ }
+
+ // Determine whether the next list item belongs here.
+ // Backpedal if it does not belong in this list.
+ if (this.options.smartLists && i !== l - 1) {
+ b = block.bullet.exec(cap[i + 1])[0];
+ if (bull !== b && !(bull.length > 1 && b.length > 1)) {
+ src = cap.slice(i + 1).join('\n') + src;
+ i = l - 1;
+ }
+ }
+
+ // Determine whether item is loose or not.
+ // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
+ // for discount behavior.
+ loose = next || /\n\n(?!\s*$)/.test(item);
+ if (i !== l - 1) {
+ next = item.charAt(item.length - 1) === '\n';
+ if (!loose) loose = next;
+ }
+
+ this.tokens.push({
+ type: loose
+ ? 'loose_item_start'
+ : 'list_item_start'
+ });
+
+ // Recurse.
+ this.token(item, false);
+
+ this.tokens.push({
+ type: 'list_item_end'
+ });
+ }
+
+ this.tokens.push({
+ type: 'list_end'
+ });
+
+ continue;
+ }
+
+ // html
+ if (cap = this.rules.html.exec(src)) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: this.options.sanitize
+ ? 'paragraph'
+ : 'html',
+ pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
+ text: cap[0]
+ });
+ continue;
+ }
+
+ // def
+ if (top && (cap = this.rules.def.exec(src))) {
+ src = src.substring(cap[0].length);
+ this.tokens.links[cap[1].toLowerCase()] = {
+ href: cap[2],
+ title: cap[3]
+ };
+ continue;
+ }
+
+ // table (gfm)
+ if (top && (cap = this.rules.table.exec(src))) {
+ src = src.substring(cap[0].length);
+
+ item = {
+ type: 'table',
+ header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
+ align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
+ cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
+ };
+
+ for (i = 0; i < item.align.length; i++) {
+ if (/^ *-+: *$/.test(item.align[i])) {
+ item.align[i] = 'right';
+ } else if (/^ *:-+: *$/.test(item.align[i])) {
+ item.align[i] = 'center';
+ } else if (/^ *:-+ *$/.test(item.align[i])) {
+ item.align[i] = 'left';
+ } else {
+ item.align[i] = null;
+ }
+ }
+
+ for (i = 0; i < item.cells.length; i++) {
+ item.cells[i] = item.cells[i]
+ .replace(/^ *\| *| *\| *$/g, '')
+ .split(/ *\| */);
+ }
+
+ this.tokens.push(item);
+
+ continue;
+ }
+
+ // top-level paragraph
+ if (top && (cap = this.rules.paragraph.exec(src))) {
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'paragraph',
+ text: cap[1].charAt(cap[1].length - 1) === '\n'
+ ? cap[1].slice(0, -1)
+ : cap[1]
+ });
+ continue;
+ }
+
+ // text
+ if (cap = this.rules.text.exec(src)) {
+ // Top-level should never reach here.
+ src = src.substring(cap[0].length);
+ this.tokens.push({
+ type: 'text',
+ text: cap[0]
+ });
+ continue;
+ }
+
+ if (src) {
+ throw new
+ Error('Infinite loop on byte: ' + src.charCodeAt(0));
+ }
+ }
+
+ return this.tokens;
+};
+
+/**
+ * Inline-Level Grammar
+ */
+
+var inline = {
+ escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
+ autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
+ url: noop,
+ tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
+ link: /^!?\[(inside)\]\(href\)/,
+ reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
+ nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
+ strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
+ em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
+ code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
+ br: /^ {2,}\n(?!\s*$)/,
+ del: noop,
+ text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
+};
+
+inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
+inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
+
+inline.link = replace(inline.link)
+ ('inside', inline._inside)
+ ('href', inline._href)
+ ();
+
+inline.reflink = replace(inline.reflink)
+ ('inside', inline._inside)
+ ();
+
+/**
+ * Normal Inline Grammar
+ */
+
+inline.normal = merge({}, inline);
+
+/**
+ * Pedantic Inline Grammar
+ */
+
+inline.pedantic = merge({}, inline.normal, {
+ strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
+ em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
+});
+
+/**
+ * GFM Inline Grammar
+ */
+
+inline.gfm = merge({}, inline.normal, {
+ escape: replace(inline.escape)('])', '~|])')(),
+ url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
+ del: /^~~(?=\S)([\s\S]*?\S)~~/,
+ text: replace(inline.text)
+ (']|', '~]|')
+ ('|', '|https?://|')
+ ()
+});
+
+/**
+ * GFM + Line Breaks Inline Grammar
+ */
+
+inline.breaks = merge({}, inline.gfm, {
+ br: replace(inline.br)('{2,}', '*')(),
+ text: replace(inline.gfm.text)('{2,}', '*')()
+});
+
+/**
+ * Inline Lexer & Compiler
+ */
+
+function InlineLexer(links, options) {
+ this.options = options || marked.defaults;
+ this.links = links;
+ this.rules = inline.normal;
+
+ if (!this.links) {
+ throw new
+ Error('Tokens array requires a `links` property.');
+ }
+
+ if (this.options.gfm) {
+ if (this.options.breaks) {
+ this.rules = inline.breaks;
+ } else {
+ this.rules = inline.gfm;
+ }
+ } else if (this.options.pedantic) {
+ this.rules = inline.pedantic;
+ }
+}
+
+/**
+ * Expose Inline Rules
+ */
+
+InlineLexer.rules = inline;
+
+/**
+ * Static Lexing/Compiling Method
+ */
+
+InlineLexer.output = function(src, links, options) {
+ var inline = new InlineLexer(links, options);
+ return inline.output(src);
+};
+
+/**
+ * Lexing/Compiling
+ */
+
+InlineLexer.prototype.output = function(src) {
+ var out = ''
+ , link
+ , text
+ , href
+ , cap;
+
+ while (src) {
+ // escape
+ if (cap = this.rules.escape.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += cap[1];
+ continue;
+ }
+
+ // autolink
+ if (cap = this.rules.autolink.exec(src)) {
+ src = src.substring(cap[0].length);
+ if (cap[2] === '@') {
+ text = cap[1].charAt(6) === ':'
+ ? this.mangle(cap[1].substring(7))
+ : this.mangle(cap[1]);
+ href = this.mangle('mailto:') + text;
+ } else {
+ text = escape(cap[1]);
+ href = text;
+ }
+ out += '<a href="'
+ + href
+ + '">'
+ + text
+ + '</a>';
+ continue;
+ }
+
+ // url (gfm)
+ if (cap = this.rules.url.exec(src)) {
+ src = src.substring(cap[0].length);
+ text = escape(cap[1]);
+ href = text;
+ out += '<a href="'
+ + href
+ + '">'
+ + text
+ + '</a>';
+ continue;
+ }
+
+ // tag
+ if (cap = this.rules.tag.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.options.sanitize
+ ? escape(cap[0])
+ : cap[0];
+ continue;
+ }
+
+ // link
+ if (cap = this.rules.link.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += this.outputLink(cap, {
+ href: cap[2],
+ title: cap[3]
+ });
+ continue;
+ }
+
+ // reflink, nolink
+ if ((cap = this.rules.reflink.exec(src))
+ || (cap = this.rules.nolink.exec(src))) {
+ src = src.substring(cap[0].length);
+ link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
+ link = this.links[link.toLowerCase()];
+ if (!link || !link.href) {
+ out += cap[0].charAt(0);
+ src = cap[0].substring(1) + src;
+ continue;
+ }
+ out += this.outputLink(cap, link);
+ continue;
+ }
+
+ // strong
+ if (cap = this.rules.strong.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += '<strong>'
+ + this.output(cap[2] || cap[1])
+ + '</strong>';
+ continue;
+ }
+
+ // em
+ if (cap = this.rules.em.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += '<em>'
+ + this.output(cap[2] || cap[1])
+ + '</em>';
+ continue;
+ }
+
+ // code
+ if (cap = this.rules.code.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += '<code>'
+ + escape(cap[2], true)
+ + '</code>';
+ continue;
+ }
+
+ // br
+ if (cap = this.rules.br.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += '<br>';
+ continue;
+ }
+
+ // del (gfm)
+ if (cap = this.rules.del.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += '<del>'
+ + this.output(cap[1])
+ + '</del>';
+ continue;
+ }
+
+ // text
+ if (cap = this.rules.text.exec(src)) {
+ src = src.substring(cap[0].length);
+ out += escape(this.smartypants(cap[0]));
+ continue;
+ }
+
+ if (src) {
+ throw new
+ Error('Infinite loop on byte: ' + src.charCodeAt(0));
+ }
+ }
+
+ return out;
+};
+
+/**
+ * Compile Link
+ */
+
+InlineLexer.prototype.outputLink = function(cap, link) {
+ if (cap[0].charAt(0) !== '!') {
+ return '<a href="'
+ + escape(link.href)
+ + '"'
+ + (link.title
+ ? ' title="'
+ + escape(link.title)
+ + '"'
+ : '')
+ + '>'
+ + this.output(cap[1])
+ + '</a>';
+ } else {
+ return '<img src="'
+ + escape(link.href)
+ + '" alt="'
+ + escape(cap[1])
+ + '"'
+ + (link.title
+ ? ' title="'
+ + escape(link.title)
+ + '"'
+ : '')
+ + '>';
+ }
+};
+
+/**
+ * Smartypants Transformations
+ */
+
+InlineLexer.prototype.smartypants = function(text) {
+ if (!this.options.smartypants) return text;
+ return text
+ // em-dashes
+ .replace(/--/g, '\u2014')
+ // opening singles
+ .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
+ // closing singles & apostrophes
+ .replace(/'/g, '\u2019')
+ // opening doubles
+ .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
+ // closing doubles
+ .replace(/"/g, '\u201d')
+ // ellipses
+ .replace(/\.{3}/g, '\u2026');
+};
+
+/**
+ * Mangle Links
+ */
+
+InlineLexer.prototype.mangle = function(text) {
+ var out = ''
+ , l = text.length
+ , i = 0
+ , ch;
+
+ for (; i < l; i++) {
+ ch = text.charCodeAt(i);
+ if (Math.random() > 0.5) {
+ ch = 'x' + ch.toString(16);
+ }
+ out += '&#' + ch + ';';
+ }
+
+ return out;
+};
+
+/**
+ * Parsing & Compiling
+ */
+
+function Parser(options) {
+ this.tokens = [];
+ this.token = null;
+ this.options = options || marked.defaults;
+}
+
+/**
+ * Static Parse Method
+ */
+
+Parser.parse = function(src, options) {
+ var parser = new Parser(options);
+ return parser.parse(src);
+};
+
+/**
+ * Parse Loop
+ */
+
+Parser.prototype.parse = function(src) {
+ this.inline = new InlineLexer(src.links, this.options);
+ this.tokens = src.reverse();
+
+ var out = '';
+ while (this.next()) {
+ out += this.tok();
+ }
+
+ return out;
+};
+
+/**
+ * Next Token
+ */
+
+Parser.prototype.next = function() {
+ return this.token = this.tokens.pop();
+};
+
+/**
+ * Preview Next Token
+ */
+
+Parser.prototype.peek = function() {
+ return this.tokens[this.tokens.length - 1] || 0;
+};
+
+/**
+ * Parse Text Tokens
+ */
+
+Parser.prototype.parseText = function() {
+ var body = this.token.text;
+
+ while (this.peek().type === 'text') {
+ body += '\n' + this.next().text;
+ }
+
+ return this.inline.output(body);
+};
+
+/**
+ * Parse Current Token
+ */
+
+Parser.prototype.tok = function() {
+ switch (this.token.type) {
+ case 'space': {
+ return '';
+ }
+ case 'hr': {
+ return '<hr>\n';
+ }
+ case 'heading': {
+ return '<h'
+ + this.token.depth
+ + ' id="'
+ + this.token.text.toLowerCase().replace(/[^\w]+/g, '-')
+ + '">'
+ + this.inline.output(this.token.text)
+ + '</h'
+ + this.token.depth
+ + '>\n';
+ }
+ case 'code': {
+ if (this.options.highlight) {
+ var code = this.options.highlight(this.token.text, this.token.lang);
+ if (code != null && code !== this.token.text) {
+ this.token.escaped = true;
+ this.token.text = code;
+ }
+ }
+
+ if (!this.token.escaped) {
+ this.token.text = escape(this.token.text, true);
+ }
+
+ return '<pre><code'
+ + (this.token.lang
+ ? ' class="'
+ + this.options.langPrefix
+ + this.token.lang
+ + '"'
+ : '')
+ + '>'
+ + this.token.text
+ + '</code></pre>\n';
+ }
+ case 'table': {
+ var body = ''
+ , heading
+ , i
+ , row
+ , cell
+ , j;
+
+ // header
+ body += '<thead>\n<tr>\n';
+ for (i = 0; i < this.token.header.length; i++) {
+ heading = this.inline.output(this.token.header[i]);
+ body += '<th';
+ if (this.token.align[i]) {
+ body += ' style="text-align:' + this.token.align[i] + '"';
+ }
+ body += '>' + heading + '</th>\n';
+ }
+ body += '</tr>\n</thead>\n';
+
+ // body
+ body += '<tbody>\n'
+ for (i = 0; i < this.token.cells.length; i++) {
+ row = this.token.cells[i];
+ body += '<tr>\n';
+ for (j = 0; j < row.length; j++) {
+ cell = this.inline.output(row[j]);
+ body += '<td';
+ if (this.token.align[j]) {
+ body += ' style="text-align:' + this.token.align[j] + '"';
+ }
+ body += '>' + cell + '</td>\n';
+ }
+ body += '</tr>\n';
+ }
+ body += '</tbody>\n';
+
+ return '<table>\n'
+ + body
+ + '</table>\n';
+ }
+ case 'blockquote_start': {
+ var body = '';
+
+ while (this.next().type !== 'blockquote_end') {
+ body += this.tok();
+ }
+
+ return '<blockquote>\n'
+ + body
+ + '</blockquote>\n';
+ }
+ case 'list_start': {
+ var type = this.token.ordered ? 'ol' : 'ul'
+ , body = '';
+
+ while (this.next().type !== 'list_end') {
+ body += this.tok();
+ }
+
+ return '<'
+ + type
+ + '>\n'
+ + body
+ + '</'
+ + type
+ + '>\n';
+ }
+ case 'list_item_start': {
+ var body = '';
+
+ while (this.next().type !== 'list_item_end') {
+ body += this.token.type === 'text'
+ ? this.parseText()
+ : this.tok();
+ }
+
+ return '<li>'
+ + body
+ + '</li>\n';
+ }
+ case 'loose_item_start': {
+ var body = '';
+
+ while (this.next().type !== 'list_item_end') {
+ body += this.tok();
+ }
+
+ return '<li>'
+ + body
+ + '</li>\n';
+ }
+ case 'html': {
+ return !this.token.pre && !this.options.pedantic
+ ? this.inline.output(this.token.text)
+ : this.token.text;
+ }
+ case 'paragraph': {
+ return '<p>'
+ + this.inline.output(this.token.text)
+ + '</p>\n';
+ }
+ case 'text': {
+ return '<p>'
+ + this.parseText()
+ + '</p>\n';
+ }
+ }
+};
+
+/**
+ * Helpers
+ */
+
+function escape(html, encode) {
+ return html
+ .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+}
+
+function replace(regex, opt) {
+ regex = regex.source;
+ opt = opt || '';
+ return function self(name, val) {
+ if (!name) return new RegExp(regex, opt);
+ val = val.source || val;
+ val = val.replace(/(^|[^\[])\^/g, '$1');
+ regex = regex.replace(name, val);
+ return self;
+ };
+}
+
+function noop() {}
+noop.exec = noop;
+
+function merge(obj) {
+ var i = 1
+ , target
+ , key;
+
+ for (; i < arguments.length; i++) {
+ target = arguments[i];
+ for (key in target) {
+ if (Object.prototype.hasOwnProperty.call(target, key)) {
+ obj[key] = target[key];
+ }
+ }
+ }
+
+ return obj;
+}
+
+/**
+ * Marked
+ */
+
+function marked(src, opt, callback) {
+ if (callback || typeof opt === 'function') {
+ if (!callback) {
+ callback = opt;
+ opt = null;
+ }
+
+ opt = merge({}, marked.defaults, opt || {});
+
+ var highlight = opt.highlight
+ , tokens
+ , pending
+ , i = 0;
+
+ try {
+ tokens = Lexer.lex(src, opt)
+ } catch (e) {
+ return callback(e);
+ }
+
+ pending = tokens.length;
+
+ var done = function() {
+ var out, err;
+
+ try {
+ out = Parser.parse(tokens, opt);
+ } catch (e) {
+ err = e;
+ }
+
+ opt.highlight = highlight;
+
+ return err
+ ? callback(err)
+ : callback(null, out);
+ };
+
+ if (!highlight || highlight.length < 3) {
+ return done();
+ }
+
+ delete opt.highlight;
+
+ if (!pending) return done();
+
+ for (; i < tokens.length; i++) {
+ (function(token) {
+ if (token.type !== 'code') {
+ return --pending || done();
+ }
+ return highlight(token.text, token.lang, function(err, code) {
+ if (code == null || code === token.text) {
+ return --pending || done();
+ }
+ token.text = code;
+ token.escaped = true;
+ --pending || done();
+ });
+ })(tokens[i]);
+ }
+
+ return;
+ }
+ try {
+ if (opt) opt = merge({}, marked.defaults, opt);
+ return Parser.parse(Lexer.lex(src, opt), opt);
+ } catch (e) {
+ e.message += '\nPlease report this to https://github.com/chjj/marked.';
+ if ((opt || marked.defaults).silent) {
+ return '<p>An error occured:</p><pre>'
+ + escape(e.message + '', true)
+ + '</pre>';
+ }
+ throw e;
+ }
+}
+
+/**
+ * Options
+ */
+
+marked.options =
+marked.setOptions = function(opt) {
+ merge(marked.defaults, opt);
+ return marked;
+};
+
+marked.defaults = {
+ gfm: true,
+ tables: true,
+ breaks: false,
+ pedantic: false,
+ sanitize: false,
+ smartLists: false,
+ silent: false,
+ highlight: null,
+ langPrefix: 'lang-',
+ smartypants: false
+};
+
+/**
+ * Expose
+ */
+
+marked.Parser = Parser;
+marked.parser = Parser.parse;
+
+marked.Lexer = Lexer;
+marked.lexer = Lexer.lex;
+
+marked.InlineLexer = InlineLexer;
+marked.inlineLexer = InlineLexer.output;
+
+marked.parse = marked;
+
+if (typeof exports === 'object') {
+ module.exports = marked;
+} else if (typeof define === 'function' && define.amd) {
+ define(function() { return marked; });
+} else {
+ this.marked = marked;
+}
+
+}).call(function() {
+ return this || (typeof window !== 'undefined' ? window : global);
+}());
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/js/sf_markitup.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/sf_markitup.js b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
index 6598b1c..ecb84db 100644
--- a/Allura/allura/lib/widgets/resources/js/sf_markitup.js
+++ b/Allura/allura/lib/widgets/resources/js/sf_markitup.js
@@ -23,6 +23,9 @@ $(window).load(function() {
$('div.markdown_edit').each(function(){
var $container = $(this);
var $textarea = $('textarea', $container);
+ new Editor({
+ element: $textarea[0]
+ }).render();
$textarea.tabby({tabString : " "});
var $preview = $('a.markdown_preview', $container);
var $edit = $('a.markdown_edit', $container);
[05/21] allura git commit: [#7897] ticket:804 Add lepture/editor to
MarkdownEdit
Posted by je...@apache.org.
http://git-wip-us.apache.org/repos/asf/allura/blob/ab2b11e0/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js b/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
new file mode 100644
index 0000000..7fbeede
--- /dev/null
+++ b/Allura/allura/lib/widgets/resources/js/markdown_editor/editor.js
@@ -0,0 +1,7395 @@
+(function(global) {
+// CodeMirror version 3.15
+//
+// CodeMirror is the only global var we claim
+var CodeMirror = (function() {
+ "use strict";
+
+ // BROWSER SNIFFING
+
+ // Crude, but necessary to handle a number of hard-to-feature-detect
+ // bugs and behavior differences.
+ var gecko = /gecko\/\d/i.test(navigator.userAgent);
+ var ie = /MSIE \d/.test(navigator.userAgent);
+ var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
+ var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+ var webkit = /WebKit\//.test(navigator.userAgent);
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
+ var chrome = /Chrome\//.test(navigator.userAgent);
+ var opera = /Opera\//.test(navigator.userAgent);
+ var safari = /Apple Computer/.test(navigator.vendor);
+ var khtml = /KHTML\//.test(navigator.userAgent);
+ var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
+ var phantom = /PhantomJS/.test(navigator.userAgent);
+
+ var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
+ var mac = ios || /Mac/.test(navigator.platform);
+ var windows = /windows/i.test(navigator.platform);
+
+ var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
+ if (opera_version) opera_version = Number(opera_version[1]);
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
+ var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
+ var captureMiddleClick = gecko || (ie && !ie_lt9);
+
+ // Optimize some code when these features are not used
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
+
+ // CONSTRUCTOR
+
+ function CodeMirror(place, options) {
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
+
+ this.options = options = options || {};
+ // Determine effective options based on given values and defaults.
+ for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
+ options[opt] = defaults[opt];
+ setGuttersForLineNumbers(options);
+
+ var docStart = typeof options.value == "string" ? 0 : options.value.first;
+ var display = this.display = makeDisplay(place, docStart);
+ display.wrapper.CodeMirror = this;
+ updateGutters(this);
+ if (options.autofocus && !mobile) focusInput(this);
+
+ this.state = {keyMaps: [],
+ overlays: [],
+ modeGen: 0,
+ overwrite: false, focused: false,
+ suppressEdits: false, pasteIncoming: false,
+ draggingText: false,
+ highlight: new Delayed()};
+
+ themeChanged(this);
+ if (options.lineWrapping)
+ this.display.wrapper.className += " CodeMirror-wrap";
+
+ var doc = options.value;
+ if (typeof doc == "string") doc = new Doc(options.value, options.mode);
+ operation(this, attachDoc)(this, doc);
+
+ // Override magic textarea content restore that IE sometimes does
+ // on our hidden textarea on reload
+ if (ie) setTimeout(bind(resetInput, this, true), 20);
+
+ registerEventHandlers(this);
+ // IE throws unspecified error in certain cases, when
+ // trying to access activeElement before onload
+ var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
+ if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
+ else onBlur(this);
+
+ operation(this, function() {
+ for (var opt in optionHandlers)
+ if (optionHandlers.propertyIsEnumerable(opt))
+ optionHandlers[opt](this, options[opt], Init);
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
+ })();
+ }
+
+ // DISPLAY CONSTRUCTOR
+
+ function makeDisplay(place, docStart) {
+ var d = {};
+
+ var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
+ if (webkit) input.style.width = "1000px";
+ else input.setAttribute("wrap", "off");
+ // if border: 0; -- iOS fails to open keyboard (issue #1287)
+ if (ios) input.style.border = "1px solid black";
+ input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");
+
+ // Wraps and hides input textarea
+ d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
+ // The actual fake scrollbars.
+ d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
+ d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
+ // DIVs containing the selection and the actual code
+ d.lineDiv = elt("div", null, "CodeMirror-code");
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
+ // Blinky cursor, and element used to ensure cursor fits at the end of a line
+ d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
+ d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
+ // Used to measure text size
+ d.measure = elt("div", null, "CodeMirror-measure");
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
+ d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
+ null, "position: relative; outline: none");
+ // Moved around its parent to cover visible view
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
+ // Set to the height of the text, causes scrolling
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
+ // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
+ // Will contain the gutters, if any
+ d.gutters = elt("div", null, "CodeMirror-gutters");
+ d.lineGutter = null;
+ // Provides scrolling
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
+ d.scroller.setAttribute("tabIndex", "-1");
+ // The element in which the editor lives.
+ d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
+ d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
+ // Work around IE7 z-index bug
+ if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
+ if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);
+
+ // Needed to hide big blue blinking cursor on Mobile Safari
+ if (ios) input.style.width = "0px";
+ if (!webkit) d.scroller.draggable = true;
+ // Needed to handle Tab key in KHTML
+ if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
+ else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";
+
+ // Current visible range (may be bigger than the view window).
+ d.viewOffset = d.lastSizeC = 0;
+ d.showingFrom = d.showingTo = docStart;
+
+ // Used to only resize the line number gutter when necessary (when
+ // the amount of lines crosses a boundary that makes its width change)
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
+ // See readInput and resetInput
+ d.prevInput = "";
+ // Set to true when a non-horizontal-scrolling widget is added. As
+ // an optimization, widget aligning is skipped when d is false.
+ d.alignWidgets = false;
+ // Flag that indicates whether we currently expect input to appear
+ // (after some event like 'keypress' or 'input') and are polling
+ // intensively.
+ d.pollingFast = false;
+ // Self-resetting timeout for the poller
+ d.poll = new Delayed();
+
+ d.cachedCharWidth = d.cachedTextHeight = null;
+ d.measureLineCache = [];
+ d.measureLineCachePos = 0;
+
+ // Tracks when resetInput has punted to just putting a short
+ // string instead of the (large) selection.
+ d.inaccurateSelection = false;
+
+ // Tracks the maximum line length so that the horizontal scrollbar
+ // can be kept static when scrolling.
+ d.maxLine = null;
+ d.maxLineLength = 0;
+ d.maxLineChanged = false;
+
+ // Used for measuring wheel scrolling granularity
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
+
+ return d;
+ }
+
+ // STATE UPDATES
+
+ // Used to get the editor into a consistent state again when options change.
+
+ function loadMode(cm) {
+ cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
+ cm.doc.iter(function(line) {
+ if (line.stateAfter) line.stateAfter = null;
+ if (line.styles) line.styles = null;
+ });
+ cm.doc.frontier = cm.doc.first;
+ startWorker(cm, 100);
+ cm.state.modeGen++;
+ if (cm.curOp) regChange(cm);
+ }
+
+ function wrappingChanged(cm) {
+ if (cm.options.lineWrapping) {
+ cm.display.wrapper.className += " CodeMirror-wrap";
+ cm.display.sizer.style.minWidth = "";
+ } else {
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
+ computeMaxLength(cm);
+ }
+ estimateLineHeights(cm);
+ regChange(cm);
+ clearCaches(cm);
+ setTimeout(function(){updateScrollbars(cm);}, 100);
+ }
+
+ function estimateHeight(cm) {
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
+ return function(line) {
+ if (lineIsHidden(cm.doc, line))
+ return 0;
+ else if (wrapping)
+ return (Math.ceil(line.text.length / perLine) || 1) * th;
+ else
+ return th;
+ };
+ }
+
+ function estimateLineHeights(cm) {
+ var doc = cm.doc, est = estimateHeight(cm);
+ doc.iter(function(line) {
+ var estHeight = est(line);
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
+ });
+ }
+
+ function keyMapChanged(cm) {
+ var map = keyMap[cm.options.keyMap], style = map.style;
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
+ (style ? " cm-keymap-" + style : "");
+ cm.state.disableInput = map.disableInput;
+ }
+
+ function themeChanged(cm) {
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
+ clearCaches(cm);
+ }
+
+ function guttersChanged(cm) {
+ updateGutters(cm);
+ regChange(cm);
+ setTimeout(function(){alignHorizontally(cm);}, 20);
+ }
+
+ function updateGutters(cm) {
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
+ removeChildren(gutters);
+ for (var i = 0; i < specs.length; ++i) {
+ var gutterClass = specs[i];
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
+ if (gutterClass == "CodeMirror-linenumbers") {
+ cm.display.lineGutter = gElt;
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
+ }
+ }
+ gutters.style.display = i ? "" : "none";
+ }
+
+ function lineLength(doc, line) {
+ if (line.height == 0) return 0;
+ var len = line.text.length, merged, cur = line;
+ while (merged = collapsedSpanAtStart(cur)) {
+ var found = merged.find();
+ cur = getLine(doc, found.from.line);
+ len += found.from.ch - found.to.ch;
+ }
+ cur = line;
+ while (merged = collapsedSpanAtEnd(cur)) {
+ var found = merged.find();
+ len -= cur.text.length - found.from.ch;
+ cur = getLine(doc, found.to.line);
+ len += cur.text.length - found.to.ch;
+ }
+ return len;
+ }
+
+ function computeMaxLength(cm) {
+ var d = cm.display, doc = cm.doc;
+ d.maxLine = getLine(doc, doc.first);
+ d.maxLineLength = lineLength(doc, d.maxLine);
+ d.maxLineChanged = true;
+ doc.iter(function(line) {
+ var len = lineLength(doc, line);
+ if (len > d.maxLineLength) {
+ d.maxLineLength = len;
+ d.maxLine = line;
+ }
+ });
+ }
+
+ // Make sure the gutters options contains the element
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
+ function setGuttersForLineNumbers(options) {
+ var found = false;
+ for (var i = 0; i < options.gutters.length; ++i) {
+ if (options.gutters[i] == "CodeMirror-linenumbers") {
+ if (options.lineNumbers) found = true;
+ else options.gutters.splice(i--, 1);
+ }
+ }
+ if (!found && options.lineNumbers)
+ options.gutters.push("CodeMirror-linenumbers");
+ }
+
+ // SCROLLBARS
+
+ // Re-synchronize the fake scrollbars with the actual size of the
+ // content. Optionally force a scrollTop.
+ function updateScrollbars(cm) {
+ var d = cm.display, docHeight = cm.doc.height;
+ var totalHeight = docHeight + paddingVert(d);
+ d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
+ d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
+ var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
+ var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
+ var needsV = scrollHeight > (d.scroller.clientHeight + 1);
+ if (needsV) {
+ d.scrollbarV.style.display = "block";
+ d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
+ d.scrollbarV.firstChild.style.height =
+ (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
+ } else d.scrollbarV.style.display = "";
+ if (needsH) {
+ d.scrollbarH.style.display = "block";
+ d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
+ d.scrollbarH.firstChild.style.width =
+ (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
+ } else d.scrollbarH.style.display = "";
+ if (needsH && needsV) {
+ d.scrollbarFiller.style.display = "block";
+ d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
+ } else d.scrollbarFiller.style.display = "";
+ if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
+ d.gutterFiller.style.display = "block";
+ d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
+ d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
+ } else d.gutterFiller.style.display = "";
+
+ if (mac_geLion && scrollbarWidth(d.measure) === 0)
+ d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
+ }
+
+ function visibleLines(display, doc, viewPort) {
+ var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
+ if (typeof viewPort == "number") top = viewPort;
+ else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
+ top = Math.floor(top - paddingTop(display));
+ var bottom = Math.ceil(top + height);
+ return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
+ }
+
+ // LINE NUMBERS
+
+ function alignHorizontally(cm) {
+ var display = cm.display;
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
+ var gutterW = display.gutters.offsetWidth, l = comp + "px";
+ for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
+ for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
+ }
+ if (cm.options.fixedGutter)
+ display.gutters.style.left = (comp + gutterW) + "px";
+ }
+
+ function maybeUpdateLineNumberWidth(cm) {
+ if (!cm.options.lineNumbers) return false;
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
+ if (last.length != display.lineNumChars) {
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
+ display.lineGutter.style.width = "";
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
+ display.lineGutter.style.width = display.lineNumWidth + "px";
+ return true;
+ }
+ return false;
+ }
+
+ function lineNumberFor(options, i) {
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
+ }
+ function compensateForHScroll(display) {
+ return getRect(display.scroller).left - getRect(display.sizer).left;
+ }
+
+ // DISPLAY DRAWING
+
+ function updateDisplay(cm, changes, viewPort, forced) {
+ var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
+ var visible = visibleLines(cm.display, cm.doc, viewPort);
+ for (;;) {
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
+ forced = false;
+ updated = true;
+ updateSelection(cm);
+ updateScrollbars(cm);
+
+ // Clip forced viewport to actual scrollable area
+ if (viewPort)
+ viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
+ typeof viewPort == "number" ? viewPort : viewPort.top);
+ visible = visibleLines(cm.display, cm.doc, viewPort);
+ if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
+ break;
+ changes = [];
+ }
+
+ if (updated) {
+ signalLater(cm, "update", cm);
+ if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
+ signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
+ }
+ return updated;
+ }
+
+ // Uses a set of changes plus the current scroll position to
+ // determine which DOM updates have to be made, and makes the
+ // updates.
+ function updateDisplayInner(cm, changes, visible, forced) {
+ var display = cm.display, doc = cm.doc;
+ if (!display.wrapper.clientWidth) {
+ display.showingFrom = display.showingTo = doc.first;
+ display.viewOffset = 0;
+ return;
+ }
+
+ // Bail out if the visible area is already rendered and nothing changed.
+ if (!forced && changes.length == 0 &&
+ visible.from > display.showingFrom && visible.to < display.showingTo)
+ return;
+
+ if (maybeUpdateLineNumberWidth(cm))
+ changes = [{from: doc.first, to: doc.first + doc.size}];
+ var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
+ display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";
+
+ // Used to determine which lines need their line numbers updated
+ var positionsChangedFrom = Infinity;
+ if (cm.options.lineNumbers)
+ for (var i = 0; i < changes.length; ++i)
+ if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
+
+ var end = doc.first + doc.size;
+ var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
+ var to = Math.min(end, visible.to + cm.options.viewportMargin);
+ if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
+ if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
+ if (sawCollapsedSpans) {
+ from = lineNo(visualLine(doc, getLine(doc, from)));
+ while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
+ }
+
+ // Create a range of theoretically intact lines, and punch holes
+ // in that using the change info.
+ var intact = [{from: Math.max(display.showingFrom, doc.first),
+ to: Math.min(display.showingTo, end)}];
+ if (intact[0].from >= intact[0].to) intact = [];
+ else intact = computeIntact(intact, changes);
+ // When merged lines are present, we might have to reduce the
+ // intact ranges because changes in continued fragments of the
+ // intact lines do require the lines to be redrawn.
+ if (sawCollapsedSpans)
+ for (var i = 0; i < intact.length; ++i) {
+ var range = intact[i], merged;
+ while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
+ var newTo = merged.find().from.line;
+ if (newTo > range.from) range.to = newTo;
+ else { intact.splice(i--, 1); break; }
+ }
+ }
+
+ // Clip off the parts that won't be visible
+ var intactLines = 0;
+ for (var i = 0; i < intact.length; ++i) {
+ var range = intact[i];
+ if (range.from < from) range.from = from;
+ if (range.to > to) range.to = to;
+ if (range.from >= range.to) intact.splice(i--, 1);
+ else intactLines += range.to - range.from;
+ }
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
+ updateViewOffset(cm);
+ return;
+ }
+ intact.sort(function(a, b) {return a.from - b.from;});
+
+ // Avoid crashing on IE's "unspecified error" when in iframes
+ try {
+ var focused = document.activeElement;
+ } catch(e) {}
+ if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
+ patchDisplay(cm, from, to, intact, positionsChangedFrom);
+ display.lineDiv.style.display = "";
+ if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();
+
+ var different = from != display.showingFrom || to != display.showingTo ||
+ display.lastSizeC != display.wrapper.clientHeight;
+ // This is just a bogus formula that detects when the editor is
+ // resized or the font size changes.
+ if (different) {
+ display.lastSizeC = display.wrapper.clientHeight;
+ startWorker(cm, 400);
+ }
+ display.showingFrom = from; display.showingTo = to;
+
+ updateHeightsInViewport(cm);
+ updateViewOffset(cm);
+
+ return true;
+ }
+
+ function updateHeightsInViewport(cm) {
+ var display = cm.display;
+ var prevBottom = display.lineDiv.offsetTop;
+ for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
+ if (ie_lt8) {
+ var bot = node.offsetTop + node.offsetHeight;
+ height = bot - prevBottom;
+ prevBottom = bot;
+ } else {
+ var box = getRect(node);
+ height = box.bottom - box.top;
+ }
+ var diff = node.lineObj.height - height;
+ if (height < 2) height = textHeight(display);
+ if (diff > .001 || diff < -.001) {
+ updateLineHeight(node.lineObj, height);
+ var widgets = node.lineObj.widgets;
+ if (widgets) for (var i = 0; i < widgets.length; ++i)
+ widgets[i].height = widgets[i].node.offsetHeight;
+ }
+ }
+ }
+
+ function updateViewOffset(cm) {
+ var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
+ // Position the mover div to align with the current virtual scroll position
+ cm.display.mover.style.top = off + "px";
+ }
+
+ function computeIntact(intact, changes) {
+ for (var i = 0, l = changes.length || 0; i < l; ++i) {
+ var change = changes[i], intact2 = [], diff = change.diff || 0;
+ for (var j = 0, l2 = intact.length; j < l2; ++j) {
+ var range = intact[j];
+ if (change.to <= range.from && change.diff) {
+ intact2.push({from: range.from + diff, to: range.to + diff});
+ } else if (change.to <= range.from || change.from >= range.to) {
+ intact2.push(range);
+ } else {
+ if (change.from > range.from)
+ intact2.push({from: range.from, to: change.from});
+ if (change.to < range.to)
+ intact2.push({from: change.to + diff, to: range.to + diff});
+ }
+ }
+ intact = intact2;
+ }
+ return intact;
+ }
+
+ function getDimensions(cm) {
+ var d = cm.display, left = {}, width = {};
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
+ left[cm.options.gutters[i]] = n.offsetLeft;
+ width[cm.options.gutters[i]] = n.offsetWidth;
+ }
+ return {fixedPos: compensateForHScroll(d),
+ gutterTotalWidth: d.gutters.offsetWidth,
+ gutterLeft: left,
+ gutterWidth: width,
+ wrapperWidth: d.wrapper.clientWidth};
+ }
+
+ function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
+ var dims = getDimensions(cm);
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
+ if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
+ removeChildren(display.lineDiv);
+ var container = display.lineDiv, cur = container.firstChild;
+
+ function rm(node) {
+ var next = node.nextSibling;
+ if (webkit && mac && cm.display.currentWheelTarget == node) {
+ node.style.display = "none";
+ node.lineObj = null;
+ } else {
+ node.parentNode.removeChild(node);
+ }
+ return next;
+ }
+
+ var nextIntact = intact.shift(), lineN = from;
+ cm.doc.iter(from, to, function(line) {
+ if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
+ if (lineIsHidden(cm.doc, line)) {
+ if (line.height != 0) updateLineHeight(line, 0);
+ if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
+ var w = line.widgets[i];
+ if (w.showIfHidden) {
+ var prev = cur.previousSibling;
+ if (/pre/i.test(prev.nodeName)) {
+ var wrap = elt("div", null, null, "position: relative");
+ prev.parentNode.replaceChild(wrap, prev);
+ wrap.appendChild(prev);
+ prev = wrap;
+ }
+ var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
+ if (!w.handleMouseEvents) wnode.ignoreEvents = true;
+ positionLineWidget(w, wnode, prev, dims);
+ }
+ }
+ } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
+ // This line is intact. Skip to the actual node. Update its
+ // line number if needed.
+ while (cur.lineObj != line) cur = rm(cur);
+ if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
+ setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
+ cur = cur.nextSibling;
+ } else {
+ // For lines with widgets, make an attempt to find and reuse
+ // the existing element, so that widgets aren't needlessly
+ // removed and re-inserted into the dom
+ if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
+ if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
+ // This line needs to be generated.
+ var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
+ if (lineNode != reuse) {
+ container.insertBefore(lineNode, cur);
+ } else {
+ while (cur != reuse) cur = rm(cur);
+ cur = cur.nextSibling;
+ }
+
+ lineNode.lineObj = line;
+ }
+ ++lineN;
+ });
+ while (cur) cur = rm(cur);
+ }
+
+ function buildLineElement(cm, line, lineNo, dims, reuse) {
+ var lineElement = lineContent(cm, line);
+ var markers = line.gutterMarkers, display = cm.display, wrap;
+
+ if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
+ return lineElement;
+
+ // Lines with gutter elements, widgets or a background class need
+ // to be wrapped again, and have the extra elements added to the
+ // wrapper div
+
+ if (reuse) {
+ reuse.alignable = null;
+ var isOk = true, widgetsSeen = 0, insertBefore = null;
+ for (var n = reuse.firstChild, next; n; n = next) {
+ next = n.nextSibling;
+ if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
+ reuse.removeChild(n);
+ } else {
+ for (var i = 0; i < line.widgets.length; ++i) {
+ var widget = line.widgets[i];
+ if (widget.node == n.firstChild) {
+ if (!widget.above && !insertBefore) insertBefore = n;
+ positionLineWidget(widget, n, reuse, dims);
+ ++widgetsSeen;
+ break;
+ }
+ }
+ if (i == line.widgets.length) { isOk = false; break; }
+ }
+ }
+ reuse.insertBefore(lineElement, insertBefore);
+ if (isOk && widgetsSeen == line.widgets.length) {
+ wrap = reuse;
+ reuse.className = line.wrapClass || "";
+ }
+ }
+ if (!wrap) {
+ wrap = elt("div", null, line.wrapClass, "position: relative");
+ wrap.appendChild(lineElement);
+ }
+ // Kludge to make sure the styled element lies behind the selection (by z-index)
+ if (line.bgClass)
+ wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
+ if (cm.options.lineNumbers || markers) {
+ var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
+ (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
+ wrap.firstChild);
+ if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
+ wrap.lineNumber = gutterWrap.appendChild(
+ elt("div", lineNumberFor(cm.options, lineNo),
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
+ + display.lineNumInnerWidth + "px"));
+ if (markers)
+ for (var k = 0; k < cm.options.gutters.length; ++k) {
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
+ if (found)
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
+ }
+ }
+ if (ie_lt8) wrap.style.zIndex = 2;
+ if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
+ if (!widget.handleMouseEvents) node.ignoreEvents = true;
+ positionLineWidget(widget, node, wrap, dims);
+ if (widget.above)
+ wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
+ else
+ wrap.appendChild(node);
+ signalLater(widget, "redraw");
+ }
+ return wrap;
+ }
+
+ function positionLineWidget(widget, node, wrap, dims) {
+ if (widget.noHScroll) {
+ (wrap.alignable || (wrap.alignable = [])).push(node);
+ var width = dims.wrapperWidth;
+ node.style.left = dims.fixedPos + "px";
+ if (!widget.coverGutter) {
+ width -= dims.gutterTotalWidth;
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
+ }
+ node.style.width = width + "px";
+ }
+ if (widget.coverGutter) {
+ node.style.zIndex = 5;
+ node.style.position = "relative";
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
+ }
+ }
+
+ // SELECTION / CURSOR
+
+ function updateSelection(cm) {
+ var display = cm.display;
+ var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
+ if (collapsed || cm.options.showCursorWhenSelecting)
+ updateSelectionCursor(cm);
+ else
+ display.cursor.style.display = display.otherCursor.style.display = "none";
+ if (!collapsed)
+ updateSelectionRange(cm);
+ else
+ display.selectionDiv.style.display = "none";
+
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
+ if (cm.options.moveInputWithCursor) {
+ var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
+ var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
+ display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
+ headPos.top + lineOff.top - wrapOff.top)) + "px";
+ display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
+ headPos.left + lineOff.left - wrapOff.left)) + "px";
+ }
+ }
+
+ // No selection, plain cursor
+ function updateSelectionCursor(cm) {
+ var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
+ display.cursor.style.left = pos.left + "px";
+ display.cursor.style.top = pos.top + "px";
+ display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
+ display.cursor.style.display = "";
+
+ if (pos.other) {
+ display.otherCursor.style.display = "";
+ display.otherCursor.style.left = pos.other.left + "px";
+ display.otherCursor.style.top = pos.other.top + "px";
+ display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
+ } else { display.otherCursor.style.display = "none"; }
+ }
+
+ // Highlight selection
+ function updateSelectionRange(cm) {
+ var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
+ var fragment = document.createDocumentFragment();
+ var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);
+
+ function add(left, top, width, bottom) {
+ if (top < 0) top = 0;
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
+ "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
+ "px; height: " + (bottom - top) + "px"));
+ }
+
+ function drawForLine(line, fromArg, toArg) {
+ var lineObj = getLine(doc, line);
+ var lineLen = lineObj.text.length;
+ var start, end;
+ function coords(ch, bias) {
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
+ }
+
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
+ var leftPos = coords(from, "left"), rightPos, left, right;
+ if (from == to) {
+ rightPos = leftPos;
+ left = right = leftPos.left;
+ } else {
+ rightPos = coords(to - 1, "right");
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
+ left = leftPos.left;
+ right = rightPos.right;
+ }
+ if (fromArg == null && from == 0) left = pl;
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
+ add(left, leftPos.top, null, leftPos.bottom);
+ left = pl;
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
+ }
+ if (toArg == null && to == lineLen) right = clientWidth;
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
+ start = leftPos;
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
+ end = rightPos;
+ if (left < pl + 1) left = pl;
+ add(left, rightPos.top, right - left, rightPos.bottom);
+ });
+ return {start: start, end: end};
+ }
+
+ if (sel.from.line == sel.to.line) {
+ drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
+ } else {
+ var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
+ var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
+ var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
+ var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
+ if (singleVLine) {
+ if (leftEnd.top < rightStart.top - 2) {
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
+ add(pl, rightStart.top, rightStart.left, rightStart.bottom);
+ } else {
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
+ }
+ }
+ if (leftEnd.bottom < rightStart.top)
+ add(pl, leftEnd.bottom, null, rightStart.top);
+ }
+
+ removeChildrenAndAdd(display.selectionDiv, fragment);
+ display.selectionDiv.style.display = "";
+ }
+
+ // Cursor-blinking
+ function restartBlink(cm) {
+ if (!cm.state.focused) return;
+ var display = cm.display;
+ clearInterval(display.blinker);
+ var on = true;
+ display.cursor.style.visibility = display.otherCursor.style.visibility = "";
+ display.blinker = setInterval(function() {
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate);
+ }
+
+ // HIGHLIGHT WORKER
+
+ function startWorker(cm, time) {
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
+ cm.state.highlight.set(time, bind(highlightWorker, cm));
+ }
+
+ function highlightWorker(cm) {
+ var doc = cm.doc;
+ if (doc.frontier < doc.first) doc.frontier = doc.first;
+ if (doc.frontier >= cm.display.showingTo) return;
+ var end = +new Date + cm.options.workTime;
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
+ var changed = [], prevChange;
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
+ if (doc.frontier >= cm.display.showingFrom) { // Visible
+ var oldStyles = line.styles;
+ line.styles = highlightLine(cm, line, state);
+ var ischange = !oldStyles || oldStyles.length != line.styles.length;
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
+ if (ischange) {
+ if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
+ else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
+ }
+ line.stateAfter = copyState(doc.mode, state);
+ } else {
+ processLine(cm, line, state);
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
+ }
+ ++doc.frontier;
+ if (+new Date > end) {
+ startWorker(cm, cm.options.workDelay);
+ return true;
+ }
+ });
+ if (changed.length)
+ operation(cm, function() {
+ for (var i = 0; i < changed.length; ++i)
+ regChange(this, changed[i].start, changed[i].end);
+ })();
+ }
+
+ // Finds the line to start with when starting a parse. Tries to
+ // find a line with a stateAfter, so that it can start with a
+ // valid state. If that fails, it returns the line with the
+ // smallest indentation, which tends to need the least context to
+ // parse correctly.
+ function findStartLine(cm, n, precise) {
+ var minindent, minline, doc = cm.doc;
+ for (var search = n, lim = n - 100; search > lim; --search) {
+ if (search <= doc.first) return doc.first;
+ var line = getLine(doc, search - 1);
+ if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
+ var indented = countColumn(line.text, null, cm.options.tabSize);
+ if (minline == null || minindent > indented) {
+ minline = search - 1;
+ minindent = indented;
+ }
+ }
+ return minline;
+ }
+
+ function getStateBefore(cm, n, precise) {
+ var doc = cm.doc, display = cm.display;
+ if (!doc.mode.startState) return true;
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
+ if (!state) state = startState(doc.mode);
+ else state = copyState(doc.mode, state);
+ doc.iter(pos, n, function(line) {
+ processLine(cm, line, state);
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
+ line.stateAfter = save ? copyState(doc.mode, state) : null;
+ ++pos;
+ });
+ return state;
+ }
+
+ // POSITION MEASUREMENT
+
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
+ function paddingLeft(display) {
+ var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
+ return e.offsetLeft;
+ }
+
+ function measureChar(cm, line, ch, data, bias) {
+ var dir = -1;
+ data = data || measureLine(cm, line);
+
+ for (var pos = ch;; pos += dir) {
+ var r = data[pos];
+ if (r) break;
+ if (dir < 0 && pos == 0) dir = 1;
+ }
+ bias = pos > ch ? "left" : pos < ch ? "right" : bias;
+ if (bias == "left" && r.leftSide) r = r.leftSide;
+ else if (bias == "right" && r.rightSide) r = r.rightSide;
+ return {left: pos < ch ? r.right : r.left,
+ right: pos > ch ? r.left : r.right,
+ top: r.top,
+ bottom: r.bottom};
+ }
+
+ function findCachedMeasurement(cm, line) {
+ var cache = cm.display.measureLineCache;
+ for (var i = 0; i < cache.length; ++i) {
+ var memo = cache[i];
+ if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
+ cm.display.scroller.clientWidth == memo.width &&
+ memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
+ return memo;
+ }
+ }
+
+ function clearCachedMeasurement(cm, line) {
+ var exists = findCachedMeasurement(cm, line);
+ if (exists) exists.text = exists.measure = exists.markedSpans = null;
+ }
+
+ function measureLine(cm, line) {
+ // First look in the cache
+ var cached = findCachedMeasurement(cm, line);
+ if (cached) return cached.measure;
+
+ // Failing that, recompute and store result in cache
+ var measure = measureLineInner(cm, line);
+ var cache = cm.display.measureLineCache;
+ var memo = {text: line.text, width: cm.display.scroller.clientWidth,
+ markedSpans: line.markedSpans, measure: measure,
+ classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
+ if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
+ else cache.push(memo);
+ return measure;
+ }
+
+ function measureLineInner(cm, line) {
+ var display = cm.display, measure = emptyArray(line.text.length);
+ var pre = lineContent(cm, line, measure, true);
+
+ // IE does not cache element positions of inline elements between
+ // calls to getBoundingClientRect. This makes the loop below,
+ // which gathers the positions of all the characters on the line,
+ // do an amount of layout work quadratic to the number of
+ // characters. When line wrapping is off, we try to improve things
+ // by first subdividing the line into a bunch of inline blocks, so
+ // that IE can reuse most of the layout information from caches
+ // for those blocks. This does interfere with line wrapping, so it
+ // doesn't work when wrapping is on, but in that case the
+ // situation is slightly better, since IE does cache line-wrapping
+ // information and only recomputes per-line.
+ if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
+ var fragment = document.createDocumentFragment();
+ var chunk = 10, n = pre.childNodes.length;
+ for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
+ var wrap = elt("div", null, null, "display: inline-block");
+ for (var j = 0; j < chunk && n; ++j) {
+ wrap.appendChild(pre.firstChild);
+ --n;
+ }
+ fragment.appendChild(wrap);
+ }
+ pre.appendChild(fragment);
+ }
+
+ removeChildrenAndAdd(display.measure, pre);
+
+ var outer = getRect(display.lineDiv);
+ var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
+ // Work around an IE7/8 bug where it will sometimes have randomly
+ // replaced our pre with a clone at this point.
+ if (ie_lt9 && display.measure.first != pre)
+ removeChildrenAndAdd(display.measure, pre);
+
+ function measureRect(rect) {
+ var top = rect.top - outer.top, bot = rect.bottom - outer.top;
+ if (bot > maxBot) bot = maxBot;
+ if (top < 0) top = 0;
+ for (var i = vranges.length - 2; i >= 0; i -= 2) {
+ var rtop = vranges[i], rbot = vranges[i+1];
+ if (rtop > bot || rbot < top) continue;
+ if (rtop <= top && rbot >= bot ||
+ top <= rtop && bot >= rbot ||
+ Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
+ vranges[i] = Math.min(top, rtop);
+ vranges[i+1] = Math.max(bot, rbot);
+ break;
+ }
+ }
+ if (i < 0) { i = vranges.length; vranges.push(top, bot); }
+ return {left: rect.left - outer.left,
+ right: rect.right - outer.left,
+ top: i, bottom: null};
+ }
+ function finishRect(rect) {
+ rect.bottom = vranges[rect.top+1];
+ rect.top = vranges[rect.top];
+ }
+
+ for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
+ var node = cur, rect = null;
+ // A widget might wrap, needs special care
+ if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
+ if (cur.firstChild.nodeType == 1) node = cur.firstChild;
+ var rects = node.getClientRects();
+ if (rects.length > 1) {
+ rect = data[i] = measureRect(rects[0]);
+ rect.rightSide = measureRect(rects[rects.length - 1]);
+ }
+ }
+ if (!rect) rect = data[i] = measureRect(getRect(node));
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
+ if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
+ }
+ for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
+ finishRect(cur);
+ if (cur.leftSide) finishRect(cur.leftSide);
+ if (cur.rightSide) finishRect(cur.rightSide);
+ }
+ return data;
+ }
+
+ function measureLineWidth(cm, line) {
+ var hasBadSpan = false;
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
+ var sp = line.markedSpans[i];
+ if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
+ }
+ var cached = !hasBadSpan && findCachedMeasurement(cm, line);
+ if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
+
+ var pre = lineContent(cm, line, null, true);
+ var end = pre.appendChild(zeroWidthElement(cm.display.measure));
+ removeChildrenAndAdd(cm.display.measure, pre);
+ return getRect(end).right - getRect(cm.display.lineDiv).left;
+ }
+
+ function clearCaches(cm) {
+ cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
+ if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
+ cm.display.lineNumChars = null;
+ }
+
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
+
+ // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
+ function intoCoordSystem(cm, lineObj, rect, context) {
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
+ var size = widgetHeight(lineObj.widgets[i]);
+ rect.top += size; rect.bottom += size;
+ }
+ if (context == "line") return rect;
+ if (!context) context = "local";
+ var yOff = heightAtLine(cm, lineObj);
+ if (context == "local") yOff += paddingTop(cm.display);
+ else yOff -= cm.display.viewOffset;
+ if (context == "page" || context == "window") {
+ var lOff = getRect(cm.display.lineSpace);
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
+ rect.left += xOff; rect.right += xOff;
+ }
+ rect.top += yOff; rect.bottom += yOff;
+ return rect;
+ }
+
+ // Context may be "window", "page", "div", or "local"/null
+ // Result is in "div" coords
+ function fromCoordSystem(cm, coords, context) {
+ if (context == "div") return coords;
+ var left = coords.left, top = coords.top;
+ // First move into "page" coordinate system
+ if (context == "page") {
+ left -= pageScrollX();
+ top -= pageScrollY();
+ } else if (context == "local" || !context) {
+ var localBox = getRect(cm.display.sizer);
+ left += localBox.left;
+ top += localBox.top;
+ }
+
+ var lineSpaceBox = getRect(cm.display.lineSpace);
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
+ }
+
+ function charCoords(cm, pos, context, lineObj, bias) {
+ if (!lineObj) lineObj = getLine(cm.doc, pos.line);
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
+ }
+
+ function cursorCoords(cm, pos, context, lineObj, measurement) {
+ lineObj = lineObj || getLine(cm.doc, pos.line);
+ if (!measurement) measurement = measureLine(cm, lineObj);
+ function get(ch, right) {
+ var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
+ if (right) m.left = m.right; else m.right = m.left;
+ return intoCoordSystem(cm, lineObj, m, context);
+ }
+ function getBidi(ch, partPos) {
+ var part = order[partPos], right = part.level % 2;
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
+ part = order[--partPos];
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
+ right = true;
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
+ part = order[++partPos];
+ ch = bidiLeft(part) - part.level % 2;
+ right = false;
+ }
+ if (right && ch == part.to && ch > part.from) return get(ch - 1);
+ return get(ch, right);
+ }
+ var order = getOrder(lineObj), ch = pos.ch;
+ if (!order) return get(ch);
+ var partPos = getBidiPartAt(order, ch);
+ var val = getBidi(ch, partPos);
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther);
+ return val;
+ }
+
+ function PosWithInfo(line, ch, outside, xRel) {
+ var pos = new Pos(line, ch);
+ pos.xRel = xRel;
+ if (outside) pos.outside = true;
+ return pos;
+ }
+
+ // Coords must be lineSpace-local
+ function coordsChar(cm, x, y) {
+ var doc = cm.doc;
+ y += cm.display.viewOffset;
+ if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
+ var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
+ if (lineNo > last)
+ return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
+ if (x < 0) x = 0;
+
+ for (;;) {
+ var lineObj = getLine(doc, lineNo);
+ var found = coordsCharInner(cm, lineObj, lineNo, x, y);
+ var merged = collapsedSpanAtEnd(lineObj);
+ var mergedPos = merged && merged.find();
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
+ lineNo = mergedPos.to.line;
+ else
+ return found;
+ }
+ }
+
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
+ var innerOff = y - heightAtLine(cm, lineObj);
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
+ var measurement = measureLine(cm, lineObj);
+
+ function getX(ch) {
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
+ lineObj, measurement);
+ wrongLine = true;
+ if (innerOff > sp.bottom) return sp.left - adjust;
+ else if (innerOff < sp.top) return sp.left + adjust;
+ else wrongLine = false;
+ return sp.left;
+ }
+
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
+
+ if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
+ // Do a binary search between these bounds.
+ for (;;) {
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
+ var ch = x < fromX || x - fromX <= toX - x ? from : to;
+ var xDiff = x - (ch == from ? fromX : toX);
+ while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
+ var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
+ xDiff < 0 ? -1 : xDiff ? 1 : 0);
+ return pos;
+ }
+ var step = Math.ceil(dist / 2), middle = from + step;
+ if (bidi) {
+ middle = from;
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
+ }
+ var middleX = getX(middle);
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
+ }
+ }
+
+ var measureText;
+ function textHeight(display) {
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
+ if (measureText == null) {
+ measureText = elt("pre");
+ // Measure a bunch of lines, for browsers that compute
+ // fractional heights.
+ for (var i = 0; i < 49; ++i) {
+ measureText.appendChild(document.createTextNode("x"));
+ measureText.appendChild(elt("br"));
+ }
+ measureText.appendChild(document.createTextNode("x"));
+ }
+ removeChildrenAndAdd(display.measure, measureText);
+ var height = measureText.offsetHeight / 50;
+ if (height > 3) display.cachedTextHeight = height;
+ removeChildren(display.measure);
+ return height || 1;
+ }
+
+ function charWidth(display) {
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
+ var anchor = elt("span", "x");
+ var pre = elt("pre", [anchor]);
+ removeChildrenAndAdd(display.measure, pre);
+ var width = anchor.offsetWidth;
+ if (width > 2) display.cachedCharWidth = width;
+ return width || 10;
+ }
+
+ // OPERATIONS
+
+ // Operations are used to wrap changes in such a way that each
+ // change won't have to update the cursor and display (which would
+ // be awkward, slow, and error-prone), but instead updates are
+ // batched and then all combined and executed at once.
+
+ var nextOpId = 0;
+ function startOperation(cm) {
+ cm.curOp = {
+ // An array of ranges of lines that have to be updated. See
+ // updateDisplay.
+ changes: [],
+ forceUpdate: false,
+ updateInput: null,
+ userSelChange: null,
+ textChanged: null,
+ selectionChanged: false,
+ cursorActivity: false,
+ updateMaxLine: false,
+ updateScrollPos: false,
+ id: ++nextOpId
+ };
+ if (!delayedCallbackDepth++) delayedCallbacks = [];
+ }
+
+ function endOperation(cm) {
+ var op = cm.curOp, doc = cm.doc, display = cm.display;
+ cm.curOp = null;
+
+ if (op.updateMaxLine) computeMaxLength(cm);
+ if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
+ var width = measureLineWidth(cm, display.maxLine);
+ display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
+ display.maxLineChanged = false;
+ var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
+ if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
+ setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
+ }
+ var newScrollPos, updated;
+ if (op.updateScrollPos) {
+ newScrollPos = op.updateScrollPos;
+ } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
+ var coords = cursorCoords(cm, doc.sel.head);
+ newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
+ }
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
+ if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
+ }
+ if (!updated && op.selectionChanged) updateSelection(cm);
+ if (op.updateScrollPos) {
+ display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
+ display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
+ alignHorizontally(cm);
+ if (op.scrollToPos)
+ scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
+ } else if (newScrollPos) {
+ scrollCursorIntoView(cm);
+ }
+ if (op.selectionChanged) restartBlink(cm);
+
+ if (cm.state.focused && op.updateInput)
+ resetInput(cm, op.userSelChange);
+
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
+ if (hidden) for (var i = 0; i < hidden.length; ++i)
+ if (!hidden[i].lines.length) signal(hidden[i], "hide");
+ if (unhidden) for (var i = 0; i < unhidden.length; ++i)
+ if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
+
+ var delayed;
+ if (!--delayedCallbackDepth) {
+ delayed = delayedCallbacks;
+ delayedCallbacks = null;
+ }
+ if (op.textChanged)
+ signal(cm, "change", cm, op.textChanged);
+ if (op.cursorActivity) signal(cm, "cursorActivity", cm);
+ if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
+ }
+
+ // Wraps a function in an operation. Returns the wrapped function.
+ function operation(cm1, f) {
+ return function() {
+ var cm = cm1 || this, withOp = !cm.curOp;
+ if (withOp) startOperation(cm);
+ try { var result = f.apply(cm, arguments); }
+ finally { if (withOp) endOperation(cm); }
+ return result;
+ };
+ }
+ function docOperation(f) {
+ return function() {
+ var withOp = this.cm && !this.cm.curOp, result;
+ if (withOp) startOperation(this.cm);
+ try { result = f.apply(this, arguments); }
+ finally { if (withOp) endOperation(this.cm); }
+ return result;
+ };
+ }
+ function runInOp(cm, f) {
+ var withOp = !cm.curOp, result;
+ if (withOp) startOperation(cm);
+ try { result = f(); }
+ finally { if (withOp) endOperation(cm); }
+ return result;
+ }
+
+ function regChange(cm, from, to, lendiff) {
+ if (from == null) from = cm.doc.first;
+ if (to == null) to = cm.doc.first + cm.doc.size;
+ cm.curOp.changes.push({from: from, to: to, diff: lendiff});
+ }
+
+ // INPUT HANDLING
+
+ function slowPoll(cm) {
+ if (cm.display.pollingFast) return;
+ cm.display.poll.set(cm.options.pollInterval, function() {
+ readInput(cm);
+ if (cm.state.focused) slowPoll(cm);
+ });
+ }
+
+ function fastPoll(cm) {
+ var missed = false;
+ cm.display.pollingFast = true;
+ function p() {
+ var changed = readInput(cm);
+ if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
+ else {cm.display.pollingFast = false; slowPoll(cm);}
+ }
+ cm.display.poll.set(20, p);
+ }
+
+ // prevInput is a hack to work with IME. If we reset the textarea
+ // on every change, that breaks IME. So we look for changes
+ // compared to the previous content instead. (Modern browsers have
+ // events that indicate IME taking place, but these are not widely
+ // supported or compatible enough yet to rely on.)
+ function readInput(cm) {
+ var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
+ if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
+ var text = input.value;
+ if (text == prevInput && posEq(sel.from, sel.to)) return false;
+ if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
+ resetInput(cm, true);
+ return false;
+ }
+
+ var withOp = !cm.curOp;
+ if (withOp) startOperation(cm);
+ sel.shift = false;
+ var same = 0, l = Math.min(prevInput.length, text.length);
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
+ var from = sel.from, to = sel.to;
+ if (same < prevInput.length)
+ from = Pos(from.line, from.ch - (prevInput.length - same));
+ else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));
+
+ var updateInput = cm.curOp.updateInput;
+ var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
+ origin: cm.state.pasteIncoming ? "paste" : "+input"};
+ makeChange(cm.doc, changeEvent, "end");
+ cm.curOp.updateInput = updateInput;
+ signalLater(cm, "inputRead", cm, changeEvent);
+
+ if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
+ else cm.display.prevInput = text;
+ if (withOp) endOperation(cm);
+ cm.state.pasteIncoming = false;
+ return true;
+ }
+
+ function resetInput(cm, user) {
+ var minimal, selected, doc = cm.doc;
+ if (!posEq(doc.sel.from, doc.sel.to)) {
+ cm.display.prevInput = "";
+ minimal = hasCopyEvent &&
+ (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
+ var content = minimal ? "-" : selected || cm.getSelection();
+ cm.display.input.value = content;
+ if (cm.state.focused) selectInput(cm.display.input);
+ if (ie && !ie_lt9) cm.display.inputHasSelection = content;
+ } else if (user) {
+ cm.display.prevInput = cm.display.input.value = "";
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
+ }
+ cm.display.inaccurateSelection = minimal;
+ }
+
+ function focusInput(cm) {
+ if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
+ cm.display.input.focus();
+ }
+
+ function isReadOnly(cm) {
+ return cm.options.readOnly || cm.doc.cantEdit;
+ }
+
+ // EVENT HANDLERS
+
+ function registerEventHandlers(cm) {
+ var d = cm.display;
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
+ if (ie)
+ on(d.scroller, "dblclick", operation(cm, function(e) {
+ if (signalDOMEvent(cm, e)) return;
+ var pos = posFromMouse(cm, e);
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
+ e_preventDefault(e);
+ var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
+ extendSelection(cm.doc, word.from, word.to);
+ }));
+ else
+ on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
+ on(d.lineSpace, "selectstart", function(e) {
+ if (!eventInWidget(d, e)) e_preventDefault(e);
+ });
+ // Gecko browsers fire contextmenu *after* opening the menu, at
+ // which point we can't mess with it anymore. Context menu is
+ // handled in onMouseDown for Gecko.
+ if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
+
+ on(d.scroller, "scroll", function() {
+ if (d.scroller.clientHeight) {
+ setScrollTop(cm, d.scroller.scrollTop);
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
+ signal(cm, "scroll", cm);
+ }
+ });
+ on(d.scrollbarV, "scroll", function() {
+ if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
+ });
+ on(d.scrollbarH, "scroll", function() {
+ if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
+ });
+
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
+
+ function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
+ on(d.scrollbarH, "mousedown", reFocus);
+ on(d.scrollbarV, "mousedown", reFocus);
+ // Prevent wrapper from ever scrolling
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
+
+ var resizeTimer;
+ function onResize() {
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
+ resizeTimer = null;
+ // Might be a text scaling operation, clear size caches.
+ d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
+ clearCaches(cm);
+ runInOp(cm, bind(regChange, cm));
+ }, 100);
+ }
+ on(window, "resize", onResize);
+ // Above handler holds on to the editor and its data structures.
+ // Here we poll to unregister it when the editor is no longer in
+ // the document, so that it can be garbage-collected.
+ function unregister() {
+ for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
+ if (p) setTimeout(unregister, 5000);
+ else off(window, "resize", onResize);
+ }
+ setTimeout(unregister, 5000);
+
+ on(d.input, "keyup", operation(cm, function(e) {
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ if (e.keyCode == 16) cm.doc.sel.shift = false;
+ }));
+ on(d.input, "input", bind(fastPoll, cm));
+ on(d.input, "keydown", operation(cm, onKeyDown));
+ on(d.input, "keypress", operation(cm, onKeyPress));
+ on(d.input, "focus", bind(onFocus, cm));
+ on(d.input, "blur", bind(onBlur, cm));
+
+ function drag_(e) {
+ if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
+ e_stop(e);
+ }
+ if (cm.options.dragDrop) {
+ on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
+ on(d.scroller, "dragenter", drag_);
+ on(d.scroller, "dragover", drag_);
+ on(d.scroller, "drop", operation(cm, onDrop));
+ }
+ on(d.scroller, "paste", function(e){
+ if (eventInWidget(d, e)) return;
+ focusInput(cm);
+ fastPoll(cm);
+ });
+ on(d.input, "paste", function() {
+ cm.state.pasteIncoming = true;
+ fastPoll(cm);
+ });
+
+ function prepareCopy() {
+ if (d.inaccurateSelection) {
+ d.prevInput = "";
+ d.inaccurateSelection = false;
+ d.input.value = cm.getSelection();
+ selectInput(d.input);
+ }
+ }
+ on(d.input, "cut", prepareCopy);
+ on(d.input, "copy", prepareCopy);
+
+ // Needed to handle Tab key in KHTML
+ if (khtml) on(d.sizer, "mouseup", function() {
+ if (document.activeElement == d.input) d.input.blur();
+ focusInput(cm);
+ });
+ }
+
+ function eventInWidget(display, e) {
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
+ if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
+ }
+ }
+
+ function posFromMouse(cm, e, liberal) {
+ var display = cm.display;
+ if (!liberal) {
+ var target = e_target(e);
+ if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
+ target == display.scrollbarV || target == display.scrollbarV.firstChild ||
+ target == display.scrollbarFiller || target == display.gutterFiller) return null;
+ }
+ var x, y, space = getRect(display.lineSpace);
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
+ try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
+ return coordsChar(cm, x - space.left, y - space.top);
+ }
+
+ var lastClick, lastDoubleClick;
+ function onMouseDown(e) {
+ if (signalDOMEvent(this, e)) return;
+ var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
+ sel.shift = e.shiftKey;
+
+ if (eventInWidget(display, e)) {
+ if (!webkit) {
+ display.scroller.draggable = false;
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
+ }
+ return;
+ }
+ if (clickInGutter(cm, e)) return;
+ var start = posFromMouse(cm, e);
+
+ switch (e_button(e)) {
+ case 3:
+ if (captureMiddleClick) onContextMenu.call(cm, cm, e);
+ return;
+ case 2:
+ if (start) extendSelection(cm.doc, start);
+ setTimeout(bind(focusInput, cm), 20);
+ e_preventDefault(e);
+ return;
+ }
+ // For button 1, if it was clicked inside the editor
+ // (posFromMouse returning non-null), we have to adjust the
+ // selection.
+ if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}
+
+ if (!cm.state.focused) onFocus(cm);
+
+ var now = +new Date, type = "single";
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
+ type = "triple";
+ e_preventDefault(e);
+ setTimeout(bind(focusInput, cm), 20);
+ selectLine(cm, start.line);
+ } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
+ type = "double";
+ lastDoubleClick = {time: now, pos: start};
+ e_preventDefault(e);
+ var word = findWordAt(getLine(doc, start.line).text, start);
+ extendSelection(cm.doc, word.from, word.to);
+ } else { lastClick = {time: now, pos: start}; }
+
+ var last = start;
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
+ !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
+ var dragEnd = operation(cm, function(e2) {
+ if (webkit) display.scroller.draggable = false;
+ cm.state.draggingText = false;
+ off(document, "mouseup", dragEnd);
+ off(display.scroller, "drop", dragEnd);
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
+ e_preventDefault(e2);
+ extendSelection(cm.doc, start);
+ focusInput(cm);
+ }
+ });
+ // Let the drag handler handle this.
+ if (webkit) display.scroller.draggable = true;
+ cm.state.draggingText = dragEnd;
+ // IE's approach to draggable
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
+ on(document, "mouseup", dragEnd);
+ on(display.scroller, "drop", dragEnd);
+ return;
+ }
+ e_preventDefault(e);
+ if (type == "single") extendSelection(cm.doc, clipPos(doc, start));
+
+ var startstart = sel.from, startend = sel.to, lastPos = start;
+
+ function doSelect(cur) {
+ if (posEq(lastPos, cur)) return;
+ lastPos = cur;
+
+ if (type == "single") {
+ extendSelection(cm.doc, clipPos(doc, start), cur);
+ return;
+ }
+
+ startstart = clipPos(doc, startstart);
+ startend = clipPos(doc, startend);
+ if (type == "double") {
+ var word = findWordAt(getLine(doc, cur.line).text, cur);
+ if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
+ else extendSelection(cm.doc, startstart, word.to);
+ } else if (type == "triple") {
+ if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
+ else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
+ }
+ }
+
+ var editorSize = getRect(display.wrapper);
+ // Used to ensure timeout re-tries don't fire when another extend
+ // happened in the meantime (clearTimeout isn't reliable -- at
+ // least on Chrome, the timeouts still happen even when cleared,
+ // if the clear happens after their scheduled firing time).
+ var counter = 0;
+
+ function extend(e) {
+ var curCount = ++counter;
+ var cur = posFromMouse(cm, e, true);
+ if (!cur) return;
+ if (!posEq(cur, last)) {
+ if (!cm.state.focused) onFocus(cm);
+ last = cur;
+ doSelect(cur);
+ var visible = visibleLines(display, doc);
+ if (cur.line >= visible.to || cur.line < visible.from)
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
+ } else {
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
+ if (outside) setTimeout(operation(cm, function() {
+ if (counter != curCount) return;
+ display.scroller.scrollTop += outside;
+ extend(e);
+ }), 50);
+ }
+ }
+
+ function done(e) {
+ counter = Infinity;
+ e_preventDefault(e);
+ focusInput(cm);
+ off(document, "mousemove", move);
+ off(document, "mouseup", up);
+ }
+
+ var move = operation(cm, function(e) {
+ if (!ie && !e_button(e)) done(e);
+ else extend(e);
+ });
+ var up = operation(cm, done);
+ on(document, "mousemove", move);
+ on(document, "mouseup", up);
+ }
+
+ function clickInGutter(cm, e) {
+ var display = cm.display;
+ try { var mX = e.clientX, mY = e.clientY; }
+ catch(e) { return false; }
+
+ if (mX >= Math.floor(getRect(display.gutters).right)) return false;
+ e_preventDefault(e);
+ if (!hasHandler(cm, "gutterClick")) return true;
+
+ var lineBox = getRect(display.lineDiv);
+ if (mY > lineBox.bottom) return true;
+ mY -= lineBox.top - display.viewOffset;
+
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
+ var g = display.gutters.childNodes[i];
+ if (g && getRect(g).right >= mX) {
+ var line = lineAtHeight(cm.doc, mY);
+ var gutter = cm.options.gutters[i];
+ signalLater(cm, "gutterClick", cm, line, gutter, e);
+ break;
+ }
+ }
+ return true;
+ }
+
+ // Kludge to work around strange IE behavior where it'll sometimes
+ // re-fire a series of drag-related events right after the drop (#1551)
+ var lastDrop = 0;
+
+ function onDrop(e) {
+ var cm = this;
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
+ return;
+ e_preventDefault(e);
+ if (ie) lastDrop = +new Date;
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
+ if (!pos || isReadOnly(cm)) return;
+ if (files && files.length && window.FileReader && window.File) {
+ var n = files.length, text = Array(n), read = 0;
+ var loadFile = function(file, i) {
+ var reader = new FileReader;
+ reader.onload = function() {
+ text[i] = reader.result;
+ if (++read == n) {
+ pos = clipPos(cm.doc, pos);
+ makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
+ }
+ };
+ reader.readAsText(file);
+ };
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
+ } else {
+ // Don't do a replace if the drop happened inside of the selected text.
+ if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
+ cm.state.draggingText(e);
+ // Ensure the editor is re-focused
+ setTimeout(bind(focusInput, cm), 20);
+ return;
+ }
+ try {
+ var text = e.dataTransfer.getData("Text");
+ if (text) {
+ var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
+ setSelection(cm.doc, pos, pos);
+ if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
+ cm.replaceSelection(text, null, "paste");
+ focusInput(cm);
+ onFocus(cm);
+ }
+ }
+ catch(e){}
+ }
+ }
+
+ function onDragStart(cm, e) {
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
+
+ var txt = cm.getSelection();
+ e.dataTransfer.setData("Text", txt);
+
+ // Use dummy image instead of default browsers image.
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
+ if (e.dataTransfer.setDragImage && !safari) {
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
+ if (opera) {
+ img.width = img.height = 1;
+ cm.display.wrapper.appendChild(img);
+ // Force a relayout, or Opera won't use our image for some obscure reason
+ img._top = img.offsetTop;
+ }
+ e.dataTransfer.setDragImage(img, 0, 0);
+ if (opera) img.parentNode.removeChild(img);
+ }
+ }
+
+ function setScrollTop(cm, val) {
+ if (Math.abs(cm.doc.scrollTop - val) < 2) return;
+ cm.doc.scrollTop = val;
+ if (!gecko) updateDisplay(cm, [], val);
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
+ if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
+ if (gecko) updateDisplay(cm, []);
+ startWorker(cm, 100);
+ }
+ function setScrollLeft(cm, val, isScroller) {
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
+ cm.doc.scrollLeft = val;
+ alignHorizontally(cm);
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
+ if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
+ }
+
+ // Since the delta values reported on mouse wheel events are
+ // unstandardized between browsers and even browser versions, and
+ // generally horribly unpredictable, this code starts by measuring
+ // the scroll effect that the first few mouse wheel events have,
+ // and, from that, detects the way it can convert deltas to pixel
+ // offsets afterwards.
+ //
+ // The reason we want to know the amount a wheel event will scroll
+ // is that it gives us a chance to update the display before the
+ // actual scrolling happens, reducing flickering.
+
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
+ // Fill in a browser-detected starting value on browsers where we
+ // know one. These don't have to be accurate -- the result of them
+ // being wrong would just be a slight flicker on the first wheel
+ // scroll (if it is large enough).
+ if (ie) wheelPixelsPerUnit = -.53;
+ else if (gecko) wheelPixelsPerUnit = 15;
+ else if (chrome) wheelPixelsPerUnit = -.7;
+ else if (safari) wheelPixelsPerUnit = -1/3;
+
+ function onScrollWheel(cm, e) {
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
+ else if (dy == null) dy = e.wheelDelta;
+
+ var display = cm.display, scroll = display.scroller;
+ // Quit if there's nothing to scroll here
+ if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
+ dy && scroll.scrollHeight > scroll.clientHeight)) return;
+
+ // Webkit browsers on OS X abort momentum scrolls when the target
+ // of the scroll event is removed from the scrollable element.
+ // This hack (see related code in patchDisplay) makes sure the
+ // element is kept around.
+ if (dy && mac && webkit) {
+ for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
+ if (cur.lineObj) {
+ cm.display.currentWheelTarget = cur;
+ break;
+ }
+ }
+ }
+
+ // On some browsers, horizontal scrolling will cause redraws to
+ // happen before the gutter has been realigned, causing it to
+ // wriggle around in a most unseemly way. When we have an
+ // estimated pixels/delta value, we just handle horizontal
+ // scrolling entirely here. It'll be slightly off from native, but
+ // better than glitching out.
+ if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
+ if (dy)
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
+ e_preventDefault(e);
+ display.wheelStartX = null; // Abort measurement, if in progress
+ return;
+ }
+
+ if (dy && wheelPixelsPerUnit != null) {
+ var pixels = dy * wheelPixelsPerUnit;
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
+ else bot = Math.min(cm.doc.height, bot + pixels + 50);
+ updateDisplay(cm, [], {top: top, bottom: bot});
+ }
+
+ if (wheelSamples < 20) {
+ if (display.wheelStartX == null) {
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
+ display.wheelDX = dx; display.wheelDY = dy;
+ setTimeout(function() {
+ if (display.wheelStartX == null) return;
+ var movedX = scroll.scrollLeft - display.wheelStartX;
+ var movedY = scroll.scrollTop - display.wheelStartY;
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
+ (movedX && display.wheelDX && movedX / display.wheelDX);
+ display.wheelStartX = display.wheelStartY = null;
+ if (!sample) return;
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
+ ++wheelSamples;
+ }, 200);
+ } else {
+ display.wheelDX += dx; display.wheelDY += dy;
+ }
+ }
+ }
+
+ function doHandleBinding(cm, bound, dropShift) {
+ if (typeof bound == "string") {
+ bound = commands[bound];
+ if (!bound) return false;
+ }
+ // Ensure previous input has been read, so that the handler sees a
+ // consistent view of the document
+ if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
+ var doc = cm.doc, prevShift = doc.sel.shift, done = false;
+ try {
+ if (isReadOnly(cm)) cm.state.suppressEdits = true;
+ if (dropShift) doc.sel.shift = false;
+ done = bound(cm) != Pass;
+ } finally {
+ doc.sel.shift = prevShift;
+ cm.state.suppressEdits = false;
+ }
+ return done;
+ }
+
+ function allKeyMaps(cm) {
+ var maps = cm.state.keyMaps.slice(0);
+ if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
+ maps.push(cm.options.keyMap);
+ return maps;
+ }
+
+ var maybeTransition;
+ function handleKeyBinding(cm, e) {
+ // Handle auto keymap transitions
+ var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
+ clearTimeout(maybeTransition);
+ if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
+ if (getKeyMap(cm.options.keyMap) == startMap) {
+ cm.options.keyMap = (next.call ? next.call(null, cm) : next);
+ keyMapChanged(cm);
+ }
+ }, 50);
+
+ var name = keyName(e, true), handled = false;
+ if (!name) return false;
+ var keymaps = allKeyMaps(cm);
+
+ if (e.shiftKey) {
+ // First try to resolve full name (including 'Shift-'). Failing
+ // that, see if there is a cursor-motion command (starting with
+ // 'go') bound to the keyname without 'Shift-'.
+ handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
+ || lookupKey(name, keymaps, function(b) {
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
+ return doHandleBinding(cm, b);
+ });
+ } else {
+ handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
+ }
+
+ if (handled) {
+ e_preventDefault(e);
+ restartBlink(cm);
+ if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
+ signalLater(cm, "keyHandled", cm, name, e);
+ }
+ return handled;
+ }
+
+ function handleCharBinding(cm, e, ch) {
+ var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
+ function(b) { return doHandleBinding(cm, b, true); });
+ if (handled) {
+ e_preventDefault(e);
+ restartBlink(cm);
+ signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
+ }
+ return handled;
+ }
+
+ var lastStoppedKey = null;
+ function onKeyDown(e) {
+ var cm = this;
+ if (!cm.state.focused) onFocus(cm);
+ if (ie && e.keyCode == 27) { e.returnValue = false; }
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ var code = e.keyCode;
+ // IE does strange things with escape.
+ cm.doc.sel.shift = code == 16 || e.shiftKey;
+ // First give onKeyEvent option a chance to handle this.
+ var handled = handleKeyBinding(cm, e);
+ if (opera) {
+ lastStoppedKey = handled ? code : null;
+ // Opera has no cut event... we try to at least catch the key combo
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
+ cm.replaceSelection("");
+ }
+ }
+
+ function onKeyPress(e) {
+ var cm = this;
+ if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ var keyCode = e.keyCode, charCode = e.charCode;
+ if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
+ if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
+ if (this.options.electricChars && this.doc.mode.electricChars &&
+ this.options.smartIndent && !isReadOnly(this) &&
+ this.doc.mode.electricChars.indexOf(ch) > -1)
+ setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
+ if (handleCharBinding(cm, e, ch)) return;
+ if (ie && !ie_lt9) cm.display.inputHasSelection = null;
+ fastPoll(cm);
+ }
+
+ function onFocus(cm) {
+ if (cm.options.readOnly == "nocursor") return;
+ if (!cm.state.focused) {
+ signal(cm, "focus", cm);
+ cm.state.focused = true;
+ if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
+ cm.display.wrapper.className += " CodeMirror-focused";
+ resetInput(cm, true);
+ }
+ slowPoll(cm);
+ restartBlink(cm);
+ }
+ function onBlur(cm) {
+ if (cm.state.focused) {
+ signal(cm, "blur", cm);
+ cm.state.focused = false;
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
+ }
+ clearInterval(cm.display.blinker);
+ setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
+ }
+
+ var detectingSelectAll;
+ function onContextMenu(cm, e) {
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
+ var display = cm.display, sel = cm.doc.sel;
+ if (eventInWidget(display, e)) return;
+
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
+ if (!pos || opera) return; // Opera is difficult.
+ if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
+ operation(cm, setSelection)(cm.doc, pos, pos);
+
+ var oldCSS = display.input.style.cssText;
+ display.inputDiv.style.position = "absolute";
+ display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; backgro
<TRUNCATED>