
Research
Security News
Lazarus Strikes npm Again with New Wave of Malicious Packages
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
medium-editor
Advanced tools
This is a clone of medium.com inline editor toolbar.
MediumEditor has been written using vanilla JavaScript, no additional frameworks required.
demo: http://yabwe.github.io/medium-editor/
Via npm:
Run in your console: npm install medium-editor
Via bower:
bower install medium-editor
Via an external CDN
For the latest version:
<script src="//cdn.jsdelivr.net/medium-editor/latest/js/medium-editor.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/medium-editor/latest/css/medium-editor.min.css" type="text/css" media="screen" charset="utf-8">
For a custom one:
<script src="//cdn.jsdelivr.net/medium-editor/4.11.1/js/medium-editor.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/medium-editor/4.11.1/css/medium-editor.min.css" type="text/css" media="screen" charset="utf-8">
Manual installation:
Download the latest release and attach medium editor's stylesheets to your page:
<link rel="stylesheet" href="css/medium-editor.css"> <!-- Core -->
<link rel="stylesheet" href="css/themes/default.css"> <!-- or any other theme -->
The next step is to reference the editor's script
<script src="js/medium-editor.js"></script>
You can now instantiate a new MediumEditor object:
<script>var editor = new MediumEditor('.editable');</script>
The above code will transform all the elements with the .editable class into HTML5 editable contents and add the medium editor toolbar to them.
You can also pass a list of HTML elements:
var elements = document.querySelectorAll('.editable'),
editor = new MediumEditor(elements);
MediumEditor also supports textarea. If you provide a textarea element, the script will create a new div with contentEditable=true
, hide the textarea and link the textarea value to the div HTML content.
People have contributed wrappers around MediumEditor for integrating with different frameworks and tech stacks. Take a look at the list of existing Wrappers and Integrations that have already been written for MediumEditor!
View the MediumEditor Options documentation on all the various options for MediumEditor.
Options to customize medium-editor are passed as the second argument to the MediumEditor constructor. Example:
var editor = new MediumEditor('.editor', {
// options go here
});
'medium-editor-button-active'
false
| 'fontawesome'. Default: false
Using 'fontawesome'
as the buttonLabels requires version 4.1.0 of the fontawesome css to be on the page to ensure all icons will be displayed correctly
0
false
false
false
false
document.body
{}
true
false
The toolbar for MediumEditor is implemented as a built-in extension which automatically displays whenever the user selects some text. The toolbar can hold any set of defined built-in buttons, but can also hold any custom buttons passed in as extensions.
Options for the toolbar are passed as an object that is a member of the outer options object. Example:
var editor = new MediumEditor('.editable', {
toolbar: {
/* These are the default options for the toolbar,
if nothing is passed this is what is used */
allowMultiParagraphSelection: true,
buttons: ['bold', 'italic', 'underline', 'anchor', 'h2', 'h3', 'quote'],
diffLeft: 0,
diffTop: -10,
firstButtonClass: 'medium-editor-button-first',
lastButtonClass: 'medium-editor-button-last',
standardizeSelectionStart: false,
static: false,
relativeContainer: null,
/* options which only apply when static is true */
align: 'center',
sticky: false,
updateOnEmptySelection: false
}
});
true
['bold', 'italic', 'underline', 'anchor', 'h2', 'h3', 'quote']
0
-10
'medium-editor-button-first'
'medium-editor-button-last'
false
false
static
option is being used:left
|center
|right
- When the static option is true
, this aligns the static toolbar relative to the medium-editor element. Default: center
true
, this enables/disables the toolbar "sticking" to the viewport and staying visible on the screen while the page scrolls. Default: false
true
, this enables/disables updating the state of the toolbar buttons even when the selection is collapsed (there is no selection, just a cursor). Default: false
To disable the toolbar (which also disables the anchor-preview extension), set the value of the toolbar
option to false
:
var editor = new MediumEditor('.editable', {
toolbar: false
});
Button behavior can be modified by passing an object into the buttons array instead of a string. This allow for overriding some of the default behavior of buttons. The following options are some of the basic parts of buttons that you may override, but any part of the MediumEditor.Extension.prototype
can be overriden via these button options. (Check out the source code for buttons to see what all can be overriden).
MediumEditor.execAction()
when the button is clicked.<b>
or <strong>
tag that indicates the text is already bold. So the array of tagNames for bold would be: ['b', 'strong']
useQueryState
is set to true
.'font-weight'
style property set to 700
or 'bold'
, that indicates the text is already bold. So the style object for bold would be { prop: 'font-weight', value: '700|bold' }
useQueryState
is set to true
.'|'
)document.queryCommandState()
method to determine whether the action has already been applied. If the action has already been applied, the button will be displayed as 'active' in the toolbar
document.queryCommandState('bold')
which will return true if the browser thinks the text is already bold, and false otherwiseinnerHTML
to put inside the buttoninnerHTML
to use for the content of the button if the buttonLabels option for MediumEditor is set to 'fontawesome'
Example of overriding buttons (here, the goal is to mimic medium by having H1 and H2 buttons which actually produce <h2>
and <h3>
tags respectively):
var editor = new MediumEditor('.editable', {
toolbar: {
buttons: [
'bold',
'italic',
{
name: 'h1',
action: 'append-h2',
aria: 'header type 1',
tagNames: ['h2'],
contentDefault: '<b>H1</b>',
classList: ['custom-class-h1'],
attrs: {
'data-custom-attr': 'attr-value-h1'
}
},
{
name: 'h2',
action: 'append-h3',
aria: 'header type 2',
tagNames: ['h3'],
contentDefault: '<b>H2</b>',
classList: ['custom-class-h2'],
attrs: {
'data-custom-attr': 'attr-value-h2'
}
},
'justifyCenter',
'quote',
'anchor'
]
}
});
The anchor preview is a built-in extension which automatically displays a 'tooltip' when the user is hovering over a link in the editor. The tooltip will display the href
of the link, and when click, will open the anchor editing form in the toolbar.
Options for the anchor preview 'tooltip' are passed as an object that is a member of the outer options object. Example:
var editor = new MediumEditor('.editable', {
anchorPreview: {
/* These are the default options for anchor preview,
if nothing is passed this is what it used */
hideDelay: 500,
previewValueSelector: 'a'
}
}
});
500
'a'
false
To disable the anchor preview, set the value of the anchorPreview
option to false
:
var editor = new MediumEditor('.editable', {
anchorPreview: false
});
toolbar: false
option or data-disable-toolbar
attribute) the anchor-preview is automatically disabled.The placeholder handler is a built-in extension which displays placeholder text when the editor is empty.
Options for placeholder are passed as an object that is a member of the outer options object. Example:
var editor = new MediumEditor('.editable', {
placeholder: {
/* This example includes the default options for placeholder,
if nothing is passed this is what it used */
text: 'Type your text'
}
});
data-placeholder
attribute on the editor elements. Default: 'Type your text'
To disable the placeholder, set the value of the placeholder
option to false
:
var editor = new MediumEditor('.editable', {
placeholder: false
});
The anchor form is a built-in button extension which allows the user to add/edit/remove links from within the editor. When 'anchor' is passed in as a button in the list of buttons, this extension will be enabled and can be triggered by clicking the corresponding button in the toolbar.
Options for the anchor form are passed as an object that is a member of the outer options object. Example:
var editor = new MediumEditor('.editable', {
toolbar: {
buttons: ['bold', 'italic', 'underline', 'anchor']
},
anchor: {
/* These are the default options for anchor form,
if nothing is passed this is what it used */
customClassOption: null,
customClassOptionText: 'Button',
linkValidation: false,
placeholderText: 'Paste or type a link',
targetCheckbox: false,
targetCheckboxText: 'Open in new window'
}
}
});
null
'Button'
false
'Paste or type a link'
target
attribute of the created link. Default: false
'Open in new window'
The paste handler is a built-in extension which attempts to filter the content when the user pastes. How the paste handler filters is configurable via specific options.
Options for paste handling are passed as an object that is a member of the outer options object. Example:
var editor = new MediumEditor('.editable', {
paste: {
/* This example includes the default options for paste,
if nothing is passed this is what it used */
forcePlainText: true,
cleanPastedHTML: false,
cleanReplacements: [],
cleanAttrs: ['class', 'style', 'dir'],
cleanTags: ['meta']
}
});
true
false
true
OR when calling cleanPaste(text)
helper method. Default: []
true
or when calling cleanPaste(text)
or pasteHTML(html,options)
helper methods. Default: ['class', 'style', 'dir']
true
or when calling cleanPaste(text)
or pasteHTML(html,options)
helper methods. Default: ['meta']
The keyboard commands handler is a built-in extension for mapping key-combinations to actions to execute in the editor.
Options for KeyboardCommands are passed as an object that is a member of the outer options object. Example:
var editor = new MediumEditor('.editable', {
keyboardCommands: {
/* This example includes the default options for keyboardCommands,
if nothing is passed this is what it used */
commands: [
{
command: 'bold',
key: 'B',
meta: true,
shift: false,
alt: false
},
{
command: 'italic',
key: 'I',
meta: true,
shift: false,
alt: false
},
{
command: 'underline',
key: 'U',
meta: true,
shift: false,
alt: false
}
],
}
});
editor.execAction()
when key-combination is used
false
, the shortcut will be disabledTo disable the keyboard commands, set the value of the keyboardCommands
option to false
:
var editor = new MediumEditor('.editable', {
keyboardCommands: false
});
The auto-link handler is a built-in extension which automatically turns URLs entered into the text field into HTML anchor tags (similar to the functionality of Markdown). This feature is OFF by default.
To enable built-in auto-link support, set the value of the autoLink
option to true
:
var editor = new MediumEditor('.editable', {
autoLink: true
});
The image dragging handler is a built-in extenson for handling dragging & dropping images into the contenteditable. This feature is ON by default.
To disable built-in image dragging, set the value of the imageDragging
option to false
:
var editor = new MediumEditor('.editable', {
imageDragging: false
});
var editor = new MediumEditor('.editable', {
delay: 1000,
targetBlank: true,
toolbar: {
buttons: ['bold', 'italic', 'quote'],
diffLeft: 25,
diffTop: 10,
},
anchor: {
placeholderText: 'Type a link',
customClassOption: 'btn',
customClassOptionText: 'Create Button'
},
paste: {
cleanPastedHTML: true,
cleanAttrs: ['style', 'dir'],
cleanTags: ['label', 'meta']
},
anchorPreview: {
hideDelay: 300
},
placeholder: {
text: 'Click to edit'
}
});
By default, MediumEditor supports buttons for most of the commands for document.execCommand()
that are well-supported across all its supported browsers.
MediumEditor, by default, will show only the buttons listed here to avoid a huge toolbar:
These are all the built-in buttons supported by MediumEditor.
Check out the Wiki page for a list of available themes: https://github.com/yabwe/medium-editor/wiki/Themes
View the MediumEditor Object API documentation on the Wiki for details on all the methods supported on the MediumEditor object.
on()
importSelection()
exportSelection()
)saveSelection()
was calleddocument.execCommand('createLink')
commanddocument.execCommand
document.queryCommandState(action)
for checking whether a specific action has already been applied to the selection.delay
optioninnerHTML
to html
of the element at index
For observing any changes on contentEditable, use the custom 'editableInput'
event exposed via the subscribe()
method:
var editor = new MediumEditor('.editable');
editor.subscribe('editableInput', function (event, editable) {
// Do some work
});
This event is supported in all browsers supported by MediumEditor (including IE9+)! To help with cases when one instance of MediumEditor is monitoring multiple elements, the 2nd argument passed to the event handler (editable
in the example above) will be a reference to the contenteditable element that has actually changed.
This is handy when you need to capture any modifications to the contenteditable element including:
Why is this interesting and why should you use this event instead of just attaching to the input
event on the contenteditable element?
So for most modern browsers (Chrome, Firefox, Safari, etc.), the input
event works just fine. Infact, editableInput
is just a proxy for the input
event in those browsers. However, the input
event is not supported for contenteditable elements in IE 9-11.
So, to properly support the editableInput
event in Internet Explorer, MediumEditor uses a combination of the selectionchange
and keypress
events, as well as monitoring calls to document.execCommand
.
Check the documentation in order to learn how to develop extensions for MediumEditor.
A list of existing extensions and plugins, such as Images and Media embeds, Tables and Markdown can be found here.
MediumEditor development tasks are managed by Grunt. To install all the necessary packages, just invoke:
npm install
To run all the test and build the dist files for testing on demo pages, just invoke:
grunt
These are the other available grunt tasks:
The source files are located inside the src directory. Be sure to make changes to these files and not files in the dist directory.
git checkout -b my-new-feature
)git commit -am 'Added some feature'
) without files from the dist directory.git push origin my-new-feature
)To help create consistent looking code throughout the project, we use a few tools to help us. They have plugins for most popular editors/IDEs to make coding for our project, but you should use them in your project as well!
We use JSHint on each build to find easy-to-catch errors and potential problems in our js. You can find our JSHint settings in the .jshintrc
file in the root of the project.
We use jscs on each build to enforce some code style rules we have for our project. You can find our jscs settings in the .jscsrc
file in the root of the project.
We use EditorConfig to maintain consistent coding styles between various editors and IDEs. You can find our settings in the .editorconfig
file in the root of the project.
Looking for something simple for a first contribution? Try fixing an easy first bug!
https://github.com/yabwe/medium-editor/graphs/contributors
MIT: https://github.com/yabwe/medium-editor/blob/master/LICENSE
FAQs
Medium.com WYSIWYG editor clone.
The npm package medium-editor receives a total of 19,944 weekly downloads. As such, medium-editor popularity was classified as popular.
We found that medium-editor demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Security News
Socket CEO Feross Aboukhadijeh discusses the open web, open source security, and how Socket tackles software supply chain attacks on The Pair Program podcast.
Security News
Opengrep continues building momentum with the alpha release of its Playground tool, demonstrating the project's rapid evolution just two months after its initial launch.