bustle / ember-mobiledoc-editor

MIT License
86 stars 48 forks source link

ember-mobiledoc-editor

npm version Build Status Ember Observer Score

A Mobiledoc editor written using Ember.js UI components and Mobiledoc Kit.

Additionally, ember-mobiledoc-editor supports the creation of Mobiledoc cards as Ember components. This is a significant improvement for developer ergonomics over using Mobiledoc cards directly.

Installation

ember install ember-mobiledoc-editor

ember-mobiledoc-editor will install the mobiledoc-kit package as a dependency and load its assets.

Usage

This addon is primarily composed of components used for building an editor UI.

{{mobiledoc-editor}}

This component is the main entrance point for a mobiledoc editor instance in your Ember app. Used in the most basic form it will render a dummy editor with no toolbar. For example this usage:

{{mobiledoc-editor}}

Will render a blank Mobiledoc into the following DOM:

<article class="mobiledoc-editor">
  <div class="mobiledoc-editor__editor-wrapper">
    <div class="mobiledoc-editor__editor"></div>
  </div>
</article>

The component accepts these arguments:

For example, the following index route and template would log before and after creating the MobiledocKitEditor, and every time the user modified the mobiledoc (by typing some text, e.g.).

// routes/index.js

export default Ember.Route.extend({
 ...,
 actions: {
   mobiledocWasUpdated(updatedMobiledoc) {
     console.log('New mobiledoc:',updatedMobiledoc);
     // note that this action will be fired for every changed character,
     // so you may want to debounce API calls if you are using it for
     // an "autosave" feature.
   },
   willCreateEditor() {
     console.log('about to create the editor');
   },
   didCreateEditor(editor) {
     console.log('created the editor:', editor);
   }
 }
});
{{! index.hbs }}

{{mobiledoc-editor
    on-change=(action 'mobiledocWasUpdated')
    will-create-editor=(action 'willCreateEditor')
    did-create-editor=(action 'didCreateEditor')
}}

Of course often you want to provide a user interface to bold text, create headlines, or otherwise reflect the state of the editor.

Called with a block, the editor param is yielded.

{{#mobiledoc-editor mobiledoc=someDoc as |editor|}}
{{/mobiledoc-editor}}

editor has the following properties, useful to inspect the current state of the editor:

Additionally editor provides the following actions:

The editor object is often used indirectly by passing it to other components. For example:

{{#mobiledoc-editor as |editor|}}
  <div class="toolbar">
    {{mobiledoc-markup-button editor=editor for="strong"}}
    {{mobiledoc-link-button editor=editor}}
  </div>
{{/mobiledoc-editor}}

{{mobiledoc-section-button}}

Requires two properties:

And accepts one optional property:

Creates a <button> element that has a class of active when the provided section tag is used in the current selection. For example:

{{mobiledoc-section-button editor=editor for="h2"}}

Alternatively, custom text for the HTML of the button can be yielded:

{{#mobiledoc-section-button editor=editor for="h2"}}
  Headline 2
{{/mobiledoc-section-button}}

When clicked, the section tag name will be toggled.

{{mobiledoc-markup-button}}

Requires two properties:

And accepts one optional property:

Creates a <button> element that has a class of active when the provided markup tag is used in the current selection. For example:

{{mobiledoc-markup-button editor=editor for="em"}}

Alternatively, custom text for the HTML of the button can be yielded:

{{#mobiledoc-markup-button editor=editor for="em"}}
  Italicize
{{/mobiledoc-markup-button}}

When clicked, the markup tag name will be toggled.

{{mobiledoc-link-button}}

Requires one property:

And accepts one optional property:

Creates a <button> element that has a class of active when the an a tag is used in the current selection. For example:

{{mobiledoc-link-button editor=editor}}

Custom text for the HTML of the button can be yielded:

{{#mobiledoc-link-button editor=editor}}
  Toggle Link
{{/mobiledoc-link-button}}

When clicked, the presence of a link will be toggled. The user will be prompted for a URL if required.

{{mobiledoc-section-attribute-button}}

Requires two properties:

And accepts one optional property:

Creates a <button> element that has a class of active when the provided attributeValue is used in the current section. For example:

{{mobiledoc-section-attribute-button editor=editor attributeName="text-align" attributeValue="center"}}

Alternatively, custom text for the HTML of the button can be yielded:

{{#mobiledoc-section-attribute-button editor=editor attributeName="text-align" attributeValue="center"}}
  Center
{{/mobiledoc-section-attribute-button}}

{{mobiledoc-toolbar}}

Requires one property:

This component creates a full-featured toolbar for the Mobiledoc editor. For example:

{{#mobiledoc-editor as |editor|}}
  {{mobiledoc-toolbar editor=editor}}
{{/mobiledoc-editor}}

Component-based Cards

Mobiledoc supports "cards", blocks of rich content that are embedded into a post. For more details on the API for authoring cards in vanilla JavaScript, see CARDS.md.

ember-mobiledoc-editor comes with a handle helper for using Ember components as the display and edit modes of a card. Create a list of cards using the createComponentCard helper:

import Ember from 'ember';
import createComponentCard from 'ember-mobiledoc-editor/utils/create-component-card';

export default Ember.Component.extend({
  cards: Ember.computed(function() {
    return [
      createComponentCard('demo-card')
    ];
  })
});

And pass that list into the {{mobiledoc-editor}} component:

{{mobiledoc-editor cards=cards}}

When added to the post (or loaded from a passed-in Mobiledoc), these components will be used:

The component will be provided with the following attrs:

Component-based Atoms

Mobiledoc supports "atoms", inline sections of rich content that are embedded into a line of text in your post. For more details on the API for authoring atoms in vanilla JavaScript, see ATOMS.md.

ember-mobiledoc-editor comes with a handle helper for using Ember components as an atom. Create a list of atoms using the createComponentAtom helper:

import Ember from 'ember';
import createComponentAtom from 'ember-mobiledoc-editor/utils/create-component-atom';

export default Ember.Component.extend({
  atoms: Ember.computed(function() {
    return [
      createComponentAtom('demo-atom')
    ];
  })
});

And pass that list into the {{mobiledoc-editor}} component:

{{mobiledoc-editor atoms=atoms}}

Editor Lifecycle Hooks

Currently editor lifecycle hooks are available by available by extending the mobiledoc-editor component.

import Component from 'ember-mobiledoc-editor/components/mobiledoc-editor/component';

export default Component.extend({
  cursorDidChange(editor) {
    this._super(...arguments);
    // custom event handling goes here
  }
});

The following lifecycle hooks are available:

Test Helpers

ember-mobiledoc-editor exposes two test helpers for use in your acceptance tests:

Example usage:

// acceptance test
import { insertText, run } from '../../helpers/ember-mobiledoc-editor';
import { find } from '@enber/test-helpers';
test('visit /', function(assert) {
  visit('/');
  andThen(() => {
    let editorEl = find('.mobiledoc-editor__editor');
    return insertText(editorEl, 'here is some text');
    /* Or:
      return run(editorEl, (postEditor) => ...);
    */
  });
  andThen(() => {
    // assert text inserted, etc.
  });
});

Developing ember-mobiledoc-editor

Releasing a new version:

This README outlines the details of collaborating on this Ember addon.

Installation

Run the development server:

Running Tests

Building

For more information on using ember-cli, visit https://ember-cli.com/.