Compare commits

...

261 Commits

Author SHA1 Message Date
Jeroen Akkerman a6b121f2e6
Merge pull request #592 from p1gp1g/fix/image-processing
Avoid processing many times the same image
4 days ago
Jeroen Akkerman 65dfecf484
Merge pull request #591 from p1gp1g/fix/relative-img-url
Fix relative image url fetched from stylesheet domain
4 days ago
S1m 97bf9ce8fd Avoid processing many times the same image
Cache img key during processing to avoid having to process it
thousands of times
1 week ago
S1m 9b420ac103 Fix relative image url fetched from stylesheet domain
Partial URLs are interpreted relative to the source of
the style sheet, not relative to the document
https://www.w3.org/TR/CSS1/
1 week ago
Jeroen Akkerman f039bae67f
Merge pull request #573 from robinvandernoord/custom-image-input-name-option
Allow setting a custom `name` for the upload-image input
6 months ago
Robin van der Noord c68bdf148a
Allow setting a custom `name` for the upload-image input 6 months ago
Jeroen Akkerman 35587a9477 Update dependencies, fixes #562 9 months ago
Jeroen Akkerman d9ab397b88
Update demo URL
fixes #526
1 year ago
Jeroen Akkerman abead2a068
Update build status badge 1 year ago
Jeroen Akkerman c25adab400
Merge pull request #519 from borodean/update-status-bar-typing 1 year ago
Jeroen Akkerman a49e867930
Merge pull request #520 from borodean/upload-image-typing 1 year ago
Vadym Borodin cb5564e1b2 Expose the `"upload-image"` variant for `ToolbarButton` 1 year ago
Vadym Borodin fbc181f5c8 Expose the `updateStatusBar` type 1 year ago
Jeroen akkerman 041594ae4a 2.18.0 2 years ago
Jeroen akkerman 6ab32d9fd6 Update changelog for 2.18.0 2 years ago
Jeroen akkerman 950f689dc7 Update codemirror 2 years ago
Jeroen akkerman 6560950b65 Update workflow file 2 years ago
Jeroen akkerman f60c9b24c5 Update dependencies 2 years ago
Jeroen akkerman 4b48564730 Revert example html 2 years ago
Jeroen akkerman d26b4e399b Add toolbarButtonClassPrefix option
Fixes #493
2 years ago
Jeroen akkerman 84aafddd92 Add extra typing tests for previewRender 2 years ago
Jeroen akkerman 4a73c911d0 2.17.0 2 years ago
Jeroen akkerman 086e73b835 Update changelog for 2.17.0 2 years ago
Jeroen akkerman aa2f225340 Add past merges to README 2 years ago
Jeroen akkerman 0062ba38e1 Update dependencies 2 years ago
Jeroen akkerman f8a66b120b Edit regex pattern for Safari browser, fixes #478 2 years ago
Jeroen Akkerman b4c55d9075
Merge pull request #471 from LevitatingOrange/detachedPreviewRendering 2 years ago
Jeroen Akkerman c27f5d1d23
Merge pull request #492 from vanillajonathan/patch-1 2 years ago
Jonathan f7b4fbfda5
Add support for Header size 4, 5, 6 2 years ago
Jeroen Akkerman d22fd40625
Merge pull request #488 from LoyalPotato/master 2 years ago
David Bazílio Ribeiro 9ddbc4a585 Fix type for hideIcons 2 years ago
Jeroen akkerman 03f018a472 Migrate cypress files 2 years ago
Jeroen akkerman 9232608bf3 Fix changelog 2 years ago
Jeroen akkerman 2930abdd50 Update dependencies 2 years ago
Jeroen Akkerman b347a911c1
Merge pull request #486 from hlf20010508/master 2 years ago
Jeroen Akkerman 3e653dc900
Merge pull request #484 from kicksent/patch-1
Fix typo in readme
2 years ago
L-ING acbed01b34
Add missed "upload-image" icon 2 years ago
Nick Trierweiler ef827ba61f
Fix typo in readme
This is meant to be "italic" not "italics" which will render an empty icon here. The docs specify this as well and I tested locally while working through implementing this on a project.
2 years ago
Jeroen Akkerman 37561e4458
Merge pull request #479 from hackerwins/fix-invalid-icons 2 years ago
hackerwins 03fec127eb Fix invalid icons 2 years ago
Jeroen Akkerman 4d065c361e
Merge pull request #454 from vanillajonathan/patch-8
Refactor into using a map for icon classes
2 years ago
Jonathan 78fcda535d
Update easymde.js 2 years ago
Jeroen Akkerman c84af4c3ed Fix hyperlink doubling
Closes #25
Closes #95
Closes #281
2 years ago
Jeroen Akkerman c311b7b8da Merge branch 'master' of https://github.com/Ionaru/easy-markdown-editor 2 years ago
Jeroen Akkerman 3d6d56edef
Merge pull request #467 from vanillajonathan/patch-1
Use classList.add and classList.remove
2 years ago
Lennart Vogelsang 67f75535ad
Updated documentation 2 years ago
Lennart Vogelsang 8295aa6a5a
Changed: ignore output of previewRender if it is null 2 years ago
Jeroen Akkerman 7338ddb6e3 Replace remaining className usages 2 years ago
Jeroen Akkerman 96a5aac921 Add testing on Node.js 18 2 years ago
Jeroen Akkerman 0c31e06928 Update dependencies 2 years ago
Jonathan 23f241bd47
Use classList.add and classList.remove 2 years ago
Jonathan fc839e8dc8
Update README.md 2 years ago
Jonathan 0eab3e11e8
Update easymde.js 2 years ago
Jeroen Akkerman e4610b3763
Merge pull request #452 from vanillajonathan/patch-4
Use Responsive Font Sizes
2 years ago
Jeroen Akkerman 24feffcba6
Merge pull request #464 from vanillajonathan/patch-1
Add ARIA role=application
2 years ago
Jeroen Akkerman e57c16bc5c
Merge pull request #461 from vanillajonathan/patch-12 2 years ago
Jeroen Akkerman eb51f0fe53
Merge pull request #466 from vanillajonathan/patch-5
Fix inconsistent border color
2 years ago
Jonathan 554112b05f
Update easymde.css 2 years ago
Jonathan 2972b280a5
Update easymde.css 2 years ago
Jonathan eee701ef86
Update easymde.js 2 years ago
Jonathan 7f9ba6abc8
Fix inconsistent border color 2 years ago
Jeroen Akkerman 3895e0a607
Merge pull request #451 from vanillajonathan/patch-7
Add keyboard shortcuts for headings
2 years ago
Jonathan b675e611a4
Update easymde.css 2 years ago
Jonathan 3cc99e47ae
Add ARIA role=application 2 years ago
Jonathan f4a02e39a9
Update README.md 2 years ago
Jonathan 4714577c36
Update easymde.js 2 years ago
Jeroen Akkerman 45e0f36685
Merge pull request #463 from vanillajonathan/patch-1
Add ARIA attribute to button
2 years ago
Jonathan cd9bbe7939
Add ARIA attribute to button 2 years ago
Jonathan 5a4af7e38a
Update easymde.css 2 years ago
Jeroen Akkerman 611aa50443
Merge pull request #455 from vanillajonathan/patch-9
Set role attribute on the toolbar
2 years ago
Jeroen Akkerman 68d33ec2c1
Merge pull request #459 from vanillajonathan/patch-2
Accept APNG for image uploads
2 years ago
Jonathan 855a5d72f5
Update README.md 2 years ago
Jonathan 38717daffe
Add support for text buttons 2 years ago
Jonathan 146a5e3fb1
Accept APNG for image uploads 2 years ago
Jeroen Akkerman c311bfa6b0
Merge pull request #458 from vanillajonathan/patch-2
Accept AVIF for image uploads
2 years ago
Jonathan b31cf2bf7c
Accept AVIF for image uploads 2 years ago
Jonathan bed6b493c8
Update easymde.js 2 years ago
Jeroen Akkerman 2b178671ca
Merge pull request #449 from vanillajonathan/patch-2
Add actions for header size 4, 5 and 6
2 years ago
Jonathan 2666001eda
Set role attribute on the toolbar 2 years ago
Jonathan 21fda66d3d
Update easymde.js 2 years ago
Jonathan 9d74ea296c
Refactor into using a map for icon classes 2 years ago
Jonathan 1706b4b0cf
Use Responsive Font Sizes 2 years ago
Jeroen Akkerman aca4b5c816
Merge pull request #450 from vanillajonathan/patch-6
Accept GIF for image uploads
2 years ago
Jonathan 757d5eb729
Add keyboard shortcuts for headings 2 years ago
Jonathan be1d994322
Update easymde.js 2 years ago
Jonathan 0dd2f99f9d
Accept GIF for image uploads 2 years ago
Jonathan 9a57f00d92
Update easymde.js 2 years ago
Jonathan 332cf61086
Add header size 4, 5 and 6 2 years ago
Jonathan c1071c8539
Add header size 4, 5 and 6 2 years ago
Jeroen Akkerman 16b1de652e Update dependencies 2 years ago
Jeroen Akkerman 8b9cf3e812
Merge pull request #444 from vanillajonathan/patch-2 2 years ago
Jonathan a433f72891
Update README.md
Co-authored-by: Jeroen Akkerman <Jeroen_akkerman1@hotmail.com>
2 years ago
Jonathan 4b3930c4a7
Update README.md 2 years ago
Jeroen Akkerman a7fb5d8f06
Merge pull request #436 from vanillajonathan/patch-2
Add missing undo and redo actions
2 years ago
Jeroen Akkerman 7b4c6dae9e
Merge pull request #438 from vanillajonathan/patch-3
Use <kbd> markup element for keyboard shortcuts
2 years ago
Jeroen Akkerman b6f207d235
Merge pull request #440 from vanillajonathan/patch-5
Fix broken markdown
2 years ago
Jonathan 591e278745
Fix broken markdown 2 years ago
Jonathan 764ce93d59
Use <kbd> markup element for keyboard shortcuts 2 years ago
Jonathan af81424b78
Add missing undo and redo actions 2 years ago
Jeroen Akkerman 3d07f0eb97 Update dependencies 2 years ago
Jeroen Akkerman 16f2dde59d Fix #399 autofocus property 2 years ago
Jeroen Akkerman 57f72bd5ae Merge branch 'master' of https://github.com/Ionaru/simplemde-markdown-editor 2 years ago
Jeroen Akkerman 8765cf197b
Merge pull request #417 from sghoweri/patch-1 2 years ago
Salem Cobalt bf9b0108d7
Handle Webp Image Uploads
With this fix, uploaded WebP images render as links in the markdown (vs images).
2 years ago
Jeroen Akkerman f283f76f5c Update dependencies 2 years ago
Jeroen Akkerman a1ad87986d Merge branch 'master' of https://github.com/Ionaru/simplemde-markdown-editor 2 years ago
Jeroen Akkerman 76fda35bf9
Merge pull request #411 from diego-gw/imagePreviewHandler 2 years ago
Jeroen Akkerman 1f30a11773 Add changelog entry 2 years ago
Diego Garcia Weber aa711787b2 clarified readme description of parameter, removed extra parantheses from type 2 years ago
Jeroen Akkerman 853efd8a5e Update dependencies 2 years ago
Diego Garcia Weber ed196be5a0 added option to readme, imagesPreviewHandler to types and defensive check that the handler provided by the user returns a string 2 years ago
Diego Garcia Weber d8fa00e460 Adds the option to add a handler for images preview 2 years ago
Jeroen Akkerman f573560bb4 Update dependencies 2 years ago
Jeroen Akkerman a021bdf8ae
Merge pull request #394 from ZsgsDesign/master
Add robust CSRF support and provide default values for CSRF fields
2 years ago
ZsgsDesign aa6fe59e93 fixed default image configuration typo 2 years ago
ZsgsDesign 8805c379d8 fixed comment typo for csrf token 2 years ago
ZsgsDesign b0d20adc6e add instances example for imageCSRFToken 2 years ago
ZsgsDesign f3dca2e82a add robust CSRF support and provide default values for CSRF fields 2 years ago
Jeroen Akkerman 50d3680017
Merge pull request #393 from Zignature/escape-url-via-prompt
Fix #373 Encode and escape URLs entered via prompt
2 years ago
Jeroen Akkerman 81ec7780bc Update changelog 2 years ago
Jeroen Akkerman d8eae5d74c Improve readability of encode/escape functionality 2 years ago
Jeroen Akkerman 0c2cf4cd51 Add tests for url prompts 2 years ago
Zignature 16545eb0e1 Made escaping prompt URLs automatic instead of optional again 2 years ago
Zignature 47f1e4f892 Updated readme and easymde.d.ts to reflect escapePrompURLs option 2 years ago
Zignature c174b6f149 Changed function name escapeURI to escapedPromptURL and option escapeURLs to option escapePromptURLs 2 years ago
Zignature 33489ab616 URL encoding and escaping for JS prompt URLs
- URL encoding and escaping added for JS prompt entered URLs
- added option escapeURLs (boolean)
2 years ago
Zignature 5d0294f5f5 Fix issue #373 problems in urls with special characters
Added function to escape URLs entered via JS prompt.

It's a partial fix because people cannot be stopped entering URLs manually and forgetting to escape them.
2 years ago
Jeroen Akkerman 4fb35f2758 2.16.1 2 years ago
Jeroen Akkerman d0116608e6 Update changelog for 2.16.1 2 years ago
Jeroen Akkerman 6159ed1383 Update marked to resolve security vulnerability 2 years ago
Jeroen Akkerman a56badd0dc Add test for markdown rendering 2 years ago
Jeroen Akkerman 24d86491da Fix incorrect initial line and column count 2 years ago
Jeroen Akkerman 56532f9ce4 Add cypress tests 2 years ago
Jeroen Akkerman 722fb61ed2 Remove old travis build status badge 2 years ago
Jeroen Akkerman 33a4043dbb Update build status badge 2 years ago
Jeroen Akkerman 75fe53f062 2.16.0 2 years ago
Jeroen Akkerman 384655f968 Update changelog for 2.16.0 2 years ago
Jeroen Akkerman 6445f3c2d9
Merge pull request #388 from Zignature/options-toolbarbutton-attributes
Fix for issue #380 Custom attributes for toolbar buttons
2 years ago
Jeroen Akkerman 7a2373eae5 Update changelog 2 years ago
Jeroen Akkerman 4ddb5b8e1b Add toolbar button attributes to type declaration 2 years ago
Jeroen Akkerman 98d9049728 Move adding custom attributes above all others 2 years ago
Jeroen Akkerman 565c42e0ff Add hasOwnProperty check 2 years ago
Jeroen Akkerman 1c656d5712 Merge branch 'master' into options-toolbarbutton-attributes 2 years ago
Jeroen Akkerman c1da7424e9
Merge pull request #389 from Zignature/options-liststyle
Fix for issue #386 Show '-' instead of '*' for unordered list
2 years ago
Jeroen Akkerman e2db3c6946 Attempt at improving submenus in Safari for #362 2 years ago
Jeroen Akkerman 267db2dbe3 Update changelog 2 years ago
Jeroen Akkerman 9862ecf98c Add unorderedListStyle option to type declaration 2 years ago
Zignature 2cdc11848a Requested changes applied 2 years ago
Zignature 5df842b630 Fix for issue #386 Show '-' instead of '*' for unordered list
Added unorderedListStyle to the options
2 years ago
Zignature a9d9993dae Fix for issue #380 Custom attributes for toolbar buttons
Added "attributes" option to custom toolbar button
2 years ago
Jeroen Akkerman 59a676bc8a
Merge pull request #384 from Zignature/ZignatureEasyMDE
Fix #381 Accurate line and column count in status bar
2 years ago
Zignature 2936fc3383 Accurate line and column count in status bar
Both Line and column (character) count are increased by 1.

This fixes issue #381
2 years ago
Zignature a7170b9392 Fix issue #381 2 years ago
Jeroen Akkerman 598821b6bb Add typings and tests for 'direction' option 3 years ago
Jeroen Akkerman de1cd3b293 Update changelog for 2.16.0 3 years ago
Jeroen Akkerman d27adc6a16 Update dependencies 3 years ago
Jeroen Akkerman c15c699a52 Update changelog for PR #364 3 years ago
Jeroen Akkerman 8ad896fb40
Merge pull request #364 from robjean9/master
update easymde.css, fix issue #362
3 years ago
Robson Jean Penteado b640429f19 fix issue #362 3 years ago
Robson Jean Penteado 8ef68936b0 update easymde.css, fix issue #362 3 years ago
Jeroen Akkerman f004c2d0c3 More small README improvements 3 years ago
Jeroen Akkerman 551c84bc01 Fix indenting and some leftover old JS 3 years ago
Jeroen Akkerman 86e40bcf4a Update README with some more modern JS 3 years ago
Jeroen Akkerman 35b42c404a Update changelog 3 years ago
Jeroen Akkerman 42304e8a87 Update editorconfig and automatic code format 3 years ago
Jeroen Akkerman dc38624378 Update dependencies 3 years ago
Jeroen Akkerman c24dd01880 Drop testing support on older Node.js versions 3 years ago
Jeroen Akkerman b364a6095a Use Github Actions instead of Tavis 3 years ago
Jeroen Akkerman cda237031f
Merge pull request #357 from ukjinjang/fix/compare_image_extension
Convert media file extension to lowercase before check if image
3 years ago
Jeroen Akkerman 534e2cadee
Merge pull request #358 from souljuse/master
Add support for RTL languages
3 years ago
Irene Oppo aafd40f35b Add direction option to README 3 years ago
Irene Oppo 53223c4de0 Support rtl languages by adding a direction option 3 years ago
Uk-Jin Jang b121795887 fix: convert media file extension to lowercase before check if image 3 years ago
Jeroen Akkerman 0f559258c5
Merge pull request #338 from mrlugilugi/fix-error-formatting-asterisks-as-unordered-list
fix: Formatting asterisks divided by space results in console error #337
3 years ago
Jeroen Akkerman 3e403d9712
Merge pull request #339 from CamilleDrapier/add-cleanup-to-ts
Add the cleanup function to TypeScript definition
3 years ago
Camille Drapier cb351333d1 Add cleanup function to TypeScript definition 3 years ago
mrlugilugi f52f9807a2
fix: Escaping asterisk to produce valid RegEx 3 years ago
Jeroen Akkerman c1d35b04c5
Merge pull request #333 from smundro/custom-spellchecker
Allow for specifying a custom spell-checker
3 years ago
Steve 737aa13709 add a dash 3 years ago
Steve 038a9204b4 Allow for specifying a custom spell-checker for EasyMDE 3 years ago
Jeroen Akkerman dbab7e95e7 2.15.0 3 years ago
Jeroen Akkerman 51d496aea6 Update changelog for 2.15.0 3 years ago
Jeroen Akkerman 735d31fb29 Update dependencies 3 years ago
Jeroen Akkerman ebcc835ee9 Update changelog 3 years ago
Jeroen Akkerman c58eb54379
Merge pull request #322 from marekdedic/320-fix
Exposing types as non-dev dependencies
3 years ago
Marek Dědič 529c7bf04d
Fixes #320 3 years ago
Jeroen Akkerman e3480c2f60 Update dependencies 3 years ago
Jeroen Akkerman fc0ecfa77e
Merge pull request #313 from wwsalmon/absolute-image-paths
Absolute image paths
3 years ago
Jeroen Akkerman 113c5b45b1
Merge pull request #316 from smundro/bugfix-fullscreen-sidebyside-handle
Bugfix: Correctly keep preview active during fullscreen-toggle
3 years ago
Steve b61fe7945a Add simple class handling utiltity to DRY adding/removing class names.
Note that this isn't necessary and can be rolled back, but could be used throughout the code to make class handling more clear and consistent.
3 years ago
Steve 82a8e4a8ce restore removed comment 3 years ago
Steve 548229dd1a remove added comment 3 years ago
Steve 40ddcea4e3 remove extra comment updates 3 years ago
Steve d0f69390ce a little comment/cleanup 3 years ago
Steve 1ee8519e50 Unwind all the onlyCleanup stuff and set classes directly. 3 years ago
Steve 4533dd4776 clarify comments in togglePreview 3 years ago
Steve d636eb7407 clean up diff 3 years ago
Steve 7069fd1031 Move from multiple "no-fullscreen" classes to one using inheritance 3 years ago
Steve d76872f4ff undo some comment changes to make diff cleaner 3 years ago
Steve 8ed6cd699e make toggle cleanup flag clearer 3 years ago
Steve 25db654cf0 more code cleanup for readibilty 3 years ago
Steve 8702dd22d0 correct test page title 3 years ago
Steve fa8855e3be code refactoring to improve readability 3 years ago
Steve 61e93a3d53 handle fullscreen toggle consistently by adusting toggleSideBySide 3 years ago
Steve abbec5bde1 bugfix: move sidebyside accessor outside of options check 3 years ago
Samson Zhang 3b755026d6 update readme with imagePathAbsolute option info 3 years ago
Samson Zhang 6e7e8f9b82 add imagePathAbsolute option 3 years ago
Jeroen Akkerman 072176a86e
Merge pull request #311 from deerboy/patch-1
Fixed extension acquisition logic
3 years ago
Daichi Ninomiya c2dbe77615
fix(easymde.js): Fixed extension acquisition logic 3 years ago
Jeroen Akkerman 95b848a825
Merge pull request #308 from ChronosMasterOfAllTime/307-fix-toolbaricon-typing
Resolve Issue #307 - add optional icon field to ToolbarIcon interface in easymde.d.ts
3 years ago
ChronosMasterOfAllTime 6527a311a3 #307 - add optional icon field to ToolbarIcon interface in easymde.d.ts 3 years ago
Jeroen Akkerman 8fa54c496f Fix changelog version link 3 years ago
Jeroen Akkerman fdc9ce4935 2.14.0 3 years ago
Jeroen Akkerman 0ac130306d Update changelog for 2.14.0 3 years ago
Jeroen Akkerman 59b6b0719e Update dependencies 3 years ago
Jeroen Akkerman bc17533def
Merge pull request #293 from sn3p/toolbar-top-and-bottom-padding
Add toolbar top and bottom padding
3 years ago
Jeroen Akkerman 0241584921
Merge pull request #298 from Ionaru/dependabot/npm_and_yarn/marked-2.0.0
Bump marked from 1.2.6 to 2.0.0
3 years ago
dependabot[bot] dd449cf9a7
Bump marked from 1.2.6 to 2.0.0
Bumps [marked](https://github.com/markedjs/marked) from 1.2.6 to 2.0.0.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/release.config.js)
- [Commits](https://github.com/markedjs/marked/compare/v1.2.6...v2.0.0)

Signed-off-by: dependabot[bot] <support@github.com>
3 years ago
Matthijs Kuiper ec94037ac2 Add toolbar top and bottom padding 3 years ago
Jeroen Akkerman 0ff81e89a6
Merge pull request #286 from smundro/retain-preview-on-fullscreen-toggle
don't toggle preview if sideBySideFullscreen is false
3 years ago
Jeroen Akkerman 65f66138c0
Merge pull request #285 from Situphen/dropdown
Use visibility:hidden; instead of display:none; for the dropdown menu
3 years ago
Jeroen Akkerman 3f90b9fe72
Merge pull request #284 from Fanvadar/fix-spellchecker
Fix spell checker
3 years ago
Steve 480145264a don't toggle preview if sideBySideFullscreen is false 3 years ago
Situphen a070698b34 Use visibility:hidden; instead of display:none; for the dropdown menu 3 years ago
Alexander Wilson 7b0411fd79 Fix spell checker 4 years ago
Jeroen Akkerman 1386fb0319
Merge pull request #280 from emirotin/patch-1
Fix #278
4 years ago
Jeroen Akkerman 80e2fc1bbd Merge remote-tracking branch 'origin/master' 4 years ago
Jeroen Akkerman dbe3872afb Update demo website link in README
Closes #283
4 years ago
Eugene Mirotin b7d5af36c8
Fix #278
Remove erroneous and unneeded call to window.removeEventListener
4 years ago
Jeroen Akkerman 67592df8bf
Merge pull request #277 from Juupaa/drag_and_drop_link
Drag and drop a file checks the extension to either create an image or link
4 years ago
Marc-Etienne Trudel db348fe44b
wip 4 years ago
Jeroen Akkerman 3b6402b3e8 Update dependencies 4 years ago
Jeroen Akkerman a7f4262166 Update changelog for PR #272 4 years ago
Jeroen Akkerman 6306b96cf7
Merge pull request #272 from joahim/master
Fix the sideBySideFullscreen=false + status=false bug
4 years ago
Joh Dokler c428a37ee3 Fix additional edge case for the sideBySideFullscreen=false + status=false bug 4 years ago
Joh Dokler 2a904b24ab Fix the sideBySideFullscreen=false + status=false bug 4 years ago
Jeroen Akkerman f286a6bae5
Merge pull request #250 from danice/scrollbar-styles
Include Codemirror scrollbar style property
4 years ago
Jeroen Akkerman 6209e53c69
Merge pull request #253 from devforth/master
Bugfixes for preview images in editor
4 years ago
Jeroen Akkerman 62b95316b2 2.13.0 4 years ago
Jeroen Akkerman 7efef3b003 Update changelog for 2.13.0 4 years ago
Jeroen Akkerman 9a2e12a4e9 Update dependencies 4 years ago
Jeroen Akkerman e087158074
Merge pull request #267 from nhymxu/patch-1
Allow modify lineNumbers via config options
4 years ago
Jeroen Akkerman b06d1fe67f Add documentation and typings 4 years ago
Dung Nguyen 65186e4537
Allow modify lineNumbers via config options 4 years ago
Jeroen Akkerman 11f805f0b5 Fix CSS scoping issues (#252) 4 years ago
Jeroen Akkerman 21d51a053b Updated dependencies 4 years ago
Jeroen Akkerman f65d2a7cc9 Updated changelog for PR #249 4 years ago
Jeroen Akkerman 70f3512120
Merge pull request #249 from mbolli/codemirror-autorefresh
include codemirror autorefresh addon
4 years ago
Jeroen Akkerman 6d173d0024
Update CONTRIBUTING.md 4 years ago
dani 29d2c6c5be fix for undefined scrollbar style 4 years ago
Ivan Borshchov 0c9be85cd7 fix not option 4 years ago
Ivan Borshchov edfeb87653 previewImagesInEditor doc improve 4 years ago
Ivan Borshchov dba3201c79 fix cursor preceise positioning when content with images are loaded into editor, show preview only for images on separate lines (not inlines) 4 years ago
Jeroen Akkerman 23c17b88b4 2.12.1 4 years ago
Jeroen Akkerman 1e41667ec6 Update changelog for 2.12.1 4 years ago
Jeroen Akkerman 6e48fc293c Set `previewImagesInEditor` option to `false` by default
Fixes #251
4 years ago
Daniel Calbet c696922fe1 changelog: include new scrollbarStyle option 4 years ago
Daniel Calbet 3517348ef7 scrollbar style in options type 4 years ago
Daniel Calbet eabb23fd3e using scrollbarStyle option 4 years ago
Michael Bolli 206f02272b changelog: include new autoRefresh option 4 years ago
Michael Bolli c780d5af38 include codemirror autorefresh addon 4 years ago

@ -1,9 +1,17 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=4
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_size = 4
indent_style = space
trim_trailing_whitespace = true
[*.yaml]
indent_size = 2
[*.{yml,yaml}]
indent_size=2
[*.md]
max_line_length = off
trim_trailing_whitespace = false

@ -1,4 +1,5 @@
{
"root": true,
"rules": {
"strict": 0,
"no-console": 0,
@ -10,11 +11,17 @@
"error",
"always"
],
"comma-dangle": ["error", "always-multiline"]
"comma-dangle": [
"error",
"always-multiline"
]
},
"env": {
"browser": true,
"node": true
},
"parserOptions": {
"ecmaVersion": 2018
},
"extends": "eslint:recommended"
}

@ -23,7 +23,7 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
** Version information **
**Version information**
- OS: [e.g. Windows, MacOS]
- Browser: [e.g. Chrome 72]
- EasyMDE version: [e.g. 2.5.1]

@ -0,0 +1,95 @@
name: Test & Deploy
on:
workflow_dispatch:
push:
branches:
- master
tags:
- '*'
pull_request:
branches:
- master
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: current
- uses: actions/checkout@v3
- run: npm audit --omit=dev
test:
needs: [ audit ]
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ '14', '16', '18' ]
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- uses: actions/checkout@v3
- run: npm ci
- name: Test
run: npm test
- uses: actions/upload-artifact@v3
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
retention-days: 7
- uses: actions/upload-artifact@v3
if: always()
with:
name: cypress-videos
path: cypress/videos
retention-days: 7
deploy:
needs: [ test ]
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- uses: actions/setup-node@v3
with:
node-version: current
- uses: actions/checkout@v3
- run: npm ci
- name: Deploy @latest version to npm
if: startsWith(github.ref, 'refs/tags/')
uses: JS-DevTools/npm-publish@v1
with:
token: ${{ secrets.NPM_TOKEN }}
- name: Update @next version
if: startsWith(github.ref, 'refs/heads/')
run: npm version prerelease --no-git-tag-version --preid "$GITHUB_RUN_NUMBER"
- name: Deploy @next version to npm
if: startsWith(github.ref, 'refs/heads/')
uses: JS-DevTools/npm-publish@v1
with:
tag: next
token: ${{ secrets.NPM_TOKEN }}
check-version: false

4
.gitignore vendored

@ -11,3 +11,7 @@ node_modules/
.idea/
.vscode/
dev_test/
# Test artifacts
cypress/screenshots
cypress/videos

@ -1,33 +0,0 @@
language: node_js
node_js:
- '14' # EOL: April 2023
- '12' # EOL: April 2022
- '11' # EOL: June 2019
- '10' # EOL: April 2021
- '8' # EOL: December 2019
jobs:
include:
- stage: deploy
node_js: "lts/*"
script: skip
before_deploy: if [ "$TRAVIS_BRANCH" = master ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then npm version prerelease --no-git-tag-version --preid "$TRAVIS_BUILD_NUMBER"; fi
deploy:
- provider: npm
email: info@saturnserver.org
api_key:
secure: rp4P11u0Vvz6iTkC1uj9LfNVOJASnTjffpqpe9lhuC/php7+fdoYvZ4e1EwKj2RVbi7YNqZE6w+Y6fsxZk72N4RGVO6HROm6gNv2wl+qk0B1XwciONO9y5FhTcdZrsq5Vx5WdoZThs5CSkXpvtHiavAnAt1ufYjqKGBZOENdxJ40kkn9WdQG2WvG7iZWDlDpDoqof2uO9k89d2UuTG5DKAoMpN+4UH0Fr0gV0u11IcBeH7rlSo2btlMaMsSO9Nb10Zf1rC0USHfyrui/BKvVGeRh7FASYrHwjqt4bwqzKZlP5bZ4zGIPMYXXsGLcidxIvSsNIRp7cgkWvsywe8cIi5XzaM48afWsbMUfMgXi9BDNjK7vBiuPBnGWYS3ylJZn/7SvMuqsoj4De5GWrCJ5pTsEKD5yw5+iqQv7v2ZYhuN7/tTSoEy/BOMdN43zWquJp57LXkyFQ9esGoI0bfeYojV2BvcpwY/UFS27e/9bH+RBlXsLfP0kEtosVGZ6i3AuUKtsYOxo4QZSI4yHtP7fKsoCoJIvpW3hcWjrnI8N7IC18/KihsUByuMgDgTTXXtDKxLbNVjbiVvFJeuClwe1oc1uusY1v/EkNpGDFZX5zFEVv3zC76NaLB75kCUN3gGC0RRFk0J9i3k8qa42TLjbOqvxgRxOEtVeRxowBNrymIQ=
tag: next
skip_cleanup: true
on:
branch: master
repo: Ionaru/easy-markdown-editor
- provider: npm
email: info@saturnserver.org
api_key:
secure: rp4P11u0Vvz6iTkC1uj9LfNVOJASnTjffpqpe9lhuC/php7+fdoYvZ4e1EwKj2RVbi7YNqZE6w+Y6fsxZk72N4RGVO6HROm6gNv2wl+qk0B1XwciONO9y5FhTcdZrsq5Vx5WdoZThs5CSkXpvtHiavAnAt1ufYjqKGBZOENdxJ40kkn9WdQG2WvG7iZWDlDpDoqof2uO9k89d2UuTG5DKAoMpN+4UH0Fr0gV0u11IcBeH7rlSo2btlMaMsSO9Nb10Zf1rC0USHfyrui/BKvVGeRh7FASYrHwjqt4bwqzKZlP5bZ4zGIPMYXXsGLcidxIvSsNIRp7cgkWvsywe8cIi5XzaM48afWsbMUfMgXi9BDNjK7vBiuPBnGWYS3ylJZn/7SvMuqsoj4De5GWrCJ5pTsEKD5yw5+iqQv7v2ZYhuN7/tTSoEy/BOMdN43zWquJp57LXkyFQ9esGoI0bfeYojV2BvcpwY/UFS27e/9bH+RBlXsLfP0kEtosVGZ6i3AuUKtsYOxo4QZSI4yHtP7fKsoCoJIvpW3hcWjrnI8N7IC18/KihsUByuMgDgTTXXtDKxLbNVjbiVvFJeuClwe1oc1uusY1v/EkNpGDFZX5zFEVv3zC76NaLB75kCUN3gGC0RRFk0J9i3k8qa42TLjbOqvxgRxOEtVeRxowBNrymIQ=
skip_cleanup: true
on:
branch: master
repo: Ionaru/easy-markdown-editor
tags: true

@ -1,10 +1,98 @@
# EasyMDE Changelog
All notable changes to easymde 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
<!--## [Unreleased]-->
<!-- ## [Unreleased] -->
## [2.18.0] - 2022-09-20
### Added
- `toolbarButtonClassPrefix` option to resolve conflicts with Bootstrap classes ([#493]).
## [2.17.0] - 2022-08-20
### Added
- Improved CSRF support for uploading images (Thanks to [@ZsgsDesign], [#394]).
- Option to register an image preview handler: `imagesPreviewHandler` (Thanks to [@diego-gw], [#411]).
- Support for `.webp` image formats (Thanks to [@sghoweri], [#417]).
- `toggleHeading` methods for headings 4, 5 and 6 (Thanks to [@vanillajonathan], [#449] and [#492]).
- Support for `.gif`, `.avif` and `.apng` image formats (Thanks to [@vanillajonathan], [#450], [#458] and [#459]).
- Keyboard shortcuts for `toggleHeading` methods (Thanks to [@vanillajonathan], [#451]).
- `iconClassMap` option to specify icon class names for toolbar buttons (Thanks to [@vanillajonathan], [#454]).
- `role="toolbar"` on the toolbar element (Thanks to [@vanillajonathan], [#455]).
- Support for text buttons in the toolbar (Thanks to [@vanillajonathan], [#461]).
- `aria-label` attribute for toolbar buttons (uses the `title` option) (Thanks to [@vanillajonathan], [#463]).
- `role="application"` on the editor container element (Thanks to [@vanillajonathan], [#464]).
- Option to not overwrite the preview HTML by returning `null` from `previewRender` (Thanks to [@LevitatingOrange], [#471]).
### Fixed
- Hyperlink doubling (Thanks to [@danielok1993], [#95]).
- URLs with certain characters entered through prompts causing invalid markdown (Thanks to [@Zignature], [#393]).
- Autofocus option not working properly ([#399]).
- Inconsistent border colour (Thanks to [@vanillajonathan], [#466]).
- Invalid regex on Safari browsers ([#478])
- `hideIcons` option type (Thanks to [@LoyalPotato], [#488]).
### Changed
- Editor now uses responsive font sizes (Thanks to [@vanillajonathan], [#452]).
### Documentation
- Added several improvements to README (Thanks to [@vanillajonathan], [#436], [#438], [#440], [#444]).
- Fixed typo in README (Thanks to [@kicksent], [#484]).
- Added missing icon for `upload-image` in README (Thanks to [@hlf20010508], [#486]).
## [2.16.1] - 2022-01-14
### Fixed
- Incorrect initial line and column count in status bar.
- Security issue in `marked` dependency.
## [2.16.0] - 2022-01-11
### Added
- `direction` option to enable RTL mode (Thanks to [@souljuse], [#358]).
- `attributes` option to add custom attributes to toolbar buttons (Thanks to [@Zignature], [#388]).
- `unorderedListStyle` option to change the character used for unordered lists (Thanks to [@Zignature], [#389]).
### Fixed
- Image extension detection when extension is uppercase (Thanks to [@ukjinjang], [#357]).
- Submenu actions not working in Chromium Browsers (Thanks to [@Offerel], [@robjean9] and [@kelvinj], [#364]).
- Incorrect line and column count in status bar (Thanks to [@Zignature], [#384]).
## [2.15.0] - 2021-04-22
### Added
- `imagePathAbsolute` option to return the absolute path when uploading an image (Thanks to [@wwsalmon], [#313]).
### Fixed
- `ToolbarIcon` typings, added `icon` (Thanks to [@ChronosMasterOfAllTime], [#308]).
- Image link extension when it was not the last part of the URL (Thanks to [@deerboy], [#311]).
- Preview mode did not stay enabled when toggling to fullscreen (Thanks to [@smundro], [#316]).
- Required typings not being included in `dependencies` (Thanks to [@marekdedic], [#322]).
## [2.14.0] - 2021-02-14
### Added
- The `scrollbarStyle` option to change the style of the scrollbar (Thanks to [@danice], [#250]).
### Fixed
- Issues with images not displaying correctly in the preview screen (Thanks to [@ivictbor], [#253]).
- An error when both `sideBySideFullscreen` and `status` were set to `false` (Thanks to [@joahim], [#272]).
- Editor trying to display non-image files (Thanks to [@Juupaa], [#277])
- Unneeded call to `window.removeEventListener` (Thanks to [@emirotin], [#280])
- Spell checker (Thanks to [@Fanvadar], [#284]).
- Focus issues with toolbar dropdown menus (Thanks to [@Situphen], [#285]).
- Interaction between the `sideBySideFullscreen` and the preview state (Thanks to [@smundro], [#286])
- Refactored strange method of padding the toolbar into regular padding (Thanks to [@sn3p], [#293]).
- Security issue in `marked` dependency (Thanks to [@dependabot], [#298]).
## [2.13.0] - 2020-11-11
### Added
- CodeMirror autorefresh plugin and autoRefresh option (Thanks to [@mbolli], [#249]).
- `lineNumbers` option to display line numbers in the editor (Thanks to [@nhymxu], [#267]).
### Fixed
- CSS scoping issues when the editor is used in combination with other CodeMirror instances ([#252]).
## [2.12.1] - 2020-10-06
### Changed
- Set `previewImagesInEditor` option to `false` by default ([#251]).
## [2.12.0] - 2020-09-29
### Added
- `this` context in imageUploadFunction (Thanks to [@JoshuaLicense], [#225]).
@ -37,9 +125,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Group buttons in drop-down lists by adding a sub-option `children` for the items in the toolbar (Thanks to [@firm1], [#141]).
- `sanitizerFunction` option to allow custom HTML sanitizing in the markdown preview (Thanks to [@adamb70], [#147]).
- Time formatting and custom text options for the autosave message (Thanks to [@dima-bzz], [#170]).
### Changed
- Delay before assuming that submit of the form as failed is `autosave.submit_delay` instead of `autosave.delay` (Thanks to [@Situphen], [#139]).
- Add `watch` task for gulp (Thanks to [@A-312], [#150]).
### Fixed
- Issue with Marked when using IE11 and webpack (Thanks to [@felipefdl], [#169]).
- Updated codemirror to version 5.52.2 (Thanks to [@A-312], [#173]).
@ -167,6 +257,11 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown
- Cursor not always showing in "text" mode over the edit field
<!-- Linked issues -->
[#493]: https://github.com/Ionaru/easy-markdown-editor/issues/493
[#478]: https://github.com/Ionaru/easy-markdown-editor/issues/478
[#399]: https://github.com/Ionaru/easy-markdown-editor/issues/399
[#252]: https://github.com/Ionaru/easy-markdown-editor/issues/252
[#251]: https://github.com/Ionaru/easy-markdown-editor/issues/251
[#239]: https://github.com/Ionaru/easy-markdown-editor/issues/239
[#178]: https://github.com/Ionaru/easy-markdown-editor/issues/178
[#136]: https://github.com/Ionaru/easy-markdown-editor/issues/136
@ -183,6 +278,56 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown
[#9]: https://github.com/Ionaru/easy-markdown-editor/issues/9
<!-- Linked PRs -->
[#492]: https://github.com/Ionaru/easy-markdown-editor/pull/492
[#488]: https://github.com/Ionaru/easy-markdown-editor/pull/488
[#486]: https://github.com/Ionaru/easy-markdown-editor/pull/486
[#484]: https://github.com/Ionaru/easy-markdown-editor/pull/484
[#479]: https://github.com/Ionaru/easy-markdown-editor/pull/479
[#471]: https://github.com/Ionaru/easy-markdown-editor/pull/471
[#467]: https://github.com/Ionaru/easy-markdown-editor/pull/467
[#466]: https://github.com/Ionaru/easy-markdown-editor/pull/466
[#464]: https://github.com/Ionaru/easy-markdown-editor/pull/464
[#463]: https://github.com/Ionaru/easy-markdown-editor/pull/463
[#461]: https://github.com/Ionaru/easy-markdown-editor/pull/461
[#459]: https://github.com/Ionaru/easy-markdown-editor/pull/459
[#458]: https://github.com/Ionaru/easy-markdown-editor/pull/458
[#455]: https://github.com/Ionaru/easy-markdown-editor/pull/455
[#454]: https://github.com/Ionaru/easy-markdown-editor/pull/454
[#452]: https://github.com/Ionaru/easy-markdown-editor/pull/452
[#451]: https://github.com/Ionaru/easy-markdown-editor/pull/451
[#450]: https://github.com/Ionaru/easy-markdown-editor/pull/450
[#449]: https://github.com/Ionaru/easy-markdown-editor/pull/449
[#444]: https://github.com/Ionaru/easy-markdown-editor/pull/444
[#440]: https://github.com/Ionaru/easy-markdown-editor/pull/440
[#438]: https://github.com/Ionaru/easy-markdown-editor/pull/438
[#436]: https://github.com/Ionaru/easy-markdown-editor/pull/436
[#417]: https://github.com/Ionaru/easy-markdown-editor/pull/417
[#411]: https://github.com/Ionaru/easy-markdown-editor/pull/411
[#394]: https://github.com/Ionaru/easy-markdown-editor/pull/394
[#393]: https://github.com/Ionaru/easy-markdown-editor/pull/393
[#389]: https://github.com/Ionaru/easy-markdown-editor/pull/389
[#388]: https://github.com/Ionaru/easy-markdown-editor/pull/388
[#384]: https://github.com/Ionaru/easy-markdown-editor/pull/384
[#364]: https://github.com/Ionaru/easy-markdown-editor/pull/364
[#358]: https://github.com/Ionaru/easy-markdown-editor/pull/358
[#357]: https://github.com/Ionaru/easy-markdown-editor/pull/357
[#322]: https://github.com/Ionaru/easy-markdown-editor/pull/322
[#316]: https://github.com/Ionaru/easy-markdown-editor/pull/316
[#313]: https://github.com/Ionaru/easy-markdown-editor/pull/313
[#311]: https://github.com/Ionaru/easy-markdown-editor/pull/311
[#308]: https://github.com/Ionaru/easy-markdown-editor/pull/308
[#298]: https://github.com/Ionaru/easy-markdown-editor/pull/298
[#293]: https://github.com/Ionaru/easy-markdown-editor/pull/293
[#286]: https://github.com/Ionaru/easy-markdown-editor/pull/286
[#285]: https://github.com/Ionaru/easy-markdown-editor/pull/285
[#284]: https://github.com/Ionaru/easy-markdown-editor/pull/284
[#280]: https://github.com/Ionaru/easy-markdown-editor/pull/280
[#277]: https://github.com/Ionaru/easy-markdown-editor/pull/277
[#272]: https://github.com/Ionaru/easy-markdown-editor/pull/272
[#267]: https://github.com/Ionaru/easy-markdown-editor/pull/267
[#253]: https://github.com/Ionaru/easy-markdown-editor/pull/253
[#250]: https://github.com/Ionaru/easy-markdown-editor/pull/250
[#249]: https://github.com/Ionaru/easy-markdown-editor/pull/249
[#244]: https://github.com/Ionaru/easy-markdown-editor/pull/244
[#235]: https://github.com/Ionaru/easy-markdown-editor/pull/235
[#225]: https://github.com/Ionaru/easy-markdown-editor/pull/225
@ -207,6 +352,7 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown
[#106]: https://github.com/Ionaru/easy-markdown-editor/pull/106
[#101]: https://github.com/Ionaru/easy-markdown-editor/pull/101
[#97]: https://github.com/Ionaru/easy-markdown-editor/pull/97
[#95]: https://github.com/Ionaru/easy-markdown-editor/pull/95
[#93]: https://github.com/Ionaru/easy-markdown-editor/pull/93
[#75]: https://github.com/Ionaru/easy-markdown-editor/pull/75
[#71]: https://github.com/Ionaru/easy-markdown-editor/pull/71
@ -216,6 +362,19 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown
[#19]: https://github.com/Ionaru/easy-markdown-editor/pull/19
<!-- Linked users -->
[@dependabot]: https://github.com/dependabot
[@wwsalmon]: https://github.com/wwsalmon
[@ChronosMasterOfAllTime]: https://github.com/ChronosMasterOfAllTime
[@deerboy]: https://github.com/deerboy
[@marekdedic]: https://github.com/marekdedic
[@emirotin]: https://github.com/emirotin
[@smundro]: https://github.com/smundro
[@Juupaa]: https://github.com/Juupaa
[@Fanvadar]: https://github.com/Fanvadar
[@danice]: https://github.com/danice
[@joahim]: https://github.com/joahim
[@nhymxu]: https://github.com/nhymxu
[@mbolli]: https://github.com/mbolli
[@ivictbor]: https://github.com/ivictbor
[@JoshuaLicense]: https://github.com/JoshuaLicense
[@czynskee]: https://github.com/czynskee
@ -243,9 +402,32 @@ Project forked from [SimpleMDE](https://github.com/sparksuite/simplemde-markdown
[@n-3-0]: https://github.com/n-3-0
[@aphitiel]: https://github.com/aphitiel
[@sne11ius]: https://github.com/sne11ius
[@souljuse]: https://github.com/souljuse
[@ukjinjang]: https://github.com/ukjinjang
[@robjean9]: https://github.com/robjean9
[@Offerel]: https://github.com/Offerel
[@Zignature]: https://github.com/Zignature
[@kelvinj]: https://github.com/kelvinj
[@diego-gw]: https://github.com/diego-gw
[@danielok1993]: https://github.com/danielok1993
[@vanillajonathan]: https://github.com/vanillajonathan
[@LevitatingOrange]: https://github.com/LevitatingOrange
[@LoyalPotato]: https://github.com/LoyalPotato
[@kicksent]: https://github.com/kicksent
[@hlf20010508]: https://github.com/hlf20010508
[@ZsgsDesign]: https://github.com/ZsgsDesign
[@sghoweri]: https://github.com/sghoweri
<!-- Linked versions -->
[Unreleased]: https://github.com/Ionaru/easy-markdown-editor/compare/2.12.0...HEAD
[Unreleased]: https://github.com/Ionaru/easy-markdown-editor/compare/2.18.0...HEAD
[2.18.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.17.0...2.18.0
[2.17.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.16.1...2.17.0
[2.16.1]: https://github.com/Ionaru/easy-markdown-editor/compare/2.16.0...2.16.1
[2.16.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.15.0...2.16.0
[2.15.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.14.0...2.15.0
[2.14.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.13.0...2.14.0
[2.13.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.12.1...2.13.0
[2.12.1]: https://github.com/Ionaru/easy-markdown-editor/compare/2.12.0...2.12.1
[2.12.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.11.0...2.12.0
[2.11.0]: https://github.com/Ionaru/easy-markdown-editor/compare/2.10.1...2.11.0
[2.10.1]: https://github.com/Ionaru/easy-markdown-editor/compare/2.10.0...2.10.1

@ -1,63 +1,44 @@
# Contributing
Hey, welcome to the party! 🎉
Thank you so much for your interest in contributing to EasyMDE!
Thank you so much for contributing to EasyMDE. 😘
## Asking questions, suggesting ideas or reporting bugs
## Asking questions, suggesting wonderful ideas or reporting bugs
You can [submit an issue](https://github.com/Ionaru/easy-markdown-editor/issues/new) on this GitHub repository.
You can [submit an issue](https://github.com/Ionaru/easy-markdown-editor/issues) on this GitHub repository.
## Coding
### 📦 Prerequisites
You need Node.js and npm.
To install them on Debian-based systems:
```bash
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y nodejs
echo -e "nodejs version:\t$(nodejs -v) \nnpm version:\t$(npm -v)"
# check that you have node.js and npm.
```
For other systems, please [read the official page](https://nodejs.org/en/download/).
### 🏗️ Installation
Here we go! 🤠 First, clone this repository:
```bash
git clone https://github.com/Ionaru/easy-markdown-editor.git
cd easy-markdown-editor
```
Then install the required dependencies:
To contribute code to this project you'll need an up-to-date LTS or current version of Node.js and npm.
```bash
npm install
```
Please find information about the installation on [the official Node.js website](https://nodejs.org/en/download/).
Yay! You are ready! 🍾
### ⤴️ Workflow
### ⤴️ Creating a pull request
Please make sure any code you submit is compliant and compatible with this repository's [license](./LICENSE).
1. First, [create a fork of this project](https://github.com/Ionaru/easy-markdown-editor/fork), and copy the https URL (*clone or download* button) of your project (something like https://github.com/YOUR_USERNAME/easy-markdown-editor.git );
2. a) If you already cloned and worked on the project: `git remote add source https://github.com/Ionaru/easy-markdown-editor.git`;
b) Otherwise, clone your fork: `git clone https://github.com/YOUR_USERNAME/easy-markdown-editor.git`;
3. Create a new dedicated branch `git checkout -b myMergeRequest`;
4. Write some nice code and commit your work. (Don't forget to add your changes to the changelog!);
5. Check files against the ESLint syntax and build minified versions: `gulp`;
6. Test your changes;
7. Push it to a dedicated branch `git push origin myMergeRequest`;
8. Go to the [main project page](https://github.com/Ionaru/easy-markdown-editor) and click on the button *Compare and pull request*, then fill the description.
#### Your first pull request
1. [Create a fork of this project](https://github.com/Ionaru/easy-markdown-editor/fork).
1. Clone your fork: `git clone https://github.com/YOUR_USERNAME/easy-markdown-editor.git`.
1. Add the original repository as remote to keep it up-to-date: `git remote add upstream https://github.com/Ionaru/easy-markdown-editor.git`.
1. Fetch the latest changes from upstream: `git fetch upstream`.
1. Run `npm ci` to install the required dependencies.
1. Create a new branch to work on: `git checkout -b MyNewFeatureName`.
1. Write your awesome improvement and commit your work.
1. Make sure your changes comply with the established code and tests succeed: `npm run test`.
1. Push your changes to GitHub: `git push origin`.
1. On GitHub, go to your forked branch, and click **New pull request**.
1. Choose the correct branches, add a description and submit your pull request!
If you want to make other pull requests, go back to the master branch (`git checkout master`), update it (`git pull --rebase source master`), then follow the instructions above from step 3.
#### Continuing development
To create more pull requests, please follow the steps below:
1. Go back to the master branch: `git checkout master`.
1. Fetch the upstream changes: `git fetch upstream`.
1. Update the master branch with upstream changes: `git merge upstream/master`.
1. Repeat ["Your first pull request"](#your-first-pull-request) from step 5.
Thank you! 💜

@ -2,7 +2,7 @@
[![npm version](https://img.shields.io/npm/v/easymde.svg?style=for-the-badge)](https://www.npmjs.com/package/easymde)
[![npm version](https://img.shields.io/npm/v/easymde/next.svg?style=for-the-badge)](https://www.npmjs.com/package/easymde/v/next)
[![Build Status](https://img.shields.io/travis/Ionaru/easy-markdown-editor/master.svg?style=for-the-badge)](https://travis-ci.org/Ionaru/easy-markdown-editor)
[![Build Status](https://img.shields.io/github/actions/workflow/status/ionaru/easy-markdown-editor/cd.yaml?branch=master&style=for-the-badge)](https://github.com/Ionaru/easy-markdown-editor/actions?query=branch%3Amaster)
> This repository is a fork of
[SimpleMDE, made by Sparksuite](https://github.com/sparksuite/simplemde-markdown-editor/).
@ -16,9 +16,9 @@ In addition, the syntax is rendered while editing to clearly show the expected r
EasyMDE also features both built-in auto saving and spell checking.
The editor is entirely customizable, from theming to toolbar buttons and javascript hooks.
[**Try the demo**](https://easymde.tk/)
[**Try the demo**](https://stackblitz.com/edit/easymde/)
[![Preview](https://user-images.githubusercontent.com/3472373/51319377-26fe6e00-1a5d-11e9-8cc6-3137a566796d.png)](https://easymde.tk/)
[![Preview](https://user-images.githubusercontent.com/3472373/51319377-26fe6e00-1a5d-11e9-8cc6-3137a566796d.png)](https://stackblitz.com/edit/easymde/)
## Quick access
@ -51,7 +51,7 @@ The editor is entirely customizable, from theming to toolbar buttons and javascr
Via [npm](https://www.npmjs.com/package/easymde):
```
npm install easymde --save
npm install easymde
```
Via the *UNPKG* CDN:
@ -61,42 +61,37 @@ Via the *UNPKG* CDN:
<script src="https://unpkg.com/easymde/dist/easymde.min.js"></script>
```
Or *jsDelivr*:
```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css">
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
```
## How to use
### Loading the editor
After installing and/or importing the module, you can load EasyMDE onto the first TextArea on the web page:
After installing and/or importing the module, you can load EasyMDE onto the first `textarea` element on the web page:
```html
<textarea></textarea>
<script>
var easyMDE = new EasyMDE();
</script>
```
Alternatively you can select a specific TextArea, via Javascript:
```html
<textarea id="my-text-area"></textarea>
<script>
var easyMDE = new EasyMDE({element: document.getElementById('my-text-area')});
const easyMDE = new EasyMDE();
</script>
```
Or via jQuery:
Alternatively you can select a specific `textarea`, via JavaScript:
```html
<textarea id="my-text-area"></textarea>
<script>
var easyMDE = new EasyMDE({element: $('#my-text-area')[0]});
const easyMDE = new EasyMDE({element: document.getElementById('my-text-area')});
</script>
```
### Editor functions
Use EasyMDE.value() to get the content of the editor:
Use `easyMDE.value()` to get the content of the editor:
```html
<script>
@ -104,7 +99,7 @@ easyMDE.value();
</script>
```
Use EasyMDE.value(val) to set the content of the editor:
Use `easyMDE.value(val)` to set the content of the editor:
```html
<script>
@ -121,26 +116,31 @@ easyMDE.value('New input for **EasyMDE**');
- **autofocus**: If set to `true`, focuses the editor automatically. Defaults to `false`.
- **autosave**: *Saves the text that's being written and will load it back in the future. It will forget the text when the form it's contained in is submitted.*
- **enabled**: If set to `true`, saves the text automatically. Defaults to `false`.
- **delay**: Delay between saves, in milliseconds. Defaults to `10000` (10s).
- **submit_delay**: Delay before assuming that submit of the form failed and saving the text, in milliseconds. Defaults to `autosave.delay` or `10000` (10s).
- **delay**: Delay between saves, in milliseconds. Defaults to `10000` (10 seconds).
- **submit_delay**: Delay before assuming that submit of the form failed and saving the text, in milliseconds. Defaults to `autosave.delay` or `10000` (10 seconds).
- **uniqueId**: You must set a unique string identifier so that EasyMDE can autosave. Something that separates this from other instances of EasyMDE elsewhere on your website.
- **timeFormat**: Set DateTimeFormat. More information see [DateTimeFormat instances](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat). Default `locale: en-US, format: hour:minute`.
- **text**: Set text for autosave.
- **autoRefresh**: Useful, when initializing the editor in a hidden DOM node. If set to `{ delay: 300 }`, it will check every 300 ms if the editor is visible and if positive, call CodeMirror's [`refresh()`](https://codemirror.net/doc/manual.html#refresh).
- **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.
- **unorderedListStyle**: can be `*`, `-` or `+`. Defaults to `*`.
- **scrollbarStyle**: Chooses a scrollbar implementation. The default is "native", showing native scrollbars. The core library also provides the "null" style, which completely hides the scrollbars. Addons can implement additional scrollbar models.
- **element**: The DOM element for the `textarea` element to use. Defaults to the first `textarea` element on the page.
- **forceSync**: If set to `true`, force text changes made in EasyMDE to be immediately stored in original text area. 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.
- **previewImagesInEditor**: - EasyMDE will show preview of images, `true` by default, use `false` to disable.
- **previewImagesInEditor**: - EasyMDE will show preview of images, `false` by default, preview for images will appear only for images on separate lines.
- **imagesPreviewHandler**: - A custom function for handling the preview of images. Takes the parsed string between the parantheses of the image markdown `![]( )` as argument and returns a string that serves as the `src` attribute of the `<img>` tag in the preview. Enables dynamic previewing of images in the frontend without having to upload them to a server, allows copy-pasting of images to the editor with preview.
- **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
- link
- table
- **lineNumbers**: If set to `true`, enables line numbers in the editor.
- **lineWrapping**: If set to `false`, disable line wrapping. Defaults to `true`.
- **minHeight**: Sets the minimum height for the composition area, before it starts auto-growing. Should be a string containing a valid CSS value like `"500px"`. Defaults to `"300px"`.
- **maxHeight**: Sets fixed height for the composition area. `minHeight` option will be ignored. Should be a string containing a valid CSS value like `"500px"`. Defaults to `undefined`.
@ -151,7 +151,7 @@ easyMDE.value('New input for **EasyMDE**');
- **underscoresBreakWords**: If set to `true`, let underscores be a delimiter for separating words. Defaults to `false`.
- **overlayMode**: Pass a custom codemirror [overlay mode](https://codemirror.net/doc/manual.html#modeapi) to parse and style the Markdown during editing.
- **mode**: A codemirror mode object.
- **combine**: If set to `false`, will *replace* CSS classes returned by the default Markdown mode. Otherwise the classes returned by the custom mode will be combined with the classes returned by the default mode. Defaults to `true`.
- **combine**: If set to `false`, will *replace* CSS classes returned by the default Markdown mode. Otherwise the classes returned by the custom mode will be combined with the classes returned by the default mode. Defaults to `true`.
- **placeholder**: If set, displays a custom placeholder message.
- **previewClass**: A string or array of strings that will be applied to the preview screen when activated. Defaults to `"editor-preview"`.
- **previewRender**: Custom function for parsing the plaintext Markdown and returning HTML. Used when user previews.
@ -159,16 +159,20 @@ easyMDE.value('New input for **EasyMDE**');
- **promptTexts**: Customize the text used to prompt for URLs.
- **image**: The text to use when prompting for an image's URL. Defaults to `URL of the image:`.
- **link**: The text to use when prompting for a link's URL. Defaults to `URL for the link:`.
- **uploadImage**: If set to `true`, enables the image upload functionality, which can be triggered by drag&drop, copy-paste and through the browse-file window (opened when the user click on the *upload-image* icon). Defaults to `false`.
- **imageMaxSize**: Maximum image size in bytes, checked before upload (note: never trust client, always check image size at server-side). Defaults to `1024*1024*2` (2Mb).
- **iconClassMap**: Used to specify the icon class names for the various toolbar buttons.
- **uploadImage**: If set to `true`, enables the image upload functionality, which can be triggered by drag and drop, copy-paste and through the browse-file window (opened when the user click on the *upload-image* icon). Defaults to `false`.
- **imageMaxSize**: Maximum image size in bytes, checked before upload (note: never trust client, always check the image size at server-side). Defaults to `1024 * 1024 * 2` (2 MB).
- **imageAccept**: A comma-separated list of mime-types used to check image type before upload (note: never trust client, always check file types at server-side). Defaults to `image/png, image/jpeg`.
- **imageUploadFunction**: A custom function for handling the image upload. Using this function will render the options `imageMaxSize`, `imageAccept`, `imageUploadEndpoint` and `imageCSRFToken` ineffective.
- The function gets a file and onSuccess and onError callback functions as parameters. `onSuccess(imageUrl: string)` and `onError(errorMessage: string)`
- **imageUploadEndpoint**: The endpoint where the images data will be sent, via an asynchronous *POST* request. The server is supposed to save this image, and return a json response.
- if the request was successfully processed (HTTP 200-OK): `{"data": {"filePath": "<filePath>"}}` where *filePath* is the relative path of the image;
- otherwise: `{"error": "<errorCode>"}`, where *errorCode* can be `noFileGiven` (HTTP 400), `typeNotAllowed` (HTTP 415), `fileTooLarge` (HTTP 413) or `importError` (see *errorMessages* below). If *errorCode* is not one of the *errorMessages*, it is alerted unchanged to the user. This allows for server side error messages.
- The function gets a file and `onSuccess` and `onError` callback functions as parameters. `onSuccess(imageUrl: string)` and `onError(errorMessage: string)`
- **imageUploadEndpoint**: The endpoint where the images data will be sent, via an asynchronous *POST* request. The server is supposed to save this image, and return a JSON response.
- if the request was successfully processed (HTTP 200 OK): `{"data": {"filePath": "<filePath>"}}` where *filePath* is the path of the image (absolute if `imagePathAbsolute` is set to true, relative if otherwise);
- otherwise: `{"error": "<errorCode>"}`, where *errorCode* can be `noFileGiven` (HTTP 400 Bad Request), `typeNotAllowed` (HTTP 415 Unsupported Media Type), `fileTooLarge` (HTTP 413 Payload Too Large) or `importError` (see *errorMessages* below). If *errorCode* is not one of the *errorMessages*, it is alerted unchanged to the user. This allows for server-side error messages.
No default value.
- **imageCSRFToken**: CSRF token to include with AJAX call to upload image. For instance used with Django backend.
- **imagePathAbsolute**: If set to `true`, will treat `imageUrl` from `imageUploadFunction` and *filePath* returned from `imageUploadEndpoint` as an absolute rather than relative path, i.e. not prepend `window.location.origin` to it.
- **imageCSRFToken**: CSRF token to include with AJAX call to upload image. For various instances like Django, Spring and Laravel.
- **imageCSRFName**: CSRF token filed name to include with AJAX call to upload image, applied when `imageCSRFToken` has value, defaults to `csrfmiddlewaretoken`.
- **imageCSRFHeader**: If set to `true`, passing CSRF token via header. Defaults to `false`, which pass CSRF through request body.
- **imageTexts**: Texts displayed to the user (mainly on the status bar) for the import image feature, where `#image_name#`, `#image_size#` and `#image_max_size#` will replaced by their respective values, that can be used for customization or internationalization:
- **sbInit**: Status message displayed initially if `uploadImage` is set to `true`. Defaults to `Attach files by drag and dropping or pasting from clipboard.`.
- **sbOnDragEnter**: Status message displayed when the user drags a file to the text area. Defaults to `Drop image to upload it.`.
@ -181,16 +185,16 @@ easyMDE.value('New input for **EasyMDE**');
- **typeNotAllowed**: The user send a file type which doesn't match the `imageAccept` list, or the server returned this error code. Defaults to `This image type is not allowed.`.
- **fileTooLarge**: The size of the image being imported is bigger than the `imageMaxSize`, or if the server returned this error code. Defaults to `Image #image_name# is too big (#image_size#).\nMaximum file size is #image_max_size#.`.
- **importError**: An unexpected error occurred when uploading the image. Defaults to `Something went wrong when uploading the image #image_name#.`.
- **errorCallback**: A callback function used to define how to display an error message. Defaults to `function(errorMessage) {alert(errorMessage);};`.
- **errorCallback**: A callback function used to define how to display an error message. Defaults to `(errorMessage) => alert(errorMessage)`.
- **renderingConfig**: Adjust settings for parsing the Markdown during previewing (not editing).
- **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 or pass in using the `hljs` option. 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">`
- **hljs**: An injectible instance of [highlight.js](https://github.com/isagalaev/highlight.js). If you don't want to rely on the global namespace (`window.hljs`), you can provide an instance here. Defaults to `undefined`.
- **markedOptions**: Set the internal Markdown renderer's [options](https://marked.js.org/#/USING_ADVANCED.md#options). Other `renderingConfig` options will take precedence.
- **singleLineBreaks**: If set to `false`, disable parsing GFM single line breaks. Defaults to `true`.
- **sanitizerFunction**: Custom function for sanitizing the HTML output of markdown renderer.
- **singleLineBreaks**: If set to `false`, disable parsing [GitHub Flavored Markdown](https://github.github.com/gfm/) (GFM) single line breaks. Defaults to `true`.
- **sanitizerFunction**: Custom function for sanitizing the HTML output of Markdown renderer.
- **shortcuts**: Keyboard shortcuts associated with this instance. Defaults to the [array of shortcuts](#keyboard-shortcuts).
- **showIcons**: An array of icon names to show. Can be used to show specific icons hidden by default without completely customizing the toolbar.
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`.
- **spellChecker**: If set to `false`, disable the spell checker. Defaults to `true`. Optionally pass a CodeMirrorSpellChecker-compliant function.
- **inputStyle**: `textarea` or `contenteditable`. Defaults to `textarea` for desktop and `contenteditable` for mobile. `contenteditable` option is necessary to enable nativeSpellcheck.
- **nativeSpellcheck**: If set to `false`, disable native spell checker. Defaults to `true`.
- **sideBySideFullscreen**: If set to `false`, allows side-by-side editing without going into fullscreen. Defaults to `true`.
@ -202,112 +206,120 @@ easyMDE.value('New input for **EasyMDE**');
- **theme**: Override the theme. Defaults to `easymde`.
- **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`.
- **toolbarButtonClassPrefix**: Adds a prefix to the toolbar button classes when set. For example, a value of `"mde"` results in `"mde-bold"` for the Bold button.
- **direction**: `rtl` or `ltr`. Changes text direction to support right-to-left languages. Defaults to `ltr`.
### Options example
Most options demonstrate the non-default behavior:
```JavaScript
var editor = new EasyMDE({
autofocus: true,
autosave: {
enabled: true,
uniqueId: "MyUniqueID",
delay: 1000,
submit_delay: 5000,
timeFormat: {
locale: 'en-US',
format: {
year: 'numeric',
month: 'long',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
},
},
text: "Autosaved: "
},
blockStyles: {
bold: "__",
italic: "_",
},
element: document.getElementById("MyID"),
forceSync: true,
hideIcons: ["guide", "heading"],
indentWithTabs: false,
initialValue: "Hello world!",
insertTexts: {
horizontalRule: ["", "\n\n-----\n\n"],
image: ["![](http://", ")"],
link: ["[", "](http://)"],
table: ["", "\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n"],
},
lineWrapping: false,
minHeight: "500px",
parsingConfig: {
allowAtxHeaderWithoutSpace: true,
strikethrough: false,
underscoresBreakWords: true,
},
placeholder: "Type here...",
previewClass: "my-custom-styling",
previewClass: ["my-custom-styling", "more-custom-styling"],
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...";
},
promptURLs: true,
promptTexts: {
image: "Custom prompt for URL:",
link: "Custom prompt for URL:",
},
renderingConfig: {
singleLineBreaks: false,
codeSyntaxHighlighting: true,
sanitizerFunction: function(renderedHTML) {
// Using DOMPurify and only allowing <b> tags
return DOMPurify.sanitize(renderedHTML, {ALLOWED_TAGS: ['b']})
},
},
shortcuts: {
drawTable: "Cmd-Alt-T"
},
showIcons: ["code", "table"],
spellChecker: false,
status: false,
status: ["autosave", "lines", "words", "cursor"], // Optional usage
status: ["autosave", "lines", "words", "cursor", {
className: "keystrokes",
defaultValue: function(el) {
this.keystrokes = 0;
el.innerHTML = "0 Keystrokes";
},
onUpdate: function(el) {
el.innerHTML = ++this.keystrokes + " Keystrokes";
},
}], // Another optional usage, with a custom status bar item that counts keystrokes
styleSelectedText: false,
sideBySideFullscreen: false,
syncSideBySidePreviewScroll: false,
tabSize: 4,
toolbar: false,
toolbarTips: false,
```js
const editor = new EasyMDE({
autofocus: true,
autosave: {
enabled: true,
uniqueId: "MyUniqueID",
delay: 1000,
submit_delay: 5000,
timeFormat: {
locale: 'en-US',
format: {
year: 'numeric',
month: 'long',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
},
},
text: "Autosaved: "
},
blockStyles: {
bold: "__",
italic: "_",
},
unorderedListStyle: "-",
element: document.getElementById("MyID"),
forceSync: true,
hideIcons: ["guide", "heading"],
indentWithTabs: false,
initialValue: "Hello world!",
insertTexts: {
horizontalRule: ["", "\n\n-----\n\n"],
image: ["![](http://", ")"],
link: ["[", "](https://)"],
table: ["", "\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n"],
},
lineWrapping: false,
minHeight: "500px",
parsingConfig: {
allowAtxHeaderWithoutSpace: true,
strikethrough: false,
underscoresBreakWords: true,
},
placeholder: "Type here...",
previewClass: "my-custom-styling",
previewClass: ["my-custom-styling", "more-custom-styling"],
previewRender: (plainText) => customMarkdownParser(plainText), // Returns HTML from a custom parser
previewRender: (plainText, preview) => { // Async method
setTimeout(() => {
preview.innerHTML = customMarkdownParser(plainText);
}, 250);
// If you return null, the innerHTML of the preview will not
// be overwritten. Useful if you control the preview node's content via
// vdom diffing.
// return null;
return "Loading...";
},
promptURLs: true,
promptTexts: {
image: "Custom prompt for URL:",
link: "Custom prompt for URL:",
},
renderingConfig: {
singleLineBreaks: false,
codeSyntaxHighlighting: true,
sanitizerFunction: (renderedHTML) => {
// Using DOMPurify and only allowing <b> tags
return DOMPurify.sanitize(renderedHTML, {ALLOWED_TAGS: ['b']})
},
},
shortcuts: {
drawTable: "Cmd-Alt-T"
},
showIcons: ["code", "table"],
spellChecker: false,
status: false,
status: ["autosave", "lines", "words", "cursor"], // Optional usage
status: ["autosave", "lines", "words", "cursor", {
className: "keystrokes",
defaultValue: (el) => {
el.setAttribute('data-keystrokes', 0);
},
onUpdate: (el) => {
const keystrokes = Number(el.getAttribute('data-keystrokes')) + 1;
el.innerHTML = `${keystrokes} Keystrokes`;
el.setAttribute('data-keystrokes', keystrokes);
},
}], // Another optional usage, with a custom status bar item that counts keystrokes
styleSelectedText: false,
sideBySideFullscreen: false,
syncSideBySidePreviewScroll: false,
tabSize: 4,
toolbar: false,
toolbarTips: false,
toolbarButtonClassPrefix: "mde",
});
```
### Toolbar icons
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. Note that shortcut hints are added automatically and reflect the specified action if it has a key bind assigned to it (i.e. with the value of `action` set to `bold` and that of `tooltip` set to `Bold`, the final text the user will see would be "Bold (Ctrl-B)").
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 JavaScript. "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. Note that shortcut hints are added automatically and reflect the specified action if it has a key bind assigned to it (i.e. with the value of `action` set to `bold` and that of `tooltip` set to `Bold`, the final text the user will see would be "Bold (Ctrl-B)").
Additionally, you can add a separator between any icons by adding `"|"` to the toolbar array.
@ -329,12 +341,15 @@ ordered-list | toggleOrderedList | Numbered List<br>fa fa-list-ol
clean-block | cleanBlock | Clean block<br>fa fa-eraser
link | drawLink | Create Link<br>fa fa-link
image | drawImage | Insert Image<br>fa fa-picture-o
upload-image | drawUploadedImage | Raise browse-file window<br>fa fa-image
table | drawTable | Insert Table<br>fa fa-table
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](https://www.markdownguide.org/basic-syntax/) | Markdown Guide<br>fa fa-question-circle
undo | undo | Undo<br>fa fa-undo
redo | redo | Redo<br>fa fa-redo
### Toolbar customization
@ -343,41 +358,48 @@ Customize the toolbar using the `toolbar` option.
Only the order of existing buttons:
```JavaScript
var easyMDE = new EasyMDE({
toolbar: ["bold", "italic", "heading", "|", "quote"]
```js
const easyMDE = new EasyMDE({
toolbar: ["bold", "italic", "heading", "|", "quote"]
});
```
All information and/or add your own icons
```Javascript
var easyMDE = new EasyMDE({
toolbar: [{
name: "bold",
action: EasyMDE.toggleBold,
className: "fa fa-bold",
title: "Bold",
},
{
name: "custom",
action: function customFunction(editor){
// Add your own code
},
className: "fa fa-star",
title: "Custom Button",
},
"|" // Separator
// [, ...]
]
All information and/or add your own icons or text
```js
const easyMDE = new EasyMDE({
toolbar: [
{
name: "bold",
action: EasyMDE.toggleBold,
className: "fa fa-bold",
title: "Bold",
},
"italic", // shortcut to pre-made button
{
name: "custom",
action: (editor) => {
// Add your own code
},
className: "fa fa-star",
text: "Starred",
title: "Custom Button",
attributes: { // for custom attributes
id: "custom-id",
"data-value": "custom value" // HTML5 data-* attributes need to be enclosed in quotation marks ("") because of the dash (-) in its name.
}
},
"|" // Separator
// [, ...]
]
});
```
Put some buttons on dropdown menu
```Javascript
var easyMDE = new EasyMDE({
toolbar: [{
```js
const easyMDE = new EasyMDE({
toolbar: [{
name: "heading",
action: EasyMDE.toggleHeadingSmaller,
className: "fa fa-header",
@ -409,8 +431,8 @@ var easyMDE = new EasyMDE({
}
]
},
// [, ...]
]
// [, ...]
]
});
```
@ -420,30 +442,36 @@ EasyMDE comes with an array of predefined keyboard shortcuts, but they can be al
Shortcut (Windows / Linux) | Shortcut (macOS) | Action
:--- | :--- | :---
*Ctrl-'* | *Cmd-'* | "toggleBlockquote"
*Ctrl-B* | *Cmd-B* | "toggleBold"
*Ctrl-E* | *Cmd-E* | "cleanBlock"
*Ctrl-H* | *Cmd-H* | "toggleHeadingSmaller"
*Ctrl-I* | *Cmd-I* | "toggleItalic"
*Ctrl-K* | *Cmd-K* | "drawLink"
*Ctrl-L* | *Cmd-L* | "toggleUnorderedList"
*Ctrl-P* | *Cmd-P* | "togglePreview"
*Ctrl-Alt-C* | *Cmd-Alt-C* | "toggleCodeBlock"
*Ctrl-Alt-I* | *Cmd-Alt-I* | "drawImage"
*Ctrl-Alt-L* | *Cmd-Alt-L* | "toggleOrderedList"
*Shift-Ctrl-H* | *Shift-Cmd-H* | "toggleHeadingBigger"
*F9* | *F9* | "toggleSideBySide"
*F11* | *F11* | "toggleFullScreen"
<kbd>Ctrl</kbd>-<kbd>'</kbd> | <kbd>Cmd</kbd>-<kbd>'</kbd> | "toggleBlockquote"
<kbd>Ctrl</kbd>-<kbd>B</kbd> | <kbd>Cmd</kbd>-<kbd>B</kbd> | "toggleBold"
<kbd>Ctrl</kbd>-<kbd>E</kbd> | <kbd>Cmd</kbd>-<kbd>E</kbd> | "cleanBlock"
<kbd>Ctrl</kbd>-<kbd>H</kbd> | <kbd>Cmd</kbd>-<kbd>H</kbd> | "toggleHeadingSmaller"
<kbd>Ctrl</kbd>-<kbd>I</kbd> | <kbd>Cmd</kbd>-<kbd>I</kbd> | "toggleItalic"
<kbd>Ctrl</kbd>-<kbd>K</kbd> | <kbd>Cmd</kbd>-<kbd>K</kbd> | "drawLink"
<kbd>Ctrl</kbd>-<kbd>L</kbd> | <kbd>Cmd</kbd>-<kbd>L</kbd> | "toggleUnorderedList"
<kbd>Ctrl</kbd>-<kbd>P</kbd> | <kbd>Cmd</kbd>-<kbd>P</kbd> | "togglePreview"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>C</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>C</kbd> | "toggleCodeBlock"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>I</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>I</kbd> | "drawImage"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>L</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>L</kbd> | "toggleOrderedList"
<kbd>Shift</kbd>-<kbd>Ctrl</kbd>-<kbd>H</kbd> | <kbd>Shift</kbd>-<kbd>Cmd</kbd>-<kbd>H</kbd> | "toggleHeadingBigger"
<kbd>F9</kbd> | <kbd>F9</kbd> | "toggleSideBySide"
<kbd>F11</kbd> | <kbd>F11</kbd> | "toggleFullScreen"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>1</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>1</kbd> | "toggleHeading1"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>2</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>2</kbd> | "toggleHeading2"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>3</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>3</kbd> | "toggleHeading3"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>4</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>4</kbd> | "toggleHeading4"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>5</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>5</kbd> | "toggleHeading5"
<kbd>Ctrl</kbd>-<kbd>Alt</kbd>-<kbd>6</kbd> | <kbd>Cmd</kbd>-<kbd>Alt</kbd>-<kbd>6</kbd> | "toggleHeading6"
Here is how you can change a few, while leaving others untouched:
```JavaScript
var editor = new EasyMDE({
shortcuts: {
"toggleOrderedList": "Ctrl-Alt-K", // alter the shortcut for toggleOrderedList
"toggleCodeBlock": null, // unbind Ctrl-Alt-C
"drawTable": "Cmd-Alt-T", // bind Cmd-Alt-T to drawTable action, which doesn't come with a default shortcut
}
```js
const editor = new EasyMDE({
shortcuts: {
"toggleOrderedList": "Ctrl-Alt-K", // alter the shortcut for toggleOrderedList
"toggleCodeBlock": null, // unbind Ctrl-Alt-C
"drawTable": "Cmd-Alt-T", // bind Cmd-Alt-T to drawTable action, which doesn't come with a default shortcut
}
});
```
@ -458,10 +486,10 @@ The list of actions that can be bound is the same as the list of built-in action
You can catch the following list of events: https://codemirror.net/doc/manual.html#events
```JavaScript
var easyMDE = new EasyMDE();
easyMDE.codemirror.on("change", function(){
console.log(easyMDE.value());
```js
const easyMDE = new EasyMDE();
easyMDE.codemirror.on("change", () => {
console.log(easyMDE.value());
});
```
@ -470,14 +498,14 @@ easyMDE.codemirror.on("change", function(){
You can revert to the initial text area by calling the `toTextArea` method. Note that this clears up the autosave (if enabled) associated with it. The text area will retain any text from the destroyed EasyMDE instance.
```JavaScript
var easyMDE = new EasyMDE();
```js
const easyMDE = new EasyMDE();
// ...
easyMDE.toTextArea();
easyMDE = null;
```
If you need to remove installed listeners (when editor not needed anymore), call `easyMDE.cleanup()`
If you need to remove registered event listeners (when the editor is not needed anymore), call `easyMDE.cleanup()`.
### Useful methods
@ -485,7 +513,7 @@ If you need to remove installed listeners (when editor not needed anymore), call
The following self-explanatory methods may be of use while developing with EasyMDE.
```js
var easyMDE = new EasyMDE();
const easyMDE = new EasyMDE();
easyMDE.isPreviewActive(); // returns boolean
easyMDE.isSideBySideActive(); // returns boolean
easyMDE.isFullscreenActive(); // returns boolean
@ -499,7 +527,7 @@ EasyMDE is a continuation of SimpleMDE.
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.
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 GitHub Flavored Markdown (GFM).
## SimpleMDE fork
@ -514,7 +542,7 @@ Changes include:
* Support for Node 8 and beyond
* Lots of refactored code
* Links in preview will open in a new tab by default
* Typescript support
* TypeScript support
My intention is to continue development on this project, improving it and keeping it alive.

@ -0,0 +1,10 @@
import { defineConfig } from 'cypress';
export default defineConfig({
e2e: {
excludeSpecPattern: [
'**/*.html',
],
video: true,
},
});

@ -0,0 +1,14 @@
{
"plugins": [
"cypress"
],
"env": {
"node": true,
"es6": true,
"cypress/globals": true
},
"extends": [
"../.eslintrc",
"plugin:cypress/recommended"
]
}

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Default</title>
<link rel="stylesheet" href="../../../dist/easymde.min.css">
<script src="../../../dist/easymde.min.js"></script>
</head>
<body>
<textarea id="textarea"></textarea>
<script>
const easyMDE = new EasyMDE();
</script>
</body>
</html>

@ -0,0 +1,31 @@
/// <reference types="cypress" />
describe('Preview', () => {
beforeEach(() => {
cy.visit(__dirname + '/index.html');
});
it('can show a preview of markdown text', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('.EasyMDEContainer .editor-preview').should('not.be.visible');
// Enter markdown text.
cy.get('.EasyMDEContainer .CodeMirror').type('# My Big Title');
cy.get('.EasyMDEContainer .CodeMirror').type('{enter}');
cy.get('.EasyMDEContainer .CodeMirror').type('This is some **important** text!');
cy.get('.EasyMDEContainer .CodeMirror-line').should('contain', '# My Big Title');
cy.get('.EasyMDEContainer .cm-header.cm-header-1').should('contain', '#');
cy.get('.EasyMDEContainer .cm-header.cm-header-1').should('contain', 'My Big Title');
cy.get('.EasyMDEContainer .CodeMirror-line').should('contain', 'This is some **important** text!');
cy.get('.EasyMDEContainer .cm-strong').should('contain', '**');
cy.get('.EasyMDEContainer .cm-strong').should('contain', 'important');
cy.previewOn();
// Check preview window for rendered markdown.
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<h1 id="my-big-title">My Big Title</h1>');
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p>This is some <strong>important</strong> text!</p>');
});
});

@ -0,0 +1,56 @@
/// <reference types="cypress" />
describe('Default statusbar', () => {
beforeEach(() => {
cy.visit(__dirname + '/index.html');
});
it('loads the editor with default statusbar', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('.EasyMDEContainer .editor-statusbar').should('be.visible');
cy.get('.EasyMDEContainer .editor-statusbar .autosave').should('be.empty');
cy.get('.EasyMDEContainer .editor-statusbar .lines').before('content').should('contain', 'lines: ');
cy.get('.EasyMDEContainer .editor-statusbar .lines').should('contain', '1');
cy.get('.EasyMDEContainer .editor-statusbar .words').before('content').should('contain', 'words: ');
cy.get('.EasyMDEContainer .editor-statusbar .words').should('contain', '0');
cy.get('.EasyMDEContainer .editor-statusbar .cursor').should('contain', '1:1');
});
it('updates the statusbar when typing', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('.EasyMDEContainer .editor-statusbar').should('be.visible');
cy.get('.EasyMDEContainer .CodeMirror').type('Hello');
cy.get('.EasyMDEContainer .editor-statusbar .autosave').should('be.empty');
cy.get('.EasyMDEContainer .editor-statusbar .lines').should('contain', '1');
cy.get('.EasyMDEContainer .editor-statusbar .words').should('contain', '1');
cy.get('.EasyMDEContainer .editor-statusbar .cursor').should('contain', '1:6');
cy.get('.EasyMDEContainer .CodeMirror').type(' World');
cy.get('.EasyMDEContainer .editor-statusbar .lines').should('contain', '1');
cy.get('.EasyMDEContainer .editor-statusbar .words').should('contain', '2');
cy.get('.EasyMDEContainer .editor-statusbar .cursor').should('contain', '1:12');
cy.get('.EasyMDEContainer .CodeMirror').type('{enter}');
cy.get('.EasyMDEContainer .editor-statusbar .lines').should('contain', '2');
cy.get('.EasyMDEContainer .editor-statusbar .words').should('contain', '2');
cy.get('.EasyMDEContainer .editor-statusbar .cursor').should('contain', '2:1');
cy.get('.EasyMDEContainer .CodeMirror').type('This is a sample text.{enter}We\'re testing the statusbar.{enter}Did it work?');
cy.get('.EasyMDEContainer .editor-statusbar .autosave').should('be.empty');
cy.get('.EasyMDEContainer .editor-statusbar .lines').before('content').should('contain', 'lines: ');
cy.get('.EasyMDEContainer .editor-statusbar .lines').should('contain', '4');
cy.get('.EasyMDEContainer .editor-statusbar .words').before('content').should('contain', 'words: ');
cy.get('.EasyMDEContainer .editor-statusbar .words').should('contain', '15');
cy.get('.EasyMDEContainer .editor-statusbar .cursor').should('contain', '4:13');
});
});

@ -0,0 +1,17 @@
/// <reference types="cypress" />
describe('Default editor', () => {
beforeEach(() => {
cy.visit(__dirname + '/index.html');
});
it('loads the editor with default settings', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.get('.EasyMDEContainer .editor-toolbar').should('be.visible');
cy.get('.EasyMDEContainer .CodeMirror').should('be.visible');
cy.get('.EasyMDEContainer .editor-preview').should('not.be.visible');
cy.get('.EasyMDEContainer .editor-statusbar').should('be.visible');
});
});

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Default</title>
<link rel="stylesheet" href="../../../dist/easymde.min.css">
<script src="../../../dist/easymde.min.js"></script>
</head>
<body>
<textarea id="textarea"></textarea>
<script>
const easyMDE = new EasyMDE({
promptURLs: true,
});
</script>
</body>
</html>

@ -0,0 +1,232 @@
/// <reference types="cypress" />
describe('URL prompts', () => {
beforeEach(() => {
cy.visit(__dirname + '/index.html');
});
it('must show the correct text for a link prompt', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
const stub = cy.stub($win, 'prompt');
cy.get('button.link').click();
cy.get('button.link').then(() => {
expect(stub).to.be.calledWith('URL for the link:', 'https://');
});
});
});
it('must show the correct text for an image prompt', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
const stub = cy.stub($win, 'prompt');
cy.get('button.image').click();
cy.get('button.image').then(() => {
expect(stub).to.be.calledWith('URL of the image:', 'https://');
});
});
});
it('must enter a link correctly through a prompt', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com" target="_blank">Link to a website!</a></p>');
});
it('can use the prompt multiple times', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
const stub = cy.stub($win, 'prompt');
stub.returns('https://example.com');
cy.get('button.link').click();
cy.get('button.link').then(() => {
expect(stub).to.be.calledWith('URL for the link:', 'https://');
stub.restore();
});
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!{end}{enter}');
cy.window().then(($win) => {
const stub = cy.stub($win, 'prompt');
stub.returns('https://example.eu');
cy.get('button.link').click();
cy.get('button.link').then(() => {
expect(stub).to.be.calledWith('URL for the link:', 'https://');
stub.restore();
});
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.eu)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a second website!');
cy.get('.EasyMDEContainer .CodeMirror').contains('[Link to a website!](https://example.com)');
cy.get('.EasyMDEContainer .CodeMirror').contains('[Link to a second website!](https://example.eu)');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should(
'contain.html',
'<p><a href="https://example.com" target="_blank">Link to a website!</a><br><a href="https://example.eu" target="_blank">Link to a second website!</a></p>',
);
});
it('must be able to deal with parameters in links', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=param&moo=cow');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=param&moo=cow)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=param&amp;moo=cow" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with brackets in links', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=[]param');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=%5B%5Dparam)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=%5B%5Dparam" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with parentheses in links', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=(param)');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=\\(param\\))');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=(param)" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with parentheses in links (multiple)', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=(param1,param2)&more=(param3,param4)&end=true');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=\\(param1,param2\\)&more=\\(param3,param4\\)&end=true)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=(param1,param2)&amp;more=(param3,param4)&amp;end=true" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with unbalanced parentheses in links (opening)', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=(param');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=\\(param)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=(param" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with unbalanced parentheses in links (closing)', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=)param');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=\\)param)');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=)param" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with inequality symbols in links', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=<param');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=%3Cparam');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=%3Cparam" target="_blank">Link to a website!</a></p>');
});
it('must be able to deal with emoji in links', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=👷‍♂️');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=%F0%9F%91%B7%E2%80%8D%E2%99%82%EF%B8%8F');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a 👌 website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=%F0%9F%91%B7%E2%80%8D%E2%99%82%EF%B8%8F" target="_blank">Link to a 👌 website!</a></p>');
});
it('must be able to deal with spaces in links', () => {
cy.get('.EasyMDEContainer').should('be.visible');
cy.get('#textarea').should('not.be.visible');
cy.window().then(($win) => {
cy.stub($win, 'prompt').returns('https://example.com?some=very special param');
cy.get('button.link').click();
});
cy.get('.EasyMDEContainer .CodeMirror').contains('[](https://example.com?some=very%20special%20param');
cy.get('.EasyMDEContainer .CodeMirror').type('{home}{rightarrow}Link to a website!');
cy.previewOn();
cy.get('.EasyMDEContainer .editor-preview').should('contain.html', '<p><a href="https://example.com?some=very%20special%20param" target="_blank">Link to a website!</a></p>');
});
});

@ -0,0 +1,17 @@
/// <reference types="cypress" />
describe('Default editor', () => {
it('table', () => {
cy.visit(__dirname + '/index-no-prefix.html');
cy.get('button.table').should('be.visible');
cy.get('button.table').invoke('outerWidth').should('not.equal', 30);
});
it('loads the editor with default settings', () => {
cy.visit(__dirname + '/index.html');
cy.get('button.mde-table').should('be.visible');
cy.get('button.mde-table').invoke('outerWidth').should('equal', 30);
});
});

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Default</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="../../../dist/easymde.min.css">
<script src="../../../dist/easymde.min.js"></script>
</head>
<body>
<textarea id="textarea"></textarea>
<script>
const easyMDE = new EasyMDE({
showIcons: ["table"],
});
</script>
</body>
</html>

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Default</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="../../../dist/easymde.min.css">
<script src="../../../dist/easymde.min.js"></script>
</head>
<body>
<textarea id="textarea"></textarea>
<script>
const easyMDE = new EasyMDE({
toolbarButtonClassPrefix: 'mde',
showIcons: ["table"],
});
</script>
</body>
</html>

@ -0,0 +1,10 @@
/// <reference types="cypress" />
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
};

@ -0,0 +1,31 @@
/// <reference types="cypress" />
const unquote = (str) => str.replace(/(^")|("$)/g, '');
Cypress.Commands.add(
'before',
{
prevSubject: 'element',
},
(element, property) => {
const win = element[0].ownerDocument.defaultView;
const before = win.getComputedStyle(element[0], 'before');
return unquote(before.getPropertyValue(property));
},
);
Cypress.Commands.add('previewOn' , () => {
cy.get('.EasyMDEContainer .editor-preview').should('not.be.visible');
cy.get('.EasyMDEContainer .editor-toolbar button.preview').should('not.have.class', 'active');
cy.get('.EasyMDEContainer .editor-toolbar button.preview').click();
cy.get('.EasyMDEContainer .editor-toolbar button.preview').should('have.class', 'active');
cy.get('.EasyMDEContainer .editor-preview').should('be.visible');
});
Cypress.Commands.add('previewOff' , () => {
cy.get('.EasyMDEContainer .editor-preview').should('be.visible');
cy.get('.EasyMDEContainer .editor-toolbar button.preview').should('have.class', 'active');
cy.get('.EasyMDEContainer .editor-toolbar button.preview').click();
cy.get('.EasyMDEContainer .editor-toolbar button.preview').should('not.have.class', 'active');
cy.get('.EasyMDEContainer .editor-preview').should('not.be.visible');
});

@ -0,0 +1 @@
require('./commands');

@ -13,7 +13,7 @@
<body>
<textarea></textarea>
<script>
var easyMDE = new EasyMDE();
const easyMDE = new EasyMDE();
</script>
</body>

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Example / Preview / sideBySideFullscreen : false</title>
<link rel="stylesheet" href="../dist/easymde.min.css">
<script src="../dist/easymde.min.js"></script>
</head>
<body>
<textarea></textarea>
<script>
const easyMDE = new EasyMDE({sideBySideFullscreen: false});
</script>
</body>
</html>

15051
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "easymde",
"version": "2.12.0",
"version": "2.18.0",
"description": "A simple, beautiful, and embeddable JavaScript Markdown editor that easy to use. Features include autosaving and spell checking.",
"files": [
"dist/**/*",
@ -19,31 +19,37 @@
"license": "MIT",
"author": "Jeroen Akkerman",
"dependencies": {
"codemirror": "^5.58.1",
"@types/codemirror": "^5.60.10",
"@types/marked": "^4.0.7",
"codemirror": "^5.65.15",
"codemirror-spell-checker": "1.1.2",
"marked": "^1.2.0"
"marked": "^4.1.0"
},
"devDependencies": {
"@types/codemirror": "0.0.98",
"@types/marked": "^1.1.0",
"browserify": "^16.5.2",
"browserify": "^17.0.0",
"cypress": "^13.2.0",
"eslint": "^8.50.0",
"eslint-plugin-cypress": "^2.15.1",
"gulp": "^4.0.2",
"gulp-clean-css": "^4.2.0",
"gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
"gulp-eslint": "^6.0.0",
"gulp-header": "^2.0.9",
"gulp-rename": "^2.0.0",
"gulp-terser": "^1.4.0",
"gulp-terser": "^2.1.0",
"gulp-uglify": "^3.0.2",
"typescript": "^4.0.3",
"vinyl-buffer": "^1.0.0",
"typescript": "^5.2.2",
"vinyl-buffer": "^1.0.1",
"vinyl-source-stream": "^2.0.0"
},
"repository": "github:Ionaru/easy-markdown-editor",
"scripts": {
"prepare": "gulp",
"test": "npm run lint && npm run test:types",
"test": "npm run lint && npm run test:types && npm run e2e",
"lint": "gulp lint",
"cypress:lint": "eslint cypress",
"cypress:run": "cypress run",
"e2e": "gulp && npm run cypress:lint && npm run cypress:run",
"test:types": "tsc --project types/tsconfig.json"
}
}

@ -2,16 +2,20 @@
display: block;
}
.CodeMirror-rtl pre {
direction: rtl;
}
.EasyMDEContainer.sided--no-fullscreen {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.CodeMirror {
.EasyMDEContainer .CodeMirror {
box-sizing: border-box;
height: auto;
border: 1px solid #ddd;
border: 1px solid #ced4da;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 10px;
@ -20,11 +24,11 @@
word-wrap: break-word;
}
.CodeMirror-scroll {
.EasyMDEContainer .CodeMirror-scroll {
cursor: text;
}
.CodeMirror-fullscreen {
.EasyMDEContainer .CodeMirror-fullscreen {
background: #fff;
position: fixed !important;
top: 50px;
@ -37,22 +41,22 @@
border-bottom-right-radius: 0 !important;
}
.CodeMirror-sided {
.EasyMDEContainer .CodeMirror-sided {
width: 50% !important;
}
.CodeMirror-sided.sided--no-fullscreen {
border-right: none!important;
border-bottom-right-radius: 0px;
.EasyMDEContainer.sided--no-fullscreen .CodeMirror-sided {
border-right: none !important;
border-bottom-right-radius: 0;
position: relative;
flex: 1 1 auto;
}
.CodeMirror-placeholder {
.EasyMDEContainer .CodeMirror-placeholder {
opacity: .5;
}
.CodeMirror-focused .CodeMirror-selected {
.EasyMDEContainer .CodeMirror-focused .CodeMirror-selected {
background: #d9d9d9;
}
@ -63,29 +67,14 @@
-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;
padding: 9px 10px;
border-top: 1px solid #ced4da;
border-left: 1px solid #ced4da;
border-right: 1px solid #ced4da;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.editor-toolbar:after,
.editor-toolbar:before {
display: block;
content: ' ';
height: 1px;
}
.editor-toolbar:before {
margin-bottom: 8px
}
.editor-toolbar:after {
margin-top: 8px
}
.editor-toolbar.fullscreen {
width: 100%;
height: 50px;
@ -133,7 +122,7 @@
padding: 0;
}
.editor-toolbar.sided--no-fullscreen {
.EasyMDEContainer.sided--no-fullscreen .editor-toolbar {
width: 100%;
}
@ -151,7 +140,10 @@
}
.editor-toolbar button {
width: 30px;
font-weight: bold;
min-width: 30px;
padding: 0 6px;
white-space: nowrap;
}
.editor-toolbar button.active,
@ -216,7 +208,7 @@
text-align: right;
}
.editor-statusbar.sided--no-fullscreen {
.EasyMDEContainer.sided--no-fullscreen .editor-statusbar {
width: 100%;
}
@ -268,7 +260,7 @@
display: block
}
.editor-preview-active-side.sided--no-fullscreen {
.EasyMDEContainer.sided--no-fullscreen .editor-preview-active-side {
flex: 1 1 auto;
height: auto;
position: static;
@ -311,23 +303,37 @@
}
.cm-s-easymde .cm-header-1 {
font-size: 200%;
line-height: 200%;
font-size: calc(1.375rem + 1.5vw);
}
.cm-s-easymde .cm-header-2 {
font-size: 160%;
line-height: 160%;
font-size: calc(1.325rem + .9vw);
}
.cm-s-easymde .cm-header-3 {
font-size: 125%;
line-height: 125%;
font-size: calc(1.3rem + .6vw);
}
.cm-s-easymde .cm-header-4 {
font-size: 110%;
line-height: 110%;
font-size: calc(1.275rem + .3vw);
}
.cm-s-easymde .cm-header-5 {
font-size: 1.25rem;
}
.cm-s-easymde .cm-header-6 {
font-size: 1rem;
}
.cm-s-easymde .cm-header-1,
.cm-s-easymde .cm-header-2,
.cm-s-easymde .cm-header-3,
.cm-s-easymde .cm-header-4,
.cm-s-easymde .cm-header-5,
.cm-s-easymde .cm-header-6 {
margin-bottom: .5rem;
line-height: 1.2;
}
.cm-s-easymde .cm-comment {
@ -360,7 +366,8 @@
}
.easymde-dropdown-content {
display: none;
display: block;
visibility: hidden;
position: absolute;
background-color: #f9f9f9;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
@ -370,19 +377,27 @@
}
.easymde-dropdown:active .easymde-dropdown-content,
.easymde-dropdown:focus .easymde-dropdown-content {
.easymde-dropdown:focus .easymde-dropdown-content,
.easymde-dropdown:focus-within .easymde-dropdown-content {
visibility: visible;
}
.easymde-dropdown-content button {
display: block;
}
span[data-img-src]::before{
span[data-img-src]::after {
content: '';
/*noinspection CssUnresolvedCustomProperty, added through JS*/
background-image: var(--bg-image);
display: block;
max-height: 100%;
max-width: 100%;
background-size: contain;
height: 0;
/*noinspection CssUnresolvedCustomProperty, added through JS*/
padding-top: var(--height);
/*noinspection CssUnresolvedCustomProperty, added through JS*/
width: var(--width);
background-repeat: no-repeat;
}
}

@ -16,8 +16,7 @@ CodeMirror.commands.tabAndIndentMarkdownList = function (cm) {
if (cm.options.indentWithTabs) {
cm.execCommand('insertTab');
}
else {
} else {
var spaces = Array(cm.options.tabSize + 1).join(' ');
cm.replaceSelection(spaces);
}
@ -36,8 +35,7 @@ CodeMirror.commands.shiftTabAndUnindentMarkdownList = function (cm) {
if (cm.options.indentWithTabs) {
cm.execCommand('insertTab');
}
else {
} else {
var spaces = Array(cm.options.tabSize + 1).join(' ');
cm.replaceSelection(spaces);
}

File diff suppressed because it is too large Load Diff

@ -8,7 +8,7 @@ const editor = new EasyMDE({
inputStyle: 'textarea',
shortcuts: {
drawTable: 'Cmd-Alt-T',
toggleFullScreen: null
toggleFullScreen: null,
},
previewClass: 'my-custom-class',
spellChecker: false,
@ -16,7 +16,7 @@ const editor = new EasyMDE({
console.log('FullscreenToggled', full);
},
theme: 'someOtherTheme',
minHeight: '200px'
minHeight: '200px',
});
// Editor functions
@ -38,13 +38,14 @@ const editor2 = new EasyMDE({
autoDownloadFontAwesome: undefined,
previewClass: ['my-custom-class', 'some-other-class'],
nativeSpellcheck: true,
unorderedListStyle: '-',
inputStyle: 'contenteditable',
toolbar: [
{
name: 'bold',
action: EasyMDE.toggleBold,
className: 'fa fas fa-bolt',
title: 'Bold'
title: 'Bold',
},
'|',
'undo',
@ -57,7 +58,10 @@ const editor2 = new EasyMDE({
className: 'fa fas fa-star',
title: 'A Custom Button',
noDisable: undefined,
noMobile: false
noMobile: false,
attributes: {
'data-custom': 'attribute',
}
},
'|',
{
@ -66,7 +70,7 @@ const editor2 = new EasyMDE({
className: 'fa fab fa-github',
title: 'A Custom Link',
noDisable: true,
noMobile: true
noMobile: true,
},
'preview',
{
@ -80,21 +84,26 @@ const editor2 = new EasyMDE({
className: 'fa fab fa-github',
title: 'A Custom Link',
noDisable: true,
noMobile: true
noMobile: true,
},
'preview',
{
name: 'bold',
action: EasyMDE.toggleBold,
className: 'fa fas fa-bold',
title: 'Bold'
title: 'Bold',
attributes: {
'data-custom': 'some value',
'data-custom-2': 'another value',
}
},
]
}
]
],
},
],
});
editor2.clearAutosavedValue();
editor2.updateStatusBar('upload-image', 'Drag & drop images!');
EasyMDE.togglePreview(editor2);
EasyMDE.toggleSideBySide(editor2);
@ -104,6 +113,7 @@ const editorImages = new EasyMDE({
previewImagesInEditor: false,
imageAccept: 'image/png, image/bmp',
imageCSRFToken: undefined,
unorderedListStyle: '+',
imageMaxSize: 10485760,
imageUploadEndpoint: 'https://my.domain/image-upload/',
imageTexts: {
@ -112,17 +122,17 @@ const editorImages = new EasyMDE({
sbOnDrop: 'Uploading...',
sbProgress: 'Uploading... (#progress#)',
sbOnUploaded: 'Upload complete!',
sizeUnits: 'b,Kb,Mb'
sizeUnits: 'b,Kb,Mb',
},
errorMessages: {
noFileGiven: 'Please select a file',
typeNotAllowed: 'This file type is not allowed!',
fileTooLarge: 'Image too big',
importError: 'Something went oops!'
importError: 'Something went oops!',
},
errorCallback: errorMessage => {
console.error(errorMessage);
}
},
});
const editorImagesCustom = new EasyMDE({
@ -141,13 +151,13 @@ const editorImagesCustom = new EasyMDE({
sbOnDrop: 'Uploading...',
sbProgress: 'Uploading... (#progress#)',
sbOnUploaded: 'Upload complete!',
sizeUnits: 'b,Kb,Mb'
sizeUnits: 'b,Kb,Mb',
},
errorMessages: {
noFileGiven: 'Please select a file',
typeNotAllowed: 'This file type is not allowed!',
fileTooLarge: 'Image too big',
importError: 'Something went oops!'
importError: 'Something went oops!',
},
errorCallback: errorMessage => {
console.error(errorMessage);
@ -157,18 +167,21 @@ const editorImagesCustom = new EasyMDE({
markedOptions: {
silent: true,
highlight(code: string, lang: string, callback?: (error: (any | undefined), code: string) => void): string {
return 'something'
return 'something';
},
},
},
promptTexts: {
image: 'Insert URL'
image: 'Insert URL',
},
syncSideBySidePreviewScroll: true
syncSideBySidePreviewScroll: true,
});
new EasyMDE({
toolbarButtonClassPrefix: 'mde',
sideBySideFullscreen: true,
lineNumbers: false,
unorderedListStyle: '*',
autosave: {
enabled: true,
delay: 2000,
@ -178,14 +191,15 @@ new EasyMDE({
locale: 'en-GB',
format: {
month: 'long',
}
},
},
text: 'Stored: ',
}
},
});
new EasyMDE({
sideBySideFullscreen: false,
lineNumbers: true,
maxHeight: '500px',
toolbar: [
'bold',
@ -196,7 +210,29 @@ new EasyMDE({
'unordered-list',
'ordered-list',
'table',
'upload-image',
'|',
'link'
]
'link',
],
});
new EasyMDE({
direction: 'ltr',
});
new EasyMDE({
direction: 'rtl',
});
new EasyMDE({
previewRender: (plainText: string) => {
return '<pre>' + plainText + '</pre>';
}
});
new EasyMDE({
previewRender: (plainText: string, preview) => {
preview.innerHTML = '<pre>' + plainText + '</pre>';
return null;
}
});

47
types/easymde.d.ts vendored

@ -20,10 +20,11 @@
// SOFTWARE.
/// <reference types="codemirror"/>
/// <reference types="marked"/>
import { marked } from 'marked';
interface ArrayOneOrMore<T> extends Array<T> {
0: T
0: T;
}
type ToolbarButton =
@ -34,6 +35,7 @@ type ToolbarButton =
| 'ordered-list'
| 'link'
| 'image'
| 'upload-image'
| 'strikethrough'
| 'code'
| 'table'
@ -74,6 +76,10 @@ declare namespace EasyMDE {
italic?: string;
}
interface CustomAttributes {
[key: string]: string;
}
interface InsertTextOptions {
horizontalRule?: ReadonlyArray<string>;
image?: ReadonlyArray<string>;
@ -141,6 +147,8 @@ declare namespace EasyMDE {
title: string;
noDisable?: boolean;
noMobile?: boolean;
icon?: string;
attributes?: CustomAttributes;
}
interface ImageTextsOptions {
@ -160,21 +168,27 @@ declare namespace EasyMDE {
}
interface OverlayModeOptions {
mode: CodeMirror.Mode<any>
combine?: boolean
mode: CodeMirror.Mode<any>;
combine?: boolean;
}
interface SpellCheckerOptions {
codeMirrorInstance: CodeMirror.Editor;
}
interface Options {
autoDownloadFontAwesome?: boolean;
autofocus?: boolean;
autosave?: AutoSaveOptions;
autoRefresh?: boolean | { delay: number; };
blockStyles?: BlockStyleOptions;
element?: HTMLElement;
forceSync?: boolean;
hideIcons?: ReadonlyArray<string>;
hideIcons?: ReadonlyArray<ToolbarButton>;
indentWithTabs?: boolean;
initialValue?: string;
insertTexts?: InsertTextOptions;
lineNumbers?: boolean;
lineWrapping?: boolean;
minHeight?: string;
maxHeight?: string;
@ -182,12 +196,13 @@ declare namespace EasyMDE {
placeholder?: string;
previewClass?: string | ReadonlyArray<string>;
previewImagesInEditor?: boolean;
previewRender?: (markdownPlaintext: string, previewElement: HTMLElement) => string;
imagesPreviewHandler?: (src: string) => string,
previewRender?: (markdownPlaintext: string, previewElement: HTMLElement) => string | null;
promptURLs?: boolean;
renderingConfig?: RenderingOptions;
shortcuts?: Shortcuts;
showIcons?: ReadonlyArray<ToolbarButton>;
spellChecker?: boolean;
spellChecker?: boolean | ((options: SpellCheckerOptions) => void);
inputStyle?: 'textarea' | 'contenteditable';
nativeSpellcheck?: boolean;
sideBySideFullscreen?: boolean;
@ -196,23 +211,32 @@ declare namespace EasyMDE {
tabSize?: number;
toolbar?: boolean | ReadonlyArray<'|' | ToolbarButton | ToolbarIcon | ToolbarDropdownIcon>;
toolbarTips?: boolean;
toolbarButtonClassPrefix?: string;
onToggleFullScreen?: (goingIntoFullScreen: boolean) => void;
theme?: string;
scrollbarStyle?: string;
unorderedListStyle?: '*' | '-' | '+';
uploadImage?: boolean;
imageMaxSize?: number;
imageAccept?: string;
imageUploadFunction?: (file: File, onSuccess: (url: string) => void, onError: (error: string) => void) => void;
imageUploadEndpoint?: string;
imagePathAbsolute?: boolean;
imageCSRFToken?: string;
imageCSRFName?: string;
imageCSRFHeader?: boolean;
imageTexts?: ImageTextsOptions;
imageInputName?: string
errorMessages?: ImageErrorTextsOptions;
errorCallback?: (errorMessage: string) => void;
promptTexts?: PromptTexts;
syncSideBySidePreviewScroll?: boolean;
overlayMode?: OverlayModeOptions
overlayMode?: OverlayModeOptions;
direction?: 'ltr' | 'rtl';
}
}
@ -224,6 +248,8 @@ declare class EasyMDE {
codemirror: CodeMirror.Editor;
cleanup(): void;
toTextArea(): void;
isPreviewActive(): boolean;
@ -234,6 +260,8 @@ declare class EasyMDE {
clearAutosavedValue(): void;
updateStatusBar(itemName: string, content: string): void;
static toggleBold: (editor: EasyMDE) => void;
static toggleItalic: (editor: EasyMDE) => void;
static toggleStrikethrough: (editor: EasyMDE) => void;
@ -242,6 +270,9 @@ declare class EasyMDE {
static toggleHeading1: (editor: EasyMDE) => void;
static toggleHeading2: (editor: EasyMDE) => void;
static toggleHeading3: (editor: EasyMDE) => void;
static toggleHeading4: (editor: EasyMDE) => void;
static toggleHeading5: (editor: EasyMDE) => void;
static toggleHeading6: (editor: EasyMDE) => void;
static toggleCodeBlock: (editor: EasyMDE) => void;
static toggleBlockquote: (editor: EasyMDE) => void;
static toggleUnorderedList: (editor: EasyMDE) => void;

@ -1,6 +1,7 @@
{
"compilerOptions": {
"target": "es3",
"ignoreDeprecations": "5.0",
"strict": true,
"noImplicitReturns": true,
"noEmit": true

Loading…
Cancel
Save