Skip to content

Repository files navigation

<markdown-toolbar> element

Markdown formatting buttons for text inputs.

This is a FlaskBB maintained fork of github/markdown-toolbar-element, forked at upstream v2.2.3. See Relationship to upstream.

Installation

$ npm install --save @flaskbb/markdown-toolbar-element

Usage

import '@flaskbb/markdown-toolbar-element'
<markdown-toolbar for="textarea_id">
  <md-bold>bold</md-bold>
  <md-header>header</md-header>
  <md-italic>italic</md-italic>
  <md-quote>quote</md-quote>
  <md-code>code</md-code>
  <md-link>link</md-link>
  <md-image>image</md-image>
  <md-unordered-list>unordered-list</md-unordered-list>
  <md-ordered-list>ordered-list</md-ordered-list>
  <md-task-list>task-list</md-task-list>
  <md-mention>mention</md-mention>
  <md-ref>ref</md-ref>
  <button data-md-button>Custom button</button>
</markdown-toolbar>
<textarea id="textarea_id"></textarea>

<markdown-toolbar> comes with focus management as advised in WAI-ARIA Authoring Practices 1.1: Toolbar Design Pattern. The md-* buttons that ship with this package are automatically managed. Add a data-md-button attribute to any custom toolbar items to enroll them into focus management.

Custom buttons

There are two ways to add a button for markup this package does not ship with.

<md-custom> - configured from markup

<md-custom> covers the common case of wrapping the selection in fixed text, without writing any JavaScript:

<markdown-toolbar for="textarea_id">
  <md-custom data-md-prefix="||" data-md-placeholder="spoiler">spoiler</md-custom>
  <md-custom data-md-prefix="[[" data-md-suffix="]]">wiki link</md-custom>
  <md-custom data-md-insert="[TOC]">table of contents</md-custom>
</markdown-toolbar>
Attribute Effect
data-md-prefix Text inserted before the selection.
data-md-suffix Text inserted after the selection. Defaults to data-md-prefix; set it to "" for no suffix.
data-md-insert Insert this text as its own block instead of wrapping the selection. Overrides prefix/suffix.
data-md-placeholder Inserted between prefix and suffix, and selected, when the button is clicked with no selection.

Clicking a wrapping button a second time on text it already wrapped removes the markup again, the same way <md-bold> does. All four attributes are observed, so changing them at runtime takes effect on the next click.

MarkdownButtonElement subclasses - anything else

Multi-line aware buttons, buttons that open a dialog, or anything else the attributes above cannot express, subclass MarkdownButtonElement:

import {MarkdownButtonElement} from '@flaskbb/markdown-toolbar-element'

class MyPluginCalloutElement extends MarkdownButtonElement {
  connectedCallback() {
    super.connectedCallback()
    this.markdownStyle = {prefix: '> ', multiline: true, surroundWithNewlines: true}
  }
}

customElements.define('myplugin-callout', MyPluginCalloutElement)

The class is also available as window.MarkdownButtonElement for scripts that are loaded with a plain <script> tag rather than bundled.

The contract for a subclass:

  • Assign this.markdownStyle before the element can be clicked. Doing it in connectedCallback() is the right place; attributes are already readable there. A button with no style assigned does nothing when clicked.
  • Call super.connectedCallback(). It sets role="button" and marks the element as part of the toolbar's keyboard navigation set. If you cannot call it, put data-md-toolbar-button on the element in markup instead.
  • Pick a tag name prefixed with your plugin or application name. customElements.define throws if a name is registered twice, so md-* and bare names like spoiler-button are collision risks.

markdownStyle accepts the Style type, which is exported for TypeScript consumers:

Field Type Effect
prefix string Text inserted before the selection.
suffix string Text inserted after the selection.
blockPrefix string Replaces prefix when the selection spans multiple lines.
blockSuffix string Replaces suffix when the selection spans multiple lines.
multiline boolean Apply prefix/suffix to each selected line instead of the block.
surroundWithNewlines boolean Pad the result with blank lines so it forms its own block.
trimFirst boolean Move leading/trailing whitespace out of the wrapped text.
prefixSpace boolean Insert a space before prefix when the preceding character is not blank.
replaceNext string Substring of suffix that gets selected after inserting, e.g. url.
scanFor string Regex; if the selection matches, it is put into replaceNext's place.
orderedList boolean Renumber the selected lines as an ordered list.
unorderedList boolean Prefix the selected lines as an unordered list.
placeholder string Inserted and selected when the button is used with an empty selection.
insert string Insert this text as its own block, ignoring every field above.

A custom element whose definition never loaded (a plugin script that failed to fetch, for example) is skipped by the toolbar's keyboard navigation instead of becoming a dead stop between the other buttons.

Relationship to upstream

This is a hard fork, and adapted to the own needs of FlaskBB.

Changes against upstream v2.2.3:

  • MarkdownButtonElement, MarkdownToolbarElement, MarkdownCustomButtonElement and the Style type are exported, and MarkdownButtonElement is exposed on window.
  • MarkdownButtonElement gained a markdownStyle accessor, so subclasses outside this package can configure themselves. Upstream keeps the styles in a module-private WeakMap with no way in.
  • Added the <md-custom> element.
  • Added the placeholder and insert style fields.
  • MarkdownButtonElement.connectedCallback() marks the element with data-md-toolbar-button, which enrolls it into focus management. The built-in md-* elements now call super.connectedCallback(), so they also get role="button" - upstream never set it on them, a pre-existing accessibility gap fixed here.
  • Keyboard navigation skips undefined custom elements.
  • Package renamed, TypeScript and CI updated.

Browser support

Browsers without native custom element support require a polyfill.

  • Chrome
  • Firefox
  • Safari
  • Microsoft Edge

Development

npm install
npm test

License

Distributed under the MIT license. See LICENSE for details. Originally written by GitHub, Inc.; the fork is maintained by the FlaskBB team.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages