Merge pull request #107 from NextStepWebs/development

Custom preview rendering, Loads of bug fixes
pull/124/head 1.7.1
Wes Cossick 9 years ago
commit 57fcf521a0

@ -9,7 +9,7 @@ A drop-in JavaScript textarea replacement for writing beautiful and understandab
WYSIWYG editors that produce HTML are often complex and buggy. Markdown solves this problem in many ways, plus Markdown can be rendered natively on more platforms than HTML. However, Markdown is not a syntax that an average user will be familiar with, nor is it visually clear while editing. In otherwords, for an unfamiliar user, the syntax they write will make little sense until they click the preview button. SimpleMDE has been designed to bridge this gap for non-technical users who are less familiar with or just learning Markdown syntax.
## Quick start
SimpleMDE is available on npm.
SimpleMDE is available on [npm](https://www.npmjs.com/package/simplemde).
```
npm install simplemde --save
```
@ -32,7 +32,6 @@ And then load SimpleMDE on the first textarea on a page
```HTML
<script>
var simplemde = new SimpleMDE();
simplemde.render();
</script>
```
@ -43,7 +42,6 @@ Pure JavaScript method
```HTML
<script>
var simplemde = new SimpleMDE({ element: document.getElementById("MyID") });
simplemde.render();
</script>
```
@ -52,56 +50,81 @@ jQuery method
```HTML
<script>
var simplemde = new SimpleMDE({ element: $("#MyID")[0] });
simplemde.render();
</script>
```
## Get the content
## Get/set the content
```JavaScript
simplemde.value();
```
```JavaScript
simplemde.value("This text will appear in the editor");
```
## Configuration
- **autofocus**: If set to `true`, autofocuses the editor. Defaults to `false`.
- **autosave**: *Saves the text that's being written. It will forget the text when the form is submitted.*
- **enabled**: If set to `true`, autosave the text. Defaults to `false`.
- **delay**: Delay between saves, in milliseconds. Defaults to `10000` (10s).
- **unique_id**: You must set a unique identifier so that SimpleMDE can autosave. Something that separates this from other textareas.
- **element**: The DOM element for the textarea to use. Defaults to the first textarea on the page.
- **indentWithTabs**: If set to `false`, indent using spaces instead of tabs. Defaults to `true`.
- **initialValue**: If set, will customize the initial value of the editor.
- **lineWrapping**: If set to `false`, disable line wrapping. Defaults to `true`.
- **parsingConfig**: Adjust settings for parsing the Markdown during editing (not previewing).
- **allowAtxHeaderWithoutSpace**: If set to `true`, will render headers without a space after the `#`. Defaults to `false`.
- **fencedCodeBlocks**: If set to `false`, will not process GFM fenced code blocks syntax. Defaults to `true`.
- **strikethrough**: If set to `false`, will not process GFM strikethrough syntax. Defaults to `true`.
- **underscoresBreakWords**: If set to `true`, let underscores be a delimiter for separating words. Defaults to `false`.
- **previewRender**: Custom function for parsing the plaintext Markdown and returning HTML. Used when user previews.
- **singleLineBreaks**: If set to `false`, disable parsing GFM single line breaks. Defaults to `true`.
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`.
- **status**: If set to `false`, hide the status bar. Defaults to `true`.
- Optionally, you can set an array of status bar elements to include, and in what order.
- **tabSize**: If set, customize the tab size. Defaults to `2`.
- **toolbar**: If set to `false`, hide the toolbar. Defaults to the [array of icons](#toolbar-icons).
- **toolbarTips**: If set to `false`, disable toolbar button tips. Defaults to `true`.
- **toolbarGuideIcon**: If set to `false`, disable guide icon in the toolbar. Defaults to `true`.
- **autofocus**: If set to `true`, autofocuses the editor. Defaults to `false`.
- **lineWrapping**: If set to `false`, disable line wrapping. Defaults to `true`.
- **indentWithTabs**: If set to `false`, indent using spaces instead of tabs. Defaults to `true`.
- **tabSize**: If set, customize the tab size. Defaults to `2`.
- **initialValue**: If set, will customize the initial value of the editor.
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`.
- **singleLineBreaks**: If set to `false`, disable parsing GFM single line breaks. Defaults to `true`.
- **autosave**: *Saves the text that's being written. It will forget the text when the form is submitted.*
- **enabled**: If set to `true`, autosave the text. Defaults to `false`.
- **unique_id**: You must set a unique identifier so that SimpleMDE can autosave. Something that separates this from other textareas.
- **delay**: Delay between saves, in milliseconds. Defaults to `10000` (10s).
- **toolbarTips**: If set to `false`, disable toolbar button tips. Defaults to `true`.
```JavaScript
var simplemde = new SimpleMDE({
element: document.getElementById("MyID"),
status: false,
status: ['autosave', 'lines', 'words', 'cursor'], // Optional usage
toolbar: false,
toolbarTips: false,
toolbarGuideIcon: false,
autofocus: true,
lineWrapping: false,
indentWithTabs: false,
tabSize: 4,
initialValue: "Hello world!",
spellChecker: false,
singleLineBreaks: false,
autosave: {
enabled: true,
unique_id: "MyUniqueID",
delay: 1000,
},
element: document.getElementById("MyID"),
indentWithTabs: false,
initialValue: "Hello world!",
lineWrapping: false,
parsingConfig: {
allowAtxHeaderWithoutSpace: true,
fencedCodeBlocks: false,
strikethrough: false,
underscoresBreakWords: true,
},
previewRender: function(plainText) {
return customMarkdownParser(plainText); // Returns HTML from a custom parser
},
previewRender: function(plainText, preview) { // Async method
setTimeout(function(){
preview.innerHTML = customMarkdownParser(plainText);
}, 250);
return "Loading...";
}
singleLineBreaks: false,
spellChecker: false,
status: false,
status: ['autosave', 'lines', 'words', 'cursor'], // Optional usage
tabSize: 4,
toolbar: false,
toolbarGuideIcon: false,
toolbarTips: false,
});
```
@ -109,28 +132,28 @@ var simplemde = new SimpleMDE({
Below are the built-in toolbar icons (only some of which are enabled by default), which can be reorganized however you like. "Name" is the name of the icon, referenced in the JS. "Action" is either a function or a URL to open. "Class" is the class given to the icon. "Tooltip" is the small tooltip that appears via the `title=""` attribute. The `Ctrl` and `Alt` in the title tags will be changed automatically to their Mac equivalents when needed. Additionally, you can add a separator between any icons by adding `"|"` to the toolbar array.
Name | Action | Class | Tooltip
:--- | :----- | :---- | :------
bold | toggleBold | fa fa-bold | Bold (Ctrl+B)
italic | toggleItalic | fa fa-italic | Italic (Ctrl+I)
strikethrough | toggleStrikethrough | fa fa-strikethrough | Strikethrough
heading | toggleHeadingSmaller | fa fa-header | Heading (Ctrl+H)
heading-smaller | toggleHeadingSmaller | fa fa-header | Smaller Heading (Ctrl+H)
heading-bigger | toggleHeadingBigger | fa fa-lg fa-header | Bigger Heading (Shift+Ctrl+H)
heading-1 | toggleHeading1 | fa fa-header fa-header-x fa-header-1 | Big Heading
heading-2 | toggleHeading2 | fa fa-header fa-header-x fa-header-2 | Medium Heading
heading-3 | toggleHeading3 | fa fa-header fa-header-x fa-header-3 | Small Heading
code | toggleCodeBlock | fa fa-code | Code (Ctrl+Alt+C)
quote | toggleBlockquote | fa fa-quote-left | Quote (Ctrl+')
unordered-list | toggleUnorderedList | fa fa-list-ul | Generic List (Ctrl+L)
numbered-list | toggleOrderedList | fa fa-list-ol | Numbered List (Ctrl+Alt+L)
link | drawLink | fa fa-link | Create Link (Ctrl+K)
image | drawImage | fa fa-picture-o | Insert Image (Ctrl+Alt+I)
horizontal-rule | drawHorizontalRule | fa fa-minus | Insert Horizontal Line
preview | togglePreview | fa fa-eye | Toggle Preview (Ctrl+P)
side-by-side | toggleSideBySide | fa fa-columns | Toggle Side by Side (F9)
fullscreen | toggleFullScreen | fa fa-arrows-alt | Toggle Fullscreen (F11)
guide | [This link](http://nextstepwebs.github.io/simplemde-markdown-editor/markdown-guide) | fa fa-question-circle | Markdown Guide
Name | Action | Tooltip<br>Class
:--- | :----- | :--------------
bold | toggleBold | Bold (Ctrl+B)<br>fa fa-bold
italic | toggleItalic | Italic (Ctrl+I)<br>fa fa-italic
strikethrough | toggleStrikethrough | Strikethrough<br>fa fa-strikethrough
heading | toggleHeadingSmaller | Heading (Ctrl+H)<br>fa fa-header
heading-smaller | toggleHeadingSmaller | Smaller Heading (Ctrl+H)<br>fa fa-header
heading-bigger | toggleHeadingBigger | Bigger Heading (Shift+Ctrl+H)<br>fa fa-lg fa-header
heading-1 | toggleHeading1 | Big Heading<br>fa fa-header fa-header-x fa-header-1
heading-2 | toggleHeading2 | Medium Heading<br>fa fa-header fa-header-x fa-header-2
heading-3 | toggleHeading3 | Small Heading<br>fa fa-header fa-header-x fa-header-3
code | toggleCodeBlock | Code (Ctrl+Alt+C)<br>fa fa-code
quote | toggleBlockquote | Quote (Ctrl+')<br>fa fa-quote-left
unordered-list | toggleUnorderedList | Generic List (Ctrl+L)<br>fa fa-list-ul
ordered-list | toggleOrderedList | Numbered List (Ctrl+Alt+L)<br>fa fa-list-ol
link | drawLink | Create Link (Ctrl+K)<br>fa fa-link
image | drawImage | Insert Image (Ctrl+Alt+I)<br>fa fa-picture-o
horizontal-rule | drawHorizontalRule | Insert Horizontal Line<br>fa fa-minus
preview | togglePreview | Toggle Preview (Ctrl+P)<br>fa fa-eye
side-by-side | toggleSideBySide | Toggle Side by Side (F9)<br>fa fa-columns
fullscreen | toggleFullScreen | Toggle Fullscreen (F11)<br>fa fa-arrows-alt
guide | [This link](http://nextstepwebs.github.io/simplemde-markdown-editor/markdown-guide) | Markdown Guide<br>fa fa-question-circle
Customize the toolbar using the `toolbar` option like:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,61 +1,112 @@
var gulp = require('gulp'),
minifycss = require('gulp-minify-css'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
header = require('gulp-header'),
pkg = require('./package.json'),
prettify = require('gulp-jsbeautifier');
var banner = ['/**',
' * <%= pkg.name %> v<%= pkg.version %>',
' * Copyright <%= pkg.company %>',
' * @link <%= pkg.homepage %>',
' * @license <%= pkg.license %>',
' */',
''].join('\n');
gulp.task('scripts', function() {
var gulp = require("gulp"),
minifycss = require("gulp-minify-css"),
uglify = require("gulp-uglify"),
concat = require("gulp-concat"),
header = require("gulp-header"),
pkg = require("./package.json"),
prettify = require("gulp-jsbeautifier"),
download = require("gulp-download");
var banner = ["/**",
" * <%= pkg.name %> v<%= pkg.version %>",
" * Copyright <%= pkg.company %>",
" * @link <%= pkg.homepage %>",
" * @license <%= pkg.license %>",
" */",
""].join("\n");
gulp.task("downloads-codemirror", function(callback) {
var download_urls = [
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/lib/codemirror.js",
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/addon/edit/continuelist.js",
//"https://raw.githubusercontent.com/codemirror/CodeMirror/master/addon/edit/tablist.js", //waiting for PRs
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/addon/display/fullscreen.js",
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/addon/mode/overlay.js",
//"https://raw.githubusercontent.com/codemirror/CodeMirror/master/mode/gfm/gfm.js", //waiting for PRs
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/mode/markdown/markdown.js",
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/mode/xml/xml.js"];
download(download_urls)
.pipe(gulp.dest("src/js/codemirror/"));
// Wait to make sure they've been downloaded
setTimeout(function() {
callback();
}, 5000);
});
gulp.task("downloads-js", function(callback) {
var download_urls = [
"https://raw.githubusercontent.com/chjj/marked/master/lib/marked.js",
"https://raw.githubusercontent.com/NextStepWebs/codemirror-spell-checker/master/src/js/spell-checker.js",
"https://raw.githubusercontent.com/NextStepWebs/codemirror-spell-checker/master/src/js/typo.js"];
download(download_urls)
.pipe(gulp.dest("src/js/"));
// Wait to make sure they've been downloaded
setTimeout(function() {
callback();
}, 5000);
});
gulp.task("downloads-css", function(callback) {
var download_urls = [
"https://raw.githubusercontent.com/codemirror/CodeMirror/master/lib/codemirror.css",
"https://raw.githubusercontent.com/NextStepWebs/codemirror-spell-checker/master/src/css/spell-checker.css"];
download(download_urls)
.pipe(gulp.dest("src/css/"));
// Wait to make sure they've been downloaded
setTimeout(function() {
callback();
}, 5000);
});
gulp.task("scripts", ["downloads-codemirror", "downloads-js", "downloads-css"], function() {
var js_files = [
'./src/js/codemirror/codemirror.js',
'./src/js/codemirror/continuelist.js',
'./src/js/codemirror/fullscreen.js',
'./src/js/codemirror/markdown.js',
'./src/js/codemirror/overlay.js',
'./src/js/codemirror/gfm.js',
'./src/js/codemirror/xml.js',
'./src/js/typo.js',
'./src/js/spell-checker.js',
'./src/js/marked.js',
'./src/js/simplemde.js'];
"./src/js/codemirror/codemirror.js",
"./src/js/codemirror/continuelist.js",
"./src/js/codemirror/tablist.js",
"./src/js/codemirror/fullscreen.js",
"./src/js/codemirror/markdown.js",
"./src/js/codemirror/overlay.js",
"./src/js/codemirror/gfm.js",
"./src/js/codemirror/xml.js",
"./src/js/typo.js",
"./src/js/spell-checker.js",
"./src/js/marked.js",
"./src/js/simplemde.js"];
return gulp.src(js_files)
.pipe(header(banner, {pkg: pkg}))
.pipe(concat('simplemde.min.js'))
.pipe(gulp.dest('dist'))
.pipe(concat("simplemde.min.js"))
.pipe(gulp.dest("dist"))
.pipe(uglify())
.pipe(header(banner, {pkg: pkg}))
.pipe(gulp.dest('dist'));
.pipe(gulp.dest("dist"));
});
gulp.task('styles', function() {
return gulp.src('./src/css/*.css')
.pipe(concat('simplemde.min.css'))
.pipe(gulp.dest('dist'))
gulp.task("styles", ["downloads-codemirror", "downloads-js", "downloads-css"], function() {
return gulp.src("./src/css/*.css")
.pipe(concat("simplemde.min.css"))
.pipe(gulp.dest("dist"))
.pipe(minifycss())
.pipe(header(banner, {pkg: pkg}))
.pipe(gulp.dest('dist'));
.pipe(gulp.dest("dist"));
});
gulp.task('prettify-js', function() {
gulp.src('./src/js/simplemde.js')
gulp.task("prettify-js", function() {
gulp.src("./src/js/simplemde.js")
.pipe(prettify({js: {braceStyle: "collapse", indentChar: "\t", indentSize: 1, maxPreserveNewlines: 3, spaceBeforeConditional: false}}))
.pipe(gulp.dest('./src/js'));
.pipe(gulp.dest("./src/js"));
});
gulp.task('prettify-css', function() {
gulp.src('./src/css/simplemde.css')
gulp.task("prettify-css", function() {
gulp.src("./src/css/simplemde.css")
.pipe(prettify({css: {indentChar: "\t", indentSize: 1}}))
.pipe(gulp.dest('./src/css'));
.pipe(gulp.dest("./src/css"));
});
gulp.task('default', ['scripts', 'styles', 'prettify-js', 'prettify-css']);
gulp.task("default", ["downloads-codemirror", "downloads-js", "downloads-css", "scripts", "styles", "prettify-js", "prettify-css"]);

@ -1,29 +1,36 @@
{
"name": "simplemde",
"version": "1.7.0",
"description": "A simple, beautiful, and embeddable JavaScript markdown editor. Features autosaving and spell checking.",
"keywords": ["embeddable", "markdown", "editor", "javascript", "wysiwyg"],
"homepage": "https://github.com/NextStepWebs/simplemde-markdown-editor",
"main": "gulpfile.js",
"license": "MIT",
"company": "Next Step Webs, Inc.",
"author": {
"name": "Wes Cossick",
"url": "http://www.WesCossick.com"
},
"bugs": {
"url": "https://github.com/NextStepWebs/simplemde-markdown-editor/issues"
},
"devDependencies": {
"gulp": "*",
"gulp-minify-css": "*",
"gulp-uglify": "*",
"gulp-concat": "*",
"gulp-header": "*",
"gulp-jsbeautifier": "*"
},
"repository": {
"type": "git",
"url": "https://github.com/NextStepWebs/simplemde-markdown-editor"
}
"name": "simplemde",
"version": "1.7.1",
"description": "A simple, beautiful, and embeddable JavaScript markdown editor. Features autosaving and spell checking.",
"keywords": [
"embeddable",
"markdown",
"editor",
"javascript",
"wysiwyg"
],
"homepage": "https://github.com/NextStepWebs/simplemde-markdown-editor",
"main": "gulpfile.js",
"license": "MIT",
"company": "Next Step Webs, Inc.",
"author": {
"name": "Wes Cossick",
"url": "http://www.WesCossick.com"
},
"bugs": {
"url": "https://github.com/NextStepWebs/simplemde-markdown-editor/issues"
},
"devDependencies": {
"gulp": "*",
"gulp-minify-css": "*",
"gulp-uglify": "*",
"gulp-concat": "*",
"gulp-header": "*",
"gulp-jsbeautifier": "*",
"gulp-download": "*"
},
"repository": {
"type": "git",
"url": "https://github.com/NextStepWebs/simplemde-markdown-editor"
}
}

@ -323,7 +323,7 @@ div.CodeMirror-dragcursors {
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
visibility: hidden;
}
}
@ -331,4 +331,4 @@ div.CodeMirror-dragcursors {
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
span.CodeMirror-selectedtext { background: none; }

@ -66,11 +66,13 @@
.editor-toolbar.fullscreen {
width: 100%;
height: 40px;
height: 50px;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
padding-top: 10px;
padding-bottom: 10px;
box-sizing: border-box;
background: #fff;
border: 0;
position: fixed;
@ -178,6 +180,8 @@
.editor-toolbar.disabled-for-preview a:not(.fa-eye):not(.fa-arrows-alt):not(.fa-columns) {
pointer-events: none;
background: #fff;
border-color: transparent;
text-shadow: inherit;
}
@media only screen and (max-width: 700px) {

@ -1,3 +1,3 @@
.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment) {
background: rgba(255, 0, 0, .15);
}
background: rgba(255, 0, 0, .15);
}

File diff suppressed because it is too large Load Diff

@ -1,94 +1,51 @@
// NOTE: This has been modified from the original version to add additional commands
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))(\s*)/,
emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)[.)])(\s*)$/,
unorderedListRE = /[*+-]\s/;
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(),
replacements = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
var inQuote = eolState.quote !== 0;
var line = cm.getLine(pos.line),
match = listRE.exec(line);
if (!ranges[i].empty() || (!inList && !inQuote) || !match) {
cm.execCommand("newlineAndIndent");
return;
}
if (emptyListRE.test(line)) {
cm.replaceRange("", {
line: pos.line,
ch: 0
}, {
line: pos.line,
ch: pos.ch + 1
});
replacements[i] = "\n";
} else {
var indent = match[1],
after = match[5];
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0 ? match[2] : (parseInt(match[3], 10) + 1) + match[4];
replacements[i] = "\n" + indent + bullet + after;
}
}
cm.replaceSelections(replacements);
};
CodeMirror.commands.shiftTabAndIndentContinueMarkdownList = function(cm) {
var ranges = cm.listSelections();
var pos = ranges[0].head;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
if (inList) {
cm.execCommand('indentLess');
return;
}
if(cm.options.indentWithTabs){
cm.execCommand('insertTab');
}
else{
var spaces = Array(cm.options.tabSize + 1).join(" ");
cm.replaceSelection(spaces);
}
};
CodeMirror.commands.tabAndIndentContinueMarkdownList = function(cm) {
var ranges = cm.listSelections();
var pos = ranges[0].head;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
if (inList) {
cm.execCommand('indentMore');
return;
}
if(cm.options.indentWithTabs){
cm.execCommand('insertTab');
}
else{
var spaces = Array(cm.options.tabSize + 1).join(" ");
cm.replaceSelection(spaces);
}
};
});
"use strict";
var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))(\s*)/,
emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)[.)])(\s*)$/,
unorderedListRE = /[*+-]\s/;
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
var inQuote = eolState.quote !== 0;
var line = cm.getLine(pos.line), match = listRE.exec(line);
if (!ranges[i].empty() || (!inList && !inQuote) || !match) {
cm.execCommand("newlineAndIndent");
return;
}
if (emptyListRE.test(line)) {
cm.replaceRange("", {
line: pos.line, ch: 0
}, {
line: pos.line, ch: pos.ch + 1
});
replacements[i] = "\n";
} else {
var indent = match[1], after = match[5];
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
? match[2]
: (parseInt(match[3], 10) + 1) + match[4];
replacements[i] = "\n" + indent + bullet + after;
}
}
cm.replaceSelections(replacements);
};
});

@ -3,39 +3,39 @@
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {
if (old == CodeMirror.Init) old = false;
if (!old == !val) return;
if (val) setFullscreen(cm);
else setNormal(cm);
if (old == CodeMirror.Init) old = false;
if (!old == !val) return;
if (val) setFullscreen(cm);
else setNormal(cm);
});
function setFullscreen(cm) {
var wrap = cm.getWrapperElement();
cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
width: wrap.style.width, height: wrap.style.height};
wrap.style.width = "";
wrap.style.height = "auto";
wrap.className += " CodeMirror-fullscreen";
document.documentElement.style.overflow = "hidden";
cm.refresh();
var wrap = cm.getWrapperElement();
cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
width: wrap.style.width, height: wrap.style.height};
wrap.style.width = "";
wrap.style.height = "auto";
wrap.className += " CodeMirror-fullscreen";
document.documentElement.style.overflow = "hidden";
cm.refresh();
}
function setNormal(cm) {
var wrap = cm.getWrapperElement();
wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
document.documentElement.style.overflow = "";
var info = cm.state.fullScreenRestore;
wrap.style.width = info.width; wrap.style.height = info.height;
window.scrollTo(info.scrollLeft, info.scrollTop);
cm.refresh();
var wrap = cm.getWrapperElement();
wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
document.documentElement.style.overflow = "";
var info = cm.state.fullScreenRestore;
wrap.style.width = info.width; wrap.style.height = info.height;
window.scrollTo(info.scrollLeft, info.scrollTop);
cm.refresh();
}
});
});

@ -1,113 +1,133 @@
// NOTE: This has been modified from the original version to remove linking GitHub-only references, like references to issues using #X.
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);
else // Plain browser env
mod(CodeMirror);
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
"use strict";
CodeMirror.defineMode("gfm", function(config, modeConfig) {
var codeDepth = 0;
var urlRE = /^((?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris\.beep|iris\.xpc|iris\.xpcs|iris\.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap\.beep|soap\.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc\.beep|xmlrpc\.beeps|xmpp|z39\.50r|z39\.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i
function blankLine(state) {
state.code = false;
return null;
}
var gfmOverlay = {
startState: function() {
return {
code: false,
codeBlock: false,
ateSpace: false
};
},
copyState: function(s) {
return {
code: s.code,
codeBlock: s.codeBlock,
ateSpace: s.ateSpace
};
},
token: function(stream, state) {
state.combineTokens = null;
CodeMirror.defineMode("gfm", function(config, modeConfig) {
// Should GitHub spice be added (like linking #Num, SHA, etc.)
if (modeConfig.gitHubSpice === undefined)
modeConfig.gitHubSpice = true;
// Hack to prevent formatting override inside code blocks (block and inline)
if (state.codeBlock) {
if (stream.match(/^```/)) {
state.codeBlock = false;
return null;
}
stream.skipToEnd();
return null;
}
if (stream.sol()) {
state.code = false;
}
if (stream.sol() && stream.match(/^```/)) {
stream.skipToEnd();
state.codeBlock = true;
return null;
}
// If this block is changed, it may need to be updated in Markdown mode
if (stream.peek() === '`') {
stream.next();
var before = stream.pos;
stream.eatWhile('`');
var difference = 1 + stream.pos - before;
if (!state.code) {
codeDepth = difference;
state.code = true;
} else {
if (difference === codeDepth) { // Must be exact
state.code = false;
}
}
return null;
} else if (state.code) {
stream.next();
return null;
}
// Check if space. If so, links can be formatted later on
if (stream.eatSpace()) {
state.ateSpace = true;
return null;
}
if (stream.sol() || state.ateSpace) {
state.ateSpace = false;
}
if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i) &&
stream.string.slice(stream.start - 2, stream.start) != "](") {
// URLs
// Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
// And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
state.combineTokens = true;
return "link";
}
stream.next();
return null;
},
blankLine: blankLine
};
var codeDepth = 0;
function blankLine(state) {
state.code = false;
return null;
}
var gfmOverlay = {
startState: function() {
return {
code: false,
codeBlock: false,
ateSpace: false
};
},
copyState: function(s) {
return {
code: s.code,
codeBlock: s.codeBlock,
ateSpace: s.ateSpace
};
},
token: function(stream, state) {
state.combineTokens = null;
var markdownConfig = {
underscoresBreakWords: false,
taskLists: true,
fencedCodeBlocks: true,
strikethrough: true
};
for (var attr in modeConfig) {
markdownConfig[attr] = modeConfig[attr];
// Hack to prevent formatting override inside code blocks (block and inline)
if (state.codeBlock) {
if (stream.match(/^```/)) {
state.codeBlock = false;
return null;
}
markdownConfig.name = "markdown";
return CodeMirror.overlayMode(CodeMirror.getMode(config, markdownConfig), gfmOverlay);
stream.skipToEnd();
return null;
}
if (stream.sol()) {
state.code = false;
}
if (stream.sol() && stream.match(/^```/)) {
stream.skipToEnd();
state.codeBlock = true;
return null;
}
// If this block is changed, it may need to be updated in Markdown mode
if (stream.peek() === '`') {
stream.next();
var before = stream.pos;
stream.eatWhile('`');
var difference = 1 + stream.pos - before;
if (!state.code) {
codeDepth = difference;
state.code = true;
} else {
if (difference === codeDepth) { // Must be exact
state.code = false;
}
}
return null;
} else if (state.code) {
stream.next();
return null;
}
// Check if space. If so, links can be formatted later on
if (stream.eatSpace()) {
state.ateSpace = true;
return null;
}
if (stream.sol() || state.ateSpace) {
state.ateSpace = false;
if (modeConfig.gitHubSpice) {
if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
// User/Project@SHA
// User@SHA
// SHA
state.combineTokens = true;
return "link";
} else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
// User/Project#Num
// User#Num
// #Num
state.combineTokens = true;
return "link";
}
}
}
if (stream.match(urlRE) &&
stream.string.slice(stream.start - 2, stream.start) != "](") {
// URLs
// Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
// And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
// And then limited url schemes to the CommonMark list, so foo:bar isn't matched as a URL
state.combineTokens = true;
return "link";
}
stream.next();
return null;
},
blankLine: blankLine
};
var markdownConfig = {
underscoresBreakWords: false,
taskLists: true,
fencedCodeBlocks: true,
strikethrough: true
};
for (var attr in modeConfig) {
markdownConfig[attr] = modeConfig[attr];
}
markdownConfig.name = "markdown";
return CodeMirror.overlayMode(CodeMirror.getMode(config, markdownConfig), gfmOverlay);
}, "markdown");
}, "markdown");
CodeMirror.defineMIME("text/x-gfm", "gfm");
CodeMirror.defineMIME("text/x-gfm", "gfm");
});

File diff suppressed because it is too large Load Diff

@ -12,74 +12,74 @@
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.overlayMode = function(base, overlay, combine) {
return {
startState: function() {
return {
base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null,
streamSeen: null
};
},
copyState: function(state) {
return {
base: CodeMirror.copyState(base, state.base),
overlay: CodeMirror.copyState(overlay, state.overlay),
basePos: state.basePos, baseCur: null,
overlayPos: state.overlayPos, overlayCur: null
};
},
startState: function() {
return {
base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null,
streamSeen: null
};
},
copyState: function(state) {
return {
base: CodeMirror.copyState(base, state.base),
overlay: CodeMirror.copyState(overlay, state.overlay),
basePos: state.basePos, baseCur: null,
overlayPos: state.overlayPos, overlayCur: null
};
},
token: function(stream, state) {
if (stream != state.streamSeen ||
Math.min(state.basePos, state.overlayPos) < stream.start) {
state.streamSeen = stream;
state.basePos = state.overlayPos = stream.start;
}
token: function(stream, state) {
if (stream != state.streamSeen ||
Math.min(state.basePos, state.overlayPos) < stream.start) {
state.streamSeen = stream;
state.basePos = state.overlayPos = stream.start;
}
if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos;
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start;
state.overlayCur = overlay.token(stream, state.overlay);
state.overlayPos = stream.pos;
}
stream.pos = Math.min(state.basePos, state.overlayPos);
if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos;
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start;
state.overlayCur = overlay.token(stream, state.overlay);
state.overlayPos = stream.pos;
}
stream.pos = Math.min(state.basePos, state.overlayPos);
// state.overlay.combineTokens always takes precedence over combine,
// unless set to null
if (state.overlayCur == null) return state.baseCur;
else if (state.baseCur != null &&
state.overlay.combineTokens ||
combine && state.overlay.combineTokens == null)
return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
// state.overlay.combineTokens always takes precedence over combine,
// unless set to null
if (state.overlayCur == null) return state.baseCur;
else if (state.baseCur != null &&
state.overlay.combineTokens ||
combine && state.overlay.combineTokens == null)
return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars,
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars,
innerMode: function(state) { return {state: state.base, mode: base}; },
innerMode: function(state) { return {state: state.base, mode: base}; },
blankLine: function(state) {
if (base.blankLine) base.blankLine(state.base);
if (overlay.blankLine) overlay.blankLine(state.overlay);
}
blankLine: function(state) {
if (base.blankLine) base.blankLine(state.base);
if (overlay.blankLine) overlay.blankLine(state.overlay);
}
};
};
});
});

@ -0,0 +1,53 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.commands.tabAndIndentMarkdownList = function(cm) {
var ranges = cm.listSelections();
var pos = ranges[0].head;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
if (inList) {
cm.execCommand('indentMore');
return;
}
if(cm.options.indentWithTabs){
cm.execCommand('insertTab');
}
else{
var spaces = Array(cm.options.tabSize + 1).join(" ");
cm.replaceSelection(spaces);
}
};
CodeMirror.commands.shiftTabAndUnindentMarkdownList = function(cm) {
var ranges = cm.listSelections();
var pos = ranges[0].head;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
if (inList) {
cm.execCommand('indentLess');
return;
}
if(cm.options.indentWithTabs){
cm.execCommand('insertTab');
}
else{
var spaces = Array(cm.options.tabSize + 1).join(" ");
cm.replaceSelection(spaces);
}
};
});

@ -3,11 +3,11 @@
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
@ -18,45 +18,45 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true, 'menuitem': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: true,
caseFold: true
} : {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
caseFold: false
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false,
caseFold: false
};
var alignCDATA = parserConfig.alignCDATA;
@ -64,316 +64,316 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
var type, setStyle;
function inText(stream, state) {
function chain(parser) {
state.tokenize = parser;
return parser(stream, state);
}
function chain(parser) {
state.tokenize = parser;
return parser(stream, state);
}
var ch = stream.next();
if (ch == "<") {
if (stream.eat("!")) {
if (stream.eat("[")) {
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
else return null;
} else if (stream.match("--")) {
return chain(inBlock("comment", "-->"));
} else if (stream.match("DOCTYPE", true, true)) {
stream.eatWhile(/[\w\._\-]/);
return chain(doctype(1));
} else {
return null;
}
} else if (stream.eat("?")) {
stream.eatWhile(/[\w\._\-]/);
state.tokenize = inBlock("meta", "?>");
return "meta";
} else {
type = stream.eat("/") ? "closeTag" : "openTag";
state.tokenize = inTag;
return "tag bracket";
}
} else if (ch == "&") {
var ok;
if (stream.eat("#")) {
if (stream.eat("x")) {
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
} else {
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
}
} else {
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
}
return ok ? "atom" : "error";
} else {
stream.eatWhile(/[^&<]/);
return null;
}
var ch = stream.next();
if (ch == "<") {
if (stream.eat("!")) {
if (stream.eat("[")) {
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
else return null;
} else if (stream.match("--")) {
return chain(inBlock("comment", "-->"));
} else if (stream.match("DOCTYPE", true, true)) {
stream.eatWhile(/[\w\._\-]/);
return chain(doctype(1));
} else {
return null;
}
} else if (stream.eat("?")) {
stream.eatWhile(/[\w\._\-]/);
state.tokenize = inBlock("meta", "?>");
return "meta";
} else {
type = stream.eat("/") ? "closeTag" : "openTag";
state.tokenize = inTag;
return "tag bracket";
}
} else if (ch == "&") {
var ok;
if (stream.eat("#")) {
if (stream.eat("x")) {
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
} else {
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
}
} else {
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
}
return ok ? "atom" : "error";
} else {
stream.eatWhile(/[^&<]/);
return null;
}
}
inText.isInText = true;
function inTag(stream, state) {
var ch = stream.next();
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
state.tokenize = inText;
type = ch == ">" ? "endTag" : "selfcloseTag";
return "tag bracket";
} else if (ch == "=") {
type = "equals";
return null;
} else if (ch == "<") {
state.tokenize = inText;
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
return "word";
}
var ch = stream.next();
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
state.tokenize = inText;
type = ch == ">" ? "endTag" : "selfcloseTag";
return "tag bracket";
} else if (ch == "=") {
type = "equals";
return null;
} else if (ch == "<") {
state.tokenize = inText;
state.state = baseState;
state.tagName = state.tagStart = null;
var next = state.tokenize(stream, state);
return next ? next + " tag error" : "tag error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
return "word";
}
}
function inAttribute(quote) {
var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
break;
}
}
return "string";
};
closure.isInAttribute = true;
return closure;
var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
break;
}
}
return "string";
};
closure.isInAttribute = true;
return closure;
}
function inBlock(style, terminator) {
return function(stream, state) {
while (!stream.eol()) {
if (stream.match(terminator)) {
state.tokenize = inText;
break;
}
stream.next();
}
return style;
};
return function(stream, state) {
while (!stream.eol()) {
if (stream.match(terminator)) {
state.tokenize = inText;
break;
}
stream.next();
}
return style;
};
}
function doctype(depth) {
return function(stream, state) {
var ch;
while ((ch = stream.next()) != null) {
if (ch == "<") {
state.tokenize = doctype(depth + 1);
return state.tokenize(stream, state);
} else if (ch == ">") {
if (depth == 1) {
state.tokenize = inText;
break;
} else {
state.tokenize = doctype(depth - 1);
return state.tokenize(stream, state);
}
}
}
return "meta";
};
return function(stream, state) {
var ch;
while ((ch = stream.next()) != null) {
if (ch == "<") {
state.tokenize = doctype(depth + 1);
return state.tokenize(stream, state);
} else if (ch == ">") {
if (depth == 1) {
state.tokenize = inText;
break;
} else {
state.tokenize = doctype(depth - 1);
return state.tokenize(stream, state);
}
}
}
return "meta";
};
}
function Context(state, tagName, startOfLine) {
this.prev = state.context;
this.tagName = tagName;
this.indent = state.indented;
this.startOfLine = startOfLine;
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
this.prev = state.context;
this.tagName = tagName;
this.indent = state.indented;
this.startOfLine = startOfLine;
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
this.noIndent = true;
}
function popContext(state) {
if (state.context) state.context = state.context.prev;
if (state.context) state.context = state.context.prev;
}
function maybePopContext(state, nextTagName) {
var parentTagName;
while (true) {
if (!state.context) {
return;
}
parentTagName = state.context.tagName;
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext(state);
}
var parentTagName;
while (true) {
if (!state.context) {
return;
}
parentTagName = state.context.tagName;
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext(state);
}
}
function baseState(type, stream, state) {
if (type == "openTag") {
state.tagStart = stream.column();
return tagNameState;
} else if (type == "closeTag") {
return closeTagNameState;
} else {
return baseState;
}
if (type == "openTag") {
state.tagStart = stream.column();
return tagNameState;
} else if (type == "closeTag") {
return closeTagNameState;
} else {
return baseState;
}
}
function tagNameState(type, stream, state) {
if (type == "word") {
state.tagName = stream.current();
setStyle = "tag";
return attrState;
} else {
setStyle = "error";
return tagNameState;
}
if (type == "word") {
state.tagName = stream.current();
setStyle = "tag";
return attrState;
} else {
setStyle = "error";
return tagNameState;
}
}
function closeTagNameState(type, stream, state) {
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
popContext(state);
if (state.context && state.context.tagName == tagName) {
setStyle = "tag";
return closeState;
} else {
setStyle = "tag error";
return closeStateErr;
}
} else {
setStyle = "error";
return closeStateErr;
}
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
popContext(state);
if (state.context && state.context.tagName == tagName) {
setStyle = "tag";
return closeState;
} else {
setStyle = "tag error";
return closeStateErr;
}
} else {
setStyle = "error";
return closeStateErr;
}
}
function closeState(type, _stream, state) {
if (type != "endTag") {
setStyle = "error";
return closeState;
}
popContext(state);
return baseState;
if (type != "endTag") {
setStyle = "error";
return closeState;
}
popContext(state);
return baseState;
}
function closeStateErr(type, stream, state) {
setStyle = "error";
return closeState(type, stream, state);
setStyle = "error";
return closeState(type, stream, state);
}
function attrState(type, _stream, state) {
if (type == "word") {
setStyle = "attribute";
return attrEqState;
} else if (type == "endTag" || type == "selfcloseTag") {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
state.context = new Context(state, tagName, tagStart == state.indented);
}
return baseState;
}
setStyle = "error";
return attrState;
if (type == "word") {
setStyle = "attribute";
return attrEqState;
} else if (type == "endTag" || type == "selfcloseTag") {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
state.context = new Context(state, tagName, tagStart == state.indented);
}
return baseState;
}
setStyle = "error";
return attrState;
}
function attrEqState(type, stream, state) {
if (type == "equals") return attrValueState;
if (!Kludges.allowMissing) setStyle = "error";
return attrState(type, stream, state);
if (type == "equals") return attrValueState;
if (!Kludges.allowMissing) setStyle = "error";
return attrState(type, stream, state);
}
function attrValueState(type, stream, state) {
if (type == "string") return attrContinuedState;
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return attrState(type, stream, state);
if (type == "string") return attrContinuedState;
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
setStyle = "error";
return attrState(type, stream, state);
}
function attrContinuedState(type, stream, state) {
if (type == "string") return attrContinuedState;
return attrState(type, stream, state);
if (type == "string") return attrContinuedState;
return attrState(type, stream, state);
}
return {
startState: function() {
return {tokenize: inText,
state: baseState,
indented: 0,
tagName: null, tagStart: null,
context: null};
},
startState: function() {
return {tokenize: inText,
state: baseState,
indented: 0,
tagName: null, tagStart: null,
context: null};
},
token: function(stream, state) {
if (!state.tagName && stream.sol())
state.indented = stream.indentation();
token: function(stream, state) {
if (!state.tagName && stream.sol())
state.indented = stream.indentation();
if (stream.eatSpace()) return null;
type = null;
var style = state.tokenize(stream, state);
if ((style || type) && style != "comment") {
setStyle = null;
state.state = state.state(type || style, stream, state);
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
}
return style;
},
if (stream.eatSpace()) return null;
type = null;
var style = state.tokenize(stream, state);
if ((style || type) && style != "comment") {
setStyle = null;
state.state = state.state(type || style, stream, state);
if (setStyle)
style = setStyle == "error" ? style + " error" : setStyle;
}
return style;
},
indent: function(state, textAfter, fullLine) {
var context = state.context;
// Indent multi-line strings (e.g. css).
if (state.tokenize.isInAttribute) {
if (state.tagStart == state.indented)
return state.stringStartCol + 1;
else
return state.indented + indentUnit;
}
if (context && context.noIndent) return CodeMirror.Pass;
if (state.tokenize != inTag && state.tokenize != inText)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
if (multilineTagIndentPastTag)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * multilineTagIndentFactor;
}
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
if (tagAfter && tagAfter[1]) { // Closing tag spotted
while (context) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
context = context.prev;
} else {
break;
}
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
var grabbers = Kludges.contextGrabbers[context.tagName];
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
context = context.prev;
else
break;
}
}
while (context && !context.startOfLine)
context = context.prev;
if (context) return context.indent + indentUnit;
else return 0;
},
indent: function(state, textAfter, fullLine) {
var context = state.context;
// Indent multi-line strings (e.g. css).
if (state.tokenize.isInAttribute) {
if (state.tagStart == state.indented)
return state.stringStartCol + 1;
else
return state.indented + indentUnit;
}
if (context && context.noIndent) return CodeMirror.Pass;
if (state.tokenize != inTag && state.tokenize != inText)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
// Indent the starts of attribute names.
if (state.tagName) {
if (multilineTagIndentPastTag)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * multilineTagIndentFactor;
}
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
if (tagAfter && tagAfter[1]) { // Closing tag spotted
while (context) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
context = context.prev;
} else {
break;
}
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
var grabbers = Kludges.contextGrabbers[context.tagName];
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
context = context.prev;
else
break;
}
}
while (context && !context.startOfLine)
context = context.prev;
if (context) return context.indent + indentUnit;
else return 0;
},
electricInput: /<\/[\s\w:]+>$/,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
electricInput: /<\/[\s\w:]+>$/,
blockCommentStart: "<!--",
blockCommentEnd: "-->",
configuration: parserConfig.htmlMode ? "html" : "xml",
helperType: parserConfig.htmlMode ? "html" : "xml"
configuration: parserConfig.htmlMode ? "html" : "xml",
helperType: parserConfig.htmlMode ? "html" : "xml"
};
});
@ -382,4 +382,4 @@ CodeMirror.defineMIME("application/xml", "xml");
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
});
});

File diff suppressed because it is too large Load Diff

@ -88,6 +88,8 @@ function getState(cm, pos) {
ret.quote = true;
} else if(data === 'strikethrough') {
ret.strikethrough = true;
} else if(data === 'comment') {
ret.code = true;
}
}
return ret;
@ -331,12 +333,11 @@ function toggleSideBySide(editor) {
}
// Start preview with the current text
var parse = editor.constructor.markdown;
preview.innerHTML = parse(cm.getValue());
preview.innerHTML = editor.options.previewRender(editor.value(), preview);
// Updates preview
cm.on('update', function() {
preview.innerHTML = parse(cm.getValue());
preview.innerHTML = editor.options.previewRender(editor.value(), preview);
});
}
@ -349,9 +350,8 @@ function togglePreview(editor) {
var wrapper = cm.getWrapperElement();
var toolbar_div = wrapper.previousSibling;
var toolbar = editor.toolbarElements.preview;
var parse = editor.constructor.markdown;
var preview = wrapper.lastChild;
if(!/editor-preview/.test(preview.className)) {
if(!preview || !/editor-preview/.test(preview.className)) {
preview = document.createElement('div');
preview.className = 'editor-preview';
wrapper.appendChild(preview);
@ -373,8 +373,7 @@ function togglePreview(editor) {
toolbar.className += ' active';
toolbar_div.className += ' disabled-for-preview';
}
var text = cm.getValue();
preview.innerHTML = parse(text);
preview.innerHTML = editor.options.previewRender(editor.value(), preview);
// Turn off side by side if needed
var sidebyside = cm.getWrapperElement().nextSibling;
@ -402,7 +401,9 @@ function _replaceSelection(cm, active, start, end) {
cm.replaceSelection(start + text + end);
startPoint.ch += start.length;
endPoint.ch += start.length;
if(startPoint !== endPoint) {
endPoint.ch += start.length;
}
}
cm.setSelection(startPoint, endPoint);
cm.focus();
@ -555,10 +556,14 @@ function _toggleBlock(editor, type, start_chars, end_chars) {
if(type == "bold" || type == "strikethrough") {
startPoint.ch -= 2;
endPoint.ch -= 2;
if(startPoint !== endPoint) {
endPoint.ch -= 2;
}
} else if(type == "italic") {
startPoint.ch -= 1;
endPoint.ch -= 1;
if(startPoint !== endPoint) {
endPoint.ch -= 1;
}
}
} else {
text = cm.getSelection();
@ -730,6 +735,10 @@ var toolbar = ["bold", "italic", "heading", "|", "quote", "unordered-list", "ord
function SimpleMDE(options) {
options = options || {};
// Used later to refer to it's parent
options.parent = this;
// Find the textarea to use
if(options.element) {
this.element = options.element;
} else if(options.element === null) {
@ -738,6 +747,7 @@ function SimpleMDE(options) {
return;
}
// Handle toolbar and status bar
if(options.toolbar !== false)
options.toolbar = options.toolbar || SimpleMDE.toolbar;
@ -745,9 +755,21 @@ function SimpleMDE(options) {
options.status = ['autosave', 'lines', 'words', 'cursor'];
}
// Add default preview rendering function
if(!options.previewRender) {
options.previewRender = function(plainText) {
// Note: 'this' refers to the options object
return this.parent.markdown(plainText);
}
}
// Set default options for parsing config
options.parsingConfig = options.parsingConfig || {};
// Update this options
this.options = options;
// If user has passed an element, it should auto rendered
// Auto render
this.render();
// The codemirror component is only available after rendering
@ -766,10 +788,10 @@ SimpleMDE.toolbar = toolbar;
/**
* Default markdown render.
*/
SimpleMDE.markdown = function(text) {
SimpleMDE.prototype.markdown = function(text) {
if(window.marked) {
// Update options
if(this.options.singleLineBreaks !== false) {
if(this.options && this.options.singleLineBreaks !== false) {
marked.setOptions({
breaks: true
});
@ -807,8 +829,8 @@ SimpleMDE.prototype.render = function(el) {
}
keyMaps["Enter"] = "newlineAndIndentContinueMarkdownList";
keyMaps["Tab"] = "tabAndIndentContinueMarkdownList";
keyMaps["Shift-Tab"] = "shiftTabAndIndentContinueMarkdownList";
keyMaps["Tab"] = "tabAndIndentMarkdownList";
keyMaps["Shift-Tab"] = "shiftTabAndUnindentMarkdownList";
keyMaps["F11"] = function(cm) {
toggleFullScreen(self);
};
@ -816,21 +838,25 @@ SimpleMDE.prototype.render = function(el) {
toggleSideBySide(self);
};
keyMaps["Esc"] = function(cm) {
if(cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
if(cm.getOption("fullScreen")) toggleFullScreen(self);
};
var mode = "spell-checker";
var backdrop = "gfm";
if(options.spellChecker === false) {
mode = "gfm";
backdrop = undefined;
var mode, backdrop;
if(options.spellChecker !== false) {
mode = "spell-checker";
backdrop = options.parsingConfig;
backdrop.name = "gfm";
backdrop.gitHubSpice = false;
} else {
mode = options.parsingConfig;
mode.name = "gfm";
mode.gitHubSpice = false;
}
this.codemirror = CodeMirror.fromTextArea(el, {
mode: mode,
backdrop: backdrop,
theme: 'paper',
theme: "paper",
tabSize: (options.tabSize != undefined) ? options.tabSize : 2,
indentUnit: (options.tabSize != undefined) ? options.tabSize : 2,
indentWithTabs: (options.indentWithTabs === false) ? false : true,
@ -850,7 +876,7 @@ SimpleMDE.prototype.render = function(el) {
this.autosave();
}
this.createSidebyside();
this.createSideBySide();
this._rendered = this.element;
};
@ -905,12 +931,12 @@ SimpleMDE.prototype.autosave = function() {
}, this.options.autosave.delay || 10000);
};
SimpleMDE.prototype.createSidebyside = function() {
SimpleMDE.prototype.createSideBySide = function() {
var cm = this.codemirror;
var wrapper = cm.getWrapperElement();
var preview = wrapper.nextSibling;
if(!/editor-preview-side/.test(preview.className)) {
if(!preview || !/editor-preview-side/.test(preview.className)) {
preview = document.createElement('div');
preview.className = 'editor-preview-side';
wrapper.parentNode.insertBefore(preview, wrapper.nextSibling);

Loading…
Cancel
Save