diff --git a/package.json b/package.json
index 171225041..ee7b40a37 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,8 @@
"scripts": {
"start": "rollup -c --watch",
"test:ci": "yarn build:docs && yarn build && testem ci -f testem-ci.js",
- "test": "yarn build && testem ci -f testem.js",
+ "test": "yarn format && yarn build && testem ci -f testem.js",
+ "format": "prettier src --write",
"build": "rollup -c",
"build:docs": "jsdoc -c ./.jsdoc",
"build:website": "yarn build:docs && yarn build && ./bin/build-website.sh",
@@ -52,6 +53,7 @@
"conventional-changelog-cli": "^2.0.34",
"jquery": "^3.5.1",
"jsdoc": "^3.6.4",
+ "prettier": "^2.0.5",
"qunit": "^2.10.0",
"rollup": "^2.10.3",
"rollup-plugin-copy": "^3.3.0",
@@ -60,6 +62,12 @@
"saucie": "^3.3.3",
"testem": "^3.1.0"
},
+ "prettier": {
+ "arrowParens": "avoid",
+ "printWidth": 120,
+ "semi": false,
+ "singleQuote": true
+ },
"volta": {
"node": "12.14.1",
"yarn": "1.22.1"
diff --git a/src/css/mobiledoc-kit.css b/src/css/mobiledoc-kit.css
index ae0cb66d3..1fcdf89be 100644
--- a/src/css/mobiledoc-kit.css
+++ b/src/css/mobiledoc-kit.css
@@ -96,26 +96,34 @@
*/
@-webkit-keyframes fade-in {
- 0% { opacity: 0; }
- 100% { opacity: 1; }
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
}
@keyframes fade-in {
- 0% { opacity: 0; }
- 100% { opacity: 1; }
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
}
.__mobiledoc-tooltip {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 0.7em;
white-space: nowrap;
position: absolute;
- background-color: rgba(43,43,43,0.9);
+ background-color: rgba(43, 43, 43, 0.9);
border-radius: 3px;
line-height: 1em;
padding: 0.7em 0.9em;
- color: #FFF;
+ color: #fff;
-webkit-animation: fade-in 0.2s;
- animation: fade-in 0.2s;
+ animation: fade-in 0.2s;
}
.__mobiledoc-tooltip:before {
@@ -126,7 +134,7 @@
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
- border-bottom: 5px solid rgba(43,43,43,0.9);
+ border-bottom: 5px solid rgba(43, 43, 43, 0.9);
top: -5px;
margin-left: -5px;
}
@@ -142,7 +150,7 @@
}
.__mobiledoc-tooltip a {
- color: #FFF;
+ color: #fff;
text-decoration: none;
}
diff --git a/src/js/cards/image.js b/src/js/cards/image.js
index 5b30ea2fc..0d10202db 100644
--- a/src/js/cards/image.js
+++ b/src/js/cards/image.js
@@ -1,12 +1,12 @@
-import placeholderImageSrc from 'mobiledoc-kit/utils/placeholder-image-src';
+import placeholderImageSrc from 'mobiledoc-kit/utils/placeholder-image-src'
export default {
name: 'image',
type: 'dom',
- render({payload}) {
- let img = document.createElement('img');
- img.src = payload.src || placeholderImageSrc;
- return img;
- }
-};
+ render({ payload }) {
+ let img = document.createElement('img')
+ img.src = payload.src || placeholderImageSrc
+ return img
+ },
+}
diff --git a/src/js/editor/edit-history.js b/src/js/editor/edit-history.js
index 3d24cf9ec..07a076c5a 100644
--- a/src/js/editor/edit-history.js
+++ b/src/js/editor/edit-history.js
@@ -1,126 +1,122 @@
-import mobiledocParsers from 'mobiledoc-kit/parsers/mobiledoc';
-import FixedQueue from 'mobiledoc-kit/utils/fixed-queue';
+import mobiledocParsers from 'mobiledoc-kit/parsers/mobiledoc'
+import FixedQueue from 'mobiledoc-kit/utils/fixed-queue'
function findLeafSectionAtIndex(post, index) {
- let section;
+ let section
post.walkAllLeafSections((_section, _index) => {
if (index === _index) {
- section = _section;
+ section = _section
}
- });
- return section;
+ })
+ return section
}
export class Snapshot {
- constructor(takenAt, editor, editAction=null) {
- this.mobiledoc = editor.serialize();
- this.editor = editor;
- this.editAction = editAction;
- this.takenAt = takenAt;
+ constructor(takenAt, editor, editAction = null) {
+ this.mobiledoc = editor.serialize()
+ this.editor = editor
+ this.editAction = editAction
+ this.takenAt = takenAt
- this.snapshotRange();
+ this.snapshotRange()
}
snapshotRange() {
- let { range, cursor } = this.editor;
+ let { range, cursor } = this.editor
if (cursor.hasCursor() && !range.isBlank) {
- let { head, tail } = range;
+ let { head, tail } = range
this.range = {
head: [head.leafSectionIndex, head.offset],
- tail: [tail.leafSectionIndex, tail.offset]
- };
+ tail: [tail.leafSectionIndex, tail.offset],
+ }
}
}
getRange(post) {
if (this.range) {
- let { head, tail } = this.range;
- let [headLeafSectionIndex, headOffset] = head;
- let [tailLeafSectionIndex, tailOffset] = tail;
- let headSection = findLeafSectionAtIndex(post, headLeafSectionIndex);
- let tailSection = findLeafSectionAtIndex(post, tailLeafSectionIndex);
+ let { head, tail } = this.range
+ let [headLeafSectionIndex, headOffset] = head
+ let [tailLeafSectionIndex, tailOffset] = tail
+ let headSection = findLeafSectionAtIndex(post, headLeafSectionIndex)
+ let tailSection = findLeafSectionAtIndex(post, tailLeafSectionIndex)
- head = headSection.toPosition(headOffset);
- tail = tailSection.toPosition(tailOffset);
+ head = headSection.toPosition(headOffset)
+ tail = tailSection.toPosition(tailOffset)
- return head.toRange(tail);
+ return head.toRange(tail)
}
}
groupsWith(groupingTimeout, editAction, takenAt) {
- return (
- editAction !== null &&
- this.editAction === editAction &&
- this.takenAt + groupingTimeout > takenAt
- );
+ return editAction !== null && this.editAction === editAction && this.takenAt + groupingTimeout > takenAt
}
}
export default class EditHistory {
constructor(editor, queueLength, groupingTimeout) {
- this.editor = editor;
- this._undoStack = new FixedQueue(queueLength);
- this._redoStack = new FixedQueue(queueLength);
+ this.editor = editor
+ this._undoStack = new FixedQueue(queueLength)
+ this._redoStack = new FixedQueue(queueLength)
- this._pendingSnapshot = null;
- this._groupingTimeout = groupingTimeout;
+ this._pendingSnapshot = null
+ this._groupingTimeout = groupingTimeout
}
snapshot() {
// update the current snapshot with the range read from DOM
if (this._pendingSnapshot) {
- this._pendingSnapshot.snapshotRange();
+ this._pendingSnapshot.snapshotRange()
}
}
- storeSnapshot(editAction=null) {
- let now = Date.now();
+ storeSnapshot(editAction = null) {
+ let now = Date.now()
// store pending snapshot
- let pendingSnapshot = this._pendingSnapshot;
+ let pendingSnapshot = this._pendingSnapshot
if (pendingSnapshot) {
if (!pendingSnapshot.groupsWith(this._groupingTimeout, editAction, now)) {
- this._undoStack.push(pendingSnapshot);
+ this._undoStack.push(pendingSnapshot)
}
- this._redoStack.clear();
+ this._redoStack.clear()
}
// take new pending snapshot to store next time `storeSnapshot` is called
- this._pendingSnapshot = new Snapshot(now, this.editor, editAction);
+ this._pendingSnapshot = new Snapshot(now, this.editor, editAction)
}
stepBackward(postEditor) {
// Throw away the pending snapshot
- this._pendingSnapshot = null;
+ this._pendingSnapshot = null
- let snapshot = this._undoStack.pop();
+ let snapshot = this._undoStack.pop()
if (snapshot) {
- this._redoStack.push(new Snapshot(Date.now(), this.editor));
- this._restoreFromSnapshot(snapshot, postEditor);
+ this._redoStack.push(new Snapshot(Date.now(), this.editor))
+ this._restoreFromSnapshot(snapshot, postEditor)
}
}
stepForward(postEditor) {
- let snapshot = this._redoStack.pop();
+ let snapshot = this._redoStack.pop()
if (snapshot) {
- this._undoStack.push(new Snapshot(Date.now(), this.editor));
- this._restoreFromSnapshot(snapshot, postEditor);
+ this._undoStack.push(new Snapshot(Date.now(), this.editor))
+ this._restoreFromSnapshot(snapshot, postEditor)
}
- postEditor.cancelSnapshot();
+ postEditor.cancelSnapshot()
}
_restoreFromSnapshot(snapshot, postEditor) {
- let { mobiledoc } = snapshot;
- let { editor } = this;
- let { builder, post } = editor;
- let restoredPost = mobiledocParsers.parse(builder, mobiledoc);
+ let { mobiledoc } = snapshot
+ let { editor } = this
+ let { builder, post } = editor
+ let restoredPost = mobiledocParsers.parse(builder, mobiledoc)
- postEditor.removeAllSections();
- postEditor.migrateSectionsFromPost(restoredPost);
+ postEditor.removeAllSections()
+ postEditor.migrateSectionsFromPost(restoredPost)
// resurrect snapshotted range if it exists
- let newRange = snapshot.getRange(post);
+ let newRange = snapshot.getRange(post)
if (newRange) {
- postEditor.setRange(newRange);
+ postEditor.setRange(newRange)
}
}
}
diff --git a/src/js/editor/edit-state.js b/src/js/editor/edit-state.js
index be4d0f9c6..0d68d0d5a 100644
--- a/src/js/editor/edit-state.js
+++ b/src/js/editor/edit-state.js
@@ -1,9 +1,5 @@
-import {
- contains,
- isArrayEqual,
- objectToSortedKVArray
-} from 'mobiledoc-kit/utils/array-utils';
-import Range from 'mobiledoc-kit/utils/cursor/range';
+import { contains, isArrayEqual, objectToSortedKVArray } from 'mobiledoc-kit/utils/array-utils'
+import Range from 'mobiledoc-kit/utils/cursor/range'
/**
* Used by {@link Editor} to manage its current state (cursor, active markups
@@ -12,36 +8,39 @@ import Range from 'mobiledoc-kit/utils/cursor/range';
*/
class EditState {
constructor(editor) {
- this.editor = editor;
+ this.editor = editor
let defaultState = {
range: Range.blankRange(),
activeMarkups: [],
activeSections: [],
activeSectionTagNames: [],
- activeSectionAttributes: {}
- };
+ activeSectionAttributes: {},
+ }
- this.prevState = this.state = defaultState;
+ this.prevState = this.state = defaultState
}
updateRange(newRange) {
- this.prevState = this.state;
- this.state = this._readState(newRange);
+ this.prevState = this.state
+ this.state = this._readState(newRange)
}
destroy() {
- this.editor = null;
- this.prevState = this.state = null;
+ this.editor = null
+ this.prevState = this.state = null
}
/**
* @return {Boolean}
*/
rangeDidChange() {
- let { state: { range } , prevState: {range: prevRange} } = this;
+ let {
+ state: { range },
+ prevState: { range: prevRange },
+ } = this
- return !prevRange.isEqual(range);
+ return !prevRange.isEqual(range)
}
/**
@@ -49,39 +48,43 @@ class EditState {
* has changed.
*/
inputModeDidChange() {
- let { state, prevState } = this;
- return (!isArrayEqual(state.activeMarkups, prevState.activeMarkups) ||
- !isArrayEqual(state.activeSectionTagNames, prevState.activeSectionTagNames) ||
- !isArrayEqual(objectToSortedKVArray(state.activeSectionAttributes), objectToSortedKVArray(prevState.activeSectionAttributes)));
+ let { state, prevState } = this
+ return (
+ !isArrayEqual(state.activeMarkups, prevState.activeMarkups) ||
+ !isArrayEqual(state.activeSectionTagNames, prevState.activeSectionTagNames) ||
+ !isArrayEqual(
+ objectToSortedKVArray(state.activeSectionAttributes),
+ objectToSortedKVArray(prevState.activeSectionAttributes)
+ )
+ )
}
/**
* @return {Range}
*/
get range() {
- return this.state.range;
+ return this.state.range
}
/**
* @return {Section[]}
*/
get activeSections() {
- return this.state.activeSections;
+ return this.state.activeSections
}
-
/**
* @return {Object}
*/
get activeSectionAttributes() {
- return this.state.activeSectionAttributes;
+ return this.state.activeSectionAttributes
}
/**
* @return {Markup[]}
*/
get activeMarkups() {
- return this.state.activeMarkups;
+ return this.state.activeMarkups
}
/**
@@ -92,67 +95,71 @@ class EditState {
*/
toggleMarkupState(markup) {
if (contains(this.activeMarkups, markup)) {
- this._removeActiveMarkup(markup);
+ this._removeActiveMarkup(markup)
} else {
- this._addActiveMarkup(markup);
+ this._addActiveMarkup(markup)
}
}
_readState(range) {
let state = {
range,
- activeMarkups: this._readActiveMarkups(range),
- activeSections: this._readActiveSections(range)
- };
+ activeMarkups: this._readActiveMarkups(range),
+ activeSections: this._readActiveSections(range),
+ }
// Section objects are 'live', so to check that they changed, we
// need to map their tagNames now (and compare to mapped tagNames later).
// In addition, to catch changes from ul -> ol, we keep track of the
// un-nested tag names (otherwise we'd only see li -> li change)
state.activeSectionTagNames = state.activeSections.map(s => {
- return s.isNested ? s.parent.tagName : s.tagName;
- });
- state.activeSectionAttributes = this._readSectionAttributes(state.activeSections);
- return state;
+ return s.isNested ? s.parent.tagName : s.tagName
+ })
+ state.activeSectionAttributes = this._readSectionAttributes(state.activeSections)
+ return state
}
_readActiveSections(range) {
- let { head, tail } = range;
- let { editor: { post } } = this;
+ let { head, tail } = range
+ let {
+ editor: { post },
+ } = this
if (range.isBlank) {
- return [];
+ return []
} else {
- return post.sections.readRange(head.section, tail.section);
+ return post.sections.readRange(head.section, tail.section)
}
}
_readActiveMarkups(range) {
- let { editor: { post } } = this;
- return post.markupsInRange(range);
+ let {
+ editor: { post },
+ } = this
+ return post.markupsInRange(range)
}
_readSectionAttributes(sections) {
return sections.reduce((sectionAttributes, s) => {
- let attributes = s.isNested ? s.parent.attributes : s.attributes;
+ let attributes = s.isNested ? s.parent.attributes : s.attributes
Object.keys(attributes || {}).forEach(attrName => {
- let camelizedAttrName = attrName.replace(/^data-md-/, '');
- let attrValue = attributes[attrName];
- sectionAttributes[camelizedAttrName] = sectionAttributes[camelizedAttrName] || [];
+ let camelizedAttrName = attrName.replace(/^data-md-/, '')
+ let attrValue = attributes[attrName]
+ sectionAttributes[camelizedAttrName] = sectionAttributes[camelizedAttrName] || []
if (!contains(sectionAttributes[camelizedAttrName], attrValue)) {
- sectionAttributes[camelizedAttrName].push(attrValue);
+ sectionAttributes[camelizedAttrName].push(attrValue)
}
- });
- return sectionAttributes;
- }, {});
+ })
+ return sectionAttributes
+ }, {})
}
_removeActiveMarkup(markup) {
- let index = this.state.activeMarkups.indexOf(markup);
- this.state.activeMarkups.splice(index, 1);
+ let index = this.state.activeMarkups.indexOf(markup)
+ this.state.activeMarkups.splice(index, 1)
}
_addActiveMarkup(markup) {
- this.state.activeMarkups.push(markup);
+ this.state.activeMarkups.push(markup)
}
}
-export default EditState;
+export default EditState
diff --git a/src/js/editor/editor.js b/src/js/editor/editor.js
index 54a699924..34150a20e 100644
--- a/src/js/editor/editor.js
+++ b/src/js/editor/editor.js
@@ -1,43 +1,41 @@
-import Tooltip, { DEFAULT_TOOLTIP_PLUGIN } from '../views/tooltip';
-import PostEditor from './post';
-import ImageCard from '../cards/image';
-import { DIRECTION } from '../utils/key';
-import mobiledocParsers from '../parsers/mobiledoc';
-import HTMLParser from '../parsers/html';
-import DOMParser from '../parsers/dom';
-import Renderer from 'mobiledoc-kit/renderers/editor-dom';
-import RenderTree from 'mobiledoc-kit/models/render-tree';
-import mobiledocRenderers from '../renderers/mobiledoc';
-import { MOBILEDOC_VERSION } from 'mobiledoc-kit/renderers/mobiledoc';
-import { mergeWithOptions } from '../utils/merge';
-import { normalizeTagName, clearChildNodes, serializeHTML } from '../utils/dom-utils';
-import { forEach, filter, contains, values, detect } from '../utils/array-utils';
-import { setData } from '../utils/element-utils';
-import Cursor from '../utils/cursor';
-import Range from '../utils/cursor/range';
-import Position from '../utils/cursor/position';
-import Environment from '../utils/environment';
-import PostNodeBuilder from '../models/post-node-builder';
-import { DEFAULT_TEXT_INPUT_HANDLERS } from './text-input-handlers';
-import {
- DEFAULT_KEY_COMMANDS, buildKeyCommand, findKeyCommands, validateKeyCommand
-} from './key-commands';
-import { CARD_MODES } from '../models/card';
-import assert from '../utils/assert';
-import MutationHandler from 'mobiledoc-kit/editor/mutation-handler';
-import EditHistory from 'mobiledoc-kit/editor/edit-history';
-import EventManager from 'mobiledoc-kit/editor/event-manager';
-import EditState from 'mobiledoc-kit/editor/edit-state';
-import DOMRenderer from 'mobiledoc-dom-renderer';
-import TextRenderer from 'mobiledoc-text-renderer';
-import LifecycleCallbacks from 'mobiledoc-kit/models/lifecycle-callbacks';
-import LogManager from 'mobiledoc-kit/utils/log-manager';
-import toRange from 'mobiledoc-kit/utils/to-range';
-import MobiledocError from 'mobiledoc-kit/utils/mobiledoc-error';
+import Tooltip, { DEFAULT_TOOLTIP_PLUGIN } from '../views/tooltip'
+import PostEditor from './post'
+import ImageCard from '../cards/image'
+import { DIRECTION } from '../utils/key'
+import mobiledocParsers from '../parsers/mobiledoc'
+import HTMLParser from '../parsers/html'
+import DOMParser from '../parsers/dom'
+import Renderer from 'mobiledoc-kit/renderers/editor-dom'
+import RenderTree from 'mobiledoc-kit/models/render-tree'
+import mobiledocRenderers from '../renderers/mobiledoc'
+import { MOBILEDOC_VERSION } from 'mobiledoc-kit/renderers/mobiledoc'
+import { mergeWithOptions } from '../utils/merge'
+import { normalizeTagName, clearChildNodes, serializeHTML } from '../utils/dom-utils'
+import { forEach, filter, contains, values, detect } from '../utils/array-utils'
+import { setData } from '../utils/element-utils'
+import Cursor from '../utils/cursor'
+import Range from '../utils/cursor/range'
+import Position from '../utils/cursor/position'
+import Environment from '../utils/environment'
+import PostNodeBuilder from '../models/post-node-builder'
+import { DEFAULT_TEXT_INPUT_HANDLERS } from './text-input-handlers'
+import { DEFAULT_KEY_COMMANDS, buildKeyCommand, findKeyCommands, validateKeyCommand } from './key-commands'
+import { CARD_MODES } from '../models/card'
+import assert from '../utils/assert'
+import MutationHandler from 'mobiledoc-kit/editor/mutation-handler'
+import EditHistory from 'mobiledoc-kit/editor/edit-history'
+import EventManager from 'mobiledoc-kit/editor/event-manager'
+import EditState from 'mobiledoc-kit/editor/edit-state'
+import DOMRenderer from 'mobiledoc-dom-renderer'
+import TextRenderer from 'mobiledoc-text-renderer'
+import LifecycleCallbacks from 'mobiledoc-kit/models/lifecycle-callbacks'
+import LogManager from 'mobiledoc-kit/utils/log-manager'
+import toRange from 'mobiledoc-kit/utils/to-range'
+import MobiledocError from 'mobiledoc-kit/utils/mobiledoc-error'
// This export may later be deprecated, but re-export it from the renderer here
// for consumers that may depend on it.
-export { EDITOR_ELEMENT_CLASS_NAME } from 'mobiledoc-kit/renderers/editor-dom';
+export { EDITOR_ELEMENT_CLASS_NAME } from 'mobiledoc-kit/renderers/editor-dom'
const defaults = {
placeholder: 'Write here...',
@@ -49,16 +47,16 @@ const defaults = {
cards: [],
atoms: [],
cardOptions: {},
- unknownCardHandler: ({env}) => {
- throw new MobiledocError(`Unknown card encountered: ${env.name}`);
+ unknownCardHandler: ({ env }) => {
+ throw new MobiledocError(`Unknown card encountered: ${env.name}`)
},
- unknownAtomHandler: ({env}) => {
- throw new MobiledocError(`Unknown atom encountered: ${env.name}`);
+ unknownAtomHandler: ({ env }) => {
+ throw new MobiledocError(`Unknown atom encountered: ${env.name}`)
},
mobiledoc: null,
html: null,
- tooltipPlugin: DEFAULT_TOOLTIP_PLUGIN
-};
+ tooltipPlugin: DEFAULT_TOOLTIP_PLUGIN,
+}
const CALLBACK_QUEUES = {
DID_UPDATE: 'didUpdate',
@@ -71,8 +69,8 @@ const CALLBACK_QUEUES = {
DID_REPARSE: 'didReparse',
POST_DID_CHANGE: 'postDidChange',
INPUT_MODE_DID_CHANGE: 'inputModeDidChange',
- WILL_COPY: 'willCopy'
-};
+ WILL_COPY: 'willCopy',
+}
/**
* The Editor is a core component of mobiledoc-kit. After instantiating
@@ -122,37 +120,39 @@ class Editor {
* @return {Editor}
* @public
*/
- constructor(options={}) {
- assert('editor create accepts an options object. For legacy usage passing an element for the first argument, consider the `html` option for loading DOM or HTML posts. For other cases call `editor.render(domNode)` after editor creation',
- (options && !options.nodeType));
- this._views = [];
- this.isEditable = true;
- this._parserPlugins = options.parserPlugins || [];
+ constructor(options = {}) {
+ assert(
+ 'editor create accepts an options object. For legacy usage passing an element for the first argument, consider the `html` option for loading DOM or HTML posts. For other cases call `editor.render(domNode)` after editor creation',
+ options && !options.nodeType
+ )
+ this._views = []
+ this.isEditable = true
+ this._parserPlugins = options.parserPlugins || []
// FIXME: This should merge onto this.options
- mergeWithOptions(this, defaults, options);
- this.cards.push(ImageCard);
+ mergeWithOptions(this, defaults, options)
+ this.cards.push(ImageCard)
- DEFAULT_KEY_COMMANDS.forEach(kc => this.registerKeyCommand(kc));
+ DEFAULT_KEY_COMMANDS.forEach(kc => this.registerKeyCommand(kc))
- this._logManager = new LogManager();
- this._parser = new DOMParser(this.builder);
- let {cards, atoms, unknownCardHandler, unknownAtomHandler, cardOptions} = this;
- this._renderer = new Renderer(this, cards, atoms, unknownCardHandler, unknownAtomHandler, cardOptions);
+ this._logManager = new LogManager()
+ this._parser = new DOMParser(this.builder)
+ let { cards, atoms, unknownCardHandler, unknownAtomHandler, cardOptions } = this
+ this._renderer = new Renderer(this, cards, atoms, unknownCardHandler, unknownAtomHandler, cardOptions)
- this.post = this.loadPost();
- this._renderTree = new RenderTree(this.post);
+ this.post = this.loadPost()
+ this._renderTree = new RenderTree(this.post)
- this._editHistory = new EditHistory(this, this.undoDepth, this.undoBlockTimeout);
- this._eventManager = new EventManager(this);
- this._mutationHandler = new MutationHandler(this);
- this._editState = new EditState(this);
- this._callbacks = new LifecycleCallbacks(values(CALLBACK_QUEUES));
- this._beforeHooks = { toggleMarkup: [] };
+ this._editHistory = new EditHistory(this, this.undoDepth, this.undoBlockTimeout)
+ this._eventManager = new EventManager(this)
+ this._mutationHandler = new MutationHandler(this)
+ this._editState = new EditState(this)
+ this._callbacks = new LifecycleCallbacks(values(CALLBACK_QUEUES))
+ this._beforeHooks = { toggleMarkup: [] }
- DEFAULT_TEXT_INPUT_HANDLERS.forEach(handler => this.onTextInput(handler));
+ DEFAULT_TEXT_INPUT_HANDLERS.forEach(handler => this.onTextInput(handler))
- this.hasRendered = false;
+ this.hasRendered = false
}
/**
@@ -160,11 +160,11 @@ class Editor {
* @param {Array} [logTypes=[]] If present, only the given log types will be logged.
* @public
*/
- enableLogging(logTypes=[]) {
+ enableLogging(logTypes = []) {
if (logTypes.length === 0) {
- this._logManager.enableAll();
+ this._logManager.enableAll()
} else {
- this._logManager.enableTypes(logTypes);
+ this._logManager.enableTypes(logTypes)
}
}
@@ -173,14 +173,14 @@ class Editor {
* @public
*/
disableLogging() {
- this._logManager.disable();
+ this._logManager.disable()
}
/**
* @private
*/
loggerFor(type) {
- return this._logManager.for(type);
+ return this._logManager.for(type)
}
/**
@@ -188,43 +188,44 @@ class Editor {
* @type {PostNodeBuilder}
*/
get builder() {
- if (!this._builder) { this._builder = new PostNodeBuilder(); }
- return this._builder;
+ if (!this._builder) {
+ this._builder = new PostNodeBuilder()
+ }
+ return this._builder
}
loadPost() {
- let {mobiledoc, html} = this;
+ let { mobiledoc, html } = this
if (mobiledoc) {
- return mobiledocParsers.parse(this.builder, mobiledoc);
+ return mobiledocParsers.parse(this.builder, mobiledoc)
} else if (html) {
if (typeof html === 'string') {
- let options = {plugins: this._parserPlugins};
- return new HTMLParser(this.builder, options).parse(this.html);
+ let options = { plugins: this._parserPlugins }
+ return new HTMLParser(this.builder, options).parse(this.html)
} else {
- let dom = html;
- return this._parser.parse(dom);
+ let dom = html
+ return this._parser.parse(dom)
}
} else {
- return this.builder.createPost([this.builder.createMarkupSection()]);
+ return this.builder.createPost([this.builder.createMarkupSection()])
}
}
rerender() {
- let postRenderNode = this.post.renderNode;
+ let postRenderNode = this.post.renderNode
// if we haven't rendered this post's renderNode before, mark it dirty
if (!postRenderNode.element) {
- assert('Must call `render` before `rerender` can be called',
- this.hasRendered);
- postRenderNode.element = this.element;
- postRenderNode.markDirty();
+ assert('Must call `render` before `rerender` can be called', this.hasRendered)
+ postRenderNode.element = this.element
+ postRenderNode.markDirty()
}
- this.runCallbacks(CALLBACK_QUEUES.WILL_RENDER);
+ this.runCallbacks(CALLBACK_QUEUES.WILL_RENDER)
this._mutationHandler.suspendObservation(() => {
- this._renderer.render(this._renderTree);
- });
- this.runCallbacks(CALLBACK_QUEUES.DID_RENDER);
+ this._renderer.render(this._renderTree)
+ })
+ this.runCallbacks(CALLBACK_QUEUES.DID_RENDER)
}
/**
@@ -233,55 +234,60 @@ class Editor {
* @public
*/
render(element) {
- assert('Cannot render an editor twice. Use `rerender` to update the ' +
- 'rendering of an existing editor instance.',
- !this.hasRendered);
+ assert(
+ 'Cannot render an editor twice. Use `rerender` to update the ' + 'rendering of an existing editor instance.',
+ !this.hasRendered
+ )
- element.spellcheck = this.spellcheck;
+ element.spellcheck = this.spellcheck
- clearChildNodes(element);
+ clearChildNodes(element)
- this.element = element;
+ this.element = element
if (this.showLinkTooltips) {
- this._addTooltip();
+ this._addTooltip()
}
// A call to `run` will trigger the didUpdatePostCallbacks hooks with a
// postEditor.
- this.run(() => {});
+ this.run(() => {})
// Only set `hasRendered` to true after calling `run` to ensure that
// no cursorDidChange or other callbacks get fired before the editor is
// done rendering
- this.hasRendered = true;
- this.rerender();
+ this.hasRendered = true
+ this.rerender()
- this._mutationHandler.init();
- this._eventManager.init();
+ this._mutationHandler.init()
+ this._eventManager.init()
if (this.isEditable === false) {
- this.disableEditing();
+ this.disableEditing()
} else {
- this.enableEditing();
+ this.enableEditing()
}
if (this.autofocus) {
- this.selectRange(this.post.headPosition());
+ this.selectRange(this.post.headPosition())
}
}
_addTooltip() {
- this.addView(new Tooltip({
- rootElement: this.element,
- showForTag: 'a',
- editor: this
- }));
+ this.addView(
+ new Tooltip({
+ rootElement: this.element,
+ showForTag: 'a',
+ editor: this,
+ })
+ )
}
get keyCommands() {
- if (!this._keyCommands) { this._keyCommands = []; }
- return this._keyCommands;
+ if (!this._keyCommands) {
+ this._keyCommands = []
+ }
+ return this._keyCommands
}
/**
@@ -292,9 +298,9 @@ class Editor {
* @public
*/
registerKeyCommand(rawKeyCommand) {
- const keyCommand = buildKeyCommand(rawKeyCommand);
- assert('Key Command is not valid', validateKeyCommand(keyCommand));
- this.keyCommands.unshift(keyCommand);
+ const keyCommand = buildKeyCommand(rawKeyCommand)
+ assert('Key Command is not valid', validateKeyCommand(keyCommand))
+ this.keyCommands.unshift(keyCommand)
}
/**
@@ -302,11 +308,11 @@ class Editor {
* @public
*/
unregisterKeyCommands(name) {
- for(let i = this.keyCommands.length-1; i > -1; i--) {
- let keyCommand = this.keyCommands[i];
+ for (let i = this.keyCommands.length - 1; i > -1; i--) {
+ let keyCommand = this.keyCommands[i]
- if(keyCommand.name === name) {
- this.keyCommands.splice(i,1);
+ if (keyCommand.name === name) {
+ this.keyCommands.splice(i, 1)
}
}
}
@@ -316,11 +322,11 @@ class Editor {
* cursor in the new position.
* @public
*/
- deleteAtPosition(position, direction, {unit}) {
+ deleteAtPosition(position, direction, { unit }) {
this.run(postEditor => {
- let nextPosition = postEditor.deleteAtPosition(position, direction, {unit});
- postEditor.setRange(nextPosition);
- });
+ let nextPosition = postEditor.deleteAtPosition(position, direction, { unit })
+ postEditor.setRange(nextPosition)
+ })
}
/**
@@ -331,52 +337,60 @@ class Editor {
*/
deleteRange(range) {
this.run(postEditor => {
- let nextPosition = postEditor.deleteRange(range);
- postEditor.setRange(nextPosition);
- });
+ let nextPosition = postEditor.deleteRange(range)
+ postEditor.setRange(nextPosition)
+ })
}
/**
* @private
*/
- performDelete({direction, unit}={direction: DIRECTION.BACKWARD, unit: 'char'}) {
- let { range } = this;
+ performDelete({ direction, unit } = { direction: DIRECTION.BACKWARD, unit: 'char' }) {
+ let { range } = this
- this.runCallbacks(CALLBACK_QUEUES.WILL_DELETE, [range, direction, unit]);
+ this.runCallbacks(CALLBACK_QUEUES.WILL_DELETE, [range, direction, unit])
if (range.isCollapsed) {
- this.deleteAtPosition(range.head, direction, {unit});
+ this.deleteAtPosition(range.head, direction, { unit })
} else {
- this.deleteRange(range);
+ this.deleteRange(range)
}
- this.runCallbacks(CALLBACK_QUEUES.DID_DELETE, [range, direction, unit]);
+ this.runCallbacks(CALLBACK_QUEUES.DID_DELETE, [range, direction, unit])
}
handleNewline(event) {
- if (!this.hasCursor()) { return; }
+ if (!this.hasCursor()) {
+ return
+ }
- event.preventDefault();
+ event.preventDefault()
- let { range } = this;
+ let { range } = this
this.run(postEditor => {
- let cursorSection;
+ let cursorSection
if (!range.isCollapsed) {
- let nextPosition = postEditor.deleteRange(range);
- cursorSection = nextPosition.section;
+ let nextPosition = postEditor.deleteRange(range)
+ cursorSection = nextPosition.section
if (cursorSection && cursorSection.isBlank) {
- postEditor.setRange(cursorSection.headPosition());
- return;
+ postEditor.setRange(cursorSection.headPosition())
+ return
}
}
// Above logic might delete redundant range, so callback must run after it.
- let defaultPrevented = false;
- const event = { preventDefault() { defaultPrevented = true; } };
- this.runCallbacks(CALLBACK_QUEUES.WILL_HANDLE_NEWLINE, [event]);
- if (defaultPrevented) { return; }
+ let defaultPrevented = false
+ const event = {
+ preventDefault() {
+ defaultPrevented = true
+ },
+ }
+ this.runCallbacks(CALLBACK_QUEUES.WILL_HANDLE_NEWLINE, [event])
+ if (defaultPrevented) {
+ return
+ }
- cursorSection = postEditor.splitSection(range.head)[1];
- postEditor.setRange(cursorSection.headPosition());
- });
+ cursorSection = postEditor.splitSection(range.head)[1]
+ postEditor.setRange(cursorSection.headPosition())
+ })
}
/**
@@ -385,7 +399,7 @@ class Editor {
* @private
*/
_postDidChange() {
- this.runCallbacks(CALLBACK_QUEUES.POST_DID_CHANGE);
+ this.runCallbacks(CALLBACK_QUEUES.POST_DID_CHANGE)
}
/**
@@ -395,14 +409,14 @@ class Editor {
* @param {Range|Position} range
*/
selectRange(range) {
- range = toRange(range);
+ range = toRange(range)
- this.cursor.selectRange(range);
- this.range = range;
+ this.cursor.selectRange(range)
+ this.range = range
}
get cursor() {
- return new Cursor(this);
+ return new Cursor(this)
}
/**
@@ -410,66 +424,66 @@ class Editor {
* @return {Range}
*/
get range() {
- return this._editState.range;
+ return this._editState.range
}
set range(newRange) {
- this._editState.updateRange(newRange);
+ this._editState.updateRange(newRange)
if (this._editState.rangeDidChange()) {
- this._rangeDidChange();
+ this._rangeDidChange()
}
if (this._editState.inputModeDidChange()) {
- this._inputModeDidChange();
+ this._inputModeDidChange()
}
}
_readRangeFromDOM() {
- this.range = this.cursor.offsets;
+ this.range = this.cursor.offsets
}
setPlaceholder(placeholder) {
- setData(this.element, 'placeholder', placeholder);
+ setData(this.element, 'placeholder', placeholder)
}
_reparsePost() {
- let post = this._parser.parse(this.element);
+ let post = this._parser.parse(this.element)
this.run(postEditor => {
- postEditor.removeAllSections();
- postEditor.migrateSectionsFromPost(post);
- postEditor.setRange(Range.blankRange());
- });
+ postEditor.removeAllSections()
+ postEditor.migrateSectionsFromPost(post)
+ postEditor.setRange(Range.blankRange())
+ })
- this.runCallbacks(CALLBACK_QUEUES.DID_REPARSE);
- this._postDidChange();
+ this.runCallbacks(CALLBACK_QUEUES.DID_REPARSE)
+ this._postDidChange()
}
- _reparseSections(sections=[]) {
- let currentRange;
+ _reparseSections(sections = []) {
+ let currentRange
sections.forEach(section => {
- this._parser.reparseSection(section, this._renderTree);
- });
- this._removeDetachedSections();
+ this._parser.reparseSection(section, this._renderTree)
+ })
+ this._removeDetachedSections()
if (this._renderTree.isDirty) {
- currentRange = this.range;
+ currentRange = this.range
}
// force the current snapshot's range to remain the same rather than
// rereading it from DOM after the new character is applied and the browser
// updates the cursor position
- let range = this._editHistory._pendingSnapshot.range;
+ let range = this._editHistory._pendingSnapshot.range
this.run(() => {
- this._editHistory._pendingSnapshot.range = range;
- });
- this.rerender();
+ this._editHistory._pendingSnapshot.range = range
+ })
+ this.rerender()
if (currentRange) {
- this.selectRange(currentRange);
+ this.selectRange(currentRange)
}
- this.runCallbacks(CALLBACK_QUEUES.DID_REPARSE);
- this._postDidChange();
+ this.runCallbacks(CALLBACK_QUEUES.DID_REPARSE)
+ this._postDidChange()
}
// FIXME this should be able to be removed now -- if any sections are detached,
@@ -478,7 +492,7 @@ class Editor {
forEach(
filter(this.post.sections, s => !s.renderNode.isAttached()),
s => s.renderNode.scheduleForRemoval()
- );
+ )
}
/**
@@ -486,23 +500,23 @@ class Editor {
* @type {Section[]}
*/
get activeSections() {
- return this._editState.activeSections;
+ return this._editState.activeSections
}
get activeSection() {
- const { activeSections } = this;
- return activeSections[activeSections.length - 1];
+ const { activeSections } = this
+ return activeSections[activeSections.length - 1]
}
get activeSectionAttributes() {
- return this._editState.activeSectionAttributes;
+ return this._editState.activeSectionAttributes
}
detectMarkupInRange(range, markupTagName) {
- let markups = this.post.markupsInRange(range);
+ let markups = this.post.markupsInRange(range)
return detect(markups, markup => {
- return markup.hasTag(markupTagName);
- });
+ return markup.hasTag(markupTagName)
+ })
}
/**
@@ -510,7 +524,7 @@ class Editor {
* @public
*/
get activeMarkups() {
- return this._editState.activeMarkups;
+ return this._editState.activeMarkups
}
/**
@@ -518,15 +532,15 @@ class Editor {
* @return {boolean}
*/
hasActiveMarkup(markup) {
- let matchesFn;
+ let matchesFn
if (typeof markup === 'string') {
- let tagName = normalizeTagName(markup);
- matchesFn = (m) => m.tagName === tagName;
+ let tagName = normalizeTagName(markup)
+ matchesFn = m => m.tagName === tagName
} else {
- matchesFn = (m) => m === markup;
+ matchesFn = m => m === markup
}
- return !!detect(this.activeMarkups, matchesFn);
+ return !!detect(this.activeMarkups, matchesFn)
}
/**
@@ -534,8 +548,8 @@ class Editor {
* @return {Mobiledoc} Serialized mobiledoc
* @public
*/
- serialize(version=MOBILEDOC_VERSION) {
- return this.serializePost(this.post, 'mobiledoc', {version});
+ serialize(version = MOBILEDOC_VERSION) {
+ return this.serializePost(this.post, 'mobiledoc', { version })
}
/**
@@ -549,8 +563,8 @@ class Editor {
* @public
*/
serializeTo(format) {
- let post = this.post;
- return this.serializePost(post, format);
+ let post = this.post
+ return this.serializePost(post, format)
}
/**
@@ -561,47 +575,46 @@ class Editor {
* @return {Object|String}
* @private
*/
- serializePost(post, format, options={}) {
- const validFormats = ['mobiledoc', 'html', 'text'];
- assert(`Unrecognized serialization format ${format}`,
- contains(validFormats, format));
+ serializePost(post, format, options = {}) {
+ const validFormats = ['mobiledoc', 'html', 'text']
+ assert(`Unrecognized serialization format ${format}`, contains(validFormats, format))
if (format === 'mobiledoc') {
- let version = options.version || MOBILEDOC_VERSION;
- return mobiledocRenderers.render(post, version);
+ let version = options.version || MOBILEDOC_VERSION
+ return mobiledocRenderers.render(post, version)
} else {
- let rendered;
- let mobiledoc = this.serializePost(post, 'mobiledoc');
- let unknownCardHandler = () => {};
- let unknownAtomHandler = () => {};
- let rendererOptions = { unknownCardHandler, unknownAtomHandler };
+ let rendered
+ let mobiledoc = this.serializePost(post, 'mobiledoc')
+ let unknownCardHandler = () => {}
+ let unknownAtomHandler = () => {}
+ let rendererOptions = { unknownCardHandler, unknownAtomHandler }
switch (format) {
case 'html': {
- let result;
+ let result
if (Environment.hasDOM()) {
- rendered = new DOMRenderer(rendererOptions).render(mobiledoc);
- result = `
${serializeHTML(rendered.result)}
`;
+ rendered = new DOMRenderer(rendererOptions).render(mobiledoc)
+ result = `${serializeHTML(rendered.result)}
`
} else {
// Fallback to text serialization
- result = this.serializePost(post, 'text', options);
+ result = this.serializePost(post, 'text', options)
}
- return result;
+ return result
}
case 'text':
- rendered = new TextRenderer(rendererOptions).render(mobiledoc);
- return rendered.result;
+ rendered = new TextRenderer(rendererOptions).render(mobiledoc)
+ return rendered.result
}
}
}
addView(view) {
- this._views.push(view);
+ this._views.push(view)
}
removeAllViews() {
- this._views.forEach((v) => v.destroy());
- this._views = [];
+ this._views.forEach(v => v.destroy())
+ this._views = []
}
/**
@@ -613,7 +626,7 @@ class Editor {
* @public
*/
hasCursor() {
- return this.cursor.hasCursor();
+ return this.cursor.hasCursor()
}
/**
@@ -621,18 +634,18 @@ class Editor {
* @public
*/
destroy() {
- this.isDestroyed = true;
+ this.isDestroyed = true
if (this._hasSelection()) {
- this.cursor.clearSelection();
+ this.cursor.clearSelection()
}
if (this._hasFocus()) {
- this.element.blur(); // FIXME This doesn't blur the element on IE11
+ this.element.blur() // FIXME This doesn't blur the element on IE11
}
- this._mutationHandler.destroy();
- this._eventManager.destroy();
- this.removeAllViews();
- this._renderer.destroy();
- this._editState.destroy();
+ this._mutationHandler.destroy()
+ this._eventManager.destroy()
+ this.removeAllViews()
+ this._renderer.destroy()
+ this._editState.destroy()
}
/**
@@ -642,12 +655,12 @@ class Editor {
* @public
*/
disableEditing() {
- this.isEditable = false;
+ this.isEditable = false
if (this.hasRendered) {
- this._eventManager.stop();
- this.element.setAttribute('contentEditable', false);
- this.setPlaceholder('');
- this.selectRange(Range.blankRange());
+ this._eventManager.stop()
+ this.element.setAttribute('contentEditable', false)
+ this.setPlaceholder('')
+ this.selectRange(Range.blankRange())
}
}
@@ -659,11 +672,11 @@ class Editor {
* @public
*/
enableEditing() {
- this.isEditable = true;
+ this.isEditable = true
if (this.hasRendered) {
- this._eventManager.start();
- this.element.setAttribute('contentEditable', true);
- this.setPlaceholder(this.placeholder);
+ this._eventManager.start()
+ this.element.setAttribute('contentEditable', true)
+ this.setPlaceholder(this.placeholder)
}
}
@@ -675,7 +688,7 @@ class Editor {
* @public
*/
editCard(cardSection) {
- this._setCardMode(cardSection, CARD_MODES.EDIT);
+ this._setCardMode(cardSection, CARD_MODES.EDIT)
}
/**
@@ -687,7 +700,7 @@ class Editor {
* @public
*/
displayCard(cardSection) {
- this._setCardMode(cardSection, CARD_MODES.DISPLAY);
+ this._setCardMode(cardSection, CARD_MODES.DISPLAY)
}
/**
@@ -716,20 +729,20 @@ class Editor {
* @public
*/
run(callback) {
- const postEditor = new PostEditor(this);
- postEditor.begin();
- this._editHistory.snapshot();
- const result = callback(postEditor);
- this.runCallbacks(CALLBACK_QUEUES.DID_UPDATE, [postEditor]);
- postEditor.complete();
- this._readRangeFromDOM();
+ const postEditor = new PostEditor(this)
+ postEditor.begin()
+ this._editHistory.snapshot()
+ const result = callback(postEditor)
+ this.runCallbacks(CALLBACK_QUEUES.DID_UPDATE, [postEditor])
+ postEditor.complete()
+ this._readRangeFromDOM()
if (postEditor._shouldCancelSnapshot) {
- this._editHistory._pendingSnapshot = null;
+ this._editHistory._pendingSnapshot = null
}
- this._editHistory.storeSnapshot(postEditor.editActionTaken);
+ this._editHistory.storeSnapshot(postEditor.editActionTaken)
- return result;
+ return result
}
/**
@@ -737,7 +750,7 @@ class Editor {
* @public
*/
didUpdatePost(callback) {
- this.addCallback(CALLBACK_QUEUES.DID_UPDATE, callback);
+ this.addCallback(CALLBACK_QUEUES.DID_UPDATE, callback)
}
/**
@@ -746,7 +759,7 @@ class Editor {
* retrieve the post in portable mobiledoc format.
*/
postDidChange(callback) {
- this.addCallback(CALLBACK_QUEUES.POST_DID_CHANGE, callback);
+ this.addCallback(CALLBACK_QUEUES.POST_DID_CHANGE, callback)
}
/**
@@ -765,7 +778,7 @@ class Editor {
* @public
*/
onTextInput(inputHandler) {
- this._eventManager.registerInputHandler(inputHandler);
+ this._eventManager.registerInputHandler(inputHandler)
}
/**
@@ -774,7 +787,7 @@ class Editor {
* @public
*/
unregisterAllTextInputHandlers() {
- this._eventManager.unregisterAllTextInputHandlers();
+ this._eventManager.unregisterAllTextInputHandlers()
}
/**
@@ -784,7 +797,7 @@ class Editor {
* @public
*/
unregisterTextInputHandler(name) {
- this._eventManager.unregisterInputHandler(name);
+ this._eventManager.unregisterInputHandler(name)
}
/**
@@ -792,7 +805,7 @@ class Editor {
* active sections) has changed, either via user input or programmatically
*/
inputModeDidChange(callback) {
- this.addCallback(CALLBACK_QUEUES.INPUT_MODE_DID_CHANGE, callback);
+ this.addCallback(CALLBACK_QUEUES.INPUT_MODE_DID_CHANGE, callback)
}
/**
@@ -801,7 +814,7 @@ class Editor {
* @public
*/
willRender(callback) {
- this.addCallback(CALLBACK_QUEUES.WILL_RENDER, callback);
+ this.addCallback(CALLBACK_QUEUES.WILL_RENDER, callback)
}
/**
@@ -810,11 +823,11 @@ class Editor {
* @public
*/
didRender(callback) {
- this.addCallback(CALLBACK_QUEUES.DID_RENDER, callback);
+ this.addCallback(CALLBACK_QUEUES.DID_RENDER, callback)
}
willCopy(callback) {
- this.addCallback(CALLBACK_QUEUES.WILL_COPY, callback);
+ this.addCallback(CALLBACK_QUEUES.WILL_COPY, callback)
}
/**
@@ -822,7 +835,7 @@ class Editor {
* @public
*/
willDelete(callback) {
- this.addCallback(CALLBACK_QUEUES.WILL_DELETE, callback);
+ this.addCallback(CALLBACK_QUEUES.WILL_DELETE, callback)
}
/**
@@ -830,7 +843,7 @@ class Editor {
* @public
*/
didDelete(callback) {
- this.addCallback(CALLBACK_QUEUES.DID_DELETE, callback);
+ this.addCallback(CALLBACK_QUEUES.DID_DELETE, callback)
}
/**
@@ -838,7 +851,7 @@ class Editor {
* @public
*/
willHandleNewline(callback) {
- this.addCallback(CALLBACK_QUEUES.WILL_HANDLE_NEWLINE, callback);
+ this.addCallback(CALLBACK_QUEUES.WILL_HANDLE_NEWLINE, callback)
}
/**
@@ -847,25 +860,25 @@ class Editor {
* @public
*/
cursorDidChange(callback) {
- this.addCallback(CALLBACK_QUEUES.CURSOR_DID_CHANGE, callback);
+ this.addCallback(CALLBACK_QUEUES.CURSOR_DID_CHANGE, callback)
}
_rangeDidChange() {
if (this.hasRendered) {
- this.runCallbacks(CALLBACK_QUEUES.CURSOR_DID_CHANGE);
+ this.runCallbacks(CALLBACK_QUEUES.CURSOR_DID_CHANGE)
}
}
_inputModeDidChange() {
- this.runCallbacks(CALLBACK_QUEUES.INPUT_MODE_DID_CHANGE);
+ this.runCallbacks(CALLBACK_QUEUES.INPUT_MODE_DID_CHANGE)
}
_insertEmptyMarkupSectionAtCursor() {
this.run(postEditor => {
- const section = postEditor.builder.createMarkupSection('p');
- postEditor.insertSectionBefore(this.post.sections, section);
- postEditor.setRange(section.toRange());
- });
+ const section = postEditor.builder.createMarkupSection('p')
+ postEditor.insertSectionBefore(this.post.sections, section)
+ postEditor.setRange(section.toRange())
+ })
}
/**
@@ -884,7 +897,7 @@ class Editor {
* @param {editorBeforeCallback}
*/
beforeToggleMarkup(callback) {
- this._beforeHooks.toggleMarkup.push(callback);
+ this._beforeHooks.toggleMarkup.push(callback)
}
/**
@@ -901,34 +914,36 @@ class Editor {
* @public
* @see PostEditor#toggleMarkup
*/
- toggleMarkup(markup, attributes={}) {
- markup = this.builder.createMarkup(markup, attributes);
- let { range } = this;
- let willAdd = !this.detectMarkupInRange(range, markup.tagName);
- let shouldCancel = this._runBeforeHooks('toggleMarkup', {markup, range, willAdd});
- if (shouldCancel) { return; }
+ toggleMarkup(markup, attributes = {}) {
+ markup = this.builder.createMarkup(markup, attributes)
+ let { range } = this
+ let willAdd = !this.detectMarkupInRange(range, markup.tagName)
+ let shouldCancel = this._runBeforeHooks('toggleMarkup', { markup, range, willAdd })
+ if (shouldCancel) {
+ return
+ }
if (range.isCollapsed) {
- this._editState.toggleMarkupState(markup);
- this._inputModeDidChange();
+ this._editState.toggleMarkupState(markup)
+ this._inputModeDidChange()
// when clicking a button to toggle markup, the button can end up being focused,
// so ensure the editor is focused
- this._ensureFocus();
+ this._ensureFocus()
} else {
- this.run(postEditor => postEditor.toggleMarkup(markup, range));
+ this.run(postEditor => postEditor.toggleMarkup(markup, range))
}
}
// If the editor has a selection but is not focused, focus it
_ensureFocus() {
if (this._hasSelection() && !this._hasFocus()) {
- this.focus();
+ this.focus()
}
}
focus() {
- this.element.focus();
+ this.element.focus()
}
/**
@@ -938,8 +953,8 @@ class Editor {
* @return {Boolean}
*/
_hasSelection() {
- let { cursor } = this;
- return this.hasRendered && (cursor._hasCollapsedSelection() || cursor._hasSelection());
+ let { cursor } = this
+ return this.hasRendered && (cursor._hasCollapsedSelection() || cursor._hasSelection())
}
/**
@@ -949,7 +964,7 @@ class Editor {
* @return {Boolean}
*/
_hasFocus() {
- return document.activeElement === this.element;
+ return document.activeElement === this.element
}
/**
@@ -961,7 +976,7 @@ class Editor {
* @see PostEditor#toggleSection
*/
toggleSection(tagName) {
- this.run(postEditor => postEditor.toggleSection(tagName, this.range));
+ this.run(postEditor => postEditor.toggleSection(tagName, this.range))
}
/**
@@ -973,7 +988,7 @@ class Editor {
* @see PostEditor#setAttribute
*/
setAttribute(key, value) {
- this.run(postEditor => postEditor.setAttribute(key, value, this.range));
+ this.run(postEditor => postEditor.setAttribute(key, value, this.range))
}
/**
@@ -984,7 +999,7 @@ class Editor {
* @see PostEditor#removeAttribute
*/
removeAttribute(key) {
- this.run(postEditor => postEditor.removeAttribute(key, this.range));
+ this.run(postEditor => postEditor.removeAttribute(key, this.range))
}
/**
@@ -1001,15 +1016,15 @@ class Editor {
* @private
*/
handleKeyCommand(event) {
- const keyCommands = findKeyCommands(this.keyCommands, event);
- for (let i=0; i {
if (!range.isCollapsed) {
- position = postEditor.deleteRange(range);
+ position = postEditor.deleteRange(range)
}
- postEditor.insertTextWithMarkup(position, text, activeMarkups);
- });
+ postEditor.insertTextWithMarkup(position, text, activeMarkups)
+ })
}
/**
@@ -1046,25 +1067,27 @@ class Editor {
* @return {Atom} The inserted atom.
* @public
*/
- insertAtom(atomName, atomText='', atomPayload={}) {
- if (!this.hasCursor()) { return; }
+ insertAtom(atomName, atomText = '', atomPayload = {}) {
+ if (!this.hasCursor()) {
+ return
+ }
if (this.post.isBlank) {
- this._insertEmptyMarkupSectionAtCursor();
+ this._insertEmptyMarkupSectionAtCursor()
}
- let atom;
- let { range } = this;
+ let atom
+ let { range } = this
this.run(postEditor => {
- let position = range.head;
+ let position = range.head
- atom = postEditor.builder.createAtom(atomName, atomText, atomPayload);
+ atom = postEditor.builder.createAtom(atomName, atomText, atomPayload)
if (!range.isCollapsed) {
- position = postEditor.deleteRange(range);
+ position = postEditor.deleteRange(range)
}
- postEditor.insertMarkers(position, [atom]);
- });
- return atom;
+ postEditor.insertMarkers(position, [atom])
+ })
+ return atom
}
/**
@@ -1079,33 +1102,37 @@ class Editor {
* @return {Card} The inserted Card section.
* @public
*/
- insertCard(cardName, cardPayload={}, inEditMode=false) {
- if (!this.hasCursor()) { return; }
+ insertCard(cardName, cardPayload = {}, inEditMode = false) {
+ if (!this.hasCursor()) {
+ return
+ }
if (this.post.isBlank) {
- this._insertEmptyMarkupSectionAtCursor();
+ this._insertEmptyMarkupSectionAtCursor()
}
- let card;
- let { range } = this;
+ let card
+ let { range } = this
this.run(postEditor => {
- let position = range.tail;
- card = postEditor.builder.createCardSection(cardName, cardPayload);
+ let position = range.tail
+ card = postEditor.builder.createCardSection(cardName, cardPayload)
if (inEditMode) {
- this.editCard(card);
+ this.editCard(card)
}
if (!range.isCollapsed) {
- position = postEditor.deleteRange(range);
+ position = postEditor.deleteRange(range)
}
- let section = position.section;
- if (section.isNested) { section = section.parent; }
+ let section = position.section
+ if (section.isNested) {
+ section = section.parent
+ }
if (section.isBlank) {
- postEditor.replaceSection(section, card);
+ postEditor.replaceSection(section, card)
} else {
- let collection = this.post.sections;
- postEditor.insertSectionBefore(collection, card, section.next);
+ let collection = this.post.sections
+ postEditor.insertSectionBefore(collection, card, section.next)
}
// It is important to explicitly set the range to the end of the card.
@@ -1116,9 +1143,9 @@ class Editor {
// will cause an unexpected DOM mutation (which can wipe out the
// card).
// See: https://github.com/bustle/mobiledoc-kit/issues/286
- postEditor.setRange(card.tailPosition());
- });
- return card;
+ postEditor.setRange(card.tailPosition())
+ })
+ return card
}
/**
@@ -1127,40 +1154,40 @@ class Editor {
* @return {Position|null}
*/
positionAtPoint(x, y) {
- return Position.atPoint(x, y, this);
+ return Position.atPoint(x, y, this)
}
/**
* @private
*/
_setCardMode(cardSection, mode) {
- const renderNode = cardSection.renderNode;
+ const renderNode = cardSection.renderNode
if (renderNode && renderNode.isRendered) {
- const cardNode = renderNode.cardNode;
- cardNode[mode]();
+ const cardNode = renderNode.cardNode
+ cardNode[mode]()
} else {
- cardSection.setInitialMode(mode);
+ cardSection.setInitialMode(mode)
}
}
triggerEvent(context, eventName, event) {
- this._eventManager._trigger(context, eventName, event);
+ this._eventManager._trigger(context, eventName, event)
}
addCallback(...args) {
- this._callbacks.addCallback(...args);
+ this._callbacks.addCallback(...args)
}
addCallbackOnce(...args) {
- this._callbacks.addCallbackOnce(...args);
+ this._callbacks.addCallbackOnce(...args)
}
runCallbacks(...args) {
if (this.isDestroyed) {
// TODO warn that callback attempted after editor was destroyed
- return;
+ return
}
- this._callbacks.runCallbacks(...args);
+ this._callbacks.runCallbacks(...args)
}
/**
@@ -1170,13 +1197,13 @@ class Editor {
* @private
*/
_runBeforeHooks(hookName, ...args) {
- let hooks = this._beforeHooks[hookName] || [];
+ let hooks = this._beforeHooks[hookName] || []
for (let i = 0; i < hooks.length; i++) {
if (hooks[i](...args) === false) {
- return true;
+ return true
}
}
}
}
-export default Editor;
+export default Editor
diff --git a/src/js/editor/event-manager.js b/src/js/editor/event-manager.js
index 6671f7805..ea6aa7408 100644
--- a/src/js/editor/event-manager.js
+++ b/src/js/editor/event-manager.js
@@ -1,79 +1,74 @@
-import assert from 'mobiledoc-kit/utils/assert';
-import {
- parsePostFromPaste,
- setClipboardData,
- parsePostFromDrop
-} from 'mobiledoc-kit/utils/parse-utils';
-import { filter, forEach } from 'mobiledoc-kit/utils/array-utils';
-import Key from 'mobiledoc-kit/utils/key';
-import TextInputHandler from 'mobiledoc-kit/editor/text-input-handler';
-import SelectionManager from 'mobiledoc-kit/editor/selection-manager';
-import Browser from 'mobiledoc-kit/utils/browser';
-
-const ELEMENT_EVENT_TYPES = [
- 'keydown', 'keyup', 'cut', 'copy', 'paste', 'keypress', 'drop'
-];
+import assert from 'mobiledoc-kit/utils/assert'
+import { parsePostFromPaste, setClipboardData, parsePostFromDrop } from 'mobiledoc-kit/utils/parse-utils'
+import { filter, forEach } from 'mobiledoc-kit/utils/array-utils'
+import Key from 'mobiledoc-kit/utils/key'
+import TextInputHandler from 'mobiledoc-kit/editor/text-input-handler'
+import SelectionManager from 'mobiledoc-kit/editor/selection-manager'
+import Browser from 'mobiledoc-kit/utils/browser'
+
+const ELEMENT_EVENT_TYPES = ['keydown', 'keyup', 'cut', 'copy', 'paste', 'keypress', 'drop']
export default class EventManager {
constructor(editor) {
- this.editor = editor;
- this.logger = editor.loggerFor('event-manager');
- this._textInputHandler = new TextInputHandler(editor);
- this._listeners = [];
+ this.editor = editor
+ this.logger = editor.loggerFor('event-manager')
+ this._textInputHandler = new TextInputHandler(editor)
+ this._listeners = []
this.modifierKeys = {
- shift: false
- };
+ shift: false,
+ }
- this._selectionManager = new SelectionManager(
- this.editor, this.selectionDidChange.bind(this));
- this.started = true;
+ this._selectionManager = new SelectionManager(this.editor, this.selectionDidChange.bind(this))
+ this.started = true
}
init() {
- let { editor: { element } } = this;
- assert(`Cannot init EventManager without element`, !!element);
+ let {
+ editor: { element },
+ } = this
+ assert(`Cannot init EventManager without element`, !!element)
ELEMENT_EVENT_TYPES.forEach(type => {
- this._addListener(element, type);
- });
+ this._addListener(element, type)
+ })
- this._selectionManager.start();
+ this._selectionManager.start()
}
start() {
- this.started = true;
+ this.started = true
}
stop() {
- this.started = false;
+ this.started = false
}
registerInputHandler(inputHandler) {
- this._textInputHandler.register(inputHandler);
+ this._textInputHandler.register(inputHandler)
}
unregisterInputHandler(name) {
- this._textInputHandler.unregister(name);
+ this._textInputHandler.unregister(name)
}
unregisterAllTextInputHandlers() {
- this._textInputHandler.destroy();
- this._textInputHandler = new TextInputHandler(this.editor);
+ this._textInputHandler.destroy()
+ this._textInputHandler = new TextInputHandler(this.editor)
}
_addListener(context, type) {
- assert(`Missing listener for ${type}`, !!this[type]);
+ assert(`Missing listener for ${type}`, !!this[type])
- let listener = (event) => this._handleEvent(type, event);
- context.addEventListener(type, listener);
- this._listeners.push([context, type, listener]);
+ let listener = event => this._handleEvent(type, event)
+ context.addEventListener(type, listener)
+ this._listeners.push([context, type, listener])
}
_removeListeners() {
this._listeners.forEach(([context, type, listener]) => {
- context.removeEventListener(type, listener);
- });
- this._listeners = [];
+ context.removeEventListener(type, listener)
+ })
+ this._listeners = []
}
// This is primarily useful for programmatically simulating events on the
@@ -81,211 +76,223 @@ export default class EventManager {
_trigger(context, type, event) {
forEach(
filter(this._listeners, ([_context, _type]) => {
- return _context === context && _type === type;
+ return _context === context && _type === type
}),
- ([context,, listener]) => {
- listener.call(context, event);
+ ([context, , listener]) => {
+ listener.call(context, event)
}
- );
+ )
}
destroy() {
- this._textInputHandler.destroy();
- this._selectionManager.destroy();
- this._removeListeners();
+ this._textInputHandler.destroy()
+ this._selectionManager.destroy()
+ this._removeListeners()
}
_handleEvent(type, event) {
- let {target: element} = event;
+ let { target: element } = event
if (!this.started) {
// abort handling this event
- return true;
+ return true
}
if (!this.isElementAddressable(element)) {
// abort handling this event
- return true;
+ return true
}
- this[type](event);
+ this[type](event)
}
isElementAddressable(element) {
- return this.editor.cursor.isAddressable(element);
+ return this.editor.cursor.isAddressable(element)
}
selectionDidChange(selection /*, prevSelection */) {
- let shouldNotify = true;
- let { anchorNode } = selection;
+ let shouldNotify = true
+ let { anchorNode } = selection
if (!this.isElementAddressable(anchorNode)) {
if (!this.editor.range.isBlank) {
// Selection changed from something addressable to something
// not-addressable -- e.g., blur event, user clicked outside editor,
// etc
- shouldNotify = true;
+ shouldNotify = true
} else {
// selection changes wholly outside the editor should not trigger
// change notifications
- shouldNotify = false;
+ shouldNotify = false
}
}
if (shouldNotify) {
- this.editor._readRangeFromDOM();
+ this.editor._readRangeFromDOM()
}
}
keypress(event) {
- let { editor, _textInputHandler } = this;
- if (!editor.hasCursor()) { return; }
+ let { editor, _textInputHandler } = this
+ if (!editor.hasCursor()) {
+ return
+ }
- let key = Key.fromEvent(event);
+ let key = Key.fromEvent(event)
if (!key.isPrintable()) {
- return;
+ return
} else {
- event.preventDefault();
+ event.preventDefault()
}
- _textInputHandler.handle(key.toString());
+ _textInputHandler.handle(key.toString())
}
keydown(event) {
- let { editor } = this;
- if (!editor.hasCursor()) { return; }
- if (!editor.isEditable) { return; }
+ let { editor } = this
+ if (!editor.hasCursor()) {
+ return
+ }
+ if (!editor.isEditable) {
+ return
+ }
- let key = Key.fromEvent(event);
- this._updateModifiersFromKey(key, {isDown:true});
+ let key = Key.fromEvent(event)
+ this._updateModifiersFromKey(key, { isDown: true })
- if (editor.handleKeyCommand(event)) { return; }
+ if (editor.handleKeyCommand(event)) {
+ return
+ }
if (editor.post.isBlank) {
- editor._insertEmptyMarkupSectionAtCursor();
+ editor._insertEmptyMarkupSectionAtCursor()
}
- let range = editor.range;
+ let range = editor.range
- switch(true) {
+ switch (true) {
// FIXME This should be restricted to only card/atom boundaries
case key.isHorizontalArrowWithoutModifiersOtherThanShift(): {
- let newRange;
+ let newRange
if (key.isShift()) {
- newRange = range.extend(key.direction * 1);
+ newRange = range.extend(key.direction * 1)
} else {
- newRange = range.move(key.direction);
+ newRange = range.move(key.direction)
}
- editor.selectRange(newRange);
- event.preventDefault();
- break;
+ editor.selectRange(newRange)
+ event.preventDefault()
+ break
}
case key.isDelete(): {
- let { direction } = key;
- let unit = 'char';
+ let { direction } = key
+ let unit = 'char'
if (key.altKey && Browser.isMac()) {
- unit = 'word';
+ unit = 'word'
} else if (key.ctrlKey && !Browser.isMac()) {
- unit = 'word';
+ unit = 'word'
}
- editor.performDelete({direction, unit});
- event.preventDefault();
- break;
+ editor.performDelete({ direction, unit })
+ event.preventDefault()
+ break
}
case key.isEnter():
- this._textInputHandler.handleNewLine();
- editor.handleNewline(event);
- break;
+ this._textInputHandler.handleNewLine()
+ editor.handleNewline(event)
+ break
case key.isTab():
// Handle tab here because it does not fire a `keypress` event
- event.preventDefault();
- this._textInputHandler.handle(key.toString());
- break;
+ event.preventDefault()
+ this._textInputHandler.handle(key.toString())
+ break
}
}
keyup(event) {
- let { editor } = this;
- if (!editor.hasCursor()) { return; }
- let key = Key.fromEvent(event);
- this._updateModifiersFromKey(key, {isDown:false});
+ let { editor } = this
+ if (!editor.hasCursor()) {
+ return
+ }
+ let key = Key.fromEvent(event)
+ this._updateModifiersFromKey(key, { isDown: false })
}
cut(event) {
- event.preventDefault();
+ event.preventDefault()
- this.copy(event);
- this.editor.performDelete();
+ this.copy(event)
+ this.editor.performDelete()
}
copy(event) {
- event.preventDefault();
+ event.preventDefault()
- let { editor, editor: { range, post } } = this;
- post = post.trimTo(range);
+ let {
+ editor,
+ editor: { range, post },
+ } = this
+ post = post.trimTo(range)
let data = {
html: editor.serializePost(post, 'html'),
text: editor.serializePost(post, 'text'),
- mobiledoc: editor.serializePost(post, 'mobiledoc')
- };
+ mobiledoc: editor.serializePost(post, 'mobiledoc'),
+ }
- editor.runCallbacks('willCopy', [data]);
+ editor.runCallbacks('willCopy', [data])
- setClipboardData(event, data, window);
+ setClipboardData(event, data, window)
}
paste(event) {
- event.preventDefault();
+ event.preventDefault()
- let { editor } = this;
- let range = editor.range;
+ let { editor } = this
+ let range = editor.range
if (!range.isCollapsed) {
- editor.performDelete();
+ editor.performDelete()
}
if (editor.post.isBlank) {
- editor._insertEmptyMarkupSectionAtCursor();
+ editor._insertEmptyMarkupSectionAtCursor()
}
- let position = editor.range.head;
- let targetFormat = this.modifierKeys.shift ? 'text' : 'html';
- let pastedPost = parsePostFromPaste(event, editor, {targetFormat});
+ let position = editor.range.head
+ let targetFormat = this.modifierKeys.shift ? 'text' : 'html'
+ let pastedPost = parsePostFromPaste(event, editor, { targetFormat })
editor.run(postEditor => {
- let nextPosition = postEditor.insertPost(position, pastedPost);
- postEditor.setRange(nextPosition);
- });
+ let nextPosition = postEditor.insertPost(position, pastedPost)
+ postEditor.setRange(nextPosition)
+ })
}
drop(event) {
- event.preventDefault();
+ event.preventDefault()
- let { clientX: x, clientY: y } = event;
- let { editor } = this;
+ let { clientX: x, clientY: y } = event
+ let { editor } = this
- let position = editor.positionAtPoint(x, y);
+ let position = editor.positionAtPoint(x, y)
if (!position) {
- this.logger.log('Could not find drop position');
- return;
+ this.logger.log('Could not find drop position')
+ return
}
- let post = parsePostFromDrop(event, editor, {logger: this.logger});
+ let post = parsePostFromDrop(event, editor, { logger: this.logger })
if (!post) {
- this.logger.log('Could not determine post from drop event');
- return;
+ this.logger.log('Could not determine post from drop event')
+ return
}
editor.run(postEditor => {
- let nextPosition = postEditor.insertPost(position, post);
- postEditor.setRange(nextPosition);
- });
+ let nextPosition = postEditor.insertPost(position, post)
+ postEditor.setRange(nextPosition)
+ })
}
- _updateModifiersFromKey(key, {isDown}) {
+ _updateModifiersFromKey(key, { isDown }) {
if (key.isShiftKey()) {
- this.modifierKeys.shift = isDown;
+ this.modifierKeys.shift = isDown
}
}
-
}
diff --git a/src/js/editor/key-commands.js b/src/js/editor/key-commands.js
index f8bf610ef..8ea7c3c49 100644
--- a/src/js/editor/key-commands.js
+++ b/src/js/editor/key-commands.js
@@ -1,187 +1,213 @@
-import Key from '../utils/key';
-import { MODIFIERS, specialCharacterToCode } from '../utils/key';
-import { filter, reduce } from '../utils/array-utils';
-import assert from '../utils/assert';
-import Browser from '../utils/browser';
-import { toggleLink } from './ui';
+import Key from '../utils/key'
+import { MODIFIERS, specialCharacterToCode } from '../utils/key'
+import { filter, reduce } from '../utils/array-utils'
+import assert from '../utils/assert'
+import Browser from '../utils/browser'
+import { toggleLink } from './ui'
function selectAll(editor) {
- let { post } = editor;
- editor.selectRange(post.toRange());
+ let { post } = editor
+ editor.selectRange(post.toRange())
}
function gotoStartOfLine(editor) {
- let {range} = editor;
- let {tail: {section}} = range;
+ let { range } = editor
+ let {
+ tail: { section },
+ } = range
editor.run(postEditor => {
- postEditor.setRange(section.headPosition());
- });
+ postEditor.setRange(section.headPosition())
+ })
}
function gotoEndOfLine(editor) {
- let {range} = editor;
- let {tail: {section}} = range;
+ let { range } = editor
+ let {
+ tail: { section },
+ } = range
editor.run(postEditor => {
- postEditor.setRange(section.tailPosition());
- });
+ postEditor.setRange(section.tailPosition())
+ })
}
function deleteToEndOfSection(editor) {
- let { range } = editor;
+ let { range } = editor
if (range.isCollapsed) {
- let { head, head: { section } } = range;
- range = head.toRange(section.tailPosition());
+ let {
+ head,
+ head: { section },
+ } = range
+ range = head.toRange(section.tailPosition())
}
editor.run(postEditor => {
- let nextPosition = postEditor.deleteRange(range);
- postEditor.setRange(nextPosition);
- });
+ let nextPosition = postEditor.deleteRange(range)
+ postEditor.setRange(nextPosition)
+ })
}
-export const DEFAULT_KEY_COMMANDS = [{
- str: 'META+B',
- run(editor) {
- editor.toggleMarkup('strong');
- }
-}, {
- str: 'CTRL+B',
- run(editor) {
- editor.toggleMarkup('strong');
- }
-}, {
- str: 'META+I',
- run(editor) {
- editor.toggleMarkup('em');
- }
-}, {
- str: 'CTRL+I',
- run(editor) {
- editor.toggleMarkup('em');
- }
-}, {
- str: 'META+U',
- run(editor) {
- editor.toggleMarkup('u');
- }
-}, {
- str: 'CTRL+U',
- run(editor) {
- editor.toggleMarkup('u');
- }
-}, {
- str: 'CTRL+K',
- run(editor) {
- if (Browser.isMac()) {
- return deleteToEndOfSection(editor);
- } else if (Browser.isWin()) {
- return toggleLink(editor);
- }
- }
-}, {
- str: 'CTRL+A',
- run(editor) {
- if (Browser.isMac()) {
- gotoStartOfLine(editor);
- } else {
- selectAll(editor);
- }
- }
-}, {
- str: 'META+A',
- run(editor) {
- if (Browser.isMac()) {
- selectAll(editor);
- }
- }
-}, {
- str: 'CTRL+E',
- run(editor) {
- if (Browser.isMac()) {
- gotoEndOfLine(editor);
- }
- }
-}, {
- str: 'META+K',
- run(editor) {
- return toggleLink(editor);
+export const DEFAULT_KEY_COMMANDS = [
+ {
+ str: 'META+B',
+ run(editor) {
+ editor.toggleMarkup('strong')
+ },
},
-
-}, {
- str: 'META+Z',
- run(editor) {
- editor.run(postEditor => {
- postEditor.undoLastChange();
- });
- }
-}, {
- str: 'META+SHIFT+Z',
- run(editor) {
- editor.run(postEditor => {
- postEditor.redoLastChange();
- });
- }
-}, {
- str: 'CTRL+Z',
- run(editor) {
- if (Browser.isMac()) { return false; }
- editor.run(postEditor => postEditor.undoLastChange());
- }
-}, {
- str: 'CTRL+SHIFT+Z',
- run(editor) {
- if (Browser.isMac()) { return false; }
- editor.run(postEditor => postEditor.redoLastChange());
- }
-}];
+ {
+ str: 'CTRL+B',
+ run(editor) {
+ editor.toggleMarkup('strong')
+ },
+ },
+ {
+ str: 'META+I',
+ run(editor) {
+ editor.toggleMarkup('em')
+ },
+ },
+ {
+ str: 'CTRL+I',
+ run(editor) {
+ editor.toggleMarkup('em')
+ },
+ },
+ {
+ str: 'META+U',
+ run(editor) {
+ editor.toggleMarkup('u')
+ },
+ },
+ {
+ str: 'CTRL+U',
+ run(editor) {
+ editor.toggleMarkup('u')
+ },
+ },
+ {
+ str: 'CTRL+K',
+ run(editor) {
+ if (Browser.isMac()) {
+ return deleteToEndOfSection(editor)
+ } else if (Browser.isWin()) {
+ return toggleLink(editor)
+ }
+ },
+ },
+ {
+ str: 'CTRL+A',
+ run(editor) {
+ if (Browser.isMac()) {
+ gotoStartOfLine(editor)
+ } else {
+ selectAll(editor)
+ }
+ },
+ },
+ {
+ str: 'META+A',
+ run(editor) {
+ if (Browser.isMac()) {
+ selectAll(editor)
+ }
+ },
+ },
+ {
+ str: 'CTRL+E',
+ run(editor) {
+ if (Browser.isMac()) {
+ gotoEndOfLine(editor)
+ }
+ },
+ },
+ {
+ str: 'META+K',
+ run(editor) {
+ return toggleLink(editor)
+ },
+ },
+ {
+ str: 'META+Z',
+ run(editor) {
+ editor.run(postEditor => {
+ postEditor.undoLastChange()
+ })
+ },
+ },
+ {
+ str: 'META+SHIFT+Z',
+ run(editor) {
+ editor.run(postEditor => {
+ postEditor.redoLastChange()
+ })
+ },
+ },
+ {
+ str: 'CTRL+Z',
+ run(editor) {
+ if (Browser.isMac()) {
+ return false
+ }
+ editor.run(postEditor => postEditor.undoLastChange())
+ },
+ },
+ {
+ str: 'CTRL+SHIFT+Z',
+ run(editor) {
+ if (Browser.isMac()) {
+ return false
+ }
+ editor.run(postEditor => postEditor.redoLastChange())
+ },
+ },
+]
function modifierNamesToMask(modiferNames) {
- let defaultVal = 0;
- return reduce(modiferNames,
- (sum, name) => {
- let modifier = MODIFIERS[name.toUpperCase()];
- assert(`No modifier named "${name}" found`, !!modifier);
- return sum + modifier;
- },
- defaultVal);
+ let defaultVal = 0
+ return reduce(
+ modiferNames,
+ (sum, name) => {
+ let modifier = MODIFIERS[name.toUpperCase()]
+ assert(`No modifier named "${name}" found`, !!modifier)
+ return sum + modifier
+ },
+ defaultVal
+ )
}
function characterToCode(character) {
- const upperCharacter = character.toUpperCase();
- const special = specialCharacterToCode(upperCharacter);
+ const upperCharacter = character.toUpperCase()
+ const special = specialCharacterToCode(upperCharacter)
if (special) {
- return special;
+ return special
} else {
- assert(`Only 1 character can be used in a key command str (got "${character}")`,
- character.length === 1);
- return upperCharacter.charCodeAt(0);
+ assert(`Only 1 character can be used in a key command str (got "${character}")`, character.length === 1)
+ return upperCharacter.charCodeAt(0)
}
}
export function buildKeyCommand(keyCommand) {
- let { str } = keyCommand;
+ let { str } = keyCommand
if (!str) {
- return keyCommand;
+ return keyCommand
}
- assert('[deprecation] Key commands no longer use the `modifier` property',
- !keyCommand.modifier);
+ assert('[deprecation] Key commands no longer use the `modifier` property', !keyCommand.modifier)
- let [character, ...modifierNames] = str.split('+').reverse();
+ let [character, ...modifierNames] = str.split('+').reverse()
- keyCommand.modifierMask = modifierNamesToMask(modifierNames);
- keyCommand.code = characterToCode(character);
+ keyCommand.modifierMask = modifierNamesToMask(modifierNames)
+ keyCommand.code = characterToCode(character)
- return keyCommand;
+ return keyCommand
}
export function validateKeyCommand(keyCommand) {
- return !!keyCommand.code && !!keyCommand.run;
+ return !!keyCommand.code && !!keyCommand.run
}
export function findKeyCommands(keyCommands, keyEvent) {
- const key = Key.fromEvent(keyEvent);
+ const key = Key.fromEvent(keyEvent)
- return filter(keyCommands, ({modifierMask, code}) => {
- return key.keyCode === code && key.modifierMask === modifierMask;
- });
+ return filter(keyCommands, ({ modifierMask, code }) => {
+ return key.keyCode === code && key.modifierMask === modifierMask
+ })
}
diff --git a/src/js/editor/mutation-handler.js b/src/js/editor/mutation-handler.js
index d93476a66..a72dc5fb1 100644
--- a/src/js/editor/mutation-handler.js
+++ b/src/js/editor/mutation-handler.js
@@ -1,69 +1,69 @@
-import Set from 'mobiledoc-kit/utils/set';
-import { forEach, filter } from 'mobiledoc-kit/utils/array-utils';
-import assert from 'mobiledoc-kit/utils/assert';
-import { containsNode } from 'mobiledoc-kit/utils/dom-utils';
+import Set from 'mobiledoc-kit/utils/set'
+import { forEach, filter } from 'mobiledoc-kit/utils/array-utils'
+import assert from 'mobiledoc-kit/utils/assert'
+import { containsNode } from 'mobiledoc-kit/utils/dom-utils'
const MUTATION = {
NODES_CHANGED: 'childList',
- CHARACTER_DATA: 'characterData'
-};
+ CHARACTER_DATA: 'characterData',
+}
export default class MutationHandler {
constructor(editor) {
- this.editor = editor;
- this.logger = editor.loggerFor('mutation-handler');
- this.renderTree = null;
- this._isObserving = false;
-
- this._observer = new MutationObserver((mutations) => {
- this._handleMutations(mutations);
- });
+ this.editor = editor
+ this.logger = editor.loggerFor('mutation-handler')
+ this.renderTree = null
+ this._isObserving = false
+
+ this._observer = new MutationObserver(mutations => {
+ this._handleMutations(mutations)
+ })
}
init() {
- this.startObserving();
+ this.startObserving()
}
destroy() {
- this.stopObserving();
- this._observer = null;
+ this.stopObserving()
+ this._observer = null
}
suspendObservation(callback) {
- this.stopObserving();
- callback();
- this.startObserving();
+ this.stopObserving()
+ callback()
+ this.startObserving()
}
stopObserving() {
if (this._isObserving) {
- this._isObserving = false;
- this._observer.disconnect();
+ this._isObserving = false
+ this._observer.disconnect()
}
}
startObserving() {
if (!this._isObserving) {
- let { editor } = this;
- assert('Cannot observe un-rendered editor', editor.hasRendered);
+ let { editor } = this
+ assert('Cannot observe un-rendered editor', editor.hasRendered)
- this._isObserving = true;
- this.renderTree = editor._renderTree;
+ this._isObserving = true
+ this.renderTree = editor._renderTree
this._observer.observe(editor.element, {
characterData: true,
childList: true,
- subtree: true
- });
+ subtree: true,
+ })
}
}
reparsePost() {
- this.editor._reparsePost();
+ this.editor._reparsePost()
}
reparseSections(sections) {
- this.editor._reparseSections(sections);
+ this.editor._reparseSections(sections)
}
/**
@@ -80,77 +80,76 @@ export default class MutationHandler {
* * if no section, reparse all (and break)
*/
_handleMutations(mutations) {
- let reparsePost = false;
- let sections = new Set();
+ let reparsePost = false
+ let sections = new Set()
for (let i = 0; i < mutations.length; i++) {
if (reparsePost) {
- break;
+ break
}
- let nodes = this._findTargetNodes(mutations[i]);
+ let nodes = this._findTargetNodes(mutations[i])
- for (let j=0; j < nodes.length; j++) {
- let node = nodes[j];
- let renderNode = this._findRenderNodeFromNode(node);
+ for (let j = 0; j < nodes.length; j++) {
+ let node = nodes[j]
+ let renderNode = this._findRenderNodeFromNode(node)
if (renderNode) {
if (renderNode.reparsesMutationOfChildNode(node)) {
- let section = this._findSectionFromRenderNode(renderNode);
+ let section = this._findSectionFromRenderNode(renderNode)
if (section) {
- sections.add(section);
+ sections.add(section)
} else {
- reparsePost = true;
+ reparsePost = true
}
}
} else {
- reparsePost = true;
- break;
+ reparsePost = true
+ break
}
}
}
if (reparsePost) {
- this.logger.log(`reparsePost (${mutations.length} mutations)`);
- this.reparsePost();
+ this.logger.log(`reparsePost (${mutations.length} mutations)`)
+ this.reparsePost()
} else if (sections.length) {
- this.logger.log(`reparse ${sections.length} sections (${mutations.length} mutations)`);
- this.reparseSections(sections.toArray());
+ this.logger.log(`reparse ${sections.length} sections (${mutations.length} mutations)`)
+ this.reparseSections(sections.toArray())
}
}
_findTargetNodes(mutation) {
- let nodes = [];
+ let nodes = []
switch (mutation.type) {
case MUTATION.CHARACTER_DATA:
- nodes.push(mutation.target);
- break;
+ nodes.push(mutation.target)
+ break
case MUTATION.NODES_CHANGED:
- forEach(mutation.addedNodes, n => nodes.push(n));
+ forEach(mutation.addedNodes, n => nodes.push(n))
if (mutation.removedNodes.length) {
- nodes.push(mutation.target);
+ nodes.push(mutation.target)
}
- break;
+ break
}
- let element = this.editor.element;
- let attachedNodes = filter(nodes, node => containsNode(element, node));
- return attachedNodes;
+ let element = this.editor.element
+ let attachedNodes = filter(nodes, node => containsNode(element, node))
+ return attachedNodes
}
_findSectionRenderNodeFromNode(node) {
- return this.renderTree.findRenderNodeFromElement(node, (rn) => {
- return rn.postNode.isSection;
- });
+ return this.renderTree.findRenderNodeFromElement(node, rn => {
+ return rn.postNode.isSection
+ })
}
_findRenderNodeFromNode(node) {
- return this.renderTree.findRenderNodeFromElement(node);
+ return this.renderTree.findRenderNodeFromElement(node)
}
_findSectionFromRenderNode(renderNode) {
- let sectionRenderNode = this._findSectionRenderNodeFromNode(renderNode.element);
- return sectionRenderNode && sectionRenderNode.postNode;
+ let sectionRenderNode = this._findSectionRenderNodeFromNode(renderNode.element)
+ return sectionRenderNode && sectionRenderNode.postNode
}
-
}
diff --git a/src/js/editor/post.js b/src/js/editor/post.js
index 4245afbe6..181e5a1e0 100644
--- a/src/js/editor/post.js
+++ b/src/js/editor/post.js
@@ -1,43 +1,43 @@
-import Position from '../utils/cursor/position';
-import Range from 'mobiledoc-kit/utils/cursor/range';
-import { detect, forEach, reduce, filter, values, commonItems } from '../utils/array-utils';
-import { DIRECTION } from '../utils/key';
-import LifecycleCallbacks from '../models/lifecycle-callbacks';
-import assert from '../utils/assert';
-import { normalizeTagName } from '../utils/dom-utils';
-import PostInserter from './post/post-inserter';
-import deprecate from 'mobiledoc-kit/utils/deprecate';
-import toRange from 'mobiledoc-kit/utils/to-range';
-
-const { FORWARD, BACKWARD } = DIRECTION;
+import Position from '../utils/cursor/position'
+import Range from 'mobiledoc-kit/utils/cursor/range'
+import { detect, forEach, reduce, filter, values, commonItems } from '../utils/array-utils'
+import { DIRECTION } from '../utils/key'
+import LifecycleCallbacks from '../models/lifecycle-callbacks'
+import assert from '../utils/assert'
+import { normalizeTagName } from '../utils/dom-utils'
+import PostInserter from './post/post-inserter'
+import deprecate from 'mobiledoc-kit/utils/deprecate'
+import toRange from 'mobiledoc-kit/utils/to-range'
+
+const { FORWARD, BACKWARD } = DIRECTION
function isListSectionTagName(tagName) {
- return tagName === 'ul' || tagName === 'ol';
+ return tagName === 'ul' || tagName === 'ol'
}
function shrinkRange(range) {
- const { head, tail } = range;
+ const { head, tail } = range
if (tail.offset === 0 && head.section !== tail.section) {
- range.tail = new Position(tail.section.prev, tail.section.prev.length);
+ range.tail = new Position(tail.section.prev, tail.section.prev.length)
}
- return range;
+ return range
}
const CALLBACK_QUEUES = {
BEFORE_COMPLETE: 'beforeComplete',
COMPLETE: 'complete',
- AFTER_COMPLETE: 'afterComplete'
-};
+ AFTER_COMPLETE: 'afterComplete',
+}
// There are only two events that we're concerned about for Undo, that is inserting text and deleting content.
// These are the only two states that go on a "run" and create a combined undo, everything else has it's own
// deadicated undo.
const EDIT_ACTIONS = {
INSERT_TEXT: 1,
- DELETE: 2
-};
+ DELETE: 2,
+}
/**
* The PostEditor is used to modify a post. It should not be instantiated directly.
@@ -57,33 +57,33 @@ class PostEditor {
* @private
*/
constructor(editor) {
- this.editor = editor;
- this.builder = this.editor.builder;
- this._callbacks = new LifecycleCallbacks(values(CALLBACK_QUEUES));
+ this.editor = editor
+ this.builder = this.editor.builder
+ this._callbacks = new LifecycleCallbacks(values(CALLBACK_QUEUES))
- this._didComplete = false;
- this.editActionTaken = null;
+ this._didComplete = false
+ this.editActionTaken = null
- this._renderRange = () => this.editor.selectRange(this._range);
- this._postDidChange = () => this.editor._postDidChange();
- this._rerender = () => this.editor.rerender();
+ this._renderRange = () => this.editor.selectRange(this._range)
+ this._postDidChange = () => this.editor._postDidChange()
+ this._rerender = () => this.editor.rerender()
}
addCallback(...args) {
- this._callbacks.addCallback(...args);
+ this._callbacks.addCallback(...args)
}
addCallbackOnce(...args) {
- this._callbacks.addCallbackOnce(...args);
+ this._callbacks.addCallbackOnce(...args)
}
runCallbacks(...args) {
- this._callbacks.runCallbacks(...args);
+ this._callbacks.runCallbacks(...args)
}
begin() {
// cache the editor's range
- this._range = this.editor.range;
+ this._range = this.editor.range
}
/**
@@ -105,12 +105,12 @@ class PostEditor {
* @public
*/
setRange(range) {
- range = toRange(range);
+ range = toRange(range)
// TODO validate that the range is valid
// (does not contain marked-for-removal head or tail sections?)
- this._range = range;
- this.scheduleAfterRender(this._renderRange, true);
+ this._range = range
+ this.scheduleAfterRender(this._renderRange, true)
}
/**
@@ -129,61 +129,65 @@ class PostEditor {
* @public
*/
deleteRange(range) {
- assert("Must pass MobiledocKit Range to `deleteRange`", range instanceof Range);
+ assert('Must pass MobiledocKit Range to `deleteRange`', range instanceof Range)
- this.editActionTaken = EDIT_ACTIONS.DELETE;
+ this.editActionTaken = EDIT_ACTIONS.DELETE
let {
- head, head: {section: headSection},
- tail, tail: {section: tailSection}
- } = range;
+ head,
+ head: { section: headSection },
+ tail,
+ tail: { section: tailSection },
+ } = range
- let { editor: { post } } = this;
+ let {
+ editor: { post },
+ } = this
if (headSection === tailSection) {
- return this.cutSection(headSection, head, tail);
+ return this.cutSection(headSection, head, tail)
}
- let nextSection = headSection.nextLeafSection();
+ let nextSection = headSection.nextLeafSection()
- let nextPos = this.cutSection(headSection, head, headSection.tailPosition());
+ let nextPos = this.cutSection(headSection, head, headSection.tailPosition())
// cutSection can replace the section, so re-read headSection here
- headSection = nextPos.section;
+ headSection = nextPos.section
// Remove sections in the middle of the range
while (nextSection !== tailSection) {
- let tmp = nextSection;
- nextSection = nextSection.nextLeafSection();
- this.removeSection(tmp);
+ let tmp = nextSection
+ nextSection = nextSection.nextLeafSection()
+ this.removeSection(tmp)
}
- let tailPos = this.cutSection(tailSection, tailSection.headPosition(), tail);
+ let tailPos = this.cutSection(tailSection, tailSection.headPosition(), tail)
// cutSection can replace the section, so re-read tailSection here
- tailSection = tailPos.section;
+ tailSection = tailPos.section
if (tailSection.isBlank) {
- this.removeSection(tailSection);
+ this.removeSection(tailSection)
} else {
// If head and tail sections are markerable, join them
// Note: They may not be the same section type. E.g. this may join
// a tail section that was a list item onto a markup section, or vice versa.
// (This is the desired behavior.)
if (headSection.isMarkerable && tailSection.isMarkerable) {
- headSection.join(tailSection);
- this._markDirty(headSection);
- this.removeSection(tailSection);
+ headSection.join(tailSection)
+ this._markDirty(headSection)
+ this.removeSection(tailSection)
} else if (headSection.isBlank) {
- this.removeSection(headSection);
- nextPos = tailPos;
+ this.removeSection(headSection)
+ nextPos = tailPos
}
}
if (post.isBlank) {
- post.sections.append(this.builder.createMarkupSection('p'));
- nextPos = post.headPosition();
+ post.sections.append(this.builder.createMarkupSection('p'))
+ nextPos = post.headPosition()
}
- return nextPos;
+ return nextPos
}
/**
@@ -202,34 +206,35 @@ class PostEditor {
* @private
*/
cutSection(section, head, tail) {
- assert('Must pass head position and tail position to `cutSection`',
- head instanceof Position && tail instanceof Position);
- assert('Must pass positions within same section to `cutSection`',
- head.section === tail.section);
+ assert(
+ 'Must pass head position and tail position to `cutSection`',
+ head instanceof Position && tail instanceof Position
+ )
+ assert('Must pass positions within same section to `cutSection`', head.section === tail.section)
if (section.isBlank || head.isEqual(tail)) {
- return head;
+ return head
}
if (section.isCardSection) {
if (head.isHead() && tail.isTail()) {
- let newSection = this.builder.createMarkupSection();
- this.replaceSection(section, newSection);
- return newSection.headPosition();
+ let newSection = this.builder.createMarkupSection()
+ this.replaceSection(section, newSection)
+ return newSection.headPosition()
} else {
- return tail;
+ return tail
}
}
- let range = head.toRange(tail);
- this.splitMarkers(range).forEach(m => this.removeMarker(m));
+ let range = head.toRange(tail)
+ this.splitMarkers(range).forEach(m => this.removeMarker(m))
- return head;
+ return head
}
_coalesceMarkers(section) {
if (section.isMarkerable) {
- this._removeBlankMarkers(section);
- this._joinSimilarMarkers(section);
+ this._removeBlankMarkers(section)
+ this._joinSimilarMarkers(section)
}
}
@@ -237,129 +242,120 @@ class PostEditor {
forEach(
filter(section.markers, m => m.isBlank),
m => this.removeMarker(m)
- );
+ )
}
// joins markers that have identical markups
_joinSimilarMarkers(section) {
- let marker = section.markers.head;
- let nextMarker;
+ let marker = section.markers.head
+ let nextMarker
while (marker && marker.next) {
- nextMarker = marker.next;
+ nextMarker = marker.next
if (marker.canJoin(nextMarker)) {
- nextMarker.value = marker.value + nextMarker.value;
- this._markDirty(nextMarker);
- this.removeMarker(marker);
+ nextMarker.value = marker.value + nextMarker.value
+ this._markDirty(nextMarker)
+ this.removeMarker(marker)
}
- marker = nextMarker;
+ marker = nextMarker
}
}
removeMarker(marker) {
- this._scheduleForRemoval(marker);
+ this._scheduleForRemoval(marker)
if (marker.section) {
- this._markDirty(marker.section);
- marker.section.markers.remove(marker);
+ this._markDirty(marker.section)
+ marker.section.markers.remove(marker)
}
}
_scheduleForRemoval(postNode) {
if (postNode.renderNode) {
- postNode.renderNode.scheduleForRemoval();
+ postNode.renderNode.scheduleForRemoval()
- this.scheduleRerender();
- this.scheduleDidUpdate();
+ this.scheduleRerender()
+ this.scheduleDidUpdate()
}
- let removedAdjacentToList = (postNode.prev && postNode.prev.isListSection) ||
- (postNode.next && postNode.next.isListSection);
+ let removedAdjacentToList =
+ (postNode.prev && postNode.prev.isListSection) || (postNode.next && postNode.next.isListSection)
if (removedAdjacentToList) {
- this.addCallback(
- CALLBACK_QUEUES.BEFORE_COMPLETE,
- () => this._joinContiguousListSections()
- );
+ this.addCallback(CALLBACK_QUEUES.BEFORE_COMPLETE, () => this._joinContiguousListSections())
}
}
_joinContiguousListSections() {
- let { post } = this.editor;
- let range = this._range;
- let prev;
- let groups = [];
- let currentGroup;
+ let { post } = this.editor
+ let range = this._range
+ let prev
+ let groups = []
+ let currentGroup
// FIXME do we need to force a re-render of the range if changed sections
// are contained within the range?
- let updatedHead = null;
+ let updatedHead = null
forEach(post.sections, section => {
- if (prev &&
- prev.isListSection &&
- section.isListSection &&
- prev.tagName === section.tagName) {
-
- currentGroup = currentGroup || [prev];
- currentGroup.push(section);
+ if (prev && prev.isListSection && section.isListSection && prev.tagName === section.tagName) {
+ currentGroup = currentGroup || [prev]
+ currentGroup.push(section)
} else {
if (currentGroup) {
- groups.push(currentGroup);
+ groups.push(currentGroup)
}
- currentGroup = null;
+ currentGroup = null
}
- prev = section;
- });
+ prev = section
+ })
if (currentGroup) {
- groups.push(currentGroup);
+ groups.push(currentGroup)
}
forEach(groups, group => {
- let list = group[0];
+ let list = group[0]
forEach(group, listSection => {
if (listSection === list) {
- return;
+ return
}
- let currentHead = range.head;
- let prevPosition;
+ let currentHead = range.head
+ let prevPosition
// FIXME is there a currentHead if there is no range?
// is the current head a list item in the section
- if (!range.isBlank && currentHead.section.isListItem &&
- currentHead.section.parent === listSection) {
- prevPosition = list.tailPosition();
+ if (!range.isBlank && currentHead.section.isListItem && currentHead.section.parent === listSection) {
+ prevPosition = list.tailPosition()
}
- this._joinListSections(list, listSection);
+ this._joinListSections(list, listSection)
if (prevPosition) {
- updatedHead = prevPosition.move(FORWARD);
+ updatedHead = prevPosition.move(FORWARD)
}
- });
- });
+ })
+ })
if (updatedHead) {
- this.setRange(updatedHead);
+ this.setRange(updatedHead)
}
}
_joinListSections(baseList, nextList) {
- baseList.join(nextList);
- this._markDirty(baseList);
- this.removeSection(nextList);
+ baseList.join(nextList)
+ this._markDirty(baseList)
+ this.removeSection(nextList)
}
_markDirty(postNode) {
if (postNode.renderNode) {
- postNode.renderNode.markDirty();
+ postNode.renderNode.markDirty()
- this.scheduleRerender();
- this.scheduleDidUpdate();
+ this.scheduleRerender()
+ this.scheduleDidUpdate()
}
if (postNode.section) {
- this._markDirty(postNode.section);
+ this._markDirty(postNode.section)
}
if (postNode.isMarkerable) {
- this.addCallback(
- CALLBACK_QUEUES.BEFORE_COMPLETE, () => this._coalesceMarkers(postNode));
+ this.addCallback(CALLBACK_QUEUES.BEFORE_COMPLETE, () => this._coalesceMarkers(postNode))
}
}
@@ -370,9 +366,11 @@ class PostEditor {
* @public
* @deprecated after v0.10.3
*/
- deleteFrom(position, direction=DIRECTION.BACKWARD) {
- deprecate("`postEditor#deleteFrom is deprecated. Use `deleteAtPosition(position, direction=BACKWARD, {unit}={unit: 'char'})` instead");
- return this.deleteAtPosition(position, direction, {unit: 'char'});
+ deleteFrom(position, direction = DIRECTION.BACKWARD) {
+ deprecate(
+ "`postEditor#deleteFrom is deprecated. Use `deleteAtPosition(position, direction=BACKWARD, {unit}={unit: 'char'})` instead"
+ )
+ return this.deleteAtPosition(position, direction, { unit: 'char' })
}
/**
@@ -397,29 +395,29 @@ class PostEditor {
* @param {String} [options.unit="char"] The unit of deletion ("word" or "char")
* @return {Position}
*/
- deleteAtPosition(position, direction=DIRECTION.BACKWARD, {unit}={unit: 'char'}) {
+ deleteAtPosition(position, direction = DIRECTION.BACKWARD, { unit } = { unit: 'char' }) {
if (direction === DIRECTION.BACKWARD) {
- return this._deleteAtPositionBackward(position, unit);
+ return this._deleteAtPositionBackward(position, unit)
} else {
- return this._deleteAtPositionForward(position, unit);
+ return this._deleteAtPositionForward(position, unit)
}
}
_deleteAtPositionBackward(position, unit) {
if (position.isHead() && position.section.isListItem) {
- this.toggleSection('p', position);
- return this._range.head;
+ this.toggleSection('p', position)
+ return this._range.head
} else {
- let prevPosition = unit === 'word' ? position.moveWord(BACKWARD) : position.move(BACKWARD);
- let range = prevPosition.toRange(position);
- return this.deleteRange(range);
+ let prevPosition = unit === 'word' ? position.moveWord(BACKWARD) : position.move(BACKWARD)
+ let range = prevPosition.toRange(position)
+ return this.deleteRange(range)
}
}
_deleteAtPositionForward(position, unit) {
- let nextPosition = unit === 'word' ? position.moveWord(FORWARD) : position.move(FORWARD);
- let range = position.toRange(nextPosition);
- return this.deleteRange(range);
+ let nextPosition = unit === 'word' ? position.moveWord(FORWARD) : position.move(FORWARD)
+ let range = position.toRange(nextPosition)
+ return this.deleteRange(range)
}
/**
@@ -441,18 +439,18 @@ class PostEditor {
* @private
*/
splitMarkers(range) {
- const { post } = this.editor;
- const { head, tail } = range;
+ const { post } = this.editor
+ const { head, tail } = range
- this.splitSectionMarkerAtOffset(head.section, head.offset);
- this.splitSectionMarkerAtOffset(tail.section, tail.offset);
+ this.splitSectionMarkerAtOffset(head.section, head.offset)
+ this.splitSectionMarkerAtOffset(tail.section, tail.offset)
- return post.markersContainedByRange(range);
+ return post.markersContainedByRange(range)
}
splitSectionMarkerAtOffset(section, offset) {
- const edit = section.splitMarkerAtOffset(offset);
- edit.removed.forEach(m => this.removeMarker(m));
+ const edit = section.splitMarkerAtOffset(offset)
+ edit.removed.forEach(m => this.removeMarker(m))
}
/**
@@ -476,31 +474,31 @@ class PostEditor {
* @public
*/
splitSection(position) {
- const { section } = position;
+ const { section } = position
if (section.isCardSection) {
- return this._splitCardSection(section, position);
+ return this._splitCardSection(section, position)
} else if (section.isListItem) {
- let isLastAndBlank = section.isBlank && !section.next;
+ let isLastAndBlank = section.isBlank && !section.next
if (isLastAndBlank) {
// if is last, replace the item with a blank markup section
- let parent = section.parent;
- let collection = this.editor.post.sections;
- let blank = this.builder.createMarkupSection();
- this.removeSection(section);
- this.insertSectionBefore(collection, blank, parent.next);
+ let parent = section.parent
+ let collection = this.editor.post.sections
+ let blank = this.builder.createMarkupSection()
+ this.removeSection(section)
+ this.insertSectionBefore(collection, blank, parent.next)
- return [null, blank];
+ return [null, blank]
} else {
- let [pre, post] = this._splitListItem(section, position);
- return [pre, post];
+ let [pre, post] = this._splitListItem(section, position)
+ return [pre, post]
}
} else {
- let splitSections = section.splitAtPosition(position);
- splitSections.forEach(s => this._coalesceMarkers(s));
- this._replaceSection(section, splitSections);
+ let splitSections = section.splitAtPosition(position)
+ splitSections.forEach(s => this._coalesceMarkers(s))
+ this._replaceSection(section, splitSections)
- return splitSections;
+ return splitSections
}
}
@@ -511,26 +509,25 @@ class PostEditor {
* @private
*/
_splitCardSection(cardSection, position) {
- let { offset } = position;
- assert('Cards section must be split at offset 0 or 1',
- offset === 0 || offset === 1);
+ let { offset } = position
+ assert('Cards section must be split at offset 0 or 1', offset === 0 || offset === 1)
- let newSection = this.builder.createMarkupSection();
- let nextSection;
- let surroundingSections;
+ let newSection = this.builder.createMarkupSection()
+ let nextSection
+ let surroundingSections
if (offset === 0) {
- nextSection = cardSection;
- surroundingSections = [newSection, cardSection];
+ nextSection = cardSection
+ surroundingSections = [newSection, cardSection]
} else {
- nextSection = cardSection.next;
- surroundingSections = [cardSection, newSection];
+ nextSection = cardSection.next
+ surroundingSections = [cardSection, newSection]
}
- let collection = this.editor.post.sections;
- this.insertSectionBefore(collection, newSection, nextSection);
+ let collection = this.editor.post.sections
+ this.insertSectionBefore(collection, newSection, nextSection)
- return surroundingSections;
+ return surroundingSections
}
/**
@@ -542,17 +539,17 @@ class PostEditor {
replaceSection(section, newSection) {
if (!section) {
// FIXME should a falsy section be a valid argument?
- this.insertSectionBefore(this.editor.post.sections, newSection, null);
+ this.insertSectionBefore(this.editor.post.sections, newSection, null)
} else {
- this._replaceSection(section, [newSection]);
+ this._replaceSection(section, [newSection])
}
}
moveSectionBefore(collection, renderedSection, beforeSection) {
- const newSection = renderedSection.clone();
- this.removeSection(renderedSection);
- this.insertSectionBefore(collection, newSection, beforeSection);
- return newSection;
+ const newSection = renderedSection.clone()
+ this.removeSection(renderedSection)
+ this.insertSectionBefore(collection, newSection, beforeSection)
+ return newSection
}
/**
@@ -560,14 +557,14 @@ class PostEditor {
* @public
*/
moveSectionUp(renderedSection) {
- const isFirst = !renderedSection.prev;
+ const isFirst = !renderedSection.prev
if (isFirst) {
- return renderedSection;
+ return renderedSection
}
- const collection = renderedSection.parent.sections;
- const beforeSection = renderedSection.prev;
- return this.moveSectionBefore(collection, renderedSection, beforeSection);
+ const collection = renderedSection.parent.sections
+ const beforeSection = renderedSection.prev
+ return this.moveSectionBefore(collection, renderedSection, beforeSection)
}
/**
@@ -575,14 +572,14 @@ class PostEditor {
* @public
*/
moveSectionDown(renderedSection) {
- const isLast = !renderedSection.next;
+ const isLast = !renderedSection.next
if (isLast) {
- return renderedSection;
+ return renderedSection
}
- const beforeSection = renderedSection.next.next;
- const collection = renderedSection.parent.sections;
- return this.moveSectionBefore(collection, renderedSection, beforeSection);
+ const beforeSection = renderedSection.next.next
+ const collection = renderedSection.parent.sections
+ return this.moveSectionBefore(collection, renderedSection, beforeSection)
}
/**
@@ -595,28 +592,27 @@ class PostEditor {
* @public
*/
insertMarkers(position, markers) {
- let { section, offset } = position;
- assert('Cannot insert markers at non-markerable position',
- section.isMarkerable);
+ let { section, offset } = position
+ assert('Cannot insert markers at non-markerable position', section.isMarkerable)
- this.editActionTaken = EDIT_ACTIONS.INSERT_TEXT;
+ this.editActionTaken = EDIT_ACTIONS.INSERT_TEXT
- let edit = section.splitMarkerAtOffset(offset);
- edit.removed.forEach(marker => this._scheduleForRemoval(marker));
+ let edit = section.splitMarkerAtOffset(offset)
+ edit.removed.forEach(marker => this._scheduleForRemoval(marker))
- let prevMarker = section.markerBeforeOffset(offset);
+ let prevMarker = section.markerBeforeOffset(offset)
markers.forEach(marker => {
- section.markers.insertAfter(marker, prevMarker);
- offset += marker.length;
- prevMarker = marker;
- });
+ section.markers.insertAfter(marker, prevMarker)
+ offset += marker.length
+ prevMarker = marker
+ })
- this._coalesceMarkers(section);
- this._markDirty(section);
+ this._coalesceMarkers(section)
+ this._markDirty(section)
- let nextPosition = section.toPosition(offset);
- this.setRange(nextPosition);
- return nextPosition;
+ let nextPosition = section.toPosition(offset)
+ this.setRange(nextPosition)
+ return nextPosition
}
/**
@@ -628,11 +624,13 @@ class PostEditor {
* @param {Markup[]} markups
* @return {Position} position at the end of the inserted text
*/
- insertTextWithMarkup(position, text, markups=[]) {
- let { section } = position;
- if (!section.isMarkerable) { return; }
- let marker = this.builder.createMarker(text, markups);
- return this.insertMarkers(position, [marker]);
+ insertTextWithMarkup(position, text, markups = []) {
+ let { section } = position
+ if (!section.isMarkerable) {
+ return
+ }
+ let marker = this.builder.createMarker(text, markups)
+ return this.insertMarkers(position, [marker])
}
/**
@@ -644,27 +642,29 @@ class PostEditor {
* @return {Position} position at the end of the inserted text.
*/
insertText(position, text) {
- let { section } = position;
- if (!section.isMarkerable) { return; }
- let markups = position.marker && position.marker.markups;
- markups = markups || [];
- return this.insertTextWithMarkup(position, text, markups);
+ let { section } = position
+ if (!section.isMarkerable) {
+ return
+ }
+ let markups = position.marker && position.marker.markups
+ markups = markups || []
+ return this.insertTextWithMarkup(position, text, markups)
}
_replaceSection(section, newSections) {
- let nextSection = section.next;
- let collection = section.parent.sections;
+ let nextSection = section.next
+ let collection = section.parent.sections
- let nextNewSection = newSections[0];
+ let nextNewSection = newSections[0]
if (nextNewSection.isMarkupSection && section.isListItem) {
// put the new section after the ListSection (section.parent)
// instead of after the ListItem
- collection = section.parent.parent.sections;
- nextSection = section.parent.next;
+ collection = section.parent.parent.sections
+ nextSection = section.parent.next
}
- newSections.forEach(s => this.insertSectionBefore(collection, s, nextSection));
- this.removeSection(section);
+ newSections.forEach(s => this.insertSectionBefore(collection, s, nextSection))
+ this.removeSection(section)
}
/**
@@ -687,9 +687,11 @@ class PostEditor {
* @public
*/
addMarkupToRange(range, markup) {
- if (range.isCollapsed) { return; }
+ if (range.isCollapsed) {
+ return
+ }
- let markers = this.splitMarkers(range);
+ let markers = this.splitMarkers(range)
if (markers.length) {
// We insert the new markup at a consistent index across the range.
// If we just push on the end of the list, it can end up in different positions
@@ -701,15 +703,19 @@ class PostEditor {
// at the end of those.
// Prompted by https://github.com/bustle/mobiledoc-kit/issues/360
- let markupsOpenAcrossRange = reduce(markers, function (soFar, marker) {
- return commonItems(soFar, marker.markups);
- }, markers[0].markups);
- let indexToInsert = markupsOpenAcrossRange.length;
+ let markupsOpenAcrossRange = reduce(
+ markers,
+ function (soFar, marker) {
+ return commonItems(soFar, marker.markups)
+ },
+ markers[0].markups
+ )
+ let indexToInsert = markupsOpenAcrossRange.length
markers.forEach(marker => {
- marker.addMarkupAtIndex(markup, indexToInsert);
- this._markDirty(marker);
- });
+ marker.addMarkupAtIndex(markup, indexToInsert)
+ this._markDirty(marker)
+ })
}
}
@@ -733,12 +739,14 @@ class PostEditor {
* @private
*/
removeMarkupFromRange(range, markupOrMarkupCallback) {
- if (range.isCollapsed) { return; }
+ if (range.isCollapsed) {
+ return
+ }
this.splitMarkers(range).forEach(marker => {
- marker.removeMarkup(markupOrMarkupCallback);
- this._markDirty(marker);
- });
+ marker.removeMarkup(markupOrMarkupCallback)
+ this._markDirty(marker)
+ })
}
/**
@@ -764,23 +772,22 @@ class PostEditor {
* @param {Range|Position} range in which to toggle. Defaults to current editor range.
* @public
*/
- toggleMarkup(markupOrMarkupString, range=this._range) {
- range = toRange(range);
- const markup = typeof markupOrMarkupString === 'string' ?
- this.builder.createMarkup(markupOrMarkupString) :
- markupOrMarkupString;
+ toggleMarkup(markupOrMarkupString, range = this._range) {
+ range = toRange(range)
+ const markup =
+ typeof markupOrMarkupString === 'string' ? this.builder.createMarkup(markupOrMarkupString) : markupOrMarkupString
- const hasMarkup = this.editor.detectMarkupInRange(range, markup.tagName);
+ const hasMarkup = this.editor.detectMarkupInRange(range, markup.tagName)
// FIXME: This implies only a single markup in a range. This may not be
// true for links (which are not the same object instance like multiple
// strong tags would be).
if (hasMarkup) {
- this.removeMarkupFromRange(range, hasMarkup);
+ this.removeMarkupFromRange(range, hasMarkup)
} else {
- this.addMarkupToRange(range, markup);
+ this.addMarkupToRange(range, markup)
}
- this.setRange(range);
+ this.setRange(range)
}
/**
@@ -794,48 +801,48 @@ class PostEditor {
* Defaults to the current editor range.
* @public
*/
- toggleSection(sectionTagName, range=this._range) {
- range = shrinkRange(toRange(range));
+ toggleSection(sectionTagName, range = this._range) {
+ range = shrinkRange(toRange(range))
- sectionTagName = normalizeTagName(sectionTagName);
- let { post } = this.editor;
+ sectionTagName = normalizeTagName(sectionTagName)
+ let { post } = this.editor
- let everySectionHasTagName = true;
+ let everySectionHasTagName = true
post.walkMarkerableSections(range, section => {
if (!this._isSameSectionType(section, sectionTagName)) {
- everySectionHasTagName = false;
+ everySectionHasTagName = false
}
- });
+ })
- let tagName = everySectionHasTagName ? 'p' : sectionTagName;
- let sectionTransformations = [];
+ let tagName = everySectionHasTagName ? 'p' : sectionTagName
+ let sectionTransformations = []
post.walkMarkerableSections(range, section => {
- let changedSection = this.changeSectionTagName(section, tagName);
+ let changedSection = this.changeSectionTagName(section, tagName)
sectionTransformations.push({
from: section,
- to: changedSection
- });
- });
+ to: changedSection,
+ })
+ })
- let nextRange = this._determineNextRangeAfterToggleSection(range, sectionTransformations);
- this.setRange(nextRange);
+ let nextRange = this._determineNextRangeAfterToggleSection(range, sectionTransformations)
+ this.setRange(nextRange)
}
_determineNextRangeAfterToggleSection(range, sectionTransformations) {
if (sectionTransformations.length) {
let changedHeadSection = detect(sectionTransformations, ({ from }) => {
- return from === range.headSection;
- }).to;
+ return from === range.headSection
+ }).to
let changedTailSection = detect(sectionTransformations, ({ from }) => {
- return from === range.tailSection;
- }).to;
+ return from === range.tailSection
+ }).to
if (changedHeadSection.isListSection || changedTailSection.isListSection) {
// We don't know to which ListItem's the original sections point at, so
// we don't have enough information to reconstruct the range when
// dealing with lists.
- return sectionTransformations[0].to.headPosition().toRange();
+ return sectionTransformations[0].to.headPosition().toRange()
} else {
return Range.create(
changedHeadSection,
@@ -843,53 +850,51 @@ class PostEditor {
changedTailSection,
range.tailSectionOffset,
range.direction
- );
+ )
}
} else {
- return range;
+ return range
}
}
- setAttribute(key, value, range=this._range) {
+ setAttribute(key, value, range = this._range) {
this._mutateAttribute(key, range, (section, attribute) => {
if (section.getAttribute(attribute) !== value) {
- section.setAttribute(attribute, value);
- return true;
+ section.setAttribute(attribute, value)
+ return true
}
- });
+ })
}
- removeAttribute(key, range=this._range) {
+ removeAttribute(key, range = this._range) {
this._mutateAttribute(key, range, (section, attribute) => {
if (section.hasAttribute(attribute)) {
- section.removeAttribute(attribute);
- return true;
+ section.removeAttribute(attribute)
+ return true
}
- });
+ })
}
_mutateAttribute(key, range, cb) {
- range = toRange(range);
- let { post } = this.editor;
- let attribute = `data-md-${key}`;
+ range = toRange(range)
+ let { post } = this.editor
+ let attribute = `data-md-${key}`
post.walkMarkerableSections(range, section => {
if (section.isListItem) {
- section = section.parent;
+ section = section.parent
}
if (cb(section, attribute) === true) {
- this._markDirty(section);
+ this._markDirty(section)
}
- });
+ })
- this.setRange(range);
+ this.setRange(range)
}
_isSameSectionType(section, sectionTagName) {
- return section.isListItem ?
- section.parent.tagName === sectionTagName :
- section.tagName === sectionTagName;
+ return section.isListItem ? section.parent.tagName === sectionTagName : section.tagName === sectionTagName
}
/**
@@ -897,17 +902,16 @@ class PostEditor {
* @private
*/
changeSectionTagName(section, newTagName) {
- assert('Cannot pass non-markerable section to `changeSectionTagName`',
- section.isMarkerable);
+ assert('Cannot pass non-markerable section to `changeSectionTagName`', section.isMarkerable)
if (isListSectionTagName(newTagName)) {
- return this._changeSectionToListItem(section, newTagName);
+ return this._changeSectionToListItem(section, newTagName)
} else if (section.isListItem) {
- return this._changeSectionFromListItem(section, newTagName);
+ return this._changeSectionFromListItem(section, newTagName)
} else {
- section.tagName = newTagName;
- this._markDirty(section);
- return section;
+ section.tagName = newTagName
+ this._markDirty(section)
+ return section
}
}
@@ -921,24 +925,23 @@ class PostEditor {
* @private
*/
_splitListItem(item, position) {
- let { section, offset } = position;
- assert('Cannot split list item at position that does not include item',
- item === section);
+ let { section, offset } = position
+ assert('Cannot split list item at position that does not include item', item === section)
- item.splitMarkerAtOffset(offset);
- let prevMarker = item.markerBeforeOffset(offset);
- let preItem = this.builder.createListItem(),
- postItem = this.builder.createListItem();
+ item.splitMarkerAtOffset(offset)
+ let prevMarker = item.markerBeforeOffset(offset)
+ let preItem = this.builder.createListItem(),
+ postItem = this.builder.createListItem()
- let currentItem = preItem;
+ let currentItem = preItem
item.markers.forEach(marker => {
- currentItem.markers.append(marker.clone());
+ currentItem.markers.append(marker.clone())
if (marker === prevMarker) {
- currentItem = postItem;
+ currentItem = postItem
}
- });
- this._replaceSection(item, [preItem, postItem]);
- return [preItem, postItem];
+ })
+ this._replaceSection(item, [preItem, postItem])
+ return [preItem, postItem]
}
/**
@@ -952,37 +955,35 @@ class PostEditor {
* @private
*/
_splitListAtPosition(list, position) {
- assert('Cannot split list at position not in list',
- position.section.parent === list);
+ assert('Cannot split list at position not in list', position.section.parent === list)
- let positionIsMiddle = !position.isHead() && !position.isTail();
+ let positionIsMiddle = !position.isHead() && !position.isTail()
if (positionIsMiddle) {
- let item = position.section;
- let [pre,] =
- this._splitListItem(item, position);
- position = pre.tailPosition();
+ let item = position.section
+ let [pre] = this._splitListItem(item, position)
+ position = pre.tailPosition()
}
- let preList = this.builder.createListSection(list.tagName);
- let postList = this.builder.createListSection(list.tagName);
+ let preList = this.builder.createListSection(list.tagName)
+ let postList = this.builder.createListSection(list.tagName)
- let preItem = position.section;
- let currentList = preList;
+ let preItem = position.section
+ let currentList = preList
list.items.forEach(item => {
// If this item matches the start item and the position is at its start,
// it should be appended to the postList instead of the preList
if (item === preItem && position.isEqual(item.headPosition())) {
- currentList = postList;
+ currentList = postList
}
- currentList.items.append(item.clone());
+ currentList.items.append(item.clone())
// If we just appended the preItem, append the remaining items to the postList
if (item === preItem) {
- currentList = postList;
+ currentList = postList
}
- });
+ })
- this._replaceSection(list, [preList, postList]);
- return [preList, postList];
+ this._replaceSection(list, [preList, postList])
+ return [preList, postList]
}
/**
@@ -995,80 +996,78 @@ class PostEditor {
* @private
*/
_splitListAtItem(list, item) {
- let next = list;
- let prev = this.builder.createListSection(next.tagName, [], next.attributes);
- let mid = this.builder.createListSection(next.tagName);
+ let next = list
+ let prev = this.builder.createListSection(next.tagName, [], next.attributes)
+ let mid = this.builder.createListSection(next.tagName)
- let addToPrev = true;
+ let addToPrev = true
// must turn the LinkedList into an array so that we can remove items
// as we iterate through it
- let items = next.items.toArray();
+ let items = next.items.toArray()
items.forEach(i => {
- let listToAppend;
+ let listToAppend
if (i === item) {
- addToPrev = false;
- listToAppend = mid;
+ addToPrev = false
+ listToAppend = mid
} else if (addToPrev) {
- listToAppend = prev;
+ listToAppend = prev
} else {
- return; // break after iterating prev and mid parts of the list
+ return // break after iterating prev and mid parts of the list
}
- listToAppend.join(i);
- this.removeSection(i);
- });
- let found = !addToPrev;
- assert('Cannot split list at item that is not present in the list', found);
+ listToAppend.join(i)
+ this.removeSection(i)
+ })
+ let found = !addToPrev
+ assert('Cannot split list at item that is not present in the list', found)
- let collection = this.editor.post.sections;
- this.insertSectionBefore(collection, mid, next);
- this.insertSectionBefore(collection, prev, mid);
+ let collection = this.editor.post.sections
+ this.insertSectionBefore(collection, mid, next)
+ this.insertSectionBefore(collection, prev, mid)
// Remove possibly blank prev/next lists
this.addCallback(CALLBACK_QUEUES.BEFORE_COMPLETE, () => {
- [prev, next].forEach(_list => {
- let isAttached = !!_list.parent;
+ ;[prev, next].forEach(_list => {
+ let isAttached = !!_list.parent
if (_list.isBlank && isAttached) {
- this.removeSection(_list);
+ this.removeSection(_list)
}
- });
- });
+ })
+ })
- return [prev, mid, next];
+ return [prev, mid, next]
}
_changeSectionFromListItem(section, newTagName) {
- assert('Must pass list item to `_changeSectionFromListItem`',
- section.isListItem);
+ assert('Must pass list item to `_changeSectionFromListItem`', section.isListItem)
- let listSection = section.parent;
- let markupSection = this.builder.createMarkupSection(newTagName);
- markupSection.join(section);
+ let listSection = section.parent
+ let markupSection = this.builder.createMarkupSection(newTagName)
+ markupSection.join(section)
- let [, mid,] = this._splitListAtItem(listSection, section);
- this.replaceSection(mid, markupSection);
- return markupSection;
+ let [, mid] = this._splitListAtItem(listSection, section)
+ this.replaceSection(mid, markupSection)
+ return markupSection
}
_changeSectionToListItem(section, newTagName) {
- let isAlreadyCorrectListItem = section.isListItem &&
- section.parent.tagName === newTagName;
+ let isAlreadyCorrectListItem = section.isListItem && section.parent.tagName === newTagName
if (isAlreadyCorrectListItem) {
- return section;
+ return section
}
- let listSection = this.builder.createListSection(newTagName);
- listSection.join(section);
+ let listSection = this.builder.createListSection(newTagName)
+ listSection.join(section)
- let sectionToReplace;
+ let sectionToReplace
if (section.isListItem) {
- let [, mid,] = this._splitListAtItem(section.parent, section);
- sectionToReplace = mid;
+ let [, mid] = this._splitListAtItem(section.parent, section)
+ sectionToReplace = mid
} else {
- sectionToReplace = section;
+ sectionToReplace = section
}
- this.replaceSection(sectionToReplace, listSection);
- return listSection;
+ this.replaceSection(sectionToReplace, listSection)
+ return listSection
}
/**
@@ -1092,8 +1091,8 @@ class PostEditor {
* @public
*/
insertSectionBefore(collection, section, beforeSection) {
- collection.insertBefore(section, beforeSection);
- this._markDirty(section.parent);
+ collection.insertBefore(section, beforeSection)
+ this._markDirty(section.parent)
}
/**
@@ -1103,11 +1102,11 @@ class PostEditor {
* @public
*/
insertSection(section) {
- const activeSection = this.editor.activeSection;
- const nextSection = activeSection && activeSection.next;
+ const activeSection = this.editor.activeSection
+ const nextSection = activeSection && activeSection.next
- const collection = this.editor.post.sections;
- this.insertSectionBefore(collection, section, nextSection);
+ const collection = this.editor.post.sections
+ this.insertSectionBefore(collection, section, nextSection)
}
/**
@@ -1116,7 +1115,7 @@ class PostEditor {
* @public
*/
insertSectionAtEnd(section) {
- this.insertSectionBefore(this.editor.post.sections, section, null);
+ this.insertSectionBefore(this.editor.post.sections, section, null)
}
/**
@@ -1126,10 +1125,10 @@ class PostEditor {
* @private
*/
insertPost(position, newPost) {
- let post = this.editor.post;
- let inserter = new PostInserter(this, post);
- let nextPosition = inserter.insert(position, newPost);
- return nextPosition;
+ let post = this.editor.post
+ let inserter = new PostInserter(this, post)
+ let nextPosition = inserter.insert(position, newPost)
+ return nextPosition
}
/**
@@ -1147,37 +1146,37 @@ class PostEditor {
* @public
*/
removeSection(section) {
- let parent = section.parent;
- this._scheduleForRemoval(section);
- parent.sections.remove(section);
+ let parent = section.parent
+ this._scheduleForRemoval(section)
+ parent.sections.remove(section)
if (parent.isListSection) {
- this._scheduleListRemovalIfEmpty(parent);
+ this._scheduleListRemovalIfEmpty(parent)
}
}
removeAllSections() {
this.editor.post.sections.toArray().forEach(section => {
- this.removeSection(section);
- });
+ this.removeSection(section)
+ })
}
migrateSectionsFromPost(post) {
post.sections.toArray().forEach(section => {
- post.sections.remove(section);
- this.insertSectionBefore(this.editor.post.sections, section, null);
- });
+ post.sections.remove(section)
+ this.insertSectionBefore(this.editor.post.sections, section, null)
+ })
}
_scheduleListRemovalIfEmpty(listSection) {
this.addCallback(CALLBACK_QUEUES.BEFORE_COMPLETE, () => {
// if the list is attached and blank after we do other rendering stuff,
// remove it
- let isAttached = !!listSection.parent;
+ let isAttached = !!listSection.parent
if (isAttached && listSection.isBlank) {
- this.removeSection(listSection);
+ this.removeSection(listSection)
}
- });
+ })
}
/**
@@ -1187,13 +1186,12 @@ class PostEditor {
* @param {Boolean} [once=false] Whether to only schedule the callback once.
* @public
*/
- schedule(callback, once=false) {
- assert('Work can only be scheduled before a post edit has completed',
- !this._didComplete);
+ schedule(callback, once = false) {
+ assert('Work can only be scheduled before a post edit has completed', !this._didComplete)
if (once) {
- this.addCallbackOnce(CALLBACK_QUEUES.COMPLETE, callback);
+ this.addCallbackOnce(CALLBACK_QUEUES.COMPLETE, callback)
} else {
- this.addCallback(CALLBACK_QUEUES.COMPLETE, callback);
+ this.addCallback(CALLBACK_QUEUES.COMPLETE, callback)
}
}
@@ -1206,7 +1204,7 @@ class PostEditor {
* @public
*/
scheduleOnce(callback) {
- this.schedule(callback, true);
+ this.schedule(callback, true)
}
/**
@@ -1215,7 +1213,7 @@ class PostEditor {
* @public
*/
scheduleRerender() {
- this.scheduleOnce(this._rerender);
+ this.scheduleOnce(this._rerender)
}
/**
@@ -1226,14 +1224,14 @@ class PostEditor {
* @public
*/
scheduleDidUpdate() {
- this.scheduleOnce(this._postDidChange);
+ this.scheduleOnce(this._postDidChange)
}
- scheduleAfterRender(callback, once=false) {
+ scheduleAfterRender(callback, once = false) {
if (once) {
- this.addCallbackOnce(CALLBACK_QUEUES.AFTER_COMPLETE, callback);
+ this.addCallbackOnce(CALLBACK_QUEUES.AFTER_COMPLETE, callback)
} else {
- this.addCallback(CALLBACK_QUEUES.AFTER_COMPLETE, callback);
+ this.addCallback(CALLBACK_QUEUES.AFTER_COMPLETE, callback)
}
}
@@ -1244,25 +1242,25 @@ class PostEditor {
* @private
*/
complete() {
- assert('Post editing can only be completed once', !this._didComplete);
+ assert('Post editing can only be completed once', !this._didComplete)
- this.runCallbacks(CALLBACK_QUEUES.BEFORE_COMPLETE);
- this._didComplete = true;
- this.runCallbacks(CALLBACK_QUEUES.COMPLETE);
- this.runCallbacks(CALLBACK_QUEUES.AFTER_COMPLETE);
+ this.runCallbacks(CALLBACK_QUEUES.BEFORE_COMPLETE)
+ this._didComplete = true
+ this.runCallbacks(CALLBACK_QUEUES.COMPLETE)
+ this.runCallbacks(CALLBACK_QUEUES.AFTER_COMPLETE)
}
undoLastChange() {
- this.editor._editHistory.stepBackward(this);
+ this.editor._editHistory.stepBackward(this)
}
redoLastChange() {
- this.editor._editHistory.stepForward(this);
+ this.editor._editHistory.stepForward(this)
}
cancelSnapshot() {
- this._shouldCancelSnapshot = true;
+ this._shouldCancelSnapshot = true
}
}
-export default PostEditor;
+export default PostEditor
diff --git a/src/js/editor/post/post-inserter.js b/src/js/editor/post/post-inserter.js
index c3b55583b..46bce5489 100644
--- a/src/js/editor/post/post-inserter.js
+++ b/src/js/editor/post/post-inserter.js
@@ -1,4 +1,4 @@
-import assert from 'mobiledoc-kit/utils/assert';
+import assert from 'mobiledoc-kit/utils/assert'
import {
MARKUP_SECTION_TYPE,
LIST_SECTION_TYPE,
@@ -6,196 +6,194 @@ import {
CARD_TYPE,
IMAGE_SECTION_TYPE,
LIST_ITEM_TYPE,
-} from 'mobiledoc-kit/models/types';
+} from 'mobiledoc-kit/models/types'
const MARKERABLE = 'markerable',
- NESTED_MARKERABLE = 'nested_markerable',
- NON_MARKERABLE = 'non_markerable';
+ NESTED_MARKERABLE = 'nested_markerable',
+ NON_MARKERABLE = 'non_markerable'
class Visitor {
constructor(inserter, cursorPosition) {
- let { postEditor, post } = inserter;
- this.postEditor = postEditor;
- this._post = post;
- this.cursorPosition = cursorPosition;
- this.builder = this.postEditor.builder;
+ let { postEditor, post } = inserter
+ this.postEditor = postEditor
+ this._post = post
+ this.cursorPosition = cursorPosition
+ this.builder = this.postEditor.builder
- this._hasInsertedFirstLeafSection = false;
+ this._hasInsertedFirstLeafSection = false
}
get cursorPosition() {
- return this._cursorPosition;
+ return this._cursorPosition
}
set cursorPosition(position) {
- this._cursorPosition = position;
- this.postEditor.setRange(position);
+ this._cursorPosition = position
+ this.postEditor.setRange(position)
}
visit(node) {
- let method = node.type;
- assert(`Cannot visit node of type ${node.type}`, !!this[method]);
- this[method](node);
+ let method = node.type
+ assert(`Cannot visit node of type ${node.type}`, !!this[method])
+ this[method](node)
}
_canMergeSection(section) {
if (this._hasInsertedFirstLeafSection) {
- return false;
+ return false
} else {
- return this._isMarkerable && section.isMarkerable;
+ return this._isMarkerable && section.isMarkerable
}
}
get _isMarkerable() {
- return this.cursorSection.isMarkerable;
+ return this.cursorSection.isMarkerable
}
get cursorSection() {
- return this.cursorPosition.section;
+ return this.cursorPosition.section
}
get cursorOffset() {
- return this.cursorPosition.offset;
+ return this.cursorPosition.offset
}
get _isNested() {
- return this.cursorSection.isNested;
+ return this.cursorSection.isNested
}
[POST_TYPE](node) {
if (this.cursorSection.isBlank && !this._isNested) {
// replace blank section with entire post
- let newSections = node.sections.map(s => s.clone());
- this._replaceSection(this.cursorSection, newSections);
+ let newSections = node.sections.map(s => s.clone())
+ this._replaceSection(this.cursorSection, newSections)
} else {
- node.sections.forEach(section => this.visit(section));
+ node.sections.forEach(section => this.visit(section))
}
}
[MARKUP_SECTION_TYPE](node) {
- this[MARKERABLE](node);
+ this[MARKERABLE](node)
}
[LIST_SECTION_TYPE](node) {
- let hasNext = !!node.next;
- node.items.forEach(item => this.visit(item));
+ let hasNext = !!node.next
+ node.items.forEach(item => this.visit(item))
if (this._isNested && hasNext) {
- this._breakNestedAtCursor();
+ this._breakNestedAtCursor()
}
}
[LIST_ITEM_TYPE](node) {
- this[NESTED_MARKERABLE](node);
+ this[NESTED_MARKERABLE](node)
}
[CARD_TYPE](node) {
- this[NON_MARKERABLE](node);
+ this[NON_MARKERABLE](node)
}
[IMAGE_SECTION_TYPE](node) {
- this[NON_MARKERABLE](node);
+ this[NON_MARKERABLE](node)
}
[NON_MARKERABLE](section) {
if (this._isNested) {
- this._breakNestedAtCursor();
+ this._breakNestedAtCursor()
} else if (!this.cursorSection.isBlank) {
- this._breakAtCursor();
+ this._breakAtCursor()
}
- this._insertLeafSection(section);
+ this._insertLeafSection(section)
}
[MARKERABLE](section) {
if (this._canMergeSection(section)) {
- this._mergeSection(section);
+ this._mergeSection(section)
} else if (this._isNested && this._isMarkerable) {
// If we are attaching a markerable section to a list item,
// insert a linebreak then merge the section onto the resulting blank list item
- this._breakAtCursor();
+ this._breakAtCursor()
// Advance the cursor to the head of the blank list item
- let nextPosition = this.cursorSection.next.headPosition();
- this.cursorPosition = nextPosition;
+ let nextPosition = this.cursorSection.next.headPosition()
+ this.cursorPosition = nextPosition
// Merge this section onto the list item
- this._mergeSection(section);
+ this._mergeSection(section)
} else {
- this._breakAtCursor();
- this._insertLeafSection(section);
+ this._breakAtCursor()
+ this._insertLeafSection(section)
}
}
[NESTED_MARKERABLE](section) {
if (this._canMergeSection(section)) {
- this._mergeSection(section);
- return;
+ this._mergeSection(section)
+ return
}
- section = this._isNested ? section : this._wrapNestedSection(section);
- this._breakAtCursor();
- this._insertLeafSection(section);
+ section = this._isNested ? section : this._wrapNestedSection(section)
+ this._breakAtCursor()
+ this._insertLeafSection(section)
}
// break out of a nested cursor position
_breakNestedAtCursor() {
- assert('Cannot call _breakNestedAtCursor if not nested', this._isNested);
+ assert('Cannot call _breakNestedAtCursor if not nested', this._isNested)
- let parent = this.cursorSection.parent;
- let cursorAtEndOfList = this.cursorPosition.isEqual(parent.tailPosition());
+ let parent = this.cursorSection.parent
+ let cursorAtEndOfList = this.cursorPosition.isEqual(parent.tailPosition())
if (cursorAtEndOfList) {
- let blank = this.builder.createMarkupSection();
- this._insertSectionAfter(blank, parent);
+ let blank = this.builder.createMarkupSection()
+ this._insertSectionAfter(blank, parent)
} else {
- let [, blank,] = this._breakListAtCursor();
- this.cursorPosition = blank.tailPosition();
+ let [, blank] = this._breakListAtCursor()
+ this.cursorPosition = blank.tailPosition()
}
}
_breakListAtCursor() {
- assert('Cannot _splitParentSection if cursor position is not nested',
- this._isNested);
+ assert('Cannot _splitParentSection if cursor position is not nested', this._isNested)
- let list = this.cursorSection.parent,
- position = this.cursorPosition,
- blank = this.builder.createMarkupSection();
- let [pre, post] = this.postEditor._splitListAtPosition(list, position);
+ let list = this.cursorSection.parent,
+ position = this.cursorPosition,
+ blank = this.builder.createMarkupSection()
+ let [pre, post] = this.postEditor._splitListAtPosition(list, position)
let collection = this._post.sections,
- reference = post;
- this.postEditor.insertSectionBefore(collection, blank, reference);
- return [pre, blank, post];
+ reference = post
+ this.postEditor.insertSectionBefore(collection, blank, reference)
+ return [pre, blank, post]
}
_wrapNestedSection(section) {
- let tagName = section.parent.tagName;
- let parent = this.builder.createListSection(tagName);
- parent.items.append(section.clone());
- return parent;
+ let tagName = section.parent.tagName
+ let parent = this.builder.createListSection(tagName)
+ parent.items.append(section.clone())
+ return parent
}
_mergeSection(section) {
- assert('Can only merge markerable sections',
- this._isMarkerable && section.isMarkerable);
- this._hasInsertedFirstLeafSection = true;
+ assert('Can only merge markerable sections', this._isMarkerable && section.isMarkerable)
+ this._hasInsertedFirstLeafSection = true
- let markers = section.markers.map(m => m.clone());
- let position = this.postEditor.insertMarkers(this.cursorPosition, markers);
+ let markers = section.markers.map(m => m.clone())
+ let position = this.postEditor.insertMarkers(this.cursorPosition, markers)
- this.cursorPosition = position;
+ this.cursorPosition = position
}
// Can be called to add a line break when in a nested section or a parent
// section.
_breakAtCursor() {
if (this.cursorSection.isBlank) {
- return;
+ return
} else if (this._isMarkerable) {
- this._breakMarkerableAtCursor();
+ this._breakMarkerableAtCursor()
} else {
- this._breakNonMarkerableAtCursor();
+ this._breakNonMarkerableAtCursor()
}
}
@@ -203,84 +201,82 @@ class Visitor {
// depending on cursor position.
_breakNonMarkerableAtCursor() {
let collection = this._post.sections,
- blank = this.builder.createMarkupSection(),
- reference = this.cursorPosition.isHead() ? this.cursorSection :
- this.cursorSection.next;
- this.postEditor.insertSectionBefore(collection, blank, reference);
- this.cursorPosition = blank.tailPosition();
+ blank = this.builder.createMarkupSection(),
+ reference = this.cursorPosition.isHead() ? this.cursorSection : this.cursorSection.next
+ this.postEditor.insertSectionBefore(collection, blank, reference)
+ this.cursorPosition = blank.tailPosition()
}
_breakMarkerableAtCursor() {
- let [pre,] =
- this.postEditor.splitSection(this.cursorPosition);
+ let [pre] = this.postEditor.splitSection(this.cursorPosition)
- this.cursorPosition = pre.tailPosition();
+ this.cursorPosition = pre.tailPosition()
}
_replaceSection(section, newSections) {
- assert('Cannot replace section that does not have parent.sections',
- section.parent && section.parent.sections);
- assert('Must pass enumerable to _replaceSection', !!newSections.forEach);
+ assert('Cannot replace section that does not have parent.sections', section.parent && section.parent.sections)
+ assert('Must pass enumerable to _replaceSection', !!newSections.forEach)
- let collection = section.parent.sections;
- let reference = section.next;
- this.postEditor.removeSection(section);
+ let collection = section.parent.sections
+ let reference = section.next
+ this.postEditor.removeSection(section)
newSections.forEach(section => {
- this.postEditor.insertSectionBefore(collection, section, reference);
- });
- let lastSection = newSections[newSections.length - 1];
+ this.postEditor.insertSectionBefore(collection, section, reference)
+ })
+ let lastSection = newSections[newSections.length - 1]
- this.cursorPosition = lastSection.tailPosition();
+ this.cursorPosition = lastSection.tailPosition()
}
_insertSectionBefore(section, reference) {
- let collection = this.cursorSection.parent.sections;
- this.postEditor.insertSectionBefore(collection, section, reference);
+ let collection = this.cursorSection.parent.sections
+ this.postEditor.insertSectionBefore(collection, section, reference)
- this.cursorPosition = section.tailPosition();
+ this.cursorPosition = section.tailPosition()
}
// Insert a section after the parent section.
// E.g., add a markup section after a list section
_insertSectionAfter(section, parent) {
- assert('Cannot _insertSectionAfter nested section', !parent.isNested);
- let reference = parent.next;
- let collection = this._post.sections;
- this.postEditor.insertSectionBefore(collection, section, reference);
- this.cursorPosition = section.tailPosition();
+ assert('Cannot _insertSectionAfter nested section', !parent.isNested)
+ let reference = parent.next
+ let collection = this._post.sections
+ this.postEditor.insertSectionBefore(collection, section, reference)
+ this.cursorPosition = section.tailPosition()
}
_insertLeafSection(section) {
- assert('Can only _insertLeafSection when cursor is at end of section',
- this.cursorPosition.isTail());
+ assert('Can only _insertLeafSection when cursor is at end of section', this.cursorPosition.isTail())
- this._hasInsertedFirstLeafSection = true;
- section = section.clone();
+ this._hasInsertedFirstLeafSection = true
+ section = section.clone()
if (this.cursorSection.isBlank) {
- assert('Cannot insert leaf non-markerable section when cursor is nested',
- !(section.isMarkerable && this._isNested));
- this._replaceSection(this.cursorSection, [section]);
+ assert(
+ 'Cannot insert leaf non-markerable section when cursor is nested',
+ !(section.isMarkerable && this._isNested)
+ )
+ this._replaceSection(this.cursorSection, [section])
} else if (this.cursorSection.next && this.cursorSection.next.isBlank) {
- this._replaceSection(this.cursorSection.next, [section]);
+ this._replaceSection(this.cursorSection.next, [section])
} else {
- let reference = this.cursorSection.next;
- this._insertSectionBefore(section, reference);
+ let reference = this.cursorSection.next
+ this._insertSectionBefore(section, reference)
}
}
}
export default class Inserter {
constructor(postEditor, post) {
- this.postEditor = postEditor;
- this.post = post;
+ this.postEditor = postEditor
+ this.post = post
}
insert(cursorPosition, newPost) {
- let visitor = new Visitor(this, cursorPosition);
+ let visitor = new Visitor(this, cursorPosition)
if (!newPost.isBlank) {
- visitor.visit(newPost);
+ visitor.visit(newPost)
}
- return visitor.cursorPosition;
+ return visitor.cursorPosition
}
}
diff --git a/src/js/editor/selection-change-observer.js b/src/js/editor/selection-change-observer.js
index 8c37411f4..c48a74538 100644
--- a/src/js/editor/selection-change-observer.js
+++ b/src/js/editor/selection-change-observer.js
@@ -1,99 +1,103 @@
-let instance;
+let instance
class SelectionChangeObserver {
constructor() {
- this.started = false;
- this.listeners = [];
- this.selection = {};
+ this.started = false
+ this.listeners = []
+ this.selection = {}
}
static getInstance() {
if (!instance) {
- instance = new SelectionChangeObserver();
+ instance = new SelectionChangeObserver()
}
- return instance;
+ return instance
}
static addListener(listener) {
- SelectionChangeObserver.getInstance().addListener(listener);
+ SelectionChangeObserver.getInstance().addListener(listener)
}
addListener(listener) {
if (this.listeners.indexOf(listener) === -1) {
- this.listeners.push(listener);
- this.start();
+ this.listeners.push(listener)
+ this.start()
}
}
static removeListener(listener) {
- SelectionChangeObserver.getInstance().removeListener(listener);
+ SelectionChangeObserver.getInstance().removeListener(listener)
}
removeListener(listener) {
- let index = this.listeners.indexOf(listener);
+ let index = this.listeners.indexOf(listener)
if (index !== -1) {
- this.listeners.splice(index, 1);
+ this.listeners.splice(index, 1)
if (this.listeners.length === 0) {
- this.stop();
+ this.stop()
}
}
}
start() {
- if (this.started) { return; }
- this.started = true;
+ if (this.started) {
+ return
+ }
+ this.started = true
- this.poll();
+ this.poll()
}
stop() {
- this.started = false;
- this.selection = {};
+ this.started = false
+ this.selection = {}
}
notifyListeners(/* newSelection, prevSelection */) {
this.listeners.forEach(listener => {
- listener.selectionDidChange(...arguments);
- });
+ listener.selectionDidChange(...arguments)
+ })
}
destroy() {
- this.stop();
- this.listeners = [];
+ this.stop()
+ this.listeners = []
}
getSelection() {
- let selection = window.getSelection();
- let { anchorNode, focusNode, anchorOffset, focusOffset } = selection;
- return { anchorNode, focusNode, anchorOffset, focusOffset };
+ let selection = window.getSelection()
+ let { anchorNode, focusNode, anchorOffset, focusOffset } = selection
+ return { anchorNode, focusNode, anchorOffset, focusOffset }
}
poll() {
if (this.started) {
- this.update();
- this.runNext(() => this.poll());
+ this.update()
+ this.runNext(() => this.poll())
}
}
runNext(fn) {
- window.requestAnimationFrame(fn);
+ window.requestAnimationFrame(fn)
}
update() {
- let prevSelection = this.selection;
- let curSelection = this.getSelection();
+ let prevSelection = this.selection
+ let curSelection = this.getSelection()
if (!this.selectionIsEqual(prevSelection, curSelection)) {
- this.selection = curSelection;
- this.notifyListeners(curSelection, prevSelection);
+ this.selection = curSelection
+ this.notifyListeners(curSelection, prevSelection)
}
}
selectionIsEqual(s1, s2) {
- return s1.anchorNode === s2.anchorNode &&
+ return (
+ s1.anchorNode === s2.anchorNode &&
s1.anchorOffset === s2.anchorOffset &&
s1.focusNode === s2.focusNode &&
- s1.focusOffset === s2.focusOffset;
+ s1.focusOffset === s2.focusOffset
+ )
}
}
-export default SelectionChangeObserver;
+export default SelectionChangeObserver
diff --git a/src/js/editor/selection-manager.js b/src/js/editor/selection-manager.js
index 72a8beb2d..6bd80febe 100644
--- a/src/js/editor/selection-manager.js
+++ b/src/js/editor/selection-manager.js
@@ -1,31 +1,33 @@
-import SelectionChangeObserver from 'mobiledoc-kit/editor/selection-change-observer';
+import SelectionChangeObserver from 'mobiledoc-kit/editor/selection-change-observer'
export default class SelectionManager {
constructor(editor, callback) {
- this.editor = editor;
- this.callback = callback;
- this.started = false;
+ this.editor = editor
+ this.callback = callback
+ this.started = false
}
start() {
- if (this.started) { return; }
+ if (this.started) {
+ return
+ }
- SelectionChangeObserver.addListener(this);
- this.started = true;
+ SelectionChangeObserver.addListener(this)
+ this.started = true
}
stop() {
- this.started = false;
- SelectionChangeObserver.removeListener(this);
+ this.started = false
+ SelectionChangeObserver.removeListener(this)
}
destroy() {
- this.stop();
+ this.stop()
}
selectionDidChange() {
if (this.started) {
- this.callback(...arguments);
+ this.callback(...arguments)
}
}
}
diff --git a/src/js/editor/text-input-handler.js b/src/js/editor/text-input-handler.js
index 535155157..ed2888e9b 100644
--- a/src/js/editor/text-input-handler.js
+++ b/src/js/editor/text-input-handler.js
@@ -1,76 +1,85 @@
-import { endsWith } from 'mobiledoc-kit/utils/string-utils';
-import assert from 'mobiledoc-kit/utils/assert';
-import deprecate from 'mobiledoc-kit/utils/deprecate';
-import { ENTER } from 'mobiledoc-kit/utils/characters';
+import { endsWith } from 'mobiledoc-kit/utils/string-utils'
+import assert from 'mobiledoc-kit/utils/assert'
+import deprecate from 'mobiledoc-kit/utils/deprecate'
+import { ENTER } from 'mobiledoc-kit/utils/characters'
class TextInputHandler {
constructor(editor) {
- this.editor = editor;
- this._handlers = [];
+ this.editor = editor
+ this._handlers = []
}
register(handler) {
- assert(`Input Handler is not valid`, this._validateHandler(handler));
- this._handlers.push(handler);
+ assert(`Input Handler is not valid`, this._validateHandler(handler))
+ this._handlers.push(handler)
}
unregister(name) {
- let handlers = this._handlers;
- for (let i=0; i {
- let { builder } = postEditor;
- let item = builder.createListItem();
- let listSection = builder.createListSection(listTagName, [item]);
+ let { builder } = postEditor
+ let item = builder.createListItem()
+ let listSection = builder.createListSection(listTagName, [item])
- postEditor.replaceSection(section, listSection);
- postEditor.setRange(listSection.headPosition());
- });
+ postEditor.replaceSection(section, listSection)
+ postEditor.setRange(listSection.headPosition())
+ })
}
/**
@@ -37,18 +42,23 @@ export function replaceWithListSection(editor, listTagName) {
* @public
*/
export function replaceWithHeaderSection(editor, headingTagName) {
- let { range: { head, head: { section } } } = editor;
+ let {
+ range: {
+ head,
+ head: { section },
+ },
+ } = editor
// Skip if cursor is not at end of section
if (!head.isTail()) {
- return;
+ return
}
editor.run(postEditor => {
- let { builder } = postEditor;
- let newSection = builder.createMarkupSection(headingTagName);
- postEditor.replaceSection(section, newSection);
- postEditor.setRange(newSection.headPosition());
- });
+ let { builder } = postEditor
+ let newSection = builder.createMarkupSection(headingTagName)
+ postEditor.replaceSection(section, newSection)
+ postEditor.setRange(newSection.headPosition())
+ })
}
export const DEFAULT_TEXT_INPUT_HANDLERS = [
@@ -57,16 +67,16 @@ export const DEFAULT_TEXT_INPUT_HANDLERS = [
// "* " -> ul
match: /^\* $/,
run(editor) {
- replaceWithListSection(editor, 'ul');
- }
+ replaceWithListSection(editor, 'ul')
+ },
},
{
name: 'ol',
// "1" -> ol, "1." -> ol
match: /^1\.? $/,
run(editor) {
- replaceWithListSection(editor, 'ol');
- }
+ replaceWithListSection(editor, 'ol')
+ },
},
{
name: 'heading',
@@ -80,9 +90,9 @@ export const DEFAULT_TEXT_INPUT_HANDLERS = [
*/
match: /^(#{1,6}) $/,
run(editor, matches) {
- let capture = matches[1];
- let headingTag = 'h' + capture.length;
- replaceWithHeaderSection(editor, headingTag);
- }
- }
-];
+ let capture = matches[1]
+ let headingTag = 'h' + capture.length
+ replaceWithHeaderSection(editor, headingTag)
+ },
+ },
+]
diff --git a/src/js/editor/ui.js b/src/js/editor/ui.js
index 06aa69d88..97099031b 100644
--- a/src/js/editor/ui.js
+++ b/src/js/editor/ui.js
@@ -2,10 +2,10 @@
* @module UI
*/
-import Position from '../utils/cursor/position';
-import Range from '../utils/cursor/range';
+import Position from '../utils/cursor/position'
+import Range from '../utils/cursor/range'
-let defaultShowPrompt = (message, defaultValue, callback) => callback(window.prompt(message, defaultValue));
+let defaultShowPrompt = (message, defaultValue, callback) => callback(window.prompt(message, defaultValue))
/**
* @callback promptCallback
@@ -44,26 +44,30 @@ let defaultShowPrompt = (message, defaultValue, callback) => callback(window.pro
* });
* @public
*/
-export function toggleLink(editor, showPrompt=defaultShowPrompt) {
+export function toggleLink(editor, showPrompt = defaultShowPrompt) {
if (editor.range.isCollapsed) {
- return;
+ return
}
- let selectedText = editor.cursor.selectedText();
- let defaultUrl = '';
- if (selectedText.indexOf('http') !== -1) { defaultUrl = selectedText; }
+ let selectedText = editor.cursor.selectedText()
+ let defaultUrl = ''
+ if (selectedText.indexOf('http') !== -1) {
+ defaultUrl = selectedText
+ }
- let {range} = editor;
- let hasLink = editor.detectMarkupInRange(range, 'a');
+ let { range } = editor
+ let hasLink = editor.detectMarkupInRange(range, 'a')
if (hasLink) {
- editor.toggleMarkup('a');
+ editor.toggleMarkup('a')
} else {
showPrompt('Enter a URL', defaultUrl, url => {
- if (!url) { return; }
+ if (!url) {
+ return
+ }
- editor.toggleMarkup('a', {href: url});
- });
+ editor.toggleMarkup('a', { href: url })
+ })
}
}
@@ -79,25 +83,27 @@ export function toggleLink(editor, showPrompt=defaultShowPrompt) {
*
* @public
*/
-export function editLink(target, editor, showPrompt=defaultShowPrompt) {
+export function editLink(target, editor, showPrompt = defaultShowPrompt) {
showPrompt('Enter a URL', target.href, url => {
- if (!url) { return; }
+ if (!url) {
+ return
+ }
- const position = Position.fromNode(editor._renderTree, target.firstChild);
- const range = new Range(position, new Position(position.section, position.offset + target.textContent.length));
+ const position = Position.fromNode(editor._renderTree, target.firstChild)
+ const range = new Range(position, new Position(position.section, position.offset + target.textContent.length))
editor.run(post => {
- let markup = editor.builder.createMarkup('a', {href: url});
+ let markup = editor.builder.createMarkup('a', { href: url })
// This is the only way to "update" a markup with new attributes in the
// current API.
- post.toggleMarkup(markup, range);
- post.toggleMarkup(markup, range);
- });
- });
+ post.toggleMarkup(markup, range)
+ post.toggleMarkup(markup, range)
+ })
+ })
}
export default {
toggleLink,
- editLink
-};
+ editLink,
+}
diff --git a/src/js/index.js b/src/js/index.js
index 404201f10..05f4d0d60 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -1,10 +1,10 @@
-import Editor from './editor/editor';
-import ImageCard from './cards/image';
-import UI from './editor/ui';
-import Range from './utils/cursor/range';
-import Position from './utils/cursor/position';
-import Error from './utils/mobiledoc-error';
-import VERSION from './version';
-import { MOBILEDOC_VERSION } from './renderers/mobiledoc';
+import Editor from './editor/editor'
+import ImageCard from './cards/image'
+import UI from './editor/ui'
+import Range from './utils/cursor/range'
+import Position from './utils/cursor/position'
+import Error from './utils/mobiledoc-error'
+import VERSION from './version'
+import { MOBILEDOC_VERSION } from './renderers/mobiledoc'
-export { Editor, UI, ImageCard, Range, Position, Error, VERSION, MOBILEDOC_VERSION };
+export { Editor, UI, ImageCard, Range, Position, Error, VERSION, MOBILEDOC_VERSION }
diff --git a/src/js/models/_attributable.js b/src/js/models/_attributable.js
index 459fd18ca..b1adc8c13 100644
--- a/src/js/models/_attributable.js
+++ b/src/js/models/_attributable.js
@@ -1,30 +1,28 @@
-import { entries } from '../utils/object-utils';
-import { contains } from '../utils/array-utils';
+import { entries } from '../utils/object-utils'
+import { contains } from '../utils/array-utils'
-export const VALID_ATTRIBUTES = [
- 'data-md-text-align'
-];
+export const VALID_ATTRIBUTES = ['data-md-text-align']
/*
* A "mixin" to add section attribute support
* to markup and list sections.
*/
export function attributable(ctx) {
- ctx.attributes = {};
+ ctx.attributes = {}
- ctx.hasAttribute = key => key in ctx.attributes;
+ ctx.hasAttribute = key => key in ctx.attributes
ctx.setAttribute = (key, value) => {
if (!contains(VALID_ATTRIBUTES, key)) {
- throw new Error(`Invalid attribute "${key}" was passed. Constrain attributes to the spec-compliant whitelist.`);
+ throw new Error(`Invalid attribute "${key}" was passed. Constrain attributes to the spec-compliant whitelist.`)
}
- ctx.attributes[key] = value;
- };
+ ctx.attributes[key] = value
+ }
ctx.removeAttribute = key => {
- delete ctx.attributes[key];
- };
- ctx.getAttribute = key => ctx.attributes[key];
+ delete ctx.attributes[key]
+ }
+ ctx.getAttribute = key => ctx.attributes[key]
ctx.eachAttribute = cb => {
- entries(ctx.attributes).forEach(([k,v]) => cb(k,v));
- };
+ entries(ctx.attributes).forEach(([k, v]) => cb(k, v))
+ }
}
diff --git a/src/js/models/_markerable.js b/src/js/models/_markerable.js
index 49104a774..c89cab809 100644
--- a/src/js/models/_markerable.js
+++ b/src/js/models/_markerable.js
@@ -1,61 +1,57 @@
-import { forEach, reduce } from '../utils/array-utils';
-import Set from '../utils/set';
+import { forEach, reduce } from '../utils/array-utils'
+import Set from '../utils/set'
-import LinkedList from '../utils/linked-list';
-import Section from './_section';
-import assert from '../utils/assert';
+import LinkedList from '../utils/linked-list'
+import Section from './_section'
+import assert from '../utils/assert'
export default class Markerable extends Section {
- constructor(type, tagName, markers=[]) {
- super(type);
- this.isMarkerable = true;
- this.tagName = tagName;
+ constructor(type, tagName, markers = []) {
+ super(type)
+ this.isMarkerable = true
+ this.tagName = tagName
this.markers = new LinkedList({
adoptItem: m => {
- assert(`Can only insert markers and atoms into markerable (was: ${m.type})`,
- m.isMarker || m.isAtom);
- m.section = m.parent = this;
+ assert(`Can only insert markers and atoms into markerable (was: ${m.type})`, m.isMarker || m.isAtom)
+ m.section = m.parent = this
},
- freeItem: m => m.section = m.parent = null
- });
+ freeItem: m => (m.section = m.parent = null),
+ })
- markers.forEach(m => this.markers.append(m));
+ markers.forEach(m => this.markers.append(m))
}
canJoin(other) {
- return other.isMarkerable &&
- other.type === this.type &&
- other.tagName === this.tagName;
+ return other.isMarkerable && other.type === this.type && other.tagName === this.tagName
}
clone() {
- const newMarkers = this.markers.map(m => m.clone());
- return this.builder.createMarkerableSection(
- this.type, this.tagName, newMarkers);
+ const newMarkers = this.markers.map(m => m.clone())
+ return this.builder.createMarkerableSection(this.type, this.tagName, newMarkers)
}
get isBlank() {
if (!this.markers.length) {
- return true;
+ return true
}
- return this.markers.every(m => m.isBlank);
+ return this.markers.every(m => m.isBlank)
}
textUntil(position) {
- assert(`Cannot get textUntil for a position not in this section`, position.section === this);
- let {marker, offsetInMarker} = position;
- let text = '';
- let currentMarker = this.markers.head;
+ assert(`Cannot get textUntil for a position not in this section`, position.section === this)
+ let { marker, offsetInMarker } = position
+ let text = ''
+ let currentMarker = this.markers.head
while (currentMarker) {
if (currentMarker === marker) {
- text += currentMarker.textUntil(offsetInMarker);
- break;
+ text += currentMarker.textUntil(offsetInMarker)
+ break
} else {
- text += currentMarker.text;
- currentMarker = currentMarker.next;
+ text += currentMarker.text
+ currentMarker = currentMarker.next
}
}
- return text;
+ return text
}
/**
@@ -64,47 +60,45 @@ export default class Markerable extends Section {
*
* @return {Number} The offset relative to the start of this section
*/
- offsetOfMarker(marker, markerOffset=0) {
- assert(`Cannot get offsetOfMarker for marker that is not child of this`,
- marker.section === this);
+ offsetOfMarker(marker, markerOffset = 0) {
+ assert(`Cannot get offsetOfMarker for marker that is not child of this`, marker.section === this)
// FIXME it is possible, when we get a cursor position before having finished reparsing,
// for markerOffset to be > marker.length. We shouldn't rely on this functionality.
- let offset = 0;
- let currentMarker = this.markers.head;
+ let offset = 0
+ let currentMarker = this.markers.head
while (currentMarker && currentMarker !== marker.next) {
- let length = currentMarker === marker ? markerOffset :
- currentMarker.length;
- offset += length;
- currentMarker = currentMarker.next;
+ let length = currentMarker === marker ? markerOffset : currentMarker.length
+ offset += length
+ currentMarker = currentMarker.next
}
- return offset;
+ return offset
}
// puts clones of this.markers into beforeSection and afterSection,
// all markers before the marker/offset split go in beforeSection, and all
// after the marker/offset split go in afterSection
// @return {Array} [beforeSection, afterSection], two new sections
- _redistributeMarkers(beforeSection, afterSection, marker, offset=0) {
- let currentSection = beforeSection;
+ _redistributeMarkers(beforeSection, afterSection, marker, offset = 0) {
+ let currentSection = beforeSection
forEach(this.markers, m => {
if (m === marker) {
- const [beforeMarker, ...afterMarkers] = marker.split(offset);
- beforeSection.markers.append(beforeMarker);
- forEach(afterMarkers, _m => afterSection.markers.append(_m));
- currentSection = afterSection;
+ const [beforeMarker, ...afterMarkers] = marker.split(offset)
+ beforeSection.markers.append(beforeMarker)
+ forEach(afterMarkers, _m => afterSection.markers.append(_m))
+ currentSection = afterSection
} else {
- currentSection.markers.append(m.clone());
+ currentSection.markers.append(m.clone())
}
- });
+ })
- return [beforeSection, afterSection];
+ return [beforeSection, afterSection]
}
splitAtMarker(/*marker, offset=0*/) {
- assert('splitAtMarker must be implemented by sub-class', false);
+ assert('splitAtMarker must be implemented by sub-class', false)
}
/**
@@ -117,85 +111,83 @@ export default class Markerable extends Section {
* result returned from `markerBeforeOffset(offset)`.
*/
splitMarkerAtOffset(sectionOffset) {
- assert('Cannot splitMarkerAtOffset when offset is > length',
- sectionOffset <= this.length);
- let markerOffset;
- let len = 0;
- let currentMarker = this.markers.head;
- let edit = {added: [], removed: []};
+ assert('Cannot splitMarkerAtOffset when offset is > length', sectionOffset <= this.length)
+ let markerOffset
+ let len = 0
+ let currentMarker = this.markers.head
+ let edit = { added: [], removed: [] }
if (!currentMarker) {
- let blankMarker = this.builder.createMarker();
- this.markers.prepend(blankMarker);
- edit.added.push(blankMarker);
+ let blankMarker = this.builder.createMarker()
+ this.markers.prepend(blankMarker)
+ edit.added.push(blankMarker)
} else {
while (currentMarker) {
- len += currentMarker.length;
+ len += currentMarker.length
if (len === sectionOffset) {
// nothing to do, there is a gap at the requested offset
- break;
+ break
} else if (len > sectionOffset) {
- markerOffset = currentMarker.length - (len - sectionOffset);
- let newMarkers = currentMarker.splitAtOffset(markerOffset);
- edit.added.push(...newMarkers);
- edit.removed.push(currentMarker);
- this.markers.splice(currentMarker, 1, newMarkers);
- break;
+ markerOffset = currentMarker.length - (len - sectionOffset)
+ let newMarkers = currentMarker.splitAtOffset(markerOffset)
+ edit.added.push(...newMarkers)
+ edit.removed.push(currentMarker)
+ this.markers.splice(currentMarker, 1, newMarkers)
+ break
} else {
- currentMarker = currentMarker.next;
+ currentMarker = currentMarker.next
}
}
}
- return edit;
+ return edit
}
splitAtPosition(position) {
- const {marker, offsetInMarker} = position;
- return this.splitAtMarker(marker, offsetInMarker);
+ const { marker, offsetInMarker } = position
+ return this.splitAtMarker(marker, offsetInMarker)
}
// returns the marker just before this offset.
// It is an error to call this method with an offset that is in the middle
// of a marker.
markerBeforeOffset(sectionOffset) {
- let len = 0;
- let currentMarker = this.markers.head;
+ let len = 0
+ let currentMarker = this.markers.head
while (currentMarker) {
- len += currentMarker.length;
+ len += currentMarker.length
if (len === sectionOffset) {
- return currentMarker;
+ return currentMarker
} else {
- assert('markerBeforeOffset called with sectionOffset not between markers',
- len < sectionOffset);
- currentMarker = currentMarker.next;
+ assert('markerBeforeOffset called with sectionOffset not between markers', len < sectionOffset)
+ currentMarker = currentMarker.next
}
}
}
markerPositionAtOffset(offset) {
- let currentOffset = 0;
- let currentMarker;
- let remaining = offset;
- this.markers.detect((marker) => {
- currentOffset = Math.min(remaining, marker.length);
- remaining -= currentOffset;
+ let currentOffset = 0
+ let currentMarker
+ let remaining = offset
+ this.markers.detect(marker => {
+ currentOffset = Math.min(remaining, marker.length)
+ remaining -= currentOffset
if (remaining === 0) {
- currentMarker = marker;
- return true; // break out of detect
+ currentMarker = marker
+ return true // break out of detect
}
- });
+ })
- return {marker:currentMarker, offset:currentOffset};
+ return { marker: currentMarker, offset: currentOffset }
}
get text() {
- return reduce(this.markers, (prev, m) => prev + m.value, '');
+ return reduce(this.markers, (prev, m) => prev + m.value, '')
}
get length() {
- return reduce(this.markers, (prev, m) => prev + m.length, 0);
+ return reduce(this.markers, (prev, m) => prev + m.length, 0)
}
/**
@@ -203,75 +195,80 @@ export default class Markerable extends Section {
* range. Does not change the existing markers in this section.
*/
markersFor(headOffset, tailOffset) {
- const range = {head: {section:this, offset:headOffset},
- tail: {section:this, offset:tailOffset}};
+ const range = { head: { section: this, offset: headOffset }, tail: { section: this, offset: tailOffset } }
- let markers = [];
- this._markersInRange(range, (marker, {markerHead, markerTail, isContained}) => {
- const cloned = marker.clone();
+ let markers = []
+ this._markersInRange(range, (marker, { markerHead, markerTail, isContained }) => {
+ const cloned = marker.clone()
if (!isContained) {
// cannot do marker.value.slice if the marker is an atom -- this breaks the atom's "atomic" value
// If a marker is an atom `isContained` should always be true so
// we shouldn't hit this code path. FIXME add tests
- cloned.value = marker.value.slice(markerHead, markerTail);
+ cloned.value = marker.value.slice(markerHead, markerTail)
}
- markers.push(cloned);
- });
- return markers;
+ markers.push(cloned)
+ })
+ return markers
}
markupsInRange(range) {
- const markups = new Set();
+ const markups = new Set()
this._markersInRange(range, marker => {
- marker.markups.forEach(m => markups.add(m));
- });
- return markups.toArray();
+ marker.markups.forEach(m => markups.add(m))
+ })
+ return markups.toArray()
}
// calls the callback with (marker, {markerHead, markerTail, isContained})
// for each marker that is wholly or partially contained in the range.
_markersInRange(range, callback) {
- const { head, tail } = range;
- assert('Cannot call #_markersInRange if range expands beyond this section',
- head.section === this && tail.section === this);
- const {offset:headOffset} = head, {offset:tailOffset} = tail;
-
- let currentHead = 0, currentTail = 0, currentMarker = this.markers.head;
+ const { head, tail } = range
+ assert(
+ 'Cannot call #_markersInRange if range expands beyond this section',
+ head.section === this && tail.section === this
+ )
+ const { offset: headOffset } = head,
+ { offset: tailOffset } = tail
+
+ let currentHead = 0,
+ currentTail = 0,
+ currentMarker = this.markers.head
while (currentMarker) {
- currentTail += currentMarker.length;
+ currentTail += currentMarker.length
if (currentTail > headOffset && currentHead < tailOffset) {
- let markerHead = Math.max(headOffset - currentHead, 0);
- let markerTail = currentMarker.length -
- Math.max(currentTail - tailOffset, 0);
- let isContained = markerHead === 0 && markerTail === currentMarker.length;
+ let markerHead = Math.max(headOffset - currentHead, 0)
+ let markerTail = currentMarker.length - Math.max(currentTail - tailOffset, 0)
+ let isContained = markerHead === 0 && markerTail === currentMarker.length
- callback(currentMarker, {markerHead, markerTail, isContained});
+ callback(currentMarker, { markerHead, markerTail, isContained })
}
- currentHead += currentMarker.length;
- currentMarker = currentMarker.next;
+ currentHead += currentMarker.length
+ currentMarker = currentMarker.next
- if (currentHead > tailOffset) { break; }
+ if (currentHead > tailOffset) {
+ break
+ }
}
}
// mutates this by appending the other section's (cloned) markers to it
join(otherSection) {
- let beforeMarker = this.markers.tail;
- let afterMarker = null;
+ let beforeMarker = this.markers.tail
+ let afterMarker = null
otherSection.markers.forEach(m => {
if (!m.isBlank) {
- m = m.clone();
- this.markers.append(m);
+ m = m.clone()
+ this.markers.append(m)
if (!afterMarker) {
- afterMarker = m;
+ afterMarker = m
}
}
- });
+ })
- return { beforeMarker, afterMarker };
+ return { beforeMarker, afterMarker }
}
}
diff --git a/src/js/models/_section.js b/src/js/models/_section.js
index 90e3a551c..439be88f8 100644
--- a/src/js/models/_section.js
+++ b/src/js/models/_section.js
@@ -1,54 +1,52 @@
-import { normalizeTagName } from '../utils/dom-utils';
-import LinkedItem from '../utils/linked-item';
-import assert from '../utils/assert';
-import Position from '../utils/cursor/position';
+import { normalizeTagName } from '../utils/dom-utils'
+import LinkedItem from '../utils/linked-item'
+import assert from '../utils/assert'
+import Position from '../utils/cursor/position'
function unimplementedMethod(methodName, me) {
- assert(`\`${methodName}()\` must be implemented by ${me.constructor.name}`,
- false);
+ assert(`\`${methodName}()\` must be implemented by ${me.constructor.name}`, false)
}
export default class Section extends LinkedItem {
constructor(type) {
- super();
- assert('Cannot create section without type', !!type);
- this.type = type;
- this.isSection = true;
- this.isMarkerable = false;
- this.isNested = false;
- this.isSection = true;
- this.isLeafSection = true;
+ super()
+ assert('Cannot create section without type', !!type)
+ this.type = type
+ this.isSection = true
+ this.isMarkerable = false
+ this.isNested = false
+ this.isSection = true
+ this.isLeafSection = true
}
set tagName(val) {
- let normalizedTagName = normalizeTagName(val);
- assert(`Cannot set section tagName to ${val}`,
- this.isValidTagName(normalizedTagName));
- this._tagName = normalizedTagName;
+ let normalizedTagName = normalizeTagName(val)
+ assert(`Cannot set section tagName to ${val}`, this.isValidTagName(normalizedTagName))
+ this._tagName = normalizedTagName
}
get tagName() {
- return this._tagName;
+ return this._tagName
}
isValidTagName(/* normalizedTagName */) {
- unimplementedMethod('isValidTagName', this);
+ unimplementedMethod('isValidTagName', this)
}
get length() {
- return 0;
+ return 0
}
get isBlank() {
- unimplementedMethod('isBlank', this);
+ unimplementedMethod('isBlank', this)
}
clone() {
- unimplementedMethod('clone', this);
+ unimplementedMethod('clone', this)
}
canJoin(/* otherSection */) {
- unimplementedMethod('canJoin', this);
+ unimplementedMethod('canJoin', this)
}
/**
@@ -56,7 +54,7 @@ export default class Section extends LinkedItem {
* @public
*/
headPosition() {
- return this.toPosition(0);
+ return this.toPosition(0)
}
/**
@@ -64,7 +62,7 @@ export default class Section extends LinkedItem {
* @public
*/
tailPosition() {
- return this.toPosition(this.length);
+ return this.toPosition(this.length)
}
/**
@@ -73,10 +71,10 @@ export default class Section extends LinkedItem {
* @public
*/
toPosition(offset) {
- assert("Must pass number to `toPosition`", typeof offset === 'number');
- assert("Cannot call `toPosition` with offset > length", offset <= this.length);
+ assert('Must pass number to `toPosition`', typeof offset === 'number')
+ assert('Cannot call `toPosition` with offset > length', offset <= this.length)
- return new Position(this, offset);
+ return new Position(this, offset)
}
/**
@@ -84,60 +82,60 @@ export default class Section extends LinkedItem {
* @public
*/
toRange() {
- return this.headPosition().toRange(this.tailPosition());
+ return this.headPosition().toRange(this.tailPosition())
}
join() {
- unimplementedMethod('join', this);
+ unimplementedMethod('join', this)
}
textUntil(/* position */) {
- return '';
+ return ''
}
/**
* Markerable sections should override this method
*/
splitMarkerAtOffset() {
- let blankEdit = { added: [], removed: [] };
- return blankEdit;
+ let blankEdit = { added: [], removed: [] }
+ return blankEdit
}
nextLeafSection() {
- const next = this.next;
+ const next = this.next
if (next) {
if (next.items) {
- return next.items.head;
+ return next.items.head
} else {
- return next;
+ return next
}
} else {
if (this.isNested) {
- return this.parent.nextLeafSection();
+ return this.parent.nextLeafSection()
}
}
}
immediatelyNextMarkerableSection() {
- let next = this.nextLeafSection();
+ let next = this.nextLeafSection()
while (next && !next.isMarkerable) {
- next = next.nextLeafSection();
+ next = next.nextLeafSection()
}
- return next;
+ return next
}
previousLeafSection() {
- const prev = this.prev;
+ const prev = this.prev
if (prev) {
if (prev.items) {
- return prev.items.tail;
+ return prev.items.tail
} else {
- return prev;
+ return prev
}
} else {
if (this.isNested) {
- return this.parent.previousLeafSection();
+ return this.parent.previousLeafSection()
}
}
}
diff --git a/src/js/models/atom-node.js b/src/js/models/atom-node.js
index 58e7f409c..ff6a8ce3d 100644
--- a/src/js/models/atom-node.js
+++ b/src/js/models/atom-node.js
@@ -1,63 +1,66 @@
-import assert from '../utils/assert';
+import assert from '../utils/assert'
export default class AtomNode {
constructor(editor, atom, model, element, atomOptions) {
- this.editor = editor;
- this.atom = atom;
- this.model = model;
- this.atomOptions = atomOptions;
- this.element = element;
-
- this._teardownCallback = null;
- this._rendered = null;
+ this.editor = editor
+ this.atom = atom
+ this.model = model
+ this.atomOptions = atomOptions
+ this.element = element
+
+ this._teardownCallback = null
+ this._rendered = null
}
render() {
if (!this._rendered) {
- let {atomOptions: options, env, model: { value, payload } } = this;
+ let {
+ atomOptions: options,
+ env,
+ model: { value, payload },
+ } = this
// cache initial render
- this._rendered = this.atom.render({options, env, value, payload});
+ this._rendered = this.atom.render({ options, env, value, payload })
}
- this._validateAndAppendRenderResult(this._rendered);
+ this._validateAndAppendRenderResult(this._rendered)
}
get env() {
return {
name: this.atom.name,
- onTeardown: (callback) => this._teardownCallback = callback,
- save: (value, payload={}) => {
- this.model.value = value;
- this.model.payload = payload;
-
- this.editor._postDidChange();
- this.teardown();
- this.render();
- }
- };
+ onTeardown: callback => (this._teardownCallback = callback),
+ save: (value, payload = {}) => {
+ this.model.value = value
+ this.model.payload = payload
+
+ this.editor._postDidChange()
+ this.teardown()
+ this.render()
+ },
+ }
}
teardown() {
if (this._teardownCallback) {
- this._teardownCallback();
- this._teardownCallback = null;
+ this._teardownCallback()
+ this._teardownCallback = null
}
if (this._rendered) {
- this.element.removeChild(this._rendered);
- this._rendered = null;
+ this.element.removeChild(this._rendered)
+ this._rendered = null
}
}
_validateAndAppendRenderResult(rendered) {
if (!rendered) {
- return;
+ return
}
- let { atom: { name } } = this;
- assert(
- `Atom "${name}" must return a DOM node (returned value was: "${rendered}")`,
- !!rendered.nodeType
- );
- this.element.appendChild(rendered);
+ let {
+ atom: { name },
+ } = this
+ assert(`Atom "${name}" must return a DOM node (returned value was: "${rendered}")`, !!rendered.nodeType)
+ this.element.appendChild(rendered)
}
}
diff --git a/src/js/models/atom.js b/src/js/models/atom.js
index 3d94f4137..972012012 100644
--- a/src/js/models/atom.js
+++ b/src/js/models/atom.js
@@ -1,91 +1,88 @@
-import { ATOM_TYPE } from './types';
-import mixin from '../utils/mixin';
-import MarkuperableMixin from '../utils/markuperable';
-import LinkedItem from '../utils/linked-item';
-import assert from '../utils/assert';
+import { ATOM_TYPE } from './types'
+import mixin from '../utils/mixin'
+import MarkuperableMixin from '../utils/markuperable'
+import LinkedItem from '../utils/linked-item'
+import assert from '../utils/assert'
-const ATOM_LENGTH = 1;
+const ATOM_LENGTH = 1
class Atom extends LinkedItem {
- constructor(name, value, payload, markups=[]) {
- super();
- this.name = name;
- this.value = value;
- this.text = ''; // An atom never has text, but it does have a value
- assert('Atom must have value', value !== undefined && value !== null);
- this.payload = payload;
- this.type = ATOM_TYPE;
- this.isMarker = false;
- this.isAtom = true;
-
- this.markups = [];
- markups.forEach(m => this.addMarkup(m));
+ constructor(name, value, payload, markups = []) {
+ super()
+ this.name = name
+ this.value = value
+ this.text = '' // An atom never has text, but it does have a value
+ assert('Atom must have value', value !== undefined && value !== null)
+ this.payload = payload
+ this.type = ATOM_TYPE
+ this.isMarker = false
+ this.isAtom = true
+
+ this.markups = []
+ markups.forEach(m => this.addMarkup(m))
}
clone() {
- let clonedMarkups = this.markups.slice();
- return this.builder.createAtom(
- this.name, this.value, this.payload, clonedMarkups
- );
+ let clonedMarkups = this.markups.slice()
+ return this.builder.createAtom(this.name, this.value, this.payload, clonedMarkups)
}
get isBlank() {
- return false;
+ return false
}
get length() {
- return ATOM_LENGTH;
+ return ATOM_LENGTH
}
canJoin(/* other */) {
- return false;
+ return false
}
textUntil(/* offset */) {
- return '';
+ return ''
}
- split(offset=0, endOffset=offset) {
- let markers = [];
+ split(offset = 0, endOffset = offset) {
+ let markers = []
if (endOffset === 0) {
- markers.push(this.builder.createMarker('', this.markups.slice()));
+ markers.push(this.builder.createMarker('', this.markups.slice()))
}
- markers.push(this.clone());
+ markers.push(this.clone())
if (offset === ATOM_LENGTH) {
- markers.push(this.builder.createMarker('', this.markups.slice()));
+ markers.push(this.builder.createMarker('', this.markups.slice()))
}
- return markers;
+ return markers
}
splitAtOffset(offset) {
- assert('Cannot split a marker at an offset > its length',
- offset <= this.length);
+ assert('Cannot split a marker at an offset > its length', offset <= this.length)
- let { builder } = this;
- let clone = this.clone();
- let blankMarker = builder.createMarker('');
- let pre, post;
+ let { builder } = this
+ let clone = this.clone()
+ let blankMarker = builder.createMarker('')
+ let pre, post
if (offset === 0) {
- ([pre, post] = [blankMarker, clone]);
+ ;[pre, post] = [blankMarker, clone]
} else if (offset === ATOM_LENGTH) {
- ([pre, post] = [clone, blankMarker]);
+ ;[pre, post] = [clone, blankMarker]
} else {
- assert(`Invalid offset given to Atom#splitAtOffset: "${offset}"`, false);
+ assert(`Invalid offset given to Atom#splitAtOffset: "${offset}"`, false)
}
this.markups.forEach(markup => {
- pre.addMarkup(markup);
- post.addMarkup(markup);
- });
- return [pre, post];
+ pre.addMarkup(markup)
+ post.addMarkup(markup)
+ })
+ return [pre, post]
}
}
-mixin(Atom, MarkuperableMixin);
+mixin(Atom, MarkuperableMixin)
-export default Atom;
+export default Atom
diff --git a/src/js/models/card-node.js b/src/js/models/card-node.js
index abfd04b72..d3470c112 100644
--- a/src/js/models/card-node.js
+++ b/src/js/models/card-node.js
@@ -1,54 +1,55 @@
-import assert from '../utils/assert';
+import assert from '../utils/assert'
export default class CardNode {
constructor(editor, card, section, element, options) {
- this.editor = editor;
- this.card = card;
- this.section = section;
- this.element = element;
- this.options = options;
+ this.editor = editor
+ this.card = card
+ this.section = section
+ this.element = element
+ this.options = options
- this.mode = null;
+ this.mode = null
- this._teardownCallback = null;
- this._rendered = null;
+ this._teardownCallback = null
+ this._rendered = null
}
render(mode) {
- if (this.mode === mode) { return; }
+ if (this.mode === mode) {
+ return
+ }
- this.teardown();
+ this.teardown()
- this.mode = mode;
+ this.mode = mode
- let method = mode === 'display' ? 'render' : 'edit';
- method = this.card[method];
+ let method = mode === 'display' ? 'render' : 'edit'
+ method = this.card[method]
- assert(`Card is missing "${method}" (tried to render mode: "${mode}")`,
- !!method);
+ assert(`Card is missing "${method}" (tried to render mode: "${mode}")`, !!method)
let rendered = method({
env: this.env,
options: this.options,
- payload: this.section.payload
- });
+ payload: this.section.payload,
+ })
- this._validateAndAppendRenderResult(rendered);
+ this._validateAndAppendRenderResult(rendered)
}
teardown() {
if (this._teardownCallback) {
- this._teardownCallback();
- this._teardownCallback = null;
+ this._teardownCallback()
+ this._teardownCallback = null
}
if (this._rendered) {
- this.element.removeChild(this._rendered);
- this._rendered = null;
+ this.element.removeChild(this._rendered)
+ this._rendered = null
}
}
didRender() {
if (this._didRenderCallback) {
- this._didRenderCallback();
+ this._didRenderCallback()
}
}
@@ -56,47 +57,46 @@ export default class CardNode {
return {
name: this.card.name,
isInEditor: true,
- onTeardown: (callback) => this._teardownCallback = callback,
- didRender: (callback) => this._didRenderCallback = callback,
+ onTeardown: callback => (this._teardownCallback = callback),
+ didRender: callback => (this._didRenderCallback = callback),
edit: () => this.edit(),
- save: (payload, transition=true) => {
- this.section.payload = payload;
+ save: (payload, transition = true) => {
+ this.section.payload = payload
- this.editor._postDidChange();
+ this.editor._postDidChange()
if (transition) {
- this.display();
+ this.display()
}
},
cancel: () => this.display(),
remove: () => this.remove(),
- postModel: this.section
- };
+ postModel: this.section,
+ }
}
display() {
- this.render('display');
+ this.render('display')
}
edit() {
- this.render('edit');
+ this.render('edit')
}
remove() {
- this.editor.run(postEditor => postEditor.removeSection(this.section));
+ this.editor.run(postEditor => postEditor.removeSection(this.section))
}
_validateAndAppendRenderResult(rendered) {
if (!rendered) {
- return;
+ return
}
- let { card: { name } } = this;
- assert(
- `Card "${name}" must render dom (render value was: "${rendered}")`,
- !!rendered.nodeType
- );
- this.element.appendChild(rendered);
- this._rendered = rendered;
- this.didRender();
+ let {
+ card: { name },
+ } = this
+ assert(`Card "${name}" must render dom (render value was: "${rendered}")`, !!rendered.nodeType)
+ this.element.appendChild(rendered)
+ this._rendered = rendered
+ this.didRender()
}
}
diff --git a/src/js/models/card.js b/src/js/models/card.js
index 2bcb758fb..127230cb6 100644
--- a/src/js/models/card.js
+++ b/src/js/models/card.js
@@ -1,48 +1,48 @@
-import Section from './_section';
-import { CARD_TYPE } from './types';
-import { shallowCopyObject } from '../utils/copy';
+import Section from './_section'
+import { CARD_TYPE } from './types'
+import { shallowCopyObject } from '../utils/copy'
export const CARD_MODES = {
DISPLAY: 'display',
- EDIT: 'edit'
-};
+ EDIT: 'edit',
+}
-const CARD_LENGTH = 1;
+const CARD_LENGTH = 1
-const DEFAULT_INITIAL_MODE = CARD_MODES.DISPLAY;
+const DEFAULT_INITIAL_MODE = CARD_MODES.DISPLAY
export default class Card extends Section {
constructor(name, payload) {
- super(CARD_TYPE);
- this.name = name;
- this.payload = payload;
- this.setInitialMode(DEFAULT_INITIAL_MODE);
- this.isCardSection = true;
+ super(CARD_TYPE)
+ this.name = name
+ this.payload = payload
+ this.setInitialMode(DEFAULT_INITIAL_MODE)
+ this.isCardSection = true
}
get isBlank() {
- return false;
+ return false
}
canJoin() {
- return false;
+ return false
}
get length() {
- return CARD_LENGTH;
+ return CARD_LENGTH
}
clone() {
- let payload = shallowCopyObject(this.payload);
- let card = this.builder.createCardSection(this.name, payload);
+ let payload = shallowCopyObject(this.payload)
+ let card = this.builder.createCardSection(this.name, payload)
// If this card is currently rendered, clone the mode it is
// currently in as the default mode of the new card.
- let mode = this._initialMode;
+ let mode = this._initialMode
if (this.renderNode && this.renderNode.cardNode) {
- mode = this.renderNode.cardNode.mode;
+ mode = this.renderNode.cardNode.mode
}
- card.setInitialMode(mode);
- return card;
+ card.setInitialMode(mode)
+ return card
}
/**
@@ -51,6 +51,6 @@ export default class Card extends Section {
*/
setInitialMode(initialMode) {
// TODO validate initialMode
- this._initialMode = initialMode;
+ this._initialMode = initialMode
}
}
diff --git a/src/js/models/image.js b/src/js/models/image.js
index a29dcdffb..a18fdfd7d 100644
--- a/src/js/models/image.js
+++ b/src/js/models/image.js
@@ -1,21 +1,21 @@
-import { IMAGE_SECTION_TYPE } from './types';
-import Section from './_section';
+import { IMAGE_SECTION_TYPE } from './types'
+import Section from './_section'
export default class Image extends Section {
constructor() {
- super(IMAGE_SECTION_TYPE);
- this.src = null;
+ super(IMAGE_SECTION_TYPE)
+ this.src = null
}
canJoin() {
- return false;
+ return false
}
get isBlank() {
- return false;
+ return false
}
get length() {
- return 1;
+ return 1
}
}
diff --git a/src/js/models/lifecycle-callbacks.js b/src/js/models/lifecycle-callbacks.js
index 11c80bcbc..4cd972349 100644
--- a/src/js/models/lifecycle-callbacks.js
+++ b/src/js/models/lifecycle-callbacks.js
@@ -1,50 +1,50 @@
-import assert from 'mobiledoc-kit/utils/assert';
+import assert from 'mobiledoc-kit/utils/assert'
export default class LifecycleCallbacks {
- constructor(queueNames=[]) {
- this.callbackQueues = {};
- this.removalQueues = {};
+ constructor(queueNames = []) {
+ this.callbackQueues = {}
+ this.removalQueues = {}
queueNames.forEach(name => {
- this.callbackQueues[name] = [];
- this.removalQueues[name] = [];
- });
+ this.callbackQueues[name] = []
+ this.removalQueues[name] = []
+ })
}
- runCallbacks(queueName, args=[]) {
- let queue = this._getQueue(queueName);
- queue.forEach(cb => cb(...args));
+ runCallbacks(queueName, args = []) {
+ let queue = this._getQueue(queueName)
+ queue.forEach(cb => cb(...args))
- let toRemove = this.removalQueues[queueName];
+ let toRemove = this.removalQueues[queueName]
toRemove.forEach(cb => {
- let index = queue.indexOf(cb);
+ let index = queue.indexOf(cb)
if (index !== -1) {
- queue.splice(index, 1);
+ queue.splice(index, 1)
}
- });
+ })
- this.removalQueues[queueName] = [];
+ this.removalQueues[queueName] = []
}
addCallback(queueName, callback) {
- this._getQueue(queueName).push(callback);
+ this._getQueue(queueName).push(callback)
}
_scheduleCallbackForRemoval(queueName, callback) {
- this.removalQueues[queueName].push(callback);
+ this.removalQueues[queueName].push(callback)
}
addCallbackOnce(queueName, callback) {
- let queue = this._getQueue(queueName);
+ let queue = this._getQueue(queueName)
if (queue.indexOf(callback) === -1) {
- queue.push(callback);
- this._scheduleCallbackForRemoval(queueName, callback);
+ queue.push(callback)
+ this._scheduleCallbackForRemoval(queueName, callback)
}
}
_getQueue(queueName) {
- let queue = this.callbackQueues[queueName];
- assert(`No queue found for "${queueName}"`, !!queue);
- return queue;
+ let queue = this.callbackQueues[queueName]
+ assert(`No queue found for "${queueName}"`, !!queue)
+ return queue
}
}
diff --git a/src/js/models/list-item.js b/src/js/models/list-item.js
index 80173c1bc..98369e59c 100644
--- a/src/js/models/list-item.js
+++ b/src/js/models/list-item.js
@@ -1,42 +1,36 @@
-import Markerable from './_markerable';
-import { LIST_ITEM_TYPE } from './types';
-import {
- normalizeTagName
-} from 'mobiledoc-kit/utils/dom-utils';
-import { contains } from 'mobiledoc-kit/utils/array-utils';
+import Markerable from './_markerable'
+import { LIST_ITEM_TYPE } from './types'
+import { normalizeTagName } from 'mobiledoc-kit/utils/dom-utils'
+import { contains } from 'mobiledoc-kit/utils/array-utils'
-export const VALID_LIST_ITEM_TAGNAMES = [
- 'li'
-].map(normalizeTagName);
+export const VALID_LIST_ITEM_TAGNAMES = ['li'].map(normalizeTagName)
export default class ListItem extends Markerable {
- constructor(tagName, markers=[]) {
- super(LIST_ITEM_TYPE, tagName, markers);
- this.isListItem = true;
- this.isNested = true;
+ constructor(tagName, markers = []) {
+ super(LIST_ITEM_TYPE, tagName, markers)
+ this.isListItem = true
+ this.isNested = true
}
isValidTagName(normalizedTagName) {
- return contains(VALID_LIST_ITEM_TAGNAMES, normalizedTagName);
+ return contains(VALID_LIST_ITEM_TAGNAMES, normalizedTagName)
}
- splitAtMarker(marker, offset=0) {
+ splitAtMarker(marker, offset = 0) {
// FIXME need to check if we are going to split into two list items
// or a list item and a new markup section:
- const isLastItem = !this.next;
- const createNewSection = (!marker && offset === 0 && isLastItem);
+ const isLastItem = !this.next
+ const createNewSection = !marker && offset === 0 && isLastItem
let [beforeSection, afterSection] = [
this.builder.createListItem(),
- createNewSection ? this.builder.createMarkupSection() :
- this.builder.createListItem()
- ];
+ createNewSection ? this.builder.createMarkupSection() : this.builder.createListItem(),
+ ]
- return this._redistributeMarkers(
- beforeSection, afterSection, marker, offset);
+ return this._redistributeMarkers(beforeSection, afterSection, marker, offset)
}
get post() {
- return this.section.post;
+ return this.section.post
}
}
diff --git a/src/js/models/list-section.js b/src/js/models/list-section.js
index 33d1f4313..2e160e33f 100644
--- a/src/js/models/list-section.js
+++ b/src/js/models/list-section.js
@@ -1,66 +1,63 @@
-import { LIST_SECTION_TYPE } from './types';
-import Section from './_section';
-import { attributable } from './_attributable';
+import { LIST_SECTION_TYPE } from './types'
+import Section from './_section'
+import { attributable } from './_attributable'
-import LinkedList from '../utils/linked-list';
-import { forEach, contains } from '../utils/array-utils';
-import { normalizeTagName } from '../utils/dom-utils';
-import assert from '../utils/assert';
-import { entries } from '../utils/object-utils';
+import LinkedList from '../utils/linked-list'
+import { forEach, contains } from '../utils/array-utils'
+import { normalizeTagName } from '../utils/dom-utils'
+import assert from '../utils/assert'
+import { entries } from '../utils/object-utils'
-export const VALID_LIST_SECTION_TAGNAMES = [
- 'ul', 'ol'
-].map(normalizeTagName);
+export const VALID_LIST_SECTION_TAGNAMES = ['ul', 'ol'].map(normalizeTagName)
-export const DEFAULT_TAG_NAME = VALID_LIST_SECTION_TAGNAMES[0];
+export const DEFAULT_TAG_NAME = VALID_LIST_SECTION_TAGNAMES[0]
export default class ListSection extends Section {
- constructor(tagName=DEFAULT_TAG_NAME, items=[], attributes={}) {
- super(LIST_SECTION_TYPE);
- this.tagName = tagName;
- this.isListSection = true;
- this.isLeafSection = false;
+ constructor(tagName = DEFAULT_TAG_NAME, items = [], attributes = {}) {
+ super(LIST_SECTION_TYPE)
+ this.tagName = tagName
+ this.isListSection = true
+ this.isLeafSection = false
- attributable(this);
- entries(attributes).forEach(([k,v]) => this.setAttribute(k, v));
+ attributable(this)
+ entries(attributes).forEach(([k, v]) => this.setAttribute(k, v))
this.items = new LinkedList({
adoptItem: i => {
- assert(`Cannot insert non-list-item to list (is: ${i.type})`,
- i.isListItem);
- i.section = i.parent = this;
+ assert(`Cannot insert non-list-item to list (is: ${i.type})`, i.isListItem)
+ i.section = i.parent = this
},
- freeItem: i => i.section = i.parent = null
- });
- this.sections = this.items;
+ freeItem: i => (i.section = i.parent = null),
+ })
+ this.sections = this.items
- items.forEach(i => this.items.append(i));
+ items.forEach(i => this.items.append(i))
}
canJoin() {
- return false;
+ return false
}
isValidTagName(normalizedTagName) {
- return contains(VALID_LIST_SECTION_TAGNAMES, normalizedTagName);
+ return contains(VALID_LIST_SECTION_TAGNAMES, normalizedTagName)
}
headPosition() {
- return this.items.head.headPosition();
+ return this.items.head.headPosition()
}
tailPosition() {
- return this.items.tail.tailPosition();
+ return this.items.tail.tailPosition()
}
get isBlank() {
- return this.items.isEmpty;
+ return this.items.isEmpty
}
clone() {
- let newSection = this.builder.createListSection(this.tagName);
- forEach(this.items, i => newSection.items.append(i.clone()));
- return newSection;
+ let newSection = this.builder.createListSection(this.tagName)
+ forEach(this.items, i => newSection.items.append(i.clone()))
+ return newSection
}
/**
@@ -70,11 +67,11 @@ export default class ListSection extends Section {
*/
join(other) {
if (other.isListSection) {
- other.items.forEach(i => this.join(i));
+ other.items.forEach(i => this.join(i))
} else if (other.isMarkerable) {
- let item = this.builder.createListItem();
- item.join(other);
- this.items.append(item);
+ let item = this.builder.createListItem()
+ item.join(other)
+ this.items.append(item)
}
}
}
diff --git a/src/js/models/marker.js b/src/js/models/marker.js
index f0389cab2..b7ad72ff2 100644
--- a/src/js/models/marker.js
+++ b/src/js/models/marker.js
@@ -1,9 +1,9 @@
-import { MARKER_TYPE } from './types';
-import mixin from '../utils/mixin';
-import MarkuperableMixin from '../utils/markuperable';
-import LinkedItem from '../utils/linked-item';
-import assert from '../utils/assert';
-import { isArrayEqual } from '../utils/array-utils';
+import { MARKER_TYPE } from './types'
+import mixin from '../utils/mixin'
+import MarkuperableMixin from '../utils/markuperable'
+import LinkedItem from '../utils/linked-item'
+import assert from '../utils/assert'
+import { isArrayEqual } from '../utils/array-utils'
// Unicode uses a pair of "surrogate" characters" (a high- and low-surrogate)
// to encode characters outside the basic multilingual plane (like emoji and
@@ -12,36 +12,36 @@ import { isArrayEqual } from '../utils/array-utils';
// high- and low-surrogate characters.
// See "high surrogate" and "low surrogate" on
// https://en.wikipedia.org/wiki/Unicode_block
-export const HIGH_SURROGATE_RANGE = [0xD800, 0xDBFF];
-export const LOW_SURROGATE_RANGE = [0xDC00, 0xDFFF];
+export const HIGH_SURROGATE_RANGE = [0xd800, 0xdbff]
+export const LOW_SURROGATE_RANGE = [0xdc00, 0xdfff]
const Marker = class Marker extends LinkedItem {
- constructor(value='', markups=[]) {
- super();
- this.value = value;
- assert('Marker must have value', value !== undefined && value !== null);
- this.markups = [];
- this.type = MARKER_TYPE;
- this.isMarker = true;
- this.isAtom = false;
- markups.forEach(m => this.addMarkup(m));
+ constructor(value = '', markups = []) {
+ super()
+ this.value = value
+ assert('Marker must have value', value !== undefined && value !== null)
+ this.markups = []
+ this.type = MARKER_TYPE
+ this.isMarker = true
+ this.isAtom = false
+ markups.forEach(m => this.addMarkup(m))
}
clone() {
- const clonedMarkups = this.markups.slice();
- return this.builder.createMarker(this.value, clonedMarkups);
+ const clonedMarkups = this.markups.slice()
+ return this.builder.createMarker(this.value, clonedMarkups)
}
get isEmpty() {
- return this.isBlank;
+ return this.isBlank
}
get isBlank() {
- return this.length === 0;
+ return this.length === 0
}
charAt(offset) {
- return this.value.slice(offset, offset+1);
+ return this.value.slice(offset, offset + 1)
}
/**
@@ -49,77 +49,71 @@ const Marker = class Marker extends LinkedItem {
* Compare with an Atom which distinguishes between text and value
*/
get text() {
- return this.value;
+ return this.value
}
get length() {
- return this.value.length;
+ return this.value.length
}
// delete the character at this offset,
// update the value with the new value
deleteValueAtOffset(offset) {
- assert('Cannot delete value at offset outside bounds',
- offset >= 0 && offset <= this.length);
+ assert('Cannot delete value at offset outside bounds', offset >= 0 && offset <= this.length)
- let width = 1;
- let code = this.value.charCodeAt(offset);
+ let width = 1
+ let code = this.value.charCodeAt(offset)
if (code >= HIGH_SURROGATE_RANGE[0] && code <= HIGH_SURROGATE_RANGE[1]) {
- width = 2;
+ width = 2
} else if (code >= LOW_SURROGATE_RANGE[0] && code <= LOW_SURROGATE_RANGE[1]) {
- width = 2;
- offset = offset - 1;
+ width = 2
+ offset = offset - 1
}
- const [ left, right ] = [
- this.value.slice(0, offset),
- this.value.slice(offset+width)
- ];
- this.value = left + right;
+ const [left, right] = [this.value.slice(0, offset), this.value.slice(offset + width)]
+ this.value = left + right
- return width;
+ return width
}
canJoin(other) {
- return other && other.isMarker && isArrayEqual(this.markups, other.markups);
+ return other && other.isMarker && isArrayEqual(this.markups, other.markups)
}
textUntil(offset) {
- return this.value.slice(0, offset);
+ return this.value.slice(0, offset)
}
- split(offset=0, endOffset=this.length) {
+ split(offset = 0, endOffset = this.length) {
let markers = [
this.builder.createMarker(this.value.substring(0, offset)),
this.builder.createMarker(this.value.substring(offset, endOffset)),
- this.builder.createMarker(this.value.substring(endOffset))
- ];
+ this.builder.createMarker(this.value.substring(endOffset)),
+ ]
- this.markups.forEach(mu => markers.forEach(m => m.addMarkup(mu)));
- return markers;
+ this.markups.forEach(mu => markers.forEach(m => m.addMarkup(mu)))
+ return markers
}
/**
* @return {Array} 2 markers either or both of which could be blank
*/
splitAtOffset(offset) {
- assert('Cannot split a marker at an offset > its length',
- offset <= this.length);
- let { value, builder } = this;
+ assert('Cannot split a marker at an offset > its length', offset <= this.length)
+ let { value, builder } = this
- let pre = builder.createMarker(value.substring(0, offset));
- let post = builder.createMarker(value.substring(offset));
+ let pre = builder.createMarker(value.substring(0, offset))
+ let post = builder.createMarker(value.substring(offset))
this.markups.forEach(markup => {
- pre.addMarkup(markup);
- post.addMarkup(markup);
- });
+ pre.addMarkup(markup)
+ post.addMarkup(markup)
+ })
- return [pre, post];
+ return [pre, post]
}
+}
-};
+mixin(Marker, MarkuperableMixin)
-mixin(Marker, MarkuperableMixin);
-
-export default Marker;
+export default Marker
diff --git a/src/js/models/markup-section.js b/src/js/models/markup-section.js
index d9edd844b..700815d3b 100644
--- a/src/js/models/markup-section.js
+++ b/src/js/models/markup-section.js
@@ -1,62 +1,46 @@
-import Markerable from './_markerable';
-import { attributable } from './_attributable';
-import { MARKUP_SECTION_TYPE } from './types';
+import Markerable from './_markerable'
+import { attributable } from './_attributable'
+import { MARKUP_SECTION_TYPE } from './types'
-import { normalizeTagName } from '../utils/dom-utils';
-import { contains } from '../utils/array-utils';
-import { entries } from '../utils/object-utils';
+import { normalizeTagName } from '../utils/dom-utils'
+import { contains } from '../utils/array-utils'
+import { entries } from '../utils/object-utils'
// valid values of `tagName` for a MarkupSection
-export const VALID_MARKUP_SECTION_TAGNAMES = [
- 'aside',
- 'blockquote',
- 'h1',
- 'h2',
- 'h3',
- 'h4',
- 'h5',
- 'h6',
- 'p'
-].map(normalizeTagName);
+export const VALID_MARKUP_SECTION_TAGNAMES = ['aside', 'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'].map(
+ normalizeTagName
+)
// valid element names for a MarkupSection. A MarkupSection with a tagName
// not in this will be rendered as a div with a className matching the
// tagName
-export const MARKUP_SECTION_ELEMENT_NAMES = [
- 'aside',
- 'blockquote',
- 'h1',
- 'h2',
- 'h3',
- 'h4',
- 'h5',
- 'h6',
- 'p'
-].map(normalizeTagName);
-export const DEFAULT_TAG_NAME = VALID_MARKUP_SECTION_TAGNAMES[8];
+export const MARKUP_SECTION_ELEMENT_NAMES = ['aside', 'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'].map(
+ normalizeTagName
+)
+export const DEFAULT_TAG_NAME = VALID_MARKUP_SECTION_TAGNAMES[8]
const MarkupSection = class MarkupSection extends Markerable {
- constructor(tagName=DEFAULT_TAG_NAME, markers=[], attributes={}) {
- super(MARKUP_SECTION_TYPE, tagName, markers);
+ constructor(tagName = DEFAULT_TAG_NAME, markers = [], attributes = {}) {
+ super(MARKUP_SECTION_TYPE, tagName, markers)
- attributable(this);
- entries(attributes).forEach(([k,v]) => this.setAttribute(k, v));
+ attributable(this)
+ entries(attributes).forEach(([k, v]) => this.setAttribute(k, v))
- this.isMarkupSection = true;
+ this.isMarkupSection = true
}
isValidTagName(normalizedTagName) {
- return contains(VALID_MARKUP_SECTION_TAGNAMES, normalizedTagName);
+ return contains(VALID_MARKUP_SECTION_TAGNAMES, normalizedTagName)
}
- splitAtMarker(marker, offset=0) {
+ splitAtMarker(marker, offset = 0) {
let [beforeSection, afterSection] = [
this.builder.createMarkupSection(this.tagName, [], false, this.attributes),
- this.builder.createMarkupSection()
- ];
+ this.builder.createMarkupSection(),
+ ]
- return this._redistributeMarkers(beforeSection, afterSection, marker, offset);
+ return this._redistributeMarkers(beforeSection, afterSection, marker, offset)
}
-};
+}
-export default MarkupSection;
+export default MarkupSection
diff --git a/src/js/models/markup.js b/src/js/models/markup.js
index 1389473b2..ecece259e 100644
--- a/src/js/models/markup.js
+++ b/src/js/models/markup.js
@@ -1,7 +1,7 @@
-import { normalizeTagName } from '../utils/dom-utils';
-import { filterObject } from '../utils/array-utils';
-import { MARKUP_TYPE } from './types';
-import assert from '../utils/assert';
+import { normalizeTagName } from '../utils/dom-utils'
+import { filterObject } from '../utils/array-utils'
+import { MARKUP_TYPE } from './types'
+import assert from '../utils/assert'
export const VALID_MARKUP_TAGNAMES = [
'a',
@@ -9,18 +9,15 @@ export const VALID_MARKUP_TAGNAMES = [
'code',
'em',
'i',
- 's', // strikethrough
+ 's', // strikethrough
'del', // deleted text (also strikethrough)
'strong',
'sub', // subscript
'sup', // superscript
- 'u'
-].map(normalizeTagName);
+ 'u',
+].map(normalizeTagName)
-export const VALID_ATTRIBUTES = [
- 'href',
- 'rel'
-];
+export const VALID_ATTRIBUTES = ['href', 'rel']
/**
* A Markup is similar with an inline HTML tag that might be added to
@@ -32,17 +29,15 @@ class Markup {
/*
* @param {Object} attributes key-values
*/
- constructor(tagName, attributes={}) {
- this.tagName = normalizeTagName(tagName);
+ constructor(tagName, attributes = {}) {
+ this.tagName = normalizeTagName(tagName)
- assert('Must use attributes object param (not array) for Markup',
- !Array.isArray(attributes));
+ assert('Must use attributes object param (not array) for Markup', !Array.isArray(attributes))
- this.attributes = filterObject(attributes, VALID_ATTRIBUTES);
- this.type = MARKUP_TYPE;
+ this.attributes = filterObject(attributes, VALID_ATTRIBUTES)
+ this.type = MARKUP_TYPE
- assert(`Cannot create markup of tagName ${tagName}`,
- VALID_MARKUP_TAGNAMES.indexOf(this.tagName) !== -1);
+ assert(`Cannot create markup of tagName ${tagName}`, VALID_MARKUP_TAGNAMES.indexOf(this.tagName) !== -1)
}
/**
@@ -51,15 +46,15 @@ class Markup {
* @private
*/
isForwardInclusive() {
- return this.tagName === normalizeTagName("a") ? false : true;
+ return this.tagName === normalizeTagName('a') ? false : true
}
isBackwardInclusive() {
- return false;
+ return false
}
hasTag(tagName) {
- return this.tagName === normalizeTagName(tagName);
+ return this.tagName === normalizeTagName(tagName)
}
/**
@@ -67,13 +62,13 @@ class Markup {
* @param {String} name, e.g. "href"
*/
getAttribute(name) {
- return this.attributes[name];
+ return this.attributes[name]
}
static isValidElement(element) {
- const tagName = normalizeTagName(element.tagName);
- return VALID_MARKUP_TAGNAMES.indexOf(tagName) !== -1;
+ const tagName = normalizeTagName(element.tagName)
+ return VALID_MARKUP_TAGNAMES.indexOf(tagName) !== -1
}
}
-export default Markup;
+export default Markup
diff --git a/src/js/models/post-node-builder.js b/src/js/models/post-node-builder.js
index 16755d6a8..0690ecc0c 100644
--- a/src/js/models/post-node-builder.js
+++ b/src/js/models/post-node-builder.js
@@ -1,37 +1,30 @@
-import Atom from '../models/atom';
-import Post from '../models/post';
-import MarkupSection from '../models/markup-section';
-import ListSection from '../models/list-section';
-import ListItem from '../models/list-item';
-import ImageSection from '../models/image';
-import Marker from '../models/marker';
-import Markup from '../models/markup';
-import Card from '../models/card';
-import { normalizeTagName } from '../utils/dom-utils';
-import { objectToSortedKVArray } from '../utils/array-utils';
-import {
- LIST_ITEM_TYPE,
- MARKUP_SECTION_TYPE
-} from '../models/types';
-import {
- DEFAULT_TAG_NAME as DEFAULT_MARKUP_SECTION_TAG_NAME
-} from '../models/markup-section';
-import {
- DEFAULT_TAG_NAME as DEFAULT_LIST_SECTION_TAG_NAME
-} from '../models/list-section';
-import assert from '../utils/assert';
+import Atom from '../models/atom'
+import Post from '../models/post'
+import MarkupSection from '../models/markup-section'
+import ListSection from '../models/list-section'
+import ListItem from '../models/list-item'
+import ImageSection from '../models/image'
+import Marker from '../models/marker'
+import Markup from '../models/markup'
+import Card from '../models/card'
+import { normalizeTagName } from '../utils/dom-utils'
+import { objectToSortedKVArray } from '../utils/array-utils'
+import { LIST_ITEM_TYPE, MARKUP_SECTION_TYPE } from '../models/types'
+import { DEFAULT_TAG_NAME as DEFAULT_MARKUP_SECTION_TAG_NAME } from '../models/markup-section'
+import { DEFAULT_TAG_NAME as DEFAULT_LIST_SECTION_TAG_NAME } from '../models/list-section'
+import assert from '../utils/assert'
function cacheKey(tagName, attributes) {
- return `${normalizeTagName(tagName)}-${objectToSortedKVArray(attributes).join('-')}`;
+ return `${normalizeTagName(tagName)}-${objectToSortedKVArray(attributes).join('-')}`
}
function addMarkupToCache(cache, markup) {
- cache[cacheKey(markup.tagName, markup.attributes)] = markup;
+ cache[cacheKey(markup.tagName, markup.attributes)] = markup
}
function findMarkupInCache(cache, tagName, attributes) {
- const key = cacheKey(tagName, attributes);
- return cache[key];
+ const key = cacheKey(tagName, attributes)
+ return cache[key]
}
/**
@@ -47,29 +40,29 @@ class PostNodeBuilder {
* @private
*/
constructor() {
- this.markupCache = {};
+ this.markupCache = {}
}
/**
* @return {Post} A new, blank post
*/
- createPost(sections=[]) {
- const post = new Post();
- post.builder = this;
+ createPost(sections = []) {
+ const post = new Post()
+ post.builder = this
- sections.forEach(s => post.sections.append(s));
+ sections.forEach(s => post.sections.append(s))
- return post;
+ return post
}
- createMarkerableSection(type, tagName, markers=[]) {
+ createMarkerableSection(type, tagName, markers = []) {
switch (type) {
case LIST_ITEM_TYPE:
- return this.createListItem(markers);
+ return this.createListItem(markers)
case MARKUP_SECTION_TYPE:
- return this.createMarkupSection(tagName, markers);
+ return this.createMarkupSection(tagName, markers)
default:
- assert(`Cannot create markerable section of type ${type}`, false);
+ assert(`Cannot create markerable section of type ${type}`, false)
}
}
@@ -78,36 +71,36 @@ class PostNodeBuilder {
* @param {Marker[]} [markers=[]]
* @return {MarkupSection}
*/
- createMarkupSection(tagName=DEFAULT_MARKUP_SECTION_TAG_NAME, markers=[], isGenerated=false, attributes={}) {
- tagName = normalizeTagName(tagName);
- const section = new MarkupSection(tagName, markers, attributes);
+ createMarkupSection(tagName = DEFAULT_MARKUP_SECTION_TAG_NAME, markers = [], isGenerated = false, attributes = {}) {
+ tagName = normalizeTagName(tagName)
+ const section = new MarkupSection(tagName, markers, attributes)
if (isGenerated) {
- section.isGenerated = true;
+ section.isGenerated = true
}
- section.builder = this;
- return section;
+ section.builder = this
+ return section
}
- createListSection(tagName=DEFAULT_LIST_SECTION_TAG_NAME, items=[], attributes={}) {
- tagName = normalizeTagName(tagName);
- const section = new ListSection(tagName, items, attributes);
- section.builder = this;
- return section;
+ createListSection(tagName = DEFAULT_LIST_SECTION_TAG_NAME, items = [], attributes = {}) {
+ tagName = normalizeTagName(tagName)
+ const section = new ListSection(tagName, items, attributes)
+ section.builder = this
+ return section
}
- createListItem(markers=[]) {
- const tagName = normalizeTagName('li');
- const item = new ListItem(tagName, markers);
- item.builder = this;
- return item;
+ createListItem(markers = []) {
+ const tagName = normalizeTagName('li')
+ const item = new ListItem(tagName, markers)
+ item.builder = this
+ return item
}
createImageSection(url) {
- let section = new ImageSection();
+ let section = new ImageSection()
if (url) {
- section.src = url;
+ section.src = url
}
- return section;
+ return section
}
/**
@@ -115,10 +108,10 @@ class PostNodeBuilder {
* @param {Object} [payload={}]
* @return {CardSection}
*/
- createCardSection(name, payload={}) {
- const card = new Card(name, payload);
- card.builder = this;
- return card;
+ createCardSection(name, payload = {}) {
+ const card = new Card(name, payload)
+ card.builder = this
+ return card
}
/**
@@ -126,10 +119,10 @@ class PostNodeBuilder {
* @param {Markup[]} [markups=[]]
* @return {Marker}
*/
- createMarker(value, markups=[]) {
- const marker = new Marker(value, markups);
- marker.builder = this;
- return marker;
+ createMarker(value, markups = []) {
+ const marker = new Marker(value, markups)
+ marker.builder = this
+ return marker
}
/**
@@ -139,10 +132,10 @@ class PostNodeBuilder {
* @param {Markup[]} [markups=[]]
* @return {Atom}
*/
- createAtom(name, value='', payload={}, markups=[]) {
- const atom = new Atom(name, value, payload, markups);
- atom.builder = this;
- return atom;
+ createAtom(name, value = '', payload = {}, markups = []) {
+ const atom = new Atom(name, value, payload, markups)
+ atom.builder = this
+ return atom
}
/**
@@ -150,18 +143,18 @@ class PostNodeBuilder {
* @param {Object} attributes Key-value pairs of attributes for the markup
* @return {Markup}
*/
- createMarkup(tagName, attributes={}) {
- tagName = normalizeTagName(tagName);
+ createMarkup(tagName, attributes = {}) {
+ tagName = normalizeTagName(tagName)
- let markup = findMarkupInCache(this.markupCache, tagName, attributes);
+ let markup = findMarkupInCache(this.markupCache, tagName, attributes)
if (!markup) {
- markup = new Markup(tagName, attributes);
- markup.builder = this;
- addMarkupToCache(this.markupCache, markup);
+ markup = new Markup(tagName, attributes)
+ markup.builder = this
+ addMarkupToCache(this.markupCache, markup)
}
- return markup;
+ return markup
}
}
-export default PostNodeBuilder;
+export default PostNodeBuilder
diff --git a/src/js/models/post.js b/src/js/models/post.js
index 18772dd29..4117cfc48 100644
--- a/src/js/models/post.js
+++ b/src/js/models/post.js
@@ -1,9 +1,9 @@
-import { POST_TYPE } from './types';
-import LinkedList from 'mobiledoc-kit/utils/linked-list';
-import { forEach } from 'mobiledoc-kit/utils/array-utils';
-import Set from 'mobiledoc-kit/utils/set';
-import Position from 'mobiledoc-kit/utils/cursor/position';
-import assert from 'mobiledoc-kit/utils/assert';
+import { POST_TYPE } from './types'
+import LinkedList from 'mobiledoc-kit/utils/linked-list'
+import { forEach } from 'mobiledoc-kit/utils/array-utils'
+import Set from 'mobiledoc-kit/utils/set'
+import Position from 'mobiledoc-kit/utils/cursor/position'
+import assert from 'mobiledoc-kit/utils/assert'
/**
* The Post is an in-memory representation of an editor's document.
@@ -18,11 +18,11 @@ class Post {
* @private
*/
constructor() {
- this.type = POST_TYPE;
+ this.type = POST_TYPE
this.sections = new LinkedList({
- adoptItem: s => s.post = s.parent = this,
- freeItem: s => s.post = s.parent = null
- });
+ adoptItem: s => (s.post = s.parent = this),
+ freeItem: s => (s.post = s.parent = null),
+ })
}
/**
@@ -32,9 +32,9 @@ class Post {
*/
headPosition() {
if (this.isBlank) {
- return Position.blankPosition();
+ return Position.blankPosition()
} else {
- return this.sections.head.headPosition();
+ return this.sections.head.headPosition()
}
}
@@ -45,9 +45,9 @@ class Post {
*/
tailPosition() {
if (this.isBlank) {
- return Position.blankPosition();
+ return Position.blankPosition()
} else {
- return this.sections.tail.tailPosition();
+ return this.sections.tail.tailPosition()
}
}
@@ -56,11 +56,11 @@ class Post {
* @public
*/
toRange() {
- return this.headPosition().toRange(this.tailPosition());
+ return this.headPosition().toRange(this.tailPosition())
}
get isBlank() {
- return this.sections.isEmpty;
+ return this.sections.isEmpty
}
/**
@@ -70,11 +70,10 @@ class Post {
* @public
*/
get hasContent() {
- if ((this.sections.length > 1) ||
- (this.sections.length === 1 && !this.sections.head.isBlank)) {
- return true;
+ if (this.sections.length > 1 || (this.sections.length === 1 && !this.sections.head.isBlank)) {
+ return true
} else {
- return false;
+ return false
}
}
@@ -83,75 +82,73 @@ class Post {
* @return {Array} markers that are completely contained by the range
*/
markersContainedByRange(range) {
- const markers = [];
+ const markers = []
this.walkMarkerableSections(range, section => {
- section._markersInRange(
- range.trimTo(section),
- (m, {isContained}) => { if (isContained) { markers.push(m); } }
- );
- });
+ section._markersInRange(range.trimTo(section), (m, { isContained }) => {
+ if (isContained) {
+ markers.push(m)
+ }
+ })
+ })
- return markers;
+ return markers
}
markupsInRange(range) {
- const markups = new Set();
+ const markups = new Set()
if (range.isCollapsed) {
- let pos = range.head;
+ let pos = range.head
if (pos.isMarkerable) {
- let [back, forward] = [pos.markerIn(-1), pos.markerIn(1)];
+ let [back, forward] = [pos.markerIn(-1), pos.markerIn(1)]
if (back && forward && back === forward) {
- back.markups.forEach(m => markups.add(m));
+ back.markups.forEach(m => markups.add(m))
} else {
- (back && back.markups || []).forEach(m => {
+ ;((back && back.markups) || []).forEach(m => {
if (m.isForwardInclusive()) {
- markups.add(m);
+ markups.add(m)
}
- });
- (forward && forward.markups || []).forEach(m => {
+ })
+ ;((forward && forward.markups) || []).forEach(m => {
if (m.isBackwardInclusive()) {
- markups.add(m);
+ markups.add(m)
}
- });
+ })
}
}
} else {
- this.walkMarkerableSections(range, (section) => {
- forEach(
- section.markupsInRange(range.trimTo(section)),
- m => markups.add(m)
- );
- });
+ this.walkMarkerableSections(range, section => {
+ forEach(section.markupsInRange(range.trimTo(section)), m => markups.add(m))
+ })
}
- return markups.toArray();
+ return markups.toArray()
}
walkAllLeafSections(callback) {
- let range = this.headPosition().toRange(this.tailPosition());
- return this.walkLeafSections(range, callback);
+ let range = this.headPosition().toRange(this.tailPosition())
+ return this.walkLeafSections(range, callback)
}
walkLeafSections(range, callback) {
- const { head, tail } = range;
+ const { head, tail } = range
- let index = 0;
- let nextSection, shouldStop;
- let currentSection = head.section;
+ let index = 0
+ let nextSection, shouldStop
+ let currentSection = head.section
while (currentSection) {
- nextSection = this._nextLeafSection(currentSection);
- shouldStop = currentSection === tail.section;
+ nextSection = this._nextLeafSection(currentSection)
+ shouldStop = currentSection === tail.section
- callback(currentSection, index);
- index++;
+ callback(currentSection, index)
+ index++
if (shouldStop) {
- break;
+ break
} else {
- currentSection = nextSection;
+ currentSection = nextSection
}
}
}
@@ -159,30 +156,32 @@ class Post {
walkMarkerableSections(range, callback) {
this.walkLeafSections(range, section => {
if (section.isMarkerable) {
- callback(section);
+ callback(section)
}
- });
+ })
}
// return the next section that has markers after this one,
// possibly skipping non-markerable sections
_nextLeafSection(section) {
- if (!section) { return null; }
+ if (!section) {
+ return null
+ }
- const next = section.next;
+ const next = section.next
if (next) {
if (next.isLeafSection) {
- return next;
+ return next
} else if (next.items) {
- return next.items.head;
+ return next.items.head
} else {
- assert('Cannot determine next section from non-leaf-section', false);
+ assert('Cannot determine next section from non-leaf-section', false)
}
} else if (section.isNested) {
// if there is no section after this, but this section is a child
// (e.g. a ListItem inside a ListSection), check for a markerable
// section after its parent
- return this._nextLeafSection(section.parent);
+ return this._nextLeafSection(section.parent)
}
}
@@ -191,53 +190,48 @@ class Post {
* @return {Post} A new post, constrained to {range}
*/
trimTo(range) {
- const post = this.builder.createPost();
- const { builder } = this;
- const { head, tail } = range;
- const tailNotSelected = tail.offset === 0 && head.section !== tail.section;
+ const post = this.builder.createPost()
+ const { builder } = this
+ const { head, tail } = range
+ const tailNotSelected = tail.offset === 0 && head.section !== tail.section
let sectionParent = post,
- listParent = null;
+ listParent = null
this.walkLeafSections(range, section => {
- let newSection;
+ let newSection
if (section.isMarkerable) {
if (section.isListItem) {
if (listParent) {
- sectionParent = null;
+ sectionParent = null
} else {
- listParent = builder.createListSection(section.parent.tagName);
- post.sections.append(listParent);
- sectionParent = null;
+ listParent = builder.createListSection(section.parent.tagName)
+ post.sections.append(listParent)
+ sectionParent = null
}
- newSection = builder.createListItem();
- listParent.items.append(newSection);
+ newSection = builder.createListItem()
+ listParent.items.append(newSection)
} else {
- listParent = null;
- sectionParent = post;
- const tagName = tailNotSelected && tail.section === section ?
- 'p' :
- section.tagName;
- newSection = builder.createMarkupSection(tagName);
+ listParent = null
+ sectionParent = post
+ const tagName = tailNotSelected && tail.section === section ? 'p' : section.tagName
+ newSection = builder.createMarkupSection(tagName)
}
- let currentRange = range.trimTo(section);
- forEach(
- section.markersFor(currentRange.headSectionOffset, currentRange.tailSectionOffset),
- m => newSection.markers.append(m)
- );
+ let currentRange = range.trimTo(section)
+ forEach(section.markersFor(currentRange.headSectionOffset, currentRange.tailSectionOffset), m =>
+ newSection.markers.append(m)
+ )
} else {
- newSection = tailNotSelected && tail.section === section ?
- builder.createMarkupSection('p') :
- section.clone();
+ newSection = tailNotSelected && tail.section === section ? builder.createMarkupSection('p') : section.clone()
- sectionParent = post;
+ sectionParent = post
}
if (sectionParent) {
- sectionParent.sections.append(newSection);
+ sectionParent.sections.append(newSection)
}
- });
- return post;
+ })
+ return post
}
}
-export default Post;
+export default Post
diff --git a/src/js/models/render-node.js b/src/js/models/render-node.js
index 6807e0a7c..8ad21aa9b 100644
--- a/src/js/models/render-node.js
+++ b/src/js/models/render-node.js
@@ -1,92 +1,95 @@
-import LinkedItem from 'mobiledoc-kit/utils/linked-item';
-import LinkedList from 'mobiledoc-kit/utils/linked-list';
-import { containsNode } from 'mobiledoc-kit/utils/dom-utils';
-import assert from 'mobiledoc-kit/utils/assert';
+import LinkedItem from 'mobiledoc-kit/utils/linked-item'
+import LinkedList from 'mobiledoc-kit/utils/linked-list'
+import { containsNode } from 'mobiledoc-kit/utils/dom-utils'
+import assert from 'mobiledoc-kit/utils/assert'
export default class RenderNode extends LinkedItem {
constructor(postNode, renderTree) {
- super();
- this.parent = null;
- this.isDirty = true;
- this.isRemoved = false;
- this.postNode = postNode;
- this._childNodes = null;
- this._element = null;
- this._cursorElement = null; // blank render nodes need a cursor element
- this.renderTree = renderTree;
+ super()
+ this.parent = null
+ this.isDirty = true
+ this.isRemoved = false
+ this.postNode = postNode
+ this._childNodes = null
+ this._element = null
+ this._cursorElement = null // blank render nodes need a cursor element
+ this.renderTree = renderTree
// RenderNodes for Markers keep track of their markupElement
- this.markupElement = null;
+ this.markupElement = null
// RenderNodes for Atoms use these properties
- this.headTextNode = null;
- this.tailTextNode = null;
- this.atomNode = null;
+ this.headTextNode = null
+ this.tailTextNode = null
+ this.atomNode = null
// RenderNodes for cards use this property
- this.cardNode = null;
+ this.cardNode = null
}
isAttached() {
- assert('Cannot check if a renderNode is attached without an element.',
- !!this.element);
- return containsNode(this.renderTree.rootElement, this.element);
+ assert('Cannot check if a renderNode is attached without an element.', !!this.element)
+ return containsNode(this.renderTree.rootElement, this.element)
}
get childNodes() {
if (!this._childNodes) {
this._childNodes = new LinkedList({
- adoptItem: item => item.parent = this,
- freeItem: item => item.destroy()
- });
+ adoptItem: item => (item.parent = this),
+ freeItem: item => item.destroy(),
+ })
}
- return this._childNodes;
+ return this._childNodes
}
scheduleForRemoval() {
- this.isRemoved = true;
- if (this.parent) { this.parent.markDirty(); }
+ this.isRemoved = true
+ if (this.parent) {
+ this.parent.markDirty()
+ }
}
markDirty() {
- this.isDirty = true;
- if (this.parent) { this.parent.markDirty(); }
+ this.isDirty = true
+ if (this.parent) {
+ this.parent.markDirty()
+ }
}
get isRendered() {
- return !!this.element;
+ return !!this.element
}
markClean() {
- this.isDirty = false;
+ this.isDirty = false
}
set element(element) {
- const currentElement = this._element;
- this._element = element;
+ const currentElement = this._element
+ this._element = element
if (currentElement) {
- this.renderTree.removeElementRenderNode(currentElement);
+ this.renderTree.removeElementRenderNode(currentElement)
}
if (element) {
- this.renderTree.setElementRenderNode(element, this);
+ this.renderTree.setElementRenderNode(element, this)
}
}
get element() {
- return this._element;
+ return this._element
}
set cursorElement(cursorElement) {
- this._cursorElement = cursorElement;
+ this._cursorElement = cursorElement
}
get cursorElement() {
- return this._cursorElement || this.element;
+ return this._cursorElement || this.element
}
destroy() {
- this.element = null;
- this.parent = null;
- this.postNode = null;
- this.renderTree = null;
+ this.element = null
+ this.parent = null
+ this.postNode = null
+ this.renderTree = null
}
reparsesMutationOfChildNode(node) {
if (this.postNode.isCardSection) {
- return !containsNode(this.cardNode.element, node);
+ return !containsNode(this.cardNode.element, node)
} else if (this.postNode.isAtom) {
- return !containsNode(this.atomNode.element, node);
+ return !containsNode(this.atomNode.element, node)
}
- return true;
+ return true
}
}
diff --git a/src/js/models/render-tree.js b/src/js/models/render-tree.js
index dbfc67fb2..d4d3d9195 100644
--- a/src/js/models/render-tree.js
+++ b/src/js/models/render-tree.js
@@ -1,70 +1,70 @@
-import RenderNode from 'mobiledoc-kit/models/render-node';
-import ElementMap from '../utils/element-map';
+import RenderNode from 'mobiledoc-kit/models/render-node'
+import ElementMap from '../utils/element-map'
export default class RenderTree {
constructor(rootPostNode) {
- this._rootNode = this.buildRenderNode(rootPostNode);
- this._elements = new ElementMap();
+ this._rootNode = this.buildRenderNode(rootPostNode)
+ this._elements = new ElementMap()
}
/*
* @return {RenderNode} The root render node in this tree
*/
get rootNode() {
- return this._rootNode;
+ return this._rootNode
}
/**
* @return {Boolean}
*/
get isDirty() {
- return this.rootNode && this.rootNode.isDirty;
+ return this.rootNode && this.rootNode.isDirty
}
/*
* @return {DOMNode} The root DOM element in this tree
*/
get rootElement() {
- return this.rootNode.element;
+ return this.rootNode.element
}
/*
* @param {DOMNode} element
* @return {RenderNode} The renderNode for this element, if any
*/
getElementRenderNode(element) {
- return this._elements.get(element);
+ return this._elements.get(element)
}
setElementRenderNode(element, renderNode) {
- this._elements.set(element, renderNode);
+ this._elements.set(element, renderNode)
}
removeElementRenderNode(element) {
- this._elements.remove(element);
+ this._elements.remove(element)
}
/**
* @param {DOMNode} element
* Walk up from the dom element until we find a renderNode element
*/
- findRenderNodeFromElement(element, conditionFn=()=>true) {
- let renderNode;
+ findRenderNodeFromElement(element, conditionFn = () => true) {
+ let renderNode
while (element) {
- renderNode = this.getElementRenderNode(element);
+ renderNode = this.getElementRenderNode(element)
if (renderNode && conditionFn(renderNode)) {
- return renderNode;
+ return renderNode
}
// continue loop
- element = element.parentNode;
+ element = element.parentNode
// stop if we are at the root element
if (element === this.rootElement) {
if (conditionFn(this.rootNode)) {
- return this.rootNode;
+ return this.rootNode
} else {
- return;
+ return
}
}
}
}
buildRenderNode(postNode) {
- const renderNode = new RenderNode(postNode, this);
- postNode.renderNode = renderNode;
- return renderNode;
+ const renderNode = new RenderNode(postNode, this)
+ postNode.renderNode = renderNode
+ return renderNode
}
}
diff --git a/src/js/models/types.js b/src/js/models/types.js
index aa2f6f0c9..4105d6297 100644
--- a/src/js/models/types.js
+++ b/src/js/models/types.js
@@ -1,9 +1,9 @@
-export const MARKUP_SECTION_TYPE = 'markup-section';
-export const LIST_SECTION_TYPE = 'list-section';
-export const MARKUP_TYPE = 'markup';
-export const MARKER_TYPE = 'marker';
-export const POST_TYPE = 'post';
-export const LIST_ITEM_TYPE = 'list-item';
-export const CARD_TYPE = 'card-section';
-export const IMAGE_SECTION_TYPE = 'image-section';
-export const ATOM_TYPE = 'atom';
\ No newline at end of file
+export const MARKUP_SECTION_TYPE = 'markup-section'
+export const LIST_SECTION_TYPE = 'list-section'
+export const MARKUP_TYPE = 'markup'
+export const MARKER_TYPE = 'marker'
+export const POST_TYPE = 'post'
+export const LIST_ITEM_TYPE = 'list-item'
+export const CARD_TYPE = 'card-section'
+export const IMAGE_SECTION_TYPE = 'image-section'
+export const ATOM_TYPE = 'atom'
diff --git a/src/js/parsers/dom.js b/src/js/parsers/dom.js
index 91447d772..d20318c37 100644
--- a/src/js/parsers/dom.js
+++ b/src/js/parsers/dom.js
@@ -1,99 +1,77 @@
-import {
- NO_BREAK_SPACE,
- TAB_CHARACTER,
- ATOM_CLASS_NAME
-} from '../renderers/editor-dom';
-import {
- MARKUP_SECTION_TYPE,
- LIST_SECTION_TYPE,
- LIST_ITEM_TYPE
-} from '../models/types';
-import {
- isTextNode,
- isCommentNode,
- isElementNode,
- getAttributes,
- normalizeTagName
-} from '../utils/dom-utils';
-import {
- any,
- detect,
- forEach
-} from '../utils/array-utils';
-import { TAB } from 'mobiledoc-kit/utils/characters';
-import { ZWNJ } from 'mobiledoc-kit/renderers/editor-dom';
-
-import SectionParser from 'mobiledoc-kit/parsers/section';
-import Markup from 'mobiledoc-kit/models/markup';
-
-const GOOGLE_DOCS_CONTAINER_ID_REGEX = /^docs\-internal\-guid/;
-
-const NO_BREAK_SPACE_REGEX = new RegExp(NO_BREAK_SPACE, 'g');
-const TAB_CHARACTER_REGEX = new RegExp(TAB_CHARACTER, 'g');
+import { NO_BREAK_SPACE, TAB_CHARACTER, ATOM_CLASS_NAME } from '../renderers/editor-dom'
+import { MARKUP_SECTION_TYPE, LIST_SECTION_TYPE, LIST_ITEM_TYPE } from '../models/types'
+import { isTextNode, isCommentNode, isElementNode, getAttributes, normalizeTagName } from '../utils/dom-utils'
+import { any, detect, forEach } from '../utils/array-utils'
+import { TAB } from 'mobiledoc-kit/utils/characters'
+import { ZWNJ } from 'mobiledoc-kit/renderers/editor-dom'
+
+import SectionParser from 'mobiledoc-kit/parsers/section'
+import Markup from 'mobiledoc-kit/models/markup'
+
+const GOOGLE_DOCS_CONTAINER_ID_REGEX = /^docs\-internal\-guid/
+
+const NO_BREAK_SPACE_REGEX = new RegExp(NO_BREAK_SPACE, 'g')
+const TAB_CHARACTER_REGEX = new RegExp(TAB_CHARACTER, 'g')
export function transformHTMLText(textContent) {
- let text = textContent;
- text = text.replace(NO_BREAK_SPACE_REGEX, ' ');
- text = text.replace(TAB_CHARACTER_REGEX, TAB);
- return text;
+ let text = textContent
+ text = text.replace(NO_BREAK_SPACE_REGEX, ' ')
+ text = text.replace(TAB_CHARACTER_REGEX, TAB)
+ return text
}
export function trimSectionText(section) {
if (section.isMarkerable && section.markers.length) {
- let { head, tail } = section.markers;
- head.value = head.value.replace(/^\s+/, '');
- tail.value = tail.value.replace(/\s+$/, '');
+ let { head, tail } = section.markers
+ head.value = head.value.replace(/^\s+/, '')
+ tail.value = tail.value.replace(/\s+$/, '')
}
}
function isGoogleDocsContainer(element) {
- return !isTextNode(element) &&
- !isCommentNode(element) &&
- normalizeTagName(element.tagName) === normalizeTagName('b') &&
- GOOGLE_DOCS_CONTAINER_ID_REGEX.test(element.id);
+ return (
+ !isTextNode(element) &&
+ !isCommentNode(element) &&
+ normalizeTagName(element.tagName) === normalizeTagName('b') &&
+ GOOGLE_DOCS_CONTAINER_ID_REGEX.test(element.id)
+ )
}
function detectRootElement(element) {
- let childNodes = element.childNodes || [];
- let googleDocsContainer = detect(childNodes, isGoogleDocsContainer);
+ let childNodes = element.childNodes || []
+ let googleDocsContainer = detect(childNodes, isGoogleDocsContainer)
if (googleDocsContainer) {
- return googleDocsContainer;
+ return googleDocsContainer
} else {
- return element;
+ return element
}
}
const TAG_REMAPPING = {
- 'b': 'strong',
- 'i': 'em'
-};
+ b: 'strong',
+ i: 'em',
+}
function remapTagName(tagName) {
- let normalized = normalizeTagName(tagName);
- let remapped = TAG_REMAPPING[normalized];
- return remapped || normalized;
+ let normalized = normalizeTagName(tagName)
+ let remapped = TAG_REMAPPING[normalized]
+ return remapped || normalized
}
function trim(str) {
- return str.replace(/^\s+/, '').replace(/\s+$/, '');
+ return str.replace(/^\s+/, '').replace(/\s+$/, '')
}
function walkMarkerableNodes(parent, callback) {
- let currentNode = parent;
-
- if (
- isTextNode(currentNode) ||
- (
- isElementNode(currentNode) &&
- currentNode.classList.contains(ATOM_CLASS_NAME)
- )
- ) {
- callback(currentNode);
+ let currentNode = parent
+
+ if (isTextNode(currentNode) || (isElementNode(currentNode) && currentNode.classList.contains(ATOM_CLASS_NAME))) {
+ callback(currentNode)
} else {
- currentNode = currentNode.firstChild;
+ currentNode = currentNode.firstChild
while (currentNode) {
- walkMarkerableNodes(currentNode, callback);
- currentNode = currentNode.nextSibling;
+ walkMarkerableNodes(currentNode, callback)
+ currentNode = currentNode.nextSibling
}
}
}
@@ -103,83 +81,83 @@ function walkMarkerableNodes(parent, callback) {
* @private
*/
class DOMParser {
- constructor(builder, options={}) {
- this.builder = builder;
- this.sectionParser = new SectionParser(this.builder, options);
+ constructor(builder, options = {}) {
+ this.builder = builder
+ this.sectionParser = new SectionParser(this.builder, options)
}
parse(element) {
- const post = this.builder.createPost();
- let rootElement = detectRootElement(element);
+ const post = this.builder.createPost()
+ let rootElement = detectRootElement(element)
this._eachChildNode(rootElement, child => {
- let sections = this.parseSections(child);
- this.appendSections(post, sections);
- });
+ let sections = this.parseSections(child)
+ this.appendSections(post, sections)
+ })
// trim leading/trailing whitespace of markerable sections to avoid
// unnessary whitespace from indented HTML input
- forEach(post.sections, section => trimSectionText(section));
+ forEach(post.sections, section => trimSectionText(section))
- return post;
+ return post
}
appendSections(post, sections) {
- forEach(sections, section => this.appendSection(post, section));
+ forEach(sections, section => this.appendSection(post, section))
}
appendSection(post, section) {
if (
section.isBlank ||
- (section.isMarkerable &&
- trim(section.text) === "" &&
- !any(section.markers, marker => marker.isAtom))
+ (section.isMarkerable && trim(section.text) === '' && !any(section.markers, marker => marker.isAtom))
) {
- return;
+ return
}
- let lastSection = post.sections.tail;
- if (lastSection &&
- lastSection._inferredTagName &&
- section._inferredTagName &&
- lastSection.tagName === section.tagName) {
- lastSection.join(section);
+ let lastSection = post.sections.tail
+ if (
+ lastSection &&
+ lastSection._inferredTagName &&
+ section._inferredTagName &&
+ lastSection.tagName === section.tagName
+ ) {
+ lastSection.join(section)
} else {
- post.sections.append(section);
+ post.sections.append(section)
}
}
_eachChildNode(element, callback) {
- let nodes = isTextNode(element) ? [element] : element.childNodes;
- forEach(nodes, node => callback(node));
+ let nodes = isTextNode(element) ? [element] : element.childNodes
+ forEach(nodes, node => callback(node))
}
parseSections(element) {
- return this.sectionParser.parse(element);
+ return this.sectionParser.parse(element)
}
// walk up from the textNode until the rootNode, converting each
// parentNode into a markup
collectMarkups(textNode, rootNode) {
- let markups = [];
- let currentNode = textNode.parentNode;
+ let markups = []
+ let currentNode = textNode.parentNode
while (currentNode && currentNode !== rootNode) {
- let markup = this.markupFromNode(currentNode);
+ let markup = this.markupFromNode(currentNode)
if (markup) {
- markups.push(markup);
+ markups.push(markup)
}
- currentNode = currentNode.parentNode;
+ currentNode = currentNode.parentNode
}
- return markups;
+ return markups
}
// Turn an element node into a markup
markupFromNode(node) {
if (Markup.isValidElement(node)) {
- let tagName = remapTagName(node.tagName);
- let attributes = getAttributes(node);
- return this.builder.createMarkup(tagName, attributes);
+ let tagName = remapTagName(node.tagName)
+ let attributes = getAttributes(node)
+ return this.builder.createMarkup(tagName, attributes)
}
}
@@ -188,135 +166,134 @@ class DOMParser {
reparseSection(section, renderTree) {
switch (section.type) {
case LIST_SECTION_TYPE:
- return this.reparseListSection(section, renderTree);
+ return this.reparseListSection(section, renderTree)
case LIST_ITEM_TYPE:
- return this.reparseListItem(section, renderTree);
+ return this.reparseListItem(section, renderTree)
case MARKUP_SECTION_TYPE:
- return this.reparseMarkupSection(section, renderTree);
+ return this.reparseMarkupSection(section, renderTree)
default:
- return; // can only parse the above types
+ return // can only parse the above types
}
}
reparseMarkupSection(section, renderTree) {
- return this._reparseSectionContainingMarkers(section, renderTree);
+ return this._reparseSectionContainingMarkers(section, renderTree)
}
reparseListItem(listItem, renderTree) {
- return this._reparseSectionContainingMarkers(listItem, renderTree);
+ return this._reparseSectionContainingMarkers(listItem, renderTree)
}
reparseListSection(listSection, renderTree) {
- listSection.items.forEach(li => this.reparseListItem(li, renderTree));
+ listSection.items.forEach(li => this.reparseListItem(li, renderTree))
}
_reparseSectionContainingMarkers(section, renderTree) {
- let element = section.renderNode.element;
- let seenRenderNodes = [];
- let previousMarker;
+ let element = section.renderNode.element
+ let seenRenderNodes = []
+ let previousMarker
- walkMarkerableNodes(element, (node) => {
- let marker;
- let renderNode = renderTree.getElementRenderNode(node);
+ walkMarkerableNodes(element, node => {
+ let marker
+ let renderNode = renderTree.getElementRenderNode(node)
if (renderNode) {
if (renderNode.postNode.isMarker) {
- let text = transformHTMLText(node.textContent);
- let markups = this.collectMarkups(node, element);
+ let text = transformHTMLText(node.textContent)
+ let markups = this.collectMarkups(node, element)
if (text.length) {
- marker = renderNode.postNode;
- marker.value = text;
- marker.markups = markups;
+ marker = renderNode.postNode
+ marker.value = text
+ marker.markups = markups
} else {
- renderNode.scheduleForRemoval();
+ renderNode.scheduleForRemoval()
}
} else if (renderNode.postNode.isAtom) {
- let { headTextNode, tailTextNode } = renderNode;
+ let { headTextNode, tailTextNode } = renderNode
if (headTextNode.textContent !== ZWNJ) {
- let value = headTextNode.textContent.replace(new RegExp(ZWNJ, 'g'), '');
- headTextNode.textContent = ZWNJ;
+ let value = headTextNode.textContent.replace(new RegExp(ZWNJ, 'g'), '')
+ headTextNode.textContent = ZWNJ
if (previousMarker && previousMarker.isMarker) {
- previousMarker.value += value;
+ previousMarker.value += value
if (previousMarker.renderNode) {
- previousMarker.renderNode.markDirty();
+ previousMarker.renderNode.markDirty()
}
} else {
- let postNode = renderNode.postNode;
- let newMarkups = postNode.markups.slice();
- let newPreviousMarker = this.builder.createMarker(value, newMarkups);
- section.markers.insertBefore(newPreviousMarker, postNode);
-
- let newPreviousRenderNode = renderTree.buildRenderNode(newPreviousMarker);
- newPreviousRenderNode.markDirty();
- section.renderNode.markDirty();
-
- seenRenderNodes.push(newPreviousRenderNode);
- section.renderNode.childNodes.insertBefore(newPreviousRenderNode,
- renderNode);
+ let postNode = renderNode.postNode
+ let newMarkups = postNode.markups.slice()
+ let newPreviousMarker = this.builder.createMarker(value, newMarkups)
+ section.markers.insertBefore(newPreviousMarker, postNode)
+
+ let newPreviousRenderNode = renderTree.buildRenderNode(newPreviousMarker)
+ newPreviousRenderNode.markDirty()
+ section.renderNode.markDirty()
+
+ seenRenderNodes.push(newPreviousRenderNode)
+ section.renderNode.childNodes.insertBefore(newPreviousRenderNode, renderNode)
}
}
if (tailTextNode.textContent !== ZWNJ) {
- let value = tailTextNode.textContent.replace(new RegExp(ZWNJ, 'g'), '');
- tailTextNode.textContent = ZWNJ;
+ let value = tailTextNode.textContent.replace(new RegExp(ZWNJ, 'g'), '')
+ tailTextNode.textContent = ZWNJ
if (renderNode.postNode.next && renderNode.postNode.next.isMarker) {
- let nextMarker = renderNode.postNode.next;
+ let nextMarker = renderNode.postNode.next
if (nextMarker.renderNode) {
- let nextValue = nextMarker.renderNode.element.textContent;
- nextMarker.renderNode.element.textContent = value + nextValue;
+ let nextValue = nextMarker.renderNode.element.textContent
+ nextMarker.renderNode.element.textContent = value + nextValue
} else {
- let nextValue = value + nextMarker.value;
- nextMarker.value = nextValue;
+ let nextValue = value + nextMarker.value
+ nextMarker.value = nextValue
}
} else {
- let postNode = renderNode.postNode;
- let newMarkups = postNode.markups.slice();
- let newMarker = this.builder.createMarker(value, newMarkups);
+ let postNode = renderNode.postNode
+ let newMarkups = postNode.markups.slice()
+ let newMarker = this.builder.createMarker(value, newMarkups)
- section.markers.insertAfter(newMarker, postNode);
+ section.markers.insertAfter(newMarker, postNode)
- let newRenderNode = renderTree.buildRenderNode(newMarker);
- seenRenderNodes.push(newRenderNode);
+ let newRenderNode = renderTree.buildRenderNode(newMarker)
+ seenRenderNodes.push(newRenderNode)
- newRenderNode.markDirty();
- section.renderNode.markDirty();
+ newRenderNode.markDirty()
+ section.renderNode.markDirty()
- section.renderNode.childNodes.insertAfter(newRenderNode, renderNode);
+ section.renderNode.childNodes.insertAfter(newRenderNode, renderNode)
}
}
if (renderNode) {
- marker = renderNode.postNode;
+ marker = renderNode.postNode
}
}
} else if (isTextNode(node)) {
- let text = transformHTMLText(node.textContent);
- let markups = this.collectMarkups(node, element);
- marker = this.builder.createMarker(text, markups);
-
- renderNode = renderTree.buildRenderNode(marker);
- renderNode.element = node;
- renderNode.markClean();
- section.renderNode.markDirty();
-
- let previousRenderNode = previousMarker && previousMarker.renderNode;
- section.markers.insertAfter(marker, previousMarker);
- section.renderNode.childNodes.insertAfter(renderNode, previousRenderNode);
+ let text = transformHTMLText(node.textContent)
+ let markups = this.collectMarkups(node, element)
+ marker = this.builder.createMarker(text, markups)
+
+ renderNode = renderTree.buildRenderNode(marker)
+ renderNode.element = node
+ renderNode.markClean()
+ section.renderNode.markDirty()
+
+ let previousRenderNode = previousMarker && previousMarker.renderNode
+ section.markers.insertAfter(marker, previousMarker)
+ section.renderNode.childNodes.insertAfter(renderNode, previousRenderNode)
}
if (renderNode) {
- seenRenderNodes.push(renderNode);
+ seenRenderNodes.push(renderNode)
}
- previousMarker = marker;
- });
+ previousMarker = marker
+ })
- let renderNode = section.renderNode.childNodes.head;
+ let renderNode = section.renderNode.childNodes.head
while (renderNode) {
if (seenRenderNodes.indexOf(renderNode) === -1) {
- renderNode.scheduleForRemoval();
+ renderNode.scheduleForRemoval()
}
- renderNode = renderNode.next;
+ renderNode = renderNode.next
}
}
}
-export default DOMParser;
+export default DOMParser
diff --git a/src/js/parsers/html.js b/src/js/parsers/html.js
index b12472761..20cb92b43 100644
--- a/src/js/parsers/html.js
+++ b/src/js/parsers/html.js
@@ -1,12 +1,12 @@
-import { parseHTML } from '../utils/dom-utils';
-import assert from '../utils/assert';
-import DOMParser from './dom';
+import { parseHTML } from '../utils/dom-utils'
+import assert from '../utils/assert'
+import DOMParser from './dom'
export default class HTMLParser {
- constructor(builder, options={}) {
- assert('Must pass builder to HTMLParser', builder);
- this.builder = builder;
- this.options = options;
+ constructor(builder, options = {}) {
+ assert('Must pass builder to HTMLParser', builder)
+ this.builder = builder
+ this.options = options
}
/**
@@ -14,8 +14,8 @@ export default class HTMLParser {
* @return {Post} A post abstract
*/
parse(html) {
- let dom = parseHTML(html);
- let parser = new DOMParser(this.builder, this.options);
- return parser.parse(dom);
+ let dom = parseHTML(html)
+ let parser = new DOMParser(this.builder, this.options)
+ return parser.parse(dom)
}
}
diff --git a/src/js/parsers/mobiledoc/0-2.js b/src/js/parsers/mobiledoc/0-2.js
index 9e77348e4..3410c7f00 100644
--- a/src/js/parsers/mobiledoc/0-2.js
+++ b/src/js/parsers/mobiledoc/0-2.js
@@ -2,120 +2,120 @@ import {
MOBILEDOC_MARKUP_SECTION_TYPE,
MOBILEDOC_IMAGE_SECTION_TYPE,
MOBILEDOC_LIST_SECTION_TYPE,
- MOBILEDOC_CARD_SECTION_TYPE
-} from 'mobiledoc-kit/renderers/mobiledoc/0-2';
-import { kvArrayToObject, filter } from "../../utils/array-utils";
-import assert from 'mobiledoc-kit/utils/assert';
+ MOBILEDOC_CARD_SECTION_TYPE,
+} from 'mobiledoc-kit/renderers/mobiledoc/0-2'
+import { kvArrayToObject, filter } from '../../utils/array-utils'
+import assert from 'mobiledoc-kit/utils/assert'
/*
* Parses from mobiledoc -> post
*/
export default class MobiledocParser {
constructor(builder) {
- this.builder = builder;
+ this.builder = builder
}
/**
* @param {Mobiledoc}
* @return {Post}
*/
- parse({sections: sectionData}) {
+ parse({ sections: sectionData }) {
try {
- const markerTypes = sectionData[0];
- const sections = sectionData[1];
+ const markerTypes = sectionData[0]
+ const sections = sectionData[1]
- const post = this.builder.createPost();
+ const post = this.builder.createPost()
- this.markups = [];
- this.markerTypes = this.parseMarkerTypes(markerTypes);
- this.parseSections(sections, post);
+ this.markups = []
+ this.markerTypes = this.parseMarkerTypes(markerTypes)
+ this.parseSections(sections, post)
- return post;
+ return post
} catch (e) {
- assert(`Unable to parse mobiledoc: ${e.message}`, false);
+ assert(`Unable to parse mobiledoc: ${e.message}`, false)
}
}
parseMarkerTypes(markerTypes) {
- return markerTypes.map((markerType) => this.parseMarkerType(markerType));
+ return markerTypes.map(markerType => this.parseMarkerType(markerType))
}
parseMarkerType([tagName, attributesArray]) {
- const attributesObject = kvArrayToObject(attributesArray || []);
- return this.builder.createMarkup(tagName, attributesObject);
+ const attributesObject = kvArrayToObject(attributesArray || [])
+ return this.builder.createMarkup(tagName, attributesObject)
}
parseSections(sections, post) {
- sections.forEach((section) => this.parseSection(section, post));
+ sections.forEach(section => this.parseSection(section, post))
}
parseSection(section, post) {
- let [type] = section;
- switch(type) {
+ let [type] = section
+ switch (type) {
case MOBILEDOC_MARKUP_SECTION_TYPE:
- this.parseMarkupSection(section, post);
- break;
+ this.parseMarkupSection(section, post)
+ break
case MOBILEDOC_IMAGE_SECTION_TYPE:
- this.parseImageSection(section, post);
- break;
+ this.parseImageSection(section, post)
+ break
case MOBILEDOC_CARD_SECTION_TYPE:
- this.parseCardSection(section, post);
- break;
+ this.parseCardSection(section, post)
+ break
case MOBILEDOC_LIST_SECTION_TYPE:
- this.parseListSection(section, post);
- break;
+ this.parseListSection(section, post)
+ break
default:
- assert(`Unexpected section type ${type}`, false);
+ assert(`Unexpected section type ${type}`, false)
}
}
parseCardSection([, name, payload], post) {
- const section = this.builder.createCardSection(name, payload);
- post.sections.append(section);
+ const section = this.builder.createCardSection(name, payload)
+ post.sections.append(section)
}
parseImageSection([, src], post) {
- const section = this.builder.createImageSection(src);
- post.sections.append(section);
+ const section = this.builder.createImageSection(src)
+ post.sections.append(section)
}
parseMarkupSection([, tagName, markers], post) {
- const section = this.builder.createMarkupSection(tagName.toLowerCase() === 'pull-quote' ? 'aside' : tagName);
- post.sections.append(section);
- this.parseMarkers(markers, section);
+ const section = this.builder.createMarkupSection(tagName.toLowerCase() === 'pull-quote' ? 'aside' : tagName)
+ post.sections.append(section)
+ this.parseMarkers(markers, section)
// Strip blank markers after they have been created. This ensures any
// markup they include has been correctly populated.
filter(section.markers, m => m.isBlank).forEach(m => {
- section.markers.remove(m);
- });
+ section.markers.remove(m)
+ })
}
parseListSection([, tagName, items], post) {
- const section = this.builder.createListSection(tagName);
- post.sections.append(section);
- this.parseListItems(items, section);
+ const section = this.builder.createListSection(tagName)
+ post.sections.append(section)
+ this.parseListItems(items, section)
}
parseListItems(items, section) {
- items.forEach(i => this.parseListItem(i, section));
+ items.forEach(i => this.parseListItem(i, section))
}
parseListItem(markers, section) {
- const item = this.builder.createListItem();
- this.parseMarkers(markers, item);
- section.items.append(item);
+ const item = this.builder.createListItem()
+ this.parseMarkers(markers, item)
+ section.items.append(item)
}
parseMarkers(markers, parent) {
- markers.forEach(m => this.parseMarker(m, parent));
+ markers.forEach(m => this.parseMarker(m, parent))
}
parseMarker([markerTypeIndexes, closeCount, value], parent) {
markerTypeIndexes.forEach(index => {
- this.markups.push(this.markerTypes[index]);
- });
- const marker = this.builder.createMarker(value, this.markups.slice());
- parent.markers.append(marker);
- this.markups = this.markups.slice(0, this.markups.length-closeCount);
+ this.markups.push(this.markerTypes[index])
+ })
+ const marker = this.builder.createMarker(value, this.markups.slice())
+ parent.markers.append(marker)
+ this.markups = this.markups.slice(0, this.markups.length - closeCount)
}
}
diff --git a/src/js/parsers/mobiledoc/0-3-1.js b/src/js/parsers/mobiledoc/0-3-1.js
index 398cfa0fb..80c810767 100644
--- a/src/js/parsers/mobiledoc/0-3-1.js
+++ b/src/js/parsers/mobiledoc/0-3-1.js
@@ -4,17 +4,17 @@ import {
MOBILEDOC_LIST_SECTION_TYPE,
MOBILEDOC_CARD_SECTION_TYPE,
MOBILEDOC_MARKUP_MARKER_TYPE,
- MOBILEDOC_ATOM_MARKER_TYPE
-} from 'mobiledoc-kit/renderers/mobiledoc/0-3-1';
-import { kvArrayToObject, filter } from "../../utils/array-utils";
-import assert from 'mobiledoc-kit/utils/assert';
+ MOBILEDOC_ATOM_MARKER_TYPE,
+} from 'mobiledoc-kit/renderers/mobiledoc/0-3-1'
+import { kvArrayToObject, filter } from '../../utils/array-utils'
+import assert from 'mobiledoc-kit/utils/assert'
/*
* Parses from mobiledoc -> post
*/
export default class MobiledocParser {
constructor(builder) {
- this.builder = builder;
+ this.builder = builder
}
/**
@@ -23,144 +23,144 @@ export default class MobiledocParser {
*/
parse({ sections, markups: markerTypes, cards: cardTypes, atoms: atomTypes }) {
try {
- const post = this.builder.createPost();
+ const post = this.builder.createPost()
- this.markups = [];
- this.markerTypes = this.parseMarkerTypes(markerTypes);
- this.cardTypes = this.parseCardTypes(cardTypes);
- this.atomTypes = this.parseAtomTypes(atomTypes);
- this.parseSections(sections, post);
+ this.markups = []
+ this.markerTypes = this.parseMarkerTypes(markerTypes)
+ this.cardTypes = this.parseCardTypes(cardTypes)
+ this.atomTypes = this.parseAtomTypes(atomTypes)
+ this.parseSections(sections, post)
- return post;
+ return post
} catch (e) {
- assert(`Unable to parse mobiledoc: ${e.message}`, false);
+ assert(`Unable to parse mobiledoc: ${e.message}`, false)
}
}
parseMarkerTypes(markerTypes) {
- return markerTypes.map((markerType) => this.parseMarkerType(markerType));
+ return markerTypes.map(markerType => this.parseMarkerType(markerType))
}
parseMarkerType([tagName, attributesArray]) {
- const attributesObject = kvArrayToObject(attributesArray || []);
- return this.builder.createMarkup(tagName, attributesObject);
+ const attributesObject = kvArrayToObject(attributesArray || [])
+ return this.builder.createMarkup(tagName, attributesObject)
}
parseCardTypes(cardTypes) {
- return cardTypes.map((cardType) => this.parseCardType(cardType));
+ return cardTypes.map(cardType => this.parseCardType(cardType))
}
parseCardType([cardName, cardPayload]) {
- return [cardName, cardPayload];
+ return [cardName, cardPayload]
}
parseAtomTypes(atomTypes) {
- return atomTypes.map((atomType) => this.parseAtomType(atomType));
+ return atomTypes.map(atomType => this.parseAtomType(atomType))
}
parseAtomType([atomName, atomValue, atomPayload]) {
- return [atomName, atomValue, atomPayload];
+ return [atomName, atomValue, atomPayload]
}
parseSections(sections, post) {
- sections.forEach((section) => this.parseSection(section, post));
+ sections.forEach(section => this.parseSection(section, post))
}
parseSection(section, post) {
- let [type] = section;
- switch(type) {
+ let [type] = section
+ switch (type) {
case MOBILEDOC_MARKUP_SECTION_TYPE:
- this.parseMarkupSection(section, post);
- break;
+ this.parseMarkupSection(section, post)
+ break
case MOBILEDOC_IMAGE_SECTION_TYPE:
- this.parseImageSection(section, post);
- break;
+ this.parseImageSection(section, post)
+ break
case MOBILEDOC_CARD_SECTION_TYPE:
- this.parseCardSection(section, post);
- break;
+ this.parseCardSection(section, post)
+ break
case MOBILEDOC_LIST_SECTION_TYPE:
- this.parseListSection(section, post);
- break;
+ this.parseListSection(section, post)
+ break
default:
- assert('Unexpected section type ${type}', false);
+ assert('Unexpected section type ${type}', false)
}
}
getAtomTypeFromIndex(index) {
- const atomType = this.atomTypes[index];
- assert(`No atom definition found at index ${index}`, !!atomType);
- return atomType;
+ const atomType = this.atomTypes[index]
+ assert(`No atom definition found at index ${index}`, !!atomType)
+ return atomType
}
getCardTypeFromIndex(index) {
- const cardType = this.cardTypes[index];
- assert(`No card definition found at index ${index}`, !!cardType);
- return cardType;
+ const cardType = this.cardTypes[index]
+ assert(`No card definition found at index ${index}`, !!cardType)
+ return cardType
}
parseCardSection([, cardIndex], post) {
- const [name, payload] = this.getCardTypeFromIndex(cardIndex);
- const section = this.builder.createCardSection(name, payload);
- post.sections.append(section);
+ const [name, payload] = this.getCardTypeFromIndex(cardIndex)
+ const section = this.builder.createCardSection(name, payload)
+ post.sections.append(section)
}
parseImageSection([, src], post) {
- const section = this.builder.createImageSection(src);
- post.sections.append(section);
+ const section = this.builder.createImageSection(src)
+ post.sections.append(section)
}
parseMarkupSection([, tagName, markers], post) {
- const section = this.builder.createMarkupSection(tagName);
- post.sections.append(section);
- this.parseMarkers(markers, section);
+ const section = this.builder.createMarkupSection(tagName)
+ post.sections.append(section)
+ this.parseMarkers(markers, section)
// Strip blank markers after they have been created. This ensures any
// markup they include has been correctly populated.
filter(section.markers, m => m.isBlank).forEach(m => {
- section.markers.remove(m);
- });
+ section.markers.remove(m)
+ })
}
parseListSection([, tagName, items], post) {
- const section = this.builder.createListSection(tagName);
- post.sections.append(section);
- this.parseListItems(items, section);
+ const section = this.builder.createListSection(tagName)
+ post.sections.append(section)
+ this.parseListItems(items, section)
}
parseListItems(items, section) {
- items.forEach(i => this.parseListItem(i, section));
+ items.forEach(i => this.parseListItem(i, section))
}
parseListItem(markers, section) {
- const item = this.builder.createListItem();
- this.parseMarkers(markers, item);
- section.items.append(item);
+ const item = this.builder.createListItem()
+ this.parseMarkers(markers, item)
+ section.items.append(item)
}
parseMarkers(markers, parent) {
- markers.forEach(m => this.parseMarker(m, parent));
+ markers.forEach(m => this.parseMarker(m, parent))
}
parseMarker([type, markerTypeIndexes, closeCount, value], parent) {
markerTypeIndexes.forEach(index => {
- this.markups.push(this.markerTypes[index]);
- });
+ this.markups.push(this.markerTypes[index])
+ })
- const marker = this.buildMarkerType(type, value);
- parent.markers.append(marker);
+ const marker = this.buildMarkerType(type, value)
+ parent.markers.append(marker)
- this.markups = this.markups.slice(0, this.markups.length-closeCount);
+ this.markups = this.markups.slice(0, this.markups.length - closeCount)
}
buildMarkerType(type, value) {
switch (type) {
case MOBILEDOC_MARKUP_MARKER_TYPE:
- return this.builder.createMarker(value, this.markups.slice());
+ return this.builder.createMarker(value, this.markups.slice())
case MOBILEDOC_ATOM_MARKER_TYPE: {
- const [atomName, atomValue, atomPayload] = this.getAtomTypeFromIndex(value);
- return this.builder.createAtom(atomName, atomValue, atomPayload, this.markups.slice());
+ const [atomName, atomValue, atomPayload] = this.getAtomTypeFromIndex(value)
+ return this.builder.createAtom(atomName, atomValue, atomPayload, this.markups.slice())
}
default:
- assert(`Unexpected marker type ${type}`, false);
+ assert(`Unexpected marker type ${type}`, false)
}
}
}
diff --git a/src/js/parsers/mobiledoc/0-3-2.js b/src/js/parsers/mobiledoc/0-3-2.js
index 7f9c65344..1b5d6e74d 100644
--- a/src/js/parsers/mobiledoc/0-3-2.js
+++ b/src/js/parsers/mobiledoc/0-3-2.js
@@ -4,19 +4,19 @@ import {
MOBILEDOC_LIST_SECTION_TYPE,
MOBILEDOC_CARD_SECTION_TYPE,
MOBILEDOC_MARKUP_MARKER_TYPE,
- MOBILEDOC_ATOM_MARKER_TYPE
-} from '../../renderers/mobiledoc/0-3-2';
+ MOBILEDOC_ATOM_MARKER_TYPE,
+} from '../../renderers/mobiledoc/0-3-2'
-import { kvArrayToObject, filter } from '../../utils/array-utils';
-import assert from '../../utils/assert';
-import { entries } from '../../utils/object-utils';
+import { kvArrayToObject, filter } from '../../utils/array-utils'
+import assert from '../../utils/assert'
+import { entries } from '../../utils/object-utils'
/*
* Parses from mobiledoc -> post
*/
export default class MobiledocParser {
constructor(builder) {
- this.builder = builder;
+ this.builder = builder
}
/**
@@ -25,154 +25,154 @@ export default class MobiledocParser {
*/
parse({ sections, markups: markerTypes, cards: cardTypes, atoms: atomTypes }) {
try {
- const post = this.builder.createPost();
+ const post = this.builder.createPost()
- this.markups = [];
- this.markerTypes = this.parseMarkerTypes(markerTypes);
- this.cardTypes = this.parseCardTypes(cardTypes);
- this.atomTypes = this.parseAtomTypes(atomTypes);
- this.parseSections(sections, post);
+ this.markups = []
+ this.markerTypes = this.parseMarkerTypes(markerTypes)
+ this.cardTypes = this.parseCardTypes(cardTypes)
+ this.atomTypes = this.parseAtomTypes(atomTypes)
+ this.parseSections(sections, post)
- return post;
+ return post
} catch (e) {
- assert(`Unable to parse mobiledoc: ${e.message}`, false);
+ assert(`Unable to parse mobiledoc: ${e.message}`, false)
}
}
parseMarkerTypes(markerTypes) {
- return markerTypes.map((markerType) => this.parseMarkerType(markerType));
+ return markerTypes.map(markerType => this.parseMarkerType(markerType))
}
parseMarkerType([tagName, attributesArray]) {
- const attributesObject = kvArrayToObject(attributesArray || []);
- return this.builder.createMarkup(tagName, attributesObject);
+ const attributesObject = kvArrayToObject(attributesArray || [])
+ return this.builder.createMarkup(tagName, attributesObject)
}
parseCardTypes(cardTypes) {
- return cardTypes.map((cardType) => this.parseCardType(cardType));
+ return cardTypes.map(cardType => this.parseCardType(cardType))
}
parseCardType([cardName, cardPayload]) {
- return [cardName, cardPayload];
+ return [cardName, cardPayload]
}
parseAtomTypes(atomTypes) {
- return atomTypes.map((atomType) => this.parseAtomType(atomType));
+ return atomTypes.map(atomType => this.parseAtomType(atomType))
}
parseAtomType([atomName, atomValue, atomPayload]) {
- return [atomName, atomValue, atomPayload];
+ return [atomName, atomValue, atomPayload]
}
parseSections(sections, post) {
- sections.forEach((section) => this.parseSection(section, post));
+ sections.forEach(section => this.parseSection(section, post))
}
parseSection(section, post) {
- let [type] = section;
- switch(type) {
+ let [type] = section
+ switch (type) {
case MOBILEDOC_MARKUP_SECTION_TYPE:
- this.parseMarkupSection(section, post);
- break;
+ this.parseMarkupSection(section, post)
+ break
case MOBILEDOC_IMAGE_SECTION_TYPE:
- this.parseImageSection(section, post);
- break;
+ this.parseImageSection(section, post)
+ break
case MOBILEDOC_CARD_SECTION_TYPE:
- this.parseCardSection(section, post);
- break;
+ this.parseCardSection(section, post)
+ break
case MOBILEDOC_LIST_SECTION_TYPE:
- this.parseListSection(section, post);
- break;
+ this.parseListSection(section, post)
+ break
default:
- assert('Unexpected section type ${type}', false);
+ assert('Unexpected section type ${type}', false)
}
}
getAtomTypeFromIndex(index) {
- const atomType = this.atomTypes[index];
- assert(`No atom definition found at index ${index}`, !!atomType);
- return atomType;
+ const atomType = this.atomTypes[index]
+ assert(`No atom definition found at index ${index}`, !!atomType)
+ return atomType
}
getCardTypeFromIndex(index) {
- const cardType = this.cardTypes[index];
- assert(`No card definition found at index ${index}`, !!cardType);
- return cardType;
+ const cardType = this.cardTypes[index]
+ assert(`No card definition found at index ${index}`, !!cardType)
+ return cardType
}
parseCardSection([, cardIndex], post) {
- const [name, payload] = this.getCardTypeFromIndex(cardIndex);
- const section = this.builder.createCardSection(name, payload);
- post.sections.append(section);
+ const [name, payload] = this.getCardTypeFromIndex(cardIndex)
+ const section = this.builder.createCardSection(name, payload)
+ post.sections.append(section)
}
parseImageSection([, src], post) {
- const section = this.builder.createImageSection(src);
- post.sections.append(section);
+ const section = this.builder.createImageSection(src)
+ post.sections.append(section)
}
parseMarkupSection([, tagName, markers, attributesArray], post) {
- const section = this.builder.createMarkupSection(tagName);
- post.sections.append(section);
+ const section = this.builder.createMarkupSection(tagName)
+ post.sections.append(section)
if (attributesArray) {
entries(kvArrayToObject(attributesArray)).forEach(([key, value]) => {
- section.setAttribute(key, value);
- });
+ section.setAttribute(key, value)
+ })
}
- this.parseMarkers(markers, section);
+ this.parseMarkers(markers, section)
// Strip blank markers after they have been created. This ensures any
// markup they include has been correctly populated.
filter(section.markers, m => m.isBlank).forEach(m => {
- section.markers.remove(m);
- });
+ section.markers.remove(m)
+ })
}
parseListSection([, tagName, items, attributesArray], post) {
- const section = this.builder.createListSection(tagName);
- post.sections.append(section);
+ const section = this.builder.createListSection(tagName)
+ post.sections.append(section)
if (attributesArray) {
entries(kvArrayToObject(attributesArray)).forEach(([key, value]) => {
- section.setAttribute(key, value);
- });
+ section.setAttribute(key, value)
+ })
}
- this.parseListItems(items, section);
+ this.parseListItems(items, section)
}
parseListItems(items, section) {
- items.forEach(i => this.parseListItem(i, section));
+ items.forEach(i => this.parseListItem(i, section))
}
parseListItem(markers, section) {
- const item = this.builder.createListItem();
- this.parseMarkers(markers, item);
- section.items.append(item);
+ const item = this.builder.createListItem()
+ this.parseMarkers(markers, item)
+ section.items.append(item)
}
parseMarkers(markers, parent) {
- markers.forEach(m => this.parseMarker(m, parent));
+ markers.forEach(m => this.parseMarker(m, parent))
}
parseMarker([type, markerTypeIndexes, closeCount, value], parent) {
markerTypeIndexes.forEach(index => {
- this.markups.push(this.markerTypes[index]);
- });
+ this.markups.push(this.markerTypes[index])
+ })
- const marker = this.buildMarkerType(type, value);
- parent.markers.append(marker);
+ const marker = this.buildMarkerType(type, value)
+ parent.markers.append(marker)
- this.markups = this.markups.slice(0, this.markups.length-closeCount);
+ this.markups = this.markups.slice(0, this.markups.length - closeCount)
}
buildMarkerType(type, value) {
switch (type) {
case MOBILEDOC_MARKUP_MARKER_TYPE:
- return this.builder.createMarker(value, this.markups.slice());
+ return this.builder.createMarker(value, this.markups.slice())
case MOBILEDOC_ATOM_MARKER_TYPE: {
- const [atomName, atomValue, atomPayload] = this.getAtomTypeFromIndex(value);
- return this.builder.createAtom(atomName, atomValue, atomPayload, this.markups.slice());
+ const [atomName, atomValue, atomPayload] = this.getAtomTypeFromIndex(value)
+ return this.builder.createAtom(atomName, atomValue, atomPayload, this.markups.slice())
}
default:
- assert(`Unexpected marker type ${type}`, false);
+ assert(`Unexpected marker type ${type}`, false)
}
}
}
diff --git a/src/js/parsers/mobiledoc/0-3.js b/src/js/parsers/mobiledoc/0-3.js
index 00addadfd..03b6f00c1 100644
--- a/src/js/parsers/mobiledoc/0-3.js
+++ b/src/js/parsers/mobiledoc/0-3.js
@@ -4,17 +4,17 @@ import {
MOBILEDOC_LIST_SECTION_TYPE,
MOBILEDOC_CARD_SECTION_TYPE,
MOBILEDOC_MARKUP_MARKER_TYPE,
- MOBILEDOC_ATOM_MARKER_TYPE
-} from 'mobiledoc-kit/renderers/mobiledoc/0-3';
-import { kvArrayToObject, filter } from "../../utils/array-utils";
-import assert from 'mobiledoc-kit/utils/assert';
+ MOBILEDOC_ATOM_MARKER_TYPE,
+} from 'mobiledoc-kit/renderers/mobiledoc/0-3'
+import { kvArrayToObject, filter } from '../../utils/array-utils'
+import assert from 'mobiledoc-kit/utils/assert'
/*
* Parses from mobiledoc -> post
*/
export default class MobiledocParser {
constructor(builder) {
- this.builder = builder;
+ this.builder = builder
}
/**
@@ -23,144 +23,144 @@ export default class MobiledocParser {
*/
parse({ sections, markups: markerTypes, cards: cardTypes, atoms: atomTypes }) {
try {
- const post = this.builder.createPost();
+ const post = this.builder.createPost()
- this.markups = [];
- this.markerTypes = this.parseMarkerTypes(markerTypes);
- this.cardTypes = this.parseCardTypes(cardTypes);
- this.atomTypes = this.parseAtomTypes(atomTypes);
- this.parseSections(sections, post);
+ this.markups = []
+ this.markerTypes = this.parseMarkerTypes(markerTypes)
+ this.cardTypes = this.parseCardTypes(cardTypes)
+ this.atomTypes = this.parseAtomTypes(atomTypes)
+ this.parseSections(sections, post)
- return post;
+ return post
} catch (e) {
- assert(`Unable to parse mobiledoc: ${e.message}`, false);
+ assert(`Unable to parse mobiledoc: ${e.message}`, false)
}
}
parseMarkerTypes(markerTypes) {
- return markerTypes.map((markerType) => this.parseMarkerType(markerType));
+ return markerTypes.map(markerType => this.parseMarkerType(markerType))
}
parseMarkerType([tagName, attributesArray]) {
- const attributesObject = kvArrayToObject(attributesArray || []);
- return this.builder.createMarkup(tagName, attributesObject);
+ const attributesObject = kvArrayToObject(attributesArray || [])
+ return this.builder.createMarkup(tagName, attributesObject)
}
parseCardTypes(cardTypes) {
- return cardTypes.map((cardType) => this.parseCardType(cardType));
+ return cardTypes.map(cardType => this.parseCardType(cardType))
}
parseCardType([cardName, cardPayload]) {
- return [cardName, cardPayload];
+ return [cardName, cardPayload]
}
parseAtomTypes(atomTypes) {
- return atomTypes.map((atomType) => this.parseAtomType(atomType));
+ return atomTypes.map(atomType => this.parseAtomType(atomType))
}
parseAtomType([atomName, atomValue, atomPayload]) {
- return [atomName, atomValue, atomPayload];
+ return [atomName, atomValue, atomPayload]
}
parseSections(sections, post) {
- sections.forEach((section) => this.parseSection(section, post));
+ sections.forEach(section => this.parseSection(section, post))
}
parseSection(section, post) {
- let [type] = section;
- switch(type) {
+ let [type] = section
+ switch (type) {
case MOBILEDOC_MARKUP_SECTION_TYPE:
- this.parseMarkupSection(section, post);
- break;
+ this.parseMarkupSection(section, post)
+ break
case MOBILEDOC_IMAGE_SECTION_TYPE:
- this.parseImageSection(section, post);
- break;
+ this.parseImageSection(section, post)
+ break
case MOBILEDOC_CARD_SECTION_TYPE:
- this.parseCardSection(section, post);
- break;
+ this.parseCardSection(section, post)
+ break
case MOBILEDOC_LIST_SECTION_TYPE:
- this.parseListSection(section, post);
- break;
+ this.parseListSection(section, post)
+ break
default:
- assert('Unexpected section type ${type}', false);
+ assert('Unexpected section type ${type}', false)
}
}
getAtomTypeFromIndex(index) {
- const atomType = this.atomTypes[index];
- assert(`No atom definition found at index ${index}`, !!atomType);
- return atomType;
+ const atomType = this.atomTypes[index]
+ assert(`No atom definition found at index ${index}`, !!atomType)
+ return atomType
}
getCardTypeFromIndex(index) {
- const cardType = this.cardTypes[index];
- assert(`No card definition found at index ${index}`, !!cardType);
- return cardType;
+ const cardType = this.cardTypes[index]
+ assert(`No card definition found at index ${index}`, !!cardType)
+ return cardType
}
parseCardSection([, cardIndex], post) {
- const [name, payload] = this.getCardTypeFromIndex(cardIndex);
- const section = this.builder.createCardSection(name, payload);
- post.sections.append(section);
+ const [name, payload] = this.getCardTypeFromIndex(cardIndex)
+ const section = this.builder.createCardSection(name, payload)
+ post.sections.append(section)
}
parseImageSection([, src], post) {
- const section = this.builder.createImageSection(src);
- post.sections.append(section);
+ const section = this.builder.createImageSection(src)
+ post.sections.append(section)
}
parseMarkupSection([, tagName, markers], post) {
- const section = this.builder.createMarkupSection(tagName.toLowerCase() === 'pull-quote' ? 'aside' : tagName);
- post.sections.append(section);
- this.parseMarkers(markers, section);
+ const section = this.builder.createMarkupSection(tagName.toLowerCase() === 'pull-quote' ? 'aside' : tagName)
+ post.sections.append(section)
+ this.parseMarkers(markers, section)
// Strip blank markers after they have been created. This ensures any
// markup they include has been correctly populated.
filter(section.markers, m => m.isBlank).forEach(m => {
- section.markers.remove(m);
- });
+ section.markers.remove(m)
+ })
}
parseListSection([, tagName, items], post) {
- const section = this.builder.createListSection(tagName);
- post.sections.append(section);
- this.parseListItems(items, section);
+ const section = this.builder.createListSection(tagName)
+ post.sections.append(section)
+ this.parseListItems(items, section)
}
parseListItems(items, section) {
- items.forEach(i => this.parseListItem(i, section));
+ items.forEach(i => this.parseListItem(i, section))
}
parseListItem(markers, section) {
- const item = this.builder.createListItem();
- this.parseMarkers(markers, item);
- section.items.append(item);
+ const item = this.builder.createListItem()
+ this.parseMarkers(markers, item)
+ section.items.append(item)
}
parseMarkers(markers, parent) {
- markers.forEach(m => this.parseMarker(m, parent));
+ markers.forEach(m => this.parseMarker(m, parent))
}
parseMarker([type, markerTypeIndexes, closeCount, value], parent) {
markerTypeIndexes.forEach(index => {
- this.markups.push(this.markerTypes[index]);
- });
+ this.markups.push(this.markerTypes[index])
+ })
- const marker = this.buildMarkerType(type, value);
- parent.markers.append(marker);
+ const marker = this.buildMarkerType(type, value)
+ parent.markers.append(marker)
- this.markups = this.markups.slice(0, this.markups.length-closeCount);
+ this.markups = this.markups.slice(0, this.markups.length - closeCount)
}
buildMarkerType(type, value) {
switch (type) {
case MOBILEDOC_MARKUP_MARKER_TYPE:
- return this.builder.createMarker(value, this.markups.slice());
+ return this.builder.createMarker(value, this.markups.slice())
case MOBILEDOC_ATOM_MARKER_TYPE: {
- const [atomName, atomValue, atomPayload] = this.getAtomTypeFromIndex(value);
- return this.builder.createAtom(atomName, atomValue, atomPayload, this.markups.slice());
+ const [atomName, atomValue, atomPayload] = this.getAtomTypeFromIndex(value)
+ return this.builder.createAtom(atomName, atomValue, atomPayload, this.markups.slice())
}
default:
- assert(`Unexpected marker type ${type}`, false);
+ assert(`Unexpected marker type ${type}`, false)
}
}
}
diff --git a/src/js/parsers/mobiledoc/index.js b/src/js/parsers/mobiledoc/index.js
index 5c111ca72..50194df92 100644
--- a/src/js/parsers/mobiledoc/index.js
+++ b/src/js/parsers/mobiledoc/index.js
@@ -1,33 +1,32 @@
-import MobiledocParser_0_2 from './0-2';
-import MobiledocParser_0_3 from './0-3';
-import MobiledocParser_0_3_1 from './0-3-1';
-import MobiledocParser_0_3_2 from './0-3-2';
+import MobiledocParser_0_2 from './0-2'
+import MobiledocParser_0_3 from './0-3'
+import MobiledocParser_0_3_1 from './0-3-1'
+import MobiledocParser_0_3_2 from './0-3-2'
-import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_2 } from 'mobiledoc-kit/renderers/mobiledoc/0-2';
-import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3 } from 'mobiledoc-kit/renderers/mobiledoc/0-3';
-import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_1 } from 'mobiledoc-kit/renderers/mobiledoc/0-3-1';
-import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_2 } from 'mobiledoc-kit/renderers/mobiledoc/0-3-2';
-import assert from 'mobiledoc-kit/utils/assert';
+import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_2 } from 'mobiledoc-kit/renderers/mobiledoc/0-2'
+import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3 } from 'mobiledoc-kit/renderers/mobiledoc/0-3'
+import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_1 } from 'mobiledoc-kit/renderers/mobiledoc/0-3-1'
+import { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_2 } from 'mobiledoc-kit/renderers/mobiledoc/0-3-2'
+import assert from 'mobiledoc-kit/utils/assert'
function parseVersion(mobiledoc) {
- return mobiledoc.version;
+ return mobiledoc.version
}
export default {
parse(builder, mobiledoc) {
- let version = parseVersion(mobiledoc);
+ let version = parseVersion(mobiledoc)
switch (version) {
case MOBILEDOC_VERSION_0_2:
- return new MobiledocParser_0_2(builder).parse(mobiledoc);
+ return new MobiledocParser_0_2(builder).parse(mobiledoc)
case MOBILEDOC_VERSION_0_3:
- return new MobiledocParser_0_3(builder).parse(mobiledoc);
+ return new MobiledocParser_0_3(builder).parse(mobiledoc)
case MOBILEDOC_VERSION_0_3_1:
- return new MobiledocParser_0_3_1(builder).parse(mobiledoc);
+ return new MobiledocParser_0_3_1(builder).parse(mobiledoc)
case MOBILEDOC_VERSION_0_3_2:
- return new MobiledocParser_0_3_2(builder).parse(mobiledoc);
+ return new MobiledocParser_0_3_2(builder).parse(mobiledoc)
default:
- assert(`Unknown version of mobiledoc parser requested: ${version}`,
- false);
+ assert(`Unknown version of mobiledoc parser requested: ${version}`, false)
}
- }
-};
+ },
+}
diff --git a/src/js/parsers/section.js b/src/js/parsers/section.js
index 93d6fcc29..3a1c70f0b 100644
--- a/src/js/parsers/section.js
+++ b/src/js/parsers/section.js
@@ -1,54 +1,26 @@
-import {
- DEFAULT_TAG_NAME,
- VALID_MARKUP_SECTION_TAGNAMES
-} from 'mobiledoc-kit/models/markup-section';
-
-import {
- VALID_LIST_SECTION_TAGNAMES
-} from 'mobiledoc-kit/models/list-section';
-
-import {
- VALID_LIST_ITEM_TAGNAMES
-} from 'mobiledoc-kit/models/list-item';
-
-import {
- LIST_SECTION_TYPE,
- LIST_ITEM_TYPE,
- MARKUP_SECTION_TYPE
-} from 'mobiledoc-kit/models/types';
-
-import {
- VALID_MARKUP_TAGNAMES
-} from 'mobiledoc-kit/models/markup';
-
-import {
- getAttributes,
- normalizeTagName,
- isTextNode,
- isCommentNode,
- NODE_TYPES
-} from 'mobiledoc-kit/utils/dom-utils';
-
-import {
- any,
- forEach,
- contains
-} from 'mobiledoc-kit/utils/array-utils';
-
-import {
- transformHTMLText,
- trimSectionText
-} from '../parsers/dom';
-
-import assert from '../utils/assert';
-
-const SKIPPABLE_ELEMENT_TAG_NAMES = [
- 'style', 'head', 'title', 'meta'
-].map(normalizeTagName);
-
-const NEWLINES = /\s*\n\s*/g;
+import { DEFAULT_TAG_NAME, VALID_MARKUP_SECTION_TAGNAMES } from 'mobiledoc-kit/models/markup-section'
+
+import { VALID_LIST_SECTION_TAGNAMES } from 'mobiledoc-kit/models/list-section'
+
+import { VALID_LIST_ITEM_TAGNAMES } from 'mobiledoc-kit/models/list-item'
+
+import { LIST_SECTION_TYPE, LIST_ITEM_TYPE, MARKUP_SECTION_TYPE } from 'mobiledoc-kit/models/types'
+
+import { VALID_MARKUP_TAGNAMES } from 'mobiledoc-kit/models/markup'
+
+import { getAttributes, normalizeTagName, isTextNode, isCommentNode, NODE_TYPES } from 'mobiledoc-kit/utils/dom-utils'
+
+import { any, forEach, contains } from 'mobiledoc-kit/utils/array-utils'
+
+import { transformHTMLText, trimSectionText } from '../parsers/dom'
+
+import assert from '../utils/assert'
+
+const SKIPPABLE_ELEMENT_TAG_NAMES = ['style', 'head', 'title', 'meta'].map(normalizeTagName)
+
+const NEWLINES = /\s*\n\s*/g
function sanitize(text) {
- return text.replace(NEWLINES, ' ');
+ return text.replace(NEWLINES, ' ')
}
/**
@@ -57,124 +29,124 @@ function sanitize(text) {
* @private
*/
class SectionParser {
- constructor(builder, options={}) {
- this.builder = builder;
- this.plugins = options.plugins || [];
+ constructor(builder, options = {}) {
+ this.builder = builder
+ this.plugins = options.plugins || []
}
parse(element) {
if (this._isSkippable(element)) {
- return [];
+ return []
}
- this.sections = [];
- this.state = {};
+ this.sections = []
+ this.state = {}
- this._updateStateFromElement(element);
+ this._updateStateFromElement(element)
- let finished = false;
+ let finished = false
// top-level text nodes will be run through parseNode later so avoid running
// the node through parserPlugins twice
if (!isTextNode(element)) {
- finished = this.runPlugins(element);
+ finished = this.runPlugins(element)
}
if (!finished) {
- let childNodes = isTextNode(element) ? [element] : element.childNodes;
+ let childNodes = isTextNode(element) ? [element] : element.childNodes
forEach(childNodes, el => {
- this.parseNode(el);
- });
+ this.parseNode(el)
+ })
}
- this._closeCurrentSection();
+ this._closeCurrentSection()
- return this.sections;
+ return this.sections
}
runPlugins(node) {
- let isNodeFinished = false;
+ let isNodeFinished = false
let env = {
- addSection: (section) => {
+ addSection: section => {
// avoid creating empty paragraphs due to wrapper elements around
// parser-plugin-handled elements
if (this.state.section && this.state.section.isMarkerable && !this.state.section.text && !this.state.text) {
- this.state.section = null;
+ this.state.section = null
} else {
- this._closeCurrentSection();
+ this._closeCurrentSection()
}
- this.sections.push(section);
+ this.sections.push(section)
},
- addMarkerable: (marker) => {
- let { state } = this;
- let { section } = state;
+ addMarkerable: marker => {
+ let { state } = this
+ let { section } = state
// if the first element doesn't create it's own state and it's plugin
// handler uses `addMarkerable` we won't have a section yet
if (!section) {
- state.text = '';
- state.section = this.builder.createMarkupSection(normalizeTagName('p'));
- section = state.section;
+ state.text = ''
+ state.section = this.builder.createMarkupSection(normalizeTagName('p'))
+ section = state.section
}
assert(
'Markerables can only be appended to markup sections and list item sections',
section && section.isMarkerable
- );
+ )
if (state.text) {
- this._createMarker();
+ this._createMarker()
}
- section.markers.append(marker);
+ section.markers.append(marker)
},
nodeFinished() {
- isNodeFinished = true;
- }
- };
- for (let i=0; i.
// deals with typical case of Text
Text
if (
@@ -212,99 +180,99 @@ class SectionParser {
tagName === 'p' &&
!node.nextSibling &&
contains(VALID_LIST_ITEM_TAGNAMES, normalizeTagName(node.parentElement.tagName))
- ) {
- this.parseElementNode(node);
- return;
+ ) {
+ this.parseElementNode(node)
+ return
}
// avoid creating empty paragraphs due to wrapper elements around
// section-creating elements
if (this.state.section.isMarkerable && !this.state.text && this.state.section.markers.length === 0) {
- this.state.section = null;
+ this.state.section = null
} else {
- this._closeCurrentSection();
+ this._closeCurrentSection()
}
- this._updateStateFromElement(node);
+ this._updateStateFromElement(node)
}
if (this.state.section.isListSection) {
// ensure the list section is closed and added to the sections list.
// _closeCurrentSection handles pushing list items onto the list section
- this._closeCurrentSection();
+ this._closeCurrentSection()
- forEach(node.childNodes, (node) => {
- this.parseNode(node);
- });
- return;
+ forEach(node.childNodes, node => {
+ this.parseNode(node)
+ })
+ return
}
}
switch (node.nodeType) {
case NODE_TYPES.TEXT:
- this.parseTextNode(node);
- break;
+ this.parseTextNode(node)
+ break
case NODE_TYPES.ELEMENT:
- this.parseElementNode(node);
- break;
+ this.parseElementNode(node)
+ break
}
}
parseElementNode(element) {
- let { state } = this;
+ let { state } = this
- const markups = this._markupsFromElement(element);
+ const markups = this._markupsFromElement(element)
if (markups.length && state.text.length && state.section.isMarkerable) {
- this._createMarker();
+ this._createMarker()
}
- state.markups.push(...markups);
+ state.markups.push(...markups)
- forEach(element.childNodes, (node) => {
- this.parseNode(node);
- });
+ forEach(element.childNodes, node => {
+ this.parseNode(node)
+ })
if (markups.length && state.text.length && state.section.isMarkerable) {
// create the marker started for this node
- this._createMarker();
+ this._createMarker()
}
// pop the current markups from the stack
- state.markups.splice(-markups.length, markups.length);
+ state.markups.splice(-markups.length, markups.length)
}
parseTextNode(textNode) {
- let { state } = this;
- state.text += sanitize(textNode.textContent);
+ let { state } = this
+ state.text += sanitize(textNode.textContent)
}
_updateStateFromElement(element) {
if (isCommentNode(element)) {
- return;
+ return
}
- let { state } = this;
- state.section = this._createSectionFromElement(element);
- state.markups = this._markupsFromElement(element);
- state.text = '';
+ let { state } = this
+ state.section = this._createSectionFromElement(element)
+ state.markups = this._markupsFromElement(element)
+ state.text = ''
}
_closeCurrentSection() {
- let { sections, state } = this;
- let lastSection = sections[sections.length - 1];
+ let { sections, state } = this
+ let lastSection = sections[sections.length - 1]
if (!state.section) {
- return;
+ return
}
// close a trailing text node if it exists
if (state.text.length && state.section.isMarkerable) {
- this._createMarker();
+ this._createMarker()
}
// push listItems onto the listSection or add a new section
if (state.section.isListItem && lastSection && lastSection.isListSection) {
- trimSectionText(state.section);
- lastSection.items.append(state.section);
+ trimSectionText(state.section)
+ lastSection.items.append(state.section)
} else {
// avoid creating empty markup sections, especially useful for indented source
if (
@@ -312,85 +280,83 @@ class SectionParser {
!state.section.text.trim() &&
!any(state.section.markers, marker => marker.isAtom)
) {
- state.section = null;
- state.text = '';
- return;
+ state.section = null
+ state.text = ''
+ return
}
// remove empty list sections before creating a new section
if (lastSection && lastSection.isListSection && lastSection.items.length === 0) {
- sections.pop();
+ sections.pop()
}
- sections.push(state.section);
+ sections.push(state.section)
}
- state.section = null;
- state.text = '';
+ state.section = null
+ state.text = ''
}
_markupsFromElement(element) {
- let { builder } = this;
- let markups = [];
+ let { builder } = this
+ let markups = []
if (isTextNode(element)) {
- return markups;
+ return markups
}
- const tagName = normalizeTagName(element.tagName);
+ const tagName = normalizeTagName(element.tagName)
if (this._isValidMarkupForElement(tagName, element)) {
- markups.push(builder.createMarkup(tagName, getAttributes(element)));
+ markups.push(builder.createMarkup(tagName, getAttributes(element)))
}
- this._markupsFromElementStyle(element).forEach(
- markup => markups.push(markup)
- );
+ this._markupsFromElementStyle(element).forEach(markup => markups.push(markup))
- return markups;
+ return markups
}
_isValidMarkupForElement(tagName, element) {
if (VALID_MARKUP_TAGNAMES.indexOf(tagName) === -1) {
- return false;
+ return false
} else if (tagName === 'b') {
// google docs add a that should not
// create a "b" markup
- return element.style.fontWeight !== 'normal';
+ return element.style.fontWeight !== 'normal'
}
- return true;
+ return true
}
_markupsFromElementStyle(element) {
- let { builder } = this;
- let markups = [];
- let { fontStyle, fontWeight } = element.style;
+ let { builder } = this
+ let markups = []
+ let { fontStyle, fontWeight } = element.style
if (fontStyle === 'italic') {
- markups.push(builder.createMarkup('em'));
+ markups.push(builder.createMarkup('em'))
}
if (fontWeight === 'bold' || fontWeight === '700') {
- markups.push(builder.createMarkup('strong'));
+ markups.push(builder.createMarkup('strong'))
}
- return markups;
+ return markups
}
_createMarker() {
- let { state } = this;
- let text = transformHTMLText(state.text);
- let marker = this.builder.createMarker(text, state.markups);
- state.section.markers.append(marker);
- state.text = '';
+ let { state } = this
+ let text = transformHTMLText(state.text)
+ let marker = this.builder.createMarker(text, state.markups)
+ state.section.markers.append(marker)
+ state.text = ''
}
_getSectionDetails(element) {
let sectionType,
- tagName,
- inferredTagName = false;
+ tagName,
+ inferredTagName = false
if (isTextNode(element)) {
- tagName = DEFAULT_TAG_NAME;
- sectionType = MARKUP_SECTION_TYPE;
- inferredTagName = true;
+ tagName = DEFAULT_TAG_NAME
+ sectionType = MARKUP_SECTION_TYPE
+ inferredTagName = true
} else {
- tagName = normalizeTagName(element.tagName);
+ tagName = normalizeTagName(element.tagName)
// blockquote>p is valid html and should be treated as a blockquote section
// rather than a plain markup section
@@ -399,58 +365,58 @@ class SectionParser {
element.parentElement &&
normalizeTagName(element.parentElement.tagName) === 'blockquote'
) {
- tagName = 'blockquote';
+ tagName = 'blockquote'
}
if (contains(VALID_LIST_SECTION_TAGNAMES, tagName)) {
- sectionType = LIST_SECTION_TYPE;
+ sectionType = LIST_SECTION_TYPE
} else if (contains(VALID_LIST_ITEM_TAGNAMES, tagName)) {
- sectionType = LIST_ITEM_TYPE;
+ sectionType = LIST_ITEM_TYPE
} else if (contains(VALID_MARKUP_SECTION_TAGNAMES, tagName)) {
- sectionType = MARKUP_SECTION_TYPE;
+ sectionType = MARKUP_SECTION_TYPE
} else {
- sectionType = MARKUP_SECTION_TYPE;
- tagName = DEFAULT_TAG_NAME;
- inferredTagName = true;
+ sectionType = MARKUP_SECTION_TYPE
+ tagName = DEFAULT_TAG_NAME
+ inferredTagName = true
}
}
- return {sectionType, tagName, inferredTagName};
+ return { sectionType, tagName, inferredTagName }
}
_createSectionFromElement(element) {
if (isCommentNode(element)) {
- return;
+ return
}
- let { builder } = this;
- let section;
- let {tagName, sectionType, inferredTagName} =
- this._getSectionDetails(element);
+ let { builder } = this
+ let section
+ let { tagName, sectionType, inferredTagName } = this._getSectionDetails(element)
switch (sectionType) {
case LIST_SECTION_TYPE:
- section = builder.createListSection(tagName);
- break;
+ section = builder.createListSection(tagName)
+ break
case LIST_ITEM_TYPE:
- section = builder.createListItem();
- break;
+ section = builder.createListItem()
+ break
case MARKUP_SECTION_TYPE:
- section = builder.createMarkupSection(tagName);
- section._inferredTagName = inferredTagName;
- break;
+ section = builder.createMarkupSection(tagName)
+ section._inferredTagName = inferredTagName
+ break
default:
- assert('Cannot parse section from element', false);
+ assert('Cannot parse section from element', false)
}
- return section;
+ return section
}
_isSkippable(element) {
- return element.nodeType === NODE_TYPES.ELEMENT &&
- contains(SKIPPABLE_ELEMENT_TAG_NAMES,
- normalizeTagName(element.tagName));
+ return (
+ element.nodeType === NODE_TYPES.ELEMENT &&
+ contains(SKIPPABLE_ELEMENT_TAG_NAMES, normalizeTagName(element.tagName))
+ )
}
}
-export default SectionParser;
+export default SectionParser
diff --git a/src/js/parsers/text.js b/src/js/parsers/text.js
index 6c4a9546d..65cbe72ad 100644
--- a/src/js/parsers/text.js
+++ b/src/js/parsers/text.js
@@ -1,33 +1,27 @@
-import assert from 'mobiledoc-kit/utils/assert';
-import {
- MARKUP_SECTION_TYPE,
- LIST_SECTION_TYPE
-} from 'mobiledoc-kit/models/types';
-import {
- DEFAULT_TAG_NAME as DEFAULT_MARKUP_SECTION_TAG_NAME
-} from 'mobiledoc-kit/models/markup-section';
+import assert from 'mobiledoc-kit/utils/assert'
+import { MARKUP_SECTION_TYPE, LIST_SECTION_TYPE } from 'mobiledoc-kit/models/types'
+import { DEFAULT_TAG_NAME as DEFAULT_MARKUP_SECTION_TAG_NAME } from 'mobiledoc-kit/models/markup-section'
-const UL_LI_REGEX = /^\* (.*)$/;
-const OL_LI_REGEX = /^\d\.? (.*)$/;
-const CR = '\r';
-const LF = '\n';
-const CR_REGEX = new RegExp(CR, 'g');
-const CR_LF_REGEX = new RegExp(CR+LF, 'g');
+const UL_LI_REGEX = /^\* (.*)$/
+const OL_LI_REGEX = /^\d\.? (.*)$/
+const CR = '\r'
+const LF = '\n'
+const CR_REGEX = new RegExp(CR, 'g')
+const CR_LF_REGEX = new RegExp(CR + LF, 'g')
-export const SECTION_BREAK = LF;
+export const SECTION_BREAK = LF
function normalizeLineEndings(text) {
- return text.replace(CR_LF_REGEX, LF)
- .replace(CR_REGEX, LF);
+ return text.replace(CR_LF_REGEX, LF).replace(CR_REGEX, LF)
}
export default class TextParser {
constructor(builder, options) {
- this.builder = builder;
- this.options = options;
+ this.builder = builder
+ this.options = options
- this.post = this.builder.createPost();
- this.prevSection = null;
+ this.post = this.builder.createPost()
+ this.prevSection = null
}
/**
@@ -35,62 +29,63 @@ export default class TextParser {
* @return {Post} a post abstract
*/
parse(text) {
- text = normalizeLineEndings(text);
+ text = normalizeLineEndings(text)
text.split(SECTION_BREAK).forEach(text => {
- let section = this._parseSection(text);
- this._appendSection(section);
- });
+ let section = this._parseSection(text)
+ this._appendSection(section)
+ })
- return this.post;
+ return this.post
}
_parseSection(text) {
let tagName = DEFAULT_MARKUP_SECTION_TAG_NAME,
- type = MARKUP_SECTION_TYPE,
- section;
+ type = MARKUP_SECTION_TYPE,
+ section
if (UL_LI_REGEX.test(text)) {
- tagName = 'ul';
- type = LIST_SECTION_TYPE;
- text = text.match(UL_LI_REGEX)[1];
+ tagName = 'ul'
+ type = LIST_SECTION_TYPE
+ text = text.match(UL_LI_REGEX)[1]
} else if (OL_LI_REGEX.test(text)) {
- tagName = 'ol';
- type = LIST_SECTION_TYPE;
- text = text.match(OL_LI_REGEX)[1];
+ tagName = 'ol'
+ type = LIST_SECTION_TYPE
+ text = text.match(OL_LI_REGEX)[1]
}
- let markers = [this.builder.createMarker(text)];
+ let markers = [this.builder.createMarker(text)]
switch (type) {
case LIST_SECTION_TYPE: {
- let item = this.builder.createListItem(markers);
- let list = this.builder.createListSection(tagName, [item]);
- section = list;
- break;
+ let item = this.builder.createListItem(markers)
+ let list = this.builder.createListSection(tagName, [item])
+ section = list
+ break
}
case MARKUP_SECTION_TYPE:
- section = this.builder.createMarkupSection(tagName, markers);
- break;
+ section = this.builder.createMarkupSection(tagName, markers)
+ break
default:
- assert(`Unknown type encountered ${type}`, false);
+ assert(`Unknown type encountered ${type}`, false)
}
- return section;
+ return section
}
_appendSection(section) {
let isSameListSection =
section.isListSection &&
- this.prevSection && this.prevSection.isListSection &&
- this.prevSection.tagName === section.tagName;
+ this.prevSection &&
+ this.prevSection.isListSection &&
+ this.prevSection.tagName === section.tagName
if (isSameListSection) {
section.items.forEach(item => {
- this.prevSection.items.append(item.clone());
- });
+ this.prevSection.items.append(item.clone())
+ })
} else {
- this.post.sections.insertAfter(section, this.prevSection);
- this.prevSection = section;
+ this.post.sections.insertAfter(section, this.prevSection)
+ this.prevSection = section
}
}
}
diff --git a/src/js/renderers/editor-dom.js b/src/js/renderers/editor-dom.js
index 3d4bb83e4..95f001dbf 100644
--- a/src/js/renderers/editor-dom.js
+++ b/src/js/renderers/editor-dom.js
@@ -1,6 +1,6 @@
-import CardNode from 'mobiledoc-kit/models/card-node';
-import { detect, forEach } from 'mobiledoc-kit/utils/array-utils';
-import AtomNode from 'mobiledoc-kit/models/atom-node';
+import CardNode from 'mobiledoc-kit/models/card-node'
+import { detect, forEach } from 'mobiledoc-kit/utils/array-utils'
+import AtomNode from 'mobiledoc-kit/models/atom-node'
import {
POST_TYPE,
MARKUP_SECTION_TYPE,
@@ -9,48 +9,47 @@ import {
MARKER_TYPE,
IMAGE_SECTION_TYPE,
CARD_TYPE,
- ATOM_TYPE
-} from '../models/types';
-import { startsWith, endsWith } from '../utils/string-utils';
-import { addClassName, removeClassName } from '../utils/dom-utils';
-import { MARKUP_SECTION_ELEMENT_NAMES } from '../models/markup-section';
-import assert from '../utils/assert';
-import { TAB } from 'mobiledoc-kit/utils/characters';
-
-export const CARD_ELEMENT_CLASS_NAME = '__mobiledoc-card';
-export const NO_BREAK_SPACE = '\u00A0';
-export const TAB_CHARACTER = '\u2003';
-export const SPACE = ' ';
-export const ZWNJ = '\u200c';
-export const ATOM_CLASS_NAME = '-mobiledoc-kit__atom';
-export const EDITOR_HAS_NO_CONTENT_CLASS_NAME = '__has-no-content';
-export const EDITOR_ELEMENT_CLASS_NAME = '__mobiledoc-editor';
+ ATOM_TYPE,
+} from '../models/types'
+import { startsWith, endsWith } from '../utils/string-utils'
+import { addClassName, removeClassName } from '../utils/dom-utils'
+import { MARKUP_SECTION_ELEMENT_NAMES } from '../models/markup-section'
+import assert from '../utils/assert'
+import { TAB } from 'mobiledoc-kit/utils/characters'
+
+export const CARD_ELEMENT_CLASS_NAME = '__mobiledoc-card'
+export const NO_BREAK_SPACE = '\u00A0'
+export const TAB_CHARACTER = '\u2003'
+export const SPACE = ' '
+export const ZWNJ = '\u200c'
+export const ATOM_CLASS_NAME = '-mobiledoc-kit__atom'
+export const EDITOR_HAS_NO_CONTENT_CLASS_NAME = '__has-no-content'
+export const EDITOR_ELEMENT_CLASS_NAME = '__mobiledoc-editor'
function createElementFromMarkup(doc, markup) {
- let element = doc.createElement(markup.tagName);
+ let element = doc.createElement(markup.tagName)
Object.keys(markup.attributes).forEach(k => {
- element.setAttribute(k, markup.attributes[k]);
- });
- return element;
+ element.setAttribute(k, markup.attributes[k])
+ })
+ return element
}
-const TWO_SPACES = `${SPACE}${SPACE}`;
-const SPACE_AND_NO_BREAK = `${SPACE}${NO_BREAK_SPACE}`;
-const SPACES_REGEX = new RegExp(TWO_SPACES, 'g');
-const TAB_REGEX = new RegExp(TAB, 'g');
-const endsWithSpace = function(text) {
- return endsWith(text, SPACE);
-};
-const startsWithSpace = function(text) {
- return startsWith(text, SPACE);
-};
+const TWO_SPACES = `${SPACE}${SPACE}`
+const SPACE_AND_NO_BREAK = `${SPACE}${NO_BREAK_SPACE}`
+const SPACES_REGEX = new RegExp(TWO_SPACES, 'g')
+const TAB_REGEX = new RegExp(TAB, 'g')
+const endsWithSpace = function (text) {
+ return endsWith(text, SPACE)
+}
+const startsWithSpace = function (text) {
+ return startsWith(text, SPACE)
+}
// FIXME: This can be done more efficiently with a single pass
// building a correct string based on the original.
function renderHTMLText(marker) {
- let text = marker.value;
- text = text.replace(SPACES_REGEX, SPACE_AND_NO_BREAK)
- .replace(TAB_REGEX, TAB_CHARACTER);
+ let text = marker.value
+ text = text.replace(SPACES_REGEX, SPACE_AND_NO_BREAK).replace(TAB_REGEX, TAB_CHARACTER)
// If the first marker has a leading space or the last marker has a
// trailing space, the browser will collapse the space when we position
@@ -58,76 +57,80 @@ function renderHTMLText(marker) {
// See https://github.com/bustle/mobiledoc-kit/issues/68
// and https://github.com/bustle/mobiledoc-kit/issues/75
if (marker.isMarker && endsWithSpace(text) && !marker.next) {
- text = text.substr(0, text.length - 1) + NO_BREAK_SPACE;
+ text = text.substr(0, text.length - 1) + NO_BREAK_SPACE
}
- if (marker.isMarker && startsWithSpace(text) &&
- (!marker.prev || (marker.prev.isMarker && endsWithSpace(marker.prev.value)))) {
- text = NO_BREAK_SPACE + text.substr(1);
+ if (
+ marker.isMarker &&
+ startsWithSpace(text) &&
+ (!marker.prev || (marker.prev.isMarker && endsWithSpace(marker.prev.value)))
+ ) {
+ text = NO_BREAK_SPACE + text.substr(1)
}
- return text;
+ return text
}
// ascends from element upward, returning the last parent node that is not
// parentElement
function penultimateParentOf(element, parentElement) {
- while (parentElement &&
- element.parentNode !== parentElement &&
- element.parentNode !== document.body // ensure the while loop stops
- ) {
- element = element.parentNode;
+ while (
+ parentElement &&
+ element.parentNode !== parentElement &&
+ element.parentNode !== document.body // ensure the while loop stops
+ ) {
+ element = element.parentNode
}
- return element;
+ return element
}
function setSectionAttributesOnElement(section, element) {
section.eachAttribute((key, value) => {
- element.setAttribute(key, value);
- });
+ element.setAttribute(key, value)
+ })
}
function renderMarkupSection(section) {
- let element;
+ let element
if (MARKUP_SECTION_ELEMENT_NAMES.indexOf(section.tagName) !== -1) {
- element = document.createElement(section.tagName);
+ element = document.createElement(section.tagName)
} else {
- element = document.createElement('div');
- addClassName(element, section.tagName);
+ element = document.createElement('div')
+ addClassName(element, section.tagName)
}
- setSectionAttributesOnElement(section, element);
+ setSectionAttributesOnElement(section, element)
- return element;
+ return element
}
function renderListSection(section) {
- let element = document.createElement(section.tagName);
+ let element = document.createElement(section.tagName)
- setSectionAttributesOnElement(section, element);
+ setSectionAttributesOnElement(section, element)
- return element;
+ return element
}
function renderListItem() {
- return document.createElement('li');
+ return document.createElement('li')
}
function renderCursorPlaceholder() {
- return document.createElement('br');
+ return document.createElement('br')
}
function renderInlineCursorPlaceholder() {
- return document.createTextNode(ZWNJ);
+ return document.createTextNode(ZWNJ)
}
function renderCard() {
- let wrapper = document.createElement('div');
- let cardElement = document.createElement('div');
- cardElement.contentEditable = false;
- addClassName(cardElement, CARD_ELEMENT_CLASS_NAME);
- wrapper.appendChild(renderInlineCursorPlaceholder());
- wrapper.appendChild(cardElement);
- wrapper.appendChild(renderInlineCursorPlaceholder());
- return { wrapper, cardElement };
+ let wrapper = document.createElement('div')
+ let cardElement = document.createElement('div')
+ cardElement.contentEditable = false
+ addClassName(cardElement, CARD_ELEMENT_CLASS_NAME)
+ wrapper.appendChild(renderInlineCursorPlaceholder())
+ wrapper.appendChild(cardElement)
+ wrapper.appendChild(renderInlineCursorPlaceholder())
+ return { wrapper, cardElement }
}
/**
@@ -136,65 +139,64 @@ function renderCard() {
* @private
*/
function wrapElement(element, openedMarkups) {
- let wrappedElement = element;
+ let wrappedElement = element
- for (let i=openedMarkups.length - 1; i>=0; i--) {
- let markup = openedMarkups[i];
- let openedElement = createElementFromMarkup(document, markup);
- openedElement.appendChild(wrappedElement);
- wrappedElement = openedElement;
+ for (let i = openedMarkups.length - 1; i >= 0; i--) {
+ let markup = openedMarkups[i]
+ let openedElement = createElementFromMarkup(document, markup)
+ openedElement.appendChild(wrappedElement)
+ wrappedElement = openedElement
}
- return wrappedElement;
+ return wrappedElement
}
// Attach the element to its parent element at the correct position based on the
// previousRenderNode
-function attachElementToParent(element, parentElement, previousRenderNode=null) {
+function attachElementToParent(element, parentElement, previousRenderNode = null) {
if (previousRenderNode) {
- let previousSibling = previousRenderNode.element;
- let previousSiblingPenultimate = penultimateParentOf(previousSibling,
- parentElement);
- parentElement.insertBefore(element, previousSiblingPenultimate.nextSibling);
+ let previousSibling = previousRenderNode.element
+ let previousSiblingPenultimate = penultimateParentOf(previousSibling, parentElement)
+ parentElement.insertBefore(element, previousSiblingPenultimate.nextSibling)
} else {
- parentElement.insertBefore(element, parentElement.firstChild);
+ parentElement.insertBefore(element, parentElement.firstChild)
}
}
function renderAtom(atom, element, previousRenderNode) {
- let atomElement = document.createElement('span');
- atomElement.contentEditable = false;
+ let atomElement = document.createElement('span')
+ atomElement.contentEditable = false
- let wrapper = document.createElement('span');
- addClassName(wrapper, ATOM_CLASS_NAME);
- let headTextNode = renderInlineCursorPlaceholder();
- let tailTextNode = renderInlineCursorPlaceholder();
+ let wrapper = document.createElement('span')
+ addClassName(wrapper, ATOM_CLASS_NAME)
+ let headTextNode = renderInlineCursorPlaceholder()
+ let tailTextNode = renderInlineCursorPlaceholder()
- wrapper.appendChild(headTextNode);
- wrapper.appendChild(atomElement);
- wrapper.appendChild(tailTextNode);
+ wrapper.appendChild(headTextNode)
+ wrapper.appendChild(atomElement)
+ wrapper.appendChild(tailTextNode)
- let wrappedElement = wrapElement(wrapper, atom.openedMarkups);
- attachElementToParent(wrappedElement, element, previousRenderNode);
+ let wrappedElement = wrapElement(wrapper, atom.openedMarkups)
+ attachElementToParent(wrappedElement, element, previousRenderNode)
return {
markupElement: wrappedElement,
wrapper,
atomElement,
headTextNode,
- tailTextNode
- };
+ tailTextNode,
+ }
}
function getNextMarkerElement(renderNode) {
- let element = renderNode.element.parentNode;
- let marker = renderNode.postNode;
- let closedCount = marker.closedMarkups.length;
+ let element = renderNode.element.parentNode
+ let marker = renderNode.postNode
+ let closedCount = marker.closedMarkups.length
while (closedCount--) {
- element = element.parentNode;
+ element = element.parentNode
}
- return element;
+ return element
}
/**
@@ -210,294 +212,272 @@ function getNextMarkerElement(renderNode) {
* @private
*/
function renderMarker(marker, parentElement, previousRenderNode) {
- let text = renderHTMLText(marker);
+ let text = renderHTMLText(marker)
- let element = document.createTextNode(text);
- let markupElement = wrapElement(element, marker.openedMarkups);
- attachElementToParent(markupElement, parentElement, previousRenderNode);
+ let element = document.createTextNode(text)
+ let markupElement = wrapElement(element, marker.openedMarkups)
+ attachElementToParent(markupElement, parentElement, previousRenderNode)
- return { element, markupElement };
+ return { element, markupElement }
}
// Attach the render node's element to the DOM,
// replacing the originalElement if it exists
-function attachRenderNodeElementToDOM(renderNode, originalElement=null) {
- const element = renderNode.element;
- const hasRendered = !!originalElement;
+function attachRenderNodeElementToDOM(renderNode, originalElement = null) {
+ const element = renderNode.element
+ const hasRendered = !!originalElement
if (hasRendered) {
- let parentElement = renderNode.parent.element;
- parentElement.replaceChild(element, originalElement);
+ let parentElement = renderNode.parent.element
+ parentElement.replaceChild(element, originalElement)
} else {
- let parentElement, nextSiblingElement;
+ let parentElement, nextSiblingElement
if (renderNode.prev) {
- let previousElement = renderNode.prev.element;
- parentElement = previousElement.parentNode;
- nextSiblingElement = previousElement.nextSibling;
+ let previousElement = renderNode.prev.element
+ parentElement = previousElement.parentNode
+ nextSiblingElement = previousElement.nextSibling
} else {
- parentElement = renderNode.parent.element;
- nextSiblingElement = parentElement.firstChild;
+ parentElement = renderNode.parent.element
+ nextSiblingElement = parentElement.firstChild
}
- parentElement.insertBefore(element, nextSiblingElement);
+ parentElement.insertBefore(element, nextSiblingElement)
}
}
function removeRenderNodeSectionFromParent(renderNode, section) {
- const parent = renderNode.parent.postNode;
- parent.sections.remove(section);
+ const parent = renderNode.parent.postNode
+ parent.sections.remove(section)
}
function removeRenderNodeElementFromParent(renderNode) {
if (renderNode.element && renderNode.element.parentNode) {
- renderNode.element.parentNode.removeChild(renderNode.element);
+ renderNode.element.parentNode.removeChild(renderNode.element)
}
}
-function validateCards(cards=[]) {
+function validateCards(cards = []) {
forEach(cards, card => {
- assert(
- `Card "${card.name}" must define type "dom", has: "${card.type}"`,
- card.type === 'dom'
- );
- assert(
- `Card "${card.name}" must define \`render\` method`,
- !!card.render
- );
- });
- return cards;
+ assert(`Card "${card.name}" must define type "dom", has: "${card.type}"`, card.type === 'dom')
+ assert(`Card "${card.name}" must define \`render\` method`, !!card.render)
+ })
+ return cards
}
-function validateAtoms(atoms=[]) {
+function validateAtoms(atoms = []) {
forEach(atoms, atom => {
- assert(
- `Atom "${atom.name}" must define type "dom", has: "${atom.type}"`,
- atom.type === 'dom'
- );
- assert(
- `Atom "${atom.name}" must define \`render\` method`,
- !!atom.render
- );
- });
- return atoms;
+ assert(`Atom "${atom.name}" must define type "dom", has: "${atom.type}"`, atom.type === 'dom')
+ assert(`Atom "${atom.name}" must define \`render\` method`, !!atom.render)
+ })
+ return atoms
}
class Visitor {
constructor(editor, cards, atoms, unknownCardHandler, unknownAtomHandler, options) {
- this.editor = editor;
- this.cards = validateCards(cards);
- this.atoms = validateAtoms(atoms);
- this.unknownCardHandler = unknownCardHandler;
- this.unknownAtomHandler = unknownAtomHandler;
- this.options = options;
+ this.editor = editor
+ this.cards = validateCards(cards)
+ this.atoms = validateAtoms(atoms)
+ this.unknownCardHandler = unknownCardHandler
+ this.unknownAtomHandler = unknownAtomHandler
+ this.options = options
}
_findCard(cardName) {
- let card = detect(this.cards, card => card.name === cardName);
- return card || this._createUnknownCard(cardName);
+ let card = detect(this.cards, card => card.name === cardName)
+ return card || this._createUnknownCard(cardName)
}
_createUnknownCard(cardName) {
- assert(
- `Unknown card "${cardName}" found, but no unknownCardHandler is defined`,
- !!this.unknownCardHandler
- );
+ assert(`Unknown card "${cardName}" found, but no unknownCardHandler is defined`, !!this.unknownCardHandler)
return {
name: cardName,
type: 'dom',
render: this.unknownCardHandler,
- edit: this.unknownCardHandler
- };
+ edit: this.unknownCardHandler,
+ }
}
_findAtom(atomName) {
- let atom = detect(this.atoms, atom => atom.name === atomName);
- return atom || this._createUnknownAtom(atomName);
+ let atom = detect(this.atoms, atom => atom.name === atomName)
+ return atom || this._createUnknownAtom(atomName)
}
_createUnknownAtom(atomName) {
- assert(
- `Unknown atom "${atomName}" found, but no unknownAtomHandler is defined`,
- !!this.unknownAtomHandler
- );
+ assert(`Unknown atom "${atomName}" found, but no unknownAtomHandler is defined`, !!this.unknownAtomHandler)
return {
name: atomName,
type: 'dom',
- render: this.unknownAtomHandler
- };
+ render: this.unknownAtomHandler,
+ }
}
[POST_TYPE](renderNode, post, visit) {
if (!renderNode.element) {
- renderNode.element = document.createElement('div');
+ renderNode.element = document.createElement('div')
}
- addClassName(renderNode.element, EDITOR_ELEMENT_CLASS_NAME);
+ addClassName(renderNode.element, EDITOR_ELEMENT_CLASS_NAME)
if (post.hasContent) {
- removeClassName(renderNode.element, EDITOR_HAS_NO_CONTENT_CLASS_NAME);
+ removeClassName(renderNode.element, EDITOR_HAS_NO_CONTENT_CLASS_NAME)
} else {
- addClassName(renderNode.element, EDITOR_HAS_NO_CONTENT_CLASS_NAME);
+ addClassName(renderNode.element, EDITOR_HAS_NO_CONTENT_CLASS_NAME)
}
- visit(renderNode, post.sections);
+ visit(renderNode, post.sections)
}
[MARKUP_SECTION_TYPE](renderNode, section, visit) {
- const originalElement = renderNode.element;
+ const originalElement = renderNode.element
// Always rerender the section -- its tag name or attributes may have changed.
// TODO make this smarter, only rerendering and replacing the element when necessary
- renderNode.element = renderMarkupSection(section);
- renderNode.cursorElement = null;
- attachRenderNodeElementToDOM(renderNode, originalElement);
+ renderNode.element = renderMarkupSection(section)
+ renderNode.cursorElement = null
+ attachRenderNodeElementToDOM(renderNode, originalElement)
if (section.isBlank) {
- let cursorPlaceholder = renderCursorPlaceholder();
- renderNode.element.appendChild(cursorPlaceholder);
- renderNode.cursorElement = cursorPlaceholder;
+ let cursorPlaceholder = renderCursorPlaceholder()
+ renderNode.element.appendChild(cursorPlaceholder)
+ renderNode.cursorElement = cursorPlaceholder
} else {
- const visitAll = true;
- visit(renderNode, section.markers, visitAll);
+ const visitAll = true
+ visit(renderNode, section.markers, visitAll)
}
}
[LIST_SECTION_TYPE](renderNode, section, visit) {
- const originalElement = renderNode.element;
+ const originalElement = renderNode.element
- renderNode.element = renderListSection(section);
- attachRenderNodeElementToDOM(renderNode, originalElement);
+ renderNode.element = renderListSection(section)
+ attachRenderNodeElementToDOM(renderNode, originalElement)
- const visitAll = true;
- visit(renderNode, section.items, visitAll);
+ const visitAll = true
+ visit(renderNode, section.items, visitAll)
}
[LIST_ITEM_TYPE](renderNode, item, visit) {
// FIXME do we need to do anything special for rerenders?
- renderNode.element = renderListItem();
- renderNode.cursorElement = null;
- attachRenderNodeElementToDOM(renderNode, null);
+ renderNode.element = renderListItem()
+ renderNode.cursorElement = null
+ attachRenderNodeElementToDOM(renderNode, null)
if (item.isBlank) {
- let cursorPlaceholder = renderCursorPlaceholder();
- renderNode.element.appendChild(cursorPlaceholder);
- renderNode.cursorElement = cursorPlaceholder;
+ let cursorPlaceholder = renderCursorPlaceholder()
+ renderNode.element.appendChild(cursorPlaceholder)
+ renderNode.cursorElement = cursorPlaceholder
} else {
- const visitAll = true;
- visit(renderNode, item.markers, visitAll);
+ const visitAll = true
+ visit(renderNode, item.markers, visitAll)
}
}
[MARKER_TYPE](renderNode, marker) {
- let parentElement;
+ let parentElement
if (renderNode.prev) {
- parentElement = getNextMarkerElement(renderNode.prev);
+ parentElement = getNextMarkerElement(renderNode.prev)
} else {
- parentElement = renderNode.parent.element;
+ parentElement = renderNode.parent.element
}
- let { element, markupElement } =
- renderMarker(marker, parentElement, renderNode.prev);
+ let { element, markupElement } = renderMarker(marker, parentElement, renderNode.prev)
- renderNode.element = element;
- renderNode.markupElement = markupElement;
+ renderNode.element = element
+ renderNode.markupElement = markupElement
}
[IMAGE_SECTION_TYPE](renderNode, section) {
if (renderNode.element) {
if (renderNode.element.src !== section.src) {
- renderNode.element.src = section.src;
+ renderNode.element.src = section.src
}
} else {
- let element = document.createElement('img');
- element.src = section.src;
+ let element = document.createElement('img')
+ element.src = section.src
if (renderNode.prev) {
- let previousElement = renderNode.prev.element;
- let nextElement = previousElement.nextSibling;
+ let previousElement = renderNode.prev.element
+ let nextElement = previousElement.nextSibling
if (nextElement) {
- nextElement.parentNode.insertBefore(element, nextElement);
+ nextElement.parentNode.insertBefore(element, nextElement)
}
}
if (!element.parentNode) {
- renderNode.parent.element.appendChild(element);
+ renderNode.parent.element.appendChild(element)
}
- renderNode.element = element;
+ renderNode.element = element
}
}
[CARD_TYPE](renderNode, section) {
- const originalElement = renderNode.element;
- const {editor, options} = this;
+ const originalElement = renderNode.element
+ const { editor, options } = this
- const card = this._findCard(section.name);
+ const card = this._findCard(section.name)
- let { wrapper, cardElement } = renderCard();
- renderNode.element = wrapper;
- attachRenderNodeElementToDOM(renderNode, originalElement);
+ let { wrapper, cardElement } = renderCard()
+ renderNode.element = wrapper
+ attachRenderNodeElementToDOM(renderNode, originalElement)
- const cardNode = new CardNode(
- editor, card, section, cardElement, options);
- renderNode.cardNode = cardNode;
+ const cardNode = new CardNode(editor, card, section, cardElement, options)
+ renderNode.cardNode = cardNode
- const initialMode = section._initialMode;
- cardNode[initialMode]();
+ const initialMode = section._initialMode
+ cardNode[initialMode]()
}
[ATOM_TYPE](renderNode, atomModel) {
- let parentElement;
+ let parentElement
if (renderNode.prev) {
- parentElement = getNextMarkerElement(renderNode.prev);
+ parentElement = getNextMarkerElement(renderNode.prev)
} else {
- parentElement = renderNode.parent.element;
+ parentElement = renderNode.parent.element
}
- const { editor, options } = this;
- const {
- wrapper,
- markupElement,
- atomElement,
- headTextNode,
- tailTextNode
- } = renderAtom(atomModel, parentElement, renderNode.prev);
- const atom = this._findAtom(atomModel.name);
-
- let atomNode = renderNode.atomNode;
+ const { editor, options } = this
+ const { wrapper, markupElement, atomElement, headTextNode, tailTextNode } = renderAtom(
+ atomModel,
+ parentElement,
+ renderNode.prev
+ )
+ const atom = this._findAtom(atomModel.name)
+
+ let atomNode = renderNode.atomNode
if (!atomNode) {
// create new AtomNode
- atomNode = new AtomNode(editor, atom, atomModel, atomElement, options);
+ atomNode = new AtomNode(editor, atom, atomModel, atomElement, options)
} else {
// retarget atomNode to new atom element
- atomNode.element = atomElement;
+ atomNode.element = atomElement
}
- atomNode.render();
+ atomNode.render()
- renderNode.atomNode = atomNode;
- renderNode.element = wrapper;
- renderNode.headTextNode = headTextNode;
- renderNode.tailTextNode = tailTextNode;
- renderNode.markupElement = markupElement;
+ renderNode.atomNode = atomNode
+ renderNode.element = wrapper
+ renderNode.headTextNode = headTextNode
+ renderNode.tailTextNode = tailTextNode
+ renderNode.markupElement = markupElement
}
}
let destroyHooks = {
[POST_TYPE](/*renderNode, post*/) {
- assert('post destruction is not supported by the renderer', false);
+ assert('post destruction is not supported by the renderer', false)
},
[MARKUP_SECTION_TYPE](renderNode, section) {
- removeRenderNodeSectionFromParent(renderNode, section);
- removeRenderNodeElementFromParent(renderNode);
+ removeRenderNodeSectionFromParent(renderNode, section)
+ removeRenderNodeElementFromParent(renderNode)
},
[LIST_SECTION_TYPE](renderNode, section) {
- removeRenderNodeSectionFromParent(renderNode, section);
- removeRenderNodeElementFromParent(renderNode);
+ removeRenderNodeSectionFromParent(renderNode, section)
+ removeRenderNodeElementFromParent(renderNode)
},
[LIST_ITEM_TYPE](renderNode, li) {
- removeRenderNodeSectionFromParent(renderNode, li);
- removeRenderNodeElementFromParent(renderNode);
+ removeRenderNodeSectionFromParent(renderNode, li)
+ removeRenderNodeElementFromParent(renderNode)
},
[MARKER_TYPE](renderNode, marker) {
@@ -507,57 +487,57 @@ let destroyHooks = {
// If an atom throws during render we may end up later destroying a renderNode
// that has not rendered yet, so exit early here if so.
if (!renderNode.isRendered) {
- return;
+ return
}
- let { markupElement } = renderNode;
+ let { markupElement } = renderNode
if (marker.section) {
- marker.section.markers.remove(marker);
+ marker.section.markers.remove(marker)
}
if (markupElement.parentNode) {
// if no parentNode, the browser already removed this element
- markupElement.parentNode.removeChild(markupElement);
+ markupElement.parentNode.removeChild(markupElement)
}
},
[IMAGE_SECTION_TYPE](renderNode, section) {
- removeRenderNodeSectionFromParent(renderNode, section);
- removeRenderNodeElementFromParent(renderNode);
+ removeRenderNodeSectionFromParent(renderNode, section)
+ removeRenderNodeElementFromParent(renderNode)
},
[CARD_TYPE](renderNode, section) {
if (renderNode.cardNode) {
- renderNode.cardNode.teardown();
+ renderNode.cardNode.teardown()
}
- removeRenderNodeSectionFromParent(renderNode, section);
- removeRenderNodeElementFromParent(renderNode);
+ removeRenderNodeSectionFromParent(renderNode, section)
+ removeRenderNodeElementFromParent(renderNode)
},
[ATOM_TYPE](renderNode, atom) {
if (renderNode.atomNode) {
- renderNode.atomNode.teardown();
+ renderNode.atomNode.teardown()
}
// an atom is a kind of marker so just call its destroy hook vs copying here
- destroyHooks[MARKER_TYPE](renderNode, atom);
- }
-};
+ destroyHooks[MARKER_TYPE](renderNode, atom)
+ },
+}
// removes children from parentNode (a RenderNode) that are scheduled for removal
-function removeDestroyedChildren(parentNode, forceRemoval=false) {
- let child = parentNode.childNodes.head;
- let nextChild, method;
+function removeDestroyedChildren(parentNode, forceRemoval = false) {
+ let child = parentNode.childNodes.head
+ let nextChild, method
while (child) {
- nextChild = child.next;
+ nextChild = child.next
if (child.isRemoved || forceRemoval) {
- removeDestroyedChildren(child, true);
- method = child.postNode.type;
- assert(`editor-dom cannot destroy "${method}"`, !!destroyHooks[method]);
- destroyHooks[method](child, child.postNode);
- parentNode.childNodes.remove(child);
+ removeDestroyedChildren(child, true)
+ method = child.postNode.type
+ assert(`editor-dom cannot destroy "${method}"`, !!destroyHooks[method])
+ destroyHooks[method](child, child.postNode)
+ parentNode.childNodes.remove(child)
}
- child = nextChild;
+ child = nextChild
}
}
@@ -565,58 +545,57 @@ function removeDestroyedChildren(parentNode, forceRemoval=false) {
// create one, insert it into the tree, and return it
function lookupNode(renderTree, parentNode, postNode, previousNode) {
if (postNode.renderNode) {
- return postNode.renderNode;
+ return postNode.renderNode
} else {
- const renderNode = renderTree.buildRenderNode(postNode);
- parentNode.childNodes.insertAfter(renderNode, previousNode);
- return renderNode;
+ const renderNode = renderTree.buildRenderNode(postNode)
+ parentNode.childNodes.insertAfter(renderNode, previousNode)
+ return renderNode
}
}
export default class Renderer {
constructor(editor, cards, atoms, unknownCardHandler, unknownAtomHandler, options) {
- this.editor = editor;
- this.visitor = new Visitor(editor, cards, atoms, unknownCardHandler, unknownAtomHandler, options);
- this.nodes = [];
- this.hasRendered = false;
+ this.editor = editor
+ this.visitor = new Visitor(editor, cards, atoms, unknownCardHandler, unknownAtomHandler, options)
+ this.nodes = []
+ this.hasRendered = false
}
destroy() {
if (!this.hasRendered) {
- return;
+ return
}
- let renderNode = this.renderTree.rootNode;
- let force = true;
- removeDestroyedChildren(renderNode, force);
+ let renderNode = this.renderTree.rootNode
+ let force = true
+ removeDestroyedChildren(renderNode, force)
}
- visit(renderTree, parentNode, postNodes, visitAll=false) {
- let previousNode;
+ visit(renderTree, parentNode, postNodes, visitAll = false) {
+ let previousNode
postNodes.forEach(postNode => {
- let node = lookupNode(renderTree, parentNode, postNode, previousNode);
+ let node = lookupNode(renderTree, parentNode, postNode, previousNode)
if (node.isDirty || visitAll) {
- this.nodes.push(node);
+ this.nodes.push(node)
}
- previousNode = node;
- });
+ previousNode = node
+ })
}
render(renderTree) {
- this.hasRendered = true;
- this.renderTree = renderTree;
- let renderNode = renderTree.rootNode;
- let method, postNode;
+ this.hasRendered = true
+ this.renderTree = renderTree
+ let renderNode = renderTree.rootNode
+ let method, postNode
while (renderNode) {
- removeDestroyedChildren(renderNode);
- postNode = renderNode.postNode;
-
- method = postNode.type;
- assert(`EditorDom visitor cannot handle type ${method}`, !!this.visitor[method]);
- this.visitor[method](renderNode, postNode,
- (...args) => this.visit(renderTree, ...args));
- renderNode.markClean();
- renderNode = this.nodes.shift();
+ removeDestroyedChildren(renderNode)
+ postNode = renderNode.postNode
+
+ method = postNode.type
+ assert(`EditorDom visitor cannot handle type ${method}`, !!this.visitor[method])
+ this.visitor[method](renderNode, postNode, (...args) => this.visit(renderTree, ...args))
+ renderNode.markClean()
+ renderNode = this.nodes.shift()
}
}
}
diff --git a/src/js/renderers/mobiledoc/0-2.js b/src/js/renderers/mobiledoc/0-2.js
index 5e85061bd..a01c7b9ee 100644
--- a/src/js/renderers/mobiledoc/0-2.js
+++ b/src/js/renderers/mobiledoc/0-2.js
@@ -1,5 +1,5 @@
-import {visit, visitArray, compile} from '../../utils/compiler';
-import { objectToSortedKVArray } from '../../utils/array-utils';
+import { visit, visitArray, compile } from '../../utils/compiler'
+import { objectToSortedKVArray } from '../../utils/array-utils'
import {
POST_TYPE,
MARKUP_SECTION_TYPE,
@@ -8,103 +8,103 @@ import {
MARKER_TYPE,
MARKUP_TYPE,
IMAGE_SECTION_TYPE,
- CARD_TYPE
-} from '../../models/types';
+ CARD_TYPE,
+} from '../../models/types'
-export const MOBILEDOC_VERSION = '0.2.0';
-export const MOBILEDOC_MARKUP_SECTION_TYPE = 1;
-export const MOBILEDOC_IMAGE_SECTION_TYPE = 2;
-export const MOBILEDOC_LIST_SECTION_TYPE = 3;
-export const MOBILEDOC_CARD_SECTION_TYPE = 10;
+export const MOBILEDOC_VERSION = '0.2.0'
+export const MOBILEDOC_MARKUP_SECTION_TYPE = 1
+export const MOBILEDOC_IMAGE_SECTION_TYPE = 2
+export const MOBILEDOC_LIST_SECTION_TYPE = 3
+export const MOBILEDOC_CARD_SECTION_TYPE = 10
const visitor = {
[POST_TYPE](node, opcodes) {
- opcodes.push(['openPost']);
- visitArray(visitor, node.sections, opcodes);
+ opcodes.push(['openPost'])
+ visitArray(visitor, node.sections, opcodes)
},
[MARKUP_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openMarkupSection', node.tagName]);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openMarkupSection', node.tagName])
+ visitArray(visitor, node.markers, opcodes)
},
[LIST_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openListSection', node.tagName]);
- visitArray(visitor, node.items, opcodes);
+ opcodes.push(['openListSection', node.tagName])
+ visitArray(visitor, node.items, opcodes)
},
[LIST_ITEM_TYPE](node, opcodes) {
- opcodes.push(['openListItem']);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openListItem'])
+ visitArray(visitor, node.markers, opcodes)
},
[IMAGE_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openImageSection', node.src]);
+ opcodes.push(['openImageSection', node.src])
},
[CARD_TYPE](node, opcodes) {
- opcodes.push(['openCardSection', node.name, node.payload]);
+ opcodes.push(['openCardSection', node.name, node.payload])
},
[MARKER_TYPE](node, opcodes) {
- opcodes.push(['openMarker', node.closedMarkups.length, node.value]);
- visitArray(visitor, node.openedMarkups, opcodes);
+ opcodes.push(['openMarker', node.closedMarkups.length, node.value])
+ visitArray(visitor, node.openedMarkups, opcodes)
},
[MARKUP_TYPE](node, opcodes) {
- opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)]);
- }
-};
+ opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)])
+ },
+}
const postOpcodeCompiler = {
openMarker(closeCount, value) {
- this.markupMarkerIds = [];
- this.markers.push([
- this.markupMarkerIds,
- closeCount,
- value || ''
- ]);
+ this.markupMarkerIds = []
+ this.markers.push([this.markupMarkerIds, closeCount, value || ''])
},
openMarkupSection(tagName) {
- this.markers = [];
- this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers]);
+ this.markers = []
+ this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers])
},
openListSection(tagName) {
- this.items = [];
- this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items]);
+ this.items = []
+ this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items])
},
openListItem() {
- this.markers = [];
- this.items.push(this.markers);
+ this.markers = []
+ this.items.push(this.markers)
},
openImageSection(url) {
- this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url]);
+ this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url])
},
openCardSection(name, payload) {
- this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, name, payload]);
+ this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, name, payload])
},
openPost() {
- this.markerTypes = [];
- this.sections = [];
+ this.markerTypes = []
+ this.sections = []
this.result = {
version: MOBILEDOC_VERSION,
- sections: [this.markerTypes, this.sections]
- };
+ sections: [this.markerTypes, this.sections],
+ }
},
openMarkup(tagName, attributes) {
- const index = this._findOrAddMarkerTypeIndex(tagName, attributes);
- this.markupMarkerIds.push(index);
+ const index = this._findOrAddMarkerTypeIndex(tagName, attributes)
+ this.markupMarkerIds.push(index)
},
_findOrAddMarkerTypeIndex(tagName, attributesArray) {
- if (!this._markerTypeCache) { this._markerTypeCache = {}; }
- const key = `${tagName}-${attributesArray.join('-')}`;
+ if (!this._markerTypeCache) {
+ this._markerTypeCache = {}
+ }
+ const key = `${tagName}-${attributesArray.join('-')}`
- let index = this._markerTypeCache[key];
+ let index = this._markerTypeCache[key]
if (index === undefined) {
- let markerType = [tagName];
- if (attributesArray.length) { markerType.push(attributesArray); }
- this.markerTypes.push(markerType);
+ let markerType = [tagName]
+ if (attributesArray.length) {
+ markerType.push(attributesArray)
+ }
+ this.markerTypes.push(markerType)
- index = this.markerTypes.length - 1;
- this._markerTypeCache[key] = index;
+ index = this.markerTypes.length - 1
+ this._markerTypeCache[key] = index
}
- return index;
- }
-};
+ return index
+ },
+}
/**
* Render from post -> mobiledoc
@@ -115,10 +115,10 @@ export default {
* @return {Mobiledoc}
*/
render(post) {
- let opcodes = [];
- visit(visitor, post, opcodes);
- let compiler = Object.create(postOpcodeCompiler);
- compile(compiler, opcodes);
- return compiler.result;
- }
-};
+ let opcodes = []
+ visit(visitor, post, opcodes)
+ let compiler = Object.create(postOpcodeCompiler)
+ compile(compiler, opcodes)
+ return compiler.result
+ },
+}
diff --git a/src/js/renderers/mobiledoc/0-3-1.js b/src/js/renderers/mobiledoc/0-3-1.js
index 74c109ff4..170a6eb44 100644
--- a/src/js/renderers/mobiledoc/0-3-1.js
+++ b/src/js/renderers/mobiledoc/0-3-1.js
@@ -1,5 +1,5 @@
-import {visit, visitArray, compile} from '../../utils/compiler';
-import { objectToSortedKVArray } from '../../utils/array-utils';
+import { visit, visitArray, compile } from '../../utils/compiler'
+import { objectToSortedKVArray } from '../../utils/array-utils'
import {
POST_TYPE,
MARKUP_SECTION_TYPE,
@@ -9,137 +9,131 @@ import {
MARKUP_TYPE,
IMAGE_SECTION_TYPE,
CARD_TYPE,
- ATOM_TYPE
-} from '../../models/types';
+ ATOM_TYPE,
+} from '../../models/types'
-export const MOBILEDOC_VERSION = '0.3.1';
-export const MOBILEDOC_MARKUP_SECTION_TYPE = 1;
-export const MOBILEDOC_IMAGE_SECTION_TYPE = 2;
-export const MOBILEDOC_LIST_SECTION_TYPE = 3;
-export const MOBILEDOC_CARD_SECTION_TYPE = 10;
+export const MOBILEDOC_VERSION = '0.3.1'
+export const MOBILEDOC_MARKUP_SECTION_TYPE = 1
+export const MOBILEDOC_IMAGE_SECTION_TYPE = 2
+export const MOBILEDOC_LIST_SECTION_TYPE = 3
+export const MOBILEDOC_CARD_SECTION_TYPE = 10
-export const MOBILEDOC_MARKUP_MARKER_TYPE = 0;
-export const MOBILEDOC_ATOM_MARKER_TYPE = 1;
+export const MOBILEDOC_MARKUP_MARKER_TYPE = 0
+export const MOBILEDOC_ATOM_MARKER_TYPE = 1
const visitor = {
[POST_TYPE](node, opcodes) {
- opcodes.push(['openPost']);
- visitArray(visitor, node.sections, opcodes);
+ opcodes.push(['openPost'])
+ visitArray(visitor, node.sections, opcodes)
},
[MARKUP_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openMarkupSection', node.tagName]);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openMarkupSection', node.tagName])
+ visitArray(visitor, node.markers, opcodes)
},
[LIST_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openListSection', node.tagName]);
- visitArray(visitor, node.items, opcodes);
+ opcodes.push(['openListSection', node.tagName])
+ visitArray(visitor, node.items, opcodes)
},
[LIST_ITEM_TYPE](node, opcodes) {
- opcodes.push(['openListItem']);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openListItem'])
+ visitArray(visitor, node.markers, opcodes)
},
[IMAGE_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openImageSection', node.src]);
+ opcodes.push(['openImageSection', node.src])
},
[CARD_TYPE](node, opcodes) {
- opcodes.push(['openCardSection', node.name, node.payload]);
+ opcodes.push(['openCardSection', node.name, node.payload])
},
[MARKER_TYPE](node, opcodes) {
- opcodes.push(['openMarker', node.closedMarkups.length, node.value]);
- visitArray(visitor, node.openedMarkups, opcodes);
+ opcodes.push(['openMarker', node.closedMarkups.length, node.value])
+ visitArray(visitor, node.openedMarkups, opcodes)
},
[MARKUP_TYPE](node, opcodes) {
- opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)]);
+ opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)])
},
[ATOM_TYPE](node, opcodes) {
- opcodes.push(['openAtom', node.closedMarkups.length, node.name, node.value, node.payload]);
- visitArray(visitor, node.openedMarkups, opcodes);
- }
-};
+ opcodes.push(['openAtom', node.closedMarkups.length, node.name, node.value, node.payload])
+ visitArray(visitor, node.openedMarkups, opcodes)
+ },
+}
const postOpcodeCompiler = {
openMarker(closeCount, value) {
- this.markupMarkerIds = [];
- this.markers.push([
- MOBILEDOC_MARKUP_MARKER_TYPE,
- this.markupMarkerIds,
- closeCount,
- value || ''
- ]);
+ this.markupMarkerIds = []
+ this.markers.push([MOBILEDOC_MARKUP_MARKER_TYPE, this.markupMarkerIds, closeCount, value || ''])
},
openMarkupSection(tagName) {
- this.markers = [];
- this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers]);
+ this.markers = []
+ this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers])
},
openListSection(tagName) {
- this.items = [];
- this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items]);
+ this.items = []
+ this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items])
},
openListItem() {
- this.markers = [];
- this.items.push(this.markers);
+ this.markers = []
+ this.items.push(this.markers)
},
openImageSection(url) {
- this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url]);
+ this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url])
},
openCardSection(name, payload) {
- const index = this._addCardTypeIndex(name, payload);
- this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, index]);
+ const index = this._addCardTypeIndex(name, payload)
+ this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, index])
},
openAtom(closeCount, name, value, payload) {
- const index = this._addAtomTypeIndex(name, value, payload);
- this.markupMarkerIds = [];
- this.markers.push([
- MOBILEDOC_ATOM_MARKER_TYPE,
- this.markupMarkerIds,
- closeCount,
- index
- ]);
+ const index = this._addAtomTypeIndex(name, value, payload)
+ this.markupMarkerIds = []
+ this.markers.push([MOBILEDOC_ATOM_MARKER_TYPE, this.markupMarkerIds, closeCount, index])
},
openPost() {
- this.atomTypes = [];
- this.cardTypes = [];
- this.markerTypes = [];
- this.sections = [];
+ this.atomTypes = []
+ this.cardTypes = []
+ this.markerTypes = []
+ this.sections = []
this.result = {
version: MOBILEDOC_VERSION,
atoms: this.atomTypes,
cards: this.cardTypes,
markups: this.markerTypes,
- sections: this.sections
- };
+ sections: this.sections,
+ }
},
openMarkup(tagName, attributes) {
- const index = this._findOrAddMarkerTypeIndex(tagName, attributes);
- this.markupMarkerIds.push(index);
+ const index = this._findOrAddMarkerTypeIndex(tagName, attributes)
+ this.markupMarkerIds.push(index)
},
_addCardTypeIndex(cardName, payload) {
- let cardType = [cardName, payload];
- this.cardTypes.push(cardType);
- return this.cardTypes.length - 1;
+ let cardType = [cardName, payload]
+ this.cardTypes.push(cardType)
+ return this.cardTypes.length - 1
},
_addAtomTypeIndex(atomName, atomValue, payload) {
- let atomType = [atomName, atomValue, payload];
- this.atomTypes.push(atomType);
- return this.atomTypes.length - 1;
+ let atomType = [atomName, atomValue, payload]
+ this.atomTypes.push(atomType)
+ return this.atomTypes.length - 1
},
_findOrAddMarkerTypeIndex(tagName, attributesArray) {
- if (!this._markerTypeCache) { this._markerTypeCache = {}; }
- const key = `${tagName}-${attributesArray.join('-')}`;
+ if (!this._markerTypeCache) {
+ this._markerTypeCache = {}
+ }
+ const key = `${tagName}-${attributesArray.join('-')}`
- let index = this._markerTypeCache[key];
+ let index = this._markerTypeCache[key]
if (index === undefined) {
- let markerType = [tagName];
- if (attributesArray.length) { markerType.push(attributesArray); }
- this.markerTypes.push(markerType);
+ let markerType = [tagName]
+ if (attributesArray.length) {
+ markerType.push(attributesArray)
+ }
+ this.markerTypes.push(markerType)
- index = this.markerTypes.length - 1;
- this._markerTypeCache[key] = index;
+ index = this.markerTypes.length - 1
+ this._markerTypeCache[key] = index
}
- return index;
- }
-};
+ return index
+ },
+}
/**
* Render from post -> mobiledoc
@@ -150,10 +144,10 @@ export default {
* @return {Mobiledoc}
*/
render(post) {
- let opcodes = [];
- visit(visitor, post, opcodes);
- let compiler = Object.create(postOpcodeCompiler);
- compile(compiler, opcodes);
- return compiler.result;
- }
-};
+ let opcodes = []
+ visit(visitor, post, opcodes)
+ let compiler = Object.create(postOpcodeCompiler)
+ compile(compiler, opcodes)
+ return compiler.result
+ },
+}
diff --git a/src/js/renderers/mobiledoc/0-3-2.js b/src/js/renderers/mobiledoc/0-3-2.js
index 9656fb80f..b9f3edae0 100644
--- a/src/js/renderers/mobiledoc/0-3-2.js
+++ b/src/js/renderers/mobiledoc/0-3-2.js
@@ -1,5 +1,5 @@
-import {visit, visitArray, compile} from '../../utils/compiler';
-import { objectToSortedKVArray } from '../../utils/array-utils';
+import { visit, visitArray, compile } from '../../utils/compiler'
+import { objectToSortedKVArray } from '../../utils/array-utils'
import {
POST_TYPE,
MARKUP_SECTION_TYPE,
@@ -9,145 +9,139 @@ import {
MARKUP_TYPE,
IMAGE_SECTION_TYPE,
CARD_TYPE,
- ATOM_TYPE
-} from '../../models/types';
+ ATOM_TYPE,
+} from '../../models/types'
-export const MOBILEDOC_VERSION = '0.3.2';
-export const MOBILEDOC_MARKUP_SECTION_TYPE = 1;
-export const MOBILEDOC_IMAGE_SECTION_TYPE = 2;
-export const MOBILEDOC_LIST_SECTION_TYPE = 3;
-export const MOBILEDOC_CARD_SECTION_TYPE = 10;
+export const MOBILEDOC_VERSION = '0.3.2'
+export const MOBILEDOC_MARKUP_SECTION_TYPE = 1
+export const MOBILEDOC_IMAGE_SECTION_TYPE = 2
+export const MOBILEDOC_LIST_SECTION_TYPE = 3
+export const MOBILEDOC_CARD_SECTION_TYPE = 10
-export const MOBILEDOC_MARKUP_MARKER_TYPE = 0;
-export const MOBILEDOC_ATOM_MARKER_TYPE = 1;
+export const MOBILEDOC_MARKUP_MARKER_TYPE = 0
+export const MOBILEDOC_ATOM_MARKER_TYPE = 1
const visitor = {
[POST_TYPE](node, opcodes) {
- opcodes.push(['openPost']);
- visitArray(visitor, node.sections, opcodes);
+ opcodes.push(['openPost'])
+ visitArray(visitor, node.sections, opcodes)
},
[MARKUP_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openMarkupSection', node.tagName, objectToSortedKVArray(node.attributes)]);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openMarkupSection', node.tagName, objectToSortedKVArray(node.attributes)])
+ visitArray(visitor, node.markers, opcodes)
},
[LIST_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openListSection', node.tagName, objectToSortedKVArray(node.attributes)]);
- visitArray(visitor, node.items, opcodes);
+ opcodes.push(['openListSection', node.tagName, objectToSortedKVArray(node.attributes)])
+ visitArray(visitor, node.items, opcodes)
},
[LIST_ITEM_TYPE](node, opcodes) {
- opcodes.push(['openListItem']);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openListItem'])
+ visitArray(visitor, node.markers, opcodes)
},
[IMAGE_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openImageSection', node.src]);
+ opcodes.push(['openImageSection', node.src])
},
[CARD_TYPE](node, opcodes) {
- opcodes.push(['openCardSection', node.name, node.payload]);
+ opcodes.push(['openCardSection', node.name, node.payload])
},
[MARKER_TYPE](node, opcodes) {
- opcodes.push(['openMarker', node.closedMarkups.length, node.value]);
- visitArray(visitor, node.openedMarkups, opcodes);
+ opcodes.push(['openMarker', node.closedMarkups.length, node.value])
+ visitArray(visitor, node.openedMarkups, opcodes)
},
[MARKUP_TYPE](node, opcodes) {
- opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)]);
+ opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)])
},
[ATOM_TYPE](node, opcodes) {
- opcodes.push(['openAtom', node.closedMarkups.length, node.name, node.value, node.payload]);
- visitArray(visitor, node.openedMarkups, opcodes);
- }
-};
+ opcodes.push(['openAtom', node.closedMarkups.length, node.name, node.value, node.payload])
+ visitArray(visitor, node.openedMarkups, opcodes)
+ },
+}
const postOpcodeCompiler = {
openMarker(closeCount, value) {
- this.markupMarkerIds = [];
- this.markers.push([
- MOBILEDOC_MARKUP_MARKER_TYPE,
- this.markupMarkerIds,
- closeCount,
- value || ''
- ]);
+ this.markupMarkerIds = []
+ this.markers.push([MOBILEDOC_MARKUP_MARKER_TYPE, this.markupMarkerIds, closeCount, value || ''])
},
openMarkupSection(tagName, attributes) {
- this.markers = [];
+ this.markers = []
if (attributes && attributes.length !== 0) {
- this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers, attributes]);
+ this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers, attributes])
} else {
- this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers]);
+ this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers])
}
},
openListSection(tagName, attributes) {
- this.items = [];
+ this.items = []
if (attributes && attributes.length !== 0) {
- this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items, attributes]);
+ this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items, attributes])
} else {
- this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items]);
+ this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items])
}
},
openListItem() {
- this.markers = [];
- this.items.push(this.markers);
+ this.markers = []
+ this.items.push(this.markers)
},
openImageSection(url) {
- this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url]);
+ this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url])
},
openCardSection(name, payload) {
- const index = this._addCardTypeIndex(name, payload);
- this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, index]);
+ const index = this._addCardTypeIndex(name, payload)
+ this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, index])
},
openAtom(closeCount, name, value, payload) {
- const index = this._addAtomTypeIndex(name, value, payload);
- this.markupMarkerIds = [];
- this.markers.push([
- MOBILEDOC_ATOM_MARKER_TYPE,
- this.markupMarkerIds,
- closeCount,
- index
- ]);
+ const index = this._addAtomTypeIndex(name, value, payload)
+ this.markupMarkerIds = []
+ this.markers.push([MOBILEDOC_ATOM_MARKER_TYPE, this.markupMarkerIds, closeCount, index])
},
openPost() {
- this.atomTypes = [];
- this.cardTypes = [];
- this.markerTypes = [];
- this.sections = [];
+ this.atomTypes = []
+ this.cardTypes = []
+ this.markerTypes = []
+ this.sections = []
this.result = {
version: MOBILEDOC_VERSION,
atoms: this.atomTypes,
cards: this.cardTypes,
markups: this.markerTypes,
- sections: this.sections
- };
+ sections: this.sections,
+ }
},
openMarkup(tagName, attributes) {
- const index = this._findOrAddMarkerTypeIndex(tagName, attributes);
- this.markupMarkerIds.push(index);
+ const index = this._findOrAddMarkerTypeIndex(tagName, attributes)
+ this.markupMarkerIds.push(index)
},
_addCardTypeIndex(cardName, payload) {
- let cardType = [cardName, payload];
- this.cardTypes.push(cardType);
- return this.cardTypes.length - 1;
+ let cardType = [cardName, payload]
+ this.cardTypes.push(cardType)
+ return this.cardTypes.length - 1
},
_addAtomTypeIndex(atomName, atomValue, payload) {
- let atomType = [atomName, atomValue, payload];
- this.atomTypes.push(atomType);
- return this.atomTypes.length - 1;
+ let atomType = [atomName, atomValue, payload]
+ this.atomTypes.push(atomType)
+ return this.atomTypes.length - 1
},
_findOrAddMarkerTypeIndex(tagName, attributesArray) {
- if (!this._markerTypeCache) { this._markerTypeCache = {}; }
- const key = `${tagName}-${attributesArray.join('-')}`;
+ if (!this._markerTypeCache) {
+ this._markerTypeCache = {}
+ }
+ const key = `${tagName}-${attributesArray.join('-')}`
- let index = this._markerTypeCache[key];
+ let index = this._markerTypeCache[key]
if (index === undefined) {
- let markerType = [tagName];
- if (attributesArray.length) { markerType.push(attributesArray); }
- this.markerTypes.push(markerType);
+ let markerType = [tagName]
+ if (attributesArray.length) {
+ markerType.push(attributesArray)
+ }
+ this.markerTypes.push(markerType)
- index = this.markerTypes.length - 1;
- this._markerTypeCache[key] = index;
+ index = this.markerTypes.length - 1
+ this._markerTypeCache[key] = index
}
- return index;
- }
-};
+ return index
+ },
+}
/**
* Render from post -> mobiledoc
@@ -158,10 +152,10 @@ export default {
* @return {Mobiledoc}
*/
render(post) {
- let opcodes = [];
- visit(visitor, post, opcodes);
- let compiler = Object.create(postOpcodeCompiler);
- compile(compiler, opcodes);
- return compiler.result;
- }
-};
+ let opcodes = []
+ visit(visitor, post, opcodes)
+ let compiler = Object.create(postOpcodeCompiler)
+ compile(compiler, opcodes)
+ return compiler.result
+ },
+}
diff --git a/src/js/renderers/mobiledoc/0-3.js b/src/js/renderers/mobiledoc/0-3.js
index b11b2a855..cdd4a793b 100644
--- a/src/js/renderers/mobiledoc/0-3.js
+++ b/src/js/renderers/mobiledoc/0-3.js
@@ -1,5 +1,5 @@
-import {visit, visitArray, compile} from '../../utils/compiler';
-import { objectToSortedKVArray } from '../../utils/array-utils';
+import { visit, visitArray, compile } from '../../utils/compiler'
+import { objectToSortedKVArray } from '../../utils/array-utils'
import {
POST_TYPE,
MARKUP_SECTION_TYPE,
@@ -9,137 +9,131 @@ import {
MARKUP_TYPE,
IMAGE_SECTION_TYPE,
CARD_TYPE,
- ATOM_TYPE
-} from '../../models/types';
+ ATOM_TYPE,
+} from '../../models/types'
-export const MOBILEDOC_VERSION = '0.3.0';
-export const MOBILEDOC_MARKUP_SECTION_TYPE = 1;
-export const MOBILEDOC_IMAGE_SECTION_TYPE = 2;
-export const MOBILEDOC_LIST_SECTION_TYPE = 3;
-export const MOBILEDOC_CARD_SECTION_TYPE = 10;
+export const MOBILEDOC_VERSION = '0.3.0'
+export const MOBILEDOC_MARKUP_SECTION_TYPE = 1
+export const MOBILEDOC_IMAGE_SECTION_TYPE = 2
+export const MOBILEDOC_LIST_SECTION_TYPE = 3
+export const MOBILEDOC_CARD_SECTION_TYPE = 10
-export const MOBILEDOC_MARKUP_MARKER_TYPE = 0;
-export const MOBILEDOC_ATOM_MARKER_TYPE = 1;
+export const MOBILEDOC_MARKUP_MARKER_TYPE = 0
+export const MOBILEDOC_ATOM_MARKER_TYPE = 1
const visitor = {
[POST_TYPE](node, opcodes) {
- opcodes.push(['openPost']);
- visitArray(visitor, node.sections, opcodes);
+ opcodes.push(['openPost'])
+ visitArray(visitor, node.sections, opcodes)
},
[MARKUP_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openMarkupSection', node.tagName]);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openMarkupSection', node.tagName])
+ visitArray(visitor, node.markers, opcodes)
},
[LIST_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openListSection', node.tagName]);
- visitArray(visitor, node.items, opcodes);
+ opcodes.push(['openListSection', node.tagName])
+ visitArray(visitor, node.items, opcodes)
},
[LIST_ITEM_TYPE](node, opcodes) {
- opcodes.push(['openListItem']);
- visitArray(visitor, node.markers, opcodes);
+ opcodes.push(['openListItem'])
+ visitArray(visitor, node.markers, opcodes)
},
[IMAGE_SECTION_TYPE](node, opcodes) {
- opcodes.push(['openImageSection', node.src]);
+ opcodes.push(['openImageSection', node.src])
},
[CARD_TYPE](node, opcodes) {
- opcodes.push(['openCardSection', node.name, node.payload]);
+ opcodes.push(['openCardSection', node.name, node.payload])
},
[MARKER_TYPE](node, opcodes) {
- opcodes.push(['openMarker', node.closedMarkups.length, node.value]);
- visitArray(visitor, node.openedMarkups, opcodes);
+ opcodes.push(['openMarker', node.closedMarkups.length, node.value])
+ visitArray(visitor, node.openedMarkups, opcodes)
},
[MARKUP_TYPE](node, opcodes) {
- opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)]);
+ opcodes.push(['openMarkup', node.tagName, objectToSortedKVArray(node.attributes)])
},
[ATOM_TYPE](node, opcodes) {
- opcodes.push(['openAtom', node.closedMarkups.length, node.name, node.value, node.payload]);
- visitArray(visitor, node.openedMarkups, opcodes);
- }
-};
+ opcodes.push(['openAtom', node.closedMarkups.length, node.name, node.value, node.payload])
+ visitArray(visitor, node.openedMarkups, opcodes)
+ },
+}
const postOpcodeCompiler = {
openMarker(closeCount, value) {
- this.markupMarkerIds = [];
- this.markers.push([
- MOBILEDOC_MARKUP_MARKER_TYPE,
- this.markupMarkerIds,
- closeCount,
- value || ''
- ]);
+ this.markupMarkerIds = []
+ this.markers.push([MOBILEDOC_MARKUP_MARKER_TYPE, this.markupMarkerIds, closeCount, value || ''])
},
openMarkupSection(tagName) {
- this.markers = [];
- this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers]);
+ this.markers = []
+ this.sections.push([MOBILEDOC_MARKUP_SECTION_TYPE, tagName, this.markers])
},
openListSection(tagName) {
- this.items = [];
- this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items]);
+ this.items = []
+ this.sections.push([MOBILEDOC_LIST_SECTION_TYPE, tagName, this.items])
},
openListItem() {
- this.markers = [];
- this.items.push(this.markers);
+ this.markers = []
+ this.items.push(this.markers)
},
openImageSection(url) {
- this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url]);
+ this.sections.push([MOBILEDOC_IMAGE_SECTION_TYPE, url])
},
openCardSection(name, payload) {
- const index = this._addCardTypeIndex(name, payload);
- this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, index]);
+ const index = this._addCardTypeIndex(name, payload)
+ this.sections.push([MOBILEDOC_CARD_SECTION_TYPE, index])
},
openAtom(closeCount, name, value, payload) {
- const index = this._addAtomTypeIndex(name, value, payload);
- this.markupMarkerIds = [];
- this.markers.push([
- MOBILEDOC_ATOM_MARKER_TYPE,
- this.markupMarkerIds,
- closeCount,
- index
- ]);
+ const index = this._addAtomTypeIndex(name, value, payload)
+ this.markupMarkerIds = []
+ this.markers.push([MOBILEDOC_ATOM_MARKER_TYPE, this.markupMarkerIds, closeCount, index])
},
openPost() {
- this.atomTypes = [];
- this.cardTypes = [];
- this.markerTypes = [];
- this.sections = [];
+ this.atomTypes = []
+ this.cardTypes = []
+ this.markerTypes = []
+ this.sections = []
this.result = {
version: MOBILEDOC_VERSION,
atoms: this.atomTypes,
cards: this.cardTypes,
markups: this.markerTypes,
- sections: this.sections
- };
+ sections: this.sections,
+ }
},
openMarkup(tagName, attributes) {
- const index = this._findOrAddMarkerTypeIndex(tagName, attributes);
- this.markupMarkerIds.push(index);
+ const index = this._findOrAddMarkerTypeIndex(tagName, attributes)
+ this.markupMarkerIds.push(index)
},
_addCardTypeIndex(cardName, payload) {
- let cardType = [cardName, payload];
- this.cardTypes.push(cardType);
- return this.cardTypes.length - 1;
+ let cardType = [cardName, payload]
+ this.cardTypes.push(cardType)
+ return this.cardTypes.length - 1
},
_addAtomTypeIndex(atomName, atomValue, payload) {
- let atomType = [atomName, atomValue, payload];
- this.atomTypes.push(atomType);
- return this.atomTypes.length - 1;
+ let atomType = [atomName, atomValue, payload]
+ this.atomTypes.push(atomType)
+ return this.atomTypes.length - 1
},
_findOrAddMarkerTypeIndex(tagName, attributesArray) {
- if (!this._markerTypeCache) { this._markerTypeCache = {}; }
- const key = `${tagName}-${attributesArray.join('-')}`;
+ if (!this._markerTypeCache) {
+ this._markerTypeCache = {}
+ }
+ const key = `${tagName}-${attributesArray.join('-')}`
- let index = this._markerTypeCache[key];
+ let index = this._markerTypeCache[key]
if (index === undefined) {
- let markerType = [tagName];
- if (attributesArray.length) { markerType.push(attributesArray); }
- this.markerTypes.push(markerType);
+ let markerType = [tagName]
+ if (attributesArray.length) {
+ markerType.push(attributesArray)
+ }
+ this.markerTypes.push(markerType)
- index = this.markerTypes.length - 1;
- this._markerTypeCache[key] = index;
+ index = this.markerTypes.length - 1
+ this._markerTypeCache[key] = index
}
- return index;
- }
-};
+ return index
+ },
+}
/**
* Render from post -> mobiledoc
@@ -150,10 +144,10 @@ export default {
* @return {Mobiledoc}
*/
render(post) {
- let opcodes = [];
- visit(visitor, post, opcodes);
- let compiler = Object.create(postOpcodeCompiler);
- compile(compiler, opcodes);
- return compiler.result;
- }
-};
+ let opcodes = []
+ visit(visitor, post, opcodes)
+ let compiler = Object.create(postOpcodeCompiler)
+ compile(compiler, opcodes)
+ return compiler.result
+ },
+}
diff --git a/src/js/renderers/mobiledoc/index.js b/src/js/renderers/mobiledoc/index.js
index da1622900..a0b86ae8a 100644
--- a/src/js/renderers/mobiledoc/index.js
+++ b/src/js/renderers/mobiledoc/index.js
@@ -1,26 +1,26 @@
-import MobiledocRenderer_0_2, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_2 } from './0-2';
-import MobiledocRenderer_0_3, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3 } from './0-3';
-import MobiledocRenderer_0_3_1, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_1 } from './0-3-1';
-import MobiledocRenderer_0_3_2, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_2 } from './0-3-2';
-import assert from 'mobiledoc-kit/utils/assert';
+import MobiledocRenderer_0_2, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_2 } from './0-2'
+import MobiledocRenderer_0_3, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3 } from './0-3'
+import MobiledocRenderer_0_3_1, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_1 } from './0-3-1'
+import MobiledocRenderer_0_3_2, { MOBILEDOC_VERSION as MOBILEDOC_VERSION_0_3_2 } from './0-3-2'
+import assert from 'mobiledoc-kit/utils/assert'
-export const MOBILEDOC_VERSION = MOBILEDOC_VERSION_0_3_2;
+export const MOBILEDOC_VERSION = MOBILEDOC_VERSION_0_3_2
export default {
render(post, version) {
switch (version) {
case MOBILEDOC_VERSION_0_2:
- return MobiledocRenderer_0_2.render(post);
+ return MobiledocRenderer_0_2.render(post)
case MOBILEDOC_VERSION_0_3:
- return MobiledocRenderer_0_3.render(post);
+ return MobiledocRenderer_0_3.render(post)
case MOBILEDOC_VERSION_0_3_1:
- return MobiledocRenderer_0_3_1.render(post);
+ return MobiledocRenderer_0_3_1.render(post)
case undefined:
case null:
case MOBILEDOC_VERSION_0_3_2:
- return MobiledocRenderer_0_3_2.render(post);
+ return MobiledocRenderer_0_3_2.render(post)
default:
- assert(`Unknown version of mobiledoc renderer requested: ${version}`, false);
+ assert(`Unknown version of mobiledoc renderer requested: ${version}`, false)
}
- }
-};
+ },
+}
diff --git a/src/js/utils/array-utils.js b/src/js/utils/array-utils.js
index 9ab77d945..54380d4a5 100644
--- a/src/js/utils/array-utils.js
+++ b/src/js/utils/array-utils.js
@@ -1,40 +1,44 @@
function detect(enumerable, callback) {
if (enumerable.detect) {
- return enumerable.detect(callback);
+ return enumerable.detect(callback)
} else {
- for (let i=0; i {
- if (conditionFn(i)) { filtered.push(i); }
- });
- return filtered;
+ if (conditionFn(i)) {
+ filtered.push(i)
+ }
+ })
+ return filtered
}
/**
@@ -65,14 +71,14 @@ function filter(enumerable, conditionFn) {
* @private
*/
function commonItemLength(listA, listB) {
- let offset = 0;
+ let offset = 0
while (offset < listA.length && offset < listB.length) {
if (listA[offset] !== listB[offset]) {
- break;
+ break
}
- offset++;
+ offset++
}
- return offset;
+ return offset
}
/**
@@ -80,27 +86,27 @@ function commonItemLength(listA, listB) {
* @private
*/
function commonItems(listA, listB) {
- let offset = 0;
+ let offset = 0
while (offset < listA.length && offset < listB.length) {
if (listA[offset] !== listB[offset]) {
- break;
+ break
}
- offset++;
+ offset++
}
- return listA.slice(0, offset);
+ return listA.slice(0, offset)
}
// return new array without falsy items like ruby's `compact`
function compact(enumerable) {
- return filter(enumerable, i => !!i);
+ return filter(enumerable, i => !!i)
}
function reduce(enumerable, callback, initialValue) {
- let previousValue = initialValue;
+ let previousValue = initialValue
forEach(enumerable, (val, index) => {
- previousValue = callback(previousValue, val, index);
- });
- return previousValue;
+ previousValue = callback(previousValue, val, index)
+ })
+ return previousValue
}
/**
@@ -109,51 +115,56 @@ function reduce(enumerable, callback, initialValue) {
* @private
*/
function kvArrayToObject(array) {
- const obj = {};
- for (let i = 0; i < array.length; i+=2) {
- let [key, value] = [array[i], array[i+1]];
- obj[key] = value;
+ const obj = {}
+ for (let i = 0; i < array.length; i += 2) {
+ let [key, value] = [array[i], array[i + 1]]
+ obj[key] = value
}
- return obj;
+ return obj
}
function objectToSortedKVArray(obj) {
- const keys = Object.keys(obj).sort();
- const result = [];
+ const keys = Object.keys(obj).sort()
+ const result = []
keys.forEach(k => {
- result.push(k);
- result.push(obj[k]);
- });
- return result;
+ result.push(k)
+ result.push(obj[k])
+ })
+ return result
}
// check shallow equality of two non-nested arrays
function isArrayEqual(arr1, arr2) {
- let l1 = arr1.length, l2 = arr2.length;
- if (l1 !== l2) { return false; }
+ let l1 = arr1.length,
+ l2 = arr2.length
+ if (l1 !== l2) {
+ return false
+ }
- for (let i=0; i < l1; i++) {
- if (arr1[i] !== arr2[i]) { return false; }
+ for (let i = 0; i < l1; i++) {
+ if (arr1[i] !== arr2[i]) {
+ return false
+ }
}
- return true;
+ return true
}
// return an object with only the valid keys
-function filterObject(object, validKeys=[]) {
- let result = {};
+function filterObject(object, validKeys = []) {
+ let result = {}
forEach(
filter(Object.keys(object), key => validKeys.indexOf(key) !== -1),
- key => result[key] = object[key]
- );
- return result;
+ key => (result[key] = object[key])
+ )
+ return result
}
function contains(array, item) {
- return array.indexOf(item) !== -1;
+ return array.indexOf(item) !== -1
}
function values(object) {
- return Object.keys(object).map(key => object[key]);
+ return Object.keys(object).map(key => object[key])
}
export {
@@ -172,5 +183,5 @@ export {
toArray,
filterObject,
contains,
- values
-};
+ values,
+}
diff --git a/src/js/utils/assert.js b/src/js/utils/assert.js
index 3e3df8f0d..b35ec961c 100644
--- a/src/js/utils/assert.js
+++ b/src/js/utils/assert.js
@@ -1,7 +1,7 @@
-import MobiledocError from './mobiledoc-error';
+import MobiledocError from './mobiledoc-error'
-export default function(message, conditional) {
+export default function (message, conditional) {
if (!conditional) {
- throw new MobiledocError(message);
+ throw new MobiledocError(message)
}
}
diff --git a/src/js/utils/browser.js b/src/js/utils/browser.js
index 5c296f0b0..559b05b8c 100644
--- a/src/js/utils/browser.js
+++ b/src/js/utils/browser.js
@@ -1,8 +1,8 @@
export default {
isMac() {
- return (typeof window !== 'undefined') && window.navigator && /Mac/.test(window.navigator.platform);
+ return typeof window !== 'undefined' && window.navigator && /Mac/.test(window.navigator.platform)
},
isWin() {
- return (typeof window !== 'undefined') && window.navigator && /Win/.test(window.navigator.platform);
- }
-};
+ return typeof window !== 'undefined' && window.navigator && /Win/.test(window.navigator.platform)
+ },
+}
diff --git a/src/js/utils/characters.js b/src/js/utils/characters.js
index d906126d8..f3f373d01 100644
--- a/src/js/utils/characters.js
+++ b/src/js/utils/characters.js
@@ -1,3 +1,3 @@
-export const TAB = '\t';
-export const ENTER = '\n';
-export const SPACE = ' ';
+export const TAB = '\t'
+export const ENTER = '\n'
+export const SPACE = ' '
diff --git a/src/js/utils/compiler.js b/src/js/utils/compiler.js
index 2b549d903..d2e23967e 100644
--- a/src/js/utils/compiler.js
+++ b/src/js/utils/compiler.js
@@ -1,33 +1,33 @@
-import { forEach } from './array-utils';
-import assert from './assert';
+import { forEach } from './array-utils'
+import assert from './assert'
export function visit(visitor, node, opcodes) {
- const method = node.type;
- assert(`Cannot visit unknown type ${method}`, !!visitor[method]);
- visitor[method](node, opcodes);
+ const method = node.type
+ assert(`Cannot visit unknown type ${method}`, !!visitor[method])
+ visitor[method](node, opcodes)
}
export function compile(compiler, opcodes) {
- for (var i=0, l=opcodes.length; i {
- visit(visitor, node, opcodes);
- });
+ visit(visitor, node, opcodes)
+ })
}
diff --git a/src/js/utils/copy.js b/src/js/utils/copy.js
index a5005b4ad..3a28e9023 100644
--- a/src/js/utils/copy.js
+++ b/src/js/utils/copy.js
@@ -1,11 +1,9 @@
function shallowCopyObject(object) {
- let copy = {};
+ let copy = {}
Object.keys(object).forEach(key => {
- copy[key] = object[key];
- });
- return copy;
+ copy[key] = object[key]
+ })
+ return copy
}
-export {
- shallowCopyObject
-};
+export { shallowCopyObject }
diff --git a/src/js/utils/cursor.js b/src/js/utils/cursor.js
index 15d3d145a..858f8c4bd 100644
--- a/src/js/utils/cursor.js
+++ b/src/js/utils/cursor.js
@@ -1,24 +1,21 @@
-import {
- clearSelection,
- comparePosition
-} from '../utils/selection-utils';
-import { containsNode } from '../utils/dom-utils';
-import Position from './cursor/position';
-import Range from './cursor/range';
-import { DIRECTION } from '../utils/key';
-import { constrainSelectionTo } from '../utils/selection-utils';
-
-export { Position, Range };
+import { clearSelection, comparePosition } from '../utils/selection-utils'
+import { containsNode } from '../utils/dom-utils'
+import Position from './cursor/position'
+import Range from './cursor/range'
+import { DIRECTION } from '../utils/key'
+import { constrainSelectionTo } from '../utils/selection-utils'
+
+export { Position, Range }
const Cursor = class Cursor {
constructor(editor) {
- this.editor = editor;
- this.renderTree = editor._renderTree;
- this.post = editor.post;
+ this.editor = editor
+ this.renderTree = editor._renderTree
+ this.post = editor.post
}
clearSelection() {
- clearSelection();
+ clearSelection()
}
/**
@@ -26,111 +23,111 @@ const Cursor = class Cursor {
* editor's element or a selection that is contained in the editor's element
*/
hasCursor() {
- return this.editor.hasRendered &&
- (this._hasCollapsedSelection() || this._hasSelection());
+ return this.editor.hasRendered && (this._hasCollapsedSelection() || this._hasSelection())
}
hasSelection() {
- return this.editor.hasRendered &&
- this._hasSelection();
+ return this.editor.hasRendered && this._hasSelection()
}
/**
* @return {Boolean} Can the cursor be on this element?
*/
isAddressable(element) {
- let { renderTree } = this;
- let renderNode = renderTree.findRenderNodeFromElement(element);
+ let { renderTree } = this
+ let renderNode = renderTree.findRenderNodeFromElement(element)
if (renderNode && renderNode.postNode.isCardSection) {
- let renderedElement = renderNode.element;
+ let renderedElement = renderNode.element
// card sections have addressable text nodes containing
// as their first and last child
- if (element !== renderedElement &&
- element !== renderedElement.firstChild &&
- element !== renderedElement.lastChild) {
- return false;
+ if (
+ element !== renderedElement &&
+ element !== renderedElement.firstChild &&
+ element !== renderedElement.lastChild
+ ) {
+ return false
}
}
- return !!renderNode;
+ return !!renderNode
}
/*
* @return {Range} Cursor#Range object
*/
get offsets() {
- if (!this.hasCursor()) { return Range.blankRange(); }
+ if (!this.hasCursor()) {
+ return Range.blankRange()
+ }
- let { selection, renderTree } = this;
- let parentNode = this.editor.element;
- selection = constrainSelectionTo(selection, parentNode);
+ let { selection, renderTree } = this
+ let parentNode = this.editor.element
+ selection = constrainSelectionTo(selection, parentNode)
- const {
- headNode, headOffset, tailNode, tailOffset, direction
- } = comparePosition(selection);
+ const { headNode, headOffset, tailNode, tailOffset, direction } = comparePosition(selection)
- const headPosition = Position.fromNode(renderTree, headNode, headOffset);
- const tailPosition = Position.fromNode(renderTree, tailNode, tailOffset);
+ const headPosition = Position.fromNode(renderTree, headNode, headOffset)
+ const tailPosition = Position.fromNode(renderTree, tailNode, tailOffset)
- return new Range(headPosition, tailPosition, direction);
+ return new Range(headPosition, tailPosition, direction)
}
_findNodeForPosition(position) {
- let { section } = position;
- let node, offset;
+ let { section } = position
+ let node, offset
if (section.isCardSection) {
- offset = 0;
+ offset = 0
if (position.offset === 0) {
- node = section.renderNode.element.firstChild;
+ node = section.renderNode.element.firstChild
} else {
- node = section.renderNode.element.lastChild;
+ node = section.renderNode.element.lastChild
}
} else if (section.isBlank) {
- node = section.renderNode.cursorElement;
- offset = 0;
+ node = section.renderNode.cursorElement
+ offset = 0
} else {
- let {marker, offsetInMarker} = position;
+ let { marker, offsetInMarker } = position
if (marker.isAtom) {
if (offsetInMarker > 0) {
// FIXME -- if there is a next marker, focus on it?
- offset = 0;
- node = marker.renderNode.tailTextNode;
+ offset = 0
+ node = marker.renderNode.tailTextNode
} else {
- offset = 0;
- node = marker.renderNode.headTextNode;
+ offset = 0
+ node = marker.renderNode.headTextNode
}
} else {
- node = marker.renderNode.element;
- offset = offsetInMarker;
+ node = marker.renderNode.element
+ offset = offsetInMarker
}
}
- return {node, offset};
+ return { node, offset }
}
selectRange(range) {
if (range.isBlank) {
- this.clearSelection();
- return;
+ this.clearSelection()
+ return
}
- const { head, tail, direction } = range;
- const { node:headNode, offset:headOffset } = this._findNodeForPosition(head),
- { node:tailNode, offset:tailOffset } = this._findNodeForPosition(tail);
- this._moveToNode(headNode, headOffset, tailNode, tailOffset, direction);
+ const { head, tail, direction } = range
+ const { node: headNode, offset: headOffset } = this._findNodeForPosition(head),
+ { node: tailNode, offset: tailOffset } = this._findNodeForPosition(tail)
+ this._moveToNode(headNode, headOffset, tailNode, tailOffset, direction)
// Firefox sometimes doesn't keep focus in the editor after adding a card
- this.editor._ensureFocus();
+ this.editor._ensureFocus()
}
get selection() {
- return window.getSelection();
+ return window.getSelection()
}
selectedText() {
// FIXME remove this
- return this.selection.toString();
+ return this.selection.toString()
}
/**
@@ -141,46 +138,51 @@ const Cursor = class Cursor {
* @param {integer} direction forward or backward, default forward
* @private
*/
- _moveToNode(node, offset, endNode, endOffset, direction=DIRECTION.FORWARD) {
- this.clearSelection();
+ _moveToNode(node, offset, endNode, endOffset, direction = DIRECTION.FORWARD) {
+ this.clearSelection()
if (direction === DIRECTION.BACKWARD) {
- [node, offset, endNode, endOffset] = [ endNode, endOffset, node, offset ];
+ ;[node, offset, endNode, endOffset] = [endNode, endOffset, node, offset]
}
- const range = document.createRange();
- range.setStart(node, offset);
+ const range = document.createRange()
+ range.setStart(node, offset)
if (direction === DIRECTION.BACKWARD && !!this.selection.extend) {
- this.selection.addRange(range);
- this.selection.extend(endNode, endOffset);
+ this.selection.addRange(range)
+ this.selection.extend(endNode, endOffset)
} else {
- range.setEnd(endNode, endOffset);
- this.selection.addRange(range);
+ range.setEnd(endNode, endOffset)
+ this.selection.addRange(range)
}
}
_hasSelection() {
- const element = this.editor.element;
- const { _selectionRange } = this;
- if (!_selectionRange || _selectionRange.collapsed) { return false; }
+ const element = this.editor.element
+ const { _selectionRange } = this
+ if (!_selectionRange || _selectionRange.collapsed) {
+ return false
+ }
- return containsNode(element, this.selection.anchorNode) &&
- containsNode(element, this.selection.focusNode);
+ return containsNode(element, this.selection.anchorNode) && containsNode(element, this.selection.focusNode)
}
_hasCollapsedSelection() {
- const { _selectionRange } = this;
- if (!_selectionRange) { return false; }
+ const { _selectionRange } = this
+ if (!_selectionRange) {
+ return false
+ }
- const element = this.editor.element;
- return containsNode(element, this.selection.anchorNode);
+ const element = this.editor.element
+ return containsNode(element, this.selection.anchorNode)
}
get _selectionRange() {
- const { selection } = this;
- if (selection.rangeCount === 0) { return null; }
- return selection.getRangeAt(0);
+ const { selection } = this
+ if (selection.rangeCount === 0) {
+ return null
+ }
+ return selection.getRangeAt(0)
}
-};
+}
-export default Cursor;
+export default Cursor
diff --git a/src/js/utils/cursor/position.js b/src/js/utils/cursor/position.js
index 14847c0b1..bff47ac76 100644
--- a/src/js/utils/cursor/position.js
+++ b/src/js/utils/cursor/position.js
@@ -1,68 +1,61 @@
-import { isTextNode } from 'mobiledoc-kit/utils/dom-utils';
-import assert from 'mobiledoc-kit/utils/assert';
-import {
- HIGH_SURROGATE_RANGE,
- LOW_SURROGATE_RANGE
-} from 'mobiledoc-kit/models/marker';
-import { containsNode } from 'mobiledoc-kit/utils/dom-utils';
-import { findOffsetInNode } from 'mobiledoc-kit/utils/selection-utils';
-import { DIRECTION } from 'mobiledoc-kit/utils/key';
-import Range from './range';
-
-const { FORWARD, BACKWARD } = DIRECTION;
+import { isTextNode } from 'mobiledoc-kit/utils/dom-utils'
+import assert from 'mobiledoc-kit/utils/assert'
+import { HIGH_SURROGATE_RANGE, LOW_SURROGATE_RANGE } from 'mobiledoc-kit/models/marker'
+import { containsNode } from 'mobiledoc-kit/utils/dom-utils'
+import { findOffsetInNode } from 'mobiledoc-kit/utils/selection-utils'
+import { DIRECTION } from 'mobiledoc-kit/utils/key'
+import Range from './range'
+
+const { FORWARD, BACKWARD } = DIRECTION
// generated via http://xregexp.com/ to cover chars that \w misses
// (new XRegExp('\\p{Alphabetic}|[0-9]|_|:')).toString()
-const WORD_CHAR_REGEX = /[A-Za-zªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͅͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևְ-ׇֽֿׁׂׅׄא-תװ-ײؐ-ؚؠ-ٗٙ-ٟٮ-ۓە-ۜۡ-ۭۨ-ۯۺ-ۼۿܐ-ܿݍ-ޱߊ-ߪߴߵߺࠀ-ࠗࠚ-ࠬࡀ-ࡘࢠ-ࢴࣣ-ࣰࣩ-ऻऽ-ौॎ-ॐॕ-ॣॱ-ঃঅ-ঌএঐও-নপ-রলশ-হঽ-ৄেৈোৌৎৗড়ঢ়য়-ৣৰৱਁ-ਃਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਾ-ੂੇੈੋੌੑਖ਼-ੜਫ਼ੰ-ੵઁ-ઃઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽ-ૅે-ૉોૌૐૠ-ૣૹଁ-ଃଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽ-ୄେୈୋୌୖୗଡ଼ଢ଼ୟ-ୣୱஂஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹா-ூெ-ைொ-ௌௐௗఀ-ఃఅ-ఌఎ-ఐఒ-నప-హఽ-ౄె-ైొ-ౌౕౖౘ-ౚౠ-ౣಁ-ಃಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ೄೆ-ೈೊ-ೌೕೖೞೠ-ೣೱೲഁ-ഃഅ-ഌഎ-ഐഒ-ഺഽ-ൄെ-ൈൊ-ൌൎൗൟ-ൣൺ-ൿංඃඅ-ඖක-නඳ-රලව-ෆා-ුූෘ-ෟෲෳก-ฺเ-ๆํກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ູົ-ຽເ-ໄໆໍໜ-ໟༀཀ-ཇཉ-ཬཱ-ཱྀྈ-ྗྙ-ྼက-ံးျ-ဿၐ-ၢၥ-ၨၮ-ႆႎႜႝႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚ፟ᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜓᜠ-ᜳᝀ-ᝓᝠ-ᝬᝮ-ᝰᝲᝳក-ឳា-ៈៗៜᠠ-ᡷᢀ-ᢪᢰ-ᣵᤀ-ᤞᤠ-ᤫᤰ-ᤸᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨛᨠ-ᩞᩡ-ᩴᪧᬀ-ᬳᬵ-ᭃᭅ-ᭋᮀ-ᮩᮬ-ᮯᮺ-ᯥᯧ-ᯱᰀ-ᰵᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳳᳵᳶᴀ-ᶿᷧ-ᷴḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⒶ-ⓩⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⷠ-ⷿⸯ々-〇〡-〩〱-〵〸-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙴ-ꙻꙿ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠧꡀ-ꡳꢀ-ꣃꣲ-ꣷꣻꣽꤊ-ꤪꤰ-ꥒꥠ-ꥼꦀ-ꦲꦴ-ꦿꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨶꩀ-ꩍꩠ-ꩶꩺꩾ-ꪾꫀꫂꫛ-ꫝꫠ-ꫯꫲ-ꫵꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯪ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ]|[0-9]|_|:/;
+const WORD_CHAR_REGEX = /[A-Za-zªµºÀ-ÖØ-öø-ˁˆ-ˑˠ-ˤˬˮͅͰ-ʹͶͷͺ-ͽͿΆΈ-ΊΌΎ-ΡΣ-ϵϷ-ҁҊ-ԯԱ-Ֆՙա-ևְ-ׇֽֿׁׂׅׄא-תװ-ײؐ-ؚؠ-ٗٙ-ٟٮ-ۓە-ۜۡ-ۭۨ-ۯۺ-ۼۿܐ-ܿݍ-ޱߊ-ߪߴߵߺࠀ-ࠗࠚ-ࠬࡀ-ࡘࢠ-ࢴࣣ-ࣰࣩ-ऻऽ-ौॎ-ॐॕ-ॣॱ-ঃঅ-ঌএঐও-নপ-রলশ-হঽ-ৄেৈোৌৎৗড়ঢ়য়-ৣৰৱਁ-ਃਅ-ਊਏਐਓ-ਨਪ-ਰਲਲ਼ਵਸ਼ਸਹਾ-ੂੇੈੋੌੑਖ਼-ੜਫ਼ੰ-ੵઁ-ઃઅ-ઍએ-ઑઓ-નપ-રલળવ-હઽ-ૅે-ૉોૌૐૠ-ૣૹଁ-ଃଅ-ଌଏଐଓ-ନପ-ରଲଳଵ-ହଽ-ୄେୈୋୌୖୗଡ଼ଢ଼ୟ-ୣୱஂஃஅ-ஊஎ-ஐஒ-கஙசஜஞடணதந-பம-ஹா-ூெ-ைொ-ௌௐௗఀ-ఃఅ-ఌఎ-ఐఒ-నప-హఽ-ౄె-ైొ-ౌౕౖౘ-ౚౠ-ౣಁ-ಃಅ-ಌಎ-ಐಒ-ನಪ-ಳವ-ಹಽ-ೄೆ-ೈೊ-ೌೕೖೞೠ-ೣೱೲഁ-ഃഅ-ഌഎ-ഐഒ-ഺഽ-ൄെ-ൈൊ-ൌൎൗൟ-ൣൺ-ൿංඃඅ-ඖක-නඳ-රලව-ෆා-ුූෘ-ෟෲෳก-ฺเ-ๆํກຂຄງຈຊຍດ-ທນ-ຟມ-ຣລວສຫອ-ູົ-ຽເ-ໄໆໍໜ-ໟༀཀ-ཇཉ-ཬཱ-ཱྀྈ-ྗྙ-ྼက-ံးျ-ဿၐ-ၢၥ-ၨၮ-ႆႎႜႝႠ-ჅჇჍა-ჺჼ-ቈቊ-ቍቐ-ቖቘቚ-ቝበ-ኈኊ-ኍነ-ኰኲ-ኵኸ-ኾዀዂ-ዅወ-ዖዘ-ጐጒ-ጕጘ-ፚ፟ᎀ-ᎏᎠ-Ᏽᏸ-ᏽᐁ-ᙬᙯ-ᙿᚁ-ᚚᚠ-ᛪᛮ-ᛸᜀ-ᜌᜎ-ᜓᜠ-ᜳᝀ-ᝓᝠ-ᝬᝮ-ᝰᝲᝳក-ឳា-ៈៗៜᠠ-ᡷᢀ-ᢪᢰ-ᣵᤀ-ᤞᤠ-ᤫᤰ-ᤸᥐ-ᥭᥰ-ᥴᦀ-ᦫᦰ-ᧉᨀ-ᨛᨠ-ᩞᩡ-ᩴᪧᬀ-ᬳᬵ-ᭃᭅ-ᭋᮀ-ᮩᮬ-ᮯᮺ-ᯥᯧ-ᯱᰀ-ᰵᱍ-ᱏᱚ-ᱽᳩ-ᳬᳮ-ᳳᳵᳶᴀ-ᶿᷧ-ᷴḀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼιῂ-ῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲ-ῴῶ-ῼⁱⁿₐ-ₜℂℇℊ-ℓℕℙ-ℝℤΩℨK-ℭℯ-ℹℼ-ℿⅅ-ⅉⅎⅠ-ↈⒶ-ⓩⰀ-Ⱞⰰ-ⱞⱠ-ⳤⳫ-ⳮⳲⳳⴀ-ⴥⴧⴭⴰ-ⵧⵯⶀ-ⶖⶠ-ⶦⶨ-ⶮⶰ-ⶶⶸ-ⶾⷀ-ⷆⷈ-ⷎⷐ-ⷖⷘ-ⷞⷠ-ⷿⸯ々-〇〡-〩〱-〵〸-〼ぁ-ゖゝ-ゟァ-ヺー-ヿㄅ-ㄭㄱ-ㆎㆠ-ㆺㇰ-ㇿ㐀-䶵一-鿕ꀀ-ꒌꓐ-ꓽꔀ-ꘌꘐ-ꘟꘪꘫꙀ-ꙮꙴ-ꙻꙿ-ꛯꜗ-ꜟꜢ-ꞈꞋ-ꞭꞰ-ꞷꟷ-ꠁꠃ-ꠅꠇ-ꠊꠌ-ꠧꡀ-ꡳꢀ-ꣃꣲ-ꣷꣻꣽꤊ-ꤪꤰ-ꥒꥠ-ꥼꦀ-ꦲꦴ-ꦿꧏꧠ-ꧤꧦ-ꧯꧺ-ꧾꨀ-ꨶꩀ-ꩍꩠ-ꩶꩺꩾ-ꪾꫀꫂꫛ-ꫝꫠ-ꫯꫲ-ꫵꬁ-ꬆꬉ-ꬎꬑ-ꬖꬠ-ꬦꬨ-ꬮꬰ-ꭚꭜ-ꭥꭰ-ꯪ가-힣ힰ-ퟆퟋ-ퟻ豈-舘並-龎ff-stﬓ-ﬗיִ-ﬨשׁ-זּטּ-לּמּנּסּףּפּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-ﷻﹰ-ﹴﹶ-ﻼA-Za-zヲ-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ]|[0-9]|_|:/
function findParentSectionFromNode(renderTree, node) {
- let renderNode = renderTree.findRenderNodeFromElement(
- node,
- (renderNode) => renderNode.postNode.isSection
- );
+ let renderNode = renderTree.findRenderNodeFromElement(node, renderNode => renderNode.postNode.isSection)
- return renderNode && renderNode.postNode;
+ return renderNode && renderNode.postNode
}
function findOffsetInMarkerable(markerable, node, offset) {
- let offsetInSection = 0;
- let marker = markerable.markers.head;
+ let offsetInSection = 0
+ let marker = markerable.markers.head
while (marker) {
- let markerNode = marker.renderNode.element;
+ let markerNode = marker.renderNode.element
if (markerNode === node) {
- return offsetInSection + offset;
+ return offsetInSection + offset
} else if (marker.isAtom) {
if (marker.renderNode.headTextNode === node) {
- return offsetInSection;
+ return offsetInSection
} else if (marker.renderNode.tailTextNode === node) {
- return offsetInSection + 1;
+ return offsetInSection + 1
}
}
- offsetInSection += marker.length;
- marker = marker.next;
+ offsetInSection += marker.length
+ marker = marker.next
}
- return offsetInSection;
+ return offsetInSection
}
function findOffsetInSection(section, node, offset) {
if (section.isMarkerable) {
- return findOffsetInMarkerable(section, node, offset);
+ return findOffsetInMarkerable(section, node, offset)
} else {
- assert('findOffsetInSection must be called with markerable or card section',
- section.isCardSection);
+ assert('findOffsetInSection must be called with markerable or card section', section.isCardSection)
- let wrapperNode = section.renderNode.element;
- let endTextNode = wrapperNode.lastChild;
+ let wrapperNode = section.renderNode.element
+ let endTextNode = wrapperNode.lastChild
if (node === endTextNode) {
- return 1;
+ return 1
}
- return 0;
+ return 0
}
}
-let Position, BlankPosition;
+let Position, BlankPosition
Position = class Position {
/**
@@ -71,17 +64,15 @@ Position = class Position {
* Two positions (a head and a tail) make up a {@link Range}.
* @constructor
*/
- constructor(section, offset=0, isBlank=false) {
+ constructor(section, offset = 0, isBlank = false) {
if (!isBlank) {
- assert('Position must have a section that is addressable by the cursor',
- (section && section.isLeafSection));
- assert('Position must have numeric offset',
- (typeof offset === 'number'));
+ assert('Position must have a section that is addressable by the cursor', section && section.isLeafSection)
+ assert('Position must have numeric offset', typeof offset === 'number')
}
- this.section = section;
- this.offset = offset;
- this.isBlank = isBlank;
+ this.section = section
+ this.offset = offset
+ this.isBlank = isBlank
}
/**
@@ -91,18 +82,18 @@ Position = class Position {
* @return {Position|null}
*/
static atPoint(x, y, editor) {
- let { _renderTree, element: rootElement } = editor;
- let elementFromPoint = document.elementFromPoint(x, y);
+ let { _renderTree, element: rootElement } = editor
+ let elementFromPoint = document.elementFromPoint(x, y)
if (!containsNode(rootElement, elementFromPoint)) {
- return;
+ return
}
- let { node, offset } = findOffsetInNode(elementFromPoint, {left: x, top: y});
- return Position.fromNode(_renderTree, node, offset);
+ let { node, offset } = findOffsetInNode(elementFromPoint, { left: x, top: y })
+ return Position.fromNode(_renderTree, node, offset)
}
static blankPosition() {
- return new BlankPosition();
+ return new BlankPosition()
}
/**
@@ -112,23 +103,23 @@ Position = class Position {
* @return {Range}
* @public
*/
- toRange(tail=this, direction=null) {
- return new Range(this, tail, direction);
+ toRange(tail = this, direction = null) {
+ return new Range(this, tail, direction)
}
get leafSectionIndex() {
- let post = this.section.post;
- let leafSectionIndex;
+ let post = this.section.post
+ let leafSectionIndex
post.walkAllLeafSections((section, index) => {
if (section === this.section) {
- leafSectionIndex = index;
+ leafSectionIndex = index
}
- });
- return leafSectionIndex;
+ })
+ return leafSectionIndex
}
get isMarkerable() {
- return this.section && this.section.isMarkerable;
+ return this.section && this.section.isMarkerable
}
/**
@@ -137,7 +128,7 @@ Position = class Position {
* @return {Marker|undefined}
*/
get marker() {
- return this.isMarkerable && this.markerPosition.marker;
+ return this.isMarkerable && this.markerPosition.marker
}
/**
@@ -150,55 +141,58 @@ Position = class Position {
* @return {Marker|undefined}
*/
markerIn(direction) {
- if (!this.isMarkerable) { return; }
+ if (!this.isMarkerable) {
+ return
+ }
- let { marker, offsetInMarker } = this;
- if (!marker) { return; }
+ let { marker, offsetInMarker } = this
+ if (!marker) {
+ return
+ }
if (offsetInMarker > 0 && offsetInMarker < marker.length) {
- return marker;
+ return marker
} else if (offsetInMarker === 0) {
- return direction === BACKWARD ? marker : marker.prev;
+ return direction === BACKWARD ? marker : marker.prev
} else if (offsetInMarker === marker.length) {
- return direction === FORWARD ? marker.next : marker;
+ return direction === FORWARD ? marker.next : marker
}
}
get offsetInMarker() {
- return this.markerPosition.offset;
+ return this.markerPosition.offset
}
isEqual(position) {
- return this.section === position.section &&
- this.offset === position.offset;
+ return this.section === position.section && this.offset === position.offset
}
/**
* @return {Boolean} If this position is at the head of the post
*/
isHeadOfPost() {
- return this.move(BACKWARD).isEqual(this);
+ return this.move(BACKWARD).isEqual(this)
}
/**
* @return {Boolean} If this position is at the tail of the post
*/
isTailOfPost() {
- return this.move(FORWARD).isEqual(this);
+ return this.move(FORWARD).isEqual(this)
}
/**
* @return {Boolean} If this position is at the head of its section
*/
isHead() {
- return this.isEqual(this.section.headPosition());
+ return this.isEqual(this.section.headPosition())
}
/**
* @return {Boolean} If this position is at the tail of its section
*/
isTail() {
- return this.isEqual(this.section.tailPosition());
+ return this.isEqual(this.section.tailPosition())
}
/**
@@ -211,14 +205,14 @@ Position = class Position {
* at the end of the post.
*/
move(units) {
- assert('Must pass integer to Position#move', typeof units === 'number');
+ assert('Must pass integer to Position#move', typeof units === 'number')
if (units < 0) {
- return this.moveLeft().move(++units);
+ return this.moveLeft().move(++units)
} else if (units > 0) {
- return this.moveRight().move(--units);
+ return this.moveRight().move(--units)
} else {
- return this;
+ return this
}
}
@@ -227,72 +221,68 @@ Position = class Position {
* @return {Position} The result of moving 1 "word" unit in `direction`
*/
moveWord(direction) {
- let isPostBoundary = direction === BACKWARD ? this.isHeadOfPost() : this.isTailOfPost();
+ let isPostBoundary = direction === BACKWARD ? this.isHeadOfPost() : this.isTailOfPost()
if (isPostBoundary) {
- return this;
+ return this
}
if (!this.isMarkerable) {
- return this.move(direction);
+ return this.move(direction)
}
- let pos = this;
+ let pos = this
// Helper fn to check if the pos is at the `dir` boundary of its section
let isBoundary = (pos, dir) => {
- return dir === BACKWARD ? pos.isHead() : pos.isTail();
- };
+ return dir === BACKWARD ? pos.isHead() : pos.isTail()
+ }
// Get the char at this position (looking forward/right)
- let getChar = (pos) => {
- let { marker, offsetInMarker } = pos;
- return marker.charAt(offsetInMarker);
- };
+ let getChar = pos => {
+ let { marker, offsetInMarker } = pos
+ return marker.charAt(offsetInMarker)
+ }
// Get the char in `dir` at this position
let peekChar = (pos, dir) => {
- return dir === BACKWARD ? getChar(pos.move(BACKWARD)) : getChar(pos);
- };
+ return dir === BACKWARD ? getChar(pos.move(BACKWARD)) : getChar(pos)
+ }
// Whether there is an atom in `dir` from this position
let isAtom = (pos, dir) => {
// Special case when position is at end, the marker associated with it is
// the marker to its left. Normally `pos#marker` is the marker to the right of the pos's offset.
if (dir === BACKWARD && pos.isTail() && pos.marker.isAtom) {
- return true;
+ return true
}
- return dir === BACKWARD ? pos.move(BACKWARD).marker.isAtom : pos.marker.isAtom;
- };
+ return dir === BACKWARD ? pos.move(BACKWARD).marker.isAtom : pos.marker.isAtom
+ }
if (isBoundary(pos, direction)) {
// extend movement into prev/next section
- return pos.move(direction).moveWord(direction);
+ return pos.move(direction).moveWord(direction)
}
- let seekWord = (pos) => {
- return !isBoundary(pos, direction) &&
- !isAtom(pos, direction) &&
- !WORD_CHAR_REGEX.test(peekChar(pos, direction));
- };
+ let seekWord = pos => {
+ return !isBoundary(pos, direction) && !isAtom(pos, direction) && !WORD_CHAR_REGEX.test(peekChar(pos, direction))
+ }
// move(dir) while we are seeking the first word char
while (seekWord(pos)) {
- pos = pos.move(direction);
+ pos = pos.move(direction)
}
if (isAtom(pos, direction)) {
- return pos.move(direction);
+ return pos.move(direction)
}
- let seekBoundary = (pos) => {
- return !isBoundary(pos, direction) &&
- !isAtom(pos, direction) &&
- WORD_CHAR_REGEX.test(peekChar(pos, direction));
- };
+ let seekBoundary = pos => {
+ return !isBoundary(pos, direction) && !isAtom(pos, direction) && WORD_CHAR_REGEX.test(peekChar(pos, direction))
+ }
// move(dir) while we are seeking the first boundary position
while (seekBoundary(pos)) {
- pos = pos.move(direction);
+ pos = pos.move(direction)
}
- return pos;
+ return pos
}
/**
@@ -303,17 +293,17 @@ Position = class Position {
*/
moveLeft() {
if (this.isHead()) {
- let prev = this.section.previousLeafSection();
- return prev ? prev.tailPosition() : this;
+ let prev = this.section.previousLeafSection()
+ return prev ? prev.tailPosition() : this
} else {
- let offset = this.offset - 1;
+ let offset = this.offset - 1
if (this.isMarkerable && this.marker) {
- let code = this.marker.value.charCodeAt(offset);
+ let code = this.marker.value.charCodeAt(offset)
if (code >= LOW_SURROGATE_RANGE[0] && code <= LOW_SURROGATE_RANGE[1]) {
- offset = offset - 1;
+ offset = offset - 1
}
}
- return new Position(this.section, offset);
+ return new Position(this.section, offset)
}
}
@@ -325,66 +315,64 @@ Position = class Position {
*/
moveRight() {
if (this.isTail()) {
- let next = this.section.nextLeafSection();
- return next ? next.headPosition() : this;
+ let next = this.section.nextLeafSection()
+ return next ? next.headPosition() : this
} else {
- let offset = this.offset + 1;
+ let offset = this.offset + 1
if (this.isMarkerable && this.marker) {
- let code = this.marker.value.charCodeAt(offset - 1);
+ let code = this.marker.value.charCodeAt(offset - 1)
if (code >= HIGH_SURROGATE_RANGE[0] && code <= HIGH_SURROGATE_RANGE[1]) {
- offset = offset + 1;
+ offset = offset + 1
}
}
- return new Position(this.section, offset);
+ return new Position(this.section, offset)
}
}
static fromNode(renderTree, node, offset) {
if (isTextNode(node)) {
- return Position.fromTextNode(renderTree, node, offset);
+ return Position.fromTextNode(renderTree, node, offset)
} else {
- return Position.fromElementNode(renderTree, node, offset);
+ return Position.fromElementNode(renderTree, node, offset)
}
}
static fromTextNode(renderTree, textNode, offsetInNode) {
- const renderNode = renderTree.getElementRenderNode(textNode);
- let section, offsetInSection;
+ const renderNode = renderTree.getElementRenderNode(textNode)
+ let section, offsetInSection
if (renderNode) {
- const marker = renderNode.postNode;
- section = marker.section;
+ const marker = renderNode.postNode
+ section = marker.section
- assert(`Could not find parent section for mapped text node "${textNode.textContent}"`,
- !!section);
- offsetInSection = section.offsetOfMarker(marker, offsetInNode);
+ assert(`Could not find parent section for mapped text node "${textNode.textContent}"`, !!section)
+ offsetInSection = section.offsetOfMarker(marker, offsetInNode)
} else {
// all text nodes should be rendered by markers except:
// * text nodes inside cards
// * text nodes created by the browser during text input
// both of these should have rendered parent sections, though
- section = findParentSectionFromNode(renderTree, textNode);
- assert(`Could not find parent section for un-mapped text node "${textNode.textContent}"`,
- !!section);
+ section = findParentSectionFromNode(renderTree, textNode)
+ assert(`Could not find parent section for un-mapped text node "${textNode.textContent}"`, !!section)
- offsetInSection = findOffsetInSection(section, textNode, offsetInNode);
+ offsetInSection = findOffsetInSection(section, textNode, offsetInNode)
}
- return new Position(section, offsetInSection);
+ return new Position(section, offsetInSection)
}
static fromElementNode(renderTree, elementNode, offset) {
- let position;
+ let position
// The browser may change the reported selection to equal the editor's root
// element if the user clicks an element that is immediately removed,
// which can happen when clicking to remove a card.
if (elementNode === renderTree.rootElement) {
- let post = renderTree.rootNode.postNode;
- position = offset === 0 ? post.headPosition() : post.tailPosition();
+ let post = renderTree.rootNode.postNode
+ position = offset === 0 ? post.headPosition() : post.tailPosition()
} else {
- let section = findParentSectionFromNode(renderTree, elementNode);
- assert('Could not find parent section from element node', !!section);
+ let section = findParentSectionFromNode(renderTree, elementNode)
+ assert('Could not find parent section from element node', !!section)
if (section.isCardSection) {
// Selections in cards are usually made on a text node
@@ -394,72 +382,92 @@ Position = class Position {
// the final zwnj and should consider the cursor at the
// end of the card (offset 1). Otherwise, the cursor is at
// the start of the card
- position = offset < 2 ? section.headPosition() : section.tailPosition();
+ position = offset < 2 ? section.headPosition() : section.tailPosition()
} else {
-
// In Firefox it is possible for the cursor to be on an atom's wrapper
// element. (In Chrome/Safari, the browser corrects this to be on
// one of the text nodes surrounding the wrapper).
// This code corrects for when the browser reports the cursor position
// to be on the wrapper element itself
- let renderNode = renderTree.getElementRenderNode(elementNode);
- let postNode = renderNode && renderNode.postNode;
+ let renderNode = renderTree.getElementRenderNode(elementNode)
+ let postNode = renderNode && renderNode.postNode
if (postNode && postNode.isAtom) {
- let sectionOffset = section.offsetOfMarker(postNode);
+ let sectionOffset = section.offsetOfMarker(postNode)
if (offset > 1) {
// we are on the tail side of the atom
- sectionOffset += postNode.length;
+ sectionOffset += postNode.length
}
- position = new Position(section, sectionOffset);
+ position = new Position(section, sectionOffset)
} else if (offset >= elementNode.childNodes.length) {
-
// This is to deal with how Firefox handles triple-click selections.
// See https://stackoverflow.com/a/21234837/1269194 for an
// explanation.
- position = section.tailPosition();
+ position = section.tailPosition()
} else {
// The offset is 0 if the cursor is on a non-atom-wrapper element node
// (e.g., a
tag in a blank markup section)
- position = section.headPosition();
+ position = section.headPosition()
}
}
}
- return position;
+ return position
}
/**
* @private
*/
get markerPosition() {
- assert('Cannot get markerPosition without a section', !!this.section);
- assert('cannot get markerPosition of a non-markerable', !!this.section.isMarkerable);
- return this.section.markerPositionAtOffset(this.offset);
+ assert('Cannot get markerPosition without a section', !!this.section)
+ assert('cannot get markerPosition of a non-markerable', !!this.section.isMarkerable)
+ return this.section.markerPositionAtOffset(this.offset)
}
-};
+}
BlankPosition = class BlankPosition extends Position {
constructor() {
- super(null, 0, true);
+ super(null, 0, true)
}
isEqual(other) {
- return other && other.isBlank;
+ return other && other.isBlank
}
- toRange() { return Range.blankRange(); }
- get leafSectionIndex() { assert('must implement get leafSectionIndex', false); }
+ toRange() {
+ return Range.blankRange()
+ }
+ get leafSectionIndex() {
+ assert('must implement get leafSectionIndex', false)
+ }
- get isMarkerable() { return false; }
- get marker() { return false; }
- isHeadOfPost() { return false; }
- isTailOfPost() { return false; }
- isHead() { return false; }
- isTail() { return false; }
- move() { return this; }
- moveWord() { return this; }
+ get isMarkerable() {
+ return false
+ }
+ get marker() {
+ return false
+ }
+ isHeadOfPost() {
+ return false
+ }
+ isTailOfPost() {
+ return false
+ }
+ isHead() {
+ return false
+ }
+ isTail() {
+ return false
+ }
+ move() {
+ return this
+ }
+ moveWord() {
+ return this
+ }
- get markerPosition() { return {}; }
-};
+ get markerPosition() {
+ return {}
+ }
+}
-export default Position;
+export default Position
diff --git a/src/js/utils/cursor/range.js b/src/js/utils/cursor/range.js
index 00a2726b6..4de098e5d 100644
--- a/src/js/utils/cursor/range.js
+++ b/src/js/utils/cursor/range.js
@@ -1,6 +1,6 @@
-import Position from './position';
-import { DIRECTION } from '../key';
-import assert from 'mobiledoc-kit/utils/assert';
+import Position from './position'
+import { DIRECTION } from '../key'
+import assert from 'mobiledoc-kit/utils/assert'
/**
* A logical range of a {@link Post}.
@@ -15,15 +15,15 @@ class Range {
* @return {Range}
* @private
*/
- constructor(head, tail=head, direction=null) {
+ constructor(head, tail = head, direction = null) {
/** @property {Position} head */
- this.head = head;
+ this.head = head
/** @property {Position} tail */
- this.tail = tail;
+ this.tail = tail
/** @property {Direction} direction */
- this.direction = direction;
+ this.direction = direction
}
/**
@@ -36,16 +36,12 @@ class Range {
* @param {Direction} [direction=null]
* @return {Range}
*/
- static create(headSection, headOffset, tailSection=headSection, tailOffset=headOffset, direction=null) {
- return new Range(
- new Position(headSection, headOffset),
- new Position(tailSection, tailOffset),
- direction
- );
+ static create(headSection, headOffset, tailSection = headSection, tailOffset = headOffset, direction = null) {
+ return new Range(new Position(headSection, headOffset), new Position(tailSection, tailOffset), direction)
}
static blankRange() {
- return new Range(Position.blankPosition(), Position.blankPosition());
+ return new Range(Position.blankPosition(), Position.blankPosition())
}
/**
@@ -59,14 +55,12 @@ class Range {
* @private
*/
trimTo(section) {
- const length = section.length;
+ const length = section.length
- let headOffset = section === this.head.section ?
- Math.min(this.head.offset, length) : 0;
- let tailOffset = section === this.tail.section ?
- Math.min(this.tail.offset, length) : length;
+ let headOffset = section === this.head.section ? Math.min(this.head.offset, length) : 0
+ let tailOffset = section === this.tail.section ? Math.min(this.tail.offset, length) : length
- return Range.create(section, headOffset, section, tailOffset);
+ return Range.create(section, headOffset, section, tailOffset)
}
/**
@@ -79,19 +73,21 @@ class Range {
* @public
*/
extend(units) {
- assert(`Must pass integer to Range#extend`, typeof units === 'number');
+ assert(`Must pass integer to Range#extend`, typeof units === 'number')
- if (units === 0) { return this; }
+ if (units === 0) {
+ return this
+ }
- let { head, tail, direction: currentDirection } = this;
+ let { head, tail, direction: currentDirection } = this
switch (currentDirection) {
case DIRECTION.FORWARD:
- return new Range(head, tail.move(units), currentDirection);
+ return new Range(head, tail.move(units), currentDirection)
case DIRECTION.BACKWARD:
- return new Range(head.move(units), tail, currentDirection);
+ return new Range(head.move(units), tail, currentDirection)
default: {
- let newDirection = units > 0 ? DIRECTION.FORWARD : DIRECTION.BACKWARD;
- return new Range(head, tail, newDirection).extend(units);
+ let newDirection = units > 0 ? DIRECTION.FORWARD : DIRECTION.BACKWARD
+ return new Range(head, tail, newDirection).extend(units)
}
}
}
@@ -106,15 +102,17 @@ class Range {
* @public
*/
move(direction) {
- assert(`Must pass DIRECTION.FORWARD (${DIRECTION.FORWARD}) or DIRECTION.BACKWARD (${DIRECTION.BACKWARD}) to Range#move`,
- direction === DIRECTION.FORWARD || direction === DIRECTION.BACKWARD);
+ assert(
+ `Must pass DIRECTION.FORWARD (${DIRECTION.FORWARD}) or DIRECTION.BACKWARD (${DIRECTION.BACKWARD}) to Range#move`,
+ direction === DIRECTION.FORWARD || direction === DIRECTION.BACKWARD
+ )
- let { focusedPosition, isCollapsed } = this;
+ let { focusedPosition, isCollapsed } = this
if (isCollapsed) {
- return new Range(focusedPosition.move(direction));
+ return new Range(focusedPosition.move(direction))
} else {
- return this._collapse(direction);
+ return this._collapse(direction)
}
}
@@ -127,85 +125,81 @@ class Range {
* @public
*/
expandByMarker(detectMarker) {
- let {
- head,
- tail,
- direction
- } = this;
- let {section: headSection} = head;
+ let { head, tail, direction } = this
+ let { section: headSection } = head
if (headSection !== tail.section) {
- throw new Error('#expandByMarker does not work across sections. Perhaps you should confirm the range is collapsed');
+ throw new Error(
+ '#expandByMarker does not work across sections. Perhaps you should confirm the range is collapsed'
+ )
}
let firstNotMatchingDetect = i => {
- return !detectMarker(i);
- };
+ return !detectMarker(i)
+ }
- let headMarker = headSection.markers.detect(firstNotMatchingDetect, head.marker, true);
+ let headMarker = headSection.markers.detect(firstNotMatchingDetect, head.marker, true)
if (!headMarker && detectMarker(headSection.markers.head)) {
- headMarker = headSection.markers.head;
+ headMarker = headSection.markers.head
} else {
- headMarker = headMarker.next || head.marker;
+ headMarker = headMarker.next || head.marker
}
- let headPosition = new Position(headSection, headSection.offsetOfMarker(headMarker));
+ let headPosition = new Position(headSection, headSection.offsetOfMarker(headMarker))
- let tailMarker = tail.section.markers.detect(firstNotMatchingDetect, tail.marker);
+ let tailMarker = tail.section.markers.detect(firstNotMatchingDetect, tail.marker)
if (!tailMarker && detectMarker(headSection.markers.tail)) {
- tailMarker = headSection.markers.tail;
+ tailMarker = headSection.markers.tail
} else {
- tailMarker = tailMarker.prev || tail.marker;
+ tailMarker = tailMarker.prev || tail.marker
}
- let tailPosition = new Position(tail.section, tail.section.offsetOfMarker(tailMarker) + tailMarker.length);
+ let tailPosition = new Position(tail.section, tail.section.offsetOfMarker(tailMarker) + tailMarker.length)
- return headPosition.toRange(tailPosition, direction);
+ return headPosition.toRange(tailPosition, direction)
}
_collapse(direction) {
- return new Range(direction === DIRECTION.BACKWARD ? this.head : this.tail);
+ return new Range(direction === DIRECTION.BACKWARD ? this.head : this.tail)
}
get focusedPosition() {
- return this.direction === DIRECTION.BACKWARD ? this.head : this.tail;
+ return this.direction === DIRECTION.BACKWARD ? this.head : this.tail
}
isEqual(other) {
- return other &&
- this.head.isEqual(other.head) &&
- this.tail.isEqual(other.tail);
+ return other && this.head.isEqual(other.head) && this.tail.isEqual(other.tail)
}
get isBlank() {
- return this.head.isBlank && this.tail.isBlank;
+ return this.head.isBlank && this.tail.isBlank
}
// "legacy" APIs
get headSection() {
- return this.head.section;
+ return this.head.section
}
get tailSection() {
- return this.tail.section;
+ return this.tail.section
}
get headSectionOffset() {
- return this.head.offset;
+ return this.head.offset
}
get tailSectionOffset() {
- return this.tail.offset;
+ return this.tail.offset
}
get isCollapsed() {
- return this.head.isEqual(this.tail);
+ return this.head.isEqual(this.tail)
}
get headMarker() {
- return this.head.marker;
+ return this.head.marker
}
get tailMarker() {
- return this.tail.marker;
+ return this.tail.marker
}
get headMarkerOffset() {
- return this.head.offsetInMarker;
+ return this.head.offsetInMarker
}
get tailMarkerOffset() {
- return this.tail.offsetInMarker;
+ return this.tail.offsetInMarker
}
}
-export default Range;
+export default Range
diff --git a/src/js/utils/deprecate.js b/src/js/utils/deprecate.js
index e8c2fe35b..11da51f75 100644
--- a/src/js/utils/deprecate.js
+++ b/src/js/utils/deprecate.js
@@ -7,9 +7,9 @@
* conditional is false:
* `deprecate('Deprecated only if foo !== bar', foo === bar)`
*/
-export default function deprecate(message, conditional=false) {
+export default function deprecate(message, conditional = false) {
if (!conditional) {
// eslint-disable-next-line no-console
- console.log(`[mobiledoc-kit] [DEPRECATED]: ${message}`);
+ console.log(`[mobiledoc-kit] [DEPRECATED]: ${message}`)
}
}
diff --git a/src/js/utils/dom-utils.js b/src/js/utils/dom-utils.js
index 0206ed310..34fe21834 100644
--- a/src/js/utils/dom-utils.js
+++ b/src/js/utils/dom-utils.js
@@ -1,49 +1,48 @@
-import { forEach } from './array-utils';
+import { forEach } from './array-utils'
export const NODE_TYPES = {
ELEMENT: 1,
TEXT: 3,
- COMMENT: 8
-};
+ COMMENT: 8,
+}
function isTextNode(node) {
- return node.nodeType === NODE_TYPES.TEXT;
+ return node.nodeType === NODE_TYPES.TEXT
}
function isCommentNode(node) {
- return node.nodeType === NODE_TYPES.COMMENT;
+ return node.nodeType === NODE_TYPES.COMMENT
}
function isElementNode(node) {
- return node.nodeType === NODE_TYPES.ELEMENT;
+ return node.nodeType === NODE_TYPES.ELEMENT
}
// perform a pre-order tree traversal of the dom, calling `callbackFn(node)`
// for every node for which `conditionFn(node)` is true
-function walkDOM(topNode, callbackFn=()=>{}, conditionFn=()=>true) {
- let currentNode = topNode;
+function walkDOM(topNode, callbackFn = () => {}, conditionFn = () => true) {
+ let currentNode = topNode
if (conditionFn(currentNode)) {
- callbackFn(currentNode);
+ callbackFn(currentNode)
}
- currentNode = currentNode.firstChild;
+ currentNode = currentNode.firstChild
while (currentNode) {
- walkDOM(currentNode, callbackFn, conditionFn);
- currentNode = currentNode.nextSibling;
+ walkDOM(currentNode, callbackFn, conditionFn)
+ currentNode = currentNode.nextSibling
}
}
-function walkTextNodes(topNode, callbackFn=()=>{}) {
- const conditionFn = (node) => isTextNode(node);
- walkDOM(topNode, callbackFn, conditionFn);
+function walkTextNodes(topNode, callbackFn = () => {}) {
+ const conditionFn = node => isTextNode(node)
+ walkDOM(topNode, callbackFn, conditionFn)
}
-
function clearChildNodes(element) {
while (element.childNodes.length) {
- element.removeChild(element.childNodes[0]);
+ element.removeChild(element.childNodes[0])
}
}
@@ -56,10 +55,10 @@ function clearChildNodes(element) {
*/
function containsNode(parentNode, childNode) {
if (parentNode === childNode) {
- return true;
+ return true
}
- const position = parentNode.compareDocumentPosition(childNode);
- return !!(position & Node.DOCUMENT_POSITION_CONTAINED_BY);
+ const position = parentNode.compareDocumentPosition(childNode)
+ return !!(position & Node.DOCUMENT_POSITION_CONTAINED_BY)
}
/**
@@ -70,37 +69,37 @@ function containsNode(parentNode, childNode) {
* @private
*/
function getAttributes(element) {
- const result = {};
+ const result = {}
if (element.hasAttributes()) {
- forEach(element.attributes, ({name,value}) => {
- result[name] = value;
- });
+ forEach(element.attributes, ({ name, value }) => {
+ result[name] = value
+ })
}
- return result;
+ return result
}
function addClassName(element, className) {
- element.classList.add(className);
+ element.classList.add(className)
}
function removeClassName(element, className) {
- element.classList.remove(className);
+ element.classList.remove(className)
}
function normalizeTagName(tagName) {
- return tagName.toLowerCase();
+ return tagName.toLowerCase()
}
function parseHTML(html) {
- const div = document.createElement('div');
- div.innerHTML = html;
- return div;
+ const div = document.createElement('div')
+ div.innerHTML = html
+ return div
}
function serializeHTML(node) {
- const div = document.createElement('div');
- div.appendChild(node);
- return div.innerHTML;
+ const div = document.createElement('div')
+ div.appendChild(node)
+ return div.innerHTML
}
export {
@@ -116,5 +115,5 @@ export {
isCommentNode,
isElementNode,
parseHTML,
- serializeHTML
-};
+ serializeHTML,
+}
diff --git a/src/js/utils/element-map.js b/src/js/utils/element-map.js
index f33767b99..36af65133 100644
--- a/src/js/utils/element-map.js
+++ b/src/js/utils/element-map.js
@@ -1,30 +1,29 @@
-import assert from 'mobiledoc-kit/utils/assert';
+import assert from 'mobiledoc-kit/utils/assert'
// start at one to make the falsy semantics easier
-let uuidGenerator = 1;
+let uuidGenerator = 1
class ElementMap {
constructor() {
- this._map = {};
+ this._map = {}
}
set(key, value) {
- let uuid = key._uuid;
+ let uuid = key._uuid
if (!uuid) {
- key._uuid = uuid = '' + uuidGenerator++;
+ key._uuid = uuid = '' + uuidGenerator++
}
- this._map[uuid] = value;
+ this._map[uuid] = value
}
get(key) {
if (key._uuid) {
- return this._map[key._uuid];
+ return this._map[key._uuid]
}
- return null;
+ return null
}
remove(key) {
- assert('tried to fetch a value for an element not seen before', !!key._uuid);
- delete this._map[key._uuid];
+ assert('tried to fetch a value for an element not seen before', !!key._uuid)
+ delete this._map[key._uuid]
}
-
}
-export default ElementMap;
+export default ElementMap
diff --git a/src/js/utils/element-utils.js b/src/js/utils/element-utils.js
index cb0bd8df3..423f885ed 100644
--- a/src/js/utils/element-utils.js
+++ b/src/js/utils/element-utils.js
@@ -1,83 +1,83 @@
-import { dasherize } from 'mobiledoc-kit/utils/string-utils';
-import {
- normalizeTagName
-} from 'mobiledoc-kit/utils/dom-utils';
+import { dasherize } from 'mobiledoc-kit/utils/string-utils'
+import { normalizeTagName } from 'mobiledoc-kit/utils/dom-utils'
function getEventTargetMatchingTag(tagName, target, container) {
- tagName = normalizeTagName(tagName);
+ tagName = normalizeTagName(tagName)
// Traverses up DOM from an event target to find the node matching specifed tag
while (target && target !== container) {
if (normalizeTagName(target.tagName) === tagName) {
- return target;
+ return target
}
- target = target.parentNode;
+ target = target.parentNode
}
}
function getElementRelativeOffset(element) {
- var offset = { left: 0, top: -window.pageYOffset };
- var offsetParent = element.offsetParent;
- var offsetParentPosition = window.getComputedStyle(offsetParent).position;
- var offsetParentRect;
+ var offset = { left: 0, top: -window.pageYOffset }
+ var offsetParent = element.offsetParent
+ var offsetParentPosition = window.getComputedStyle(offsetParent).position
+ var offsetParentRect
if (offsetParentPosition === 'relative') {
- offsetParentRect = offsetParent.getBoundingClientRect();
- offset.left = offsetParentRect.left;
- offset.top = offsetParentRect.top;
+ offsetParentRect = offsetParent.getBoundingClientRect()
+ offset.left = offsetParentRect.left
+ offset.top = offsetParentRect.top
}
- return offset;
+ return offset
}
function getElementComputedStyleNumericProp(element, prop) {
- return parseFloat(window.getComputedStyle(element)[prop]);
+ return parseFloat(window.getComputedStyle(element)[prop])
}
function positionElementToRect(element, rect, topOffset, leftOffset) {
- var relativeOffset = getElementRelativeOffset(element);
- var style = element.style;
- var round = Math.round;
- var left, top;
+ var relativeOffset = getElementRelativeOffset(element)
+ var style = element.style
+ var round = Math.round
+ var left, top
- topOffset = topOffset || 0;
- leftOffset = leftOffset || 0;
- left = round(rect.left - relativeOffset.left - leftOffset);
- top = round(rect.top + rect.height - relativeOffset.top - topOffset);
- style.left = left + 'px';
- style.top = top + 'px';
- return { left: left, top: top };
+ topOffset = topOffset || 0
+ leftOffset = leftOffset || 0
+ left = round(rect.left - relativeOffset.left - leftOffset)
+ top = round(rect.top + rect.height - relativeOffset.top - topOffset)
+ style.left = left + 'px'
+ style.top = top + 'px'
+ return { left: left, top: top }
}
function positionElementHorizontallyCenteredToRect(element, rect, topOffset) {
- var horizontalCenter = (element.offsetWidth / 2) - (rect.width / 2);
- return positionElementToRect(element, rect, topOffset, horizontalCenter);
+ var horizontalCenter = element.offsetWidth / 2 - rect.width / 2
+ return positionElementToRect(element, rect, topOffset, horizontalCenter)
}
function positionElementCenteredBelow(element, belowElement) {
- var elementMargin = getElementComputedStyleNumericProp(element, 'marginTop');
- return positionElementHorizontallyCenteredToRect(element, belowElement.getBoundingClientRect(), -elementMargin);
+ var elementMargin = getElementComputedStyleNumericProp(element, 'marginTop')
+ return positionElementHorizontallyCenteredToRect(element, belowElement.getBoundingClientRect(), -elementMargin)
}
function setData(element, name, value) {
if (element.dataset) {
- element.dataset[name] = value;
+ element.dataset[name] = value
} else {
- const dataName = dasherize(name);
- return element.setAttribute(dataName, value);
+ const dataName = dasherize(name)
+ return element.setAttribute(dataName, value)
}
}
function whenElementIsNotInDOM(element, callback) {
- let isCanceled = false;
+ let isCanceled = false
const observerFn = () => {
- if (isCanceled) { return; }
+ if (isCanceled) {
+ return
+ }
if (!element.parentNode) {
- callback();
+ callback()
} else {
- window.requestAnimationFrame(observerFn);
+ window.requestAnimationFrame(observerFn)
}
- };
- observerFn();
- return { cancel: () => isCanceled = true };
+ }
+ observerFn()
+ return { cancel: () => (isCanceled = true) }
}
export {
@@ -88,5 +88,5 @@ export {
positionElementToRect,
positionElementHorizontallyCenteredToRect,
positionElementCenteredBelow,
- whenElementIsNotInDOM
-};
+ whenElementIsNotInDOM,
+}
diff --git a/src/js/utils/environment.js b/src/js/utils/environment.js
index 157cb8420..66f34fa04 100644
--- a/src/js/utils/environment.js
+++ b/src/js/utils/environment.js
@@ -1,5 +1,5 @@
export default {
hasDOM() {
- return typeof document !== 'undefined';
- }
-};
+ return typeof document !== 'undefined'
+ },
+}
diff --git a/src/js/utils/fixed-queue.js b/src/js/utils/fixed-queue.js
index 287bd6577..2a130b15b 100644
--- a/src/js/utils/fixed-queue.js
+++ b/src/js/utils/fixed-queue.js
@@ -1,29 +1,29 @@
export default class FixedQueue {
- constructor(length=0) {
- this._maxLength = length;
- this._items = [];
+ constructor(length = 0) {
+ this._maxLength = length
+ this._items = []
}
get length() {
- return this._items.length;
+ return this._items.length
}
pop() {
- return this._items.pop();
+ return this._items.pop()
}
push(item) {
- this._items.push(item);
+ this._items.push(item)
if (this.length > this._maxLength) {
- this._items.shift();
+ this._items.shift()
}
}
clear() {
- this._items = [];
+ this._items = []
}
toArray() {
- return this._items;
+ return this._items
}
}
diff --git a/src/js/utils/key.js b/src/js/utils/key.js
index e6c8cfbb0..cd8b80e31 100644
--- a/src/js/utils/key.js
+++ b/src/js/utils/key.js
@@ -1,6 +1,6 @@
-import Keycodes from './keycodes';
-import Keys from './keys';
-import { TAB } from 'mobiledoc-kit/utils/characters';
+import Keycodes from './keycodes'
+import Keys from './keys'
+import { TAB } from 'mobiledoc-kit/utils/characters'
/**
* @typedef Direction
@@ -10,55 +10,55 @@ import { TAB } from 'mobiledoc-kit/utils/characters';
*/
export const DIRECTION = {
FORWARD: 1,
- BACKWARD: -1
-};
-import assert from './assert';
+ BACKWARD: -1,
+}
+import assert from './assert'
export const MODIFIERS = {
META: 1, // also called "command" on OS X
CTRL: 2,
SHIFT: 4,
- ALT: 8 // also called "option" on OS X
-};
+ ALT: 8, // also called "option" on OS X
+}
export function modifierMask(event) {
- let {
- metaKey, shiftKey, ctrlKey, altKey
- } = event;
+ let { metaKey, shiftKey, ctrlKey, altKey } = event
let modVal = (val, modifier) => {
- return (val && modifier) || 0;
- };
- return modVal(metaKey, MODIFIERS.META) +
- modVal(shiftKey, MODIFIERS.SHIFT) +
- modVal(ctrlKey, MODIFIERS.CTRL) +
- modVal(altKey, MODIFIERS.ALT);
+ return (val && modifier) || 0
+ }
+ return (
+ modVal(metaKey, MODIFIERS.META) +
+ modVal(shiftKey, MODIFIERS.SHIFT) +
+ modVal(ctrlKey, MODIFIERS.CTRL) +
+ modVal(altKey, MODIFIERS.ALT)
+ )
}
const SPECIAL_KEYS = {
BACKSPACE: Keycodes.BACKSPACE,
- TAB: Keycodes.TAB,
- ENTER: Keycodes.ENTER,
- ESC: Keycodes.ESC,
- SPACE: Keycodes.SPACE,
- PAGEUP: Keycodes.PAGEUP,
- PAGEDOWN: Keycodes.PAGEDOWN,
- END: Keycodes.END,
- HOME: Keycodes.HOME,
- LEFT: Keycodes.LEFT,
- UP: Keycodes.UP,
- RIGHT: Keycodes.RIGHT,
- DOWN: Keycodes.DOWN,
- INS: Keycodes.INS,
- DEL: Keycodes.DELETE
-};
+ TAB: Keycodes.TAB,
+ ENTER: Keycodes.ENTER,
+ ESC: Keycodes.ESC,
+ SPACE: Keycodes.SPACE,
+ PAGEUP: Keycodes.PAGEUP,
+ PAGEDOWN: Keycodes.PAGEDOWN,
+ END: Keycodes.END,
+ HOME: Keycodes.HOME,
+ LEFT: Keycodes.LEFT,
+ UP: Keycodes.UP,
+ RIGHT: Keycodes.RIGHT,
+ DOWN: Keycodes.DOWN,
+ INS: Keycodes.INS,
+ DEL: Keycodes.DELETE,
+}
export function specialCharacterToCode(specialCharacter) {
- return SPECIAL_KEYS[specialCharacter];
+ return SPECIAL_KEYS[specialCharacter]
}
// heuristic for determining if `event` is a key event
function isKeyEvent(event) {
- return /^key/.test(event.type);
+ return /^key/.test(event.type)
}
/**
@@ -68,106 +68,106 @@ function isKeyEvent(event) {
*/
const Key = class Key {
constructor(event) {
- this.key = event.key;
- this.keyCode = event.keyCode;
- this.charCode = event.charCode;
- this.event = event;
- this.modifierMask = modifierMask(event);
+ this.key = event.key
+ this.keyCode = event.keyCode
+ this.charCode = event.charCode
+ this.event = event
+ this.modifierMask = modifierMask(event)
}
static fromEvent(event) {
- assert('Must pass a Key event to Key.fromEvent',
- event && isKeyEvent(event));
- return new Key(event);
+ assert('Must pass a Key event to Key.fromEvent', event && isKeyEvent(event))
+ return new Key(event)
}
toString() {
- if (this.isTab()) { return TAB; }
- return String.fromCharCode(this.charCode);
+ if (this.isTab()) {
+ return TAB
+ }
+ return String.fromCharCode(this.charCode)
}
// See https://caniuse.com/#feat=keyboardevent-key for browser support.
isKeySupported() {
- return this.key;
+ return this.key
}
isKey(identifier) {
if (this.isKeySupported()) {
- assert(`Must define Keys.${identifier}.`, Keys[identifier]);
- return this.key === Keys[identifier];
+ assert(`Must define Keys.${identifier}.`, Keys[identifier])
+ return this.key === Keys[identifier]
} else {
- assert(`Must define Keycodes.${identifier}.`, Keycodes[identifier]);
- return this.keyCode === Keycodes[identifier];
+ assert(`Must define Keycodes.${identifier}.`, Keycodes[identifier])
+ return this.keyCode === Keycodes[identifier]
}
}
isEscape() {
- return this.isKey('ESC');
+ return this.isKey('ESC')
}
isDelete() {
- return this.isKey('BACKSPACE') || this.isForwardDelete();
+ return this.isKey('BACKSPACE') || this.isForwardDelete()
}
isForwardDelete() {
- return this.isKey('DELETE');
+ return this.isKey('DELETE')
}
isArrow() {
- return this.isHorizontalArrow() || this.isVerticalArrow();
+ return this.isHorizontalArrow() || this.isVerticalArrow()
}
isHorizontalArrow() {
- return this.isLeftArrow() || this.isRightArrow();
+ return this.isLeftArrow() || this.isRightArrow()
}
isHorizontalArrowWithoutModifiersOtherThanShift() {
- return this.isHorizontalArrow() &&
- !(this.ctrlKey || this.metaKey || this.altKey);
+ return this.isHorizontalArrow() && !(this.ctrlKey || this.metaKey || this.altKey)
}
isVerticalArrow() {
- return this.isKey('UP') || this.isKey('DOWN');
+ return this.isKey('UP') || this.isKey('DOWN')
}
isLeftArrow() {
- return this.isKey('LEFT');
+ return this.isKey('LEFT')
}
isRightArrow() {
- return this.isKey('RIGHT');
+ return this.isKey('RIGHT')
}
isHome() {
- return this.isKey('HOME');
+ return this.isKey('HOME')
}
isEnd() {
- return this.isKey('END');
+ return this.isKey('END')
}
isPageUp() {
- return this.isKey('PAGEUP');
+ return this.isKey('PAGEUP')
}
isPageDown() {
- return this.isKey('PAGEDOWN');
+ return this.isKey('PAGEDOWN')
}
isInsert() {
- return this.isKey('INS');
+ return this.isKey('INS')
}
isClear() {
- return this.isKey('CLEAR');
+ return this.isKey('CLEAR')
}
isPause() {
- return this.isKey('PAUSE');
+ return this.isKey('PAUSE')
}
isSpace() {
- return this.isKey('SPACE');
+ return this.isKey('SPACE')
}
// In Firefox, pressing ctrl-TAB will switch to another open browser tab, but
@@ -178,11 +178,11 @@ const Key = class Key {
// modifier.
// See: https://github.com/bustle/mobiledoc-kit/issues/565
isTab() {
- return !this.hasAnyModifier() && this.isKey('TAB');
+ return !this.hasAnyModifier() && this.isKey('TAB')
}
isEnter() {
- return this.isKey('ENTER');
+ return this.isKey('ENTER')
}
/*
@@ -192,7 +192,7 @@ const Key = class Key {
* @return {bool}
*/
isShiftKey() {
- return this.isKey('SHIFT');
+ return this.isKey('SHIFT')
}
/*
@@ -201,7 +201,7 @@ const Key = class Key {
* @return {bool}
*/
isAltKey() {
- return this.isKey('ALT');
+ return this.isKey('ALT')
}
/*
@@ -210,21 +210,21 @@ const Key = class Key {
* @return {bool}
*/
isCtrlKey() {
- return this.isKey('CTRL');
+ return this.isKey('CTRL')
}
isIME() {
// FIXME the IME action seems to get lost when we issue an
// `editor.deleteSelection` before it (in Chrome)
- return this.keyCode === Keycodes.IME;
+ return this.keyCode === Keycodes.IME
}
get direction() {
switch (true) {
case this.isDelete():
- return this.isForwardDelete() ? DIRECTION.FORWARD : DIRECTION.BACKWARD;
+ return this.isForwardDelete() ? DIRECTION.FORWARD : DIRECTION.BACKWARD
case this.isHorizontalArrow():
- return this.isRightArrow() ? DIRECTION.FORWARD : DIRECTION.BACKWARD;
+ return this.isRightArrow() ? DIRECTION.FORWARD : DIRECTION.BACKWARD
}
}
@@ -237,74 +237,75 @@ const Key = class Key {
* @return {bool}
*/
isShift() {
- return this.shiftKey;
+ return this.shiftKey
}
hasModifier(modifier) {
- return modifier & this.modifierMask;
+ return modifier & this.modifierMask
}
hasAnyModifier() {
- return !!this.modifierMask;
+ return !!this.modifierMask
}
get ctrlKey() {
- return MODIFIERS.CTRL & this.modifierMask;
+ return MODIFIERS.CTRL & this.modifierMask
}
get metaKey() {
- return MODIFIERS.META & this.modifierMask;
+ return MODIFIERS.META & this.modifierMask
}
get shiftKey() {
- return MODIFIERS.SHIFT & this.modifierMask;
+ return MODIFIERS.SHIFT & this.modifierMask
}
get altKey() {
- return MODIFIERS.ALT & this.modifierMask;
+ return MODIFIERS.ALT & this.modifierMask
}
isPrintableKey() {
return !(
this.isArrow() ||
- this.isHome() || this.isEnd() ||
- this.isPageUp() || this.isPageDown() ||
- this.isInsert() || this.isClear() || this.isPause() ||
+ this.isHome() ||
+ this.isEnd() ||
+ this.isPageUp() ||
+ this.isPageDown() ||
+ this.isInsert() ||
+ this.isClear() ||
+ this.isPause() ||
this.isEscape()
- );
+ )
}
isNumberKey() {
if (this.isKeySupported()) {
- return this.key >= '0' && this.key <= '9';
+ return this.key >= '0' && this.key <= '9'
} else {
- const code = this.keyCode;
- return (code >= Keycodes['0'] && code <= Keycodes['9']) ||
- (code >= Keycodes.NUMPAD_0 && code <= Keycodes.NUMPAD_9); // numpad keys
+ const code = this.keyCode
+ return (
+ (code >= Keycodes['0'] && code <= Keycodes['9']) || (code >= Keycodes.NUMPAD_0 && code <= Keycodes.NUMPAD_9)
+ ) // numpad keys
}
}
isLetterKey() {
if (this.isKeySupported()) {
- const key = this.key;
- return (key >= 'a' && key <= 'z') ||
- (key >= 'A' && key <= 'Z');
+ const key = this.key
+ return (key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')
} else {
- const code = this.keyCode;
- return (code >= Keycodes.A && code <= Keycodes.Z) ||
- (code >= Keycodes.a && code <= Keycodes.z);
+ const code = this.keyCode
+ return (code >= Keycodes.A && code <= Keycodes.Z) || (code >= Keycodes.a && code <= Keycodes.z)
}
}
isPunctuation() {
if (this.isKeySupported()) {
- const key = this.key;
- return (key >= ';' && key <= '`') ||
- (key >= '[' && key <= '"');
+ const key = this.key
+ return (key >= ';' && key <= '`') || (key >= '[' && key <= '"')
} else {
- const code = this.keyCode;
- return (code >= Keycodes[';'] && code <= Keycodes['`']) ||
- (code >= Keycodes['['] && code <= Keycodes['"']);
+ const code = this.keyCode
+ return (code >= Keycodes[';'] && code <= Keycodes['`']) || (code >= Keycodes['['] && code <= Keycodes['"'])
}
}
@@ -314,12 +315,12 @@ const Key = class Key {
*/
isPrintable() {
if (this.ctrlKey || this.metaKey) {
- return false;
+ return false
}
// Firefox calls keypress events for some keys that should not be printable
if (!this.isPrintableKey()) {
- return false;
+ return false
}
return (
@@ -327,13 +328,13 @@ const Key = class Key {
this.toString().length > 0 ||
this.isNumberKey() ||
this.isSpace() ||
- this.isTab() ||
+ this.isTab() ||
this.isEnter() ||
this.isLetterKey() ||
this.isPunctuation() ||
this.isIME()
- );
+ )
}
-};
+}
-export default Key;
+export default Key
diff --git a/src/js/utils/keycodes.js b/src/js/utils/keycodes.js
index d7d0fa50a..d79aaded7 100644
--- a/src/js/utils/keycodes.js
+++ b/src/js/utils/keycodes.js
@@ -1,43 +1,43 @@
export default {
- BACKSPACE: 8,
- SPACE: 32,
- ENTER: 13,
- SHIFT: 16,
- ESC: 27,
- DELETE: 46,
- '0': 48,
- '9': 57,
- A: 65,
- Z: 90,
- a: 97,
- z: 122,
- 'NUMPAD_0': 186,
- 'NUMPAD_9': 111,
- ';': 186,
- '.': 190,
- '`': 192,
- '[': 219,
- '"': 222,
+ BACKSPACE: 8,
+ SPACE: 32,
+ ENTER: 13,
+ SHIFT: 16,
+ ESC: 27,
+ DELETE: 46,
+ '0': 48,
+ '9': 57,
+ A: 65,
+ Z: 90,
+ a: 97,
+ z: 122,
+ NUMPAD_0: 186,
+ NUMPAD_9: 111,
+ ';': 186,
+ '.': 190,
+ '`': 192,
+ '[': 219,
+ '"': 222,
// Input Method Editor uses multiple keystrokes to display characters.
// Example on mac: press option-i then i. This fires 2 key events in Chrome
// with keyCode 229 and displays ˆ and then î.
// See http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html#fixed-virtual-key-codes
- IME: 229,
+ IME: 229,
- TAB: 9,
- CLEAR: 12,
- PAUSE: 19,
- PAGEUP: 33,
- PAGEDOWN: 34,
- END: 35,
- HOME: 36,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- INS: 45,
- META: 91,
- ALT: 18,
- CTRL: 17
-};
+ TAB: 9,
+ CLEAR: 12,
+ PAUSE: 19,
+ PAGEUP: 33,
+ PAGEDOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ INS: 45,
+ META: 91,
+ ALT: 18,
+ CTRL: 17,
+}
diff --git a/src/js/utils/keys.js b/src/js/utils/keys.js
index 1bbb47f61..6b79e0653 100644
--- a/src/js/utils/keys.js
+++ b/src/js/utils/keys.js
@@ -1,23 +1,23 @@
export default {
- BACKSPACE: 'Backspace',
- SPACE: ' ',
- ENTER: 'Enter',
- SHIFT: 'Shift',
- ESC: 'Escape',
- DELETE: 'Delete',
- INS: 'Insert',
- HOME: 'Home',
- END: 'End',
- PAGEUP: 'PageUp',
- PAGEDOWN: 'PageDown',
- CLEAR: 'Clear',
- PAUSE: 'Pause',
- TAB: 'Tab',
- ALT: 'Alt',
- CTRL: 'Control',
+ BACKSPACE: 'Backspace',
+ SPACE: ' ',
+ ENTER: 'Enter',
+ SHIFT: 'Shift',
+ ESC: 'Escape',
+ DELETE: 'Delete',
+ INS: 'Insert',
+ HOME: 'Home',
+ END: 'End',
+ PAGEUP: 'PageUp',
+ PAGEDOWN: 'PageDown',
+ CLEAR: 'Clear',
+ PAUSE: 'Pause',
+ TAB: 'Tab',
+ ALT: 'Alt',
+ CTRL: 'Control',
- LEFT: 'ArrowLeft',
- RIGHT: 'ArrowRight',
- UP: 'ArrowUp',
- DOWN: 'ArrowDown'
-};
+ LEFT: 'ArrowLeft',
+ RIGHT: 'ArrowRight',
+ UP: 'ArrowUp',
+ DOWN: 'ArrowDown',
+}
diff --git a/src/js/utils/linked-item.js b/src/js/utils/linked-item.js
index 923ff20ab..ac2b86c28 100644
--- a/src/js/utils/linked-item.js
+++ b/src/js/utils/linked-item.js
@@ -1,6 +1,6 @@
export default class LinkedItem {
constructor() {
- this.next = null;
- this.prev = null;
+ this.next = null
+ this.prev = null
}
}
diff --git a/src/js/utils/linked-list.js b/src/js/utils/linked-list.js
index f95240996..fea82bfcb 100644
--- a/src/js/utils/linked-list.js
+++ b/src/js/utils/linked-list.js
@@ -1,210 +1,212 @@
-import assert from './assert';
+import assert from './assert'
-const PARENT_PROP = '__parent';
+const PARENT_PROP = '__parent'
export default class LinkedList {
constructor(options) {
- this.head = null;
- this.tail = null;
- this.length = 0;
+ this.head = null
+ this.tail = null
+ this.length = 0
if (options) {
- const {adoptItem, freeItem} = options;
- this._adoptItem = adoptItem;
- this._freeItem = freeItem;
+ const { adoptItem, freeItem } = options
+ this._adoptItem = adoptItem
+ this._freeItem = freeItem
}
}
adoptItem(item) {
- item[PARENT_PROP]= this;
- this.length++;
- if (this._adoptItem) { this._adoptItem(item); }
+ item[PARENT_PROP] = this
+ this.length++
+ if (this._adoptItem) {
+ this._adoptItem(item)
+ }
}
freeItem(item) {
- item[PARENT_PROP] = null;
- this.length--;
- if (this._freeItem) { this._freeItem(item); }
+ item[PARENT_PROP] = null
+ this.length--
+ if (this._freeItem) {
+ this._freeItem(item)
+ }
}
get isEmpty() {
- return this.length === 0;
+ return this.length === 0
}
prepend(item) {
- this.insertBefore(item, this.head);
+ this.insertBefore(item, this.head)
}
append(item) {
- this.insertBefore(item, null);
+ this.insertBefore(item, null)
}
insertAfter(item, prevItem) {
- let nextItem = prevItem ? prevItem.next : this.head;
- this.insertBefore(item, nextItem);
+ let nextItem = prevItem ? prevItem.next : this.head
+ this.insertBefore(item, nextItem)
}
- _ensureItemIsNotAlreadyInList(item){
+ _ensureItemIsNotAlreadyInList(item) {
assert(
'Cannot insert an item into a list if it is already in a list',
!item.next && !item.prev && this.head !== item
- );
+ )
}
insertBefore(item, nextItem) {
- this._ensureItemIsNotInList(item);
- this.adoptItem(item);
+ this._ensureItemIsNotInList(item)
+ this.adoptItem(item)
- let insertPos;
+ let insertPos
if (nextItem && nextItem.prev) {
- insertPos = 'middle';
+ insertPos = 'middle'
} else if (nextItem) {
- insertPos = 'start';
+ insertPos = 'start'
} else {
- insertPos = 'end';
+ insertPos = 'end'
}
switch (insertPos) {
case 'start':
if (this.head) {
- item.next = this.head;
- this.head.prev = item;
+ item.next = this.head
+ this.head.prev = item
}
- this.head = item;
+ this.head = item
- break;
+ break
case 'middle': {
- let prevItem = nextItem.prev;
- item.next = nextItem;
- item.prev = prevItem;
- nextItem.prev = item;
- prevItem.next = item;
+ let prevItem = nextItem.prev
+ item.next = nextItem
+ item.prev = prevItem
+ nextItem.prev = item
+ prevItem.next = item
- break;
+ break
}
case 'end': {
- let tail = this.tail;
- item.prev = tail;
+ let tail = this.tail
+ item.prev = tail
if (tail) {
- tail.next = item;
+ tail.next = item
} else {
- this.head = item;
+ this.head = item
}
- this.tail = item;
+ this.tail = item
- break;
+ break
}
}
}
remove(item) {
if (!item[PARENT_PROP]) {
- return;
+ return
}
- this._ensureItemIsInThisList(item);
- this.freeItem(item);
+ this._ensureItemIsInThisList(item)
+ this.freeItem(item)
- let [prev, next] = [item.prev, item.next];
- item.prev = null;
- item.next = null;
+ let [prev, next] = [item.prev, item.next]
+ item.prev = null
+ item.next = null
if (prev) {
- prev.next = next;
+ prev.next = next
} else {
- this.head = next;
+ this.head = next
}
if (next) {
- next.prev = prev;
+ next.prev = prev
} else {
- this.tail = prev;
+ this.tail = prev
}
}
forEach(callback) {
- let item = this.head;
- let index = 0;
+ let item = this.head
+ let index = 0
while (item) {
- callback(item, index++);
- item = item.next;
+ callback(item, index++)
+ item = item.next
}
}
map(callback) {
- let result = [];
- this.forEach(i => result.push(callback(i)));
- return result;
+ let result = []
+ this.forEach(i => result.push(callback(i)))
+ return result
}
walk(startItem, endItem, callback) {
- let item = startItem || this.head;
+ let item = startItem || this.head
while (item) {
- callback(item);
+ callback(item)
if (item === endItem) {
- break;
+ break
}
- item = item.next;
+ item = item.next
}
}
readRange(startItem, endItem) {
- let items = [];
- this.walk(startItem, endItem, (item) => {
- items.push(item);
- });
- return items;
+ let items = []
+ this.walk(startItem, endItem, item => {
+ items.push(item)
+ })
+ return items
}
toArray() {
- return this.readRange();
+ return this.readRange()
}
- detect(callback, item=this.head, reverse=false) {
+ detect(callback, item = this.head, reverse = false) {
while (item) {
if (callback(item)) {
- return item;
+ return item
}
- item = reverse ? item.prev : item.next;
+ item = reverse ? item.prev : item.next
}
}
any(callback) {
- return !!this.detect(callback);
+ return !!this.detect(callback)
}
every(callback) {
- let item = this.head;
+ let item = this.head
while (item) {
if (!callback(item)) {
- return false;
+ return false
}
- item = item.next;
+ item = item.next
}
- return true;
+ return true
}
objectAt(targetIndex) {
- let index = -1;
+ let index = -1
return this.detect(() => {
- index++;
- return (targetIndex === index);
- });
+ index++
+ return targetIndex === index
+ })
}
splice(targetItem, removalCount, newItems) {
- let item = targetItem;
- let nextItem = item.next;
- let count = 0;
+ let item = targetItem
+ let nextItem = item.next
+ let count = 0
while (item && count < removalCount) {
- count++;
- nextItem = item.next;
- this.remove(item);
- item = nextItem;
+ count++
+ nextItem = item.next
+ this.remove(item)
+ item = nextItem
}
- newItems.forEach((newItem) => {
- this.insertBefore(newItem, nextItem);
- });
+ newItems.forEach(newItem => {
+ this.insertBefore(newItem, nextItem)
+ })
}
removeBy(conditionFn) {
- let item = this.head;
+ let item = this.head
while (item) {
- let nextItem = item.next;
+ let nextItem = item.next
if (conditionFn(item)) {
- this.remove(item);
+ this.remove(item)
}
- item = nextItem;
+ item = nextItem
}
}
_ensureItemIsNotInList(item) {
- assert('Cannot insert an item into a list if it is already in a list',
- !item[PARENT_PROP]);
+ assert('Cannot insert an item into a list if it is already in a list', !item[PARENT_PROP])
}
_ensureItemIsInThisList(item) {
- assert('Cannot remove item that is in another list',
- item[PARENT_PROP] === this);
+ assert('Cannot remove item that is in another list', item[PARENT_PROP] === this)
}
}
diff --git a/src/js/utils/log-manager.js b/src/js/utils/log-manager.js
index b39a4b33d..92cdac8d9 100644
--- a/src/js/utils/log-manager.js
+++ b/src/js/utils/log-manager.js
@@ -1,47 +1,47 @@
class Logger {
constructor(type, manager) {
- this.type = type;
- this.manager = manager;
+ this.type = type
+ this.manager = manager
}
isEnabled() {
- return this.manager.isEnabled(this.type);
+ return this.manager.isEnabled(this.type)
}
log(...args) {
- args.unshift(`[${this.type}]`);
+ args.unshift(`[${this.type}]`)
if (this.isEnabled()) {
- window.console.log(...args);
+ window.console.log(...args)
}
}
}
class LogManager {
constructor() {
- this.enabledTypes = [];
- this.allEnabled = false;
+ this.enabledTypes = []
+ this.allEnabled = false
}
for(type) {
- return new Logger(type, this);
+ return new Logger(type, this)
}
enableAll() {
- this.allEnabled = true;
+ this.allEnabled = true
}
enableTypes(types) {
- this.enabledTypes = this.enabledTypes.concat(types);
+ this.enabledTypes = this.enabledTypes.concat(types)
}
disable() {
- this.enabledTypes = [];
- this.allEnabled = false;
+ this.enabledTypes = []
+ this.allEnabled = false
}
isEnabled(type) {
- return this.allEnabled || this.enabledTypes.indexOf(type) !== -1;
+ return this.allEnabled || this.enabledTypes.indexOf(type) !== -1
}
}
-export default LogManager;
+export default LogManager
diff --git a/src/js/utils/markuperable.js b/src/js/utils/markuperable.js
index d54753aa6..42c8cd9de 100644
--- a/src/js/utils/markuperable.js
+++ b/src/js/utils/markuperable.js
@@ -1,71 +1,67 @@
-import { normalizeTagName } from '../utils/dom-utils';
-import { detect, commonItemLength, forEach, filter } from '../utils/array-utils';
+import { normalizeTagName } from '../utils/dom-utils'
+import { detect, commonItemLength, forEach, filter } from '../utils/array-utils'
export default class Markerupable {
-
clearMarkups() {
- this.markups = [];
+ this.markups = []
}
addMarkup(markup) {
- this.markups.push(markup);
+ this.markups.push(markup)
}
addMarkupAtIndex(markup, index) {
- this.markups.splice(index, 0, markup);
+ this.markups.splice(index, 0, markup)
}
removeMarkup(markupOrMarkupCallback) {
- let callback;
+ let callback
if (typeof markupOrMarkupCallback === 'function') {
- callback = markupOrMarkupCallback;
+ callback = markupOrMarkupCallback
} else {
- let markup = markupOrMarkupCallback;
- callback = (_markup) => _markup === markup;
+ let markup = markupOrMarkupCallback
+ callback = _markup => _markup === markup
}
- forEach(
- filter(this.markups, callback),
- m => this._removeMarkup(m)
- );
+ forEach(filter(this.markups, callback), m => this._removeMarkup(m))
}
_removeMarkup(markup) {
- const index = this.markups.indexOf(markup);
+ const index = this.markups.indexOf(markup)
if (index !== -1) {
- this.markups.splice(index, 1);
+ this.markups.splice(index, 1)
}
}
hasMarkup(tagNameOrMarkup) {
- return !!this.getMarkup(tagNameOrMarkup);
+ return !!this.getMarkup(tagNameOrMarkup)
}
getMarkup(tagNameOrMarkup) {
if (typeof tagNameOrMarkup === 'string') {
- let tagName = normalizeTagName(tagNameOrMarkup);
- return detect(this.markups, markup => markup.tagName === tagName);
+ let tagName = normalizeTagName(tagNameOrMarkup)
+ return detect(this.markups, markup => markup.tagName === tagName)
} else {
- let targetMarkup = tagNameOrMarkup;
- return detect(this.markups, markup => markup === targetMarkup);
+ let targetMarkup = tagNameOrMarkup
+ return detect(this.markups, markup => markup === targetMarkup)
}
}
get openedMarkups() {
- let count = 0;
+ let count = 0
if (this.prev) {
- count = commonItemLength(this.markups, this.prev.markups);
+ count = commonItemLength(this.markups, this.prev.markups)
}
- return this.markups.slice(count);
+ return this.markups.slice(count)
}
get closedMarkups() {
- let count = 0;
+ let count = 0
if (this.next) {
- count = commonItemLength(this.markups, this.next.markups);
+ count = commonItemLength(this.markups, this.next.markups)
}
- return this.markups.slice(count);
+ return this.markups.slice(count)
}
}
diff --git a/src/js/utils/merge.js b/src/js/utils/merge.js
index 193091a73..1c3ef103c 100644
--- a/src/js/utils/merge.js
+++ b/src/js/utils/merge.js
@@ -1,13 +1,13 @@
function mergeWithOptions(original, updates, options) {
- options = options || {};
- for(var prop in updates) {
+ options = options || {}
+ for (var prop in updates) {
if (options.hasOwnProperty(prop)) {
- original[prop] = options[prop];
+ original[prop] = options[prop]
} else if (updates.hasOwnProperty(prop)) {
- original[prop] = updates[prop];
+ original[prop] = updates[prop]
}
}
- return original;
+ return original
}
/**
@@ -15,7 +15,7 @@ function mergeWithOptions(original, updates, options) {
* @private
*/
function merge(original, updates) {
- return mergeWithOptions(original, updates);
+ return mergeWithOptions(original, updates)
}
-export { mergeWithOptions, merge };
+export { mergeWithOptions, merge }
diff --git a/src/js/utils/mixin.js b/src/js/utils/mixin.js
index e798ca71e..676f530c3 100644
--- a/src/js/utils/mixin.js
+++ b/src/js/utils/mixin.js
@@ -1,15 +1,15 @@
-const CONSTRUCTOR_FN_NAME = 'constructor';
+const CONSTRUCTOR_FN_NAME = 'constructor'
export default function mixin(target, source) {
- target = target.prototype;
+ target = target.prototype
// Fallback to just `source` to allow mixing in a plain object (pojo)
- source = source.prototype || source;
+ source = source.prototype || source
- Object.getOwnPropertyNames(source).forEach((name) => {
+ Object.getOwnPropertyNames(source).forEach(name => {
if (name !== CONSTRUCTOR_FN_NAME) {
- const descriptor = Object.getOwnPropertyDescriptor(source, name);
+ const descriptor = Object.getOwnPropertyDescriptor(source, name)
- Object.defineProperty(target, name, descriptor);
+ Object.defineProperty(target, name, descriptor)
}
- });
+ })
}
diff --git a/src/js/utils/mobiledoc-error.js b/src/js/utils/mobiledoc-error.js
index 46c9f5f4f..83a2c6c1e 100644
--- a/src/js/utils/mobiledoc-error.js
+++ b/src/js/utils/mobiledoc-error.js
@@ -1,25 +1,17 @@
-var errorProps = [
- 'description',
- 'fileName',
- 'lineNumber',
- 'message',
- 'name',
- 'number',
- 'stack'
-];
+var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']
function MobiledocError() {
- let tmp = Error.apply(this, arguments);
+ let tmp = Error.apply(this, arguments)
if (Error.captureStackTrace) {
- Error.captureStackTrace(this, this.constructor);
+ Error.captureStackTrace(this, this.constructor)
}
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
for (let idx = 0; idx < errorProps.length; idx++) {
- this[errorProps[idx]] = tmp[errorProps[idx]];
+ this[errorProps[idx]] = tmp[errorProps[idx]]
}
}
-MobiledocError.prototype = Object.create(Error.prototype);
+MobiledocError.prototype = Object.create(Error.prototype)
-export default MobiledocError;
+export default MobiledocError
diff --git a/src/js/utils/object-utils.js b/src/js/utils/object-utils.js
index 1f5b5ff14..3bfb759b6 100644
--- a/src/js/utils/object-utils.js
+++ b/src/js/utils/object-utils.js
@@ -1,11 +1,11 @@
export function entries(obj) {
- const ownProps = Object.keys(obj);
- let i = ownProps.length;
- const resArray = new Array(i);
+ const ownProps = Object.keys(obj)
+ let i = ownProps.length
+ const resArray = new Array(i)
while (i--) {
- resArray[i] = [ownProps[i], obj[ownProps[i]]];
+ resArray[i] = [ownProps[i], obj[ownProps[i]]]
}
- return resArray;
+ return resArray
}
diff --git a/src/js/utils/parse-utils.js b/src/js/utils/parse-utils.js
index 6c013f539..a2ccd9d32 100644
--- a/src/js/utils/parse-utils.js
+++ b/src/js/utils/parse-utils.js
@@ -1,30 +1,30 @@
/* global JSON */
-import mobiledocParsers from '../parsers/mobiledoc';
-import HTMLParser from '../parsers/html';
-import TextParser from '../parsers/text';
+import mobiledocParsers from '../parsers/mobiledoc'
+import HTMLParser from '../parsers/html'
+import TextParser from '../parsers/text'
-export const MIME_TEXT_PLAIN = 'text/plain';
-export const MIME_TEXT_HTML = 'text/html';
-export const NONSTANDARD_IE_TEXT_TYPE = 'Text';
+export const MIME_TEXT_PLAIN = 'text/plain'
+export const MIME_TEXT_HTML = 'text/html'
+export const NONSTANDARD_IE_TEXT_TYPE = 'Text'
-const MOBILEDOC_REGEX = new RegExp(/data\-mobiledoc='(.*?)'>/);
+const MOBILEDOC_REGEX = new RegExp(/data\-mobiledoc='(.*?)'>/)
/**
* @return {Post}
* @private
*/
function parsePostFromHTML(html, builder, plugins) {
- let post;
+ let post
if (MOBILEDOC_REGEX.test(html)) {
- let mobiledocString = html.match(MOBILEDOC_REGEX)[1];
- let mobiledoc = JSON.parse(mobiledocString);
- post = mobiledocParsers.parse(builder, mobiledoc);
+ let mobiledocString = html.match(MOBILEDOC_REGEX)[1]
+ let mobiledoc = JSON.parse(mobiledocString)
+ post = mobiledocParsers.parse(builder, mobiledoc)
} else {
- post = new HTMLParser(builder, {plugins}).parse(html);
+ post = new HTMLParser(builder, { plugins }).parse(html)
}
- return post;
+ return post
}
/**
@@ -32,9 +32,9 @@ function parsePostFromHTML(html, builder, plugins) {
* @private
*/
function parsePostFromText(text, builder, plugins) {
- let parser = new TextParser(builder, {plugins});
- let post = parser.parse(text);
- return post;
+ let parser = new TextParser(builder, { plugins })
+ let post = parser.parse(text)
+ return post
}
/**
@@ -42,21 +42,23 @@ function parsePostFromText(text, builder, plugins) {
* @private
*/
export function getContentFromPasteEvent(event, window) {
- let html = '', text = '';
+ let html = '',
+ text = ''
- let { clipboardData } = event;
+ let { clipboardData } = event
if (clipboardData && clipboardData.getData) {
- html = clipboardData.getData(MIME_TEXT_HTML);
- text = clipboardData.getData(MIME_TEXT_PLAIN);
- } else if (window.clipboardData && window.clipboardData.getData) { // IE
+ html = clipboardData.getData(MIME_TEXT_HTML)
+ text = clipboardData.getData(MIME_TEXT_PLAIN)
+ } else if (window.clipboardData && window.clipboardData.getData) {
+ // IE
// The Internet Explorers (including Edge) have a non-standard way of interacting with the
// Clipboard API (see http://caniuse.com/#feat=clipboard). In short, they expose a global window.clipboardData
// object instead of the per-event event.clipboardData object on the other browsers.
- html = window.clipboardData.getData(NONSTANDARD_IE_TEXT_TYPE);
+ html = window.clipboardData.getData(NONSTANDARD_IE_TEXT_TYPE)
}
- return { html, text };
+ return { html, text }
}
/**
@@ -64,21 +66,22 @@ export function getContentFromPasteEvent(event, window) {
* @private
*/
function getContentFromDropEvent(event, logger) {
- let html = '', text = '';
+ let html = '',
+ text = ''
try {
- html = event.dataTransfer.getData(MIME_TEXT_HTML);
- text = event.dataTransfer.getData(MIME_TEXT_PLAIN);
+ html = event.dataTransfer.getData(MIME_TEXT_HTML)
+ text = event.dataTransfer.getData(MIME_TEXT_PLAIN)
} catch (e) {
// FIXME IE11 does not include any data in the 'text/html' or 'text/plain'
// mimetypes. It throws an error 'Invalid argument' when attempting to read
// these properties.
if (logger) {
- logger.log('Error getting drop data: ', e);
+ logger.log('Error getting drop data: ', e)
}
}
- return { html, text };
+ return { html, text }
}
/**
@@ -87,22 +90,22 @@ function getContentFromDropEvent(event, logger) {
* @param {Window}
* @private
*/
-export function setClipboardData(event, {mobiledoc, html, text}, window) {
+export function setClipboardData(event, { mobiledoc, html, text }, window) {
if (mobiledoc && html) {
- html = `${html}
`;
+ html = `${html}
`
}
- let { clipboardData } = event;
- let { clipboardData: nonstandardClipboardData } = window;
+ let { clipboardData } = event
+ let { clipboardData: nonstandardClipboardData } = window
if (clipboardData && clipboardData.setData) {
- clipboardData.setData(MIME_TEXT_HTML, html);
- clipboardData.setData(MIME_TEXT_PLAIN, text);
+ clipboardData.setData(MIME_TEXT_HTML, html)
+ clipboardData.setData(MIME_TEXT_PLAIN, text)
} else if (nonstandardClipboardData && nonstandardClipboardData.setData) {
// The Internet Explorers (including Edge) have a non-standard way of interacting with the
// Clipboard API (see http://caniuse.com/#feat=clipboard). In short, they expose a global window.clipboardData
// object instead of the per-event event.clipboardData object on the other browsers.
- nonstandardClipboardData.setData(NONSTANDARD_IE_TEXT_TYPE, html);
+ nonstandardClipboardData.setData(NONSTANDARD_IE_TEXT_TYPE, html)
}
}
@@ -112,13 +115,17 @@ export function setClipboardData(event, {mobiledoc, html, text}, window) {
* @return {Post}
* @private
*/
-export function parsePostFromPaste(pasteEvent, {builder, _parserPlugins: plugins}, {targetFormat}={targetFormat:'html'}) {
- let { html, text } = getContentFromPasteEvent(pasteEvent, window);
+export function parsePostFromPaste(
+ pasteEvent,
+ { builder, _parserPlugins: plugins },
+ { targetFormat } = { targetFormat: 'html' }
+) {
+ let { html, text } = getContentFromPasteEvent(pasteEvent, window)
if (targetFormat === 'html' && html && html.length) {
- return parsePostFromHTML(html, builder, plugins);
+ return parsePostFromHTML(html, builder, plugins)
} else if (text && text.length) {
- return parsePostFromText(text, builder, plugins);
+ return parsePostFromText(text, builder, plugins)
}
}
@@ -129,13 +136,13 @@ export function parsePostFromPaste(pasteEvent, {builder, _parserPlugins: plugins
* @return {Post}
* @private
*/
-export function parsePostFromDrop(dropEvent, editor, {logger}={}) {
- let { builder, _parserPlugins: plugins } = editor;
- let { html, text } = getContentFromDropEvent(dropEvent, logger);
+export function parsePostFromDrop(dropEvent, editor, { logger } = {}) {
+ let { builder, _parserPlugins: plugins } = editor
+ let { html, text } = getContentFromDropEvent(dropEvent, logger)
if (html && html.length) {
- return parsePostFromHTML(html, builder, plugins);
+ return parsePostFromHTML(html, builder, plugins)
} else if (text && text.length) {
- return parsePostFromText(text, builder, plugins);
+ return parsePostFromText(text, builder, plugins)
}
}
diff --git a/src/js/utils/placeholder-image-src.js b/src/js/utils/placeholder-image-src.js
index 4ac64acec..67b6ae34c 100644
--- a/src/js/utils/placeholder-image-src.js
+++ b/src/js/utils/placeholder-image-src.js
@@ -1,3 +1,4 @@
-const placeholderImageSrc = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAMFBMVEXp7vG6vsHm6+63u77Hy868wMPe4+bO09bh5unr8fTR1djAxMfM0NPX3N/c4eTBxcjXRf5TAAACh0lEQVR4nO3b6ZKqMBSFUSQMYZL3f9tbBq/NEEDiqUqOfusn1ZXKbjcQlGQZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACC6RkbsGHuabChEtHmiGYfS3EQYM+Sxw/gMQvmcNnYaj6oTDHi73WPn2eqnj9B8zo3TJXcq5uNjXmVff86VwSR3JtryMa1BYqi7S1hJDCVpSigyLcGhJJEwzlCSNtPKrbVhVwsdCfOhH7uuaG3ARV9DwsaOzxt3N1yPqCHhvXytTUz92VDpmE/LLhZwl++R6Sds6sUa/PL6K/2E2fIhw1xdRKefsFolrPc+xNx/N0k/4fpBsdhL2HfeiN+TsDCms8dDpeRyS3P3QDl6Iqaf8L0rTf+80m6Lmn7Ct+4Wxf+/2RY1/YRv3PHz/u+fsCmqgoTnq7Z+8SGviqoh4dnKu1ieqauiakh4/PQ0r6ivqDoSHj0B97eNRVG1JNxV+L4bnxdVecJtRTdFVZ7QU9F1UXUn9FZ0VVRlCav5ob2KLouqKmFjy676u2HsVnRRVFUJq3J+8KCi86IqSthMvyl209Hjijqm3RsqAZ5pNfa5PJ2KelJRjQmr1/r7cfy0ouoSNvOfvbvhvKLaEr4qOin9kTQnrN7LpDZhE/Zmhp6Eq4p+YcKgiipKGFhRRQkDK6ooYfgLbiSMioQkJGF8P5XwHv4O+7AaKiXzaeXh1kMl5AffTUxiKEm/krD94BR8Gdxl1fceSlR58ZhXKbEpyD2amNiBtmrJLTMHL1LF8/rpXkSZXEmz8K8uvAFFNm6Iq0aBLUFOmeCuJ6exrcCmoLpN7kYx891bSAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgh/wDdr8peyRHLogAAAAASUVORK5CYII=";
+const placeholderImageSrc =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAMFBMVEXp7vG6vsHm6+63u77Hy868wMPe4+bO09bh5unr8fTR1djAxMfM0NPX3N/c4eTBxcjXRf5TAAACh0lEQVR4nO3b6ZKqMBSFUSQMYZL3f9tbBq/NEEDiqUqOfusn1ZXKbjcQlGQZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACC6RkbsGHuabChEtHmiGYfS3EQYM+Sxw/gMQvmcNnYaj6oTDHi73WPn2eqnj9B8zo3TJXcq5uNjXmVff86VwSR3JtryMa1BYqi7S1hJDCVpSigyLcGhJJEwzlCSNtPKrbVhVwsdCfOhH7uuaG3ARV9DwsaOzxt3N1yPqCHhvXytTUz92VDpmE/LLhZwl++R6Sds6sUa/PL6K/2E2fIhw1xdRKefsFolrPc+xNx/N0k/4fpBsdhL2HfeiN+TsDCms8dDpeRyS3P3QDl6Iqaf8L0rTf+80m6Lmn7Ct+4Wxf+/2RY1/YRv3PHz/u+fsCmqgoTnq7Z+8SGviqoh4dnKu1ieqauiakh4/PQ0r6ivqDoSHj0B97eNRVG1JNxV+L4bnxdVecJtRTdFVZ7QU9F1UXUn9FZ0VVRlCav5ob2KLouqKmFjy676u2HsVnRRVFUJq3J+8KCi86IqSthMvyl209Hjijqm3RsqAZ5pNfa5PJ2KelJRjQmr1/r7cfy0ouoSNvOfvbvhvKLaEr4qOin9kTQnrN7LpDZhE/Zmhp6Eq4p+YcKgiipKGFhRRQkDK6ooYfgLbiSMioQkJGF8P5XwHv4O+7AaKiXzaeXh1kMl5AffTUxiKEm/krD94BR8Gdxl1fceSlR58ZhXKbEpyD2amNiBtmrJLTMHL1LF8/rpXkSZXEmz8K8uvAFFNm6Iq0aBLUFOmeCuJ6exrcCmoLpN7kYx891bSAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgh/wDdr8peyRHLogAAAAASUVORK5CYII='
-export default placeholderImageSrc;
+export default placeholderImageSrc
diff --git a/src/js/utils/selection-utils.js b/src/js/utils/selection-utils.js
index d932c5c93..cb595c6ca 100644
--- a/src/js/utils/selection-utils.js
+++ b/src/js/utils/selection-utils.js
@@ -1,33 +1,32 @@
-import { DIRECTION } from '../utils/key';
-import { isTextNode, isElementNode } from 'mobiledoc-kit/utils/dom-utils';
+import { DIRECTION } from '../utils/key'
+import { isTextNode, isElementNode } from 'mobiledoc-kit/utils/dom-utils'
function clearSelection() {
- window.getSelection().removeAllRanges();
+ window.getSelection().removeAllRanges()
}
function textNodeRects(node) {
- let range = document.createRange();
- range.setEnd(node, node.nodeValue.length);
- range.setStart(node, 0);
- return range.getClientRects();
+ let range = document.createRange()
+ range.setEnd(node, node.nodeValue.length)
+ range.setStart(node, 0)
+ return range.getClientRects()
}
function findOffsetInTextNode(node, coords) {
- let len = node.nodeValue.length;
- let range = document.createRange();
+ let len = node.nodeValue.length
+ let range = document.createRange()
for (let i = 0; i < len; i++) {
- range.setEnd(node, i + 1);
- range.setStart(node, i);
- let rect = range.getBoundingClientRect();
+ range.setEnd(node, i + 1)
+ range.setStart(node, i)
+ let rect = range.getBoundingClientRect()
if (rect.top === rect.bottom) {
- continue;
+ continue
}
- if (rect.left <= coords.left && rect.right >= coords.left &&
- rect.top <= coords.top && rect.bottom >= coords.top) {
- return {node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0)};
+ if (rect.left <= coords.left && rect.right >= coords.left && rect.top <= coords.top && rect.bottom >= coords.top) {
+ return { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) }
}
}
- return {node, offset: 0};
+ return { node, offset: 0 }
}
/*
@@ -37,77 +36,78 @@ function findOffsetInTextNode(node, coords) {
*/
/* eslint-disable complexity */
function findOffsetInNode(node, coords) {
- let closest, dyClosest = 1e8, coordsClosest, offset = 0;
+ let closest,
+ dyClosest = 1e8,
+ coordsClosest,
+ offset = 0
for (let child = node.firstChild; child; child = child.nextSibling) {
- let rects;
+ let rects
if (isElementNode(child)) {
- rects = child.getClientRects();
+ rects = child.getClientRects()
} else if (isTextNode(child)) {
- rects = textNodeRects(child);
+ rects = textNodeRects(child)
} else {
- continue;
+ continue
}
for (let i = 0; i < rects.length; i++) {
- let rect = rects[i];
+ let rect = rects[i]
if (rect.left <= coords.left && rect.right >= coords.left) {
- let dy = rect.top > coords.top ? rect.top - coords.top
- : rect.bottom < coords.top ? coords.top - rect.bottom : 0;
+ let dy = rect.top > coords.top ? rect.top - coords.top : rect.bottom < coords.top ? coords.top - rect.bottom : 0
if (dy < dyClosest) {
- closest = child;
- dyClosest = dy;
- coordsClosest = dy ? {left: coords.left, top: rect.top} : coords;
+ closest = child
+ dyClosest = dy
+ coordsClosest = dy ? { left: coords.left, top: rect.top } : coords
if (isElementNode(child) && !child.firstChild) {
- offset = i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0);
+ offset = i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0)
}
- continue;
+ continue
}
}
- if (!closest &&
- (coords.top >= rect.bottom || coords.top >= rect.top && coords.left >= rect.right)) {
- offset = i + 1;
+ if (!closest && (coords.top >= rect.bottom || (coords.top >= rect.top && coords.left >= rect.right))) {
+ offset = i + 1
}
}
}
if (!closest) {
- return {node, offset};
+ return { node, offset }
}
if (isTextNode(closest)) {
- return findOffsetInTextNode(closest, coordsClosest);
+ return findOffsetInTextNode(closest, coordsClosest)
}
if (closest.firstChild) {
- return findOffsetInNode(closest, coordsClosest);
+ return findOffsetInNode(closest, coordsClosest)
}
- return {node, offset};
+ return { node, offset }
}
/* eslint-enable complexity */
function constrainNodeTo(node, parentNode, existingOffset) {
- let compare = parentNode.compareDocumentPosition(node);
+ let compare = parentNode.compareDocumentPosition(node)
if (compare & Node.DOCUMENT_POSITION_CONTAINED_BY) {
// the node is inside parentNode, do nothing
- return { node, offset: existingOffset};
+ return { node, offset: existingOffset }
} else if (compare & Node.DOCUMENT_POSITION_CONTAINS) {
// the node contains parentNode. This shouldn't happen.
- return { node, offset: existingOffset};
+ return { node, offset: existingOffset }
} else if (compare & Node.DOCUMENT_POSITION_PRECEDING) {
// node is before parentNode. return start of deepest first child
- let child = parentNode.firstChild;
+ let child = parentNode.firstChild
while (child.firstChild) {
- child = child.firstChild;
+ child = child.firstChild
}
- return { node: child, offset: 0};
+ return { node: child, offset: 0 }
} else if (compare & Node.DOCUMENT_POSITION_FOLLOWING) {
// node is after parentNode. return end of deepest last child
- let child = parentNode.lastChild;
+ let child = parentNode.lastChild
while (child.lastChild) {
- child = child.lastChild;
+ child = child.lastChild
}
- let offset = isTextNode(child) ? child.textContent.length : 1;
- return {node: child, offset};
+ let offset = isTextNode(child) ? child.textContent.length : 1
+ return { node: child, offset }
} else {
- return { node, offset: existingOffset};
+ return { node, offset: existingOffset }
}
}
@@ -117,23 +117,21 @@ function constrainNodeTo(node, parentNode, existingOffset) {
* or end of the parentNode's children
*/
function constrainSelectionTo(selection, parentNode) {
- let {
- node: anchorNode,
- offset: anchorOffset
- } = constrainNodeTo(selection.anchorNode, parentNode, selection.anchorOffset);
- let {
- node: focusNode,
- offset: focusOffset
- } = constrainNodeTo(selection.focusNode, parentNode, selection.focusOffset);
+ let { node: anchorNode, offset: anchorOffset } = constrainNodeTo(
+ selection.anchorNode,
+ parentNode,
+ selection.anchorOffset
+ )
+ let { node: focusNode, offset: focusOffset } = constrainNodeTo(selection.focusNode, parentNode, selection.focusOffset)
- return { anchorNode, anchorOffset, focusNode, focusOffset };
+ return { anchorNode, anchorOffset, focusNode, focusOffset }
}
function comparePosition(selection) {
- let { anchorNode, focusNode, anchorOffset, focusOffset } = selection;
- let headNode, tailNode, headOffset, tailOffset, direction;
+ let { anchorNode, focusNode, anchorOffset, focusOffset } = selection
+ let headNode, tailNode, headOffset, tailOffset, direction
- const position = anchorNode.compareDocumentPosition(focusNode);
+ const position = anchorNode.compareDocumentPosition(focusNode)
// IE may select return focus and anchor nodes far up the DOM tree instead of
// picking the deepest, most specific possible node. For example in
@@ -149,63 +147,65 @@ function comparePosition(selection) {
//
if (position & Node.DOCUMENT_POSITION_CONTAINS) {
if (focusOffset < focusNode.childNodes.length) {
- focusNode = focusNode.childNodes[focusOffset];
- focusOffset = 0;
+ focusNode = focusNode.childNodes[focusOffset]
+ focusOffset = 0
} else {
// This situation happens on IE when triple-clicking to select.
// Set the focus to the very last character inside the node.
while (focusNode.lastChild) {
- focusNode = focusNode.lastChild;
+ focusNode = focusNode.lastChild
}
- focusOffset = focusNode.textContent.length;
+ focusOffset = focusNode.textContent.length
}
return comparePosition({
focusNode,
focusOffset,
- anchorNode, anchorOffset
- });
+ anchorNode,
+ anchorOffset,
+ })
} else if (position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
- let offset = anchorOffset - 1;
+ let offset = anchorOffset - 1
if (offset < 0) {
- offset = 0;
+ offset = 0
}
return comparePosition({
anchorNode: anchorNode.childNodes[offset],
anchorOffset: 0,
- focusNode, focusOffset
- });
- // The meat of translating anchor and focus nodes to head and tail nodes
+ focusNode,
+ focusOffset,
+ })
+ // The meat of translating anchor and focus nodes to head and tail nodes
} else if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
- headNode = anchorNode; tailNode = focusNode;
- headOffset = anchorOffset; tailOffset = focusOffset;
- direction = DIRECTION.FORWARD;
+ headNode = anchorNode
+ tailNode = focusNode
+ headOffset = anchorOffset
+ tailOffset = focusOffset
+ direction = DIRECTION.FORWARD
} else if (position & Node.DOCUMENT_POSITION_PRECEDING) {
- headNode = focusNode; tailNode = anchorNode;
- headOffset = focusOffset; tailOffset = anchorOffset;
- direction = DIRECTION.BACKWARD;
- } else { // same node
- headNode = tailNode = anchorNode;
- headOffset = anchorOffset;
- tailOffset = focusOffset;
+ headNode = focusNode
+ tailNode = anchorNode
+ headOffset = focusOffset
+ tailOffset = anchorOffset
+ direction = DIRECTION.BACKWARD
+ } else {
+ // same node
+ headNode = tailNode = anchorNode
+ headOffset = anchorOffset
+ tailOffset = focusOffset
if (tailOffset < headOffset) {
// Swap the offset order
- headOffset = focusOffset;
- tailOffset = anchorOffset;
- direction = DIRECTION.BACKWARD;
+ headOffset = focusOffset
+ tailOffset = anchorOffset
+ direction = DIRECTION.BACKWARD
} else if (headOffset < tailOffset) {
- direction = DIRECTION.FORWARD;
+ direction = DIRECTION.FORWARD
} else {
- direction = null;
+ direction = null
}
}
- return {headNode, headOffset, tailNode, tailOffset, direction};
+ return { headNode, headOffset, tailNode, tailOffset, direction }
}
-export {
- clearSelection,
- comparePosition,
- findOffsetInNode,
- constrainSelectionTo
-};
+export { clearSelection, comparePosition, findOffsetInNode, constrainSelectionTo }
diff --git a/src/js/utils/set.js b/src/js/utils/set.js
index 599673fae..1a514ccaf 100644
--- a/src/js/utils/set.js
+++ b/src/js/utils/set.js
@@ -1,24 +1,24 @@
export default class Set {
- constructor(items=[]) {
- this.items = [];
- items.forEach(i => this.add(i));
+ constructor(items = []) {
+ this.items = []
+ items.forEach(i => this.add(i))
}
add(item) {
if (!this.has(item)) {
- this.items.push(item);
+ this.items.push(item)
}
}
get length() {
- return this.items.length;
+ return this.items.length
}
has(item) {
- return this.items.indexOf(item) !== -1;
+ return this.items.indexOf(item) !== -1
}
toArray() {
- return this.items;
+ return this.items
}
}
diff --git a/src/js/utils/string-utils.js b/src/js/utils/string-utils.js
index d76137d65..9942a18a3 100644
--- a/src/js/utils/string-utils.js
+++ b/src/js/utils/string-utils.js
@@ -4,21 +4,21 @@
*/
export function dasherize(string) {
return string.replace(/[A-Z]/g, (match, offset) => {
- const lower = match.toLowerCase();
+ const lower = match.toLowerCase()
- return (offset === 0 ? lower : '-' + lower);
- });
+ return offset === 0 ? lower : '-' + lower
+ })
}
export function capitalize(string) {
- return string.charAt(0).toUpperCase() + string.slice(1);
+ return string.charAt(0).toUpperCase() + string.slice(1)
}
export function startsWith(string, character) {
- return string.charAt(0) === character;
+ return string.charAt(0) === character
}
export function endsWith(string, endString) {
- let index = string.lastIndexOf(endString);
- return index !== -1 && index === string.length - endString.length;
+ let index = string.lastIndexOf(endString)
+ return index !== -1 && index === string.length - endString.length
}
diff --git a/src/js/utils/to-range.js b/src/js/utils/to-range.js
index 1fe59660b..086baf4fe 100644
--- a/src/js/utils/to-range.js
+++ b/src/js/utils/to-range.js
@@ -1,15 +1,15 @@
-import Range from 'mobiledoc-kit/utils/cursor/range';
-import Position from 'mobiledoc-kit/utils/cursor/position';
-import assert from 'mobiledoc-kit/utils/assert';
+import Range from 'mobiledoc-kit/utils/cursor/range'
+import Position from 'mobiledoc-kit/utils/cursor/position'
+import assert from 'mobiledoc-kit/utils/assert'
export default function toRange(rangeLike) {
- assert(`Must pass non-blank object to "toRange"`, !!rangeLike);
+ assert(`Must pass non-blank object to "toRange"`, !!rangeLike)
if (rangeLike instanceof Range) {
- return rangeLike;
+ return rangeLike
} else if (rangeLike instanceof Position) {
- return rangeLike.toRange();
+ return rangeLike.toRange()
}
- assert(`Incorrect structure for rangeLike: ${rangeLike}`, false);
+ assert(`Incorrect structure for rangeLike: ${rangeLike}`, false)
}
diff --git a/src/js/version.js b/src/js/version.js
index 2034b2955..55b1d631e 100644
--- a/src/js/version.js
+++ b/src/js/version.js
@@ -1 +1 @@
-export default '##VERSION##';
+export default '##VERSION##'
diff --git a/src/js/views/tooltip.js b/src/js/views/tooltip.js
index 7c1e4d2dc..944a90bef 100644
--- a/src/js/views/tooltip.js
+++ b/src/js/views/tooltip.js
@@ -1,88 +1,86 @@
-import View from './view';
-import {
- positionElementCenteredBelow,
- getEventTargetMatchingTag,
- whenElementIsNotInDOM
-} from '../utils/element-utils';
-import { editLink } from '../editor/ui';
+import View from './view'
+import { positionElementCenteredBelow, getEventTargetMatchingTag, whenElementIsNotInDOM } from '../utils/element-utils'
+import { editLink } from '../editor/ui'
-const SHOW_DELAY = 200;
-const HIDE_DELAY = 600;
+const SHOW_DELAY = 200
+const HIDE_DELAY = 600
export default class Tooltip extends View {
constructor(options) {
- options.classNames = ['__mobiledoc-tooltip'];
- super(options);
+ options.classNames = ['__mobiledoc-tooltip']
+ super(options)
- this.rootElement = options.rootElement;
- this.editor = options.editor;
+ this.rootElement = options.rootElement
+ this.editor = options.editor
- this.addListeners(options);
+ this.addListeners(options)
}
showLink(linkEl) {
- const { editor, element: tooltipEl } = this;
- const { tooltipPlugin } = editor;
+ const { editor, element: tooltipEl } = this
+ const { tooltipPlugin } = editor
tooltipPlugin.renderLink(tooltipEl, linkEl, {
editLink: () => {
- editLink(linkEl, editor);
- this.hide();
- }
- });
+ editLink(linkEl, editor)
+ this.hide()
+ },
+ })
- this.show();
- positionElementCenteredBelow(this.element, linkEl);
+ this.show()
+ positionElementCenteredBelow(this.element, linkEl)
- this.elementObserver = whenElementIsNotInDOM(linkEl, () => this.hide());
+ this.elementObserver = whenElementIsNotInDOM(linkEl, () => this.hide())
}
addListeners(options) {
- const { rootElement, element: tooltipElement } = this;
- let showTimeout, hideTimeout;
+ const { rootElement, element: tooltipElement } = this
+ let showTimeout, hideTimeout
const scheduleHide = () => {
- clearTimeout(hideTimeout);
+ clearTimeout(hideTimeout)
hideTimeout = setTimeout(() => {
- this.hide();
- }, HIDE_DELAY);
- };
+ this.hide()
+ }, HIDE_DELAY)
+ }
this.addEventListener(tooltipElement, 'mouseenter', e => {
- clearTimeout(hideTimeout);
- });
+ clearTimeout(hideTimeout)
+ })
this.addEventListener(tooltipElement, 'mouseleave', e => {
- scheduleHide();
- });
+ scheduleHide()
+ })
- this.addEventListener(rootElement, 'mouseover', (e) => {
- let target = getEventTargetMatchingTag(options.showForTag, e.target, rootElement);
+ this.addEventListener(rootElement, 'mouseover', e => {
+ let target = getEventTargetMatchingTag(options.showForTag, e.target, rootElement)
if (target && target.isContentEditable) {
- clearTimeout(hideTimeout);
+ clearTimeout(hideTimeout)
showTimeout = setTimeout(() => {
- this.showLink(target);
- }, SHOW_DELAY);
+ this.showLink(target)
+ }, SHOW_DELAY)
}
- });
+ })
- this.addEventListener(rootElement, 'mouseout', (e) => {
- clearTimeout(showTimeout);
- if (this.elementObserver) { this.elementObserver.cancel(); }
- scheduleHide();
- });
+ this.addEventListener(rootElement, 'mouseout', e => {
+ clearTimeout(showTimeout)
+ if (this.elementObserver) {
+ this.elementObserver.cancel()
+ }
+ scheduleHide()
+ })
}
}
export const DEFAULT_TOOLTIP_PLUGIN = {
renderLink(tooltipEl, linkEl, { editLink }) {
- const { href } = linkEl;
- tooltipEl.innerHTML = `${href}`;
- const button = document.createElement('button');
+ const { href } = linkEl
+ tooltipEl.innerHTML = `${href}`
+ const button = document.createElement('button')
button.classList.add('__mobiledoc-tooltip__edit-link')
- button.innerText = 'Edit Link';
- button.addEventListener('click', editLink);
- tooltipEl.append(button);
- }
-};
+ button.innerText = 'Edit Link'
+ button.addEventListener('click', editLink)
+ tooltipEl.append(button)
+ },
+}
diff --git a/src/js/views/view.js b/src/js/views/view.js
index a356095b1..1e85a613d 100644
--- a/src/js/views/view.js
+++ b/src/js/views/view.js
@@ -1,51 +1,51 @@
-import { addClassName } from '../utils/dom-utils';
+import { addClassName } from '../utils/dom-utils'
class View {
- constructor(options={}) {
- options.tagName = options.tagName || 'div';
- options.container = options.container || document.body;
+ constructor(options = {}) {
+ options.tagName = options.tagName || 'div'
+ options.container = options.container || document.body
- this.element = document.createElement(options.tagName);
- this.container = options.container;
- this.isShowing = false;
+ this.element = document.createElement(options.tagName)
+ this.container = options.container
+ this.isShowing = false
- let classNames = options.classNames || [];
- classNames.forEach(name => addClassName(this.element, name));
- this._eventListeners = [];
+ let classNames = options.classNames || []
+ classNames.forEach(name => addClassName(this.element, name))
+ this._eventListeners = []
}
addEventListener(element, type, listener) {
- element.addEventListener(type, listener);
- this._eventListeners.push([element, type, listener]);
+ element.addEventListener(type, listener)
+ this._eventListeners.push([element, type, listener])
}
removeAllEventListeners() {
this._eventListeners.forEach(([element, type, listener]) => {
- element.removeEventListener(type, listener);
- });
+ element.removeEventListener(type, listener)
+ })
}
show() {
- if(!this.isShowing) {
- this.container.appendChild(this.element);
- this.isShowing = true;
- return true;
+ if (!this.isShowing) {
+ this.container.appendChild(this.element)
+ this.isShowing = true
+ return true
}
}
hide() {
if (this.isShowing) {
- this.container.removeChild(this.element);
- this.isShowing = false;
- return true;
+ this.container.removeChild(this.element)
+ this.isShowing = false
+ return true
}
}
destroy() {
- this.removeAllEventListeners();
- this.hide();
- this.isDestroyed = true;
+ this.removeAllEventListeners()
+ this.hide()
+ this.isDestroyed = true
}
}
-export default View;
+export default View
diff --git a/yarn.lock b/yarn.lock
index 1aebcc8fd..b573366d8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2571,6 +2571,11 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+prettier@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
+ integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
+
printf@^0.5.1:
version "0.5.2"
resolved "https://registry.yarnpkg.com/printf/-/printf-0.5.2.tgz#8546e01a1f647b1dff510ae92bdc92beb8c9b2f9"