diff --git a/README.md b/README.md index 451c3c0..4af2687 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ easyMDE.value('New input for **EasyMDE**'); - **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. +- **previewImagesInEditor**: - EasyMDE will show preview of images, `true` by default, use `false` to disable. - **insertTexts**: Customize how certain buttons that insert text behave. Takes an array with two elements. The first element will be the text inserted before the cursor or highlight, and the second element will be inserted after. For example, this is the default link value: `["[", "](http://)"]`. - horizontalRule - image @@ -471,6 +472,8 @@ easyMDE.toTextArea(); easyMDE = null; ``` +If you need to remove installed listeners (when editor not needed anymore), call `easyMDE.cleanup()` + ### Useful methods diff --git a/src/css/easymde.css b/src/css/easymde.css index c1ec62c..ddd3c00 100644 --- a/src/css/easymde.css +++ b/src/css/easymde.css @@ -373,3 +373,16 @@ .easymde-dropdown:focus .easymde-dropdown-content { display: block; } + +span[data-img-src]::before{ + content: ''; + background-image: var(--bg-image); + display: block; + max-height: 100%; + max-width: 100%; + background-size: contain; + height: 0; + padding-top: var(--height); + width: var(--width); + background-repeat: no-repeat; +} \ No newline at end of file diff --git a/src/js/easymde.js b/src/js/easymde.js index 620920b..f04076a 100644 --- a/src/js/easymde.js +++ b/src/js/easymde.js @@ -1969,13 +1969,14 @@ EasyMDE.prototype.render = function (el) { if (cm.getOption('fullScreen')) toggleFullScreen(self); }; - document.addEventListener('keydown', function (e) { + this.documentOnKeyDown = function (e) { e = e || window.event; if (e.keyCode == 27) { if (self.codemirror.getOption('fullScreen')) toggleFullScreen(self); } - }, false); + }; + document.addEventListener('keydown', this.documentOnKeyDown, false); var mode, backdrop; if (options.spellChecker !== false) { @@ -2057,11 +2058,59 @@ EasyMDE.prototype.render = function (el) { }, self.options.autosave.submit_delay || self.options.autosave.delay || 1000); }); } + - this.gui.sideBySide = this.createSideBySide(); + function handleImages() { + if (options.previewImagesInEditor === false) { + return; + } + function calcHeight(naturalWidth, naturalHeight) { + var height; + var viewportWidth = window.getComputedStyle(document.querySelector('.CodeMirror-sizer')).width.replace('px', ''); + if (naturalWidth < viewportWidth) { + height = naturalHeight + 'px'; + } else { + height = (naturalHeight / naturalWidth * 100) + '%'; + } + return height; + } + easyMDEContainer.querySelectorAll('.cm-formatting-image').forEach(function(e) { + var parentEl = e.parentElement; + if (!parentEl.hasAttribute('data-img-src')) { + var srcAttr = parentEl.innerText.match('\\((.*)\\)'); // might require better parsing according to markdown spec + if (srcAttr && srcAttr.length >= 2) { + var img = document.createElement('img'); + img.onload = function() { + parentEl.setAttribute('data-img-src', srcAttr[1]); + parentEl.setAttribute('data-img-width', img.naturalWidth); + parentEl.setAttribute('data-img-height', img.naturalHeight); + parentEl.setAttribute('style', '--bg-image:url('+srcAttr[1]+');--width:'+img.naturalWidth+'px;--height:'+calcHeight(img.naturalWidth, img.naturalHeight)); + }; + img.src = srcAttr[1]; + } + } else { + // handle resizes case + var src = parentEl.getAttribute('data-img-src'); + var naturalWidth = +parentEl.getAttribute('data-img-width'); + var naturalHeight = +parentEl.getAttribute('data-img-height'); + parentEl.setAttribute('style', '--bg-image:url('+src+');--width:'+naturalWidth+'px;--height:'+calcHeight(naturalWidth, naturalHeight)); + } + }); + } + this.codemirror.on('update', function () { + handleImages(); + }); - this._rendered = this.element; + + + this.onWindowResize = function() { + handleImages(); + }; + window.addEventListener('resize', this.onWindowResize, true); + + this.gui.sideBySide = this.createSideBySide(); + this._rendered = this.element; // Fixes CodeMirror bug (#344) var temp_cm = this.codemirror; @@ -2070,6 +2119,11 @@ EasyMDE.prototype.render = function (el) { }.bind(temp_cm), 0); }; +EasyMDE.prototype.cleanup = function () { + window.removeEventListener(this.onWindowResize); + document.removeEventListener('keydown', this.documentOnKeyDown); +}; + // 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') {