Compare commits

...

73 commits

Author SHA1 Message Date
Wes Cossick 6abda7ab68 Merge pull request #361 from NextStepWebs/development
Fix broken dependency
2016-06-14 12:57:04 -05:00
Wes Cossick 1471a4e662 Merge branch 'master' into development 2016-06-14 12:50:07 -05:00
Wes Cossick 0d9f7d9012 Update code and version 2016-06-14 12:48:07 -05:00
Wes Cossick 2c35e6782f 1.11.2 2016-06-14 12:46:09 -05:00
Wes Cossick cb10536dd4 Update bower version 2016-06-14 12:46:03 -05:00
Wes Cossick 00e0f69d93 Merge pull request #356 from NextStepWebs/development
Republishing to NPM
2016-06-09 15:42:10 -05:00
Wes Cossick 98bc1e52a1 Update version 2016-06-09 15:26:41 -05:00
Wes Cossick 47b2667e86 1.11.1 2016-06-09 15:22:15 -05:00
Wes Cossick 316b8a58f8 Merge pull request #353 from NextStepWebs/development
Development
2016-06-07 22:54:06 -05:00
Wes Cossick 6676411766 Update version in comments 2016-06-07 22:46:55 -05:00
Wes Cossick 3653d4f81d 1.11.0 2016-06-07 22:46:32 -05:00
Wes Cossick 7dc2a8f7fe Revert "Revert this"
This reverts commit 021e705242.
2016-06-07 22:46:19 -05:00
Wes Cossick 021e705242 Revert this 2016-06-07 22:46:15 -05:00
Wes Cossick e74572ac4a Update version in bower 2016-06-07 22:46:11 -05:00
Wes Cossick 487ff36385 Rebuild project 2016-06-07 22:36:54 -05:00
Wes Cossick d963582f16 Fix line and word count on init (#299) 2016-06-07 21:53:23 -05:00
Wes Cossick 69bff3ed78 Fix CodeMirror bug with init text (#344) 2016-06-07 21:43:25 -05:00
Wes Cossick b4d4e89129 Fix selection bug when toggling between side-by-side (#309) 2016-06-07 21:40:40 -05:00
Wes Cossick c949cad2d8 Update URLs; prefer SSL 2016-06-07 21:33:34 -05:00
Wes Cossick c8f23a3aa9 Clean up build process, Use new CodeMirror Spell Checker 2016-06-07 21:28:01 -05:00
Wes Cossick dbb1c25843 Travis CI now tests against Node.js 6 2016-06-07 21:28:01 -05:00
Wes Cossick a30d8f6183 Fix #326 2016-06-07 21:28:01 -05:00
Wes Cossick 51ef0cd81d Merge pull request #351 from amka/patch-2
Add support for count Cyrillic words
2016-06-07 21:18:55 -05:00
Wes Cossick 97154e2bfc Merge pull request #345 from jbutz/development
Prevent onclick event from bubbling
2016-06-07 21:07:01 -05:00
Andrey M bd33cd3c2b Add support for count Cyrillic words
Add unicode range for Cyrillic characters
2016-06-07 03:39:01 +04:00
Jason Butz 7187fb26fb Adjust whitespace characters 2016-06-03 09:09:33 -04:00
Jason Butz f21cca3068 Prevent onclick event from bubbling 2016-06-03 09:07:15 -04:00
Wes Cossick b6b1f7c1ef Merge pull request #304 from bbemis017/readmeError
Readme error
2016-04-22 18:56:43 -05:00
Wes Cossick 0ce450a7a7 Merge pull request #301 from JHeiner/issue150
Fix issue #150: use correct paths for dependencies.
2016-04-22 18:52:01 -05:00
Benjamin Bemis d9d0cd50d5 Fixed Syntax Error in readme file 2016-04-22 19:38:20 -04:00
Jeremy Heiner 7b1e8deeaa Fix issue #150: use correct paths for dependencies.
https://nodejs.org/api/modules.html specifies what paths are
correct. One should never explicitly put "node_modules" in
dependency paths because npm is under no obligation to put things
where you told it to look for them. Issue #150 arises when
SimpleMDE is a dependency in some other project, so it and its
dependencies are peers under that project's "node_modules", and
there is no "./node_modules" within the SimpleMDE folder.

TL/DR: npm tells you where it puts dependencies, not vice versa.
2016-04-19 20:02:53 -04:00
Wes Cossick e72e51c94f Merge pull request #297 from prostoandrei/development
Fix #286
2016-04-09 21:19:59 -05:00
Wes Cossick 4ec9ab8be0 Tweak documentation for styleSelectedText 2016-04-09 21:18:03 -05:00
Wes Cossick 6ed8344248 Fix documentation for styleSelectedText 2016-04-09 21:17:07 -05:00
Wes Cossick 2f4e7e4d9b Merge pull request #289 from foreachlt/style-selected-text
Added mark-selection plugin
2016-04-09 21:16:09 -05:00
andrey.vaganov 318b4c175f Merge branch 'development' of https://github.com/prostoandrei/simplemde-markdown-editor into development
Conflicts:
	debug/simplemde.debug.js
	debug/simplemde.js
	dist/simplemde.min.js
	src/js/simplemde.js
2016-03-31 13:36:05 +03:00
andrey.vaganov fe1318dd39 fix issue #286 2016-03-31 13:34:12 +03:00
andrey.vaganov 4a8ce0bd12 fix issue #286 2016-03-31 12:14:39 +03:00
Kasparas Galdikas 490e57ded1 Added mark-selection plugin from CodeMirror with config option on simplemde 2016-03-25 15:56:44 +00:00
Wes Cossick 9eb0411d82 Merge pull request #284 from foreachlt/console
Removed console.log left overs
2016-03-25 09:58:32 -05:00
Kasparas Galdikas be3fbf15b5 Removed console.log left overs 2016-03-20 14:55:19 +00:00
Wes Cossick 6eae597a69 Merge pull request #277 from NextStepWebs/development
Allow destroying instance, Prompts, README changes, Fix bugs, More
2016-03-14 21:39:46 -05:00
Wes Cossick 507e8ce67d Merge branch 'master' into development 2016-03-14 21:34:58 -05:00
Wes Cossick 24ec612c44 Fix linting and update dependencies 2016-03-14 21:28:56 -05:00
Wes Cossick 747b3ef065 Rebuild project 2016-03-14 20:59:59 -05:00
Wes Cossick 26391efa26 Better localStorage detection 2016-03-14 20:59:16 -05:00
Wes Cossick d77d4b318b Update version 2016-02-25 15:08:38 -06:00
Wes Cossick 1def5aabc2 1.10.1 2016-02-25 15:08:38 -06:00
Wes Cossick 711af1b472 Merge pull request #264 from NextStepWebs/pr/256
Pull request #256 remove conflicts
2016-02-25 15:07:33 -06:00
Wes Cossick 75b6c82940 Make compatible and able to be merged 2016-02-25 15:00:52 -06:00
Wes Cossick 1a79eefadb Hide trailing separators respects hidden icons 2016-02-25 14:53:08 -06:00
Wes Cossick 6bda28300d Fix single line breaks bug 2016-02-25 14:48:05 -06:00
Wes Cossick 435b39f96d Update dependencies 2016-02-25 14:47:56 -06:00
Wes Cossick 787ed40fe6 Update URLs to use SimpleMDE.com 2016-02-25 14:17:41 -06:00
Curtis Badke ecff05833b Add forceSync to non-default options listing. 2016-02-12 11:17:43 -07:00
Curtis Badke 20f5b54a46 Fix naming and style based on feedback
* forceSynch -> forceSync
* change documentation description
2016-02-10 13:01:22 -07:00
Curtis Badke 0fb087ca38 Add forceSynch option which will autosave to textarea.
Since this is built on CodeMirror I opted to use CodeMirror's save
behaviour rather than pulling the value and stomping on the textarea's
innerHtml.

Fixes #193
2016-02-10 03:56:39 -07:00
Wes Cossick 71d979ad61 Use SSL URLs 2016-01-27 11:26:19 -06:00
Wes Cossick 56705bfd20 Tweak wording in README 2016-01-26 10:43:25 -06:00
Wes Cossick 8618543fab Merge pull request #242 from moczolaszlo/development
Optional prompt windows to Link and Image
2016-01-26 10:41:29 -06:00
Laszlo Moczo 5a53199586 Optional prompt windows to Link and Image 2016-01-26 10:39:27 +01:00
Laszlo Moczo eb568ddbde Merge remote-tracking branch 'NextStepWebs/development' into development 2016-01-26 10:22:09 +01:00
Wes Cossick 047c0ef2c7 Merge pull request #228 from brondsem/context_aware_code_block_button
Context aware code button
2016-01-25 20:31:09 -06:00
Dave Brondsema 0166b2b367 Update dist/simplemde.min.js 2016-01-25 17:48:22 -05:00
Dave Brondsema 2c09c829ee When selecting lines within a fenced block, check if selection reaches a fenced line 2016-01-25 17:47:58 -05:00
Dave Brondsema 5e204ae66e Update token state checking to work when spellcheck is on 2016-01-25 15:09:30 -05:00
Dave Brondsema bce5372947 Context aware code button to handle toggling on and off code blocks and inline code markup 2016-01-25 15:09:30 -05:00
Laszlo Moczo 26519235c6 Optional prompt windows to Link and Image
Optional prompt windows to Link and Image
2016-01-25 14:14:46 +01:00
Wes Cossick 99e4cba72e Merge pull request #239 from trwired/destroy-instance
Allow reverting back to the initial textarea (fixes #142)
2016-01-24 21:33:13 -06:00
trwired fd8e6a7825 Allow reverting back to the initial textarea (fixes #142) 2016-01-24 07:29:18 +01:00
Wes Cossick b6bee016c2 Merge pull request #238 from trwired/fix-196
Fix #196
2016-01-23 18:58:57 -06:00
trwired da5e309ffe fixes #196 2016-01-23 23:40:31 +01:00
Wes Cossick d1445222aa Remove "What's Changed" secion, Reword "How it works" 2016-01-22 23:39:45 -06:00
12 changed files with 8144 additions and 2775 deletions

View file

@ -1,5 +1,6 @@
language: node_js
node_js:
- '6'
- '5'
- '4'
- '0.12'

View file

@ -1,9 +1,9 @@
# SimpleMDE - Markdown Editor
A drop-in JavaScript textarea replacement for writing beautiful and understandable Markdown. The WYSIWYG-esque editor allows users who may be less experienced with Markdown to use familiar toolbar buttons and shortcuts. In addition, the syntax is rendered while editing to clearly show the expected result. Headings are larger, emphasized words are italicized, links are underlined, etc. SimpleMDE is one of the first editors to feature both built-in autosaving and spell checking.
[**Demo**](http://nextstepwebs.github.io/simplemde-markdown-editor)
[**Demo**](https://simplemde.com)
[![Preview](http://i.imgur.com/zqWfJwO.png)](http://nextstepwebs.github.io/simplemde-markdown-editor)
[![Preview](http://i.imgur.com/zqWfJwO.png)](https://simplemde.com)
## Why not a WYSIWYG editor or pure Markdown?
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.
@ -20,11 +20,11 @@ Via [bower](https://www.bower.io).
bower install simplemde --save
```
Via [jsDelivr](http://www.jsdelivr.com/#!simplemde). *Please note, jsDelivr may take a few days to update to the latest release.*
Via [jsDelivr](https://www.jsdelivr.com/#!simplemde). *Please note, jsDelivr may take a few days to update to the latest release.*
```HTML
<link rel="stylesheet" href="//cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
<script src="//cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
```
## Quick start
@ -75,8 +75,10 @@ simplemde.value("This text will appear in the editor");
- **uniqueId**: You must set a unique string identifier so that SimpleMDE can autosave. Something that separates this from other instances of SimpleMDE elsewhere on your website.
- **blockStyles**: Customize how certain buttons that style blocks of text behave.
- **bold** Can be set to `**` or `__`. Defaults to `**`.
- **code** Can be set to ```` ``` ```` or `~~~`. Defaults to ```` ``` ````.
- **italic** Can be set to `*` or `_`. Defaults to `*`.
- **element**: The DOM element for the textarea to use. Defaults to the first textarea on the page.
- **forceSync**: If set to `true`, force text changes made in SimpleMDE to be immediately stored in original textarea. Defaults to `false`.
- **hideIcons**: An array of icon names to hide. Can be used to hide specific icons shown by default without completely customizing the toolbar.
- **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.
@ -92,6 +94,7 @@ simplemde.value("This text will appear in the editor");
- **underscoresBreakWords**: If set to `true`, let underscores be a delimiter for separating words. Defaults to `false`.
- **placeholder**: Custom placeholder that should be displayed
- **previewRender**: Custom function for parsing the plaintext Markdown and returning HTML. Used when user previews.
- **promptURLs**: If set to `true`, a JS alert window appears asking for the link or image URL. Defaults to `false`.
- **renderingConfig**: Adjust settings for parsing the Markdown during previewing (not editing).
- **singleLineBreaks**: If set to `false`, disable parsing GFM single line breaks. Defaults to `true`.
- **codeSyntaxHighlighting**: If set to `true`, will highlight using [highlight.js](https://github.com/isagalaev/highlight.js). Defaults to `false`. To use this feature you must include highlight.js on your page. For example, include the script and the CSS files like:<br>`<script src="https://cdn.jsdelivr.net/highlight.js/latest/highlight.min.js"></script>`<br>`<link rel="stylesheet" href="https://cdn.jsdelivr.net/highlight.js/latest/styles/github.min.css">`
@ -100,6 +103,7 @@ simplemde.value("This text will appear in the editor");
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`.
- **status**: If set to `false`, hide the status bar. Defaults to the array of built-in status bar items.
- Optionally, you can set an array of status bar items to include, and in what order. You can even define your own custom status bar items.
- **styleSelectedText**: If set to `false`, remove the `CodeMirror-selectedtext` class from selected lines. Defaults to `true`.
- **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`.
@ -118,6 +122,7 @@ var simplemde = new SimpleMDE({
italic: "_"
},
element: document.getElementById("MyID"),
forceSync: true,
hideIcons: ["guide", "heading"],
indentWithTabs: false,
initialValue: "Hello world!",
@ -144,6 +149,7 @@ var simplemde = new SimpleMDE({
return "Loading...";
},
promptURLs: true,
renderingConfig: {
singleLineBreaks: false,
codeSyntaxHighlighting: true,
@ -165,6 +171,7 @@ var simplemde = new SimpleMDE({
el.innerHTML = ++this.keystrokes + " Keystrokes";
}
}], // Another optional usage, with a custom status bar item that counts keystrokes
styleSelectedText: false,
tabSize: 4,
toolbar: false,
toolbarTips: false,
@ -200,7 +207,7 @@ horizontal-rule | drawHorizontalRule | Insert Horizontal Line<br>fa fa-minus
preview | togglePreview | Toggle Preview<br>fa fa-eye no-disable
side-by-side | toggleSideBySide | Toggle Side by Side<br>fa fa-columns no-disable no-mobile
fullscreen | toggleFullScreen | Toggle Fullscreen<br>fa fa-arrows-alt no-disable no-mobile
guide | [This link](http://nextstepwebs.github.io/simplemde-markdown-editor/markdown-guide) | Markdown Guide<br>fa fa-question-circle
guide | [This link](https://simplemde.com/markdown-guide) | Markdown Guide<br>fa fa-question-circle
Customize the toolbar using the `toolbar` option like:
@ -220,7 +227,7 @@ var simplemde = new SimpleMDE({
},
{
name: "custom",
action: customFunction(editor){
action: function customFunction(editor){
// Add your own code
},
className: "fa fa-star",
@ -297,6 +304,16 @@ simplemde.codemirror.on("change", function(){
});
```
## Removing SimpleMDE from textarea
You can revert to the initial textarea by calling the `toTextArea` method. Note that this clears up the autosave (if enabled) associated with it. The textarea will retain any text from the destroyed SimpleMDE instance.
```JavaScript
var simplemde = new SimpleMDE();
...
simplemde.toTextArea();
simplemde = null;
```
## Useful methods
The following self-explanatory methods may be of use while developing with SimpleMDE.
@ -309,25 +326,6 @@ simplemde.clearAutosavedValue(); // no returned value
```
## How it works
SimpleMDE is an improvement of [lepture's Editor project](https://github.com/lepture/editor) and includes a great many number of changes. It is bundled with [CodeMirror](https://github.com/codemirror/codemirror) and depends on [Font Awesome](http://fortawesome.github.io/Font-Awesome/).
SimpleMDE began as an improvement of [lepture's Editor project](https://github.com/lepture/editor), but has now taken on an identity of its own. It is bundled with [CodeMirror](https://github.com/codemirror/codemirror) and depends on [Font Awesome](http://fontawesome.io).
CodeMirror is the backbone of the project and parses much of the Markdown syntax as it's being written. This allows us to add styles to the Markdown that's being written. Additionally, a toolbar and status bar have been added to the top and bottom, respectively. Previews are rendered by [Marked](https://github.com/chjj/marked) using GFM.
## What's changed?
As mentioned earlier, SimpleMDE is an improvement of [lepture's Editor project](https://github.com/lepture/editor). So you might be wondering, what's changed? Quite a bit actually. Here's some notable changes:
- Upgraded from CodeMirror 3 to CodeMirror 5
- Many changes to the style, appearance, and user friendliness
- Interface more closely resembles Bootstrap
- Now mobile friendly
- Option to autosave the text as you type
- Now spell checks what you write
- The text editor now automatically grows as you type more
- Fixed a large amount of bugs
- Switched to Font Awesome icons
- Improved preview rendering in many ways
- Improved as-you-type appearance of headers and code blocks
- Simplified the toolbar
- Many new options during instantiation
- New icons and tooltips
- Additional keyboard shortcuts

View file

@ -1,25 +1,23 @@
{
"name": "simplemde",
"version": "1.10.0",
"homepage": "https://github.com/NextStepWebs/simplemde-markdown-editor",
"authors": [
"Wes Cossick"
],
"description": "A simple, beautiful, and embeddable JavaScript Markdown editor.",
"main": ["dist/simplemde.min.js", "dist/simplemde.min.css"],
"moduleType": [
"globals"
],
"keywords": [
"embeddable",
"markdown",
"editor",
"javascript",
"wysiwyg"
],
"license": "MIT",
"ignore": [
"node_modules",
"bower_components"
]
"name": "simplemde",
"version": "1.11.2",
"homepage": "https://github.com/NextStepWebs/simplemde-markdown-editor",
"authors": [
"Wes Cossick <https://wescossick.com>"
],
"description": "A simple, beautiful, and embeddable JavaScript Markdown editor.",
"main": ["src/js/simplemde.js", "src/css/simplemde.css"],
"keywords": [
"embeddable",
"markdown",
"editor",
"javascript",
"wysiwyg"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components"
]
}

View file

@ -1,5 +1,5 @@
/**
* simplemde v1.10.0
* simplemde v1.11.2
* Copyright Next Step Webs, Inc.
* @link https://github.com/NextStepWebs/simplemde-markdown-editor
* @license MIT
@ -58,7 +58,7 @@
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0;
border: 0 !important;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
@ -171,7 +171,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
@ -197,12 +197,14 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
@ -250,6 +252,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: none;
font-variant-ligatures: none;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
@ -340,333 +344,333 @@ div.CodeMirror-dragcursors {
span.CodeMirror-selectedtext { background: none; }
.CodeMirror {
height: auto;
min-height: 300px;
border: 1px solid #ddd;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
font: inherit;
z-index: 1;
height: auto;
min-height: 300px;
border: 1px solid #ddd;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
font: inherit;
z-index: 1;
}
.CodeMirror-scroll {
min-height: 300px
min-height: 300px
}
.CodeMirror-fullscreen {
background: #fff;
position: fixed !important;
top: 50px;
left: 0;
right: 0;
bottom: 0;
height: auto;
z-index: 9;
background: #fff;
position: fixed !important;
top: 50px;
left: 0;
right: 0;
bottom: 0;
height: auto;
z-index: 9;
}
.CodeMirror-sided {
width: 50% !important;
width: 50% !important;
}
.editor-toolbar {
position: relative;
opacity: .6;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
padding: 0 10px;
border-top: 1px solid #bbb;
border-left: 1px solid #bbb;
border-right: 1px solid #bbb;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
position: relative;
opacity: .6;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
padding: 0 10px;
border-top: 1px solid #bbb;
border-left: 1px solid #bbb;
border-right: 1px solid #bbb;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.editor-toolbar:after,
.editor-toolbar:before {
display: block;
content: ' ';
height: 1px;
display: block;
content: ' ';
height: 1px;
}
.editor-toolbar:before {
margin-bottom: 8px
margin-bottom: 8px
}
.editor-toolbar:after {
margin-top: 8px
margin-top: 8px
}
.editor-toolbar:hover,
.editor-wrapper input.title:focus,
.editor-wrapper input.title:hover {
opacity: .8
opacity: .8
}
.editor-toolbar.fullscreen {
width: 100%;
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;
top: 0;
left: 0;
opacity: 1;
z-index: 9;
width: 100%;
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;
top: 0;
left: 0;
opacity: 1;
z-index: 9;
}
.editor-toolbar.fullscreen::before {
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 0;
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 0;
}
.editor-toolbar.fullscreen::after {
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 1)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
position: fixed;
top: 0;
right: 0;
margin: 0;
padding: 0;
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 1)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
position: fixed;
top: 0;
right: 0;
margin: 0;
padding: 0;
}
.editor-toolbar a {
display: inline-block;
text-align: center;
text-decoration: none!important;
color: #2c3e50!important;
width: 30px;
height: 30px;
margin: 0;
border: 1px solid transparent;
border-radius: 3px;
cursor: pointer;
display: inline-block;
text-align: center;
text-decoration: none!important;
color: #2c3e50!important;
width: 30px;
height: 30px;
margin: 0;
border: 1px solid transparent;
border-radius: 3px;
cursor: pointer;
}
.editor-toolbar a.active,
.editor-toolbar a:hover {
background: #fcfcfc;
border-color: #95a5a6;
background: #fcfcfc;
border-color: #95a5a6;
}
.editor-toolbar a:before {
line-height: 30px
line-height: 30px
}
.editor-toolbar i.separator {
display: inline-block;
width: 0;
border-left: 1px solid #d9d9d9;
border-right: 1px solid #fff;
color: transparent;
text-indent: -10px;
margin: 0 6px;
display: inline-block;
width: 0;
border-left: 1px solid #d9d9d9;
border-right: 1px solid #fff;
color: transparent;
text-indent: -10px;
margin: 0 6px;
}
.editor-toolbar a.fa-header-x:after {
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 65%;
vertical-align: text-bottom;
position: relative;
top: 2px;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 65%;
vertical-align: text-bottom;
position: relative;
top: 2px;
}
.editor-toolbar a.fa-header-1:after {
content: "1";
content: "1";
}
.editor-toolbar a.fa-header-2:after {
content: "2";
content: "2";
}
.editor-toolbar a.fa-header-3:after {
content: "3";
content: "3";
}
.editor-toolbar a.fa-header-bigger:after {
content: "▲";
content: "▲";
}
.editor-toolbar a.fa-header-smaller:after {
content: "▼";
content: "▼";
}
.editor-toolbar.disabled-for-preview a:not(.no-disable) {
pointer-events: none;
background: #fff;
border-color: transparent;
text-shadow: inherit;
pointer-events: none;
background: #fff;
border-color: transparent;
text-shadow: inherit;
}
@media only screen and (max-width: 700px) {
.editor-toolbar a.no-mobile {
display: none;
}
.editor-toolbar a.no-mobile {
display: none;
}
}
.editor-statusbar {
padding: 8px 10px;
font-size: 12px;
color: #959694;
text-align: right;
padding: 8px 10px;
font-size: 12px;
color: #959694;
text-align: right;
}
.editor-statusbar span {
display: inline-block;
min-width: 4em;
margin-left: 1em;
display: inline-block;
min-width: 4em;
margin-left: 1em;
}
.editor-statusbar .lines:before {
content: 'lines: '
content: 'lines: '
}
.editor-statusbar .words:before {
content: 'words: '
content: 'words: '
}
.editor-statusbar .characters:before {
content: 'characters: '
content: 'characters: '
}
.editor-preview {
padding: 10px;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fafafa;
z-index: 7;
overflow: auto;
display: none;
box-sizing: border-box;
padding: 10px;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fafafa;
z-index: 7;
overflow: auto;
display: none;
box-sizing: border-box;
}
.editor-preview-side {
padding: 10px;
position: fixed;
bottom: 0;
width: 50%;
top: 50px;
right: 0;
background: #fafafa;
z-index: 9;
overflow: auto;
display: none;
box-sizing: border-box;
border: 1px solid #ddd;
padding: 10px;
position: fixed;
bottom: 0;
width: 50%;
top: 50px;
right: 0;
background: #fafafa;
z-index: 9;
overflow: auto;
display: none;
box-sizing: border-box;
border: 1px solid #ddd;
}
.editor-preview-active-side {
display: block
display: block
}
.editor-preview-active {
display: block
display: block
}
.editor-preview>p,
.editor-preview-side>p {
margin-top: 0
margin-top: 0
}
.editor-preview pre,
.editor-preview-side pre {
background: #eee;
margin-bottom: 10px;
background: #eee;
margin-bottom: 10px;
}
.editor-preview table td,
.editor-preview table th,
.editor-preview-side table td,
.editor-preview-side table th {
border: 1px solid #ddd;
padding: 5px;
border: 1px solid #ddd;
padding: 5px;
}
.CodeMirror .CodeMirror-code .cm-tag {
color: #63a35c;
color: #63a35c;
}
.CodeMirror .CodeMirror-code .cm-attribute {
color: #795da3;
color: #795da3;
}
.CodeMirror .CodeMirror-code .cm-string {
color: #183691;
color: #183691;
}
.CodeMirror .CodeMirror-selected {
background: #d9d9d9;
background: #d9d9d9;
}
.CodeMirror .CodeMirror-code .cm-header-1 {
font-size: 200%;
line-height: 200%;
font-size: 200%;
line-height: 200%;
}
.CodeMirror .CodeMirror-code .cm-header-2 {
font-size: 160%;
line-height: 160%;
font-size: 160%;
line-height: 160%;
}
.CodeMirror .CodeMirror-code .cm-header-3 {
font-size: 125%;
line-height: 125%;
font-size: 125%;
line-height: 125%;
}
.CodeMirror .CodeMirror-code .cm-header-4 {
font-size: 110%;
line-height: 110%;
font-size: 110%;
line-height: 110%;
}
.CodeMirror .CodeMirror-code .cm-comment {
background: rgba(0, 0, 0, .05);
border-radius: 2px;
background: rgba(0, 0, 0, .05);
border-radius: 2px;
}
.CodeMirror .CodeMirror-code .cm-link {
color: #7f8c8d;
color: #7f8c8d;
}
.CodeMirror .CodeMirror-code .cm-url {
color: #aab2b3;
color: #aab2b3;
}
.CodeMirror .CodeMirror-code .cm-strikethrough {
text-decoration: line-through;
text-decoration: line-through;
}
.CodeMirror .CodeMirror-placeholder {
opacity: .5;
opacity: .5;
}
.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word) {
background: rgba(255, 0, 0, .15);
background: rgba(255, 0, 0, .15);
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

19
dist/simplemde.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,7 @@
"use strict";
var gulp = require("gulp"),
minifycss = require("gulp-minify-css"),
minifycss = require("gulp-clean-css"),
uglify = require("gulp-uglify"),
concat = require("gulp-concat"),
header = require("gulp-header"),
@ -8,11 +9,10 @@ var gulp = require("gulp"),
pkg = require("./package.json"),
debug = require("gulp-debug"),
eslint = require("gulp-eslint"),
prettify = require("gulp-jsbeautifier");
var browserify = require("browserify");
var source = require("vinyl-source-stream");
var rename = require("gulp-rename");
prettify = require("gulp-jsbeautifier"),
browserify = require("browserify"),
source = require("vinyl-source-stream"),
rename = require("gulp-rename");
var banner = ["/**",
" * <%= pkg.name %> v<%= pkg.version %>",
@ -24,7 +24,7 @@ var banner = ["/**",
gulp.task("prettify-js", [], function() {
return gulp.src("./src/js/simplemde.js")
.pipe(prettify({js: {braceStyle: "collapse", indentChar: "\t", indentSize: 1, maxPreserveNewlines: 3, spaceBeforeConditional: false}}))
.pipe(prettify({js: {brace_style: "collapse", indent_char: "\t", indent_size: 1, max_preserve_newlines: 3, space_before_conditional: false}}))
.pipe(gulp.dest("./src/js"));
});
@ -45,10 +45,9 @@ gulp.task("lint", ["prettify-js"], function() {
function taskBrowserify(opts) {
return browserify("./src/js/simplemde.js", opts)
.bundle();
}
gulp.task("browserify:dev", ["lint"], function() {
gulp.task("browserify:debug", ["lint"], function() {
return taskBrowserify({debug:true, standalone:"SimpleMDE"})
.pipe(source("simplemde.debug.js"))
.pipe(buffer())
@ -56,7 +55,7 @@ gulp.task("browserify:dev", ["lint"], function() {
.pipe(gulp.dest("./debug/"));
});
gulp.task("browserify:min", ["lint"], function() {
gulp.task("browserify", ["lint"], function() {
return taskBrowserify({standalone:"SimpleMDE"})
.pipe(source("simplemde.js"))
.pipe(buffer())
@ -64,7 +63,7 @@ gulp.task("browserify:min", ["lint"], function() {
.pipe(gulp.dest("./debug/"));
});
gulp.task("scripts", ["browserify:dev", "browserify:min", "lint"], function() {
gulp.task("scripts", ["browserify:debug", "browserify", "lint"], function() {
var js_files = ["./debug/simplemde.js"];
return gulp.src(js_files)

View file

@ -1,6 +1,6 @@
{
"name": "simplemde",
"version": "1.10.0",
"version": "1.11.2",
"description": "A simple, beautiful, and embeddable JavaScript Markdown editor. Features autosaving and spell checking.",
"keywords": [
"embeddable",
@ -21,47 +21,26 @@
"url": "https://github.com/NextStepWebs/simplemde-markdown-editor/issues"
},
"dependencies": {
"codemirror": "codemirror/CodeMirror",
"codemirror-spell-checker": "nextstepwebs/codemirror-spell-checker",
"marked": "0.3.5"
"codemirror": "*",
"codemirror-spell-checker": "*",
"marked": "*"
},
"devDependencies": {
"browserify": "^11.2.0",
"browserify-shim": "^3.8.10",
"debug": "^2.2.0",
"eslint": "^1.6.0",
"browserify": "*",
"debug": "*",
"eslint": "*",
"gulp": "*",
"gulp-concat": "*",
"gulp-debug": "^2.1.1",
"gulp-eslint": "^1.0.0",
"gulp-debug": "*",
"gulp-eslint": "*",
"gulp-header": "*",
"gulp-jsbeautifier": "*",
"gulp-minify-css": "^1.2.1",
"gulp-rename": "^1.2.2",
"gulp-clean-css": "*",
"gulp-rename": "*",
"gulp-uglify": "*",
"vinyl-source-stream": "^1.1.0",
"vinyl-source-stream": "*",
"vinyl-buffer": "*"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"browser": {
"spell-checker": "./node_modules/codemirror-spell-checker/src/js/spell-checker.js",
"typo": "./node_modules/codemirror-spell-checker/src/js/typo.js"
},
"browserify-shim": {
"spell-checker": {
"depends": [
"typo:Typo",
"codemirror:CodeMirror"
]
},
"typo": {
"exports": "Typo"
}
},
"repository": {
"type": "git",
"url": "https://github.com/NextStepWebs/simplemde-markdown-editor"

View file

@ -1,328 +1,328 @@
.CodeMirror {
height: auto;
min-height: 300px;
border: 1px solid #ddd;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
font: inherit;
z-index: 1;
height: auto;
min-height: 300px;
border: 1px solid #ddd;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
font: inherit;
z-index: 1;
}
.CodeMirror-scroll {
min-height: 300px
min-height: 300px
}
.CodeMirror-fullscreen {
background: #fff;
position: fixed !important;
top: 50px;
left: 0;
right: 0;
bottom: 0;
height: auto;
z-index: 9;
background: #fff;
position: fixed !important;
top: 50px;
left: 0;
right: 0;
bottom: 0;
height: auto;
z-index: 9;
}
.CodeMirror-sided {
width: 50% !important;
width: 50% !important;
}
.editor-toolbar {
position: relative;
opacity: .6;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
padding: 0 10px;
border-top: 1px solid #bbb;
border-left: 1px solid #bbb;
border-right: 1px solid #bbb;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
position: relative;
opacity: .6;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
padding: 0 10px;
border-top: 1px solid #bbb;
border-left: 1px solid #bbb;
border-right: 1px solid #bbb;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.editor-toolbar:after,
.editor-toolbar:before {
display: block;
content: ' ';
height: 1px;
display: block;
content: ' ';
height: 1px;
}
.editor-toolbar:before {
margin-bottom: 8px
margin-bottom: 8px
}
.editor-toolbar:after {
margin-top: 8px
margin-top: 8px
}
.editor-toolbar:hover,
.editor-wrapper input.title:focus,
.editor-wrapper input.title:hover {
opacity: .8
opacity: .8
}
.editor-toolbar.fullscreen {
width: 100%;
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;
top: 0;
left: 0;
opacity: 1;
z-index: 9;
width: 100%;
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;
top: 0;
left: 0;
opacity: 1;
z-index: 9;
}
.editor-toolbar.fullscreen::before {
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 0;
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
position: fixed;
top: 0;
left: 0;
margin: 0;
padding: 0;
}
.editor-toolbar.fullscreen::after {
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 1)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
position: fixed;
top: 0;
right: 0;
margin: 0;
padding: 0;
width: 20px;
height: 50px;
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 1)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
position: fixed;
top: 0;
right: 0;
margin: 0;
padding: 0;
}
.editor-toolbar a {
display: inline-block;
text-align: center;
text-decoration: none!important;
color: #2c3e50!important;
width: 30px;
height: 30px;
margin: 0;
border: 1px solid transparent;
border-radius: 3px;
cursor: pointer;
display: inline-block;
text-align: center;
text-decoration: none!important;
color: #2c3e50!important;
width: 30px;
height: 30px;
margin: 0;
border: 1px solid transparent;
border-radius: 3px;
cursor: pointer;
}
.editor-toolbar a.active,
.editor-toolbar a:hover {
background: #fcfcfc;
border-color: #95a5a6;
background: #fcfcfc;
border-color: #95a5a6;
}
.editor-toolbar a:before {
line-height: 30px
line-height: 30px
}
.editor-toolbar i.separator {
display: inline-block;
width: 0;
border-left: 1px solid #d9d9d9;
border-right: 1px solid #fff;
color: transparent;
text-indent: -10px;
margin: 0 6px;
display: inline-block;
width: 0;
border-left: 1px solid #d9d9d9;
border-right: 1px solid #fff;
color: transparent;
text-indent: -10px;
margin: 0 6px;
}
.editor-toolbar a.fa-header-x:after {
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 65%;
vertical-align: text-bottom;
position: relative;
top: 2px;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 65%;
vertical-align: text-bottom;
position: relative;
top: 2px;
}
.editor-toolbar a.fa-header-1:after {
content: "1";
content: "1";
}
.editor-toolbar a.fa-header-2:after {
content: "2";
content: "2";
}
.editor-toolbar a.fa-header-3:after {
content: "3";
content: "3";
}
.editor-toolbar a.fa-header-bigger:after {
content: "▲";
content: "▲";
}
.editor-toolbar a.fa-header-smaller:after {
content: "▼";
content: "▼";
}
.editor-toolbar.disabled-for-preview a:not(.no-disable) {
pointer-events: none;
background: #fff;
border-color: transparent;
text-shadow: inherit;
pointer-events: none;
background: #fff;
border-color: transparent;
text-shadow: inherit;
}
@media only screen and (max-width: 700px) {
.editor-toolbar a.no-mobile {
display: none;
}
.editor-toolbar a.no-mobile {
display: none;
}
}
.editor-statusbar {
padding: 8px 10px;
font-size: 12px;
color: #959694;
text-align: right;
padding: 8px 10px;
font-size: 12px;
color: #959694;
text-align: right;
}
.editor-statusbar span {
display: inline-block;
min-width: 4em;
margin-left: 1em;
display: inline-block;
min-width: 4em;
margin-left: 1em;
}
.editor-statusbar .lines:before {
content: 'lines: '
content: 'lines: '
}
.editor-statusbar .words:before {
content: 'words: '
content: 'words: '
}
.editor-statusbar .characters:before {
content: 'characters: '
content: 'characters: '
}
.editor-preview {
padding: 10px;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fafafa;
z-index: 7;
overflow: auto;
display: none;
box-sizing: border-box;
padding: 10px;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: #fafafa;
z-index: 7;
overflow: auto;
display: none;
box-sizing: border-box;
}
.editor-preview-side {
padding: 10px;
position: fixed;
bottom: 0;
width: 50%;
top: 50px;
right: 0;
background: #fafafa;
z-index: 9;
overflow: auto;
display: none;
box-sizing: border-box;
border: 1px solid #ddd;
padding: 10px;
position: fixed;
bottom: 0;
width: 50%;
top: 50px;
right: 0;
background: #fafafa;
z-index: 9;
overflow: auto;
display: none;
box-sizing: border-box;
border: 1px solid #ddd;
}
.editor-preview-active-side {
display: block
display: block
}
.editor-preview-active {
display: block
display: block
}
.editor-preview>p,
.editor-preview-side>p {
margin-top: 0
margin-top: 0
}
.editor-preview pre,
.editor-preview-side pre {
background: #eee;
margin-bottom: 10px;
background: #eee;
margin-bottom: 10px;
}
.editor-preview table td,
.editor-preview table th,
.editor-preview-side table td,
.editor-preview-side table th {
border: 1px solid #ddd;
padding: 5px;
border: 1px solid #ddd;
padding: 5px;
}
.CodeMirror .CodeMirror-code .cm-tag {
color: #63a35c;
color: #63a35c;
}
.CodeMirror .CodeMirror-code .cm-attribute {
color: #795da3;
color: #795da3;
}
.CodeMirror .CodeMirror-code .cm-string {
color: #183691;
color: #183691;
}
.CodeMirror .CodeMirror-selected {
background: #d9d9d9;
background: #d9d9d9;
}
.CodeMirror .CodeMirror-code .cm-header-1 {
font-size: 200%;
line-height: 200%;
font-size: 200%;
line-height: 200%;
}
.CodeMirror .CodeMirror-code .cm-header-2 {
font-size: 160%;
line-height: 160%;
font-size: 160%;
line-height: 160%;
}
.CodeMirror .CodeMirror-code .cm-header-3 {
font-size: 125%;
line-height: 125%;
font-size: 125%;
line-height: 125%;
}
.CodeMirror .CodeMirror-code .cm-header-4 {
font-size: 110%;
line-height: 110%;
font-size: 110%;
line-height: 110%;
}
.CodeMirror .CodeMirror-code .cm-comment {
background: rgba(0, 0, 0, .05);
border-radius: 2px;
background: rgba(0, 0, 0, .05);
border-radius: 2px;
}
.CodeMirror .CodeMirror-code .cm-link {
color: #7f8c8d;
color: #7f8c8d;
}
.CodeMirror .CodeMirror-code .cm-url {
color: #aab2b3;
color: #aab2b3;
}
.CodeMirror .CodeMirror-code .cm-strikethrough {
text-decoration: line-through;
text-decoration: line-through;
}
.CodeMirror .CodeMirror-placeholder {
opacity: .5;
opacity: .5;
}

View file

@ -7,9 +7,10 @@ require("codemirror/addon/display/fullscreen.js");
require("codemirror/mode/markdown/markdown.js");
require("codemirror/addon/mode/overlay.js");
require("codemirror/addon/display/placeholder.js");
require("codemirror/addon/selection/mark-selection.js");
require("codemirror/mode/gfm/gfm.js");
require("codemirror/mode/xml/xml.js");
require("spell-checker");
var CodeMirrorSpellChecker = require("codemirror-spell-checker");
var marked = require("marked");
@ -253,7 +254,286 @@ function toggleStrikethrough(editor) {
* Action for toggling code block.
*/
function toggleCodeBlock(editor) {
_toggleBlock(editor, "code", "```\r\n", "\r\n```");
var fenceCharsToInsert = editor.options.blockStyles.code;
function fencing_line(line) {
/* return true, if this is a ``` or ~~~ line */
if(typeof line !== "object") {
throw "fencing_line() takes a 'line' object (not a line number, or line text). Got: " + typeof line + ": " + line;
}
return line.styles && line.styles[2] && line.styles[2].indexOf("formatting-code-block") !== -1;
}
function token_state(token) {
// base goes an extra level deep when mode backdrops are used, e.g. spellchecker on
return token.state.base.base || token.state.base;
}
function code_type(cm, line_num, line, firstTok, lastTok) {
/*
* Return "single", "indented", "fenced" or false
*
* cm and line_num are required. Others are optional for efficiency
* To check in the middle of a line, pass in firstTok yourself.
*/
line = line || cm.getLineHandle(line_num);
firstTok = firstTok || cm.getTokenAt({
line: line_num,
ch: 1
});
lastTok = lastTok || (!!line.text && cm.getTokenAt({
line: line_num,
ch: line.text.length - 1
}));
var types = firstTok.type ? firstTok.type.split(" ") : [];
if(lastTok && token_state(lastTok).indentedCode) {
// have to check last char, since first chars of first line aren"t marked as indented
return "indented";
} else if(types.indexOf("comment") === -1) {
// has to be after "indented" check, since first chars of first indented line aren"t marked as such
return false;
} else if(token_state(firstTok).fencedChars || token_state(lastTok).fencedChars || fencing_line(line)) {
return "fenced";
} else {
return "single";
}
}
function insertFencingAtSelection(cm, cur_start, cur_end, fenceCharsToInsert) {
var start_line_sel = cur_start.line + 1,
end_line_sel = cur_end.line + 1,
sel_multi = cur_start.line !== cur_end.line,
repl_start = fenceCharsToInsert + "\n",
repl_end = "\n" + fenceCharsToInsert;
if(sel_multi) {
end_line_sel++;
}
// handle last char including \n or not
if(sel_multi && cur_end.ch === 0) {
repl_end = fenceCharsToInsert + "\n";
end_line_sel--;
}
_replaceSelection(cm, false, [repl_start, repl_end]);
cm.setSelection({
line: start_line_sel,
ch: 0
}, {
line: end_line_sel,
ch: 0
});
}
var cm = editor.codemirror,
cur_start = cm.getCursor("start"),
cur_end = cm.getCursor("end"),
tok = cm.getTokenAt({
line: cur_start.line,
ch: cur_start.ch || 1
}), // avoid ch 0 which is a cursor pos but not token
line = cm.getLineHandle(cur_start.line),
is_code = code_type(cm, cur_start.line, line, tok);
var block_start, block_end, lineCount;
if(is_code === "single") {
// similar to some SimpleMDE _toggleBlock logic
var start = line.text.slice(0, cur_start.ch).replace("`", ""),
end = line.text.slice(cur_start.ch).replace("`", "");
cm.replaceRange(start + end, {
line: cur_start.line,
ch: 0
}, {
line: cur_start.line,
ch: 99999999999999
});
cur_start.ch--;
if(cur_start !== cur_end) {
cur_end.ch--;
}
cm.setSelection(cur_start, cur_end);
cm.focus();
} else if(is_code === "fenced") {
if(cur_start.line !== cur_end.line || cur_start.ch !== cur_end.ch) {
// use selection
// find the fenced line so we know what type it is (tilde, backticks, number of them)
for(block_start = cur_start.line; block_start >= 0; block_start--) {
line = cm.getLineHandle(block_start);
if(fencing_line(line)) {
break;
}
}
var fencedTok = cm.getTokenAt({
line: block_start,
ch: 1
});
var fence_chars = token_state(fencedTok).fencedChars;
var start_text, start_line;
var end_text, end_line;
// check for selection going up against fenced lines, in which case we don't want to add more fencing
if(fencing_line(cm.getLineHandle(cur_start.line))) {
start_text = "";
start_line = cur_start.line;
} else if(fencing_line(cm.getLineHandle(cur_start.line - 1))) {
start_text = "";
start_line = cur_start.line - 1;
} else {
start_text = fence_chars + "\n";
start_line = cur_start.line;
}
if(fencing_line(cm.getLineHandle(cur_end.line))) {
end_text = "";
end_line = cur_end.line;
if(cur_end.ch === 0) {
end_line += 1;
}
} else if(cur_end.ch !== 0 && fencing_line(cm.getLineHandle(cur_end.line + 1))) {
end_text = "";
end_line = cur_end.line + 1;
} else {
end_text = fence_chars + "\n";
end_line = cur_end.line + 1;
}
if(cur_end.ch === 0) {
// full last line selected, putting cursor at beginning of next
end_line -= 1;
}
cm.operation(function() {
// end line first, so that line numbers don't change
cm.replaceRange(end_text, {
line: end_line,
ch: 0
}, {
line: end_line + (end_text ? 0 : 1),
ch: 0
});
cm.replaceRange(start_text, {
line: start_line,
ch: 0
}, {
line: start_line + (start_text ? 0 : 1),
ch: 0
});
});
cm.setSelection({
line: start_line + (start_text ? 1 : 0),
ch: 0
}, {
line: end_line + (start_text ? 1 : -1),
ch: 0
});
cm.focus();
} else {
// no selection, search for ends of this fenced block
var search_from = cur_start.line;
if(fencing_line(cm.getLineHandle(cur_start.line))) { // gets a little tricky if cursor is right on a fenced line
if(code_type(cm, cur_start.line + 1) === "fenced") {
block_start = cur_start.line;
search_from = cur_start.line + 1; // for searching for "end"
} else {
block_end = cur_start.line;
search_from = cur_start.line - 1; // for searching for "start"
}
}
if(block_start === undefined) {
for(block_start = search_from; block_start >= 0; block_start--) {
line = cm.getLineHandle(block_start);
if(fencing_line(line)) {
break;
}
}
}
if(block_end === undefined) {
lineCount = cm.lineCount();
for(block_end = search_from; block_end < lineCount; block_end++) {
line = cm.getLineHandle(block_end);
if(fencing_line(line)) {
break;
}
}
}
cm.operation(function() {
cm.replaceRange("", {
line: block_start,
ch: 0
}, {
line: block_start + 1,
ch: 0
});
cm.replaceRange("", {
line: block_end - 1,
ch: 0
}, {
line: block_end,
ch: 0
});
});
cm.focus();
}
} else if(is_code === "indented") {
if(cur_start.line !== cur_end.line || cur_start.ch !== cur_end.ch) {
// use selection
block_start = cur_start.line;
block_end = cur_end.line;
if(cur_end.ch === 0) {
block_end--;
}
} else {
// no selection, search for ends of this indented block
for(block_start = cur_start.line; block_start >= 0; block_start--) {
line = cm.getLineHandle(block_start);
if(line.text.match(/^\s*$/)) {
// empty or all whitespace - keep going
continue;
} else {
if(code_type(cm, block_start, line) !== "indented") {
block_start += 1;
break;
}
}
}
lineCount = cm.lineCount();
for(block_end = cur_start.line; block_end < lineCount; block_end++) {
line = cm.getLineHandle(block_end);
if(line.text.match(/^\s*$/)) {
// empty or all whitespace - keep going
continue;
} else {
if(code_type(cm, block_end, line) !== "indented") {
block_end -= 1;
break;
}
}
}
}
// if we are going to un-indent based on a selected set of lines, and the next line is indented too, we need to
// insert a blank line so that the next line(s) continue to be indented code
var next_line = cm.getLineHandle(block_end + 1),
next_line_last_tok = next_line && cm.getTokenAt({
line: block_end + 1,
ch: next_line.text.length - 1
}),
next_line_indented = next_line_last_tok && token_state(next_line_last_tok).indentedCode;
if(next_line_indented) {
cm.replaceRange("\n", {
line: block_end + 1,
ch: 0
});
}
for(var i = block_start; i <= block_end; i++) {
cm.indentLine(i, "subtract"); // TODO: this doesn't get tracked in the history, so can't be undone :(
}
cm.focus();
} else {
// insert code formatting
var no_sel_and_starting_of_line = (cur_start.line === cur_end.line && cur_start.ch === cur_end.ch && cur_start.ch === 0);
var sel_multi = cur_start.line !== cur_end.line;
if(no_sel_and_starting_of_line || sel_multi) {
insertFencingAtSelection(cm, cur_start, cur_end, fenceCharsToInsert);
} else {
_replaceSelection(cm, false, ["`", "`"]);
}
}
}
/**
@ -337,7 +617,14 @@ function drawLink(editor) {
var cm = editor.codemirror;
var stat = getState(cm);
var options = editor.options;
_replaceSelection(cm, stat.link, options.insertTexts.link);
var url = "http://";
if(options.promptURLs) {
url = prompt(options.promptTexts.link);
if(!url) {
return false;
}
}
_replaceSelection(cm, stat.link, options.insertTexts.link, url);
}
/**
@ -347,7 +634,14 @@ function drawImage(editor) {
var cm = editor.codemirror;
var stat = getState(cm);
var options = editor.options;
_replaceSelection(cm, stat.image, options.insertTexts.image);
var url = "http://";
if(options.promptURLs) {
url = prompt(options.promptTexts.image);
if(!url) {
return false;
}
}
_replaceSelection(cm, stat.image, options.insertTexts.image, url);
}
/**
@ -446,6 +740,9 @@ function toggleSideBySide(editor) {
} else {
cm.off("update", cm.sideBySideRenderingFunction);
}
// Refresh to fix selection being off (#309)
cm.refresh();
}
@ -456,7 +753,7 @@ function togglePreview(editor) {
var cm = editor.codemirror;
var wrapper = cm.getWrapperElement();
var toolbar_div = wrapper.previousSibling;
var toolbar = editor.toolbarElements.preview;
var toolbar = editor.options.toolbar ? editor.toolbarElements.preview : false;
var preview = wrapper.lastChild;
if(!preview || !/editor-preview/.test(preview.className)) {
preview = document.createElement("div");
@ -467,8 +764,10 @@ function togglePreview(editor) {
preview.className = preview.className.replace(
/\s*editor-preview-active\s*/g, ""
);
toolbar.className = toolbar.className.replace(/\s*active\s*/g, "");
toolbar_div.className = toolbar_div.className.replace(/\s*disabled-for-preview*/g, "");
if(toolbar) {
toolbar.className = toolbar.className.replace(/\s*active\s*/g, "");
toolbar_div.className = toolbar_div.className.replace(/\s*disabled-for-preview*/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,
@ -476,8 +775,10 @@ function togglePreview(editor) {
setTimeout(function() {
preview.className += " editor-preview-active";
}, 1);
toolbar.className += " active";
toolbar_div.className += " disabled-for-preview";
if(toolbar) {
toolbar.className += " active";
toolbar_div.className += " disabled-for-preview";
}
}
preview.innerHTML = editor.options.previewRender(editor.value(), preview);
@ -487,7 +788,7 @@ function togglePreview(editor) {
toggleSideBySide(editor);
}
function _replaceSelection(cm, active, startEnd) {
function _replaceSelection(cm, active, startEnd, url) {
if(/editor-preview-active/.test(cm.getWrapperElement().lastChild.className))
return;
@ -496,6 +797,9 @@ function _replaceSelection(cm, active, startEnd) {
var end = startEnd[1];
var startPoint = cm.getCursor("start");
var endPoint = cm.getCursor("end");
if(url) {
end = end.replace("#url#", url);
}
if(active) {
text = cm.getLine(startPoint.line);
start = text.slice(0, startPoint.ch);
@ -748,7 +1052,7 @@ function extend(target) {
/* The right word count in respect for CJK. */
function wordCount(data) {
var pattern = /[a-zA-Z0-9_\u0392-\u03c9]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/g;
var pattern = /[a-zA-Z0-9_\u0392-\u03c9\u0410-\u04F9]+|[\u4E00-\u9FFF\u3400-\u4dbf\uf900-\ufaff\u3040-\u309f\uac00-\ud7af]+/g;
var m = data.match(pattern);
var count = 0;
if(m === null) return count;
@ -914,7 +1218,7 @@ var toolbarBuiltInButtons = {
},
"guide": {
name: "guide",
action: "http://nextstepwebs.github.io/simplemde-markdown-editor/markdown-guide",
action: "https://simplemde.com/markdown-guide",
className: "fa fa-question-circle",
title: "Markdown Guide",
default: true
@ -937,14 +1241,20 @@ var toolbarBuiltInButtons = {
};
var insertTexts = {
link: ["[", "](http://)"],
image: ["![](http://", ")"],
link: ["[", "](#url#)"],
image: ["![](", "#url#)"],
table: ["", "\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n"],
horizontalRule: ["", "\n\n-----\n\n"]
};
var promptTexts = {
link: "URL for the link:",
image: "URL of the image:"
};
var blockStyles = {
"bold": "**",
"code": "```",
"italic": "*"
};
@ -1034,13 +1344,19 @@ function SimpleMDE(options) {
// Set default options for parsing config
options.parsingConfig = options.parsingConfig || {};
options.parsingConfig = extend({
highlightFormatting: true // needed for toggleCodeBlock to detect types of code
}, options.parsingConfig || {});
// Merging the insertTexts, with the given options
options.insertTexts = extend({}, insertTexts, options.insertTexts || {});
// Merging the promptTexts, with the given options
options.promptTexts = promptTexts;
// Merging the blockStyles, with the given options
options.blockStyles = extend({}, blockStyles, options.blockStyles || {});
@ -1080,7 +1396,9 @@ SimpleMDE.prototype.markdown = function(text) {
// Update options
if(this.options && this.options.renderingConfig && this.options.renderingConfig.singleLineBreaks !== false) {
if(this.options && this.options.renderingConfig && this.options.renderingConfig.singleLineBreaks === false) {
markedOptions.breaks = false;
} else {
markedOptions.breaks = true;
}
@ -1151,6 +1469,10 @@ SimpleMDE.prototype.render = function(el) {
backdrop = options.parsingConfig;
backdrop.name = "gfm";
backdrop.gitHubSpice = false;
CodeMirrorSpellChecker({
codeMirrorInstance: CodeMirror
});
} else {
mode = options.parsingConfig;
mode.name = "gfm";
@ -1169,26 +1491,59 @@ SimpleMDE.prototype.render = function(el) {
extraKeys: keyMaps,
lineWrapping: (options.lineWrapping === false) ? false : true,
allowDropFileTypes: ["text/plain"],
placeholder: options.placeholder || el.getAttribute("placeholder") || ""
placeholder: options.placeholder || el.getAttribute("placeholder") || "",
styleSelectedText: (options.styleSelectedText != undefined) ? options.styleSelectedText : true
});
if(options.forceSync === true) {
var cm = this.codemirror;
cm.on("change", function() {
cm.save();
});
}
this.gui = {};
if(options.toolbar !== false) {
this.createToolbar();
this.gui.toolbar = this.createToolbar();
}
if(options.status !== false) {
this.createStatusbar();
this.gui.statusbar = this.createStatusbar();
}
if(options.autosave != undefined && options.autosave.enabled === true) {
this.autosave();
}
this.createSideBySide();
this.gui.sideBySide = this.createSideBySide();
this._rendered = this.element;
// Fixes CodeMirror bug (#344)
var temp_cm = this.codemirror;
setTimeout(function() {
temp_cm.refresh();
}.bind(temp_cm), 0);
};
// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem throw QuotaExceededError. We're going to detect this and set a variable accordingly.
function isLocalStorageAvailable() {
if(typeof localStorage === "object") {
try {
localStorage.setItem("smde_localStorage", 1);
localStorage.removeItem("smde_localStorage");
} catch(e) {
return false;
}
} else {
return false;
}
return true;
}
SimpleMDE.prototype.autosave = function() {
if(localStorage) {
if(isLocalStorageAvailable()) {
var simplemde = this;
if(this.options.autosave.uniqueId == undefined || this.options.autosave.uniqueId == "") {
@ -1232,7 +1587,7 @@ SimpleMDE.prototype.autosave = function() {
el.innerHTML = "Autosaved: " + h + ":" + m + " " + dd;
}
setTimeout(function() {
this.autosaveTimeoutId = setTimeout(function() {
simplemde.autosave();
}, this.options.autosave.delay || 10000);
} else {
@ -1241,7 +1596,7 @@ SimpleMDE.prototype.autosave = function() {
};
SimpleMDE.prototype.clearAutosavedValue = function() {
if(localStorage) {
if(isLocalStorageAvailable()) {
if(this.options.autosave == undefined || this.options.autosave.uniqueId == undefined || this.options.autosave.uniqueId == "") {
console.log("SimpleMDE: You must set a uniqueId to clear the autosave value");
return;
@ -1291,7 +1646,7 @@ SimpleMDE.prototype.createSideBySide = function() {
var move = (cm.getScrollInfo().height - cm.getScrollInfo().clientHeight) * ratio;
cm.scrollTo(0, move);
};
return true;
return preview;
};
SimpleMDE.prototype.createToolbar = function(items) {
@ -1333,7 +1688,7 @@ SimpleMDE.prototype.createToolbar = function(items) {
var nonSeparatorIconsFollow = false;
for(var x = (i + 1); x < items.length; x++) {
if(items[x] !== "|") {
if(items[x] !== "|" && (!self.options.hideIcons || self.options.hideIcons.indexOf(items[x].name) == -1)) {
nonSeparatorIconsFollow = true;
}
}
@ -1355,7 +1710,8 @@ SimpleMDE.prototype.createToolbar = function(items) {
// bind events, special for info
if(item.action) {
if(typeof item.action === "function") {
el.onclick = function() {
el.onclick = function(e) {
e.preventDefault();
item.action(self);
};
} else if(typeof item.action === "string") {
@ -1426,14 +1782,14 @@ SimpleMDE.prototype.createStatusbar = function(status) {
if(name === "words") {
defaultValue = function(el) {
el.innerHTML = "0";
el.innerHTML = wordCount(cm.getValue());
};
onUpdate = function(el) {
el.innerHTML = wordCount(cm.getValue());
};
} else if(name === "lines") {
defaultValue = function(el) {
el.innerHTML = "0";
el.innerHTML = cm.lineCount();
};
onUpdate = function(el) {
el.innerHTML = cm.lineCount();
@ -1644,4 +2000,29 @@ SimpleMDE.prototype.getState = function() {
return getState(cm);
};
module.exports = SimpleMDE;
SimpleMDE.prototype.toTextArea = function() {
var cm = this.codemirror;
var wrapper = cm.getWrapperElement();
if(wrapper.parentNode) {
if(this.gui.toolbar) {
wrapper.parentNode.removeChild(this.gui.toolbar);
}
if(this.gui.statusbar) {
wrapper.parentNode.removeChild(this.gui.statusbar);
}
if(this.gui.sideBySide) {
wrapper.parentNode.removeChild(this.gui.sideBySide);
}
}
cm.toTextArea();
if(this.autosaveTimeoutId) {
clearTimeout(this.autosaveTimeoutId);
this.autosaveTimeoutId = undefined;
this.clearAutosavedValue();
}
};
module.exports = SimpleMDE;