Skip to content

Commit

Permalink
[CLEANUP] Improve documentation for Editor, Post, PostNodeBuilder, Range
Browse files Browse the repository at this point in the history
  • Loading branch information
bantic committed Apr 6, 2016
1 parent 0822fa8 commit 97140e9
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 59 deletions.
84 changes: 62 additions & 22 deletions src/js/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,22 @@ const CALLBACK_QUEUES = {
DID_REPARSE: 'didReparse'
};

/**
* The Editor is a core component of mobiledoc-kit. After instantiating
* an editor, use {@link Editor#render} to display the editor on the web page.
*
* An editor uses a {@link Post} internally to represent the displayed document.
* The post can be serialized as mobiledoc using {@link Editor#serialize}. Mobiledoc
* is the transportable "over-the-wire" format (JSON) that is suited for persisting
* and sharing between editors and renderers (for display, e.g.), whereas the Post
* model is better suited for programmatic editing.
*
* The editor will call registered callbacks for certain state changes. These are:
* * cursorDidChange
* * didUpdate
*/
class Editor {
/**
* The Editor is a core component of mobiledoc-kit. After instantiating
* an editor, use {@link Editor#render} to display the editor on the web page.
*
* An editor uses a {@link Post} internally to represent the displayed document.
* The post can be serialized as mobiledoc using {@link Editor#serialize}. Mobiledoc
* is the transportable "over-the-wire" format (JSON) that is suited for persisting
* and sharing between editors and renderers (for display, e.g.), whereas the Post
* model is better suited for programmatic editing.
*
* The editor will call registered callbacks for certain state changes. These are:
* * cursorDidChange
* * didUpdate
*
* @param {Object} [options]
* @param {Object} [options.mobiledoc] The mobiledoc to load into the editor.
* Supersedes `options.html`.
Expand Down Expand Up @@ -142,10 +143,10 @@ class Editor {
this.hasRendered = false;
}

addView(view) {
this._views.push(view);
}

/**
* The editor's instance of a post node builder.
* @type {PostNodeBuilder}
*/
get builder() {
if (!this._builder) { this._builder = new PostNodeBuilder(); }
return this._builder;
Expand Down Expand Up @@ -446,7 +447,7 @@ class Editor {
}

/**
* @return {array} The sections from the cursor's selection start to the selection end
* @return {Section[]} The sections from the cursor's selection start to the selection end
*/
get activeSections() {
return this._editState.activeSections;
Expand All @@ -468,6 +469,10 @@ class Editor {
return this._editState.activeMarkups;
}

/**
* @param {Markup|String} markup A markup instance, or a string (e.g. "b")
* @return {boolean}
*/
hasActiveMarkup(markup) {
markup = this.builder._coerceMarkup(markup);
return contains(this.activeMarkups, markup);
Expand All @@ -479,10 +484,9 @@ class Editor {
}

/**
* @public
*
* @param {string} version The mobiledoc version to serialize to.
* @param {String} version The mobiledoc version to serialize to.
* @return {Mobiledoc} Serialized mobiledoc
* @public
*/
serialize(version=MOBILEDOC_VERSION) {
return this.serializePost(this.post, 'mobiledoc', {version});
Expand Down Expand Up @@ -537,6 +541,10 @@ class Editor {
}
}

addView(view) {
this._views.push(view);
}

removeAllViews() {
this._views.forEach((v) => v.destroy());
this._views = [];
Expand Down Expand Up @@ -704,7 +712,7 @@ class Editor {
}

/**
* @param {Function} callback This callback will be called after the cursor
* @param {Function} callback This callback will be called every time the cursor
* position (or selection) changes.
* @public
*/
Expand Down Expand Up @@ -772,6 +780,16 @@ class Editor {
});
}

/**
* Toggles the given markup at the editor's current {@link Range}.
* If the range is collapsed this changes the editor's state so that the
* next characters typed will be affected. If there is text selected
* (aka a non-collapsed range), the selections' markup will be toggled.
* If the editor is not focused and has no active range, nothing happens.
* @param {String} markup E.g. "b", "em", "a"
* @public
* @see PostEditor#toggleMarkup
*/
toggleMarkup(markup) {
markup = this.post.builder.createMarkup(markup);
if (this.range.isCollapsed) {
Expand Down Expand Up @@ -822,6 +840,12 @@ class Editor {
return false;
}

/**
* Inserts the text at the current cursor position. If the editor has
* no current cursor position, nothing will be inserted.
* @param {String} text
* @public
*/
insertText(text) {
let { activeMarkups, range, range: { head: position } } = this;

Expand Down Expand Up @@ -859,6 +883,22 @@ class Editor {
triggerEvent(context, eventName, event) {
this._eventManager._trigger(context, eventName, event);
}

addCallback(...args) {
this._callbacks.addCallback(...args);
}

addCallbackOnce(...args) {
this._callbacks.addCallbackOnce(...args);
}

runCallbacks(...args) {
if (this._isDestroyed) {
// warn -- should not run after destroyed
return;
}
this._callbacks.runCallbacks(...args);
}
}

mixin(Editor, EventEmitter);
Expand Down
27 changes: 14 additions & 13 deletions src/js/editor/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@ const CALLBACK_QUEUES = {
AFTER_COMPLETE: 'afterComplete'
};

/**
* The PostEditor is used to modify a post. It should not be instantiated directly.
* Instead, a new instance of a PostEditor is created by the editor and passed
* as the argument to the callback in {@link Editor#run}.
*
* Usage:
* ```
* editor.run((postEditor) => {
* // postEditor is an instance of PostEditor that can operate on the
* // editor's post
* });
* ```
*/
class PostEditor {
/**
* The PostEditor is used to modify a post. It should not be instantiated directly.
* Instead, a new instance of a PostEditor is created by the editor and passed
* as the argument to the callback in {@link Editor#run}.
*
* Usage:
* ```
* editor.run((postEditor) => {
* // postEditor is an instance of PostEditor that can operate on the
* // editor's post
* });
* ```
* @param {Editor} editor
* @class PostEditor
* @private
*/
constructor(editor) {
this.editor = editor;
Expand Down
45 changes: 43 additions & 2 deletions src/js/models/post-node-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,25 @@ function findMarkupInCache(cache, tagName, attributes) {
return cache[key];
}

export default class PostNodeBuilder {
/**
* The PostNodeBuilder is used to create new {@link Post} primitives, such
* as a MarkupSection, a CardSection, a Markup, etc. Every instance of an
* {@link Editor} has its own builder instance. The builder can be used
* inside an {@link Editor#run} callback to programmatically create new
* Post primitives to insert into the document.
* A PostNodeBuilder should be read from the Editor, *not* instantiated on its own.
*/
class PostNodeBuilder {
/**
* @private
*/
constructor() {
this.markupCache = {};
}

/**
* @return {Post} A new, blank post
*/
createPost(sections=[]) {
const post = new Post();
post.builder = this;
Expand All @@ -59,6 +73,11 @@ export default class PostNodeBuilder {
}
}

/**
* @param {tagName} [tagName='P']
* @param {Marker[]} [markers=[]]
* @return {MarkupSection}
*/
createMarkupSection(tagName=DEFAULT_MARKUP_SECTION_TAG_NAME, markers=[], isGenerated=false) {
tagName = normalizeTagName(tagName);
const section = new MarkupSection(tagName, markers);
Expand Down Expand Up @@ -91,26 +110,45 @@ export default class PostNodeBuilder {
return section;
}

/**
* @param {String} name
* @param {Object} [payload={}]
* @return {CardSection}
*/
createCardSection(name, payload={}) {
const card = new Card(name, payload);
card.builder = this;
return card;
}

/**
* @param {String} value
* @param {Markup[]} [markups=[]]
* @return {Marker}
*/
createMarker(value, markups=[]) {
const marker = new Marker(value, markups);
marker.builder = this;
return marker;
}

/**
* @param {String} name
* @param {String} [text='']
* @param {Object} [payload={}]
* @param {Markup[]} [markups=[]]
* @return {Atom}
*/
createAtom(name, text='', payload={}, markups=[]) {
const atom = new Atom(name, text, payload, markups);
atom.builder = this;
return atom;
}

/**
* @param {Object} attributes {key:value}
* @param {String} tagName
* @param {Object} attributes Key-value pairs of attributes for the markup
* @return {Markup}
*/
createMarkup(tagName, attributes={}) {
tagName = normalizeTagName(tagName);
Expand All @@ -128,9 +166,12 @@ export default class PostNodeBuilder {
/**
* @param {Markup|String} markupOrString
* @return {Markup}
* @private
*/
_coerceMarkup(markupOrString, attributes={}) {
let tagName = typeof markupOrString === 'string' ? markupOrString : markupOrString.tagName;
return this.createMarkup(tagName, attributes);
}
}

export default PostNodeBuilder;
8 changes: 6 additions & 2 deletions src/js/models/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import deprecate from 'mobiledoc-kit/utils/deprecate';
* text) or non-markerable (e.g., a card).
* When persisting a post, it must first be serialized (loss-lessly) into
* mobiledoc using {@link Editor#serialize}.
* @class Post
*/
export default class Post {
class Post {
/**
* @private
*/
constructor() {
this.type = POST_TYPE;
this.sections = new LinkedList({
Expand Down Expand Up @@ -284,3 +286,5 @@ export default class Post {
return post;
}
}

export default Post;
11 changes: 7 additions & 4 deletions src/js/parsers/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ function walkMarkerableNodes(parent, callback) {
}
}

export default class DOMParser {
/**
* Parses DOM element -> Post
*/
/**
* Parses DOM element -> Post
* @private
*/
class DOMParser {
constructor(builder, options={}) {
this.builder = builder;
this.sectionParser = new SectionParser(this.builder, options);
Expand Down Expand Up @@ -299,3 +300,5 @@ export default class DOMParser {
}
}
}

export default DOMParser;
13 changes: 8 additions & 5 deletions src/js/parsers/section.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ const SKIPPABLE_ELEMENT_TAG_NAMES = [
'style', 'head', 'title', 'meta'
].map(normalizeTagName);

export default class SectionParser {
/**
* parses an element into a section, ignoring any non-markup
* elements contained within
*/
/**
* parses an element into a section, ignoring any non-markup
* elements contained within
* @private
*/
class SectionParser {
constructor(builder, options={}) {
this.builder = builder;
this.plugins = options.plugins || [];
Expand Down Expand Up @@ -302,3 +303,5 @@ export default class SectionParser {
normalizeTagName(element.tagName)));
}
}

export default SectionParser;

0 comments on commit 97140e9

Please sign in to comment.