Merge with 2.7.0.

pull/101/head
Jeroen van Oorschot 5 years ago
parent 4ae7fc8bc9
commit ff0db2000a

@ -1,10 +1,26 @@
# EasyMDE Changelog # EasyMDE Changelog
All notable changes to this project will be documented in this file. All notable changes to easymde will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] <!--## [Unreleased]-->
Merge 2.7.0 with https://github.com/Ionaru/easy-markdown-editor/pull/71 @jeroenvo
## [2.7.0] - 2019-07-13
### Added
- `previewClass` option for overwriting the preview screen class ([#99]).
### Fixed
- Updated dependencies to resolve potential security issue.
- Resolved small code style issues shown by new eslint rules.
## [2.6.1] - 2019-06-17
### Fixed
- Error when toggling between ordered and unordered lists (Thanks to [@roryok], [#93]).
- Keyboard shortcuts for custom actions not working (Thanks to [@ysykzheng], [#75]).
## [2.6.0] - 2019-04-15
### Added ### Added
- Contributing guide (Thanks to [@roipoussiere], [#54]). - Contributing guide (Thanks to [@roipoussiere], [#54]).
- Issue templates. - Issue templates.
@ -13,7 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Finish rewrite of README (Thanks to [@roipoussiere], [#54]). - Finish rewrite of README (Thanks to [@roipoussiere], [#54]).
- Image and link prompt fill with "https://" by default. - Image and link prompt fill with "https://" by default.
- Link to markdown guide to https://www.markdownguide.org/basic-syntax/. - Link to markdown guide to <https://www.markdownguide.org/basic-syntax/>.
### Fixed ### Fixed
- Backwards compatibility in the API with SimpleMDE 1.0.0 ([#41]). - Backwards compatibility in the API with SimpleMDE 1.0.0 ([#41]).

@ -2,7 +2,7 @@
var gulp = require('gulp'); var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css'); var cleanCSS = require('gulp-clean-css');
var uglify = require('gulp-uglify'); var terser = require('gulp-terser');
var concat = require('gulp-concat'); var concat = require('gulp-concat');
var header = require('gulp-header'); var header = require('gulp-header');
var buffer = require('vinyl-buffer'); var buffer = require('vinyl-buffer');
@ -31,7 +31,7 @@ function scripts() {
return browserify({entries: './src/js/easymde.js', standalone: 'EasyMDE'}).bundle() return browserify({entries: './src/js/easymde.js', standalone: 'EasyMDE'}).bundle()
.pipe(source('easymde.min.js')) .pipe(source('easymde.min.js'))
.pipe(buffer()) .pipe(buffer())
.pipe(uglify()) .pipe(terser())
.pipe(header(banner, {pkg: pkg})) .pipe(header(banner, {pkg: pkg}))
.pipe(gulp.dest('./dist/')); .pipe(gulp.dest('./dist/'));
} }

@ -1,4 +1,3 @@
/*global require,module*/
'use strict'; 'use strict';
var CodeMirror = require('codemirror'); var CodeMirror = require('codemirror');
require('codemirror/addon/edit/continuelist.js'); require('codemirror/addon/edit/continuelist.js');
@ -122,6 +121,11 @@ function createToolbarButton(options, enableTooltips, shortcuts) {
el.setAttribute('type', 'button'); el.setAttribute('type', 'button');
enableTooltips = (enableTooltips == undefined) ? true : enableTooltips; enableTooltips = (enableTooltips == undefined) ? true : enableTooltips;
// Properly hande custom shortcuts
if( options.name && options.name in shortcuts ){
bindings[options.name] = options.action;
}
if (options.title && enableTooltips) { if (options.title && enableTooltips) {
el.title = createTooltip(options.title, options.action, shortcuts); el.title = createTooltip(options.title, options.action, shortcuts);
@ -169,7 +173,7 @@ function createToolbarButton(options, enableTooltips, shortcuts) {
function createSep() { function createSep() {
var el = document.createElement('i'); var el = document.createElement('i');
el.className = 'separator'; el.className = 'separator';
el.textContent = '|'; el.innerHTML = '|';
return el; return el;
} }
@ -840,9 +844,23 @@ function togglePreview(editor) {
var toolbar_div = wrapper.previousSibling; var toolbar_div = wrapper.previousSibling;
var toolbar = editor.options.toolbar ? editor.toolbarElements.preview : false; var toolbar = editor.options.toolbar ? editor.toolbarElements.preview : false;
var preview = wrapper.lastChild; var preview = wrapper.lastChild;
if (!preview || !/editor-preview/.test(preview.className)) { if (!preview || !/editor-preview-full/.test(preview.className)) {
preview = document.createElement('div'); preview = document.createElement('div');
preview.className = 'editor-preview'; preview.className = 'editor-preview-full';
if (editor.options.previewClass) {
if (Array.isArray(editor.options.previewClass)) {
for (var i = 0; i < editor.options.previewClass.length; i++) {
preview.className += (' ' + editor.options.previewClass[i]);
}
} else if (typeof editor.options.previewClass === 'string') {
preview.className += (' ' + editor.options.previewClass);
}
}
wrapper.appendChild(preview); wrapper.appendChild(preview);
} }
if (/editor-preview-active/.test(preview.className)) { if (/editor-preview-active/.test(preview.className)) {
@ -885,7 +903,6 @@ function _replaceSelection(cm, active, startEnd, url) {
Object.assign(startPoint, cm.getCursor('start')); Object.assign(startPoint, cm.getCursor('start'));
Object.assign(endPoint, cm.getCursor('end')); Object.assign(endPoint, cm.getCursor('end'));
if (url) { if (url) {
start = start.replace('#url#', url);
end = end.replace('#url#', url); end = end.replace('#url#', url);
} }
if (active) { if (active) {
@ -1010,13 +1027,27 @@ function _toggleLine(cm, name) {
var map = { var map = {
'quote': '>', 'quote': '>',
'unordered-list': '*', 'unordered-list': '*',
'ordered-list': 'd+.', 'ordered-list': '\\d+.',
}; };
var rt = new RegExp(map[name]); var rt = new RegExp(map[name]);
return char && rt.test(char); return char && rt.test(char);
}; };
var _toggle = function (name, text, untoggleOnly) {
var arr = listRegexp.exec(text);
var char = _getChar(name, line);
if (arr !== null) {
if (_checkChar(name, arr[2])) {
char = '';
}
text = arr[1] + char + arr[3] + text.replace(whitespacesRegexp, '').replace(repl[name], '$1');
} else if (untoggleOnly == false){
text = char + ' ' + text;
}
return text;
};
var line = 1; var line = 1;
for (var i = startPoint.line; i <= endPoint.line; i++) { for (var i = startPoint.line; i <= endPoint.line; i++) {
(function (i) { (function (i) {
@ -1024,16 +1055,13 @@ function _toggleLine(cm, name) {
if (stat[name]) { if (stat[name]) {
text = text.replace(repl[name], '$1'); text = text.replace(repl[name], '$1');
} else { } else {
var arr = listRegexp.exec(text); // If we're toggling unordered-list formatting, check if the current line
var char = _getChar(name, line); // is part of an ordered-list, and if so, untoggle that first.
if (arr !== null) { // Workaround for https://github.com/Ionaru/easy-markdown-editor/issues/92
if (_checkChar(name, arr[2])) { if (name == 'unordered-list') {
char = ''; text = _toggle('ordered-list', text, true);
}
text = arr[1] + char + arr[3] + text.replace(whitespacesRegexp, '').replace(repl[name], '$1');
} else {
text = char + ' ' + text;
} }
text = _toggle(name, text, false);
line += 1; line += 1;
} }
cm.replaceRange(text, { cm.replaceRange(text, {
@ -1160,7 +1188,7 @@ function humanFileSize(bytes, units) {
// Merge the properties of one object into another. // Merge the properties of one object into another.
function _mergeProperties(target, source) { function _mergeProperties(target, source) {
for (var property in source) { for (var property in source) {
if (source.hasOwnProperty(property)) { if (Object.prototype.hasOwnProperty.call(source, property)) {
if (source[property] instanceof Array) { if (source[property] instanceof Array) {
target[property] = source[property].concat(target[property] instanceof Array ? target[property] : []); target[property] = source[property].concat(target[property] instanceof Array ? target[property] : []);
} else if ( } else if (
@ -1491,7 +1519,7 @@ function EasyMDE(options) {
// Loop over the built in buttons, to get the preferred order // Loop over the built in buttons, to get the preferred order
for (var key in toolbarBuiltInButtons) { for (var key in toolbarBuiltInButtons) {
if (toolbarBuiltInButtons.hasOwnProperty(key)) { if (Object.prototype.hasOwnProperty.call(toolbarBuiltInButtons, key)) {
if (key.indexOf('separator-') != -1) { if (key.indexOf('separator-') != -1) {
options.toolbar.push('|'); options.toolbar.push('|');
} }
@ -1503,9 +1531,13 @@ function EasyMDE(options) {
} }
} }
// Editor preview styling class.
if (!Object.prototype.hasOwnProperty.call(options, 'previewClass')) {
options.previewClass = 'editor-preview';
}
// Handle status bar // Handle status bar
if (!options.hasOwnProperty('status')) { if (!Object.prototype.hasOwnProperty.call(options, 'status')) {
if (options.uploadImage) { if (options.uploadImage) {
options.status = ['upload-image', 'autosave', 'lines', 'words', 'cursor']; options.status = ['upload-image', 'autosave', 'lines', 'words', 'cursor'];
} else { } else {
@ -1710,7 +1742,12 @@ EasyMDE.prototype.render = function (el) {
if (options.shortcuts[key] !== null && bindings[key] !== null) { if (options.shortcuts[key] !== null && bindings[key] !== null) {
(function (key) { (function (key) {
keyMaps[fixShortcut(options.shortcuts[key])] = function () { keyMaps[fixShortcut(options.shortcuts[key])] = function () {
bindings[key](self); var action = bindings[key];
if (typeof action === 'function') {
action(self);
} else if (typeof action === 'string') {
window.open(action, '_blank');
}
}; };
})(key); })(key);
} }
@ -1874,7 +1911,7 @@ EasyMDE.prototype.autosave = function () {
} }
m = m < 10 ? '0' + m : m; m = m < 10 ? '0' + m : m;
el.textContent = 'Autosaved: ' + h + ':' + m + ' ' + dd; el.innerHTML = 'Autosaved: ' + h + ':' + m + ' ' + dd;
} }
this.autosaveTimeoutId = setTimeout(function () { this.autosaveTimeoutId = setTimeout(function () {
@ -1993,6 +2030,19 @@ EasyMDE.prototype.createSideBySide = function () {
if (!preview || !/editor-preview-side/.test(preview.className)) { if (!preview || !/editor-preview-side/.test(preview.className)) {
preview = document.createElement('div'); preview = document.createElement('div');
preview.className = 'editor-preview-side'; preview.className = 'editor-preview-side';
if (this.options.previewClass) {
if (Array.isArray(this.options.previewClass)) {
for (var i = 0; i < this.options.previewClass.length; i++) {
preview.className += (' ' + this.options.previewClass[i]);
}
} else if (typeof this.options.previewClass === 'string') {
preview.className += (' ' + this.options.previewClass);
}
}
wrapper.parentNode.insertBefore(preview, wrapper.nextSibling); wrapper.parentNode.insertBefore(preview, wrapper.nextSibling);
} }
@ -2176,25 +2226,25 @@ EasyMDE.prototype.createStatusbar = function (status) {
if (name === 'words') { if (name === 'words') {
defaultValue = function (el) { defaultValue = function (el) {
el.textContent = wordCount(cm.getValue()); el.innerHTML = wordCount(cm.getValue());
}; };
onUpdate = function (el) { onUpdate = function (el) {
el.textContent = wordCount(cm.getValue()); el.innerHTML = wordCount(cm.getValue());
}; };
} else if (name === 'lines') { } else if (name === 'lines') {
defaultValue = function (el) { defaultValue = function (el) {
el.textContent = cm.lineCount(); el.innerHTML = cm.lineCount();
}; };
onUpdate = function (el) { onUpdate = function (el) {
el.textContent = cm.lineCount(); el.innerHTML = cm.lineCount();
}; };
} else if (name === 'cursor') { } else if (name === 'cursor') {
defaultValue = function (el) { defaultValue = function (el) {
el.textContent = '0:0'; el.innerHTML = '0:0';
}; };
onUpdate = function (el) { onUpdate = function (el) {
var pos = cm.getCursor(); var pos = cm.getCursor();
el.textContent = pos.line + ':' + pos.ch; el.innerHTML = pos.line + ':' + pos.ch;
}; };
} else if (name === 'autosave') { } else if (name === 'autosave') {
defaultValue = function (el) { defaultValue = function (el) {
@ -2204,7 +2254,7 @@ EasyMDE.prototype.createStatusbar = function (status) {
}; };
} else if (name === 'upload-image') { } else if (name === 'upload-image') {
defaultValue = function (el) { defaultValue = function (el) {
el.textContent = options.imageTexts.sbInit; el.innerHTML = options.imageTexts.sbInit;
}; };
} }

@ -7,6 +7,7 @@ const editor = new EasyMDE({
drawTable: 'Cmd-Alt-T', drawTable: 'Cmd-Alt-T',
toggleFullScreen: null toggleFullScreen: null
}, },
previewClass: 'my-custom-class',
spellChecker: false, spellChecker: false,
onToggleFullScreen: (full: boolean) => { onToggleFullScreen: (full: boolean) => {
console.log('FullscreenToggled', full); console.log('FullscreenToggled', full);
@ -28,3 +29,33 @@ editor.codemirror.setOption('readOnly', true);
EasyMDE.toggleItalic = (editor: EasyMDE) => { EasyMDE.toggleItalic = (editor: EasyMDE) => {
console.log('SomeButtonOverride'); console.log('SomeButtonOverride');
}; };
const editor2 = new EasyMDE({
autoDownloadFontAwesome: undefined,
previewClass: ['my-custom-class', 'some-other-class'],
toolbar: [{
name: 'bold',
action: EasyMDE.toggleBold,
className: 'fa fa-bolt',
title: 'Bold',
}, '|', { // Separator
name: 'alert',
action: (editor) => {
alert('This is from a custom button action!');
// Custom functions have access to the `editor` instance.
},
className: 'fa fa-star',
title: 'A Custom Button',
noDisable: undefined,
noMobile: false,
}, '|', {
name: 'link',
action: 'https://github.com/Ionaru/easy-markdown-editor',
className: 'fa fab fa-github',
title: 'A Custom Link',
noDisable: true,
noMobile: true,
}]
});
editor2.clearAutosavedValue();

@ -1,16 +1,16 @@
// This file is based on https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/simplemde/index.d.ts, // This file is based on https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/simplemde/index.d.ts,
// which is written by Scalesoft <https://github.com/Scalesoft> and licensed under the MIT license: // which is written by Scalesoft <https://github.com/Scalesoft> and licensed under the MIT license:
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights // in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions: // furnished to do so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software. // copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -100,6 +100,7 @@ declare namespace EasyMDE {
lineWrapping?: boolean; lineWrapping?: boolean;
parsingConfig?: ParsingOptions; parsingConfig?: ParsingOptions;
placeholder?: string; placeholder?: string;
previewClass?: string | ReadonlyArray<string>;
previewRender?: (markdownPlaintext: string, previewElement: HTMLElement) => string; previewRender?: (markdownPlaintext: string, previewElement: HTMLElement) => string;
promptURLs?: boolean; promptURLs?: boolean;
renderingConfig?: RenderingOptions; renderingConfig?: RenderingOptions;

Loading…
Cancel
Save