diff --git a/website/demo/demo.css b/website/demo/demo.css index 341e0a067..f29d99e74 100644 --- a/website/demo/demo.css +++ b/website/demo/demo.css @@ -24,6 +24,12 @@ body { .pane { max-width: 25%; + padding: 0 1em; +} + +.pane p.desc { + height: 150px; + overflow: scroll; } .editor-pane { @@ -76,7 +82,8 @@ body { #mobiledoc-to-load { } #mobiledoc-to-load textarea { - height: 300px; + height: 500px; + width: 100%; } .code-pane:first-child { diff --git a/website/demo/demo.js b/website/demo/demo.js index 02f5c3cb0..0571d2408 100644 --- a/website/demo/demo.js +++ b/website/demo/demo.js @@ -2,6 +2,9 @@ 'use strict'; +var ContentKit = exports.ContentKit, + $ = exports.$; + var ContentKitDemo = exports.ContentKitDemo = { syncCodePane: function(editor) { var codePaneJSON = document.getElementById('serialized-mobiledoc'); @@ -40,9 +43,10 @@ var ContentKitDemo = exports.ContentKitDemo = { }; -function bootEditor(element, payload) { +function bootEditor(element, mobiledoc) { var editor = new ContentKit.Editor(element, { - mobiledoc: payload, + autofocus: false, + mobiledoc: mobiledoc, cards: { 'pick-color': function renderPickColor(payload) { return 'PICK A COLOR: '+payload.options.join(', '); @@ -55,22 +59,106 @@ function bootEditor(element, payload) { }); } -function readPayload(textarea) { - var jqueryTextarea = $(textarea); - var textPayload = jqueryTextarea.val(); - return JSON.parse(textPayload); +function readMobiledoc(string) { + return JSON.parse(string); } -$(function() { - var textarea = $('#mobiledoc-to-load textarea'); - var editor; - textarea.on('input', function() { +function isValidJSON(string) { + try { + JSON.parse(string); + return true; + } catch(e) { + return false; + } +} + +function attemptEditorReboot(editor, textarea) { + var textPayload = $(textarea).val(); + if (isValidJSON(textPayload)) { + var mobiledoc = readMobiledoc(textPayload); if (editor) { editor.destroy(); } - editor = bootEditor($('#editor')[0], readPayload(textarea)); + bootEditor($('#editor')[0], mobiledoc); + } +} + +var sampleMobiledocs = { + simpleMobiledoc: [ + [], + [ + [1, "H2", [ + [[], 0, "headline h2"] + ]], + [1, "P", [ + [[], 0, "hello world"] + ]] + ] + ], + + mobileDocWithMarker: [ + [['B']], + [ + [1, "H2", [ + [[], 0, "headline h2"] + ]], + [1, "P", [ + [[0], 1, "bold world"] + ]] + ] + ], + + mobileDocWithMultipleMarkers: [ + [['B'], ['I']], + [ + [1, "H2", [ + [[], 0, "headline h2"] + ]], + [1, "P", [ + [[], 0, "hello "], + [[0], 1, "bold, "], + [[1], 1, "italic "], + [[], 0, "world."] + ]] + ] + ], + + mobileDocWithAttributeMarker: [ + [['A', ['href', 'http://github.com/bustlelabs/content-kit-editor']]], + [ + [1, "H2", [ + [[], 0, "headline h2"] + ]], + [1, "P", [ + [[], 0, "see it "], + [[0], 1, "on github."] + ]] + ] + ] +}; + + +$(function() { + var editor; + var editorEl = $('#editor')[0]; + var mobiledoc = sampleMobiledocs.simpleMobiledoc; + + var textarea = $('#mobiledoc-to-load textarea'); + textarea.val(JSON.stringify(mobiledoc, false, 2)); + + textarea.on('input', function() { + attemptEditorReboot(editor, textarea); }); - editor = bootEditor($('#editor')[0], readPayload(textarea)); + + $('#select-mobiledoc').on('change', function() { + var mobiledocName = $(this).val(); + var mobiledoc = sampleMobiledocs[mobiledocName]; + textarea.val(JSON.stringify(mobiledoc, false, 2)); + textarea.trigger('input'); + }); + + bootEditor(editorEl, mobiledoc); + $(editorEl).focus(); }); }(this, document)); diff --git a/website/demo/index.html b/website/demo/index.html index 1992c4058..a895c7415 100644 --- a/website/demo/index.html +++ b/website/demo/index.html @@ -1,5 +1,6 @@ + Content Kit Editor Demo 0.2.0 @@ -14,42 +15,58 @@ +

mobiledoc to load

+

+ This mobiledoc will be loaded into the editor. + You can change it and see the editor reload with the new contents. + (If there is a JSON syntax error it will be ignored; if there is a parser + error the editor may stop responding.) +
+ Select a preloaded mobiledoc here: + +

- +

editor

+

+ The live-editing surface. Changes here are serialized to mobiledoc + format and displayed to the right. +

serialized mobiledoc

+

+ When the editor updates, it prints its serialized mobiledoc here. +

rendered mobiledoc

+

+ This is the output of using the runtime (client-side) + mobiledoc-dom-renderer + on the serialized mobiledoc. +

diff --git a/website/global/content-kit-editor.js b/website/global/content-kit-editor.js index a7d522601..1a0cfe368 100644 --- a/website/global/content-kit-editor.js +++ b/website/global/content-kit-editor.js @@ -193,1892 +193,450 @@ var define, requireModule, require, requirejs; }; })(); -define('content-kit-compiler/compiler', ['exports', 'content-kit-compiler/parsers/new-html-parser', 'content-kit-compiler/types/default-types', 'content-kit-utils'], function (exports, _contentKitCompilerParsersNewHtmlParser, _contentKitCompilerTypesDefaultTypes, _contentKitUtils) { - 'use strict'; +define("content-kit-editor/commands/base", ["exports"], function (exports) { + "use strict"; - /** - * @class Compiler - * @constructor - * @param options - */ - function Compiler(options) { - var parser = new _contentKitCompilerParsersNewHtmlParser['default'](); - var defaults = { - renderer: null, - parser: parser, - blockTypes: _contentKitCompilerTypesDefaultTypes.DefaultBlockTypeSet, - markupTypes: _contentKitCompilerTypesDefaultTypes.DefaultMarkupTypeSet, - // Outputs `type_name:'HEADING'` etc. when parsing. Good - // for debugging. - includeTypeNames: false - }; - (0, _contentKitUtils.mergeWithOptions)(this, defaults, options); - if (!this.renderer) { - throw new Error('renderer required'); + function Command(options) { + options = options || {}; + var command = this; + var name = options.name; + var prompt = options.prompt; + command.name = name; + command.button = options.button || name; + if (prompt) { + command.prompt = prompt; } } - /** - * @method parse - * @param input - * @return Array - */ - Compiler.prototype.parse = function (input) { - return this.parser.parse(input); - }; + Command.prototype.exec = function () {}; - /** - * @method render - * @param model - * @return String - */ - Compiler.prototype.render = function (model, target) { - return this.renderer.render(model, target); - }; + exports["default"] = Command; +}); +define('content-kit-editor/commands/bold', ['exports', 'content-kit-editor/commands/text-format', 'content-kit-editor/utils/selection-utils', 'content-kit-utils'], function (exports, _contentKitEditorCommandsTextFormat, _contentKitEditorUtilsSelectionUtils, _contentKitUtils) { + 'use strict'; - /** - * @method rerender - * @param input - * @return String - */ - Compiler.prototype.rerender = function (input) { - return this.render(this.parse(input)); - }; + var RegExpHeadingTag = /^(h1|h2|h3|h4|h5|h6)$/i; - /** - * @method reparse - * @param model - * @return String - */ - Compiler.prototype.reparse = function (model) { - return this.parse(this.render(model)); - }; + function BoldCommand() { + _contentKitEditorCommandsTextFormat['default'].call(this, { + name: 'bold', + tag: 'strong', + mappedTags: ['b'], + button: '' + }); + } + (0, _contentKitUtils.inherit)(BoldCommand, _contentKitEditorCommandsTextFormat['default']); - /** - * @method registerBlockType - * @param {Type} type - */ - Compiler.prototype.registerBlockType = function (type) { - return this.blockTypes.addType(type); + BoldCommand.prototype.exec = function () { + // Don't allow executing bold command on heading tags + if (!RegExpHeadingTag.test((0, _contentKitEditorUtilsSelectionUtils.getSelectionBlockTagName)())) { + BoldCommand._super.prototype.exec.call(this); + } }; - /** - * @method registerMarkupType - * @param {Type} type - */ - Compiler.prototype.registerMarkupType = function (type) { - return this.markupTypes.addType(type); - }; + exports['default'] = BoldCommand; +}); +define('content-kit-editor/commands/card', ['exports', 'content-kit-editor/commands/base', 'content-kit-utils'], function (exports, _contentKitEditorCommandsBase, _contentKitUtils) { + 'use strict'; + + function injectCardBlock(cardName, cardPayload, editor, index) { + throw new Error('Unimplemented: BlockModel and Type.CARD are no longer things'); + // FIXME: Do we change the block model internal representation here? + var cardBlock = BlockModel.createWithType(Type.CARD, { + attributes: { + name: cardName, + payload: cardPayload + } + }); + editor.replaceBlock(cardBlock, index); + } + + function CardCommand() { + _contentKitEditorCommandsBase['default'].call(this, { + name: 'card', + button: 'CA' + }); + } + (0, _contentKitUtils.inherit)(CardCommand, _contentKitEditorCommandsBase['default']); + + CardCommand.prototype = { + exec: function exec() { + CardCommand._super.prototype.exec.call(this); + var editor = this.editorContext; + var currentEditingIndex = editor.getCurrentBlockIndex(); - Compiler.prototype.parseSection = function (previousSection, sectionElement) { - return this.parser.parseSection(previousSection, sectionElement); + var cardName = 'pick-color'; + var cardPayload = { options: ['red', 'blue'] }; + injectCardBlock(cardName, cardPayload, editor, currentEditingIndex); + editor.renderBlockAt(currentEditingIndex, true); + } }; - exports['default'] = Compiler; + exports['default'] = CardCommand; }); -define('content-kit-compiler', ['exports', 'content-kit-compiler/types/type', 'content-kit-compiler/models/block', 'content-kit-compiler/models/embed', 'content-kit-compiler/compiler', 'content-kit-compiler/parsers/html-parser', 'content-kit-compiler/renderers/html-renderer', 'content-kit-compiler/parsers/new-html-parser', 'content-kit-compiler/parsers/document', 'content-kit-compiler/parsers/mobiledoc', 'content-kit-compiler/runtime/renderers/dom'], function (exports, _contentKitCompilerTypesType, _contentKitCompilerModelsBlock, _contentKitCompilerModelsEmbed, _contentKitCompilerCompiler, _contentKitCompilerParsersHtmlParser, _contentKitCompilerRenderersHtmlRenderer, _contentKitCompilerParsersNewHtmlParser, _contentKitCompilerParsersDocument, _contentKitCompilerParsersMobiledoc, _contentKitCompilerRuntimeRenderersDom) { +define('content-kit-editor/commands/format-block', ['exports', 'content-kit-editor/commands/text-format', 'content-kit-editor/utils/selection-utils', 'content-kit-utils'], function (exports, _contentKitEditorCommandsTextFormat, _contentKitEditorUtilsSelectionUtils, _contentKitUtils) { 'use strict'; - exports.registerGlobal = registerGlobal; + function FormatBlockCommand(options) { + options = options || {}; + options.action = 'formatBlock'; + _contentKitEditorCommandsTextFormat['default'].call(this, options); + } + (0, _contentKitUtils.inherit)(FormatBlockCommand, _contentKitEditorCommandsTextFormat['default']); - var Runtime = { - DOMRenderer: _contentKitCompilerRuntimeRenderersDom['default'] - }; + FormatBlockCommand.prototype.exec = function () { + var tag = this.tag; + // Brackets neccessary for certain browsers + var value = '<' + tag + '>'; + var blockElement = (0, _contentKitEditorUtilsSelectionUtils.getSelectionBlockElement)(); + // Allow block commands to be toggled back to a text block + if (tag === blockElement.tagName.toLowerCase()) { + throw new Error('Unimplemented: Type.BOLD.paragraph must be replaced'); + value = Type.PARAGRAPH.tag; + } else { + // Flattens the selection before applying the block format. + // Otherwise, undesirable nested blocks can occur. + // TODO: would love to be able to remove this + var flatNode = document.createTextNode(blockElement.textContent); + blockElement.parentNode.insertBefore(flatNode, blockElement); + blockElement.parentNode.removeChild(blockElement); + (0, _contentKitEditorUtilsSelectionUtils.selectNode)(flatNode); + } - /** - * @namespace ContentKit - * Register public ContentKit compiler modules - */ - var ContentKitCompiler = { - Type: _contentKitCompilerTypesType['default'], - BlockModel: _contentKitCompilerModelsBlock['default'], - EmbedModel: _contentKitCompilerModelsEmbed['default'], - Compiler: _contentKitCompilerCompiler['default'], - HTMLParser: _contentKitCompilerParsersHtmlParser['default'], - HTMLRenderer: _contentKitCompilerRenderersHtmlRenderer['default'], - NewHTMLParser: _contentKitCompilerParsersNewHtmlParser['default'], - MobiledocParser: _contentKitCompilerParsersMobiledoc['default'], - Runtime: Runtime + FormatBlockCommand._super.prototype.exec.call(this, value); }; - exports.Type = _contentKitCompilerTypesType['default']; - exports.BlockModel = _contentKitCompilerModelsBlock['default']; - exports.EmbedModel = _contentKitCompilerModelsEmbed['default']; - exports.Compiler = _contentKitCompilerCompiler['default']; - exports.HTMLParser = _contentKitCompilerParsersHtmlParser['default']; - exports.HTMLRenderer = _contentKitCompilerRenderersHtmlRenderer['default']; - exports.NewHTMLParser = _contentKitCompilerParsersNewHtmlParser['default']; - exports.MobiledocParser = _contentKitCompilerParsersMobiledoc['default']; - exports.Runtime = Runtime; - exports.doc = _contentKitCompilerParsersDocument['default']; + exports['default'] = FormatBlockCommand; +}); +define('content-kit-editor/commands/heading', ['exports', 'content-kit-editor/commands/format-block', 'content-kit-utils'], function (exports, _contentKitEditorCommandsFormatBlock, _contentKitUtils) { + 'use strict'; - function registerGlobal(window) { - window.ContentKitCompiler = ContentKitCompiler; + function HeadingCommand() { + _contentKitEditorCommandsFormatBlock['default'].call(this, { + name: 'heading', + tag: 'h2', + button: '1' + }); } + (0, _contentKitUtils.inherit)(HeadingCommand, _contentKitEditorCommandsFormatBlock['default']); - exports['default'] = ContentKitCompiler; + exports['default'] = HeadingCommand; }); -define('content-kit-compiler/models/block', ['exports', 'content-kit-compiler/models/model', 'content-kit-utils'], function (exports, _contentKitCompilerModelsModel, _contentKitUtils) { +define('content-kit-editor/commands/image', ['exports', 'content-kit-editor/commands/base', 'content-kit-editor/views/message', 'content-kit-utils', 'content-kit-editor/utils/http-utils'], function (exports, _contentKitEditorCommandsBase, _contentKitEditorViewsMessage, _contentKitUtils, _contentKitEditorUtilsHttpUtils) { 'use strict'; - /** - * Ensures block markups at the same index are always in a specific order. - * For example, so all bold links are consistently marked up - * as text instead of text - */ - function sortBlockMarkups(markups) { - return markups.sort(function (a, b) { - if (a.start === b.start && a.end === b.end) { - return b.type - a.type; - } - return 0; + function createFileInput(command) { + var fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.accept = 'image/*'; + fileInput.className = 'ck-file-input'; + fileInput.addEventListener('change', function (e) { + command.handleFile(e); }); + return fileInput; } - /** - * @class BlockModel - * @constructor - * @extends Model - */ - function BlockModel(options) { - options = options || {}; - _contentKitCompilerModelsModel['default'].call(this, options); - this.value = options.value || ''; - this.markup = sortBlockMarkups(options.markup || []); + function injectImageBlock(src, editor, index) { + throw new Error('Unimplemented: BlockModel and Type.IMAGE are no longer things'); + var imageModel = BlockModel.createWithType(Type.IMAGE, { attributes: { src: src } }); + editor.replaceBlock(imageModel, index); } - (0, _contentKitUtils.inherit)(BlockModel, _contentKitCompilerModelsModel['default']); - - exports['default'] = BlockModel; -}); -define('content-kit-compiler/models/embed', ['exports', 'content-kit-compiler/models/model', 'content-kit-compiler/types/type'], function (exports, _contentKitCompilerModelsModel, _contentKitCompilerTypesType) { - 'use strict'; - - /** - * @class EmbedModel - * @constructor - * @extends Model - * Massages data from an oEmbed response into an EmbedModel - */ - function EmbedModel(options) { - if (!options) { - return null; + function renderFromFile(file, editor, index) { + if (file && window.FileReader) { + var reader = new FileReader(); + reader.onload = function (e) { + var base64Src = e.target.result; + injectImageBlock(base64Src, editor, index); + editor.renderBlockAt(index, true); + }; + reader.readAsDataURL(file); } + } - _contentKitCompilerModelsModel['default'].call(this, { - type: _contentKitCompilerTypesType['default'].EMBED.id, - type_name: _contentKitCompilerTypesType['default'].EMBED.name, - attributes: {} + function ImageCommand(options) { + _contentKitEditorCommandsBase['default'].call(this, { + name: 'image', + button: '' }); + this.uploader = new _contentKitEditorUtilsHttpUtils.FileUploader({ url: options.serviceUrl, maxFileSize: 5000000 }); + } + (0, _contentKitUtils.inherit)(ImageCommand, _contentKitEditorCommandsBase['default']); - // Massage the oEmbed data - var attributes = this.attributes; - var embedType = options.type; - var providerName = options.provider_name; - var embedUrl = options.url; - var embedTitle = options.title; - var embedThumbnail = options.thumbnail_url; - var embedHtml = options.html; - - if (embedType) { - attributes.embed_type = embedType; - } - if (providerName) { - attributes.provider_name = providerName; - } - if (embedUrl) { - attributes.url = embedUrl; - } - if (embedTitle) { - attributes.title = embedTitle; - } - - if (embedType === 'photo') { - attributes.thumbnail = options.media_url || embedUrl; - } else if (embedThumbnail) { - attributes.thumbnail = embedThumbnail; - } + ImageCommand.prototype = { + exec: function exec() { + ImageCommand._super.prototype.exec.call(this); + var fileInput = this.fileInput; + if (!fileInput) { + fileInput = this.fileInput = createFileInput(this); + document.body.appendChild(fileInput); + } + fileInput.dispatchEvent(new MouseEvent('click', { bubbles: false })); + }, + handleFile: function handleFile(e) { + var fileInput = e.target; + var file = fileInput.files && fileInput.files[0]; + var editor = this.editorContext; + var embedIntent = this.embedIntent; + var currentEditingIndex = editor.getCurrentBlockIndex(); - if (embedHtml && (embedType === 'rich' || embedType === 'video')) { - attributes.html = embedHtml; + embedIntent.showLoading(); + renderFromFile(file, editor, currentEditingIndex); // render image immediately client-side + this.uploader.upload({ + fileInput: fileInput, + complete: function complete(response, error) { + embedIntent.hideLoading(); + if (error || !response || !response.url) { + setTimeout(function () { + editor.removeBlockAt(currentEditingIndex); + editor.syncVisual(); + }, 1000); + return new _contentKitEditorViewsMessage['default']().showError(error.message || 'Error uploading image'); + } + injectImageBlock(response.url, editor, currentEditingIndex); + } + }); + fileInput.value = null; // reset file input } - } + }; - exports['default'] = EmbedModel; + exports['default'] = ImageCommand; }); -define('content-kit-compiler/models/markup', ['exports', 'content-kit-compiler/models/model', 'content-kit-utils'], function (exports, _contentKitCompilerModelsModel, _contentKitUtils) { +define('content-kit-editor/commands/italic', ['exports', 'content-kit-editor/commands/text-format', 'content-kit-utils'], function (exports, _contentKitEditorCommandsTextFormat, _contentKitUtils) { 'use strict'; - /** - * @class MarkupModel - * @constructor - * @extends Model - */ - function MarkupModel(options) { - options = options || {}; - _contentKitCompilerModelsModel['default'].call(this, options); - this.start = options.start || 0; - this.end = options.end || 0; + function ItalicCommand() { + _contentKitEditorCommandsTextFormat['default'].call(this, { + name: 'italic', + tag: 'em', + mappedTags: ['i'], + button: '' + }); } + (0, _contentKitUtils.inherit)(ItalicCommand, _contentKitEditorCommandsTextFormat['default']); - (0, _contentKitUtils.inherit)(MarkupModel, _contentKitCompilerModelsModel['default']); - - exports['default'] = MarkupModel; + exports['default'] = ItalicCommand; }); -define("content-kit-compiler/models/model", ["exports"], function (exports) { - /** - * @class Model - * @constructor - * @private - */ - "use strict"; +define('content-kit-editor/commands/link', ['exports', 'content-kit-editor/commands/text-format', 'content-kit-editor/views/prompt', 'content-kit-editor/utils/selection-utils', 'content-kit-utils'], function (exports, _contentKitEditorCommandsTextFormat, _contentKitEditorViewsPrompt, _contentKitEditorUtilsSelectionUtils, _contentKitUtils) { + 'use strict'; - function Model(options) { - options = options || {}; - var type_name = options.type_name; - var attributes = options.attributes; + var RegExpHttp = /^https?:\/\//i; - this.type = options.type || null; - if (type_name) { - this.type_name = type_name; - } - if (attributes) { - this.attributes = attributes; - } + function LinkCommand() { + _contentKitEditorCommandsTextFormat['default'].call(this, { + name: 'link', + tag: 'a', + action: 'createLink', + removeAction: 'unlink', + button: '', + prompt: new _contentKitEditorViewsPrompt['default']({ + command: this, + placeholder: 'Enter a url, press return...' + }) + }); } + (0, _contentKitUtils.inherit)(LinkCommand, _contentKitEditorCommandsTextFormat['default']); - /** - * @method createWithType - * @static - * @param type Type - * @param options Object - */ - Model.createWithType = function (type, options) { - options = options || {}; - options.type = type.id; - options.type_name = type.name; - return new this(options); + LinkCommand.prototype.exec = function (url) { + if (!url) { + return LinkCommand._super.prototype.unexec.call(this); + } + + if (this.tag === (0, _contentKitEditorUtilsSelectionUtils.getSelectionTagName)()) { + this.unexec(); + } else { + if (!RegExpHttp.test(url)) { + url = 'http://' + url; + } + LinkCommand._super.prototype.exec.call(this, url); + } }; - exports["default"] = Model; + exports['default'] = LinkCommand; }); -define('content-kit-compiler/models/post', ['exports', 'content-kit-compiler/utils/element-map'], function (exports, _contentKitCompilerUtilsElementMap) { +define('content-kit-editor/commands/list', ['exports', 'content-kit-editor/commands/text-format', 'content-kit-editor/utils/selection-utils', 'content-kit-utils'], function (exports, _contentKitEditorCommandsTextFormat, _contentKitEditorUtilsSelectionUtils, _contentKitUtils) { 'use strict'; - var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + function ListCommand(options) { + _contentKitEditorCommandsTextFormat['default'].call(this, options); + } + (0, _contentKitUtils.inherit)(ListCommand, _contentKitEditorCommandsTextFormat['default']); - // FIXME: making sections a linked-list would greatly improve this - - var Post = (function () { - function Post() { - _classCallCheck(this, Post); + ListCommand.prototype.exec = function () { + ListCommand._super.prototype.exec.call(this); - this.type = 'post'; - this.sections = []; - this.sectionElementMap = new _contentKitCompilerUtilsElementMap['default'](); + // After creation, lists need to be unwrapped + // TODO: eventually can remove this when direct model manipulation is ready + var listElement = (0, _contentKitEditorUtilsSelectionUtils.getSelectionBlockElement)(); + var wrapperNode = listElement.parentNode; + if (wrapperNode.firstChild === listElement) { + var editorNode = wrapperNode.parentNode; + editorNode.insertBefore(listElement, wrapperNode); + editorNode.removeChild(wrapperNode); + (0, _contentKitEditorUtilsSelectionUtils.selectNode)(listElement); } + }; - _createClass(Post, [{ - key: 'appendSection', - value: function appendSection(section) { - this.sections.push(section); - } - }, { - key: 'prependSection', - value: function prependSection(section) { - this.sections.unshift(section); - } - }, { - key: 'replaceSection', - value: function replaceSection(section, newSection) { - this.insertSectionAfter(newSection, section); - this.removeSection(section); - } - }, { - key: 'insertSectionAfter', - value: function insertSectionAfter(section, previousSection) { - var i, l; - for (i = 0, l = this.sections.length; i < l; i++) { - if (this.sections[i] === previousSection) { - this.sections.splice(i + 1, 0, section); - return; - } - } - throw new Error('Previous section was not found in post.sections'); - } - }, { - key: 'setSectionElement', - value: function setSectionElement(section, element) { - section.element = element; - this.sectionElementMap.set(element, section); - } - }, { - key: 'getSectionElement', - value: function getSectionElement(section) { - return section && section.element; - } - }, { - key: 'getElementSection', - value: function getElementSection(element) { - return this.sectionElementMap.get(element); - } - }, { - key: 'removeSection', - value: function removeSection(section) { - this.sectionElementMap.remove(section.element); - var i, l; - for (i = 0, l = this.sections.length; i < l; i++) { - if (this.sections[i] === section) { - this.sections.splice(i, 1); - return; - } - } - } - }, { - key: 'getPreviousSection', - value: function getPreviousSection(section) { - var i, l; - if (this.sections[0] !== section) { - for (i = 1, l = this.sections.length; i < l; i++) { - if (this.sections[i] === section) { - return this.sections[i - 1]; - } - } - } + ListCommand.prototype.checkAutoFormat = function (node) { + // Creates unordered lists when node starts with '- ' + // or ordered list if node starts with '1. ' + var regex = this.autoFormatRegex, + text; + if (node && regex) { + text = node.textContent; + if ('li' !== (0, _contentKitEditorUtilsSelectionUtils.getSelectionTagName)() && regex.test(text)) { + this.exec(); + window.getSelection().anchorNode.textContent = text.replace(regex, ''); + return true; } - }]); - - return Post; - })(); - - exports['default'] = Post; -}); -define('content-kit-compiler/parsers/document', ['exports'], function (exports) { - /** - * Abstracted `document` between node.js and browser - */ - - 'use strict'; - - var doc; - - if (typeof module !== 'undefined' && module.exports) { - var jsdom = require('jsdom').jsdom; - doc = jsdom(); - } else { - // A document instance separate from the html page document. (if browser supports it) - // Prevents images, scripts, and styles from executing while parsing - var implementation = document.implementation; - var createHTMLDocument = implementation.createHTMLDocument; - if (createHTMLDocument) { - doc = createHTMLDocument.call(implementation, ''); - } else { - doc = document; } - } + return false; + }; - exports['default'] = doc; + exports['default'] = ListCommand; }); -define('content-kit-compiler/parsers/html-parser', ['exports', 'content-kit-compiler/parsers/document', 'content-kit-compiler/models/block', 'content-kit-compiler/models/markup', 'content-kit-compiler/types/type', 'content-kit-compiler/types/default-types', 'content-kit-utils'], function (exports, _contentKitCompilerParsersDocument, _contentKitCompilerModelsBlock, _contentKitCompilerModelsMarkup, _contentKitCompilerTypesType, _contentKitCompilerTypesDefaultTypes, _contentKitUtils) { +define('content-kit-editor/commands/oembed', ['exports', 'content-kit-editor/commands/base', 'content-kit-editor/views/prompt', 'content-kit-editor/views/message', 'content-kit-utils', 'content-kit-editor/utils/http-utils'], function (exports, _contentKitEditorCommandsBase, _contentKitEditorViewsPrompt, _contentKitEditorViewsMessage, _contentKitUtils, _contentKitEditorUtilsHttpUtils) { 'use strict'; - var ELEMENT_NODE = 1; - var TEXT_NODE = 3; - var defaultAttributeBlacklist = { 'style': 1, 'class': 1 }; - - /** - * Returns the last block in the set or creates a default block if none exist yet. - */ - function getLastBlockOrCreate(blocks) { - var blockCount = blocks.length, - block; - if (blockCount) { - block = blocks[blockCount - 1]; + function loadTwitterWidgets(element) { + if (window.twttr) { + window.twttr.widgets.load(element); } else { - block = _contentKitCompilerModelsBlock['default'].createWithType(_contentKitCompilerTypesType['default'].PARAGRAPH); - blocks.push(block); + var script = document.createElement('script'); + script.async = true; + script.src = 'http://platform.twitter.com/widgets.js'; + document.head.appendChild(script); } - return block; } - /** - * Helper to parse elements at the root that aren't blocks - */ - function handleNonBlockAtRoot(parser, elementNode, blocks) { - var block = getLastBlockOrCreate(blocks); - var markup = parser.parseMarkupForElement(elementNode, block.value.length); - if (markup) { - block.markup = block.markup.concat(markup); - } - block.value += (0, _contentKitUtils.textOfNode)(elementNode); - } + function OEmbedCommand(options) { + _contentKitEditorCommandsBase['default'].call(this, { + name: 'embed', + button: '', + prompt: new _contentKitEditorViewsPrompt['default']({ + command: this, + placeholder: 'Paste a YouTube or Twitter url...' + }) + }); - /** - * @class HTMLParser - * @constructor - */ - function HTMLParser(options) { - var defaults = { - blockTypes: _contentKitCompilerTypesDefaultTypes.DefaultBlockTypeSet, - markupTypes: _contentKitCompilerTypesDefaultTypes.DefaultMarkupTypeSet, - attributeBlacklist: defaultAttributeBlacklist, - includeTypeNames: false - }; - (0, _contentKitUtils.mergeWithOptions)(this, defaults, options); + this.embedService = new _contentKitEditorUtilsHttpUtils.OEmbedder({ url: options.serviceUrl }); } + (0, _contentKitUtils.inherit)(OEmbedCommand, _contentKitEditorCommandsBase['default']); - /** - * @method parse - * @param html String of HTML content - * @return Array Parsed JSON content array - */ - HTMLParser.prototype.parse = function (html) { - var parsingNode = _contentKitCompilerParsersDocument['default'].createElement('div'); - parsingNode.innerHTML = (0, _contentKitUtils.sanitizeWhitespace)(html); - - var nodes = (0, _contentKitUtils.toArray)(parsingNode.childNodes); - var nodeCount = nodes.length; - var blocks = []; - var i, node, nodeType, block, text; - - for (i = 0; i < nodeCount; i++) { - node = nodes[i]; - nodeType = node.nodeType; + OEmbedCommand.prototype.exec = function (url) { + var command = this; + var editorContext = command.editorContext; + var embedIntent = command.embedIntent; + var index = editorContext.getCurrentBlockIndex(); - if (nodeType === ELEMENT_NODE) { - block = this.serializeBlockNode(node); - if (block) { - blocks.push(block); + embedIntent.showLoading(); + this.embedService.fetch({ + url: url, + complete: function complete(response, error) { + embedIntent.hideLoading(); + if (error) { + var errorMsg = error; + if (error.target && error.target.status === 0) { + errorMsg = 'Error: could not connect to embed service.'; + } else if (typeof error !== 'string') { + errorMsg = 'Error: unexpected embed error.'; + } + new _contentKitEditorViewsMessage['default']().showError(errorMsg); + embedIntent.show(); + } else if (response.error_message) { + new _contentKitEditorViewsMessage['default']().showError(response.error_message); + embedIntent.show(); } else { - handleNonBlockAtRoot(this, node, blocks); - } - } else if (nodeType === TEXT_NODE) { - text = node.nodeValue; - if ((0, _contentKitUtils.trim)(text)) { - block = getLastBlockOrCreate(blocks); - block.value += text; + throw new Error('Unimplemented EmbedModel is not a thing'); + var embedModel = new EmbedModel(response); + editorContext.insertBlock(embedModel, index); + editorContext.renderBlockAt(index); + if (embedModel.attributes.provider_name.toLowerCase() === 'twitter') { + loadTwitterWidgets(editorContext.element); + } } } - } - - return blocks; + }); }; - /** - * @method parseMarkupForElement - * @param node element node to parse - * @return {Array} parsed markups - */ - HTMLParser.prototype.parseMarkupForElement = function (node, startOffset) { - var index = 0; - var markups = []; - var currentNode, nodeType, markup; - - startOffset = startOffset || 0; - node = node.cloneNode(true); - markup = this.serializeMarkupNode(node, startOffset); - if (markup) { - markups.push(markup); - } + exports['default'] = OEmbedCommand; +}); +define('content-kit-editor/commands/ordered-list', ['exports', 'content-kit-editor/commands/list', 'content-kit-utils'], function (exports, _contentKitEditorCommandsList, _contentKitUtils) { + 'use strict'; - while (node.hasChildNodes()) { - currentNode = node.firstChild; - nodeType = currentNode.nodeType; + function OrderedListCommand() { + _contentKitEditorCommandsList['default'].call(this, { + name: 'ordered list', + tag: 'ol', + action: 'insertOrderedList' + }); + } + (0, _contentKitUtils.inherit)(OrderedListCommand, _contentKitEditorCommandsList['default']); - if (nodeType === ELEMENT_NODE) { - markup = this.serializeMarkupNode(currentNode, startOffset); - if (markup) { - markups.push(markup); - } - (0, _contentKitUtils.unwrapNode)(currentNode); - } else if (nodeType === TEXT_NODE) { - var text = (0, _contentKitUtils.sanitizeWhitespace)(currentNode.nodeValue); - if (index === 0) { - text = (0, _contentKitUtils.trimLeft)(text); - } - if (text) { - startOffset += text.length; - } - } + OrderedListCommand.prototype.autoFormatRegex = /^1\.\s/; - currentNode.parentNode.removeChild(currentNode); - index++; - } + exports['default'] = OrderedListCommand; +}); +define('content-kit-editor/commands/quote', ['exports', 'content-kit-editor/commands/format-block', 'content-kit-utils'], function (exports, _contentKitEditorCommandsFormatBlock, _contentKitUtils) { + 'use strict'; - return markups; - }; + function QuoteCommand() { + _contentKitEditorCommandsFormatBlock['default'].call(this, { + name: 'quote', + tag: 'blockquote', + button: '' + }); + } + (0, _contentKitUtils.inherit)(QuoteCommand, _contentKitEditorCommandsFormatBlock['default']); - /** - * @method serializeBlockNode - * @param node element node to parse - * @return {BlockModel} parsed block model - * Serializes a single block type node into a model - */ - HTMLParser.prototype.serializeBlockNode = function (node) { - var type = this.blockTypes.findByNode(node); - if (type) { - return new _contentKitCompilerModelsBlock['default']({ - type: type.id, - type_name: this.includeTypeNames && type.name, - value: (0, _contentKitUtils.trim)((0, _contentKitUtils.textOfNode)(node)), - attributes: (0, _contentKitUtils.attributesForNode)(node, this.attributeBlacklist), - markup: this.parseMarkupForElement(node) - }); - } - }; + exports['default'] = QuoteCommand; +}); +define('content-kit-editor/commands/subheading', ['exports', 'content-kit-editor/commands/format-block', 'content-kit-utils'], function (exports, _contentKitEditorCommandsFormatBlock, _contentKitUtils) { + 'use strict'; - /** - * @method serializeMarkupNode - * @param node element node to parse - * @param startIndex - * @return {MarkupModel} markup model - * Serializes markup of a single html element node (no child elements) - */ - HTMLParser.prototype.serializeMarkupNode = function (node, startIndex) { - var type = this.markupTypes.findByNode(node); - var selfClosing, endIndex; - - if (type) { - selfClosing = type.selfClosing; - if (!selfClosing && !node.hasChildNodes()) { - return; - } // check for empty nodes - - endIndex = startIndex + (selfClosing ? 0 : (0, _contentKitUtils.textOfNode)(node).length); - if (endIndex > startIndex || selfClosing && endIndex === startIndex) { - // check for empty nodes - return new _contentKitCompilerModelsMarkup['default']({ - type: type.id, - type_name: this.includeTypeNames && type.name, - start: startIndex, - end: endIndex, - attributes: (0, _contentKitUtils.attributesForNode)(node, this.attributeBlacklist) - }); - } - } - }; + function SubheadingCommand() { + _contentKitEditorCommandsFormatBlock['default'].call(this, { + name: 'subheading', + tag: 'h3', + button: '2' + }); + } + (0, _contentKitUtils.inherit)(SubheadingCommand, _contentKitEditorCommandsFormatBlock['default']); - exports['default'] = HTMLParser; + exports['default'] = SubheadingCommand; }); -define('content-kit-compiler/parsers/mobiledoc', ['exports', 'content-kit-compiler/post-builder'], function (exports, _contentKitCompilerPostBuilder) { +define('content-kit-editor/commands/text-format', ['exports', 'content-kit-editor/commands/base', 'content-kit-utils'], function (exports, _contentKitEditorCommandsBase, _contentKitUtils) { 'use strict'; - var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); + function TextFormatCommand(options) { + options = options || {}; + _contentKitEditorCommandsBase['default'].call(this, options); + this.tag = options.tag; + this.mappedTags = options.mappedTags || []; + this.mappedTags.push(this.tag); + this.action = options.action || this.name; + this.removeAction = options.removeAction || this.action; + } + (0, _contentKitUtils.inherit)(TextFormatCommand, _contentKitEditorCommandsBase['default']); - var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + TextFormatCommand.prototype = { + exec: function exec(value) { + document.execCommand(this.action, false, value || null); + }, + unexec: function unexec(value) { + document.execCommand(this.removeAction, false, value || null); + } + }; - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - - /* - * input mobiledoc: [ markers, elements ] - * output: Post - * - */ - - var MobiledocParser = (function () { - function MobiledocParser() { - _classCallCheck(this, MobiledocParser); - - this.builder = (0, _contentKitCompilerPostBuilder.generateBuilder)(); - } - - _createClass(MobiledocParser, [{ - key: 'parse', - value: function parse(mobiledoc) { - var markerTypes = mobiledoc[0]; - var sections = mobiledoc[1]; - - var post = this.builder.generatePost(); - - this.markerTypes = this.parseMarkerTypes(markerTypes); - this.parseSections(sections, post); - - return post; - } - }, { - key: 'parseMarkerTypes', - value: function parseMarkerTypes(markerTypes) { - var _this = this; - - return markerTypes.map(function (markerType) { - return _this.parseMarkerType(markerType); - }); - } - }, { - key: 'parseMarkerType', - value: function parseMarkerType(_ref) { - var _ref2 = _slicedToArray(_ref, 2); - - var tagName = _ref2[0]; - var attributes = _ref2[1]; - - return this.builder.generateMarkerType(tagName, attributes); - } - }, { - key: 'parseSections', - value: function parseSections(sections, post) { - var _this2 = this; - - sections.forEach(function (section) { - return _this2.parseSection(section, post); - }); - } - }, { - key: 'parseSection', - value: function parseSection(section, post) { - var _section = _slicedToArray(section, 1); - - var type = _section[0]; - - switch (type) { - case 1: - // markup section - this.parseMarkupSection(section, post); - break; - default: - throw new Error('Unexpected section type ' + type); - } - } - }, { - key: 'parseMarkupSection', - value: function parseMarkupSection(_ref3, post) { - var _ref32 = _slicedToArray(_ref3, 3); - - var type = _ref32[0]; - var tagName = _ref32[1]; - var markers = _ref32[2]; - - var attributes = null; - var isGenerated = false; - var section = this.builder.generateSection(tagName, attributes, isGenerated); - - post.appendSection(section); - this.parseMarkers(markers, section); - } - }, { - key: 'parseMarkers', - value: function parseMarkers(markers, section) { - var _this3 = this; - - markers.forEach(function (marker) { - return _this3.parseMarker(marker, section); - }); - } - }, { - key: 'parseMarker', - value: function parseMarker(_ref4, section) { - var _this4 = this; - - var _ref42 = _slicedToArray(_ref4, 3); - - var markerTypeIndexes = _ref42[0]; - var closeCount = _ref42[1]; - var value = _ref42[2]; - - var markerTypes = markerTypeIndexes.map(function (index) { - return _this4.markerTypes[index]; - }); - var marker = this.builder.generateMarker(markerTypes, closeCount, value); - section.markers.push(marker); - } - }]); - - return MobiledocParser; - })(); - - exports['default'] = MobiledocParser; -}); -define('content-kit-compiler/parsers/new-html-parser', ['exports', 'content-kit-compiler/post-builder', 'content-kit-utils'], function (exports, _contentKitCompilerPostBuilder, _contentKitUtils) { - 'use strict'; - - var ELEMENT_NODE = 1; - var TEXT_NODE = 3; - - var MARKUP_SECTION_TAG_NAMES = ['P', 'H3', 'H2', 'H1', 'BLOCKQUOTE', 'UL', 'IMG', 'OL']; - - var ALLOWED_ATTRIBUTES = ['href', 'rel', 'src']; - - function isEmptyTextNode(node) { - return node.nodeType === TEXT_NODE && (0, _contentKitUtils.trim)(node.textContent) === ''; - } - - // FIXME: should probably always return an array - function readAttributes(node) { - var attributes = null; - if (node.hasAttributes()) { - attributes = []; - var i, l; - for (i = 0, l = node.attributes.length; i < l; i++) { - if (ALLOWED_ATTRIBUTES.indexOf(node.attributes[i].name) !== -1) { - attributes.push(node.attributes[i].name); - attributes.push(node.attributes[i].value); - } - } - if (attributes.length === 0) { - return null; - } - } - return attributes; - } - - var VALID_MARKER_ELEMENTS = ['B', 'I', 'STRONG', 'EM', 'A']; - - function isValidMarkerElement(element) { - return VALID_MARKER_ELEMENTS.indexOf(element.tagName) !== -1; - } - - function parseMarkers(section, postBuilder, topNode) { - var markerTypes = []; - var text = null; - var currentNode = topNode; - while (currentNode) { - switch (currentNode.nodeType) { - case ELEMENT_NODE: - if (isValidMarkerElement(currentNode)) { - markerTypes.push(postBuilder.generateMarkerType(currentNode.tagName, readAttributes(currentNode))); - } - break; - case TEXT_NODE: - text = (text || '') + currentNode.textContent; - break; - } - - if (currentNode.firstChild) { - if (isValidMarkerElement(currentNode) && text !== null) { - section.markers.push(postBuilder.generateMarker(markerTypes, 0, text)); - markerTypes = []; - text = null; - } - currentNode = currentNode.firstChild; - } else if (currentNode.nextSibling) { - if (currentNode === topNode) { - section.markers.push(postBuilder.generateMarker(markerTypes, markerTypes.length, text)); - break; - } else { - currentNode = currentNode.nextSibling; - if (currentNode.nodeType === ELEMENT_NODE && isValidMarkerElement(currentNode) && text !== null) { - section.markers.push(postBuilder.generateMarker(markerTypes, 0, text)); - markerTypes = []; - text = null; - } - } - } else { - var toClose = 0; - while (currentNode && !currentNode.nextSibling && currentNode !== topNode) { - currentNode = currentNode.parentNode; - if (isValidMarkerElement(currentNode)) { - toClose++; - } - } - - section.markers.push(postBuilder.generateMarker(markerTypes, toClose, text)); - markerTypes = []; - text = null; - - if (currentNode === topNode) { - break; - } else { - currentNode = currentNode.nextSibling; - if (currentNode === topNode) { - break; - } - } - } - } - } - - function NewHTMLParser() { - this.postBuilder = (0, _contentKitCompilerPostBuilder.generateBuilder)(); - } - - NewHTMLParser.prototype = { - parseSection: function parseSection(previousSection, sectionElement) { - var postBuilder = this.postBuilder; - var section; - switch (sectionElement.nodeType) { - case ELEMENT_NODE: - var tagName = sectionElement.tagName; - //

, etc - if (MARKUP_SECTION_TAG_NAMES.indexOf(tagName) !== -1) { - section = postBuilder.generateSection(tagName, readAttributes(sectionElement)); - var node = sectionElement.firstChild; - while (node) { - parseMarkers(section, postBuilder, node); - node = node.nextSibling; - } - // , etc - } else { - if (previousSection && previousSection.isGenerated) { - section = previousSection; - } else { - section = postBuilder.generateSection('P', {}, true); - } - parseMarkers(section, postBuilder, sectionElement); - } - break; - case TEXT_NODE: - if (previousSection && previousSection.isGenerated) { - section = previousSection; - } else { - section = postBuilder.generateSection('P', {}, true); - } - parseMarkers(section, postBuilder, sectionElement); - break; - } - return section; - }, - parse: function parse(postElement) { - var post = this.postBuilder.generatePost(); - var i, l, section, previousSection, sectionElement; - // FIXME: Instead of storing isGenerated on sections, and passing - // the previous section to the parser, we could instead do a two-pass - // parse. The first pass identifies sections and gathers a list of - // dom nodes that can be parsed for markers, the second pass parses - // for markers. - for (i = 0, l = postElement.childNodes.length; i < l; i++) { - sectionElement = postElement.childNodes[i]; - if (!isEmptyTextNode(sectionElement)) { - section = this.parseSection(previousSection, sectionElement); - if (section !== previousSection) { - post.appendSection(section); - previousSection = section; - } - } - } - return post; - } - }; - - exports['default'] = NewHTMLParser; -}); -define('content-kit-compiler/post-builder', ['exports', 'content-kit-compiler/models/post'], function (exports, _contentKitCompilerModelsPost) { - 'use strict'; - - exports.generateBuilder = generateBuilder; - - var builder = { - generatePost: function generatePost() { - return new _contentKitCompilerModelsPost['default'](); - }, - generateSection: function generateSection(tagName, attributes, isGenerated) { - var section = { - type: 'markupSection', - tagName: tagName, - markers: [] - }; - if (attributes && attributes.length) { - section.attributes = attributes; - } - if (isGenerated) { - section.isGenerated = !!isGenerated; - } - return section; - }, - // open: Array - // close: Integer - // value: String - generateMarker: function generateMarker(open, close, value) { - return { - type: 'marker', - open: open, - close: close, - value: value - }; - }, - generateMarkerType: function generateMarkerType(tagName, attributes) { - if (attributes) { - // FIXME: This could also be cached - return { - type: 'markerType', - tagName: tagName, - attributes: attributes - }; - } - var markerType = this._markerTypeCache[tagName]; - if (!markerType) { - this._markerTypeCache[tagName] = markerType = { - type: 'markerType', - tagName: tagName - }; - } - return markerType; - } - }; - - function reset(builder) { - builder._markerTypeCache = {}; - } - - function generateBuilder() { - reset(builder); - return builder; - } -}); -define('content-kit-compiler/renderers/card-renderer', ['exports'], function (exports) { - /** - * @class CardRenderer - * @constructor - */ - 'use strict'; - - function CardRenderer(cards) { - this.cards = cards; - } - - /** - * @method render - * @param model a card model - * @return String html - */ - CardRenderer.prototype.render = function (model) { - var render = this.cards[model.attributes.name]; - return '
' + render(model.attributes.payload) + '
'; - }; - - exports['default'] = CardRenderer; -}); -define('content-kit-compiler/renderers/html-element-renderer', ['exports', 'content-kit-utils'], function (exports, _contentKitUtils) { - 'use strict'; - - /** - * Builds an opening html tag. i.e. '

'; - } + var type = _ref32[0]; + var tagName = _ref32[1]; + var markers = _ref32[2]; - function imageRenderer(model) { - return '
' + '
' + this.render(model) + '
' + '
'; - } + var attributes = null; + var isGenerated = false; + var section = this.builder.generateSection(tagName, attributes, isGenerated); - var typeRenderers = {}; - typeRenderers[_contentKitCompiler.Type.EMBED.id] = embedRenderer; - typeRenderers[_contentKitCompiler.Type.IMAGE.id] = imageRenderer; + post.appendSection(section); + this.parseMarkers(markers, section); + } + }, { + key: 'parseMarkers', + value: function parseMarkers(markers, section) { + var _this3 = this; - /** - * @class EditorHTMLRenderer - * @constructor - * Subclass of HTMLRenderer specifically for the Editor - * Wraps interactive elements to add functionality - */ - function EditorHTMLRenderer(options) { - var rendererOptions = { - typeRenderers: typeRenderers - }; - (0, _contentKitUtils.merge)(rendererOptions, options); - _contentKitCompiler.HTMLRenderer.call(this, rendererOptions); - } - (0, _contentKitUtils.inherit)(EditorHTMLRenderer, _contentKitCompiler.HTMLRenderer); + markers.forEach(function (marker) { + return _this3.parseMarker(marker, section); + }); + } + }, { + key: 'parseMarker', + value: function parseMarker(_ref4, section) { + var _this4 = this; - exports['default'] = EditorHTMLRenderer; -}); -define('content-kit-editor/renderers/instagram', ['exports'], function (exports) { - 'use strict'; + var _ref42 = _slicedToArray(_ref4, 3); - function InstagramRenderer() {} - InstagramRenderer.prototype.render = function (model) { - return ''; - }; + var markerTypeIndexes = _ref42[0]; + var closeCount = _ref42[1]; + var value = _ref42[2]; - exports['default'] = InstagramRenderer; -}); -define('content-kit-editor/renderers/link-image-renderer', ['exports'], function (exports) { - 'use strict'; + var markerTypes = markerTypeIndexes.map(function (index) { + return _this4.markerTypes[index]; + }); + var marker = this.builder.generateMarker(markerTypes, closeCount, value); + section.markers.push(marker); + } + }]); - function LinkImageRenderer() {} - LinkImageRenderer.prototype.render = function (model) { - return ''; - }; + return MobiledocParser; + })(); - exports['default'] = LinkImageRenderer; + exports['default'] = MobiledocParser; }); -define('content-kit-editor/renderers/new-dom-renderer', ['exports'], function (exports) { +define('content-kit-editor/renderers/editor-dom', ['exports'], function (exports) { 'use strict'; function createElementFromMarkerType(doc, markerType) { @@ -2726,7 +1547,7 @@ define('content-kit-editor/renderers/new-dom-renderer', ['exports'], function (e exports['default'] = NewDOMRenderer; }); -define('content-kit-editor/renderers/new-serializer', ['exports', 'content-kit-editor/utils/compiler'], function (exports, _contentKitEditorUtilsCompiler) { +define('content-kit-editor/renderers/mobiledoc', ['exports', 'content-kit-editor/utils/compiler'], function (exports, _contentKitEditorUtilsCompiler) { 'use strict'; var visitor = { @@ -2781,7 +1602,7 @@ define('content-kit-editor/renderers/new-serializer', ['exports', 'content-kit-e }; exports['default'] = { - serialize: function serialize(post) { + render: function render(post) { var opcodes = []; (0, _contentKitEditorUtilsCompiler.visit)(visitor, post, opcodes); var compiler = Object.create(postOpcodeCompiler); @@ -2790,37 +1611,10 @@ define('content-kit-editor/renderers/new-serializer', ['exports', 'content-kit-e } }; }); -define('content-kit-editor/renderers/twitter', ['exports'], function (exports) { - 'use strict'; - - function TwitterRenderer() {} - TwitterRenderer.prototype.render = function (model) { - return ''; - }; - - exports['default'] = TwitterRenderer; -}); -define('content-kit-editor/renderers/youtube', ['exports'], function (exports) { +define('content-kit-editor/runtime/renderers/mobiledoc-dom', ['exports', 'mobiledoc-dom-renderer'], function (exports, _mobiledocDomRenderer) { 'use strict'; - var RegExVideoId = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; - - function getVideoIdFromUrl(url) { - var match = url && url.match(RegExVideoId); - if (match && match[1].length === 11) { - return match[1]; - } - return null; - } - - function YouTubeRenderer() {} - YouTubeRenderer.prototype.render = function (model) { - var videoId = getVideoIdFromUrl(model.attributes.url); - var embedUrl = 'http://www.youtube.com/embed/' + videoId + '?controls=2&showinfo=0&color=white&theme=light'; - return ''; - }; - - exports['default'] = YouTubeRenderer; + exports['default'] = _mobiledocDomRenderer['default']; }); define('content-kit-editor/utils/compat', ['exports', 'content-kit-editor/utils/doc', 'content-kit-editor/utils/win'], function (exports, _contentKitEditorUtilsDoc, _contentKitEditorUtilsWin) { 'use strict'; @@ -2866,15 +1660,6 @@ define("content-kit-editor/utils/compiler", ["exports"], function (exports) { } } }); -define("content-kit-editor/utils/doc", ["exports"], function (exports) { - // FIXME in theory, we might want to make this safe for node usage and - // return a jsdom? - // In practice we probably don't need this for the editor since it won't ever - // execute in a solely server-side environment - "use strict"; - - exports["default"] = document; -}); define("content-kit-editor/utils/dom-utils", ["exports"], function (exports) { "use strict"; @@ -2918,27 +1703,27 @@ define('content-kit-editor/utils/element-map', ['exports'], function (exports) { _createClass(ElementMap, [{ key: 'set', value: function set(key, value) { - var uuid = key.dataset.uuid; + var uuid = key._uuid; if (!uuid) { - key.dataset.uuid = uuid = uuidGenerator++; + key._uuid = uuid = '' + uuidGenerator++; } this._map[uuid] = value; } }, { key: 'get', value: function get(key) { - if (key.dataset && key.dataset.uuid) { - return this._map[key.dataset.uuid]; + if (key._uuid) { + return this._map[key._uuid]; } return null; } }, { key: 'remove', value: function remove(key) { - if (!key.dataset.uuid) { + if (!key._uuid) { throw new Error('tried to fetch a value for an element not seen before'); } - delete this._map[key.dataset.uuid]; + delete this._map[key._uuid]; } }]); @@ -2947,11 +1732,11 @@ define('content-kit-editor/utils/element-map', ['exports'], function (exports) { exports['default'] = ElementMap; }); -define('content-kit-editor/utils/element-utils', ['exports', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorUtilsCompat) { +define('content-kit-editor/utils/element-utils', ['exports'], function (exports) { 'use strict'; function createDiv(className) { - var div = _contentKitEditorUtilsCompat.doc.createElement('div'); + var div = document.createElement('div'); if (className) { div.className = className; } @@ -3001,9 +1786,9 @@ define('content-kit-editor/utils/element-utils', ['exports', 'content-kit-editor } function getElementRelativeOffset(element) { - var offset = { left: 0, top: -_contentKitEditorUtilsCompat.win.pageYOffset }; + var offset = { left: 0, top: -window.pageYOffset }; var offsetParent = element.offsetParent; - var offsetParentPosition = _contentKitEditorUtilsCompat.win.getComputedStyle(offsetParent).position; + var offsetParentPosition = window.getComputedStyle(offsetParent).position; var offsetParentRect; if (offsetParentPosition === 'relative') { @@ -3015,7 +1800,7 @@ define('content-kit-editor/utils/element-utils', ['exports', 'content-kit-editor } function getElementComputedStyleNumericProp(element, prop) { - return parseFloat(_contentKitEditorUtilsCompat.win.getComputedStyle(element)[prop]); + return parseFloat(window.getComputedStyle(element)[prop]); } function positionElementToRect(element, rect, topOffset, leftOffset) { @@ -3115,8 +1900,7 @@ define("content-kit-editor/utils/event-emitter", ["exports"], function (exports) exports["default"] = EventEmitter; }); -define('content-kit-editor/utils/http-utils', ['exports', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorUtilsCompat) { - /* global JSON */ +define('content-kit-editor/utils/http-utils', ['exports'], function (exports) { 'use strict'; function createXHR(options) { @@ -3189,7 +1973,7 @@ define('content-kit-editor/utils/http-utils', ['exports', 'content-kit-editor/ut var file = options.file || fileInput && fileInput.files && fileInput.files[0]; var callback = options.complete; var maxFileSize = this.maxFileSize; - if (!file || !(file instanceof _contentKitEditorUtilsCompat.win.File)) { + if (!file || !(file instanceof window.File)) { return; } @@ -3257,11 +2041,74 @@ define("content-kit-editor/utils/keycodes", ["exports"], function (exports) { M: 77 }; }); -define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-editor/utils/element-utils', 'content-kit-compiler', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorUtilsElementUtils, _contentKitCompiler, _contentKitEditorUtilsCompat) { +define('content-kit-editor/utils/post-builder', ['exports', 'content-kit-editor/models/post'], function (exports, _contentKitEditorModelsPost) { + 'use strict'; + + exports.generateBuilder = generateBuilder; + + var builder = { + generatePost: function generatePost() { + return new _contentKitEditorModelsPost['default'](); + }, + generateSection: function generateSection(tagName, attributes, isGenerated) { + var section = { + type: 'markupSection', + tagName: tagName, + markers: [] + }; + if (attributes && attributes.length) { + section.attributes = attributes; + } + if (isGenerated) { + section.isGenerated = !!isGenerated; + } + return section; + }, + // open: Array + // close: Integer + // value: String + generateMarker: function generateMarker(open, close, value) { + return { + type: 'marker', + open: open, + close: close, + value: value + }; + }, + generateMarkerType: function generateMarkerType(tagName, attributes) { + if (attributes) { + // FIXME: This could also be cached + return { + type: 'markerType', + tagName: tagName, + attributes: attributes + }; + } + var markerType = this._markerTypeCache[tagName]; + if (!markerType) { + this._markerTypeCache[tagName] = markerType = { + type: 'markerType', + tagName: tagName + }; + } + return markerType; + } + }; + + function reset(builder) { + builder._markerTypeCache = {}; + } + + function generateBuilder() { + reset(builder); + return builder; + } +}); +define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-editor/utils/element-utils'], function (exports, _contentKitEditorUtilsElementUtils) { 'use strict'; // TODO: remove, pass in Editor's current block set - var RootTags = [_contentKitCompiler.Type.PARAGRAPH.tag, _contentKitCompiler.Type.HEADING.tag, _contentKitCompiler.Type.SUBHEADING.tag, _contentKitCompiler.Type.QUOTE.tag, _contentKitCompiler.Type.LIST.tag, _contentKitCompiler.Type.ORDERED_LIST.tag]; + var RootTags = ['p', 'h2', 'h3', 'blockquote', 'ul', 'ol']; var SelectionDirection = { LEFT_TO_RIGHT: 1, @@ -3281,13 +2128,13 @@ define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-edit } function getSelectionElement(selection) { - selection = selection || _contentKitEditorUtilsCompat.win.getSelection(); + selection = selection || window.getSelection(); var node = getDirectionOfSelection(selection) === SelectionDirection.LEFT_TO_RIGHT ? selection.anchorNode : selection.focusNode; return node && (node.nodeType === 3 ? node.parentNode : node); } function getSelectionBlockElement(selection) { - selection = selection || _contentKitEditorUtilsCompat.win.getSelection(); + selection = selection || window.getSelection(); var element = getSelectionElement(); var tag = element && element.tagName.toLowerCase(); while (tag && RootTags.indexOf(tag) === -1) { @@ -3336,14 +2183,14 @@ define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-edit } function restoreRange(range) { - var selection = _contentKitEditorUtilsCompat.win.getSelection(); + var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); } function selectNode(node) { - var range = _contentKitEditorUtilsCompat.doc.createRange(); - var selection = _contentKitEditorUtilsCompat.win.getSelection(); + var range = document.createRange(); + var selection = window.getSelection(); range.setStart(node, 0); range.setEnd(node, node.length); selection.removeAllRanges(); @@ -3351,8 +2198,8 @@ define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-edit } function setCursorIndexInElement(element, index) { - var range = _contentKitEditorUtilsCompat.doc.createRange(); - var selection = _contentKitEditorUtilsCompat.win.getSelection(); + var range = document.createRange(); + var selection = window.getSelection(); range.setStart(element, index); range.collapse(true); selection.removeAllRanges(); @@ -3366,7 +2213,7 @@ define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-edit function getCursorOffsetInElement(element) { // http://stackoverflow.com/questions/4811822/get-a-ranges-start-and-end-offsets-relative-to-its-parent-container/4812022#4812022 var caretOffset = 0; - var selection = _contentKitEditorUtilsCompat.win.getSelection(); + var selection = window.getSelection(); if (selection.rangeCount > 0) { var range = selection.getRangeAt(0); var preCaretRange = range.cloneRange(); @@ -3391,20 +2238,7 @@ define('content-kit-editor/utils/selection-utils', ['exports', 'content-kit-edit exports.setCursorIndexInElement = setCursorIndexInElement; exports.getCursorOffsetInElement = getCursorOffsetInElement; }); -define('content-kit-editor/utils/win', ['exports', 'content-kit-compiler'], function (exports, _contentKitCompiler) { - 'use strict'; - - var win; - if (typeof window !== 'undefined') { - win = window; - } else { - // jsdom provides a defaultView - win = _contentKitCompiler.doc.defaultView; - } - - exports['default'] = win; -}); -define('content-kit-editor/views/embed-intent', ['exports', 'content-kit-editor/views/view', 'content-kit-editor/views/toolbar', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/element-utils', 'content-kit-editor/utils/keycodes', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorViewsView, _contentKitEditorViewsToolbar, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsElementUtils, _contentKitEditorUtilsKeycodes, _contentKitEditorUtilsCompat) { +define('content-kit-editor/views/embed-intent', ['exports', 'content-kit-editor/views/view', 'content-kit-editor/views/toolbar', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/element-utils', 'content-kit-editor/utils/keycodes'], function (exports, _contentKitEditorViewsView, _contentKitEditorViewsToolbar, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsElementUtils, _contentKitEditorUtilsKeycodes) { 'use strict'; var LayoutStyle = { @@ -3428,7 +2262,7 @@ define('content-kit-editor/views/embed-intent', ['exports', 'content-kit-editor/ embedIntent.isActive = false; embedIntent.editorContext = options.editorContext; embedIntent.loadingIndicator = (0, _contentKitEditorUtilsElementUtils.createDiv)('ck-embed-loading'); - embedIntent.button = _contentKitEditorUtilsCompat.doc.createElement('button'); + embedIntent.button = document.createElement('button'); embedIntent.button.className = 'ck-embed-intent-btn'; embedIntent.button.title = 'Insert image or embed...'; embedIntent.element.appendChild(embedIntent.button); @@ -3459,19 +2293,19 @@ define('content-kit-editor/views/embed-intent', ['exports', 'content-kit-editor/ } rootElement.addEventListener('keyup', embedIntentHandler); - _contentKitEditorUtilsCompat.doc.addEventListener('mouseup', function () { + document.addEventListener('mouseup', function () { setTimeout(function () { embedIntentHandler(); }); }); - _contentKitEditorUtilsCompat.doc.addEventListener('keyup', function (e) { + document.addEventListener('keyup', function (e) { if (e.keyCode === _contentKitEditorUtilsKeycodes['default'].ESC) { embedIntent.hide(); } }); - _contentKitEditorUtilsCompat.win.addEventListener('resize', function () { + window.addEventListener('resize', function () { if (embedIntent.isShowing) { embedIntent.reposition(); } @@ -3561,10 +2395,10 @@ define('content-kit-editor/views/message', ['exports', 'content-kit-editor/views exports['default'] = Message; }); -define('content-kit-editor/views/prompt', ['exports', 'content-kit-editor/views/view', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/element-utils', 'content-kit-editor/utils/keycodes', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorViewsView, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsElementUtils, _contentKitEditorUtilsKeycodes, _contentKitEditorUtilsCompat) { +define('content-kit-editor/views/prompt', ['exports', 'content-kit-editor/views/view', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/element-utils', 'content-kit-editor/utils/keycodes'], function (exports, _contentKitEditorViewsView, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsElementUtils, _contentKitEditorUtilsKeycodes) { 'use strict'; - var container = _contentKitEditorUtilsCompat.doc.body; + var container = document.body; var hiliter = (0, _contentKitEditorUtilsElementUtils.createDiv)('ck-editor-hilite'); function positionHiliteRange(range) { @@ -3596,7 +2430,7 @@ define('content-kit-editor/views/prompt', ['exports', 'content-kit-editor/views/ } }); - _contentKitEditorUtilsCompat.win.addEventListener('resize', function () { + window.addEventListener('resize', function () { var activeHilite = hiliter.parentNode; var range = prompt.range; if (activeHilite && range) { @@ -3609,7 +2443,7 @@ define('content-kit-editor/views/prompt', ['exports', 'content-kit-editor/views/ Prompt.prototype.show = function (callback) { var prompt = this; var element = prompt.element; - var selection = _contentKitEditorUtilsCompat.win.getSelection(); + var selection = window.getSelection(); var range = selection && selection.rangeCount && selection.getRangeAt(0); element.value = null; prompt.range = range || null; @@ -3633,7 +2467,7 @@ define('content-kit-editor/views/prompt', ['exports', 'content-kit-editor/views/ exports['default'] = Prompt; }); -define('content-kit-editor/views/text-format-toolbar', ['exports', 'content-kit-editor/views/toolbar', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/keycodes', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorViewsToolbar, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsKeycodes, _contentKitEditorUtilsCompat) { +define('content-kit-editor/views/text-format-toolbar', ['exports', 'content-kit-editor/views/toolbar', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/keycodes'], function (exports, _contentKitEditorViewsToolbar, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsKeycodes) { 'use strict'; function selectionIsEditableByToolbar(selection, toolbar) { @@ -3641,7 +2475,7 @@ define('content-kit-editor/views/text-format-toolbar', ['exports', 'content-kit- } function handleTextSelection(toolbar) { - var selection = _contentKitEditorUtilsCompat.win.getSelection(); + var selection = window.getSelection(); if (toolbar.sticky) { toolbar.updateForSelection(selectionIsEditableByToolbar(selection, toolbar) ? selection : null); } else { @@ -3662,13 +2496,13 @@ define('content-kit-editor/views/text-format-toolbar', ['exports', 'content-kit- handleTextSelection(toolbar); }); - _contentKitEditorUtilsCompat.doc.addEventListener('mouseup', function () { + document.addEventListener('mouseup', function () { setTimeout(function () { handleTextSelection(toolbar); }); }); - _contentKitEditorUtilsCompat.doc.addEventListener('keyup', function (e) { + document.addEventListener('keyup', function (e) { var key = e.keyCode; if (key === 116) { //F5 @@ -3679,10 +2513,10 @@ define('content-kit-editor/views/text-format-toolbar', ['exports', 'content-kit- } }); - _contentKitEditorUtilsCompat.win.addEventListener('resize', function () { + window.addEventListener('resize', function () { if (!toolbar.sticky && toolbar.isShowing) { var activePromptRange = toolbar.activePrompt && toolbar.activePrompt.range; - toolbar.positionToContent(activePromptRange ? activePromptRange : _contentKitEditorUtilsCompat.win.getSelection().getRangeAt(0)); + toolbar.positionToContent(activePromptRange ? activePromptRange : window.getSelection().getRangeAt(0)); } }); } @@ -3690,7 +2524,7 @@ define('content-kit-editor/views/text-format-toolbar', ['exports', 'content-kit- exports['default'] = TextFormatToolbar; }); -define('content-kit-editor/views/toolbar-button', ['exports', 'content-kit-compiler'], function (exports, _contentKitCompiler) { +define('content-kit-editor/views/toolbar-button', ['exports'], function (exports) { 'use strict'; var buttonClassName = 'ck-toolbar-btn'; @@ -3700,7 +2534,7 @@ define('content-kit-editor/views/toolbar-button', ['exports', 'content-kit-compi var toolbar = options.toolbar; var command = options.command; var prompt = command.prompt; - var element = _contentKitCompiler.doc.createElement('button'); + var element = document.createElement('button'); button.element = element; button.command = command; @@ -3739,7 +2573,7 @@ define('content-kit-editor/views/toolbar-button', ['exports', 'content-kit-compi exports['default'] = ToolbarButton; }); -define('content-kit-editor/views/toolbar', ['exports', 'content-kit-editor/views/view', 'content-kit-editor/views/toolbar-button', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/element-utils', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorViewsView, _contentKitEditorViewsToolbarButton, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsElementUtils, _contentKitEditorUtilsCompat) { +define('content-kit-editor/views/toolbar', ['exports', 'content-kit-editor/views/view', 'content-kit-editor/views/toolbar-button', 'content-kit-utils', 'content-kit-editor/utils/selection-utils', 'content-kit-editor/utils/element-utils'], function (exports, _contentKitEditorViewsView, _contentKitEditorViewsToolbarButton, _contentKitUtils, _contentKitEditorUtilsSelectionUtils, _contentKitEditorUtilsElementUtils) { 'use strict'; var ToolbarDirection = { @@ -3796,7 +2630,7 @@ define('content-kit-editor/views/toolbar', ['exports', 'content-kit-editor/views } // Closes prompt if displayed when changing selection - _contentKitEditorUtilsCompat.doc.addEventListener('mouseup', function () { + document.addEventListener('mouseup', function () { toolbar.dismissPrompt(); }); } @@ -3842,7 +2676,7 @@ define('content-kit-editor/views/toolbar', ['exports', 'content-kit-editor/views Toolbar.prototype.updateForSelection = function (selection) { var toolbar = this; - selection = selection || _contentKitEditorUtilsCompat.win.getSelection(); + selection = selection || window.getSelection(); if (toolbar.sticky) { updateButtonsForSelection(toolbar.buttons, selection); } else if (!selection.isCollapsed) { @@ -3862,7 +2696,7 @@ define('content-kit-editor/views/toolbar', ['exports', 'content-kit-editor/views positioningMethod = _contentKitEditorUtilsElementUtils.positionElementCenteredAbove; } position = positioningMethod(this.element, content); - sideEdgeOffset = Math.min(Math.max(10, position.left), _contentKitEditorUtilsCompat.doc.body.clientWidth - this.element.offsetWidth - 10); + sideEdgeOffset = Math.min(Math.max(10, position.left), document.body.clientWidth - this.element.offsetWidth - 10); this.contentElement.style.transform = 'translateX(' + (sideEdgeOffset - position.left) + 'px)'; }; @@ -3940,7 +2774,7 @@ define('content-kit-editor/views/tooltip', ['exports', 'content-kit-editor/views exports['default'] = Tooltip; }); -define('content-kit-editor/views/view', ['exports', 'content-kit-editor/utils/compat'], function (exports, _contentKitEditorUtilsCompat) { +define('content-kit-editor/views/view', ['exports'], function (exports) { 'use strict'; function renderClasses(view) { @@ -3956,8 +2790,8 @@ define('content-kit-editor/views/view', ['exports', 'content-kit-editor/utils/co options = options || {}; this.tagName = options.tagName || 'div'; this.classNames = options.classNames || []; - this.element = _contentKitEditorUtilsCompat.doc.createElement(this.tagName); - this.container = options.container || _contentKitEditorUtilsCompat.doc.body; + this.element = document.createElement(this.tagName); + this.container = options.container || document.body; this.isShowing = false; renderClasses(this); } @@ -4204,5 +3038,159 @@ define('content-kit-utils/string-utils', ['exports'], function (exports) { exports.sanitizeWhitespace = sanitizeWhitespace; exports.injectIntoString = injectIntoString; }); +define('mobiledoc-dom-renderer/dom-renderer', ['exports'], function (exports) { + /** + * runtime DOM renderer + * renders a mobiledoc to DOM + * + * input: mobiledoc + * output: DOM + */ + + 'use strict'; + + var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + var utils = { + createElement: function createElement(tagName) { + return document.createElement(tagName); + }, + appendChild: function appendChild(target, child) { + target.appendChild(child); + }, + createTextNode: function createTextNode(text) { + return document.createTextNode(text); + } + }; + + function createElementFromMarkerType() { + var _ref = arguments[0] === undefined ? ['', []] : arguments[0]; + + var _ref2 = _slicedToArray(_ref, 2); + + var tagName = _ref2[0]; + var attributes = _ref2[1]; + + var element = utils.createElement(tagName); + attributes = attributes || []; + + for (var i = 0, l = attributes.length; i < l; i = i + 2) { + var propName = attributes[i], + propValue = attributes[i + 1]; + element.setAttribute(propName, propValue); + } + return element; + } + + var DOMRenderer = (function () { + function DOMRenderer() { + _classCallCheck(this, DOMRenderer); + } + + _createClass(DOMRenderer, [{ + key: 'render', + + /** + * @param mobiledoc + * @param rootElement optional, defaults to an empty div + * @return DOMNode + */ + value: function render(mobiledoc) { + var _this = this; + + var rootElement = arguments[1] === undefined ? utils.createElement('div') : arguments[1]; + + var _mobiledoc = _slicedToArray(mobiledoc, 2); + + var markerTypes = _mobiledoc[0]; + var sections = _mobiledoc[1]; + + this.root = rootElement; + this.markerTypes = markerTypes; + + sections.forEach(function (section) { + return _this.renderSection(section); + }); + + return this.root; + } + }, { + key: 'renderSection', + value: function renderSection(section) { + var _section = _slicedToArray(section, 1); + + var type = _section[0]; + + switch (type) { + case 1: + var rendered = this.renderParagraphSection(section); + utils.appendChild(this.root, rendered); + break; + default: + throw new Error('Unimplement renderer for type ' + type); + } + } + }, { + key: 'renderParagraphSection', + value: function renderParagraphSection(_ref3) { + var _ref32 = _slicedToArray(_ref3, 3); + + var type = _ref32[0]; + var tagName = _ref32[1]; + var markers = _ref32[2]; + + var element = utils.createElement(tagName); + var elements = [element]; + var currentElement = element; + + for (var i = 0, l = markers.length; i < l; i++) { + var marker = markers[i]; + + var _marker = _slicedToArray(marker, 3); + + var openTypes = _marker[0]; + var closeTypes = _marker[1]; + var text = _marker[2]; + + for (var j = 0, m = openTypes.length; j < m; j++) { + var markerType = this.markerTypes[openTypes[j]]; + var openedElement = createElementFromMarkerType(markerType); + utils.appendChild(currentElement, openedElement); + elements.push(openedElement); + currentElement = openedElement; + } + + utils.appendChild(currentElement, utils.createTextNode(text)); + + for (var j = 0, m = closeTypes; j < m; j++) { + elements.pop(); + currentElement = elements[elements.length - 1]; + } + } + + return element; + } + }]); + + return DOMRenderer; + })(); + + exports['default'] = DOMRenderer; +}); +define('mobiledoc-dom-renderer', ['exports', 'mobiledoc-dom-renderer/dom-renderer'], function (exports, _mobiledocDomRendererDomRenderer) { + 'use strict'; + + exports.registerGlobal = registerGlobal; + + function registerGlobal(window) { + window.MobiledocDOMRenderer = _mobiledocDomRendererDomRenderer['default']; + } + + exports['default'] = _mobiledocDomRendererDomRenderer['default']; +}); require("content-kit-editor")["registerGlobal"](window, document); })(); \ No newline at end of file