diff --git a/.gitignore b/.gitignore index 829c8d7..e474388 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules .DS_store bower_components coverage +build/ \ No newline at end of file diff --git a/bower.json b/bower.json index 6000737..2ec44e5 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "onion-editor", - "version": "0.2.46", + "version": "1.0.0", "homepage": "https://github.com/theonion/editor", "authors": [ "Mike Wnuk " diff --git a/build/editor-main.css b/build/editor-main.css deleted file mode 100644 index c403415..0000000 --- a/build/editor-main.css +++ /dev/null @@ -1,493 +0,0 @@ -/* embed modal */ -.embed-modal textarea { - width: 100%; - max-width: 100%; - font-family: courier, fixed; - font-size: 14px; - padding: 5px; - background-color: #F1F1F1; -} -.embed-modal .embed-caption { - width: 100%; -} -.embed-modal textarea { - height: 200px; - resize: vertical; -} -/* embed toolbar */ -.embed-tools { - visibility: hidden; - height: 100%; - position: absolute; - margin: 12px 0; - padding: 0px 0px; - width: 100%; - opacity: 0; - transition: opacity 0.1s ease-in-out visibility 0.1s; - transition-delay: 1s; -} -.embed-tools.active { - visibility: visible; - display: block; - opacity: 1; - transition-delay: 0s; -} -.embed-tools .embed-button span.fa { - color: #333; -} -.embed-tools .embed-button span.btn-label { - font-size: 12px; -} -.embed-tools button { - width: 100%; - display: block; -} -.embed-tools.active .embed-button:hover { - transition: opacity .2 linear; - opacity: 1; -} -.embed-tools .embed-button { - display: block; - opacity: .5; -} -.embed-tools.embed-underlay { - border-top: 1px #111 solid; - border-bottom: 1px #111 solid; - background-color: red; - z-index: 10; - width: auto; -} -.embed-tools.embed-overlay { - z-index: 300; - width: 100px; -} -.embed-tools .embed-button { - right: -20px; - width: 30px; - line-height: 24px; - border: 1px #ccc solid; - font-size: 16px; - border-radius: 15px; - background-color: #eee; -} -.embed-tools .insert-above { - top: -24px; - position: absolute; - right: 0px; -} -.embed-tools .insert-below { - bottom: -24px; - position: absolute; - right: 0px; -} -.embed-fly-out { - width: auto; - height: auto; - position: absolute; - top: 200px; - z-index: 400; - border: 1px #ccc solid; - background-color: #ddd; - padding: 5px; - left: 100px; - text-align: center; -} -.embed-fly-out button:hover { - background-color: #333; - color: #fff; -} -.embed-fly-out button { - float: left; - border: 1px #ddd solid; - width: 80px; - height: 80px; - background-color: #eee; - margin: 3px; -} -.embed-fly-out button span.fa { - font-size: 24px; - display: block; -} -.embed-fly-out button span.btn-label { - font-size: 12px; -} - -div[data-picture] img { - display: block; - width: 100%; -} -div[data-picture] { - overflow: hidden; - width: auto; - max-width: 100%; -} -div[data-picture] > div { - position: relative; - padding-bottom: 56.25%; - /* default is 16x9 */ - height: 0; - overflow: hidden; -} -div[data-picture] img { - position: absolute; - top: 0; - left: 0; - height: 100%; -} - -.link-tools { - padding: 4px; - position: fixed; - z-index: 100; - top: 20px; - right: 20px; - width: auto; - display: none; - border-radius: 4px; - white-space: nowrap; - width: 400px; - background-color: #ddd; - border: 1px #ccc solid; -} -.link-tools .link-view-dialog { - width: auto; -} -.link-tools .link-edit-dialog { - width: 410px; -} -.toolbar.link-tools button { - display: inline-block; - width: auto; - font-size: 11px; - text-transform: uppercase; -} -.link-tools input { - padding: 8px; - margin-top: 4px; - width: 280px; - border-radius: 4px; - background-color: #f1f1f1; - border: 1px #ddd solid; -} -.link-search-results ul { - margin-bottom: 0px; -} - -* { - margin: 0px; - padding: 0px; -} -a { - cursor: pointer; -} -input, -textarea, -button, -.editor:focus { - outline: none; -} -::selection { - background-color: #FEFEBA; -} -body { - font-family: Helvetica, Arial, sans-serif; - background-color: #eee; -} -.editor-wrapper { - margin: 0px auto; - position: relative; -} -.editorPlaceholder, -.editor { - position: relative; - z-index: 20; - width: auto; - margin: 0px; - padding: 30px 100px; -} -.editorPlaceholder { - z-index: 10; - position: absolute; -} -.editorPlaceholder p, -.editor blockquote, -.editor ul, -.editor ol, -.editor p, -.editor > div { - min-height: 24px; - margin: 24px 0; -} -.editor blockquote { - clear: both; - padding: 0 30px; - border-left: 5px solid #ddd; -} -.editor ul, -.editor ol { - clear: both; - padding-left: 45px; - padding-right: 45px; -} -.editor li { - margin-bottom: 4px; -} -.editor h3 { - margin-top: 16px; - margin-bottom: 12px; - font-size: 32px; - font-weight: normal; -} -.editor h4 { - margin-top: 16px; - font-size: 24px; - font-weight: normal; -} -#content-wrapper { - margin-top: 100px; - margin: 20px auto 0; - border: 1px #ddd solid; -} -#content-wrapper.container { - max-width: 820px; - min-width: 400px; - width: auto; - padding: 0px; -} -.label { - opacity: .7; -} -/* status bar */ -#statusbar { - display: none; - position: fixed; - bottom: 0; - right: 0; - width: 100px; - height: 40px; - background-color: #ddd; - border-top: 1px #ccc solid; - border-left: 1px #ccc solid; - border-top-left-radius: 4px; - padding: 4px; - font-size: 12px; - color: #333; -} -#statusbar button { - display: inline-block; - width: auto; - text-align: center; -} - -/* Menus + Buttons */ -.inline-active .toolbar { - /*display:none; */ -} -.inline-active .inline-tools.toolbar { - display: block; -} -.toolbar-contents { - position: absolute; - z-index: 100; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: moz-none; - -ms-user-select: none; - user-select: none; - padding: 4px 4px; - font-size: 12px; - background-color: #EEEEEE; - border: 1px #DADADA solid; - border-radius: 4px; - width: auto; - white-space: nowrap; -} -.toolbar button { - border: 1px transparent solid; - color: #4A4A4A; - background-clip: padding-box; - background-color: transparent; - border-radius: 2px; - text-align: center; - display: inline-block; - line-height: 25px; - font-size: 14px; - width: 25px; - height: 25px; - cursor: pointer; - border-radius: 3px; -} -.toolbar button.text { - font-size: 11px; - width: auto; - padding: 0 4px; -} -.toolbar button { - width: auto; - display: block; - font-size: 14px; - width: 100%; - text-align: left; - padding: 4px 8px; - height: auto; -} -.heading-icon { - font-family: Georgia; - text-align: center; - width: 20px; - font-size: 15px; -} -.heading-icon sub { - bottom: 0px; -} -.toolbar .hiddenbydefault { - display: none; -} -.toolbar:hover .hiddenbydefault { - display: block; -} -.toolbar button.active { - display: block; - background-color: #ddd; -} -.toolbar button:hover { - background-color: #ccc; -} -.toolbar button:hover.active { - display: block; - background-color: #333; - color: #f1f1f1; -} -.toolbar .btn-label { - display: none; -} -.toolbar:hover .btn-label { - display: inline; - margin-left: 10px; - font-size: 12px; - line-height: 16px; -} -.toolbar.link-tools .toggle-filter { - background: #c8c8c8; - display: inline-block; - margin: 9px 5px; -} -.toolbar.link-tools .toggle-filter.active { - background: #969696; -} -.document-tools > .toolbar-contents { - top: 100px; - position: fixed; - left: 50%; - text-align: center; - margin-left: -480px; - display: block; - opacity: 1; -} -.toolbar button [class^="icon-"], -.toolbar button [class*=" icon-"] { - width: 15px; - display: inline-block; - text-align: center; -} -.toolbar-contents .primary { - font-size: 14px; - color: #4A4A4A; - float: right; - position: relative; - z-index: 100; - background-color: #EEEEEE; -} -/* inline tools */ -.inline-tools { - position: absolute; - display: none; - /*background-color: rgba(200,200,200,.5);*/ - z-index: 100; -} -.inline-tools button { - display: inline-block; - width: auto; -} -.inline-tools span.inline-attribute { - font-size: 11px; - text-transform: uppercase; -} -.inline-tools .remove { - position: absolute; - right: 10px; - bottom: 10px; - background-color: #930900; - border-radius: 4px; -} -.inline-tools .edit button, -.inline-tools .remove button { - color: white; -} -.inline-tools .remove button:hover { - background-color: #C70A00; -} -.inline-tools .edit { - position: absolute; - left: 10px; - bottom: 10px; - border-radius: 4px; - background-color: #333; - color: white; -} -.inline-tools .edit button:hover { - background-color: #444; -} -.inline-tools .toolbar-contents { - margin-top: 20px; - left: 50%; - margin-left: -96px; -} -/* Customize toolbar for various object types */ -.inline-tools[data-type="hr"] .edit, -.inline-tools[data-type="hr"] .size, -.inline-tools[data-type="hr"] .crop { - display: none; -} -/* size and crop are handled inside of the embed modal, for simplictiy */ -.inline-tools[data-type="embed"] .size, -.inline-tools[data-type="embed"] .crop { - display: none; -} -span.highlight { - background-color: #EC7000; -} -.find-replace-dialog { - position: fixed; - width: 820px; - margin: 0 auto; - height: 56px; - top: 0px; - left: 50%; - margin-left: -410px; - background-color: #EEEEEE; - border: 1px #DADADA solid; - border-radius: 4px; - z-index: 10000; - padding: 10px 20px; - box-shadow: 1px 3px 5px 0px rgba(50, 50, 50, 0.3); -} -.find-replace-dialog > .btn { - margin-top: -3px; -} -.find-replace-dialog input { - width: 200px; - font-size: 14px; - padding: 3px; -} -.editor span.searchResult { - background-color: #FFBB03; -} -.editor [contenteditable=false] span.searchResult { - background-color: transparent; -} -.document-tools, -embed-tools { - font-family: Helvetica, Arial, sans-serif; -} diff --git a/build/inline.css b/build/inline.css deleted file mode 100644 index 89e7e89..0000000 --- a/build/inline.css +++ /dev/null @@ -1,157 +0,0 @@ -.editor p { - margin: 24px 0; -} -.placeholder { - opacity: .5; -} -.inline img { - display: block; - width: 100%; - position: absolute; - top: 0; - left: 0; - height: 100%; -} -.inline { - overflow: hidden; - width: auto; - max-width: 100%; - cursor: pointer; - /*float:left;*/ - position: relative; - padding-top: 0px; - margin-top: 8px; - border: 1px #ccc solid; - width: 100%; - white-space: normal; -} -.inline > div { - position: relative; - height: 0; - overflow: hidden; - background-color: #e0e0e0; -} -.inline .caption { - color: #ccc; - display: block; - padding: 0 15px; - font-size: 14px; -} -/* Aspect Ratios */ -.inline.crop-16x9 > div { - padding-bottom: 56.25%; -} -.inline.crop-4x3 > div { - padding-bottom: 75%; -} -.inline.crop-1x1 > div { - padding-bottom: 100%; -} -.inline.crop-3x4 > div { - padding-bottom: 133.33%; -} -.inline.crop-3x1 > div { - padding-bottom: 33.333%; -} -/* Sizes */ -.inline.size-huge { - margin-left: -100px; - margin-right: -100px; - clear: both; - float: none; - width: auto; - max-width: none; -} -.inline.size-big { - width: 100%; -} -.inline.size-medium { - width: 496px; - float: right; - margin-right: -200px; - margin-left: 15px; -} -.inline.size-small { - width: 304px; - float: right; - margin-right: -200px; - margin-left: 15px; -} -.inline.size-tiny { - width: 144px; - float: right; - margin-right: 0px; - margin-left: 15px; -} -.video.centered { - margin-left: 15px; -} -.video { - width: 240px; -} -#editor-wrapper.mobile .inline { - margin-left: -20px; - margin-right: -20px; - width: auto; - box-sizing: border-box; - float: none; -} -#editor-wrapper.mobile .inline img { - width: 100%; -} -#editor-wrapper.mobile .inline .caption { - margin-left: 20px; -} -/* embed css */ -div.embed { - /* some videos did not migrate properly. Remove when fixed */ -} -div.embed.inline { - min-height: 30px; -} -div.embed.size-big { - width: 100%; -} -div.embed.size-small { - width: 80%; -} -div.embed.size-big > div > *, -div.embed.size-small > div > * { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; -} -div.embed.crop-original > div { - height: auto; -} -div.embed.crop-original > div > * { - position: relative; - width: 100%; -} -div.embed > div { - width: 100%; - position: relative; -} -div.embed.embed-instagram > div { - height: 100px; - padding-bottom: 0; -} -div.embed.embed-instagram > div > div.unrendered { - color: #777777; - font-size: 2em; - position: relative; - text-align: center; - top: 50%; - transform: translateY(-50%); -} -div.embed.embed-instagram > div > div.unrendered > i { - padding-right: 5px; -} -hr { - border-top: 1px #111 solid; -} -.hr.inline { - border: 0px; -} diff --git a/build/onion-editor.js b/build/onion-editor.js deleted file mode 100644 index 5fec72c..0000000 --- a/build/onion-editor.js +++ /dev/null @@ -1,11678 +0,0 @@ -// wrap-start.frag.js -(function (global, factory) { - if (typeof define === 'function') { - define(factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - global.OnionEditor = factory(); - } -}(this, function () {/** - * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/almond for details - */ -//Going sloppy to avoid 'use strict' string cost, but strict practices should -//be followed. -/*jslint sloppy: true */ -/*global setTimeout: false */ - -var requirejs, require, define; -(function (undef) { - var main, req, makeMap, handlers, - defined = {}, - waiting = {}, - config = {}, - defining = {}, - hasOwn = Object.prototype.hasOwnProperty, - aps = [].slice, - jsSuffixRegExp = /\.js$/; - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop); - } - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @returns {String} normalized name - */ - function normalize(name, baseName) { - var nameParts, nameSegment, mapValue, foundMap, lastIndex, - foundI, foundStarMap, starI, i, j, part, - baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = (map && map['*']) || {}; - - //Adjust any relative paths. - if (name && name.charAt(0) === ".") { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { - //Convert baseName to array, and lop off the last part, - //so that . matches that "directory" and not name of the baseName's - //module. For instance, baseName of "one/two/three", maps to - //"one/two/three.js", but we want the directory, "one/two" for - //this normalization. - baseParts = baseParts.slice(0, baseParts.length - 1); - name = name.split('/'); - lastIndex = name.length - 1; - - // Node .js allowance: - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - - name = baseParts.concat(name); - - //start trimDots - for (i = 0; i < name.length; i += 1) { - part = name[i]; - if (part === ".") { - name.splice(i, 1); - i -= 1; - } else if (part === "..") { - if (i === 1 && (name[2] === '..' || name[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - break; - } else if (i > 0) { - name.splice(i - 1, 2); - i -= 2; - } - } - } - //end trimDots - - name = name.join("/"); - } else if (name.indexOf('./') === 0) { - // No baseName, so this is ID is resolved relative - // to baseUrl, pull off the leading dot. - name = name.substring(2); - } - } - - //Apply map config if available. - if ((baseParts || starMap) && map) { - nameParts = name.split('/'); - - for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join("/"); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = map[baseParts.slice(0, j).join('/')]; - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = mapValue[nameSegment]; - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break; - } - } - } - } - - if (foundMap) { - break; - } - - //Check for a star map match, but just hold on to it, - //if there is a shorter segment match later in a matching - //config, then favor over this star map. - if (!foundStarMap && starMap && starMap[nameSegment]) { - foundStarMap = starMap[nameSegment]; - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } - } - - return name; - } - - function makeRequire(relName, forceSync) { - return function () { - //A version of a require function that passes a moduleName - //value for items that may need to - //look up paths relative to the moduleName - return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); - }; - } - - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName); - }; - } - - function makeLoad(depName) { - return function (value) { - defined[depName] = value; - }; - } - - function callDep(name) { - if (hasProp(waiting, name)) { - var args = waiting[name]; - delete waiting[name]; - defining[name] = true; - main.apply(undef, args); - } - - if (!hasProp(defined, name) && !hasProp(defining, name)) { - throw new Error('No ' + name); - } - return defined[name]; - } - - //Turns a plugin!resource to [plugin, resource] - //with the plugin being undefined if the name - //did not have a plugin prefix. - function splitPrefix(name) { - var prefix, - index = name ? name.indexOf('!') : -1; - if (index > -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); - } - return [prefix, name]; - } - - /** - * Makes a name map, normalizing the name, and using a plugin - * for normalization if necessary. Grabs a ref to plugin - * too, as an optimization. - */ - makeMap = function (name, relName) { - var plugin, - parts = splitPrefix(name), - prefix = parts[0]; - - name = parts[1]; - - if (prefix) { - prefix = normalize(prefix, relName); - plugin = callDep(prefix); - } - - //Normalize according - if (prefix) { - if (plugin && plugin.normalize) { - name = plugin.normalize(name, makeNormalize(relName)); - } else { - name = normalize(name, relName); - } - } else { - name = normalize(name, relName); - parts = splitPrefix(name); - prefix = parts[0]; - name = parts[1]; - if (prefix) { - plugin = callDep(prefix); - } - } - - //Using ridiculous property names for space reasons - return { - f: prefix ? prefix + '!' + name : name, //fullName - n: name, - pr: prefix, - p: plugin - }; - }; - - function makeConfig(name) { - return function () { - return (config && config.config && config.config[name]) || {}; - }; - } - - handlers = { - require: function (name) { - return makeRequire(name); - }, - exports: function (name) { - var e = defined[name]; - if (typeof e !== 'undefined') { - return e; - } else { - return (defined[name] = {}); - } - }, - module: function (name) { - return { - id: name, - uri: '', - exports: defined[name], - config: makeConfig(name) - }; - } - }; - - main = function (name, deps, callback, relName) { - var cjsModule, depName, ret, map, i, - args = [], - callbackType = typeof callback, - usingExports; - - //Use name if no relName - relName = relName || name; - - //Call the callback to define the module, if necessary. - if (callbackType === 'undefined' || callbackType === 'function') { - //Pull out the defined dependencies and pass the ordered - //values to the callback. - //Default to [require, exports, module] if no deps - deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; - for (i = 0; i < deps.length; i += 1) { - map = makeMap(deps[i], relName); - depName = map.f; - - //Fast path CommonJS standard dependencies. - if (depName === "require") { - args[i] = handlers.require(name); - } else if (depName === "exports") { - //CommonJS module spec 1.1 - args[i] = handlers.exports(name); - usingExports = true; - } else if (depName === "module") { - //CommonJS module spec 1.1 - cjsModule = args[i] = handlers.module(name); - } else if (hasProp(defined, depName) || - hasProp(waiting, depName) || - hasProp(defining, depName)) { - args[i] = callDep(depName); - } else if (map.p) { - map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); - args[i] = defined[depName]; - } else { - throw new Error(name + ' missing ' + depName); - } - } - - ret = callback ? callback.apply(defined[name], args) : undefined; - - if (name) { - //If setting exports via "module" is in play, - //favor that over return value and exports. After that, - //favor a non-undefined return value over exports use. - if (cjsModule && cjsModule.exports !== undef && - cjsModule.exports !== defined[name]) { - defined[name] = cjsModule.exports; - } else if (ret !== undef || !usingExports) { - //Use the return value from the function. - defined[name] = ret; - } - } - } else if (name) { - //May just be an object definition for the module. Only - //worry about defining if have a module name. - defined[name] = callback; - } - }; - - requirejs = require = req = function (deps, callback, relName, forceSync, alt) { - if (typeof deps === "string") { - if (handlers[deps]) { - //callback in this case is really relName - return handlers[deps](callback); - } - //Just return the module wanted. In this scenario, the - //deps arg is the module name, and second arg (if passed) - //is just the relName. - //Normalize module name, if it contains . or .. - return callDep(makeMap(deps, callback).f); - } else if (!deps.splice) { - //deps is a config object, not an array. - config = deps; - if (config.deps) { - req(config.deps, config.callback); - } - if (!callback) { - return; - } - - if (callback.splice) { - //callback is an array, which means it is a dependency list. - //Adjust args if there are dependencies - deps = callback; - callback = relName; - relName = null; - } else { - deps = undef; - } - } - - //Support require(['a']) - callback = callback || function () {}; - - //If relName is a function, it is an errback handler, - //so remove it. - if (typeof relName === 'function') { - relName = forceSync; - forceSync = alt; - } - - //Simulate async callback; - if (forceSync) { - main(undef, deps, callback, relName); - } else { - //Using a non-zero value because of concern for what old browsers - //do, and latest browsers "upgrade" to 4 if lower value is used: - //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: - //If want a value immediately, use require('id') instead -- something - //that works in almond on the global level, but not guaranteed and - //unlikely to work in other AMD implementations. - setTimeout(function () { - main(undef, deps, callback, relName); - }, 4); - } - - return req; - }; - - /** - * Just drops the config on the floor, but returns req in case - * the config return value is used. - */ - req.config = function (cfg) { - return req(cfg); - }; - - /** - * Expose module registry for debugging and tooling - */ - requirejs._defined = defined; - - define = function (name, deps, callback) { - - //This module may not have dependencies - if (!deps.splice) { - //deps is not an array, so probably means - //an object literal or factory function for - //the value. Adjust args. - callback = deps; - deps = []; - } - - if (!hasProp(defined, name) && !hasProp(waiting, name)) { - waiting[name] = [name, deps, callback]; - } - }; - - define.amd = { - jQuery: true - }; -}()); - -define("../../bower_components/almond/almond", function(){}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/isNative',[], function() { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Used to detect if a method is native */ - var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString| for [^\]]+/g, '.*?') + '$' - ); - - /** - * Checks if `value` is a native function. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. - */ - function isNative(value) { - return typeof value == 'function' && reNative.test(value); - } - - return isNative; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/objectTypes',[], function() { - - /** Used to determine if values are of the language type Object */ - var objectTypes = { - 'boolean': false, - 'function': true, - 'object': true, - 'number': false, - 'string': false, - 'undefined': false - }; - - return objectTypes; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isObject',['../internals/objectTypes'], function(objectTypes) { - - /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(1); - * // => false - */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); - } - - return isObject; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/shimKeys',['./objectTypes'], function(objectTypes) { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. - * - * @private - * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - */ - var shimKeys = function(object) { - var index, iterable = object, result = []; - if (!iterable) return result; - if (!(objectTypes[typeof object])) return result; - for (index in iterable) { - if (hasOwnProperty.call(iterable, index)) { - result.push(index); - } - } - return result - }; - - return shimKeys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/keys',['../internals/isNative', './isObject', '../internals/shimKeys'], function(isNative, isObject, shimKeys) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys; - - /** - * Creates an array composed of the own enumerable property names of an object. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - * @example - * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) - */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; - } - return nativeKeys(object); - }; - - return keys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/defaults',['./keys', '../internals/objectTypes'], function(keys, objectTypes) { - - /** - * Assigns own enumerable properties of source object(s) to the destination - * object for all destination properties that resolve to `undefined`. Once a - * property is set, additional defaults of the same property will be ignored. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param- {Object} [guard] Allows working with `_.reduce` without using its - * `key` and `object` arguments as sources. - * @returns {Object} Returns the destination object. - * @example - * - * var object = { 'name': 'barney' }; - * _.defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } - */ - var defaults = function(object, source, guard) { - var index, iterable = object, result = iterable; - if (!iterable) return result; - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - while (++argsIndex < argsLength) { - iterable = args[argsIndex]; - if (iterable && objectTypes[typeof iterable]) { - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (typeof result[index] == 'undefined') result[index] = iterable[index]; - } - } - } - return result - }; - - return defaults; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isArguments',[], function() { - - /** `Object#toString` result shortcuts */ - var argsClass = '[object Arguments]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** - * Checks if `value` is an `arguments` object. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`. - * @example - * - * (function() { return _.isArguments(arguments); })(1, 2, 3); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ - function isArguments(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == argsClass || false; - } - - return isArguments; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isArray',['../internals/isNative'], function(isNative) { - - /** `Object#toString` result shortcuts */ - var arrayClass = '[object Array]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray; - - /** - * Checks if `value` is an array. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. - * @example - * - * (function() { return _.isArray(arguments); })(); - * // => false - * - * _.isArray([1, 2, 3]); - * // => true - */ - var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; - }; - - return isArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseFlatten',['../objects/isArguments', '../objects/isArray'], function(isArguments, isArray) { - - /** - * The base implementation of `_.flatten` without support for callback - * shorthands or `thisArg` binding. - * - * @private - * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects. - * @param {number} [fromIndex=0] The index to start from. - * @returns {Array} Returns a new flattened array. - */ - function baseFlatten(array, isShallow, isStrict, fromIndex) { - var index = (fromIndex || 0) - 1, - length = array ? array.length : 0, - result = []; - - while (++index < length) { - var value = array[index]; - - if (value && typeof value == 'object' && typeof value.length == 'number' - && (isArray(value) || isArguments(value))) { - // recursively flatten arrays (susceptible to call stack limits) - if (!isShallow) { - value = baseFlatten(value, isShallow, isStrict); - } - var valIndex = -1, - valLength = value.length, - resIndex = result.length; - - result.length += valLength; - while (++valIndex < valLength) { - result[resIndex++] = value[valIndex]; - } - } else if (!isStrict) { - result.push(value); - } - } - return result; - } - - return baseFlatten; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/noop',[], function() { - - /** - * A no-operation function. - * - * @static - * @memberOf _ - * @category Utilities - * @example - * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true - */ - function noop() { - // no operation performed - } - - return noop; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreate',['./isNative', '../objects/isObject', '../utilities/noop'], function(isNative, isObject, noop) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate; - - /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. - */ - function baseCreate(prototype, properties) { - return isObject(prototype) ? nativeCreate(prototype) : {}; - } - // fallback for browsers without `Object.create` - if (!nativeCreate) { - baseCreate = (function() { - function Object() {} - return function(prototype) { - if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; - } - return result || window.Object(); - }; - }()); - } - - return baseCreate; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/setBindData',['./isNative', '../utilities/noop'], function(isNative, noop) { - - /** Used as the property descriptor for `__bindData__` */ - var descriptor = { - 'configurable': false, - 'enumerable': false, - 'value': null, - 'writable': false - }; - - /** Used to set meta data on functions */ - var defineProperty = (function() { - // IE 8 only accepts DOM elements - try { - var o = {}, - func = isNative(func = Object.defineProperty) && func, - result = func(o, o, o) && func; - } catch(e) { } - return result; - }()); - - /** - * Sets `this` binding data on a given function. - * - * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. - */ - var setBindData = !defineProperty ? noop : function(func, value) { - descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); - }; - - return setBindData; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/slice',[], function() { - - /** - * Slices the `collection` from the `start` index up to, but not including, - * the `end` index. - * - * Note: This function is used instead of `Array#slice` to support node lists - * in IE < 9 and to ensure dense arrays are returned. - * - * @private - * @param {Array|Object|string} collection The collection to slice. - * @param {number} start The start index. - * @param {number} end The end index. - * @returns {Array} Returns the new array. - */ - function slice(array, start, end) { - start || (start = 0); - if (typeof end == 'undefined') { - end = array ? array.length : 0; - } - var index = -1, - length = end - start || 0, - result = Array(length < 0 ? 0 : length); - - while (++index < length) { - result[index] = array[start + index]; - } - return result; - } - - return slice; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseBind',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new bound function. - */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; - - function bound() { - // `Function#bind` spec - // http://es5.github.io/#x15.3.4.5 - if (partialArgs) { - // avoid `arguments` object deoptimizations by using `slice` instead - // of `Array.prototype.slice.call` and not assigning `arguments` to a - // variable as a ternary expression - var args = slice(partialArgs); - push.apply(args, arguments); - } - // mimic the constructor's `return` behavior - // http://es5.github.io/#x13.2.2 - if (this instanceof bound) { - // ensure `new bound` is an instance of `func` - var thisBinding = baseCreate(func.prototype), - result = func.apply(thisBinding, args || arguments); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisArg, args || arguments); - } - setBindData(bound, bindData); - return bound; - } - - return baseBind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateWrapper',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; - - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - key = func; - - function bound() { - var thisBinding = isBind ? thisArg : this; - if (partialArgs) { - var args = slice(partialArgs); - push.apply(args, arguments); - } - if (partialRightArgs || isCurry) { - args || (args = slice(arguments)); - if (partialRightArgs) { - push.apply(args, partialRightArgs); - } - if (isCurry && args.length < arity) { - bitmask |= 16 & ~32; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]); - } - } - args || (args = arguments); - if (isBindKey) { - func = thisBinding[key]; - } - if (this instanceof bound) { - thisBinding = baseCreate(func.prototype); - var result = func.apply(thisBinding, args); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisBinding, args); - } - setBindData(bound, bindData); - return bound; - } - - return baseCreateWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isFunction',[], function() { - - /** - * Checks if `value` is a function. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - */ - function isFunction(value) { - return typeof value == 'function'; - } - - return isFunction; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/createWrapper',['./baseBind', './baseCreateWrapper', '../objects/isFunction', './slice'], function(baseBind, baseCreateWrapper, isFunction, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push, - unshift = arrayRef.unshift; - - /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. - * - * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of method flags to compose. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) - * 16 - `_.partial` - * 32 - `_.partialRight` - * @param {Array} [partialArgs] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [partialRightArgs] An array of arguments to append to those - * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new function. - */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - isPartial = bitmask & 16, - isPartialRight = bitmask & 32; - - if (!isBindKey && !isFunction(func)) { - throw new TypeError; - } - if (isPartial && !partialArgs.length) { - bitmask &= ~16; - isPartial = partialArgs = false; - } - if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; - isPartialRight = partialRightArgs = false; - } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); - } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); - } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & 1)) { - bindData[4] = thisArg; - } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & 1) { - bitmask |= 8; - } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & 4)) { - bindData[5] = arity; - } - // append partial left arguments - if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); - } - // append partial right arguments - if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); - } - // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); - } - // fast path for `_.bind` - var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); - } - - return createWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/functions/bind',['../internals/createWrapper', '../internals/slice'], function(createWrapper, slice) { - - /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. - * - * @static - * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; - * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' - */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); - } - - return bind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/identity',[], function() { - - /** - * This method returns the first argument provided to it. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; - * // => true - */ - function identity(value) { - return value; - } - - return identity; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/support',['./internals/isNative'], function(isNative) { - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** - * An object used to flag environments features. - * - * @static - * @memberOf _ - * @type Object - */ - var support = {}; - - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = !isNative(window.WinRTError) && reThis.test(function() { return this; }); - - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; - - return support; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateCallback',['../functions/bind', '../utilities/identity', './setBindData', '../support'], function(bind, identity, setBindData, support) { - - /** Used to detected named functions */ - var reFuncName = /^\s*function[ \n\r\t]+\w/; - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** Native method shortcuts */ - var fnToString = Function.prototype.toString; - - /** - * The base implementation of `_.createCallback` without support for creating - * "_.pluck" or "_.where" style callbacks. - * - * @private - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - */ - function baseCreateCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; - } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { - return func; - } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { - if (support.funcNames) { - bindData = !func.name; - } - bindData = bindData || !support.funcDecomp; - if (!bindData) { - var source = fnToString.call(func); - if (!support.funcNames) { - bindData = !reFuncName.test(source); - } - if (!bindData) { - // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); - } - } - } - // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & 1)) { - return func; - } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; - } - return bind(func, thisArg); - } - - return baseCreateCallback; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forIn',['../internals/baseCreateCallback', '../internals/objectTypes'], function(baseCreateCallback, objectTypes) { - - /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; - * - * _.forIn(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) - */ - var forIn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - for (index in iterable) { - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forIn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/arrayPool',[], function() { - - /** Used to pool arrays and objects used internally */ - var arrayPool = []; - - return arrayPool; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/getArray',['./arrayPool'], function(arrayPool) { - - /** - * Gets an array from the array pool or creates a new one if the pool is empty. - * - * @private - * @returns {Array} The array from the pool. - */ - function getArray() { - return arrayPool.pop() || []; - } - - return getArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/maxPoolSize',[], function() { - - /** Used as the max size of the `arrayPool` and `objectPool` */ - var maxPoolSize = 40; - - return maxPoolSize; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/releaseArray',['./arrayPool', './maxPoolSize'], function(arrayPool, maxPoolSize) { - - /** - * Releases the given array back to the array pool. - * - * @private - * @param {Array} [array] The array to release. - */ - function releaseArray(array) { - array.length = 0; - if (arrayPool.length < maxPoolSize) { - arrayPool.push(array); - } - } - - return releaseArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseIsEqual',['../objects/forIn', './getArray', '../objects/isFunction', './objectTypes', './releaseArray'], function(forIn, getArray, isFunction, objectTypes, releaseArray) { - - /** `Object#toString` result shortcuts */ - var argsClass = '[object Arguments]', - arrayClass = '[object Array]', - boolClass = '[object Boolean]', - dateClass = '[object Date]', - numberClass = '[object Number]', - objectClass = '[object Object]', - regexpClass = '[object RegExp]', - stringClass = '[object String]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * The base implementation of `_.isEqual`, without support for `thisArg` binding, - * that allows partial "_.where" style comparisons. - * - * @private - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `a` objects. - * @param {Array} [stackB=[]] Tracks traversed `b` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - */ - function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { - // used to indicate that when comparing objects, `a` has at least the properties of `b` - if (callback) { - var result = callback(a, b); - if (typeof result != 'undefined') { - return !!result; - } - } - // exit early for identical values - if (a === b) { - // treat `+0` vs. `-0` as not equal - return a !== 0 || (1 / a == 1 / b); - } - var type = typeof a, - otherType = typeof b; - - // exit early for unlike primitive values - if (a === a && - !(a && objectTypes[type]) && - !(b && objectTypes[otherType])) { - return false; - } - // exit early for `null` and `undefined` avoiding ES3's Function#call behavior - // http://es5.github.io/#x15.3.4.4 - if (a == null || b == null) { - return a === b; - } - // compare [[Class]] names - var className = toString.call(a), - otherClass = toString.call(b); - - if (className == argsClass) { - className = objectClass; - } - if (otherClass == argsClass) { - otherClass = objectClass; - } - if (className != otherClass) { - return false; - } - switch (className) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +a == +b; - - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (a != +a) - ? b != +b - // but treat `+0` vs. `-0` as not equal - : (a == 0 ? (1 / a == 1 / b) : a == +b); - - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and their corresponding object instances as equal - return a == String(b); - } - var isArr = className == arrayClass; - if (!isArr) { - // unwrap any `lodash` wrapped values - var aWrapped = hasOwnProperty.call(a, '__wrapped__'), - bWrapped = hasOwnProperty.call(b, '__wrapped__'); - - if (aWrapped || bWrapped) { - return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); - } - // exit for functions and DOM nodes - if (className != objectClass) { - return false; - } - // in older versions of Opera, `arguments` objects have `Array` constructors - var ctorA = a.constructor, - ctorB = b.constructor; - - // non `Object` object instances with different constructors are not equal - if (ctorA != ctorB && - !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && - ('constructor' in a && 'constructor' in b) - ) { - return false; - } - } - // assume cyclic structures are equal - // the algorithm for detecting cyclic structures is adapted from ES 5.1 - // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); - - var length = stackA.length; - while (length--) { - if (stackA[length] == a) { - return stackB[length] == b; - } - } - var size = 0; - result = true; - - // add `a` and `b` to the stack of traversed objects - stackA.push(a); - stackB.push(b); - - // recursively compare objects and arrays (susceptible to call stack limits) - if (isArr) { - // compare lengths to determine if a deep comparison is necessary - length = a.length; - size = b.length; - result = size == length; - - if (result || isWhere) { - // deep compare the contents, ignoring non-numeric properties - while (size--) { - var index = length, - value = b[size]; - - if (isWhere) { - while (index--) { - if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { - break; - } - } - } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { - break; - } - } - } - } - else { - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - forIn(b, function(value, key, b) { - if (hasOwnProperty.call(b, key)) { - // count the number of properties. - size++; - // deep compare each property value. - return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); - } - }); - - if (result && !isWhere) { - // ensure both objects have the same number of properties - forIn(a, function(value, key, a) { - if (hasOwnProperty.call(a, key)) { - // `size` will be `-1` if `a` has more properties than `b` - return (result = --size > -1); - } - }); - } - } - stackA.pop(); - stackB.pop(); - - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); - } - return result; - } - - return baseIsEqual; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/property',[], function() { - - /** - * Creates a "_.pluck" style function, which returns the `key` value of a - * given object. - * - * @static - * @memberOf _ - * @category Utilities - * @param {string} key The name of the property to retrieve. - * @returns {Function} Returns the new function. - * @example - * - * var characters = [ - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'barney', 'age': 36 } - * ]; - * - * var getName = _.property('name'); - * - * _.map(characters, getName); - * // => ['barney', 'fred'] - * - * _.sortBy(characters, getName); - * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] - */ - function property(key) { - return function(object) { - return object[key]; - }; - } - - return property; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/functions/createCallback',['../internals/baseCreateCallback', '../internals/baseIsEqual', '../objects/isObject', '../objects/keys', '../utilities/property'], function(baseCreateCallback, baseIsEqual, isObject, keys, property) { - - /** - * Produces a callback bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - * @example - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; - * - * // wrap to create custom callback shorthands - * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { - * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); - * return !match ? func(callback, thisArg) : function(object) { - * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; - * }; - * }); - * - * _.filter(characters, 'age__gt38'); - * // => [{ 'name': 'fred', 'age': 40 }] - */ - function createCallback(func, thisArg, argCount) { - var type = typeof func; - if (func == null || type == 'function') { - return baseCreateCallback(func, thisArg, argCount); - } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; - - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; - } - } - return result; - }; - } - - return createCallback; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forOwn',['../internals/baseCreateCallback', './keys', '../internals/objectTypes'], function(baseCreateCallback, keys, objectTypes) { - - /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) - */ - var forOwn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forOwn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/collections/map',['../functions/createCallback', '../objects/forOwn'], function(createCallback, forOwn) { - - /** - * Creates an array of values by running each element in the collection - * through the callback. The callback is bound to `thisArg` and invoked with - * three arguments; (value, index|key, collection). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @alias collect - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new array of the results of each `callback` execution. - * @example - * - * _.map([1, 2, 3], function(num) { return num * 3; }); - * // => [3, 6, 9] - * - * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); - * // => [3, 6, 9] (property order is not guaranteed across environments) - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; - * - * // using "_.pluck" callback shorthand - * _.map(characters, 'name'); - * // => ['barney', 'fred'] - */ - function map(collection, callback, thisArg) { - var index = -1, - length = collection ? collection.length : 0; - - callback = createCallback(callback, thisArg, 3); - if (typeof length == 'number') { - var result = Array(length); - while (++index < length) { - result[index] = callback(collection[index], index, collection); - } - } else { - result = []; - forOwn(collection, function(value, key, collection) { - result[++index] = callback(value, key, collection); - }); - } - return result; - } - - return map; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/arrays/flatten',['../internals/baseFlatten', '../collections/map'], function(baseFlatten, map) { - - /** - * Flattens a nested array (the nesting can be to any depth). If `isShallow` - * is truey, the array will only be flattened a single level. If a callback - * is provided each element of the array is passed through the callback before - * flattening. The callback is bound to `thisArg` and invoked with three - * arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @category Arrays - * @param {Array} array The array to flatten. - * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. - * @param {Function|Object|string} [callback=identity] The function called - * per iteration. If a property name or object is provided it will be used - * to create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array} Returns a new flattened array. - * @example - * - * _.flatten([1, [2], [3, [[4]]]]); - * // => [1, 2, 3, 4]; - * - * _.flatten([1, [2], [3, [[4]]]], true); - * // => [1, 2, 3, [[4]]]; - * - * var characters = [ - * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] }, - * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] } - * ]; - * - * // using "_.pluck" callback shorthand - * _.flatten(characters, 'pets'); - * // => ['hoppy', 'baby puss', 'dino'] - */ - function flatten(array, isShallow, callback, thisArg) { - // juggle arguments - if (typeof isShallow != 'boolean' && isShallow != null) { - thisArg = callback; - callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow; - isShallow = false; - } - if (callback != null) { - array = map(array, callback, thisArg); - } - return baseFlatten(array, isShallow); - } - - return flatten; -}); - -define('plugins/core/commands/indent',[],function () { - - - - return function () { - return function (scribe) { - var indentCommand = new scribe.api.Command('indent'); - - indentCommand.queryEnabled = function () { - /** - * FIXME: Chrome nests ULs inside of ULs - * Currently we just disable the command when the selection is inside of - * a list. - * As per: http://jsbin.com/ORikUPa/3/edit?html,js,output - */ - var selection = new scribe.api.Selection(); - var listElement = selection.getContaining(function (element) { - return element.nodeName === 'UL' || element.nodeName === 'OL'; - }); - - return scribe.api.Command.prototype.queryEnabled.call(this) && scribe.allowsBlockElements() && ! listElement; - }; - - scribe.commands.indent = indentCommand; - }; - }; - -}); - -define('plugins/core/commands/insert-list',[],function () { - - /** - * If the paragraphs option is set to true, then when the list is - * unapplied, ensure that we enter a P element. - */ - - - - return function () { - return function (scribe) { - var InsertListCommand = function (commandName) { - scribe.api.Command.call(this, commandName); - }; - - InsertListCommand.prototype = Object.create(scribe.api.Command.prototype); - InsertListCommand.prototype.constructor = InsertListCommand; - - InsertListCommand.prototype.execute = function (value) { - function splitList(listItemElements) { - if (listItemElements.length > 0) { - var newListNode = document.createElement(listNode.nodeName); - - listItemElements.forEach(function (listItemElement) { - newListNode.appendChild(listItemElement); - }); - - listNode.parentNode.insertBefore(newListNode, listNode.nextElementSibling); - } - } - - if (this.queryState()) { - var selection = new scribe.api.Selection(); - var range = selection.range; - - var listNode = selection.getContaining(function (node) { - return node.nodeName === 'OL' || node.nodeName === 'UL'; - }); - - var listItemElement = selection.getContaining(function (node) { - return node.nodeName === 'LI'; - }); - - scribe.transactionManager.run(function () { - if (listItemElement) { - var nextListItemElements = (new scribe.api.Node(listItemElement)).nextAll(); - - /** - * If we are not at the start or end of a UL/OL, we have to - * split the node and insert the P(s) in the middle. - */ - splitList(nextListItemElements); - - /** - * Insert a paragraph in place of the list item. - */ - - selection.placeMarkers(); - - var pNode = document.createElement('p'); - pNode.innerHTML = listItemElement.innerHTML; - - listNode.parentNode.insertBefore(pNode, listNode.nextElementSibling); - listItemElement.parentNode.removeChild(listItemElement); - } else { - /** - * When multiple list items are selected, we replace each list - * item with a paragraph. - */ - - // We can't query for list items in the selection so we loop - // through them all and find the intersection ourselves. - var selectedListItemElements = Array.prototype.map.call(listNode.querySelectorAll('li'), - function (listItemElement) { - return range.intersectsNode(listItemElement) && listItemElement; - }).filter(function (listItemElement) { - // TODO: identity - return listItemElement; - }); - var lastSelectedListItemElement = selectedListItemElements.slice(-1)[0]; - var listItemElementsAfterSelection = (new scribe.api.Node(lastSelectedListItemElement)).nextAll(); - - /** - * If we are not at the start or end of a UL/OL, we have to - * split the node and insert the P(s) in the middle. - */ - splitList(listItemElementsAfterSelection); - - // Store the caret/range positioning inside of the list items so - // we can restore it from the newly created P elements soon - // afterwards. - selection.placeMarkers(); - - var documentFragment = document.createDocumentFragment(); - selectedListItemElements.forEach(function (listItemElement) { - var pElement = document.createElement('p'); - pElement.innerHTML = listItemElement.innerHTML; - documentFragment.appendChild(pElement); - }); - - // Insert the Ps - listNode.parentNode.insertBefore(documentFragment, listNode.nextElementSibling); - - // Remove the LIs - selectedListItemElements.forEach(function (listItemElement) { - listItemElement.parentNode.removeChild(listItemElement); - }); - } - - // If the list is now empty, clean it up. - if (listNode.childNodes.length === 0) { - listNode.parentNode.removeChild(listNode); - } - - selection.selectMarkers(); - }.bind(this)); - } else { - scribe.api.Command.prototype.execute.call(this, value); - } - }; - - InsertListCommand.prototype.queryEnabled = function () { - return scribe.api.Command.prototype.queryEnabled.call(this) && scribe.allowsBlockElements(); - }; - - scribe.commands.insertOrderedList = new InsertListCommand('insertOrderedList'); - scribe.commands.insertUnorderedList = new InsertListCommand('insertUnorderedList'); - }; - }; - -}); - -define('plugins/core/commands/outdent',[],function () { - - - - return function () { - return function (scribe) { - var outdentCommand = new scribe.api.Command('outdent'); - - outdentCommand.queryEnabled = function () { - /** - * FIXME: If the paragraphs option is set to true, then when the - * list is unapplied, ensure that we enter a P element. - * Currently we just disable the command when the selection is inside of - * a list. - */ - var selection = new scribe.api.Selection(); - var listElement = selection.getContaining(function (element) { - return element.nodeName === 'UL' || element.nodeName === 'OL'; - }); - - // FIXME: define block element rule here? - return scribe.api.Command.prototype.queryEnabled.call(this) && scribe.allowsBlockElements() && ! listElement; - }; - - scribe.commands.outdent = outdentCommand; - }; - }; - -}); - -define('plugins/core/commands/redo',[],function () { - - - - return function () { - return function (scribe) { - var redoCommand = new scribe.api.Command('redo'); - - redoCommand.execute = function () { - var historyItem = scribe.undoManager.redo(); - - if (typeof historyItem !== 'undefined') { - scribe.restoreFromHistory(historyItem); - } - }; - - redoCommand.queryEnabled = function () { - return scribe.undoManager.position < scribe.undoManager.stack.length - 1; - }; - - scribe.commands.redo = redoCommand; - - scribe.el.addEventListener('keydown', function (event) { - if (event.shiftKey && (event.metaKey || event.ctrlKey) && event.keyCode === 90) { - event.preventDefault(); - redoCommand.execute(); - } - }); - }; - }; - -}); - -define('plugins/core/commands/subscript',[],function () { - - - - return function () { - return function (scribe) { - var subscriptCommand = new scribe.api.Command('subscript'); - - scribe.commands.subscript = subscriptCommand; - }; - }; - -}); - -define('plugins/core/commands/superscript',[],function () { - - - - return function () { - return function (scribe) { - var superscriptCommand = new scribe.api.Command('superscript'); - - scribe.commands.superscript = superscriptCommand; - }; - }; - -}); - -define('plugins/core/commands/undo',[],function () { - - - - return function () { - return function (scribe) { - var undoCommand = new scribe.api.Command('undo'); - - undoCommand.execute = function () { - var historyItem = scribe.undoManager.undo(); - - if (typeof historyItem !== 'undefined') { - scribe.restoreFromHistory(historyItem); - } - }; - - undoCommand.queryEnabled = function () { - return scribe.undoManager.position > 1; - }; - - scribe.commands.undo = undoCommand; - - scribe.el.addEventListener('keydown', function (event) { - // TODO: use lib to abstract meta/ctrl keys? - if (! event.shiftKey && (event.metaKey || event.ctrlKey) && event.keyCode === 90) { - event.preventDefault(); - undoCommand.execute(); - } - }); - }; - }; - -}); - -define('plugins/core/commands',[ - './commands/indent', - './commands/insert-list', - './commands/outdent', - './commands/redo', - './commands/subscript', - './commands/superscript', - './commands/undo' -], function ( - indent, - insertList, - outdent, - redo, - subscript, - superscript, - undo -) { - - - - return { - indent: indent, - insertList: insertList, - outdent: outdent, - redo: redo, - subscript: subscript, - superscript: superscript, - undo: undo - }; - -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseIndexOf',[], function() { - - /** - * The base implementation of `_.indexOf` without support for binary searches - * or `fromIndex` constraints. - * - * @private - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. - */ - function baseIndexOf(array, value, fromIndex) { - var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; - - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; - } - - return baseIndexOf; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isString',[], function() { - - /** `Object#toString` result shortcuts */ - var stringClass = '[object String]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** - * Checks if `value` is a string. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a string, else `false`. - * @example - * - * _.isString('fred'); - * // => true - */ - function isString(value) { - return typeof value == 'string' || - value && typeof value == 'object' && toString.call(value) == stringClass || false; - } - - return isString; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/collections/contains',['../internals/baseIndexOf', '../objects/forOwn', '../objects/isArray', '../objects/isString'], function(baseIndexOf, forOwn, isArray, isString) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeMax = Math.max; - - /** - * Checks if a given value is present in a collection using strict equality - * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. - * - * @static - * @memberOf _ - * @alias include - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {*} target The value to check for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if the `target` element is found, else `false`. - * @example - * - * _.contains([1, 2, 3], 1); - * // => true - * - * _.contains([1, 2, 3], 1, 2); - * // => false - * - * _.contains({ 'name': 'fred', 'age': 40 }, 'fred'); - * // => true - * - * _.contains('pebbles', 'eb'); - * // => true - */ - function contains(collection, target, fromIndex) { - var index = -1, - indexOf = baseIndexOf, - length = collection ? collection.length : 0, - result = false; - - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; - if (isArray(collection)) { - result = indexOf(collection, target, fromIndex) > -1; - } else if (typeof length == 'number') { - result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1; - } else { - forOwn(collection, function(value) { - if (++index >= fromIndex) { - return !(result = value === target); - } - }); - } - return result; - } - - return contains; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/values',['./keys'], function(keys) { - - /** - * Creates an array composed of the own enumerable property values of `object`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property values. - * @example - * - * _.values({ 'one': 1, 'two': 2, 'three': 3 }); - * // => [1, 2, 3] (property order is not guaranteed across environments) - */ - function values(object) { - var index = -1, - props = keys(object), - length = props.length, - result = Array(length); - - while (++index < length) { - result[index] = object[props[index]]; - } - return result; - } - - return values; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/collections/toArray',['../objects/isString', '../internals/slice', '../objects/values'], function(isString, slice, values) { - - /** - * Converts the `collection` to an array. - * - * @static - * @memberOf _ - * @category Collections - * @param {Array|Object|string} collection The collection to convert. - * @returns {Array} Returns the new converted array. - * @example - * - * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); - * // => [2, 3, 4] - */ - function toArray(collection) { - if (collection && typeof collection.length == 'number') { - return slice(collection); - } - return values(collection); - } - - return toArray; -}); - -define('scribe-common/src/element',['lodash-amd/modern/collections/contains'], function (contains) { - - - - // TODO: not exhaustive? - var blockElementNames = ['P', 'LI', 'DIV', 'BLOCKQUOTE', 'UL', 'OL', 'H1', - 'H2', 'H3', 'H4', 'H5', 'H6']; - function isBlockElement(node) { - return contains(blockElementNames, node.nodeName); - } - - function isSelectionMarkerNode(node) { - return (node.nodeType === Node.ELEMENT_NODE && node.className === 'scribe-marker'); - } - - function unwrap(node, childNode) { - while (childNode.childNodes.length > 0) { - node.insertBefore(childNode.childNodes[0], childNode); - } - node.removeChild(childNode); - } - - return { - isBlockElement: isBlockElement, - isSelectionMarkerNode: isSelectionMarkerNode, - unwrap: unwrap - }; - -}); - -define('scribe-common/src/node',[], function () { - - - - function isEmptyTextNode(node) { - return (node.nodeType === Node.TEXT_NODE && node.textContent === ''); - } - - function insertAfter(newNode, referenceNode) { - return referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); - } - - function removeNode(node) { - return node.parentNode.removeChild(node); - } - - return { - isEmptyTextNode: isEmptyTextNode, - insertAfter: insertAfter, - removeNode: removeNode - }; - -}); - -define('dom-observer',[ - 'lodash-amd/modern/arrays/flatten', - 'lodash-amd/modern/collections/toArray', - 'scribe-common/src/element', - 'scribe-common/src/node' -], function ( - flatten, - toArray, - elementHelpers, - nodeHelpers -) { - - function observeDomChanges(el, callback) { - function includeRealMutations(mutations) { - var allChangedNodes = flatten(mutations.map(function(mutation) { - var added = toArray(mutation.addedNodes); - var removed = toArray(mutation.removedNodes); - return added.concat(removed); - })); - - var realChangedNodes = allChangedNodes. - filter(function(n) { return ! nodeHelpers.isEmptyTextNode(n); }). - filter(function(n) { return ! elementHelpers.isSelectionMarkerNode(n); }); - - return realChangedNodes.length > 0; - } - - // Flag to avoid running recursively - var runningPostMutation = false; - var observer = new MutationObserver(function(mutations) { - if (! runningPostMutation && includeRealMutations(mutations)) { - runningPostMutation = true; - - try { - callback(); - } finally { - // We must yield to let any mutation we caused be triggered - // in the next cycle - setTimeout(function() { - runningPostMutation = false; - }, 0); - } - } - }); - - observer.observe(el, { - attributes: true, - childList: true, - subtree: true - }); - - return observer; - } - - return observeDomChanges; -}); - -define('plugins/core/events',[ - 'lodash-amd/modern/collections/contains', - '../../dom-observer' -], function ( - contains, - observeDomChanges -) { - - - - return function () { - return function (scribe) { - /** - * Push the first history item when the editor is focused. - */ - var pushHistoryOnFocus = function () { - // Tabbing into the editor doesn't create a range immediately, so we - // have to wait until the next event loop. - setTimeout(function () { - scribe.pushHistory(); - }.bind(scribe), 0); - - scribe.el.removeEventListener('focus', pushHistoryOnFocus); - }.bind(scribe); - scribe.el.addEventListener('focus', pushHistoryOnFocus); - - /** - * Firefox: Giving focus to a `contenteditable` will place the caret - * outside of any block elements. Chrome behaves correctly by placing the - * caret at the earliest point possible inside the first block element. - * As per: http://jsbin.com/eLoFOku/1/edit?js,console,output - * - * We detect when this occurs and fix it by placing the caret ourselves. - */ - scribe.el.addEventListener('focus', function placeCaretOnFocus() { - var selection = new scribe.api.Selection(); - // In Chrome, the range is not created on or before this event loop. - // It doesn’t matter because this is a fix for Firefox. - if (selection.range) { - - var isFirefoxBug = scribe.allowsBlockElements() && - selection.range.startContainer === scribe.el; - - if (isFirefoxBug) { - var focusElement = getFirstDeepestChild(scribe.el.firstChild); - - var range = selection.range; - - range.setStart(focusElement, 0); - range.setEnd(focusElement, 0); - - selection.selection.removeAllRanges(); - selection.selection.addRange(range); - } - } - - function getFirstDeepestChild(node) { - var treeWalker = document.createTreeWalker(node); - var previousNode = treeWalker.currentNode; - if (treeWalker.firstChild()) { - // TODO: build list of non-empty elements (used elsewhere) - // Do not include non-empty elements - if (treeWalker.currentNode.nodeName === 'BR') { - return previousNode; - } else { - return getFirstDeepestChild(treeWalker.currentNode); - } - } else { - return treeWalker.currentNode; - } - } - }.bind(scribe)); - - /** - * Apply the formatters when there is a DOM mutation. - */ - var applyFormatters = function() { - if (!scribe._skipFormatters) { - var selection = new scribe.api.Selection(); - var isEditorActive = selection.range; - - var runFormatters = function () { - if (isEditorActive) { - selection.placeMarkers(); - } - scribe.setHTML(scribe._htmlFormatterFactory.format(scribe.getHTML())); - selection.selectMarkers(); - }.bind(scribe); - - // We only want to wrap the formatting in a transaction if the editor is - // active. If the DOM is mutated when the editor isn't active (e.g. - // `scribe.setContent`), we do not want to push to the history. (This - // happens on the first `focus` event). - if (isEditorActive) { - // Discard the last history item, as we're going to be adding - // a new clean history item next. - scribe.undoManager.undo(); - - // Pass content through formatters, place caret back - scribe.transactionManager.run(runFormatters); - } else { - runFormatters(); - } - - } - - delete scribe._skipFormatters; - }.bind(scribe); - - observeDomChanges(scribe.el, applyFormatters); - - // TODO: disconnect on tear down: - // observer.disconnect(); - - /** - * If the paragraphs option is set to true, we need to manually handle - * keyboard navigation inside a heading to ensure a P element is created. - */ - if (scribe.allowsBlockElements()) { - scribe.el.addEventListener('keydown', function (event) { - if (event.keyCode === 13) { // enter - - var selection = new scribe.api.Selection(); - var range = selection.range; - - var headingNode = selection.getContaining(function (node) { - return (/^(H[1-6])$/).test(node.nodeName); - }); - - /** - * If we are at the end of the heading, insert a P. Otherwise handle - * natively. - */ - if (headingNode && range.collapsed) { - var contentToEndRange = range.cloneRange(); - contentToEndRange.setEndAfter(headingNode, 0); - - // Get the content from the range to the end of the heading - var contentToEndFragment = contentToEndRange.cloneContents(); - - if (contentToEndFragment.firstChild.textContent === '') { - event.preventDefault(); - - scribe.transactionManager.run(function () { - // Default P - // TODO: Abstract somewhere - var pNode = document.createElement('p'); - var brNode = document.createElement('br'); - pNode.appendChild(brNode); - - headingNode.parentNode.insertBefore(pNode, headingNode.nextElementSibling); - - // Re-apply range - range.setStart(pNode, 0); - range.setEnd(pNode, 0); - - selection.selection.removeAllRanges(); - selection.selection.addRange(range); - }); - } - } - } - }); - } - - /** - * If the paragraphs option is set to true, we need to manually handle - * keyboard navigation inside list item nodes. - */ - if (scribe.allowsBlockElements()) { - scribe.el.addEventListener('keydown', function (event) { - if (event.keyCode === 13 || event.keyCode === 8) { // enter || backspace - - var selection = new scribe.api.Selection(); - var range = selection.range; - - if (range.collapsed) { - var containerLIElement = selection.getContaining(function (node) { - return node.nodeName === 'LI'; - }); - if (containerLIElement && containerLIElement.textContent.trim() === '') { - /** - * LIs - */ - - event.preventDefault(); - - var listNode = selection.getContaining(function (node) { - return node.nodeName === 'UL' || node.nodeName === 'OL'; - }); - - var command = scribe.getCommand(listNode.nodeName === 'OL' ? 'insertOrderedList' : 'insertUnorderedList'); - - command.execute(); - } - } - } - }); - } - - /** - * We have to hijack the paste event to ensure it uses - * `scribe.insertHTML`, which executes the Scribe version of the command - * and also runs the formatters. - */ - - /** - * TODO: could we implement this as a polyfill for `event.clipboardData` instead? - * I also don't like how it has the authority to perform `event.preventDefault`. - */ - - function agentIsSafari() { - var ua = navigator.userAgent; - return ua.search('Safari') >= 0 && ua.search('Chrome') < 0; - } - - scribe.el.addEventListener('paste', function handlePaste(event) { - /** - * Browsers without the Clipboard API (specifically `ClipboardEvent.clipboardData`) - * and Safari will execute the second branch here. - */ - if (event.clipboardData - && (contains(event.clipboardData.types, 'text/html') || !agentIsSafari()) - ) { - event.preventDefault(); - - if (contains(event.clipboardData.types, 'text/html')) { - var html = event.clipboardData.getData('text/html'); - html = scribe._htmlFormatterFactory.formatPaste(html); - scribe.insertHTML(html); - } else { - scribe.insertPlainText(event.clipboardData.getData('text/plain')); - } - } else { - /** - * If the browser doesn't have `ClipboardEvent.clipboardData`, we run through a - * sequence of events: - * - * - Save the text selection - * - Focus another, hidden textarea so we paste there - * - Copy the pasted content of said textarea - * - Give focus back to the scribe - * - Restore the text selection - * - * This is required because, without access to the Clipboard API, there is literally - * no other way to manipulate content on paste. - * As per: https://github.com/jejacks0n/mercury/issues/23#issuecomment-2308347 - * - * Firefox <= 21 - * https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent.clipboardData - */ - - var selection = new scribe.api.Selection(); - - // Store the caret position - selection.placeMarkers(); - - var bin = document.createElement('div'); - document.body.appendChild(bin); - bin.setAttribute('contenteditable', true); - bin.focus(); - - // Wait for the paste to happen (next loop?) - setTimeout(function () { - var data = bin.innerHTML; - bin.parentNode.removeChild(bin); - - // Restore the caret position - selection.selectMarkers(); - /** - * Firefox 19 (and maybe others): even though the applied range - * exists within the Scribe instance, we need to focus it. - */ - scribe.el.focus(); - - data = scribe._htmlFormatterFactory.formatPaste(data); - scribe.insertHTML(data); - }, 1); - } - }); - - }; - }; -}); - -define('plugins/core/formatters/html/replace-nbsp-chars',[],function () { - - /** - * Chrome: - */ - - - - return function () { - return function (scribe) { - var nbspCharRegExp = /(\s| )+/g; - - // TODO: should we be doing this on paste? - scribe.registerHTMLFormatter('export', function (html) { - return html.replace(nbspCharRegExp, ' '); - }); - }; - }; - -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/arrays/last',['../functions/createCallback', '../internals/slice'], function(createCallback, slice) { - - /** Used as a safe reference for `undefined` in pre ES5 environments */ - var undefined; - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeMax = Math.max; - - /** - * Gets the last element or last `n` elements of an array. If a callback is - * provided elements at the end of the array are returned as long as the - * callback returns truey. The callback is bound to `thisArg` and invoked - * with three arguments; (value, index, array). - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @category Arrays - * @param {Array} array The array to query. - * @param {Function|Object|number|string} [callback] The function called - * per element or the number of elements to return. If a property name or - * object is provided it will be used to create a "_.pluck" or "_.where" - * style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the last element(s) of `array`. - * @example - * - * _.last([1, 2, 3]); - * // => 3 - * - * _.last([1, 2, 3], 2); - * // => [2, 3] - * - * _.last([1, 2, 3], function(num) { - * return num > 1; - * }); - * // => [2, 3] - * - * var characters = [ - * { 'name': 'barney', 'blocked': false, 'employer': 'slate' }, - * { 'name': 'fred', 'blocked': true, 'employer': 'slate' }, - * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' } - * ]; - * - * // using "_.pluck" callback shorthand - * _.pluck(_.last(characters, 'blocked'), 'name'); - * // => ['fred', 'pebbles'] - * - * // using "_.where" callback shorthand - * _.last(characters, { 'employer': 'na' }); - * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }] - */ - function last(array, callback, thisArg) { - var n = 0, - length = array ? array.length : 0; - - if (typeof callback != 'number' && callback != null) { - var index = length; - callback = createCallback(callback, thisArg, 3); - while (index-- && callback(array[index], index, array)) { - n++; - } - } else { - n = callback; - if (n == null || thisArg) { - return array ? array[length - 1] : undefined; - } - } - return slice(array, nativeMax(0, length - n)); - } - - return last; -}); - -define('plugins/core/formatters/html/enforce-p-elements',[ - 'lodash-amd/modern/arrays/last', - 'scribe-common/src/element' -], function ( - last, - element -) { - - /** - * Chrome and Firefox: Upon pressing backspace inside of a P, the - * browser deletes the paragraph element, leaving the caret (and any - * content) outside of any P. - * - * Firefox: Erasing across multiple paragraphs, or outside of a - * whole paragraph (e.g. by ‘Select All’) will leave content outside - * of any P. - * - * Entering a new line in a pristine state state will insert - * `
`s (in Chrome) or `
`s (in Firefox) where previously we - * had `

`'s. This patches the behaviour of delete/backspace so - * that we do not end up in a pristine state. - */ - - - - /** - * Wrap consecutive inline elements and text nodes in a P element. - */ - function wrapChildNodes(parentNode) { - var groups = Array.prototype.reduce.call(parentNode.childNodes, - function (accumulator, binChildNode) { - var group = last(accumulator); - if (! group) { - startNewGroup(); - } else { - var isBlockGroup = element.isBlockElement(group[0]); - if (isBlockGroup === element.isBlockElement(binChildNode)) { - group.push(binChildNode); - } else { - startNewGroup(); - } - } - - return accumulator; - - function startNewGroup() { - var newGroup = [binChildNode]; - accumulator.push(newGroup); - } - }, []); - - var consecutiveInlineElementsAndTextNodes = groups.filter(function (group) { - var isBlockGroup = element.isBlockElement(group[0]); - return ! isBlockGroup; - }); - - consecutiveInlineElementsAndTextNodes.forEach(function (nodes) { - var pElement = document.createElement('p'); - nodes[0].parentNode.insertBefore(pElement, nodes[0]); - nodes.forEach(function (node) { - pElement.appendChild(node); - }); - }); - - parentNode._isWrapped = true; - } - - // Traverse the tree, wrapping child nodes as we go. - function traverse(parentNode) { - var treeWalker = document.createTreeWalker(parentNode, NodeFilter.SHOW_ELEMENT); - var node = treeWalker.firstChild(); - - // FIXME: does this recurse down? - - while (node) { - // TODO: At the moment we only support BLOCKQUOTEs. See failing - // tests. - if (node.nodeName === 'BLOCKQUOTE' && ! node._isWrapped) { - wrapChildNodes(node); - traverse(parentNode); - break; - } - node = treeWalker.nextSibling(); - } - } - - return function () { - return function (scribe) { - - scribe.registerHTMLFormatter('normalize', function (html) { - /** - * Ensure P mode. - * - * Wrap any orphan text nodes in a P element. - */ - // TODO: This should be configurable and also correct markup such as - // `

    1
` to
  • 2
`. See skipped tests. - // TODO: This should probably be a part of HTML Janitor, or some other - // formatter. - var bin = document.createElement('div'); - bin.innerHTML = html; - - wrapChildNodes(bin); - traverse(bin); - - return bin.innerHTML; - }); - - }; - }; - -}); - -define('plugins/core/formatters/html/ensure-selectable-containers',[ - 'scribe-common/src/element', - 'lodash-amd/modern/collections/contains' - ], function ( - element, - contains - ) { - - /** - * Chrome and Firefox: All elements need to contain either text or a `
` to - * remain selectable. (Unless they have a width and height explicitly set with - * CSS(?), as per: http://jsbin.com/gulob/2/edit?html,css,js,output) - */ - - - - // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements - var html5VoidElements = ['AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR']; - - function traverse(parentNode) { - // Instead of TreeWalker, which gets confused when the BR is added to the dom, - // we recursively traverse the tree to look for an empty node that can have childNodes - - var node = parentNode.firstElementChild; - - function isEmpty(node) { - return node.children.length === 0 - || (node.children.length === 1 - && element.isSelectionMarkerNode(node.children[0])); - } - - while (node) { - if (!element.isSelectionMarkerNode(node)) { - // Find any node that contains no child *elements*, or just contains - // whitespace, and is not self-closing - if (isEmpty(node) && - node.textContent.trim() === '' && - !contains(html5VoidElements, node.nodeName)) { - node.appendChild(document.createElement('br')); - } else if (node.children.length > 0) { - traverse(node); - } - } - node = node.nextElementSibling; - } - } - - return function () { - return function (scribe) { - - scribe.registerHTMLFormatter('normalize', function (html) { - var bin = document.createElement('div'); - bin.innerHTML = html; - - traverse(bin); - - return bin.innerHTML; - }); - - }; - }; - -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/htmlEscapes',[], function() { - - /** - * Used to convert characters to HTML entities: - * - * Though the `>` character is escaped for symmetry, characters like `>` and `/` - * don't require escaping in HTML and have no special meaning unless they're part - * of a tag or an unquoted attribute value. - * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") - */ - var htmlEscapes = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - - return htmlEscapes; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/escapeHtmlChar',['./htmlEscapes'], function(htmlEscapes) { - - /** - * Used by `escape` to convert characters to HTML entities. - * - * @private - * @param {string} match The matched character to escape. - * @returns {string} Returns the escaped character. - */ - function escapeHtmlChar(match) { - return htmlEscapes[match]; - } - - return escapeHtmlChar; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/reUnescapedHtml',['./htmlEscapes', '../objects/keys'], function(htmlEscapes, keys) { - - /** Used to match HTML entities and HTML characters */ - var reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g'); - - return reUnescapedHtml; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/escape',['../internals/escapeHtmlChar', '../objects/keys', '../internals/reUnescapedHtml'], function(escapeHtmlChar, keys, reUnescapedHtml) { - - /** - * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their - * corresponding HTML entities. - * - * @static - * @memberOf _ - * @category Utilities - * @param {string} string The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escape('Fred, Wilma, & Pebbles'); - * // => 'Fred, Wilma, & Pebbles' - */ - function escape(string) { - return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); - } - - return escape; -}); - -define('plugins/core/formatters/plain-text/escape-html-characters',[ - 'lodash-amd/modern/utilities/escape' -], function ( - escape -) { - - - - return function () { - return function (scribe) { - scribe.registerPlainTextFormatter(escape); - }; - }; - -}); - -define('plugins/core/inline-elements-mode',[],function () { - - - - // TODO: abstract - function hasContent(rootNode) { - var treeWalker = document.createTreeWalker(rootNode); - - while (treeWalker.nextNode()) { - if (treeWalker.currentNode) { - // If the node is a non-empty element or has content - if (~['br'].indexOf(treeWalker.currentNode.nodeName.toLowerCase()) || treeWalker.currentNode.length > 0) { - return true; - } - } - } - - return false; - } - - return function () { - return function (scribe) { - /** - * Firefox has a `insertBrOnReturn` command, but this is not a part of - * any standard. One day we might have an `insertLineBreak` command, - * proposed by this spec: - * https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-insertlinebreak-command - * As per: http://jsbin.com/IQUraXA/1/edit?html,js,output - */ - scribe.el.addEventListener('keydown', function (event) { - if (event.keyCode === 13) { // enter - var selection = new scribe.api.Selection(); - var range = selection.range; - - var blockNode = selection.getContaining(function (node) { - return node.nodeName === 'LI' || (/^(H[1-6])$/).test(node.nodeName); - }); - - if (! blockNode) { - event.preventDefault(); - - scribe.transactionManager.run(function () { - /** - * Firefox: Delete the bogus BR as we insert another one later. - * We have to do this because otherwise the browser will believe - * there is content to the right of the selection. - */ - if (scribe.el.lastChild.nodeName === 'BR') { - scribe.el.removeChild(scribe.el.lastChild); - } - - var brNode = document.createElement('br'); - - range.insertNode(brNode); - // After inserting the BR into the range is no longer collapsed, so - // we have to collapse it again. - // TODO: Older versions of Firefox require this argument even though - // it is supposed to be optional. Proxy/polyfill? - range.collapse(false); - - /** - * Chrome: If there is no right-hand side content, inserting a BR - * will not appear to create a line break. - * Firefox: If there is no right-hand side content, inserting a BR - * will appear to create a weird "half-line break". - * - * Possible solution: Insert two BRs. - * ✓ Chrome: Inserting two BRs appears to create a line break. - * Typing will then delete the bogus BR element. - * Firefox: Inserting two BRs will create two line breaks. - * - * Solution: Only insert two BRs if there is no right-hand - * side content. - * - * If the user types on a line immediately after a BR element, - * Chrome will replace the BR element with the typed characters, - * whereas Firefox will not. Thus, to satisfy Firefox we have to - * insert a bogus BR element on initialization (see below). - */ - - var contentToEndRange = range.cloneRange(); - contentToEndRange.setEndAfter(scribe.el.lastChild, 0); - - // Get the content from the range to the end of the heading - var contentToEndFragment = contentToEndRange.cloneContents(); - - // If there is not already a right hand side content we need to - // insert a bogus BR element. - if (! hasContent(contentToEndFragment)) { - var bogusBrNode = document.createElement('br'); - range.insertNode(bogusBrNode); - } - - var newRange = range.cloneRange(); - - newRange.setStartAfter(brNode, 0); - newRange.setEndAfter(brNode, 0); - - selection.selection.removeAllRanges(); - selection.selection.addRange(newRange); - }); - } - } - }.bind(this)); - - if (scribe.getHTML().trim() === '') { - // Bogus BR element for Firefox — see explanation above. - // TODO: also append when consumer sets the content manually. - // TODO: hide when the user calls `getHTML`? - scribe.setContent(''); - } - }; - }; -}); - -define('plugins/core/patches/commands/indent',[],function () { - - /** - * Prevent Chrome from inserting BLOCKQUOTEs inside of Ps, and also from - * adding a redundant `style` attribute to the created BLOCKQUOTE. - */ - - - - var INVISIBLE_CHAR = '\uFEFF'; - - return function () { - return function (scribe) { - var indentCommand = new scribe.api.CommandPatch('indent'); - - indentCommand.execute = function (value) { - scribe.transactionManager.run(function () { - /** - * Chrome: If we apply the indent command on an empty P, the - * BLOCKQUOTE will be nested inside the P. - * As per: http://jsbin.com/oDOriyU/3/edit?html,js,output - */ - var selection = new scribe.api.Selection(); - var range = selection.range; - - var isCaretOnNewLine = - (range.commonAncestorContainer.nodeName === 'P' - && range.commonAncestorContainer.innerHTML === '
'); - if (isCaretOnNewLine) { - // FIXME: this text node is left behind. Tidy it up somehow, - // or don't use it at all. - var textNode = document.createTextNode(INVISIBLE_CHAR); - - range.insertNode(textNode); - - range.setStart(textNode, 0); - range.setEnd(textNode, 0); - - selection.selection.removeAllRanges(); - selection.selection.addRange(range); - } - - scribe.api.CommandPatch.prototype.execute.call(this, value); - - /** - * Chrome: The BLOCKQUOTE created contains a redundant style attribute. - * As per: http://jsbin.com/AkasOzu/1/edit?html,js,output - */ - - // Renew the selection - selection = new scribe.api.Selection(); - var blockquoteNode = selection.getContaining(function (node) { - return node.nodeName === 'BLOCKQUOTE'; - }); - - if (blockquoteNode) { - blockquoteNode.removeAttribute('style'); - } - }.bind(this)); - }; - - scribe.commandPatches.indent = indentCommand; - }; - }; - -}); - -define('plugins/core/patches/commands/insert-html',['scribe-common/src/element'], function (element) { - - - - return function () { - return function (scribe) { - var insertHTMLCommandPatch = new scribe.api.CommandPatch('insertHTML'); - - insertHTMLCommandPatch.execute = function (value) { - scribe.transactionManager.run(function () { - scribe.api.CommandPatch.prototype.execute.call(this, value); - - /** - * Chrome: If a parent node has a CSS `line-height` when we apply the - * insertHTML command, Chrome appends a SPAN to plain content with - * inline styling replicating that `line-height`, and adjusts the - * `line-height` on inline elements. - * As per: http://jsbin.com/ilEmudi/4/edit?css,js,output - * - * FIXME: what if the user actually wants to use SPANs? This could - * cause conflicts. - */ - - // TODO: share somehow with similar event patch for P nodes - sanitize(scribe.el); - - function sanitize(parentNode) { - var treeWalker = document.createTreeWalker(parentNode, NodeFilter.SHOW_ELEMENT); - var node = treeWalker.firstChild(); - if (!node) { return; } - - do { - if (node.nodeName === 'SPAN') { - element.unwrap(parentNode, node); - } else { - /** - * If the list item contains inline elements such as - * A, B, or I, Chrome will also append an inline style for - * `line-height` on those elements, so we remove it here. - */ - node.style.lineHeight = null; - - // There probably wasn’t a `style` attribute before, so - // remove it if it is now empty. - if (node.getAttribute('style') === '') { - node.removeAttribute('style'); - } - } - - // Sanitize children - sanitize(node); - } while ((node = treeWalker.nextSibling())); - } - }.bind(this)); - }; - - scribe.commandPatches.insertHTML = insertHTMLCommandPatch; - }; - }; - -}); - -define('plugins/core/patches/commands/insert-list',['scribe-common/src/element', - 'scribe-common/src/node'], function (element, nodeHelpers) { - - - - return function () { - return function (scribe) { - var InsertListCommandPatch = function (commandName) { - scribe.api.CommandPatch.call(this, commandName); - }; - - InsertListCommandPatch.prototype = Object.create(scribe.api.CommandPatch.prototype); - InsertListCommandPatch.prototype.constructor = InsertListCommandPatch; - - InsertListCommandPatch.prototype.execute = function (value) { - scribe.transactionManager.run(function () { - scribe.api.CommandPatch.prototype.execute.call(this, value); - - if (this.queryState()) { - var selection = new scribe.api.Selection(); - - var listElement = selection.getContaining(function (node) { - return node.nodeName === 'OL' || node.nodeName === 'UL'; - }); - - - /** - * Firefox: If we apply the insertOrderedList or the insertUnorderedList - * command on an empty block, a P will be inserted after the OL/UL. - * As per: http://jsbin.com/cubacoli/3/edit?html,js,output - */ - - if (listElement.nextElementSibling && - listElement.nextElementSibling.childNodes.length === 0) { - nodeHelpers.removeNode(listElement.nextElementSibling); - } - - /** - * Chrome: If we apply the insertOrderedList or the insertUnorderedList - * command on an empty block, the OL/UL will be nested inside the block. - * As per: http://jsbin.com/eFiRedUc/1/edit?html,js,output - */ - - if (listElement) { - var listParentNode = listElement.parentNode; - // If list is within a text block then split that block - if (listParentNode && /^(H[1-6]|P)$/.test(listParentNode.nodeName)) { - selection.placeMarkers(); - // Move listElement out of the block - nodeHelpers.insertAfter(listElement, listParentNode); - selection.selectMarkers(); - - /** - * Chrome 27-34: An empty text node is inserted. - */ - if (listParentNode.childNodes.length === 2 && - nodeHelpers.isEmptyTextNode(listParentNode.firstChild)) { - nodeHelpers.removeNode(listParentNode); - } - - // Remove the block if it's empty - if (listParentNode.childNodes.length === 0) { - nodeHelpers.removeNode(listParentNode); - } - } - } - - /** - * Chrome: If a parent node has a CSS `line-height` when we apply the - * insertOrderedList or the insertUnorderedList command, Chrome appends - * a SPAN to LIs with inline styling replicating that `line-height`. - * As per: http://jsbin.com/OtemujAY/7/edit?html,css,js,output - * - * FIXME: what if the user actually wants to use SPANs? This could - * cause conflicts. - */ - - // TODO: share somehow with similar event patch for P nodes - var listItemElements = Array.prototype.slice.call(listElement.childNodes); - listItemElements.forEach(function(listItemElement) { - // We clone the childNodes into an Array so that it's - // not affected by any manipulation below when we - // iterate over it - var listItemElementChildNodes = Array.prototype.slice.call(listItemElement.childNodes); - listItemElementChildNodes.forEach(function(listElementChildNode) { - if (listElementChildNode.nodeName === 'SPAN') { - // Unwrap any SPAN that has been inserted - var spanElement = listElementChildNode; - element.unwrap(listItemElement, spanElement); - } else if (listElementChildNode.nodeType === Node.ELEMENT_NODE) { - /** - * If the list item contains inline elements such as - * A, B, or I, Chrome will also append an inline style for - * `line-height` on those elements, so we remove it here. - */ - listElementChildNode.style.lineHeight = null; - - // There probably wasn’t a `style` attribute before, so - // remove it if it is now empty. - if (listElementChildNode.getAttribute('style') === '') { - listElementChildNode.removeAttribute('style'); - } - } - }); - }); - } - }.bind(this)); - }; - - scribe.commandPatches.insertOrderedList = new InsertListCommandPatch('insertOrderedList'); - scribe.commandPatches.insertUnorderedList = new InsertListCommandPatch('insertUnorderedList'); - }; - }; - -}); - -define('plugins/core/patches/commands/outdent',[],function () { - - /** - * Prevent Chrome from removing formatting of BLOCKQUOTE contents. - */ - - - - return function () { - return function (scribe) { - var outdentCommand = new scribe.api.CommandPatch('outdent'); - - outdentCommand.execute = function () { - scribe.transactionManager.run(function () { - var selection = new scribe.api.Selection(); - var range = selection.range; - - var blockquoteNode = selection.getContaining(function (node) { - return node.nodeName === 'BLOCKQUOTE'; - }); - - if (range.commonAncestorContainer.nodeName === 'BLOCKQUOTE') { - /** - * Chrome: Applying the outdent command when a whole BLOCKQUOTE is - * selected removes the formatting of its contents. - * As per: http://jsbin.com/okAYaHa/1/edit?html,js,output - */ - - // Insert a copy of the selection before the BLOCKQUOTE, and then - // restore the selection on the copy. - selection.placeMarkers(); - // We want to copy the selected nodes *with* the markers - selection.selectMarkers(true); - var selectedNodes = range.cloneContents(); - blockquoteNode.parentNode.insertBefore(selectedNodes, blockquoteNode); - range.deleteContents(); - selection.selectMarkers(); - - // Delete the BLOCKQUOTE if it's empty - if (blockquoteNode.textContent === '') { - blockquoteNode.parentNode.removeChild(blockquoteNode); - } - } else { - /** - * Chrome: If we apply the outdent command on a P, the contents of the - * P will be outdented instead of the whole P element. - * As per: http://jsbin.com/IfaRaFO/1/edit?html,js,output - */ - - var pNode = selection.getContaining(function (node) { - return node.nodeName === 'P'; - }); - - if (pNode) { - /** - * If we are not at the start of end of a BLOCKQUOTE, we have to - * split the node and insert the P in the middle. - */ - - var nextSiblingNodes = (new scribe.api.Node(pNode)).nextAll(); - - if (nextSiblingNodes.length) { - var newContainerNode = document.createElement(blockquoteNode.nodeName); - - nextSiblingNodes.forEach(function (siblingNode) { - newContainerNode.appendChild(siblingNode); - }); - - blockquoteNode.parentNode.insertBefore(newContainerNode, blockquoteNode.nextElementSibling); - } - - selection.placeMarkers(); - blockquoteNode.parentNode.insertBefore(pNode, blockquoteNode.nextElementSibling); - selection.selectMarkers(); - - // If the BLOCKQUOTE is now empty, clean it up. - if (blockquoteNode.innerHTML === '') { - blockquoteNode.parentNode.removeChild(blockquoteNode); - } - } else { - scribe.api.CommandPatch.prototype.execute.call(this); - } - } - }.bind(this)); - }; - - scribe.commandPatches.outdent = outdentCommand; - }; - }; - -}); - -define('plugins/core/patches/commands/create-link',[],function () { - - - - return function () { - return function (scribe) { - var createLinkCommand = new scribe.api.CommandPatch('createLink'); - scribe.commandPatches.createLink = createLinkCommand; - - createLinkCommand.execute = function (value) { - var selection = new scribe.api.Selection(); - - /** - * Firefox does not create a link when selection is collapsed - * so we create it manually. http://jsbin.com/tutufi/2/edit?js,output - */ - if (selection.selection.isCollapsed) { - var aElement = document.createElement('a'); - aElement.setAttribute('href', value); - aElement.textContent = value; - - selection.range.insertNode(aElement); - - // Select the created link - var newRange = document.createRange(); - newRange.setStartBefore(aElement); - newRange.setEndAfter(aElement); - - selection.selection.removeAllRanges(); - selection.selection.addRange(newRange); - } else { - scribe.api.CommandPatch.prototype.execute.call(this, value); - } - }; - }; - }; - -}); - -define('plugins/core/patches/events',['scribe-common/src/element'], function (element) { - - - - return function () { - return function (scribe) { - /** - * Chrome: If a parent node has a CSS `line-height` when we apply the - * insert(Un)OrderedList command, altering the paragraph structure by pressing - * or (merging/deleting paragraphs) sometimes - * results in the application of a line-height attribute to the - * contents of the paragraph, either onto existing elements or - * by wrapping text in a span. - * As per: http://jsbin.com/isIdoKA/4/edit?html,css,js,output - * - * FIXME: what if the user actually wants to use SPANs? This could - * cause conflicts. - */ - // TODO: do we need to run this on every key press, or could we - // detect when the issue may have occurred? - // TODO: run in a transaction so as to record the change? how do - // we know in advance whether there will be a change though? - // TODO: share somehow with `InsertList` command - if (scribe.allowsBlockElements()) { - scribe.el.addEventListener('keyup', function (event) { - if (event.keyCode === 8 || event.keyCode === 46) { // backspace or delete - - var selection = new scribe.api.Selection(); - - // Note: the range is always collapsed on keyup here - var containerPElement = selection.getContaining(function (node) { - return node.nodeName === 'P'; - }); - if (containerPElement) { - /** - * The 'input' event listener has already triggered - * and recorded the faulty content as an item in the - * UndoManager. We interfere with the undoManager - * here to discard that history item, and let the next - * transaction run produce a clean one instead. - * - * FIXME: ideally we would not trigger a - * 'content-changed' event with faulty HTML at all, but - * it's too late to cancel it at this stage (and it's - * not happened yet at keydown time). - */ - scribe.undoManager.undo(); - - scribe.transactionManager.run(function () { - // Store the caret position - selection.placeMarkers(); - - // We clone the childNodes into an Array so that it's - // not affected by any manipulation below when we - // iterate over it - var pElementChildNodes = Array.prototype.slice.call(containerPElement.childNodes); - pElementChildNodes.forEach(function(pElementChildNode) { - if (pElementChildNode.nodeName === 'SPAN') { - // Unwrap any SPAN that has been inserted - var spanElement = pElementChildNode; - element.unwrap(containerPElement, spanElement); - } else if (pElementChildNode.nodeType === Node.ELEMENT_NODE) { - /** - * If the paragraph contains inline elements such as - * A, B, or I, Chrome will also append an inline style for - * `line-height` on those elements, so we remove it here. - */ - pElementChildNode.style.lineHeight = null; - - // There probably wasn’t a `style` attribute before, so - // remove it if it is now empty. - if (pElementChildNode.getAttribute('style') === '') { - pElementChildNode.removeAttribute('style'); - } - } - }); - - selection.selectMarkers(); - }); - } - } - }); - } - }; - }; -}); - -define('plugins/core/patches',[ - './patches/commands/indent', - './patches/commands/insert-html', - './patches/commands/insert-list', - './patches/commands/outdent', - './patches/commands/create-link', - './patches/events' -], function ( - indentCommand, - insertHTMLCommand, - insertListCommands, - outdentCommand, - createLinkCommand, - events -) { - - /** - * Command patches browser inconsistencies. They do not perform core features - * of the editor, such as ensuring P elements are created when - * applying/unapplying commands — that is the job of the core commands. - */ - - - - return { - commands: { - indent: indentCommand, - insertHTML: insertHTMLCommand, - insertList: insertListCommands, - outdent: outdentCommand, - createLink: createLinkCommand, - }, - events: events - }; - -}); - -define('plugins/core/set-root-p-element',[],function () { - - /** - * Sets the default content of the scribe so that each carriage return creates - * a P. - */ - - - - return function () { - return function (scribe) { - // The content might have already been set, in which case we don't want - // to apply. - if (scribe.getHTML().trim() === '') { - /** - * We have to begin with the following HTML, because otherwise some - * browsers(?) will position the caret outside of the P when the scribe is - * focused. - */ - scribe.setContent('


'); - } - }; - }; - -}); - -define('api/command-patch',[],function () { - - - - return function (scribe) { - function CommandPatch(commandName) { - this.commandName = commandName; - } - - CommandPatch.prototype.execute = function (value) { - scribe.transactionManager.run(function () { - document.execCommand(this.commandName, false, value || null); - }.bind(this)); - }; - - CommandPatch.prototype.queryState = function () { - // Hack for firefox, which does not like this. - if (this.commandName === 'insertOrderedList' || this.commandName == 'insertUnorderedList') { - return false; - } - return document.queryCommandState(this.commandName); - }; - - CommandPatch.prototype.queryEnabled = function () { - return document.queryCommandEnabled(this.commandName); - }; - - return CommandPatch; - }; - -}); - -define('api/command',[],function () { - - - - return function (scribe) { - function Command(commandName) { - this.commandName = commandName; - this.patch = scribe.commandPatches[this.commandName]; - } - - Command.prototype.execute = function (value) { - if (this.patch) { - this.patch.execute(value); - } else { - scribe.transactionManager.run(function () { - document.execCommand(this.commandName, false, value || null); - }.bind(this)); - } - }; - - Command.prototype.queryState = function () { - if (this.patch) { - return this.patch.queryState(); - } else { - return document.queryCommandState(this.commandName); - } - }; - - Command.prototype.queryEnabled = function () { - if (this.patch) { - return this.patch.queryEnabled(); - } else { - return document.queryCommandEnabled(this.commandName); - } - }; - - return Command; - }; - -}); - -define('api/node',[],function () { - - - - function Node(node) { - this.node = node; - } - - // TODO: should the return value be wrapped in one of our APIs? - // Node or Selection? - // TODO: write tests. unit or integration? - Node.prototype.getAncestor = function (nodeFilter) { - var isTopContainerElement = function (element) { - return element && element.attributes - && element.attributes.getNamedItem('contenteditable'); - }; - // TODO: should this happen here? - if (isTopContainerElement(this.node)) { - return; - } - - var currentNode = this.node.parentNode; - - // If it's a `contenteditable` then it's likely going to be the Scribe - // instance, so stop traversing there. - while (currentNode && ! isTopContainerElement(currentNode)) { - if (nodeFilter(currentNode)) { - return currentNode; - } - currentNode = currentNode.parentNode; - } - }; - - Node.prototype.nextAll = function () { - var all = []; - var el = this.node.nextSibling; - while (el) { - all.push(el); - el = el.nextSibling; - } - return all; - }; - - return Node; - -}); - -define('api/selection',[],function () { - - - - return function (scribe) { - function Selection() { - this.selection = window.getSelection(); - - if (this.selection.rangeCount) { - this.range = this.selection.getRangeAt(0); - } - } - - Selection.prototype.getContaining = function (nodeFilter) { - if (!this.range) { - return; - } - var node = new scribe.api.Node(this.range.commonAncestorContainer); - var isTopContainerElement = node.node && node.node.attributes - && node.node.attributes.getNamedItem('contenteditable'); - - return ! isTopContainerElement && nodeFilter(node.node) ? node.node : node.getAncestor(nodeFilter); - }; - - Selection.prototype.placeMarkers = function () { - if (!this.range) { - return; - } - var startMarker = document.createElement('em'); - startMarker.classList.add('scribe-marker'); - var endMarker = document.createElement('em'); - endMarker.classList.add('scribe-marker'); - - // End marker - var rangeEnd = this.range.cloneRange(); - rangeEnd.collapse(false); - rangeEnd.insertNode(endMarker); - - /** - * Chrome and Firefox: `Range.insertNode` inserts a bogus text node after - * the inserted element. We just remove it. This in turn creates several - * bugs when perfoming commands on selections that contain an empty text - * node (`removeFormat`, `unlink`). - * As per: http://jsbin.com/hajim/5/edit?js,console,output - */ - // TODO: abstract into polyfill for `Range.insertNode` - if (endMarker.nextSibling && - endMarker.nextSibling.nodeType === Node.TEXT_NODE - && endMarker.nextSibling.data === '') { - endMarker.parentNode.removeChild(endMarker.nextSibling); - } - - - - /** - * Chrome and Firefox: `Range.insertNode` inserts a bogus text node before - * the inserted element when the child element is at the start of a block - * element. We just remove it. - * FIXME: Document why we need to remove this - * As per: http://jsbin.com/sifez/1/edit?js,console,output - */ - if (endMarker.previousSibling && - endMarker.previousSibling.nodeType === Node.TEXT_NODE - && endMarker.previousSibling.data === '') { - endMarker.parentNode.removeChild(endMarker.previousSibling); - } - - - /** - * This is meant to test Chrome inserting erroneous text blocks into - * the scribe el when focus switches from a scribe.el to a button to - * the scribe.el. However, this is impossible to simlulate correctly - * in a test. - * - * This behaviour does not happen in Firefox. - * - * See http://jsbin.com/quhin/2/edit?js,output,console - * - * To reproduce the bug, follow the following steps: - * 1. Select text and create H2 - * 2. Move cursor to front of text. - * 3. Remove the H2 by clicking the button - * 4. Observe that you are left with an empty H2 - * after the element. - * - * The problem is caused by the Range being different, depending on - * the position of the marker. - * - * Consider the following two scenarios. - * - * A) - * 1. scribe.el contains: ["1", scribe-marker] - * 2. Click button and click the right of to scribe.el - * 3. scribe.el contains: ["1", scribe-marker. #text] - * - * This is wrong but does not cause the problem. - * - * B) - * 1. scribe.el contains: ["1", scribe-marker] - * 2. Click button and click to left of scribe.el - * 3. scribe.el contains: [#text, scribe-marker, "1"] - * - * The second example sets the range in the wrong place, meaning - * that in the second case the formatBlock is executed on the wrong - * element [the text node] leaving the empty H2 behind. - **/ - - - if (! this.selection.isCollapsed) { - // Start marker - var rangeStart = this.range.cloneRange(); - rangeStart.collapse(true); - rangeStart.insertNode(startMarker); - - /** - * Chrome and Firefox: `Range.insertNode` inserts a bogus text node after - * the inserted element. We just remove it. This in turn creates several - * bugs when perfoming commands on selections that contain an empty text - * node (`removeFormat`, `unlink`). - * As per: http://jsbin.com/hajim/5/edit?js,console,output - */ - // TODO: abstract into polyfill for `Range.insertNode` - if (startMarker.nextSibling && - startMarker.nextSibling.nodeType === Node.TEXT_NODE - && startMarker.nextSibling.data === '') { - startMarker.parentNode.removeChild(startMarker.nextSibling); - } - - /** - * Chrome and Firefox: `Range.insertNode` inserts a bogus text node - * before the inserted element when the child element is at the start of - * a block element. We just remove it. - * FIXME: Document why we need to remove this - * As per: http://jsbin.com/sifez/1/edit?js,console,output - */ - if (startMarker.previousSibling && - startMarker.previousSibling.nodeType === Node.TEXT_NODE - && startMarker.previousSibling.data === '') { - startMarker.parentNode.removeChild(startMarker.previousSibling); - } - } - - - this.selection.removeAllRanges(); - this.selection.addRange(this.range); - }; - - Selection.prototype.getMarkers = function () { - return scribe.el.querySelectorAll('em.scribe-marker'); - }; - - Selection.prototype.removeMarkers = function () { - var markers = this.getMarkers(); - Array.prototype.forEach.call(markers, function (marker) { - marker.parentNode.removeChild(marker); - }); - }; - - // This will select markers if there are any. You will need to focus the - // Scribe instance’s element if it is not already for the selection to - // become active. - Selection.prototype.selectMarkers = function (keepMarkers) { - var markers = this.getMarkers(); - if (!markers.length) { - return; - } - - var newRange = document.createRange(); - - newRange.setStartBefore(markers[0]); - if (markers.length >= 2) { - newRange.setEndAfter(markers[1]); - } else { - // We always reset the end marker because otherwise it will just - // use the current range’s end marker. - newRange.setEndAfter(markers[0]); - } - - if (! keepMarkers) { - this.removeMarkers(); - } - - this.selection.removeAllRanges(); - this.selection.addRange(newRange); - }; - - Selection.prototype.isCaretOnNewLine = function () { - var containerPElement = this.getContaining(function (node) { - return node.nodeName === 'P'; - }); - // We must do `innerHTML.trim()` to avoid weird Firefox bug: - // http://stackoverflow.com/questions/3676927/why-if-element-innerhtml-is-not-working-in-firefox - if (containerPElement) { - var containerPElementInnerHTML = containerPElement.innerHTML.trim(); - return (containerPElement.nodeName === 'P' - && (containerPElementInnerHTML === '
' - || containerPElementInnerHTML === '')); - } else { - return false; - } - }; - - return Selection; - }; - -}); - -define('api/simple-command',[],function () { - - - - return function (api, scribe) { - function SimpleCommand(commandName, nodeName) { - scribe.api.Command.call(this, commandName); - - this.nodeName = nodeName; - } - - SimpleCommand.prototype = Object.create(api.Command.prototype); - SimpleCommand.prototype.constructor = SimpleCommand; - - SimpleCommand.prototype.queryState = function () { - var selection = new scribe.api.Selection(); - return scribe.api.Command.prototype.queryState.call(this) && !! selection.getContaining(function (node) { - return node.nodeName === this.nodeName; - }.bind(this)); - }; - - return SimpleCommand; - }; - -}); - -define('api',[ - './api/command-patch', - './api/command', - './api/node', - './api/selection', - './api/simple-command' -], function ( - buildCommandPatch, - buildCommand, - Node, - buildSelection, - buildSimpleCommand -) { - - - - return function Api(scribe) { - this.CommandPatch = buildCommandPatch(scribe); - this.Command = buildCommand(scribe); - this.Node = Node; - this.Selection = buildSelection(scribe); - this.SimpleCommand = buildSimpleCommand(this, scribe); - }; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/assign',['../internals/baseCreateCallback', './keys', '../internals/objectTypes'], function(baseCreateCallback, keys, objectTypes) { - - /** - * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with two - * arguments; (objectValue, sourceValue). - * - * @static - * @memberOf _ - * @type Function - * @alias extend - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize assigning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. - * @example - * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } - * - * var defaults = _.partialRight(_.assign, function(a, b) { - * return typeof a == 'undefined' ? b : a; - * }); - * - * var object = { 'name': 'barney' }; - * defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } - */ - var assign = function(object, source, guard) { - var index, iterable = object, result = iterable; - if (!iterable) return result; - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { - var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2); - } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { - callback = args[--argsLength]; - } - while (++argsIndex < argsLength) { - iterable = args[argsIndex]; - if (iterable && objectTypes[typeof iterable]) { - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]; - } - } - } - return result - }; - - return assign; -}); - -define('transaction-manager',['lodash-amd/modern/objects/assign'], function (assign) { - - - - return function (scribe) { - function TransactionManager() { - this.history = []; - } - - assign(TransactionManager.prototype, { - start: function () { - this.history.push(1); - }, - - end: function () { - this.history.pop(); - - if (this.history.length === 0) { - scribe.pushHistory(); - scribe.trigger('content-changed'); - } - }, - - run: function (transaction) { - this.start(); - // If there is an error, don't prevent the transaction from ending. - try { - if (transaction) { - transaction(); - } - } finally { - this.end(); - } - } - }); - - return TransactionManager; - }; -}); - -define('undo-manager',[],function () { - - - - return function (scribe) { - - function UndoManager() { - this.position = -1; - this.stack = []; - this.debug = scribe.isDebugModeEnabled(); - } - - UndoManager.prototype.maxStackSize = 100; - - UndoManager.prototype.push = function (item) { - if (this.debug) { - console.log('UndoManager.push: %s', item); - } - this.stack.length = ++this.position; - this.stack.push(item); - - while (this.stack.length > this.maxStackSize) { - this.stack.shift(); - --this.position; - } - }; - - UndoManager.prototype.undo = function () { - if (this.position > 0) { - return this.stack[--this.position]; - } - }; - - UndoManager.prototype.redo = function () { - if (this.position < (this.stack.length - 1)) { - return this.stack[++this.position]; - } - }; - - return UndoManager; - }; - -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/arrays/pull',[], function() { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var splice = arrayRef.splice; - - /** - * Removes all provided values from the given array using strict equality for - * comparisons, i.e. `===`. - * - * @static - * @memberOf _ - * @category Arrays - * @param {Array} array The array to modify. - * @param {...*} [value] The values to remove. - * @returns {Array} Returns `array`. - * @example - * - * var array = [1, 2, 3, 1, 2, 3]; - * _.pull(array, 2, 3); - * console.log(array); - * // => [1, 1] - */ - function pull(array) { - var args = arguments, - argsIndex = 0, - argsLength = args.length, - length = array ? array.length : 0; - - while (++argsIndex < argsLength) { - var index = -1, - value = args[argsIndex]; - while (++index < length) { - if (array[index] === value) { - splice.call(array, index--, 1); - length--; - } - } - } - return array; - } - - return pull; -}); - -define('event-emitter',['lodash-amd/modern/arrays/pull'], function (pull) { - - - - // TODO: once - // TODO: unit test - // Good example of a complete(?) implementation: https://github.com/Wolfy87/EventEmitter - function EventEmitter() { - this._listeners = {}; - } - - EventEmitter.prototype.on = function (eventName, fn) { - var listeners = this._listeners[eventName] || []; - - listeners.push(fn); - - this._listeners[eventName] = listeners; - }; - - EventEmitter.prototype.off = function (eventName, fn) { - var listeners = this._listeners[eventName] || []; - if (fn) { - pull(listeners, fn); - } else { - delete this._listeners[eventName]; - } - }; - - EventEmitter.prototype.trigger = function (eventName, args) { - var listeners = this._listeners[eventName] || []; - - listeners.forEach(function (listener) { - listener.apply(null, args); - }); - }; - - return EventEmitter; - -}); - -define('scribe',[ - 'lodash-amd/modern/objects/defaults', - 'lodash-amd/modern/arrays/flatten', - './plugins/core/commands', - './plugins/core/events', - './plugins/core/formatters/html/replace-nbsp-chars', - './plugins/core/formatters/html/enforce-p-elements', - './plugins/core/formatters/html/ensure-selectable-containers', - './plugins/core/formatters/plain-text/escape-html-characters', - './plugins/core/inline-elements-mode', - './plugins/core/patches', - './plugins/core/set-root-p-element', - './api', - './transaction-manager', - './undo-manager', - './event-emitter' -], function ( - defaults, - flatten, - commands, - events, - replaceNbspCharsFormatter, - enforcePElements, - ensureSelectableContainers, - escapeHtmlCharactersFormatter, - inlineElementsMode, - patches, - setRootPElement, - Api, - buildTransactionManager, - buildUndoManager, - EventEmitter -) { - - - - function Scribe(el, options) { - EventEmitter.call(this); - - this.el = el; - this.commands = {}; - this.options = defaults(options || {}, { - allowBlockElements: true, - debug: false - }); - this.commandPatches = {}; - this._plainTextFormatterFactory = new FormatterFactory(); - this._htmlFormatterFactory = new HTMLFormatterFactory(); - - this.api = new Api(this); - - var TransactionManager = buildTransactionManager(this); - this.transactionManager = new TransactionManager(); - - var UndoManager = buildUndoManager(this); - this.undoManager = new UndoManager(); - - this.el.setAttribute('contenteditable', true); - - this.el.addEventListener('input', function () { - /** - * This event triggers when either the user types something or a native - * command is executed which causes the content to change (i.e. - * `document.execCommand('bold')`). We can't wrap a transaction around - * these actions, so instead we run the transaction in this event. - */ - this.transactionManager.run(); - }.bind(this), false); - - /** - * Core Plugins - */ - - if (this.allowsBlockElements()) { - // Commands assume block elements are allowed, so all we have to do is - // set the content. - // TODO: replace this by initial formatter application? - this.use(setRootPElement()); - // Warning: enforcePElements must come before ensureSelectableContainers - this.use(enforcePElements()); - this.use(ensureSelectableContainers()); - } else { - // Commands assume block elements are allowed, so we have to set the - // content and override some UX. - this.use(inlineElementsMode()); - } - - // Formatters - this.use(escapeHtmlCharactersFormatter()); - this.use(replaceNbspCharsFormatter()); - - - // Patches - this.use(patches.commands.indent()); - this.use(patches.commands.insertHTML()); - this.use(patches.commands.insertList()); - this.use(patches.commands.outdent()); - this.use(patches.commands.createLink()); - this.use(patches.events()); - - this.use(commands.indent()); - this.use(commands.insertList()); - this.use(commands.outdent()); - this.use(commands.redo()); - this.use(commands.subscript()); - this.use(commands.superscript()); - this.use(commands.undo()); - - this.use(events()); - } - - Scribe.prototype = Object.create(EventEmitter.prototype); - - // For plugins - // TODO: tap combinator? - Scribe.prototype.use = function (configurePlugin) { - configurePlugin(this); - return this; - }; - - Scribe.prototype.setHTML = function (html, skipFormatters) { - if (skipFormatters) { - this._skipFormatters = true; - } - this.el.innerHTML = html; - }; - - Scribe.prototype.getHTML = function () { - return this.el.innerHTML; - }; - - Scribe.prototype.getContent = function () { - // Remove bogus BR element for Firefox — see explanation in BR mode files. - return this._htmlFormatterFactory.formatForExport(this.getHTML().replace(/
$/, '')); - }; - - Scribe.prototype.getTextContent = function () { - return this.el.textContent; - }; - - Scribe.prototype.pushHistory = function () { - var previousUndoItem = this.undoManager.stack[this.undoManager.position]; - var previousContent = previousUndoItem && previousUndoItem - .replace(//g, '').replace(/<\/em>/g, ''); - - /** - * Chrome and Firefox: If we did push to the history, this would break - * browser magic around `Document.queryCommandState` (http://jsbin.com/eDOxacI/1/edit?js,console,output). - * This happens when doing any DOM manipulation. - */ - - // We only want to push the history if the content actually changed. - if (! previousUndoItem || (previousUndoItem && this.getContent() !== previousContent)) { - var selection = new this.api.Selection(); - - selection.placeMarkers(); - var html = this.getHTML(); - selection.removeMarkers(); - - this.undoManager.push(html); - - return true; - } else { - return false; - } - }; - - Scribe.prototype.getCommand = function (commandName) { - return this.commands[commandName] || this.commandPatches[commandName] || new this.api.Command(commandName); - }; - - Scribe.prototype.restoreFromHistory = function (historyItem) { - this.setHTML(historyItem, true); - - // Restore the selection - var selection = new this.api.Selection(); - selection.selectMarkers(); - - // Because we skip the formatters, a transaction is not run, so we have to - // emit this event ourselves. - this.trigger('content-changed'); - }; - - // This will most likely be moved to another object eventually - Scribe.prototype.allowsBlockElements = function () { - return this.options.allowBlockElements; - }; - - Scribe.prototype.setContent = function (content) { - if (! this.allowsBlockElements()) { - // Set bogus BR element for Firefox — see explanation in BR mode files. - content = content + '
'; - } - - this.setHTML(content); - - this.trigger('content-changed'); - }; - - Scribe.prototype.insertPlainText = function (plainText) { - this.insertHTML('

' + this._plainTextFormatterFactory.format(plainText) + '

'); - }; - - Scribe.prototype.insertHTML = function (html) { - /** - * When pasting text from Google Docs in both Chrome and Firefox, - * the resulting text will be wrapped in a B tag. So it would look - * something like

Text

, which is invalid HTML. The command - * insertHTML will then attempt to fix this content by moving the B tag - * inside the P. The result is:

Text

, which is valid - * but means an extra P is inserted into the text. To avoid this we run the - * formatters before the insertHTML command as the formatter will - * unwrap the P and delete the B tag. It is acceptable to remove invalid - * HTML as Scribe should only accept valid HTML. - * - * See http://jsbin.com/cayosada/3/edit for more - **/ - - // TODO: error if the selection is not within the Scribe instance? Or - // focus the Scribe instance if it is not already focused? - this.getCommand('insertHTML').execute(this._htmlFormatterFactory.format(html)); - }; - - Scribe.prototype.isDebugModeEnabled = function () { - return this.options.debug; - }; - - Scribe.prototype.registerHTMLFormatter = function (phase, fn) { - this._htmlFormatterFactory.formatters[phase].push(fn); - }; - - Scribe.prototype.registerPlainTextFormatter = function (fn) { - this._plainTextFormatterFactory.formatters.push(fn); - }; - - // TODO: abstract - function FormatterFactory() { - this.formatters = []; - } - - FormatterFactory.prototype.format = function (html) { - // Map the object to an array: Array[Formatter] - var formatted = this.formatters.reduce(function (formattedData, formatter) { - return formatter(formattedData); - }, html); - - return formatted; - }; - - function HTMLFormatterFactory() { - // Object[String,Array[Formatter]] - // Define phases - // For a list of formatters, see https://github.com/guardian/scribe/issues/126 - this.formatters = { - // Configurable sanitization of the HTML, e.g. converting/filter/removing - // elements - sanitize: [], - // Normalize content to ensure it is ready for interaction - normalize: [], - paste: [], - export: [] - }; - } - - HTMLFormatterFactory.prototype = Object.create(FormatterFactory.prototype); - HTMLFormatterFactory.prototype.constructor = HTMLFormatterFactory; - - HTMLFormatterFactory.prototype.format = function (html) { - // Flatten the phases - // Map the object to an array: Array[Formatter] - var formatters = flatten([this.formatters.sanitize, this.formatters.normalize]); - var formatted = formatters.reduce(function (formattedData, formatter) { - return formatter(formattedData); - }, html); - - return formatted; - }; - - HTMLFormatterFactory.prototype.formatPaste = function (html) { - return this.formatters.paste.reduce(function (formattedData, formatter) { - return formatter(formattedData); - }, html); - }; - - HTMLFormatterFactory.prototype.formatForExport = function (html) { - return this.formatters.export.reduce(function (formattedData, formatter) { - return formatter(formattedData); - }, html); - }; - - return Scribe; - -}); - -//# sourceMappingURL=scribe.js.map; -define('scribe-plugin-blockquote-command',[],function () { - - /** - * Adds a command for using BLOCKQUOTEs. - */ - - - - return function () { - return function (scribe) { - var blockquoteCommand = new scribe.api.SimpleCommand('blockquote', 'BLOCKQUOTE'); - - blockquoteCommand.execute = function () { - var command = scribe.getCommand(this.queryState() ? 'outdent' : 'indent'); - command.execute(); - }; - - blockquoteCommand.queryEnabled = function () { - var command = scribe.getCommand(this.queryState() ? 'outdent' : 'indent'); - return command.queryEnabled(); - }; - - blockquoteCommand.queryState = function () { - var selection = new scribe.api.Selection(); - var blockquoteElement = selection.getContaining(function (element) { - return element.nodeName === 'BLOCKQUOTE'; - }); - - return scribe.allowsBlockElements() && !! blockquoteElement; - }; - - scribe.commands.blockquote = blockquoteCommand; - - /** - * If the paragraphs option is set to true, we unapply the blockquote on - * keypresses if the caret is on a new line. - */ - if (scribe.allowsBlockElements()) { - scribe.el.addEventListener('keydown', function (event) { - if (event.keyCode === 13) { // enter - - var command = scribe.getCommand('blockquote'); - if (command.queryState()) { - var selection = new scribe.api.Selection(); - if (selection.isCaretOnNewLine()) { - event.preventDefault(); - command.execute(); - } - } - } - }); - } - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-blockquote-command.js.map; -define('scribe-plugin-curly-quotes',[],function () { - - - - return function () { - - var keys = { - 34: '"', - 39: '\'' - }; - - var openDoubleCurly = '“'; - var closeDoubleCurly = '”'; - - var openSingleCurly = '‘'; - var closeSingleCurly = '’'; - - var NON_BREAKING_SPACE = '\u00A0'; - - return function (scribe) { - // Substitute quotes while typing - scribe.el.addEventListener('keypress', input); - - // Substitute quotes on setting content or paste - scribe.registerHTMLFormatter('normalize', substituteCurlyQuotes); - - function input(event) { - var curlyChar; - - // If previous char is real content, close quote; else, open - // TODO: annoying Chrome/Firefox - var currentChar = keys[event.charCode]; - if (currentChar === '"') { - if (wordBeforeSelectedRange()) { - curlyChar = closeDoubleCurly; - } else { - curlyChar = openDoubleCurly; - } - } else if (currentChar === '\'') { - if (wordBeforeSelectedRange()) { - curlyChar = closeSingleCurly; - } else { - curlyChar = openSingleCurly; - } - } - - // Substitute entered char with curly replacement - if (curlyChar) { - event.preventDefault(); - - scribe.transactionManager.run(function() { - var quoteText = replaceSelectedRangeWith(curlyChar); - placeCaretAfter(quoteText); - }); - } - } - - function wordBeforeSelectedRange() { - var prevChar = charBeforeSelectedRange() || ''; - return isWordCharacter(prevChar); - } - - function charBeforeSelectedRange() { - var selection = new scribe.api.Selection(); - var context = selection.range.commonAncestorContainer.textContent; - return context[selection.range.startOffset - 1]; - } - - function charAfterSelectedRange() { - var selection = new scribe.api.Selection(); - var context = selection.range.commonAncestorContainer.textContent; - return context[selection.range.endOffset]; - } - - function isWordCharacter(character) { - return /[^\s()]/.test(character); - } - - /** Delete any selected text, insert text instead */ - function replaceSelectedRangeWith(text) { - var textNode = document.createTextNode(text); - - var selection = new scribe.api.Selection(); - selection.range.deleteContents(); - selection.range.insertNode(textNode); - - return textNode; - } - - function placeCaretAfter(node) { - var rangeAfter = document.createRange(); - rangeAfter.setStartAfter(node); - rangeAfter.setEndAfter(node); - - var selection = new scribe.api.Selection(); - selection.selection.removeAllRanges(); - selection.selection.addRange(rangeAfter); - } - - function substituteCurlyQuotes(html) { - // We don't want to replace quotes within the HTML markup - // (e.g. attributes), only to text nodes - var holder = document.createElement('div'); - holder.innerHTML = html; - - // Replace straight single and double quotes with curly - // equivalent in the given string - mapTextNodes(holder, function(str) { - // Tokenise HTML elements vs text between them - // Note: this is escaped HTML in the text node! - var tokens = str.split(/(<[^>]+?>)/); - return tokens.map(function(token) { - // Only replace quotes in text between (potential) HTML elements - if (token[0] === '<') { - return token; - } else { - return token. - // Use [\s\S] instead of . to match any characters _including newlines_ - replace(/([\s\S])?'([\s\S])?/g, - replaceQuotesFromContext(openSingleCurly, closeSingleCurly)). - replace(/([\s\S])?"([\s\S])?/g, - replaceQuotesFromContext(openDoubleCurly, closeDoubleCurly)); - } - }).join(''); - }); - - return holder.innerHTML; - } - - function replaceQuotesFromContext(openCurly, closeCurly) { - return function(m, prev, next) { - prev = prev || ''; - next = next || ''; - var isStart = ! prev; - var isEnd = ! next; - var hasCharsBefore = isWordCharacter(prev); - var hasCharsAfter = isWordCharacter(next); - // Optimistic heuristic, would need to look at DOM structure - // (esp block vs inline elements) for more robust inference - if (hasCharsBefore || (isStart && ! hasCharsAfter && ! isEnd)) { - return prev + closeCurly + next; - } else { - return prev + openCurly + next; - } - }; - } - - // Apply a function on all text nodes in a container, mutating in place - function mapTextNodes(container, func) { - var walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT); - var node = walker.firstChild(); - if (node) { - do { - node.data = func(node.data); - } while ((node = walker.nextSibling())); - } - - return node; - } - - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-curly-quotes.js.map; -define('scribe-plugin-formatter-plain-text-convert-new-lines-to-html',[],function () { - - - - return function () { - return function (scribe) { - scribe.registerPlainTextFormatter(function (html) { - return html.replace(/\n([ \t]*\n)+/g, '

').replace(/\n/g, '
'); - }); - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-formatter-plain-text-convert-new-lines-to-html.js.map; -define('scribe-plugin-heading-command',[],function () { - - /** - * This plugin adds a command for headings. - */ - - - - return function (level) { - return function (scribe) { - var tag = ''; - var nodeName = 'H' + level; - var commandName = 'h' + level; - - /** - * Chrome: the `heading` command doesn't work. Supported by Firefox only. - */ - - var headingCommand = new scribe.api.Command('formatBlock'); - - headingCommand.execute = function () { - if (this.queryState()) { - scribe.api.Command.prototype.execute.call(this, '

'); - } else { - scribe.api.Command.prototype.execute.call(this, tag); - } - }; - - headingCommand.queryState = function () { - var selection = new scribe.api.Selection(); - return !! selection.getContaining(function (node) { - return node.nodeName === nodeName; - }); - }; - - /** - * All: Executing a heading command inside a list element corrupts the markup. - * Disabling for now. - */ - headingCommand.queryEnabled = function () { - var selection = new scribe.api.Selection(); - var listNode = selection.getContaining(function (node) { - return node.nodeName === 'OL' || node.nodeName === 'UL'; - }); - - return scribe.api.Command.prototype.queryEnabled.apply(this, arguments) - && scribe.allowsBlockElements() && ! listNode; - }; - - scribe.commands[commandName] = headingCommand; - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-heading-command.js.map; -define('scribe-plugin-intelligent-unlink-command',[],function () { - - /** - * This plugin modifies the `unlink` command so that, when the user's - * selection is collapsed, remove the containing A. - */ - - - - return function () { - return function (scribe) { - var unlinkCommand = new scribe.api.Command('unlink'); - - unlinkCommand.execute = function () { - var selection = new scribe.api.Selection(); - - if (selection.selection.isCollapsed) { - scribe.transactionManager.run(function () { - /** - * If the selection is collapsed, we can remove the containing anchor. - */ - - var aNode = selection.getContaining(function (node) { - return node.nodeName === 'A'; - }); - - if (aNode) { - new scribe.api.Element(aNode.parentNode).unwrap(aNode); - } - }.bind(this)); - } else { - scribe.api.Command.prototype.execute.apply(this, arguments); - } - }; - - unlinkCommand.queryEnabled = function () { - var selection = new scribe.api.Selection(); - if (selection.selection.isCollapsed) { - return !! selection.getContaining(function (node) { - return node.nodeName === 'A'; - }); - } else { - return scribe.api.Command.prototype.queryEnabled.apply(this, arguments); - } - }; - - scribe.commands.unlink = unlinkCommand; - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-intelligent-unlink-command.js.map; -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/isNative',[], function() { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Used to detect if a method is native */ - var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString| for [^\]]+/g, '.*?') + '$' - ); - - /** - * Checks if `value` is a native function. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. - */ - function isNative(value) { - return typeof value == 'function' && reNative.test(value); - } - - return isNative; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/objectTypes',[], function() { - - /** Used to determine if values are of the language type Object */ - var objectTypes = { - 'boolean': false, - 'function': true, - 'object': true, - 'number': false, - 'string': false, - 'undefined': false - }; - - return objectTypes; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isObject',['../internals/objectTypes'], function(objectTypes) { - - /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(1); - * // => false - */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); - } - - return isObject; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/noop',[], function() { - - /** - * A no-operation function. - * - * @static - * @memberOf _ - * @category Utilities - * @example - * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true - */ - function noop() { - // no operation performed - } - - return noop; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreate',['./isNative', '../objects/isObject', '../utilities/noop'], function(isNative, isObject, noop) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate; - - /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. - */ - function baseCreate(prototype, properties) { - return isObject(prototype) ? nativeCreate(prototype) : {}; - } - // fallback for browsers without `Object.create` - if (!nativeCreate) { - baseCreate = (function() { - function Object() {} - return function(prototype) { - if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; - } - return result || window.Object(); - }; - }()); - } - - return baseCreate; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/setBindData',['./isNative', '../utilities/noop'], function(isNative, noop) { - - /** Used as the property descriptor for `__bindData__` */ - var descriptor = { - 'configurable': false, - 'enumerable': false, - 'value': null, - 'writable': false - }; - - /** Used to set meta data on functions */ - var defineProperty = (function() { - // IE 8 only accepts DOM elements - try { - var o = {}, - func = isNative(func = Object.defineProperty) && func, - result = func(o, o, o) && func; - } catch(e) { } - return result; - }()); - - /** - * Sets `this` binding data on a given function. - * - * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. - */ - var setBindData = !defineProperty ? noop : function(func, value) { - descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); - }; - - return setBindData; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/slice',[], function() { - - /** - * Slices the `collection` from the `start` index up to, but not including, - * the `end` index. - * - * Note: This function is used instead of `Array#slice` to support node lists - * in IE < 9 and to ensure dense arrays are returned. - * - * @private - * @param {Array|Object|string} collection The collection to slice. - * @param {number} start The start index. - * @param {number} end The end index. - * @returns {Array} Returns the new array. - */ - function slice(array, start, end) { - start || (start = 0); - if (typeof end == 'undefined') { - end = array ? array.length : 0; - } - var index = -1, - length = end - start || 0, - result = Array(length < 0 ? 0 : length); - - while (++index < length) { - result[index] = array[start + index]; - } - return result; - } - - return slice; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseBind',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new bound function. - */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; - - function bound() { - // `Function#bind` spec - // http://es5.github.io/#x15.3.4.5 - if (partialArgs) { - // avoid `arguments` object deoptimizations by using `slice` instead - // of `Array.prototype.slice.call` and not assigning `arguments` to a - // variable as a ternary expression - var args = slice(partialArgs); - push.apply(args, arguments); - } - // mimic the constructor's `return` behavior - // http://es5.github.io/#x13.2.2 - if (this instanceof bound) { - // ensure `new bound` is an instance of `func` - var thisBinding = baseCreate(func.prototype), - result = func.apply(thisBinding, args || arguments); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisArg, args || arguments); - } - setBindData(bound, bindData); - return bound; - } - - return baseBind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateWrapper',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; - - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - key = func; - - function bound() { - var thisBinding = isBind ? thisArg : this; - if (partialArgs) { - var args = slice(partialArgs); - push.apply(args, arguments); - } - if (partialRightArgs || isCurry) { - args || (args = slice(arguments)); - if (partialRightArgs) { - push.apply(args, partialRightArgs); - } - if (isCurry && args.length < arity) { - bitmask |= 16 & ~32; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]); - } - } - args || (args = arguments); - if (isBindKey) { - func = thisBinding[key]; - } - if (this instanceof bound) { - thisBinding = baseCreate(func.prototype); - var result = func.apply(thisBinding, args); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisBinding, args); - } - setBindData(bound, bindData); - return bound; - } - - return baseCreateWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isFunction',[], function() { - - /** - * Checks if `value` is a function. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - */ - function isFunction(value) { - return typeof value == 'function'; - } - - return isFunction; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/createWrapper',['./baseBind', './baseCreateWrapper', '../objects/isFunction', './slice'], function(baseBind, baseCreateWrapper, isFunction, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push, - unshift = arrayRef.unshift; - - /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. - * - * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of method flags to compose. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) - * 16 - `_.partial` - * 32 - `_.partialRight` - * @param {Array} [partialArgs] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [partialRightArgs] An array of arguments to append to those - * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new function. - */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - isPartial = bitmask & 16, - isPartialRight = bitmask & 32; - - if (!isBindKey && !isFunction(func)) { - throw new TypeError; - } - if (isPartial && !partialArgs.length) { - bitmask &= ~16; - isPartial = partialArgs = false; - } - if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; - isPartialRight = partialRightArgs = false; - } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); - } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); - } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & 1)) { - bindData[4] = thisArg; - } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & 1) { - bitmask |= 8; - } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & 4)) { - bindData[5] = arity; - } - // append partial left arguments - if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); - } - // append partial right arguments - if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); - } - // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); - } - // fast path for `_.bind` - var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); - } - - return createWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/functions/bind',['../internals/createWrapper', '../internals/slice'], function(createWrapper, slice) { - - /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. - * - * @static - * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; - * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' - */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); - } - - return bind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/identity',[], function() { - - /** - * This method returns the first argument provided to it. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; - * // => true - */ - function identity(value) { - return value; - } - - return identity; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/support',['./internals/isNative'], function(isNative) { - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** - * An object used to flag environments features. - * - * @static - * @memberOf _ - * @type Object - */ - var support = {}; - - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = !isNative(window.WinRTError) && reThis.test(function() { return this; }); - - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; - - return support; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateCallback',['../functions/bind', '../utilities/identity', './setBindData', '../support'], function(bind, identity, setBindData, support) { - - /** Used to detected named functions */ - var reFuncName = /^\s*function[ \n\r\t]+\w/; - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** Native method shortcuts */ - var fnToString = Function.prototype.toString; - - /** - * The base implementation of `_.createCallback` without support for creating - * "_.pluck" or "_.where" style callbacks. - * - * @private - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - */ - function baseCreateCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; - } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { - return func; - } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { - if (support.funcNames) { - bindData = !func.name; - } - bindData = bindData || !support.funcDecomp; - if (!bindData) { - var source = fnToString.call(func); - if (!support.funcNames) { - bindData = !reFuncName.test(source); - } - if (!bindData) { - // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); - } - } - } - // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & 1)) { - return func; - } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; - } - return bind(func, thisArg); - } - - return baseCreateCallback; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forIn',['../internals/baseCreateCallback', '../internals/objectTypes'], function(baseCreateCallback, objectTypes) { - - /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; - * - * _.forIn(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) - */ - var forIn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - for (index in iterable) { - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forIn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/arrayPool',[], function() { - - /** Used to pool arrays and objects used internally */ - var arrayPool = []; - - return arrayPool; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/getArray',['./arrayPool'], function(arrayPool) { - - /** - * Gets an array from the array pool or creates a new one if the pool is empty. - * - * @private - * @returns {Array} The array from the pool. - */ - function getArray() { - return arrayPool.pop() || []; - } - - return getArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/maxPoolSize',[], function() { - - /** Used as the max size of the `arrayPool` and `objectPool` */ - var maxPoolSize = 40; - - return maxPoolSize; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/releaseArray',['./arrayPool', './maxPoolSize'], function(arrayPool, maxPoolSize) { - - /** - * Releases the given array back to the array pool. - * - * @private - * @param {Array} [array] The array to release. - */ - function releaseArray(array) { - array.length = 0; - if (arrayPool.length < maxPoolSize) { - arrayPool.push(array); - } - } - - return releaseArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseIsEqual',['../objects/forIn', './getArray', '../objects/isFunction', './objectTypes', './releaseArray'], function(forIn, getArray, isFunction, objectTypes, releaseArray) { - - /** `Object#toString` result shortcuts */ - var argsClass = '[object Arguments]', - arrayClass = '[object Array]', - boolClass = '[object Boolean]', - dateClass = '[object Date]', - numberClass = '[object Number]', - objectClass = '[object Object]', - regexpClass = '[object RegExp]', - stringClass = '[object String]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * The base implementation of `_.isEqual`, without support for `thisArg` binding, - * that allows partial "_.where" style comparisons. - * - * @private - * @param {*} a The value to compare. - * @param {*} b The other value to compare. - * @param {Function} [callback] The function to customize comparing values. - * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons. - * @param {Array} [stackA=[]] Tracks traversed `a` objects. - * @param {Array} [stackB=[]] Tracks traversed `b` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - */ - function baseIsEqual(a, b, callback, isWhere, stackA, stackB) { - // used to indicate that when comparing objects, `a` has at least the properties of `b` - if (callback) { - var result = callback(a, b); - if (typeof result != 'undefined') { - return !!result; - } - } - // exit early for identical values - if (a === b) { - // treat `+0` vs. `-0` as not equal - return a !== 0 || (1 / a == 1 / b); - } - var type = typeof a, - otherType = typeof b; - - // exit early for unlike primitive values - if (a === a && - !(a && objectTypes[type]) && - !(b && objectTypes[otherType])) { - return false; - } - // exit early for `null` and `undefined` avoiding ES3's Function#call behavior - // http://es5.github.io/#x15.3.4.4 - if (a == null || b == null) { - return a === b; - } - // compare [[Class]] names - var className = toString.call(a), - otherClass = toString.call(b); - - if (className == argsClass) { - className = objectClass; - } - if (otherClass == argsClass) { - otherClass = objectClass; - } - if (className != otherClass) { - return false; - } - switch (className) { - case boolClass: - case dateClass: - // coerce dates and booleans to numbers, dates to milliseconds and booleans - // to `1` or `0` treating invalid dates coerced to `NaN` as not equal - return +a == +b; - - case numberClass: - // treat `NaN` vs. `NaN` as equal - return (a != +a) - ? b != +b - // but treat `+0` vs. `-0` as not equal - : (a == 0 ? (1 / a == 1 / b) : a == +b); - - case regexpClass: - case stringClass: - // coerce regexes to strings (http://es5.github.io/#x15.10.6.4) - // treat string primitives and their corresponding object instances as equal - return a == String(b); - } - var isArr = className == arrayClass; - if (!isArr) { - // unwrap any `lodash` wrapped values - var aWrapped = hasOwnProperty.call(a, '__wrapped__'), - bWrapped = hasOwnProperty.call(b, '__wrapped__'); - - if (aWrapped || bWrapped) { - return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB); - } - // exit for functions and DOM nodes - if (className != objectClass) { - return false; - } - // in older versions of Opera, `arguments` objects have `Array` constructors - var ctorA = a.constructor, - ctorB = b.constructor; - - // non `Object` object instances with different constructors are not equal - if (ctorA != ctorB && - !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) && - ('constructor' in a && 'constructor' in b) - ) { - return false; - } - } - // assume cyclic structures are equal - // the algorithm for detecting cyclic structures is adapted from ES 5.1 - // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3) - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); - - var length = stackA.length; - while (length--) { - if (stackA[length] == a) { - return stackB[length] == b; - } - } - var size = 0; - result = true; - - // add `a` and `b` to the stack of traversed objects - stackA.push(a); - stackB.push(b); - - // recursively compare objects and arrays (susceptible to call stack limits) - if (isArr) { - // compare lengths to determine if a deep comparison is necessary - length = a.length; - size = b.length; - result = size == length; - - if (result || isWhere) { - // deep compare the contents, ignoring non-numeric properties - while (size--) { - var index = length, - value = b[size]; - - if (isWhere) { - while (index--) { - if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) { - break; - } - } - } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) { - break; - } - } - } - } - else { - // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` - // which, in this case, is more costly - forIn(b, function(value, key, b) { - if (hasOwnProperty.call(b, key)) { - // count the number of properties. - size++; - // deep compare each property value. - return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB)); - } - }); - - if (result && !isWhere) { - // ensure both objects have the same number of properties - forIn(a, function(value, key, a) { - if (hasOwnProperty.call(a, key)) { - // `size` will be `-1` if `a` has more properties than `b` - return (result = --size > -1); - } - }); - } - } - stackA.pop(); - stackB.pop(); - - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); - } - return result; - } - - return baseIsEqual; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/shimKeys',['./objectTypes'], function(objectTypes) { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. - * - * @private - * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - */ - var shimKeys = function(object) { - var index, iterable = object, result = []; - if (!iterable) return result; - if (!(objectTypes[typeof object])) return result; - for (index in iterable) { - if (hasOwnProperty.call(iterable, index)) { - result.push(index); - } - } - return result - }; - - return shimKeys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/keys',['../internals/isNative', './isObject', '../internals/shimKeys'], function(isNative, isObject, shimKeys) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys; - - /** - * Creates an array composed of the own enumerable property names of an object. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - * @example - * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) - */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; - } - return nativeKeys(object); - }; - - return keys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/property',[], function() { - - /** - * Creates a "_.pluck" style function, which returns the `key` value of a - * given object. - * - * @static - * @memberOf _ - * @category Utilities - * @param {string} key The name of the property to retrieve. - * @returns {Function} Returns the new function. - * @example - * - * var characters = [ - * { 'name': 'fred', 'age': 40 }, - * { 'name': 'barney', 'age': 36 } - * ]; - * - * var getName = _.property('name'); - * - * _.map(characters, getName); - * // => ['barney', 'fred'] - * - * _.sortBy(characters, getName); - * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] - */ - function property(key) { - return function(object) { - return object[key]; - }; - } - - return property; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/functions/createCallback',['../internals/baseCreateCallback', '../internals/baseIsEqual', '../objects/isObject', '../objects/keys', '../utilities/property'], function(baseCreateCallback, baseIsEqual, isObject, keys, property) { - - /** - * Produces a callback bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - * @example - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; - * - * // wrap to create custom callback shorthands - * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { - * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); - * return !match ? func(callback, thisArg) : function(object) { - * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; - * }; - * }); - * - * _.filter(characters, 'age__gt38'); - * // => [{ 'name': 'fred', 'age': 40 }] - */ - function createCallback(func, thisArg, argCount) { - var type = typeof func; - if (func == null || type == 'function') { - return baseCreateCallback(func, thisArg, argCount); - } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; - - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; - - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; - } - } - return result; - }; - } - - return createCallback; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forOwn',['../internals/baseCreateCallback', './keys', '../internals/objectTypes'], function(baseCreateCallback, keys, objectTypes) { - - /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) - */ - var forOwn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forOwn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/findKey',['../functions/createCallback', './forOwn'], function(createCallback, forOwn) { - - /** - * This method is like `_.findIndex` except that it returns the key of the - * first element that passes the callback check, instead of the element itself. - * - * If a property name is provided for `callback` the created "_.pluck" style - * callback will return the property value of the given element. - * - * If an object is provided for `callback` the created "_.where" style callback - * will return `true` for elements that have the properties of the given object, - * else `false`. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to search. - * @param {Function|Object|string} [callback=identity] The function called per - * iteration. If a property name or object is provided it will be used to - * create a "_.pluck" or "_.where" style callback, respectively. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {string|undefined} Returns the key of the found element, else `undefined`. - * @example - * - * var characters = { - * 'barney': { 'age': 36, 'blocked': false }, - * 'fred': { 'age': 40, 'blocked': true }, - * 'pebbles': { 'age': 1, 'blocked': false } - * }; - * - * _.findKey(characters, function(chr) { - * return chr.age < 40; - * }); - * // => 'barney' (property order is not guaranteed across environments) - * - * // using "_.where" callback shorthand - * _.findKey(characters, { 'age': 1 }); - * // => 'pebbles' - * - * // using "_.pluck" callback shorthand - * _.findKey(characters, 'blocked'); - * // => 'fred' - */ - function findKey(object, callback, thisArg) { - var result; - callback = createCallback(callback, thisArg, 3); - forOwn(object, function(value, key, object) { - if (callback(value, key, object)) { - result = key; - return false; - } - }); - return result; - } - - return findKey; -}); - -define('scribe-plugin-keyboard-shortcuts',[ - 'lodash-amd/modern/objects/findKey' -], function ( - findKey -) { - - - - return function (commandsToKeyboardShortcutsMap) { - return function (scribe) { - scribe.el.addEventListener('keydown', function (event) { - var commandName = findKey(commandsToKeyboardShortcutsMap, function (isKeyboardShortcut) { - return isKeyboardShortcut(event); - }); - - if (commandName) { - // FIXME: should command return undefined if one is - // not found. - - var command = scribe.getCommand(commandName); - event.preventDefault(); - - if (command.queryEnabled()) { - command.execute(); - } - } - }); - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-keyboard-shortcuts.js.map; -/* A friendly UI for adding links. */ - -define('scribe-plugin-link-ui',[],function () { - - /** - * This plugin adds a command for creating links, including a basic prompt. - */ - return function (config) { - return function (scribe) { - - var editorEl = scribe.el.parentNode, - linkPromptCommand = new scribe.api.Command('createLink'); - var $linkTools = $('.link-tools', editorEl), - $input = $('.link-tools input', editorEl), - placeHolder = '#replaceme'; - var $results = $('.search-results', $linkTools); - - // this provides a way to externally udpate the results element. - var searchHandler = config.searchHandler || function(term, resultsElement) { }; - - linkPromptCommand.nodeName = 'A'; - - linkPromptCommand.execute = function () { - var cmd = this, - selection = new scribe.api.Selection(); - if (!selection.range.collapsed) { - scribe._skipFormatters = true; // This is a little fucked... - scribe.api.SimpleCommand.prototype.execute.call(cmd, placeHolder); - showInput($('a[href*=' + placeHolder + ']')); - } - }; - - $('.remove', $linkTools).click(function() { - $input.val(''); - confirmInput(); - }); - - $('.ok', $linkTools).click(confirmInput); - - $results.click(function(e) { - var linkElement = $(e.target).closest('a'); - if (linkElement.length === 1) { - e.preventDefault(); - $input.val(linkElement.attr("href")); - updateResults(); - } - }); - - - $input - .bind('keyup', updateResults) - .bind('keydown', function(e) { - if (e.keyCode === 13 || e.keyCode === 27) { - confirmInput(); - } - }); - - scribe.el.addEventListener('click', function(e) { - // is there a link - var selection = new scribe.api.Selection(); - var linkElement = $(e.target).closest('a'); - if (linkElement.length === 1) { - showInput(linkElement); - e.preventDefault(); - } - }) - - - var searchTimeout; - function updateResults() { - var v = $input.val(); - if (isSearchTerm(v)) { - clearTimeout(searchTimeout); - searchTimeout = setTimeout(searchHandler, 200, v, $results); - $results.show(); - } - else { - $results.hide(); - } - } - - // cheap way to see if we're searching for something, or entering a url - function isSearchTerm(s) { - if (s.indexOf(".") > -1 || s.indexOf("/") > -1 || - s.indexOf("www") > -1 || s.indexOf("http://") > -1 || - s.indexOf("https://") > -1 || s === "") { - return false; - } - else { - return true; - } - } - - function showInput(linkElement) { - updateResults(); - $linkTools.show(); - linkElement.addClass('link-edit'); - setTimeout(function() { - $("body, .link-tools .close").bind('click', closeByClick); - $input.val(linkElement.attr('href').replace(placeHolder, "")) - $input[0].focus(); - }, 10) - } - - function closeByClick(e) { - if ($(e.target).closest(".link-tools").length === 0) { - confirmInput(); - } - } - - function confirmInput() { - scribe.updateContents(function() { - var linkVal = $input.val(); - if (linkVal === "") { - removeLink(); - } - else { - $('.link-edit, [href=' + placeHolder + ']') - .attr('href', linkVal) - .removeClass('link-edit'); - } - }, false); - $('body, .link-tools .close').unbind('click'); - $linkTools.hide(); - } - - function removeLink() { - var link = $('.link-edit, [href*=' + placeHolder + ']'); - link[0].outerHTML = link[0].innerHTML; - } - - linkPromptCommand.queryState = function () { - /** - * We override the native `document.queryCommandState` for links because - * the `createLink` and `unlink` commands are not supported. - * As per: http://jsbin.com/OCiJUZO/1/edit?js,console,output - */ - var selection = new scribe.api.Selection(); - return !! selection.getContaining(function (node) { - return node.nodeName === this.nodeName; - }.bind(this)); - }; - - scribe.commands.linkUI = linkPromptCommand; - }; - }; -}); -/* - - This is lifted from - -*/ - -// UMD -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - define('html-janitor',factory); - } else { - root.amdWeb = factory(); - } -}(this, function () { - - function HTMLJanitor(config) { - this.config = config; - } - - // TODO: not exhaustive? - var blockElementNames = ['P', 'LI', 'DIV']; - function isBlockElement(node) { - return blockElementNames.indexOf(node.nodeName) !== -1; - } - - var inlineElementNames = ['A', 'B', 'DEL', 'I', 'U']; - function nodeIsInlineElement(node) { - return inlineElementNames.indexOf(node.nodeName) !== -1; - } - - HTMLJanitor.prototype.clean = function (html) { - var sandbox = document.createElement('div'); - sandbox.innerHTML = html; - - this._sanitize(sandbox); - - return sandbox.innerHTML; - }; - - HTMLJanitor.prototype._sanitize = function (parentNode) { - var treeWalker = createTreeWalker(parentNode); - var node = treeWalker.firstChild(); - if (!node) { return; } - - do { - var nodeName = node.nodeName.toLowerCase(); - var allowedAttrs = this.config.tags[nodeName]; - - // Ignore nodes that have already been sanitized - if (node._sanitized) { - continue; - } - - - // Do not sanitize blocks that match - if (this.config.skipSanitization(node)) { - return; - } - - - - if (node.nodeType === Node.TEXT_NODE) { - // If this text node is just whitespace and the previous or next element - // sibling is a block element, remove it - // N.B.: This heuristic could change. Very specific to a bug with - // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output - // FIXME: make this an option? - if (node.data.trim() === '' - && ((node.previousElementSibling && isBlockElement(node.previousElementSibling)) - || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) { - parentNode.removeChild(node); - this._sanitize(parentNode); - break; - } else { - continue; - } - } - - // Remove all comments - if (node.nodeType === Node.COMMENT_NODE) { - parentNode.removeChild(node); - this._sanitize(parentNode); - break; - } - - var isInlineElement = nodeIsInlineElement(node); - var containsBlockElement; - if (isInlineElement) { - containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement); - } - - var isInvalid = isInlineElement && containsBlockElement; - - // Block elements should not be nested (e.g.

  • ...); if - // they are, we want to unwrap the inner block element. - var isNotTopContainer = !! parentNode.parentNode; - // TODO: Don't hardcore this — this is not invalid markup. Should be - // configurable. - var isNestedBlockElement = - isBlockElement(parentNode) && - isBlockElement(node) && - isNotTopContainer; - - // Drop tag entirely according to the whitelist *and* if the markup - // is invalid. - if (!this.config.tags[nodeName] || isInvalid || isNestedBlockElement) { - // Do not keep the inner text of SCRIPT/STYLE elements. - if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) { - while (node.childNodes.length > 0) { - parentNode.insertBefore(node.childNodes[0], node); - } - } - parentNode.removeChild(node); - - this._sanitize(parentNode); - break; - } - - // Sanitize attributes - for (var a = 0; a < node.attributes.length; a += 1) { - var attr = node.attributes[a]; - var attrName = attr.name.toLowerCase(); - - // Allow attribute? - var allowedAttrValue = allowedAttrs[attrName]; - var notInAttrList = ! allowedAttrValue; - var valueNotAllowed = allowedAttrValue !== true && attr.value !== allowedAttrValue; - if (notInAttrList || valueNotAllowed) { - node.removeAttribute(attr.name); - // Shift the array to continue looping. - a = a - 1; - } - } - - // Sanitize children - this._sanitize(node); - - // Mark node as sanitized so it's ignored in future runs - node._sanitized = true; - } while ((node = treeWalker.nextSibling())); - }; - - function createTreeWalker(node) { - return document.createTreeWalker(node, - NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT); - } - - return HTMLJanitor; - -})); -//# sourceMappingURL=html-janitor.js.map; -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/isNative',[], function() { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Used to detect if a method is native */ - var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString| for [^\]]+/g, '.*?') + '$' - ); - - /** - * Checks if `value` is a native function. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. - */ - function isNative(value) { - return typeof value == 'function' && reNative.test(value); - } - - return isNative; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/objectTypes',[], function() { - - /** Used to determine if values are of the language type Object */ - var objectTypes = { - 'boolean': false, - 'function': true, - 'object': true, - 'number': false, - 'string': false, - 'undefined': false - }; - - return objectTypes; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isObject',['../internals/objectTypes'], function(objectTypes) { - - /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(1); - * // => false - */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); - } - - return isObject; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/noop',[], function() { - - /** - * A no-operation function. - * - * @static - * @memberOf _ - * @category Utilities - * @example - * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true - */ - function noop() { - // no operation performed - } - - return noop; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreate',['./isNative', '../objects/isObject', '../utilities/noop'], function(isNative, isObject, noop) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate; - - /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. - */ - function baseCreate(prototype, properties) { - return isObject(prototype) ? nativeCreate(prototype) : {}; - } - // fallback for browsers without `Object.create` - if (!nativeCreate) { - baseCreate = (function() { - function Object() {} - return function(prototype) { - if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; - } - return result || window.Object(); - }; - }()); - } - - return baseCreate; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/setBindData',['./isNative', '../utilities/noop'], function(isNative, noop) { - - /** Used as the property descriptor for `__bindData__` */ - var descriptor = { - 'configurable': false, - 'enumerable': false, - 'value': null, - 'writable': false - }; - - /** Used to set meta data on functions */ - var defineProperty = (function() { - // IE 8 only accepts DOM elements - try { - var o = {}, - func = isNative(func = Object.defineProperty) && func, - result = func(o, o, o) && func; - } catch(e) { } - return result; - }()); - - /** - * Sets `this` binding data on a given function. - * - * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. - */ - var setBindData = !defineProperty ? noop : function(func, value) { - descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); - }; - - return setBindData; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/slice',[], function() { - - /** - * Slices the `collection` from the `start` index up to, but not including, - * the `end` index. - * - * Note: This function is used instead of `Array#slice` to support node lists - * in IE < 9 and to ensure dense arrays are returned. - * - * @private - * @param {Array|Object|string} collection The collection to slice. - * @param {number} start The start index. - * @param {number} end The end index. - * @returns {Array} Returns the new array. - */ - function slice(array, start, end) { - start || (start = 0); - if (typeof end == 'undefined') { - end = array ? array.length : 0; - } - var index = -1, - length = end - start || 0, - result = Array(length < 0 ? 0 : length); - - while (++index < length) { - result[index] = array[start + index]; - } - return result; - } - - return slice; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseBind',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new bound function. - */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; - - function bound() { - // `Function#bind` spec - // http://es5.github.io/#x15.3.4.5 - if (partialArgs) { - // avoid `arguments` object deoptimizations by using `slice` instead - // of `Array.prototype.slice.call` and not assigning `arguments` to a - // variable as a ternary expression - var args = slice(partialArgs); - push.apply(args, arguments); - } - // mimic the constructor's `return` behavior - // http://es5.github.io/#x13.2.2 - if (this instanceof bound) { - // ensure `new bound` is an instance of `func` - var thisBinding = baseCreate(func.prototype), - result = func.apply(thisBinding, args || arguments); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisArg, args || arguments); - } - setBindData(bound, bindData); - return bound; - } - - return baseBind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateWrapper',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; - - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - key = func; - - function bound() { - var thisBinding = isBind ? thisArg : this; - if (partialArgs) { - var args = slice(partialArgs); - push.apply(args, arguments); - } - if (partialRightArgs || isCurry) { - args || (args = slice(arguments)); - if (partialRightArgs) { - push.apply(args, partialRightArgs); - } - if (isCurry && args.length < arity) { - bitmask |= 16 & ~32; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]); - } - } - args || (args = arguments); - if (isBindKey) { - func = thisBinding[key]; - } - if (this instanceof bound) { - thisBinding = baseCreate(func.prototype); - var result = func.apply(thisBinding, args); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisBinding, args); - } - setBindData(bound, bindData); - return bound; - } - - return baseCreateWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isFunction',[], function() { - - /** - * Checks if `value` is a function. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - */ - function isFunction(value) { - return typeof value == 'function'; - } - - return isFunction; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/createWrapper',['./baseBind', './baseCreateWrapper', '../objects/isFunction', './slice'], function(baseBind, baseCreateWrapper, isFunction, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push, - unshift = arrayRef.unshift; - - /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. - * - * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of method flags to compose. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) - * 16 - `_.partial` - * 32 - `_.partialRight` - * @param {Array} [partialArgs] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [partialRightArgs] An array of arguments to append to those - * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new function. - */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - isPartial = bitmask & 16, - isPartialRight = bitmask & 32; - - if (!isBindKey && !isFunction(func)) { - throw new TypeError; - } - if (isPartial && !partialArgs.length) { - bitmask &= ~16; - isPartial = partialArgs = false; - } - if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; - isPartialRight = partialRightArgs = false; - } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); - } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); - } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & 1)) { - bindData[4] = thisArg; - } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & 1) { - bitmask |= 8; - } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & 4)) { - bindData[5] = arity; - } - // append partial left arguments - if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); - } - // append partial right arguments - if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); - } - // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); - } - // fast path for `_.bind` - var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); - } - - return createWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/functions/bind',['../internals/createWrapper', '../internals/slice'], function(createWrapper, slice) { - - /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. - * - * @static - * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; - * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' - */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); - } - - return bind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/identity',[], function() { - - /** - * This method returns the first argument provided to it. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; - * // => true - */ - function identity(value) { - return value; - } - - return identity; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/support',['./internals/isNative'], function(isNative) { - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** - * An object used to flag environments features. - * - * @static - * @memberOf _ - * @type Object - */ - var support = {}; - - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = !isNative(window.WinRTError) && reThis.test(function() { return this; }); - - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; - - return support; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateCallback',['../functions/bind', '../utilities/identity', './setBindData', '../support'], function(bind, identity, setBindData, support) { - - /** Used to detected named functions */ - var reFuncName = /^\s*function[ \n\r\t]+\w/; - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** Native method shortcuts */ - var fnToString = Function.prototype.toString; - - /** - * The base implementation of `_.createCallback` without support for creating - * "_.pluck" or "_.where" style callbacks. - * - * @private - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - */ - function baseCreateCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; - } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { - return func; - } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { - if (support.funcNames) { - bindData = !func.name; - } - bindData = bindData || !support.funcDecomp; - if (!bindData) { - var source = fnToString.call(func); - if (!support.funcNames) { - bindData = !reFuncName.test(source); - } - if (!bindData) { - // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); - } - } - } - // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & 1)) { - return func; - } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; - } - return bind(func, thisArg); - } - - return baseCreateCallback; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/shimKeys',['./objectTypes'], function(objectTypes) { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. - * - * @private - * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - */ - var shimKeys = function(object) { - var index, iterable = object, result = []; - if (!iterable) return result; - if (!(objectTypes[typeof object])) return result; - for (index in iterable) { - if (hasOwnProperty.call(iterable, index)) { - result.push(index); - } - } - return result - }; - - return shimKeys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/keys',['../internals/isNative', './isObject', '../internals/shimKeys'], function(isNative, isObject, shimKeys) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys; - - /** - * Creates an array composed of the own enumerable property names of an object. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - * @example - * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) - */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; - } - return nativeKeys(object); - }; - - return keys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forOwn',['../internals/baseCreateCallback', './keys', '../internals/objectTypes'], function(baseCreateCallback, keys, objectTypes) { - - /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) - */ - var forOwn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forOwn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/collections/forEach',['../internals/baseCreateCallback', '../objects/forOwn'], function(baseCreateCallback, forOwn) { - - /** - * Iterates over elements of a collection, executing the callback for each - * element. The callback is bound to `thisArg` and invoked with three arguments; - * (value, index|key, collection). Callbacks may exit iteration early by - * explicitly returning `false`. - * - * Note: As with other "Collections" methods, objects with a `length` property - * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` - * may be used for object iteration. - * - * @static - * @memberOf _ - * @alias each - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Array|Object|string} Returns `collection`. - * @example - * - * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(','); - * // => logs each number and returns '1,2,3' - * - * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); }); - * // => logs each number and returns the object (property order is not guaranteed across environments) - */ - function forEach(collection, callback, thisArg) { - var index = -1, - length = collection ? collection.length : 0; - - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - if (typeof length == 'number') { - while (++index < length) { - if (callback(collection[index], index, collection) === false) { - break; - } - } - } else { - forOwn(collection, callback); - } - return collection; - } - - return forEach; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isArray',['../internals/isNative'], function(isNative) { - - /** `Object#toString` result shortcuts */ - var arrayClass = '[object Array]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray; - - /** - * Checks if `value` is an array. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. - * @example - * - * (function() { return _.isArray(arguments); })(); - * // => false - * - * _.isArray([1, 2, 3]); - * // => true - */ - var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; - }; - - return isArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forIn',['../internals/baseCreateCallback', '../internals/objectTypes'], function(baseCreateCallback, objectTypes) { - - /** - * Iterates over own and inherited enumerable properties of an object, - * executing the callback for each property. The callback is bound to `thisArg` - * and invoked with three arguments; (value, key, object). Callbacks may exit - * iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * Shape.prototype.move = function(x, y) { - * this.x += x; - * this.y += y; - * }; - * - * _.forIn(new Shape, function(value, key) { - * console.log(key); - * }); - * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments) - */ - var forIn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - for (index in iterable) { - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forIn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/shimIsPlainObject',['../objects/forIn', '../objects/isFunction'], function(forIn, isFunction) { - - /** `Object#toString` result shortcuts */ - var objectClass = '[object Object]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * A fallback implementation of `isPlainObject` which checks if a given value - * is an object created by the `Object` constructor, assuming objects created - * by the `Object` constructor have no inherited enumerable properties and that - * there are no `Object.prototype` extensions. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - */ - function shimIsPlainObject(value) { - var ctor, - result; - - // avoid non Object objects, `arguments` objects, and DOM elements - if (!(value && toString.call(value) == objectClass) || - (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) { - return false; - } - // In most environments an object's own properties are iterated before - // its inherited properties. If the last iterated property is an object's - // own property then there are no inherited enumerable properties. - forIn(value, function(value, key) { - result = key; - }); - return typeof result == 'undefined' || hasOwnProperty.call(value, result); - } - - return shimIsPlainObject; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isPlainObject',['../internals/isNative', '../internals/shimIsPlainObject'], function(isNative, shimIsPlainObject) { - - /** `Object#toString` result shortcuts */ - var objectClass = '[object Object]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Native method shortcuts */ - var getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf; - - /** - * Checks if `value` is an object created by the `Object` constructor. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * _.isPlainObject(new Shape); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true - */ - var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { - if (!(value && toString.call(value) == objectClass)) { - return false; - } - var valueOf = value.valueOf, - objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); - - return objProto - ? (value == objProto || getPrototypeOf(value) == objProto) - : shimIsPlainObject(value); - }; - - return isPlainObject; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseMerge',['../collections/forEach', '../objects/forOwn', '../objects/isArray', '../objects/isPlainObject'], function(forEach, forOwn, isArray, isPlainObject) { - - /** - * The base implementation of `_.merge` without argument juggling or support - * for `thisArg` binding. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {Function} [callback] The function to customize merging properties. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates values with source counterparts. - */ - function baseMerge(object, source, callback, stackA, stackB) { - (isArray(source) ? forEach : forOwn)(source, function(source, key) { - var found, - isArr, - result = source, - value = object[key]; - - if (source && ((isArr = isArray(source)) || isPlainObject(source))) { - // avoid merging previously merged cyclic sources - var stackLength = stackA.length; - while (stackLength--) { - if ((found = stackA[stackLength] == source)) { - value = stackB[stackLength]; - break; - } - } - if (!found) { - var isShallow; - if (callback) { - result = callback(value, source); - if ((isShallow = typeof result != 'undefined')) { - value = result; - } - } - if (!isShallow) { - value = isArr - ? (isArray(value) ? value : []) - : (isPlainObject(value) ? value : {}); - } - // add `source` and associated `value` to the stack of traversed objects - stackA.push(source); - stackB.push(value); - - // recursively merge objects and arrays (susceptible to call stack limits) - if (!isShallow) { - baseMerge(value, source, callback, stackA, stackB); - } - } - } - else { - if (callback) { - result = callback(value, source); - if (typeof result == 'undefined') { - result = source; - } - } - if (typeof result != 'undefined') { - value = result; - } - } - object[key] = value; - }); - } - - return baseMerge; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/arrayPool',[], function() { - - /** Used to pool arrays and objects used internally */ - var arrayPool = []; - - return arrayPool; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/getArray',['./arrayPool'], function(arrayPool) { - - /** - * Gets an array from the array pool or creates a new one if the pool is empty. - * - * @private - * @returns {Array} The array from the pool. - */ - function getArray() { - return arrayPool.pop() || []; - } - - return getArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/maxPoolSize',[], function() { - - /** Used as the max size of the `arrayPool` and `objectPool` */ - var maxPoolSize = 40; - - return maxPoolSize; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/releaseArray',['./arrayPool', './maxPoolSize'], function(arrayPool, maxPoolSize) { - - /** - * Releases the given array back to the array pool. - * - * @private - * @param {Array} [array] The array to release. - */ - function releaseArray(array) { - array.length = 0; - if (arrayPool.length < maxPoolSize) { - arrayPool.push(array); - } - } - - return releaseArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/merge',['../internals/baseCreateCallback', '../internals/baseMerge', '../internals/getArray', './isObject', '../internals/releaseArray', '../internals/slice'], function(baseCreateCallback, baseMerge, getArray, isObject, releaseArray, slice) { - - /** - * Recursively merges own enumerable properties of the source object(s), that - * don't resolve to `undefined` into the destination object. Subsequent sources - * will overwrite property assignments of previous sources. If a callback is - * provided it will be executed to produce the merged values of the destination - * and source properties. If the callback returns `undefined` merging will - * be handled by the method instead. The callback is bound to `thisArg` and - * invoked with two arguments; (objectValue, sourceValue). - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize merging properties. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. - * @example - * - * var names = { - * 'characters': [ - * { 'name': 'barney' }, - * { 'name': 'fred' } - * ] - * }; - * - * var ages = { - * 'characters': [ - * { 'age': 36 }, - * { 'age': 40 } - * ] - * }; - * - * _.merge(names, ages); - * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } - * - * var food = { - * 'fruits': ['apple'], - * 'vegetables': ['beet'] - * }; - * - * var otherFood = { - * 'fruits': ['banana'], - * 'vegetables': ['carrot'] - * }; - * - * _.merge(food, otherFood, function(a, b) { - * return _.isArray(a) ? a.concat(b) : undefined; - * }); - * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } - */ - function merge(object) { - var args = arguments, - length = 2; - - if (!isObject(object)) { - return object; - } - // allows working with `_.reduce` and `_.reduceRight` without using - // their `index` and `collection` arguments - if (typeof args[2] != 'number') { - length = args.length; - } - if (length > 3 && typeof args[length - 2] == 'function') { - var callback = baseCreateCallback(args[--length - 1], args[length--], 2); - } else if (length > 2 && typeof args[length - 1] == 'function') { - callback = args[--length]; - } - var sources = slice(arguments, 1, length), - index = -1, - stackA = getArray(), - stackB = getArray(); - - while (++index < length) { - baseMerge(object, sources[index], callback, stackA, stackB); - } - releaseArray(stackA); - releaseArray(stackB); - return object; - } - - return merge; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/assign',['../internals/baseCreateCallback', './keys', '../internals/objectTypes'], function(baseCreateCallback, keys, objectTypes) { - - /** - * Assigns own enumerable properties of source object(s) to the destination - * object. Subsequent sources will overwrite property assignments of previous - * sources. If a callback is provided it will be executed to produce the - * assigned values. The callback is bound to `thisArg` and invoked with two - * arguments; (objectValue, sourceValue). - * - * @static - * @memberOf _ - * @type Function - * @alias extend - * @category Objects - * @param {Object} object The destination object. - * @param {...Object} [source] The source objects. - * @param {Function} [callback] The function to customize assigning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns the destination object. - * @example - * - * _.assign({ 'name': 'fred' }, { 'employer': 'slate' }); - * // => { 'name': 'fred', 'employer': 'slate' } - * - * var defaults = _.partialRight(_.assign, function(a, b) { - * return typeof a == 'undefined' ? b : a; - * }); - * - * var object = { 'name': 'barney' }; - * defaults(object, { 'name': 'fred', 'employer': 'slate' }); - * // => { 'name': 'barney', 'employer': 'slate' } - */ - var assign = function(object, source, guard) { - var index, iterable = object, result = iterable; - if (!iterable) return result; - var args = arguments, - argsIndex = 0, - argsLength = typeof guard == 'number' ? 2 : args.length; - if (argsLength > 3 && typeof args[argsLength - 2] == 'function') { - var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2); - } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') { - callback = args[--argsLength]; - } - while (++argsIndex < argsLength) { - iterable = args[argsIndex]; - if (iterable && objectTypes[typeof iterable]) { - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]; - } - } - } - return result - }; - - return assign; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseClone',['../objects/assign', '../collections/forEach', '../objects/forOwn', './getArray', '../objects/isArray', '../objects/isObject', './releaseArray', './slice'], function(assign, forEach, forOwn, getArray, isArray, isObject, releaseArray, slice) { - - /** Used to match regexp flags from their coerced string values */ - var reFlags = /\w*$/; - - /** `Object#toString` result shortcuts */ - var argsClass = '[object Arguments]', - arrayClass = '[object Array]', - boolClass = '[object Boolean]', - dateClass = '[object Date]', - funcClass = '[object Function]', - numberClass = '[object Number]', - objectClass = '[object Object]', - regexpClass = '[object RegExp]', - stringClass = '[object String]'; - - /** Used to identify object classifications that `_.clone` supports */ - var cloneableClasses = {}; - cloneableClasses[funcClass] = false; - cloneableClasses[argsClass] = cloneableClasses[arrayClass] = - cloneableClasses[boolClass] = cloneableClasses[dateClass] = - cloneableClasses[numberClass] = cloneableClasses[objectClass] = - cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to lookup a built-in constructor by [[Class]] */ - var ctorByClass = {}; - ctorByClass[arrayClass] = Array; - ctorByClass[boolClass] = Boolean; - ctorByClass[dateClass] = Date; - ctorByClass[funcClass] = Function; - ctorByClass[objectClass] = Object; - ctorByClass[numberClass] = Number; - ctorByClass[regexpClass] = RegExp; - ctorByClass[stringClass] = String; - - /** - * The base implementation of `_.clone` without argument juggling or support - * for `thisArg` binding. - * - * @private - * @param {*} value The value to clone. - * @param {boolean} [isDeep=false] Specify a deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {Array} [stackA=[]] Tracks traversed source objects. - * @param {Array} [stackB=[]] Associates clones with source counterparts. - * @returns {*} Returns the cloned value. - */ - function baseClone(value, isDeep, callback, stackA, stackB) { - if (callback) { - var result = callback(value); - if (typeof result != 'undefined') { - return result; - } - } - // inspect [[Class]] - var isObj = isObject(value); - if (isObj) { - var className = toString.call(value); - if (!cloneableClasses[className]) { - return value; - } - var ctor = ctorByClass[className]; - switch (className) { - case boolClass: - case dateClass: - return new ctor(+value); - - case numberClass: - case stringClass: - return new ctor(value); - - case regexpClass: - result = ctor(value.source, reFlags.exec(value)); - result.lastIndex = value.lastIndex; - return result; - } - } else { - return value; - } - var isArr = isArray(value); - if (isDeep) { - // check for circular references and return corresponding clone - var initedStack = !stackA; - stackA || (stackA = getArray()); - stackB || (stackB = getArray()); - - var length = stackA.length; - while (length--) { - if (stackA[length] == value) { - return stackB[length]; - } - } - result = isArr ? ctor(value.length) : {}; - } - else { - result = isArr ? slice(value) : assign({}, value); - } - // add array properties assigned by `RegExp#exec` - if (isArr) { - if (hasOwnProperty.call(value, 'index')) { - result.index = value.index; - } - if (hasOwnProperty.call(value, 'input')) { - result.input = value.input; - } - } - // exit for shallow clone - if (!isDeep) { - return result; - } - // add the source value to the stack of traversed objects - // and associate it with its clone - stackA.push(value); - stackB.push(result); - - // recursively populate clone (susceptible to call stack limits) - (isArr ? forEach : forOwn)(value, function(objValue, key) { - result[key] = baseClone(objValue, isDeep, callback, stackA, stackB); - }); - - if (initedStack) { - releaseArray(stackA); - releaseArray(stackB); - } - return result; - } - - return baseClone; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/cloneDeep',['../internals/baseClone', '../internals/baseCreateCallback'], function(baseClone, baseCreateCallback) { - - /** - * Creates a deep clone of `value`. If a callback is provided it will be - * executed to produce the cloned values. If the callback returns `undefined` - * cloning will be handled by the method instead. The callback is bound to - * `thisArg` and invoked with one argument; (value). - * - * Note: This method is loosely based on the structured clone algorithm. Functions - * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and - * objects created by constructors other than `Object` are cloned to plain `Object` objects. - * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to deep clone. - * @param {Function} [callback] The function to customize cloning values. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {*} Returns the deep cloned value. - * @example - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; - * - * var deep = _.cloneDeep(characters); - * deep[0] === characters[0]; - * // => false - * - * var view = { - * 'label': 'docs', - * 'node': element - * }; - * - * var clone = _.cloneDeep(view, function(value) { - * return _.isElement(value) ? value.cloneNode(true) : undefined; - * }); - * - * clone.node == view.node; - * // => false - */ - function cloneDeep(value, callback, thisArg) { - return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1)); - } - - return cloneDeep; -}); - -define('scribe-plugin-sanitizer',[ - 'html-janitor', - 'lodash-amd/modern/objects/merge', - 'lodash-amd/modern/objects/cloneDeep' -], function ( - HTMLJanitor, - merge, - cloneDeep -) { - - /** - * This plugin adds the ability to sanitize content when it is pasted into the - * scribe, adhering to a whitelist of allowed tags and attributes. - */ - - - - return function (config) { - // We extend the config to let through Scribe position markers, - // otherwise we lose the caret position when running the Scribe - // content through this sanitizer. - var configAllowMarkers = merge(cloneDeep(config), { - tags: { - em: {class: 'scribe-marker'} - } - }); - - return function (scribe) { - var janitor = new HTMLJanitor(configAllowMarkers); - - scribe.registerHTMLFormatter('sanitize', janitor.clean.bind(janitor)); - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-sanitizer.js.map; -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseIndexOf',[], function() { - - /** - * The base implementation of `_.indexOf` without support for binary searches - * or `fromIndex` constraints. - * - * @private - * @param {Array} array The array to search. - * @param {*} value The value to search for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value or `-1`. - */ - function baseIndexOf(array, value, fromIndex) { - var index = (fromIndex || 0) - 1, - length = array ? array.length : 0; - - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; - } - - return baseIndexOf; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/isNative',[], function() { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** Used to detect if a method is native */ - var reNative = RegExp('^' + - String(toString) - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') - .replace(/toString| for [^\]]+/g, '.*?') + '$' - ); - - /** - * Checks if `value` is a native function. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a native function, else `false`. - */ - function isNative(value) { - return typeof value == 'function' && reNative.test(value); - } - - return isNative; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/objectTypes',[], function() { - - /** Used to determine if values are of the language type Object */ - var objectTypes = { - 'boolean': false, - 'function': true, - 'object': true, - 'number': false, - 'string': false, - 'undefined': false - }; - - return objectTypes; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isObject',['../internals/objectTypes'], function(objectTypes) { - - /** - * Checks if `value` is the language type of Object. - * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(1); - * // => false - */ - function isObject(value) { - // check if the value is the ECMAScript language type of Object - // http://es5.github.io/#x8 - // and avoid a V8 bug - // http://code.google.com/p/v8/issues/detail?id=2291 - return !!(value && objectTypes[typeof value]); - } - - return isObject; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/noop',[], function() { - - /** - * A no-operation function. - * - * @static - * @memberOf _ - * @category Utilities - * @example - * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true - */ - function noop() { - // no operation performed - } - - return noop; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreate',['./isNative', '../objects/isObject', '../utilities/noop'], function(isNative, isObject, noop) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate; - - /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} prototype The object to inherit from. - * @returns {Object} Returns the new object. - */ - function baseCreate(prototype, properties) { - return isObject(prototype) ? nativeCreate(prototype) : {}; - } - // fallback for browsers without `Object.create` - if (!nativeCreate) { - baseCreate = (function() { - function Object() {} - return function(prototype) { - if (isObject(prototype)) { - Object.prototype = prototype; - var result = new Object; - Object.prototype = null; - } - return result || window.Object(); - }; - }()); - } - - return baseCreate; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/setBindData',['./isNative', '../utilities/noop'], function(isNative, noop) { - - /** Used as the property descriptor for `__bindData__` */ - var descriptor = { - 'configurable': false, - 'enumerable': false, - 'value': null, - 'writable': false - }; - - /** Used to set meta data on functions */ - var defineProperty = (function() { - // IE 8 only accepts DOM elements - try { - var o = {}, - func = isNative(func = Object.defineProperty) && func, - result = func(o, o, o) && func; - } catch(e) { } - return result; - }()); - - /** - * Sets `this` binding data on a given function. - * - * @private - * @param {Function} func The function to set data on. - * @param {Array} value The data array to set. - */ - var setBindData = !defineProperty ? noop : function(func, value) { - descriptor.value = value; - defineProperty(func, '__bindData__', descriptor); - }; - - return setBindData; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/slice',[], function() { - - /** - * Slices the `collection` from the `start` index up to, but not including, - * the `end` index. - * - * Note: This function is used instead of `Array#slice` to support node lists - * in IE < 9 and to ensure dense arrays are returned. - * - * @private - * @param {Array|Object|string} collection The collection to slice. - * @param {number} start The start index. - * @param {number} end The end index. - * @returns {Array} Returns the new array. - */ - function slice(array, start, end) { - start || (start = 0); - if (typeof end == 'undefined') { - end = array ? array.length : 0; - } - var index = -1, - length = end - start || 0, - result = Array(length < 0 ? 0 : length); - - while (++index < length) { - result[index] = array[start + index]; - } - return result; - } - - return slice; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseBind',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `_.bind` that creates the bound function and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new bound function. - */ - function baseBind(bindData) { - var func = bindData[0], - partialArgs = bindData[2], - thisArg = bindData[4]; - - function bound() { - // `Function#bind` spec - // http://es5.github.io/#x15.3.4.5 - if (partialArgs) { - // avoid `arguments` object deoptimizations by using `slice` instead - // of `Array.prototype.slice.call` and not assigning `arguments` to a - // variable as a ternary expression - var args = slice(partialArgs); - push.apply(args, arguments); - } - // mimic the constructor's `return` behavior - // http://es5.github.io/#x13.2.2 - if (this instanceof bound) { - // ensure `new bound` is an instance of `func` - var thisBinding = baseCreate(func.prototype), - result = func.apply(thisBinding, args || arguments); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisArg, args || arguments); - } - setBindData(bound, bindData); - return bound; - } - - return baseBind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateWrapper',['./baseCreate', '../objects/isObject', './setBindData', './slice'], function(baseCreate, isObject, setBindData, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push; - - /** - * The base implementation of `createWrapper` that creates the wrapper and - * sets its meta data. - * - * @private - * @param {Array} bindData The bind data array. - * @returns {Function} Returns the new function. - */ - function baseCreateWrapper(bindData) { - var func = bindData[0], - bitmask = bindData[1], - partialArgs = bindData[2], - partialRightArgs = bindData[3], - thisArg = bindData[4], - arity = bindData[5]; - - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - key = func; - - function bound() { - var thisBinding = isBind ? thisArg : this; - if (partialArgs) { - var args = slice(partialArgs); - push.apply(args, arguments); - } - if (partialRightArgs || isCurry) { - args || (args = slice(arguments)); - if (partialRightArgs) { - push.apply(args, partialRightArgs); - } - if (isCurry && args.length < arity) { - bitmask |= 16 & ~32; - return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]); - } - } - args || (args = arguments); - if (isBindKey) { - func = thisBinding[key]; - } - if (this instanceof bound) { - thisBinding = baseCreate(func.prototype); - var result = func.apply(thisBinding, args); - return isObject(result) ? result : thisBinding; - } - return func.apply(thisBinding, args); - } - setBindData(bound, bindData); - return bound; - } - - return baseCreateWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isFunction',[], function() { - - /** - * Checks if `value` is a function. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - */ - function isFunction(value) { - return typeof value == 'function'; - } - - return isFunction; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/createWrapper',['./baseBind', './baseCreateWrapper', '../objects/isFunction', './slice'], function(baseBind, baseCreateWrapper, isFunction, slice) { - - /** - * Used for `Array` method references. - * - * Normally `Array.prototype` would suffice, however, using an array literal - * avoids issues in Narwhal. - */ - var arrayRef = []; - - /** Native method shortcuts */ - var push = arrayRef.push, - unshift = arrayRef.unshift; - - /** - * Creates a function that, when called, either curries or invokes `func` - * with an optional `this` binding and partially applied arguments. - * - * @private - * @param {Function|string} func The function or method name to reference. - * @param {number} bitmask The bitmask of method flags to compose. - * The bitmask may be composed of the following flags: - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` - * 8 - `_.curry` (bound) - * 16 - `_.partial` - * 32 - `_.partialRight` - * @param {Array} [partialArgs] An array of arguments to prepend to those - * provided to the new function. - * @param {Array} [partialRightArgs] An array of arguments to append to those - * provided to the new function. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new function. - */ - function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) { - var isBind = bitmask & 1, - isBindKey = bitmask & 2, - isCurry = bitmask & 4, - isCurryBound = bitmask & 8, - isPartial = bitmask & 16, - isPartialRight = bitmask & 32; - - if (!isBindKey && !isFunction(func)) { - throw new TypeError; - } - if (isPartial && !partialArgs.length) { - bitmask &= ~16; - isPartial = partialArgs = false; - } - if (isPartialRight && !partialRightArgs.length) { - bitmask &= ~32; - isPartialRight = partialRightArgs = false; - } - var bindData = func && func.__bindData__; - if (bindData && bindData !== true) { - // clone `bindData` - bindData = slice(bindData); - if (bindData[2]) { - bindData[2] = slice(bindData[2]); - } - if (bindData[3]) { - bindData[3] = slice(bindData[3]); - } - // set `thisBinding` is not previously bound - if (isBind && !(bindData[1] & 1)) { - bindData[4] = thisArg; - } - // set if previously bound but not currently (subsequent curried functions) - if (!isBind && bindData[1] & 1) { - bitmask |= 8; - } - // set curried arity if not yet set - if (isCurry && !(bindData[1] & 4)) { - bindData[5] = arity; - } - // append partial left arguments - if (isPartial) { - push.apply(bindData[2] || (bindData[2] = []), partialArgs); - } - // append partial right arguments - if (isPartialRight) { - unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs); - } - // merge flags - bindData[1] |= bitmask; - return createWrapper.apply(null, bindData); - } - // fast path for `_.bind` - var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper; - return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]); - } - - return createWrapper; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/functions/bind',['../internals/createWrapper', '../internals/slice'], function(createWrapper, slice) { - - /** - * Creates a function that, when called, invokes `func` with the `this` - * binding of `thisArg` and prepends any additional `bind` arguments to those - * provided to the bound function. - * - * @static - * @memberOf _ - * @category Functions - * @param {Function} func The function to bind. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {...*} [arg] Arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * var func = function(greeting) { - * return greeting + ' ' + this.name; - * }; - * - * func = _.bind(func, { 'name': 'fred' }, 'hi'); - * func(); - * // => 'hi fred' - */ - function bind(func, thisArg) { - return arguments.length > 2 - ? createWrapper(func, 17, slice(arguments, 2), null, thisArg) - : createWrapper(func, 1, null, null, thisArg); - } - - return bind; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/utilities/identity',[], function() { - - /** - * This method returns the first argument provided to it. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; - * // => true - */ - function identity(value) { - return value; - } - - return identity; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/support',['./internals/isNative'], function(isNative) { - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** - * An object used to flag environments features. - * - * @static - * @memberOf _ - * @type Object - */ - var support = {}; - - /** - * Detect if functions can be decompiled by `Function#toString` - * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps). - * - * @memberOf _.support - * @type boolean - */ - support.funcDecomp = !isNative(window.WinRTError) && reThis.test(function() { return this; }); - - /** - * Detect if `Function#name` is supported (all but IE). - * - * @memberOf _.support - * @type boolean - */ - support.funcNames = typeof Function.name == 'string'; - - return support; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/baseCreateCallback',['../functions/bind', '../utilities/identity', './setBindData', '../support'], function(bind, identity, setBindData, support) { - - /** Used to detected named functions */ - var reFuncName = /^\s*function[ \n\r\t]+\w/; - - /** Used to detect functions containing a `this` reference */ - var reThis = /\bthis\b/; - - /** Native method shortcuts */ - var fnToString = Function.prototype.toString; - - /** - * The base implementation of `_.createCallback` without support for creating - * "_.pluck" or "_.where" style callbacks. - * - * @private - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - */ - function baseCreateCallback(func, thisArg, argCount) { - if (typeof func != 'function') { - return identity; - } - // exit early for no `thisArg` or already bound by `Function#bind` - if (typeof thisArg == 'undefined' || !('prototype' in func)) { - return func; - } - var bindData = func.__bindData__; - if (typeof bindData == 'undefined') { - if (support.funcNames) { - bindData = !func.name; - } - bindData = bindData || !support.funcDecomp; - if (!bindData) { - var source = fnToString.call(func); - if (!support.funcNames) { - bindData = !reFuncName.test(source); - } - if (!bindData) { - // checks if `func` references the `this` keyword and stores the result - bindData = reThis.test(source); - setBindData(func, bindData); - } - } - } - // exit early if there are no `this` references or `func` is bound - if (bindData === false || (bindData !== true && bindData[1] & 1)) { - return func; - } - switch (argCount) { - case 1: return function(value) { - return func.call(thisArg, value); - }; - case 2: return function(a, b) { - return func.call(thisArg, a, b); - }; - case 3: return function(value, index, collection) { - return func.call(thisArg, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(thisArg, accumulator, value, index, collection); - }; - } - return bind(func, thisArg); - } - - return baseCreateCallback; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/internals/shimKeys',['./objectTypes'], function(objectTypes) { - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Native method shortcuts */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** - * A fallback implementation of `Object.keys` which produces an array of the - * given object's own enumerable property names. - * - * @private - * @type Function - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - */ - var shimKeys = function(object) { - var index, iterable = object, result = []; - if (!iterable) return result; - if (!(objectTypes[typeof object])) return result; - for (index in iterable) { - if (hasOwnProperty.call(iterable, index)) { - result.push(index); - } - } - return result - }; - - return shimKeys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/keys',['../internals/isNative', './isObject', '../internals/shimKeys'], function(isNative, isObject, shimKeys) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys; - - /** - * Creates an array composed of the own enumerable property names of an object. - * - * @static - * @memberOf _ - * @category Objects - * @param {Object} object The object to inspect. - * @returns {Array} Returns an array of property names. - * @example - * - * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); - * // => ['one', 'two', 'three'] (property order is not guaranteed across environments) - */ - var keys = !nativeKeys ? shimKeys : function(object) { - if (!isObject(object)) { - return []; - } - return nativeKeys(object); - }; - - return keys; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/forOwn',['../internals/baseCreateCallback', './keys', '../internals/objectTypes'], function(baseCreateCallback, keys, objectTypes) { - - /** - * Iterates over own enumerable properties of an object, executing the callback - * for each property. The callback is bound to `thisArg` and invoked with three - * arguments; (value, key, object). Callbacks may exit iteration early by - * explicitly returning `false`. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {Object} object The object to iterate over. - * @param {Function} [callback=identity] The function called per iteration. - * @param {*} [thisArg] The `this` binding of `callback`. - * @returns {Object} Returns `object`. - * @example - * - * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { - * console.log(key); - * }); - * // => logs '0', '1', and 'length' (property order is not guaranteed across environments) - */ - var forOwn = function(collection, callback, thisArg) { - var index, iterable = collection, result = iterable; - if (!iterable) return result; - if (!objectTypes[typeof iterable]) return result; - callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3); - var ownIndex = -1, - ownProps = objectTypes[typeof iterable] && keys(iterable), - length = ownProps ? ownProps.length : 0; - - while (++ownIndex < length) { - index = ownProps[ownIndex]; - if (callback(iterable[index], index, collection) === false) return result; - } - return result - }; - - return forOwn; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isArray',['../internals/isNative'], function(isNative) { - - /** `Object#toString` result shortcuts */ - var arrayClass = '[object Array]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray; - - /** - * Checks if `value` is an array. - * - * @static - * @memberOf _ - * @type Function - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is an array, else `false`. - * @example - * - * (function() { return _.isArray(arguments); })(); - * // => false - * - * _.isArray([1, 2, 3]); - * // => true - */ - var isArray = nativeIsArray || function(value) { - return value && typeof value == 'object' && typeof value.length == 'number' && - toString.call(value) == arrayClass || false; - }; - - return isArray; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/objects/isString',[], function() { - - /** `Object#toString` result shortcuts */ - var stringClass = '[object String]'; - - /** Used for native method references */ - var objectProto = Object.prototype; - - /** Used to resolve the internal [[Class]] of values */ - var toString = objectProto.toString; - - /** - * Checks if `value` is a string. - * - * @static - * @memberOf _ - * @category Objects - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if the `value` is a string, else `false`. - * @example - * - * _.isString('fred'); - * // => true - */ - function isString(value) { - return typeof value == 'string' || - value && typeof value == 'object' && toString.call(value) == stringClass || false; - } - - return isString; -}); - -/** - * Lo-Dash 2.4.1 (Custom Build) - * Build: `lodash modularize modern exports="amd" -o ./modern/` - * Copyright 2012-2013 The Dojo Foundation - * Based on Underscore.js 1.5.2 - * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - * Available under MIT license - */ -define('lodash-amd/modern/collections/contains',['../internals/baseIndexOf', '../objects/forOwn', '../objects/isArray', '../objects/isString'], function(baseIndexOf, forOwn, isArray, isString) { - - /* Native method shortcuts for methods with the same name as other `lodash` methods */ - var nativeMax = Math.max; - - /** - * Checks if a given value is present in a collection using strict equality - * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the - * offset from the end of the collection. - * - * @static - * @memberOf _ - * @alias include - * @category Collections - * @param {Array|Object|string} collection The collection to iterate over. - * @param {*} target The value to check for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {boolean} Returns `true` if the `target` element is found, else `false`. - * @example - * - * _.contains([1, 2, 3], 1); - * // => true - * - * _.contains([1, 2, 3], 1, 2); - * // => false - * - * _.contains({ 'name': 'fred', 'age': 40 }, 'fred'); - * // => true - * - * _.contains('pebbles', 'eb'); - * // => true - */ - function contains(collection, target, fromIndex) { - var index = -1, - indexOf = baseIndexOf, - length = collection ? collection.length : 0, - result = false; - - fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; - if (isArray(collection)) { - result = indexOf(collection, target, fromIndex) > -1; - } else if (typeof length == 'number') { - result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1; - } else { - forOwn(collection, function(value) { - if (++index >= fromIndex) { - return !(result = value === target); - } - }); - } - return result; - } - - return contains; -}); - -define('scribe-common/src/element',['lodash-amd/modern/collections/contains'], function (contains) { - - - - // TODO: not exhaustive? - var blockElementNames = ['P', 'LI', 'DIV', 'BLOCKQUOTE', 'UL', 'OL', 'H1', - 'H2', 'H3', 'H4', 'H5', 'H6']; - function isBlockElement(node) { - return contains(blockElementNames, node.nodeName); - } - - function isSelectionMarkerNode(node) { - return (node.nodeType === Node.ELEMENT_NODE && node.className === 'scribe-marker'); - } - - function unwrap(node, childNode) { - while (childNode.childNodes.length > 0) { - node.insertBefore(childNode.childNodes[0], childNode); - } - node.removeChild(childNode); - } - - return { - isBlockElement: isBlockElement, - isSelectionMarkerNode: isSelectionMarkerNode, - unwrap: unwrap - }; - -}); - -define('scribe-plugin-smart-lists',['scribe-common/src/element'], function (element) { - - - - return function () { - - var keys = { - 32: 'Space', - 42: '*', - 45: '-', - 46: '.', - 49: '1', - // Bullet insertion keycode, most likely only working on OS X... - 8226: '•' - }; - - function isUnorderedListChar(string) { - return string === '*' || string === '-' || string === '•'; - } - - function findBlockContainer(node) { - while (node && ! element.isBlockElement(node)) { - node = node.parentNode; - } - - return node; - } - - return function (scribe) { - - var preLastChar, lastChar, currentChar; - - function removeSelectedTextNode() { - var selection = new scribe.api.Selection(); - var container = selection.selection.anchorNode; - /** - * Firefox: Selection object never gets access to text nodes, only - * parent elements. - * As per: http://jsbin.com/rotus/2/edit?js,output,console - * Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1042701 - */ - var textNode; - if (container.nodeType === Node.TEXT_NODE) { - textNode = container; - } else if (container.firstChild.nodeType === Node.TEXT_NODE) { - textNode = container.firstChild; - } - - if (textNode) { - var parentNode = textNode.parentNode; - /** - * Firefox: Given text of "1.", we sometimes have two text nodes - * (why?): "1" and "." - */ - if (textNode.previousSibling) { - parentNode.removeChild(textNode.previousSibling); - } - parentNode.removeChild(textNode); - } else { - throw new Error('Cannot empty non-text node!'); - } - } - - function input(event) { - var listCommand; - - preLastChar = lastChar; - lastChar = currentChar; - // FIXME: Chrome / FF, theoretically we should be using event.key? - // can we abstract this madness? - currentChar = keys[event.charCode]; - - var selection = new scribe.api.Selection(); - - // TODO: if a

    with just this content - var container = selection.range.commonAncestorContainer; - - // If in a

    - var blockContainer = findBlockContainer(container); - if (blockContainer && blockContainer.tagName === 'P') { - // Warning: There is no guarantee that `container` will be a text node - // Failing Firefox tests - - var startOfLineIsUList = isUnorderedListChar(container.textContent[0]); - if (isUnorderedListChar(lastChar) && currentChar === 'Space' && startOfLineIsUList) { - listCommand = 'insertUnorderedList'; - } - - /** - * Firefox: Selection object never gets access to text nodes, only - * parent elements. This means that *sometimes* unordered lists - * will not work. - * As per: http://jsbin.com/rotus/2/edit?js,output,console - * Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1042701 - */ - - // Some browsers split text nodes randomly, so we can't be sure the - // prefix will be contained within a single text node (observed in - // Firefox) - var startOfLineIsOList = [ - container.previousSibling && container.previousSibling.textContent, - container.textContent - ].join('').slice(0, 2) === '1.'; - if (preLastChar === '1' && lastChar === '.' && currentChar === 'Space' && startOfLineIsOList) { - listCommand = 'insertOrderedList'; - } - } - - if (listCommand) { - // Ignore the typed character - event.preventDefault(); - - scribe.transactionManager.run(function() { - scribe.getCommand(listCommand).execute(); - - // Clear "* "/etc from the list item - removeSelectedTextNode(); - }); - } - } - - scribe.el.addEventListener('keypress', input); - }; - }; - -}); - -//# sourceMappingURL=scribe-plugin-smart-lists.js.map; -define('scribe-plugin-toolbar',[],function () { - - - - return function (toolbarNode) { - return function (scribe) { - var buttons = toolbarNode.querySelectorAll('[data-command-name]'); - - Array.prototype.forEach.call(buttons, function (button) { - button.addEventListener('click', function () { - // Look for a predefined command. - var command = scribe.getCommand(button.dataset.commandName); - - /** - * Focus will have been taken away from the Scribe instance when - * clicking on a button (Chrome will return the focus automatically - * but only if the selection is not collapsed. As per: http://jsbin.com/tupaj/1/edit?html,js,output). - * It is important that we focus the instance again before executing - * the command, because it might rely on selection data. - */ - scribe.el.focus(); - command.execute(button.dataset.commandValue); - /** - * Chrome has a bit of magic to re-focus the `contenteditable` when a - * command is executed. - * As per: http://jsbin.com/papi/1/edit?html,js,output - */ - }); - - // Keep the state of toolbar buttons in sync with the current selection. - // Unfortunately, there is no `selectionchange` event. - scribe.el.addEventListener('keyup', updateUi); - scribe.el.addEventListener('mouseup', updateUi); - - scribe.el.addEventListener('focus', updateUi); - scribe.el.addEventListener('blur', updateUi); - - // We also want to update the UI whenever the content changes. This - // could be when one of the toolbar buttons is actioned. - scribe.on('content-changed', updateUi); - - function updateUi() { - // Look for a predefined command. - var command = scribe.getCommand(button.dataset.commandName); - - var selection = new scribe.api.Selection(); - - // TODO: Do we need to check for the selection? - if (selection.range && command.queryState(button.dataset.commandValue)) { - button.classList.add('active'); - } else { - button.classList.remove('active'); - } - - if (selection.range && command.queryEnabled()) { - button.removeAttribute('disabled'); - } else { - button.setAttribute('disabled', 'disabled'); - } - } - }); - }; - }; - -}); - - -//# sourceMappingURL=scribe-plugin-toolbar.js.map; - -define('scribe-plugin-inline-objects',[],function () { - - /** - * Adds support for inserting inline objects, like embeds, videos and images. - */ - return function (config) { - return function (scribe) { - // define inline objects - - var editorEl = scribe.el.parentNode; - - var templates; - var activeBlock, activeElement; - - // Load the config. - function configLoaded(data) { - templates = data; - $('.embed-button', editorEl).click(openFlyout); - - $('.inline-tools button', editorEl.parentNode).click(function(event) { - var name = $(event.target).data('commandName'); - if (typeof actions[name] === 'function') { - actions[name](); - } - }); - } - - function openFlyout(event) { - var blockPosition, - flyoutHeight = $('.embed-fly-out').height(), - buttonHeight = $('.embed-button').height(), - beforeOrAfter; - - var command = $(event.target).closest('button').data('commandName'); - if (command === 'embed-before') { - blockPosition = activeBlock.position().top - flyoutHeight / 2 + buttonHeight / 2; - beforeOrAfter = 'before'; - } - else { - blockPosition = activeBlock.position().top + - activeBlock.height() - + parseInt(activeBlock.css('margin-top')) - - flyoutHeight / 2 + buttonHeight / 2; - beforeOrAfter = 'after'; - } - - $('.embed-fly-out', editorEl) - .css({ - top: blockPosition, - left: $(scribe.el).css('padding-left') - }) - .show(); - - //register click handler for toolbar - var elementToPlaceNear = activeBlock; - $('.embed-fly-out button').bind('click.inline', function(e) { - var type = $(e.target).closest('button').data('commandName'); - insertObject(type, elementToPlaceNear, beforeOrAfter); - }); - - - $('body').bind('click.inline', function(e) { - // if a click happens outside of the flyout, close it. - if ($(e.target).closest('.embed-tools').length === 0) { - closeFlyout(); - } - }); - } - - - function closeFlyout() { - $('body').unbind('click.inline'); - $('.embed-fly-out button').unbind('click.inline'); - $('.embed-fly-out').hide(); - } - - - function insertObject(objectType, elementToPlaceNear, beforeOrAfter) { - //derive type from button clicked. - //emit an event, so handler plugin can pick up. - scribe.trigger('inline:insert:' + objectType, [ - function(values) { - scribe.updateContents(function() { - var $newEl = $(render( - templates[objectType].template, - $.extend(templates[objectType].defaults, values) - )); - - $(elementToPlaceNear)[beforeOrAfter]($newEl); - $('.inline', editorEl).attr('contenteditable', false); - - scribe.trigger('inline:insert:' + objectType + ':done', [$newEl]); - }); - } - ]); - $('.embed-tools', editorEl).removeClass('active'); - } - - // Insert toolbar. - scribe.el.addEventListener('mouseover', function (event) { - var block = $(event.target).closest('.editor>*'); - if (block.length === 1) { - //var top = blocks[i].offsetTop; - $('.embed-tools',editorEl) - .css({ - width: $(scribe.el).css('padding-left'), - top: block.position().top + block.css('margin-top').replace(/[^-\d\.]/g, '') / 2, - height: block.height() - }) - .addClass('active'); - activeBlock = block; - } - else { - $('.embed-tools', editorEl).removeClass('active'); - } - }); - - scribe.el.parentNode.addEventListener('mouseleave', function (event) { - hideToolbar(); - $('.embed-tools', editorEl).removeClass('active'); - }); - - // put the actve class back on if hover back into a button - $('.embed-tools', editorEl).mouseover(function() { - $('.embed-tools', editorEl).addClass('active'); - }); - - - - // Overlay options - $('.editor', editorEl).mouseover( function(e) { - //check to see if the target is inside of an inline element - var parents = $(e.target).parents('.inline'); - if (parents.length === 1) { - //let's position tools over the inline element - activeElement = parents[parents.length-1]; - showToolbar(); - } - else { - hideToolbar(); - } - }); - - function hideToolbar() { - $('.inline-tools').hide(); - $(editorEl).removeClass('inline-active'); - } - - function showToolbar() { - var el = $(activeElement); - var pos = el.position(); - $(editorEl).addClass('inline-active'); - - - // set the type attribute on the overlay, for custom styling. - $('.inline-tools').attr('data-type', el.attr('data-type')); - - - //set size buttons. - - $('.inline-tools .size', editorEl) - .html($(activeElement).attr('data-size')); - - //set crop - $('.inline-tools .crop', editorEl) - .html($(activeElement).attr('data-crop')); - - $('.inline-tools', editorEl) - .css({ - top: pos.top + parseInt(el.css('margin-top')), - left: pos.left + parseInt(el.css('margin-left')) + parseInt($('.editor', editorEl).css('margin-left')), - width: el.width(), - height: el.height() - }) - .show(); - } - - function getSizes() { - return templates[$(activeElement).attr('data-type')].size; - } - - function getCrops() { - return templates[$(activeElement).attr('data-type')].crop; - } - - //TODO: Determine how to handle two adjacent inline elements. Probably skip over? - var actions = { - - inline_caption: function() { - var caption = prompt('Caption', - $('.caption', activeElement).html() - ); - if (caption || caption === '') { - scribe.updateContents(function() { - $('.caption', activeElement).html(caption); - }); - } - }, - //TODO: size/crop isn't working right after you hit the 'HUGE' size in images - inline_size: function() { - var l = getSizes(); - toggleAttribute('size', l); - - var currentCrop = $(activeElement).attr('data-crop'); - var cropOptions = getCrops(); - //this crop isn't available for the new size option - if (cropOptions.indexOf(currentCrop) === -1) { - setValue('crop', cropOptions[0]); - } - }, - inline_crop: function() { - var l = templates[$(activeElement).attr('data-type')].crop; - toggleAttribute('crop', l); - }, - inline_up: function() { - hideToolbar(); - var previousBlock = $(activeElement).prev()[0]; - if (previousBlock) { - var top = $(activeElement).offset().top; - - scribe.updateContents(function() { - $(activeElement).after(previousBlock); - - setTimeout(function() { - showToolbar(); - var newTop = $(activeElement).offset().top; - window.scrollBy(0, newTop - top); - }, 0); - }); - } - }, - inline_down: function() { - hideToolbar(); - var nextBlock = $(activeElement).next()[0]; - if (nextBlock) { - var top = $(activeElement).offset().top; - scribe.updateContents(function() { - $(activeElement).before(nextBlock); - - setTimeout(function() { - showToolbar(); - var newTop = $(activeElement).offset().top; - window.scrollBy(0, newTop - top); - }, 0); - }); - } - }, - inline_remove: function () { - scribe.updateContents(function() { - $(activeElement).remove(); - }); - hideToolbar(); - }, - inline_edit: function () { - scribe.trigger('inline:edit:' + $(activeElement).attr('data-type'), - [ - activeElement, - function(element, values) { - var type = $(element).attr('data-type'); - - scribe.updateContents(function() { - element.outerHTML = - render( - templates[type].template, - $.extend(templates[type].defaults, values) - ); - - scribe.trigger('inline:edit:' + type + ':done', [$(activeElement)]); - }); - } - ] - ); - } - }; - - function toggleAttribute(attribute, list) { - var currentValue = $(activeElement).attr('data-' + attribute); - var index = list.indexOf(currentValue) + 1; - if (index >= list.length) { - index = 0; - } - setValue(attribute, list[index]); - if (typeof window.picturefill === 'function') { - setTimeout(function() { - window.picturefill(activeElement); - }, 100); - } - } - - function setValue(attribute, value) { - var currentValue = $(activeElement).attr('data-' + attribute); - scribe.updateContents(function() { - $(activeElement) - .removeClass(attribute + '-' + currentValue) - .addClass(attribute + '-' + value) - .attr('data-' + attribute, value); - showToolbar(); - }); - } - - function render(html, dict) { - for (var k in dict) { - if (k) { - html = html.replace(new RegExp('{{' + k + '}}', 'g'), dict[k]); - } - } - return html; - } - - if (typeof config === 'string' || config instanceof String) { - $.ajax(config, {success: configLoaded, dataType: 'json'}); - } else { - configLoaded(config); - } - }; - }; -}); - - -define('scribe-plugin-betty-cropper',[],function () { - return function (config) { - return function (scribe) { - - function insert(callback) { - config.insertDialog().then( - function(success){ - var format; - if (success.name.toUpperCase().indexOf('GIF') !== -1) { - format = 'gif'; - } - else { - format = 'jpg'; - } - callback({image_id: success.id, format: format}); - if (window.picturefill) { - setTimeout(function() { - // this could be nicer... - window.picturefill($('[data-image-id=' + success.id + ']')[0]); - }, 100); - } - }, - function(error){ - console.log(error); - }, - function(progress){ - console.log(progress); - } - ); - } - - var current_id; - - function edit(block, callback) { - current_id = block.getAttribute('data-image-id'); - var caption = $('.caption', block).html(); - var alt = block.getAttribute('data-alt'); - config.editDialog({id: current_id, caption: caption, alt: alt}).then( - function (image) { - - if (image.id === null) { - $(block).remove(); - } else { - $(block).attr('data-image-id', image.id); - $(block).attr('data-alt', image.alt); - $('.caption', block).html(image.caption); - if (window.picturefill) { - setTimeout(function() { - window.picturefill($('[data-image-id=' + image.id + ']')[0]); - }, 100); - } - } - } - ); - } - - scribe.on('inline:edit:image', edit); - scribe.on('inline:insert:image', insert); - }; - }; -}); -define('scribe-plugin-youtube',[],function () { - - return function (config) { - return function (scribe) { - - scribe.on("inline:insert:youtube", insert); - scribe.on("inline:edit:youtube", edit); - - function parseYoutube(url){ - if (!url) return false; - var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; - var match = url.match(regExp); - if (match && match[7].length == 11) { - return match[7]; - } - else { - return false; - } - } - - function insert(callback) { - var url = prompt("Youtube URL:"); - var youtube_id = parseYoutube(url); - if (youtube_id) { - callback( - { - "youtube_id": youtube_id, - "caption": "" - } - ); - } - } - - function edit(block, callback) { - var url = prompt("Youtube URL:", $(block).attr("data-youtube-id") || ""); - var youtube_id = parseYoutube(url); - if (youtube_id) { - callback( - block, - { - "youtube_id": youtube_id, - "caption": $(".caption", block).html() - } - ); - } - } - }; - } -}); -define('scribe-plugin-embed',[],function () { - return function (config) { - return function (scribe) { - scribe.on("inline:insert:embed", insert); - scribe.on("inline:edit:embed", edit); - var editorEl = scribe.el.parentNode; - var $modal = $(".embed-modal", editorEl); - - var $bodyInput = $(".embed-body", $modal), - $captionInput = $(".embed-caption", $modal), - $embedBtn = $(".set-embed-button", $modal), - $error = $(".embed-error", $modal), - $sizeInput = $("[name=size]", $modal); - - $modal.on("hide.bs.modal", function() { - $embedBtn.unbind("click"); - $error.hide(); - }); - - - function edit(block, callback) { - //populate modal contents - - $bodyInput.val(unescape($(block).attr("data-code"))); - $captionInput.val($(".caption", block).text()); - - var sizeCropPair = $(block).attr("data-size") + "-" + $(block).attr("data-crop"); - $("[value=" + sizeCropPair + "]", $modal).attr("checked", true); - $modal.modal("show"); - $embedBtn.click(function () { - var embedBody = $bodyInput.val(); - if (embedBody.trim() === "") { - $error.show(); - } - else { - $error.hide(); - callback(block, { - code: embedBody, - caption: $captionInput.val(), - escaped_code: escape(embedBody), - size: getSize(), - crop: getCrop() - }); - $modal.modal("hide"); - - } - }); - $modal.modal("show"); - } - - function insert(callback) { - $bodyInput.val(""); - $captionInput.val(""); - $modal.modal("show"); - - $embedBtn.click(function () { - var embedBody = $bodyInput.val(); - - if (embedBody.trim() === "") { - $error.show(); - } - else { - $error.hide(); - callback({ - code: embedBody, - caption: $captionInput.val(), - escaped_code: escape(embedBody), - size: getSize(), - crop: getCrop() - }); - $modal.modal("hide"); - } - }); - } - - function getSize() { - var value = 'original'; - if ($sizeInput.length > 0) { - $sizeInput.val().split("-")[0]; - } - return value; - } - - function getCrop() { - var value = 'original'; - if ($sizeInput.length > 0) { - $sizeInput.val().split("-")[1]; - } - return value; - } - - }; - } -}); -define('scribe-plugin-embed-instagram', [], function () { - - return function (config) { - return function (scribe) { - var $modal = $(scribe.el.parentNode).find('.embed-modal'); - var $modalCaption = $modal.find('.embed-caption'); - var $modalError = $modal.find('.embed-error'); - var $modalInput = $modal.find('.embed-body'); - var $modalOk = $modal.find('.set-embed-button'); - - $modal.on('hide.bs.modal', function () { - $modalOk.off('click'); - $modalError.hide(); - }); - - var insert = function (callback) { - $modalInput.val(''); - $modalCaption.val(''); - - $modalOk.on('click', function () { - var html = $modalInput.val(); - - if (!html.trim()) { - $modalError.show(); - } else { - $modalError.hide(); - - callback({ - html: escape(html), - caption: $modalCaption.val() - }); - - $modal.modal('hide'); - } - }); - $modal.modal('show'); - }; - - var edit = function (block, callback) { - var $block = $(block); - var $embedContainer = $block.children('.embed-container'); - var processor = $embedContainer - .instagramEmbedProcessor() - .data('pluginInstagramEmbedProcessor'); - - $modalInput.val(processor.html()); - $modalCaption.val($block.children('.caption').text()); - - $modalOk.on('click', function () { - var html = $modalInput.val(); - - if (!html.trim()) { - $modalError.show(); - } else { - $modalError.hide(); - - callback(block, { - html: escape(html), - caption: $modalCaption.val() - }); - - $modal.modal('hide'); - } - }); - $modal.modal('show'); - }; - - var after = function ($inserted) { - var $embedContainer = $inserted.find('.embed-container'); - var processor = $embedContainer - .instagramEmbedProcessor() - .data('pluginInstagramEmbedProcessor'); - processor.prep(); - }; - - scribe.on('inline:insert:embed-instagram', insert); - scribe.on('inline:insert:embed-instagram:done', after); - scribe.on('inline:edit:embed-instagram', edit); - scribe.on('inline:edit:embed-instagram:done', after); - }; - }; -}); - -define('scribe-plugin-onion-video',[],function () { - return function (config) { - return function (scribe) { - - - - scribe.on("inline:edit:onion-video", edit); - scribe.on("inline:insert:onion-video", insert); - - - function insert(callback) { - - //TODO: Show some kind of use status while waiting for the initial response. - - return config.insertDialog().then( - function(videoObject){ - scribe.updateContents(function() { - callback({embed_url: config.videoEmbedUrl, video_id:videoObject.attrs.id}); - }); - }, function(error){ - onError(error); - }, function(progress){ - onProgress(progress); - } - ); - - function onProgress() { - //update an indicator - } - - - function onError() { - //show msg, allow user to trigger upload again - } - - function onCancel() { - //remove placeholder. Call it a day. - } - - } - - function edit(block, callback) { - var id = $(block).attr('data-video-id') || $(block).attr('data-videoid'); - config.editDialog(id); - } - }; - } -}); -define('scribe-plugin-hr',[],function () { - return function (config) { - return function (scribe) { - - scribe.on("inline:insert:hr", insert); - - function insert(callback) { - callback({}); - } - }; - } -}); -define('scribe-plugin-placeholder',[],function () { - - return function (config) { - return function (scribe) { - scribe.on('content-changed', checkForEmpty); - config.container.innerHTML = config.text; - function checkForEmpty() { - var content = scribe.getContent() - if (content === "


    " || content === "") { - config.container.style.display = ''; - } - else { - config.container.style.display = 'none'; - } - } - } - } -}); -define('link-formatter',[ - 'scribe-common/src/element', - 'lodash-amd/modern/collections/contains' - - ], function ( - element, - contains - ) { - - /** - * This formatter will make sure any urls - * that are supposed to be relative stay relative to a configured - * http://www.avclub.com/some-article ==> /some-article - */ - - 'use strict'; - - // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements - - - return function (config) { - return function (scribe) { - - function fixLink(url) { - url = url.trim(); - url = fixProtocol(url); - if (config.domain) { - url = makeRelative(url, config.domain); - } - return url - } - - function makeRelative(url, domain) { - var a = document.createElement("a"); - a.href = url; - // check if it's an avclub link - var host = a.hostname; - // also check that there's a path at the end - if (host.indexOf(domain) > -1 && a.pathname.length > 1) { - url = a.pathname + a.search + a.hash; - } - return url; - } - - function fixProtocol(url) { - if ( - url.substr(0, 7) !== "http://" && - url.substr(0, 8) !== "https://" && - url.substr(0, 7) !== "mailto:" && - url.substr(0, 1) !== "/" - ) { - // check for email, but default to http - if (url.indexOf("@") != -1) { - return "mailto:" + url; - } else { - return "http://" + url; - } - } else { - return url; - } - } - - function traverse(parentNode) { - var node = parentNode.firstElementChild; - - while (node) { - if (node.nodeName === 'A') { - if (node.hasAttribute('href')) { - node.setAttribute('href', fixLink(node.getAttribute('href'))); - } - } - else if (node.children.length > 0) { - traverse(node); - } - node = node.nextElementSibling; - } - } - - scribe.registerHTMLFormatter('sanitize', function (html) { - var bin = document.createElement('div'); - bin.innerHTML = html; - traverse(bin); - return bin.innerHTML; - }); - - }; - }; - -}); - -define('only-trailing-brs',[],function () { - - 'use strict'; - - // For single-line mode: Firefox needs a BR at the end to work. - // However, we don't want multiple BRs since this is a single-line input. - // So I'm whitelisting BR in the "sanitizer" plugin and adding this guy. - // This will mess up "inline" objects which rely on BR, of which we - // currently have none so it's not a big deal. - return function () { - return function (scribe) { - scribe.registerHTMLFormatter('normalize', function (html) { - return html.replace(/
    (.)/g, ' $1'); - }); - }; - }; - -}); - -define('paste-strip-newlines',[],function () { - - 'use strict'; - - return function () { - return function (scribe) { - scribe.registerHTMLFormatter('paste', function (html) { - return html.replace(/\n/g, ' '); - }); - }; - }; - -}); - -define('paste-strip-nbsps',[],function () { - - 'use strict'; - - return function () { - return function (scribe) { - scribe.registerHTMLFormatter('paste', function (html) { - return html.replace(/ /g, ' '); - }); - scribe.registerHTMLFormatter('normalize', function (html) { - return html.replace(/ /g, ' '); - }); - }; - }; - -}); - -define('paste-from-word',['scribe-common/src/element'], function (scribeElement) { - - 'use strict'; - - return function () { - return function (scribe) { - - // Flagrantly lifted from TinyMCE - function isWordContent(html) { - return ( - (/ 0) { - traverse(node); - } - - // Kill bullshit a tags - if (node.nodeName === 'A') { - if (!node.href) { // There are a bunch of tags taht are basically bookmarks. We don't need 'em. - scribeElement.unwrap(parentNode, node); - } - } - - node = nextNode; - } - } - - scribe.registerHTMLFormatter('paste', function (html) { - if (!isWordContent(html)) { - // We only want to fuck with word docs. Word docs are crazy. - return html; - } - - // Word comments like conditional comments etc - html = html.replace(//gi, ''); - - // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, - // MS Office namespaced tags, and a few other tags - html = html.replace(/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, ''); - - // Now let's use this thing as a doc. - var bin = document.createElement('div'); - bin.innerHTML = html; - - traverse(bin); - - // In the end, we really only care about the body. - return bin.innerHTML; - }); - }; - }; - -}); -define('paste-sanitize',['scribe-common/src/element'], function (scribeElement) { - - 'use strict'; - - return function () { - return function (scribe) { - - function traverse(parentNode) { - var node = parentNode.firstElementChild; - - while (node) { - var nextNode = node.nextElementSibling; - - if (node.children.length > 0) { - traverse(node); - } - - if (node.hasAttribute('style')) { - node.removeAttribute('style'); - } - - // There seem to be a bunch of empty p tags, that cause all kinds of trouble. - if (node.nodeName === 'P' && node.textContent.trim() === '') { - parentNode.removeChild(node); // Kill these empty p tagz - } - - // FUCK YO SPANS - if (node.nodeName === 'SPAN') { - scribeElement.unwrap(parentNode, node); - } - - node = nextNode; - } - } - - scribe.registerHTMLFormatter('paste', function (html) { - - var bin = document.createElement('div'); - bin.innerHTML = html; - - var childNodes = [].slice.call(bin.childNodes); - childNodes.forEach(function(childNode) { - if (childNode.nodeType === 3 && childNode.textContent.trim() === '') { - // Kill all empty spaces between tags. - bin.removeChild(childNode); - } - }); - - traverse(bin); - return bin.innerHTML; - }); - }; - }; - -}); - -define('remove-a-styles',['scribe-common/src/element'], function (scribeElement) { - - 'use strict'; - - return function () { - return function (scribe) { - - function traverse(parentNode) { - var node = parentNode.firstElementChild; - - while (node) { - if (node.nodeName === 'A' && node.hasAttribute('style')) { - node.removeAttribute('style'); - } - else if (node.children.length > 0) { - traverse(node); - } - node = node.nextElementSibling; - } - } - - scribe.registerHTMLFormatter('sanitize', function (html) { - - var bin = document.createElement('div'); - bin.innerHTML = html; - - traverse(bin); - return bin.innerHTML; - }); - }; - }; - -}); - -define('strip-bold-in-headings',['scribe-common/src/element'], function (scribeElement) { - - 'use strict'; - - return function () { - return function (scribe) { - - function traverse(parentNode) { - var node = parentNode.firstElementChild; - - while (node) { - if (node.nodeName === 'B' && (/^(H[1-6])$/).test(parentNode.nodeName)) { - scribeElement.unwrap(parentNode, node); - } - else if (node.children.length > 0) { - traverse(node); - } - node = node.nextElementSibling; - } - } - - scribe.registerHTMLFormatter('sanitize', function (html) { - - var bin = document.createElement('div'); - bin.innerHTML = html; - - traverse(bin); - return bin.innerHTML; - }); - }; - }; - -}); - -define('scribe-plugin-anchor',[],function () { - return function (config) { - return function (scribe) { - var anchorCommand = new scribe.api.Command('anchor'); - - function getSlug(text) { - return text.toString().toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(/[^\w\-]+/g, '') // Remove all non-word chars - .replace(/\-\-+/g, '-') - .trim(); - } - - anchorCommand.queryEnabled = function () { - var selection = new scribe.api.Selection(); - var targetNode = selection.getContaining(function(node){ - return true; - }); - return targetNode !== undefined; - } - - anchorCommand.queryState = function (value) { - var selection = new scribe.api.Selection(); - var targetNode = selection.getContaining(function(node){ - return node.nodeType !== 3; - }); - if (targetNode === undefined) { - return false; - } - return !! targetNode.id - }; - - anchorCommand.execute = function () { - var selection = new scribe.api.Selection(); - console.log(selection); - var targetNode = selection.getContaining(function(node){ - return node.nodeType !== 3; - }); - console.log(targetNode); - - scribe.transactionManager.run(function () { - if (targetNode.id) { - targetNode.removeAttribute('id'); - } else { - targetNode.id = getSlug(targetNode.textContent); - } - }.bind(this)); - }; - - scribe.commands.toggleAnchor = anchorCommand; - }; - } -}); -define('our-ensure-selectable-containers',[ - 'scribe-common/src/element', - 'lodash-amd/modern/collections/contains' - ], function ( - element, - contains - ) { - - /** - * Chrome and Firefox: All elements need to contain either text or a `
    ` to - * remain selectable. (Unless they have a width and height explicitly set with - * CSS(?), as per: http://jsbin.com/gulob/2/edit?html,css,js,output) - */ - - /** - * It seems we don't want BRs inserted in html-inline elements (like I, B, A) nor - * our "inline objects" so we allow for an optional "skipElement" function in - * the config. - */ - - 'use strict'; - - // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements - var html5VoidElements = ['AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR']; - var inlineElementNames = ['A', 'B', 'DEL', 'EM', 'STRONG', 'I', 'U']; - function nodeIsInlineElement(node) { - return inlineElementNames.indexOf(node.nodeName) !== -1; - } - - function traverse(parentNode, config) { - // Instead of TreeWalker, which gets confused when the BR is added to the dom, - // we recursively traverse the tree to look for an empty node that can have childNodes - - var node = parentNode.firstElementChild; - - function isEmpty(node) { - return node.children.length === 0 - || (node.children.length === 1 - && element.isSelectionMarkerNode(node.children[0])); - } - - while (node) { - if (!element.isSelectionMarkerNode(node)) { - // Find any node that contains no child *elements*, or just contains - // whitespace, and is not self-closing - // dont put BRs in inline elements, please. - if (isEmpty(node) && - node.textContent.trim() === '' && - !contains(html5VoidElements, node.nodeName) && - element.isBlockElement(node)) { - node.appendChild(document.createElement('br')); - } else if (node.children.length > 0) { - if (!config.skipElement || !(config.skipElement && config.skipElement(node))) { - traverse(node, config); - } - } - } - node = node.nextElementSibling; - } - } - - return function (config) { - return function (scribe) { - - scribe.registerHTMLFormatter('normalize', function (html) { - var bin = document.createElement('div'); - bin.innerHTML = html; - - traverse(bin, config); - - return bin.innerHTML; - }); - - }; - }; - -}); - -define('enforce-p-elements',[ - 'lodash-amd/modern/arrays/last', - 'scribe-common/src/element' -], function ( - last, - element -) { - - /** - * Chrome and Firefox: Upon pressing backspace inside of a P, the - * browser deletes the paragraph element, leaving the caret (and any - * content) outside of any P. - * - * Firefox: Erasing across multiple paragraphs, or outside of a - * whole paragraph (e.g. by ‘Select All’) will leave content outside - * of any P. - * - * Entering a new line in a pristine state state will insert - * `
    `s (in Chrome) or `
    `s (in Firefox) where previously we - * had `

    `'s. This patches the behaviour of delete/backspace so - * that we do not end up in a pristine state. - */ - - 'use strict'; - - /** - * Wrap consecutive inline elements and text nodes in a P element. - */ - function wrapChildNodes(parentNode) { - var groups = Array.prototype.reduce.call(parentNode.childNodes, - function (accumulator, binChildNode) { - var group = last(accumulator); - if (! group) { - startNewGroup(); - } else { - var isBlockGroup = element.isBlockElement(group[0]); - if (isBlockGroup === element.isBlockElement(binChildNode)) { - group.push(binChildNode); - } else { - startNewGroup(); - } - } - - return accumulator; - - function startNewGroup() { - var newGroup = [binChildNode]; - accumulator.push(newGroup); - } - }, []); - - var consecutiveInlineElementsAndTextNodes = groups.filter(function (group) { - var isBlockGroup = element.isBlockElement(group[0]); - return ! isBlockGroup; - }); - - consecutiveInlineElementsAndTextNodes.forEach(function (nodes) { - var pElement = document.createElement('p'); - nodes[0].parentNode.insertBefore(pElement, nodes[0]); - nodes.forEach(function (node) { - pElement.appendChild(node); - }); - }); - - parentNode._isWrapped = true; - } - - // Traverse the tree, wrapping child nodes as we go. - function traverse(parentNode) { - var treeWalker = document.createTreeWalker(parentNode, NodeFilter.SHOW_ELEMENT); - var node = treeWalker.firstChild(); - - // FIXME: does this recurse down? - - while (node) { - // TODO: At the moment we only support BLOCKQUOTEs. See failing - // tests. - if (node.nodeName === 'BLOCKQUOTE' && ! node._isWrapped) { - wrapChildNodes(node); - traverse(parentNode); - break; - } - node = treeWalker.nextSibling(); - } - } - - return function () { - return function (scribe) { - - scribe.registerHTMLFormatter('normalize', function (html) { - /** - * Ensure P mode. - * - * Wrap any orphan text nodes in a P element. - */ - // TODO: This should be configurable and also correct markup such as - // `

      1
    ` to
    • 2
    `. See skipped tests. - // TODO: This should probably be a part of HTML Janitor, or some other - // formatter. - var bin = document.createElement('div'); - bin.innerHTML = html; - - wrapChildNodes(bin); - traverse(bin); - - return bin.innerHTML; - }); - - }; - }; - -}); - -define('filter-for-export',['scribe-common/src/element'], function (scribeElement) { - 'user strict'; - - return function () { - return function (scribe) { - function traverse (parentNode) { - var node = parentNode.firstElementChild; - - while (node) { - if (node.filterForExport) { - node.filterForExport(); - } - - if (node.children.length > 0) { - traverse(node); - } - - node = node.nextElementSibling; - } - } - - scribe.registerHTMLFormatter('export', function (html) { - var bin = document.createElement('div'); - bin.innerHTML = html; - traverse(bin); - return bin.innerHTML; - }); - }; - }; - -}); - -define('onion-editor',[ - 'scribe', - 'scribe-plugin-blockquote-command', - 'scribe-plugin-curly-quotes', - 'scribe-plugin-formatter-plain-text-convert-new-lines-to-html', - 'scribe-plugin-heading-command', - 'scribe-plugin-intelligent-unlink-command', - 'scribe-plugin-keyboard-shortcuts', - 'scribe-plugin-link-ui', - 'scribe-plugin-sanitizer', - 'scribe-plugin-smart-lists', - 'scribe-plugin-toolbar', - 'scribe-plugin-inline-objects', - 'scribe-plugin-betty-cropper', - 'scribe-plugin-youtube', - 'scribe-plugin-embed', - 'scribe-plugin-embed-instagram', - 'scribe-plugin-onion-video', - 'scribe-plugin-hr', - 'scribe-plugin-placeholder', - 'link-formatter', - 'only-trailing-brs', - 'paste-strip-newlines', - 'paste-strip-nbsps', - 'paste-from-word', - 'paste-sanitize', - 'remove-a-styles', - 'strip-bold-in-headings', - 'scribe-plugin-anchor', - // scribe core - 'our-ensure-selectable-containers', - 'enforce-p-elements', - 'filter-for-export', -], function ( - Scribe, - scribePluginBlockquoteCommand, - scribePluginCurlyQuotes, - scribePluginFormatterPlainTextConvertNewLinesToHtml, - scribePluginHeadingCommand, - scribePluginIntelligentUnlinkCommand, - scribePluginKeyboardShortcuts, - scribePluginLinkUI, - scribePluginSanitizer, - scribePluginSmartLists, - scribePluginToolbar, - scribePluginInlineObjects, - scribePluginBettyCropper, - scribePluginYoutube, - scribePluginEmbed, - scribePluginEmbedInstagram, - scribePluginOnionVideo, - scribePluginHr, - scribePluginPlaceholder, - linkFormatter, - onlyTrailingBrs, - pasteStripNewlines, - pasteStripNbsps, - pasteFromWord, - pasteSanitize, - removeAStyles, - stripBoldInHeadings, - scribePluginAnchor, - // scribe core - ourEnsureSelectableContainers, - enforcePElements, - filterForExport -) { - - 'use strict'; - - var defaults = { - multiline: true, - formatting: ['link', 'bold', 'italic', 'blockquote', 'heading', 'list', 'underline'], - link: { - domain: 'avclub.com' - }, - video: { - videoEmbedUrl: 'http://example.com?videoid=', - insertDialog: function() { }, - editDialog: function() { } - }, - image: { - insertDialog: function() { }, - editDialog: function() { } - } - }; - - function OnionEditor(element, options) { - options = $.extend(defaults, options); - $('.inline', element).attr('contenteditable', 'false'); - - var scribe = new Scribe(element, { allowBlockElements: options.multiline }); - - /* if a node running through the sanitizer passes this test, it won't get sanitized true */ - function skipSanitization(node) { - return ($(node).is('div.inline')); - }; - // HACK: we reset the default htmlFormatters 'normalize' because - // they don't quite work with what we're doing and there's - // apparently no other way to override/remove the offending ones. - scribe._htmlFormatterFactory.formatters['normalize'] = []; - if (scribe.allowsBlockElements()) { - scribe.use(enforcePElements()); - scribe.use(ourEnsureSelectableContainers({skipElement: skipSanitization})); - } - - // MO' HACKZ: We don't want to kill SPANS inside our inline divs - var insertHTMLCommandPatch = new scribe.api.CommandPatch('insertHTML'); - insertHTMLCommandPatch.execute = function (value) { - scribe.transactionManager.run(function () { - scribe.api.CommandPatch.prototype.execute.call(this, value); - - sanitize(scribe.el); - - function sanitize(parentNode) { - var treeWalker = document.createTreeWalker(parentNode, NodeFilter.SHOW_ELEMENT); - var node = treeWalker.firstChild(); - if (!node) { return; } - - do { - if (node.nodeName === 'SPAN' && node.className.indexOf('inline') === -1) { - element.unwrap(parentNode, node); - } else { - /** - * If the list item contains inline elements such as - * A, B, or I, Chrome will also append an inline style for - * `line-height` on those elements, so we remove it here. - */ - node.style.lineHeight = null; - - // There probably wasn’t a `style` attribute before, so - // remove it if it is now empty. - if (node.getAttribute('style') === '') { - node.removeAttribute('style'); - } - } - - // Sanitize children - sanitize(node); - } while ((node = treeWalker.nextSibling())); - } - }.bind(this)); - }; - scribe.commandPatches.insertHTML = insertHTMLCommandPatch; - - // ENDHACK - - if (options.placeholder) { - scribe.use(scribePluginPlaceholder(options.placeholder)); - } - - // For now, we need to patch some scribe commands, just in case. - var boldCommand = new scribe.api.CommandPatch('bold'); - boldCommand.execute = function (value) { - if (this.selection === undefined) { - document.execCommand(this.commandName, false, value || null); - } else { - scribe.transactionManager.run(function () { - document.execCommand(this.commandName, false, value || null); - }.bind(this)); - } - }; - scribe.commandPatches['bold'] = boldCommand; - - var italicCommand = new scribe.api.CommandPatch('italic'); - italicCommand.execute = function (value) { - if (this.selection === undefined) { - document.execCommand(this.commandName, false, value || null); - } else { - scribe.transactionManager.run(function () { - document.execCommand(this.commandName, false, value || null); - }.bind(this)); - } - }; - scribe.commandPatches['italic'] = italicCommand; - - var underlineCommand = new scribe.api.CommandPatch('underline'); - underlineCommand.execute = function (value) { - if (this.selection === undefined) { - document.execCommand(this.commandName, false, value || null); - } else { - scribe.transactionManager.run(function () { - document.execCommand(this.commandName, false, value || null); - }.bind(this)); - } - }; - scribe.commandPatches['underline'] = underlineCommand; - // End horrible patches - - var keyCommands = {}; - var ctrlKey = function (event) { return event.metaKey || event.ctrlKey; }; - - // Allowable Tags - var tags = {}; - - // Multiline - if (options.multiline) { - tags.p = {'id': true}; - tags.br = {}; - tags.hr = {}; - } else { - // tags.br = {}; - // scribe.use(onlyTrailingBrs()); - } - - // Bold - if (options.formatting.indexOf('bold') !== -1) { - keyCommands.bold = function (event) { return event.metaKey && event.keyCode === 66; }; // b - tags.b = {'id': true}; - } - - // Italics - if (options.formatting.indexOf('italic') !== -1) { - keyCommands.italic = function (event) { return event.metaKey && event.keyCode === 73; }; // i - tags.i = {'id': true}; - tags.em = {'id': true}; - } - - // Strike - if (options.formatting.indexOf('strike') !== -1) { - keyCommands.strikeThrough = function (event) { return event.altKey && event.shiftKey && event.keyCode === 83; }; // strike - tags.strike = {'id': true}; - } - - // Underline - if (options.formatting.indexOf('underline') !== -1) { - keyCommands.underline = function (event) { return event.metaKey && event.keyCode === 85; }; // u - tags.u = {'id': true}; - } - - // Remove formatting... - keyCommands.removeFormat = function (event) { return event.altKey && event.shiftKey && event.keyCode === 65; }; // a - - // Links - if (options.multiline && options.formatting.indexOf('link') !== -1) { - keyCommands.linkUI = function (event) { return event.metaKey && ! event.shiftKey && event.keyCode === 75; }; // k - keyCommands.unlink = function (event) { return event.metaKey && event.shiftKey && event.keyCode === 75; }; // k, - scribe.use(scribePluginIntelligentUnlinkCommand()); - scribe.use(scribePluginLinkUI(options.link)); - scribe.use(linkFormatter(options.link)); - tags.a = { href:true, target:true, id:true}; - } - - // Lists - if (options.multiline && options.formatting.indexOf('list') !== -1) { - keyCommands.insertUnorderedList = function (event) { return event.altKey && event.shiftKey && event.keyCode === 66; }; // b - keyCommands.insertOrderedList = function (event) { return event.altKey && event.shiftKey && event.keyCode === 78; }; // n - - scribe.use(scribePluginSmartLists()); - tags.ol = {id:true}; - tags.ul = {id:true}; - tags.li = {id:true}; - } - - //Blockquotes - if (options.multiline && options.formatting.indexOf('blockquote') !== -1) { - keyCommands.blockquote = function (event) { return event.altKey && event.shiftKey && event.keyCode === 87; }; // w - scribe.use(scribePluginBlockquoteCommand()); - tags.blockquote = {id:true}; - } - - // Headings - if (options.multiline && options.formatting.indexOf('heading') !== -1) { - keyCommands.h3 = function (event) { return ctrlKey(event) && event.keyCode === 50; }; // 2 - keyCommands.h4 = function (event) { return ctrlKey(event) && event.keyCode === 51; }; // 2 - scribe.use(scribePluginHeadingCommand(3)); - scribe.use(scribePluginHeadingCommand(4)); - tags.h3 = {id:true}; - tags.h4 = {id:true}; - } - - - // Inline Objects - if (options.multiline && options.inlineObjects) { - scribe.use(scribePluginInlineObjects(options.inlineObjects)); - - // Maybe make optionally load these similar to formatting. For now, it's an all or nothing. - - scribe.use(scribePluginBettyCropper(options.image)); - scribe.use(scribePluginYoutube()); - scribe.use(scribePluginEmbed()); - scribe.use(scribePluginEmbedInstagram()); - scribe.use(scribePluginHr()); - scribe.use(scribePluginAnchor()); - scribe.use(scribePluginOnionVideo(options.video)); - scribe.use(removeAStyles()); - scribe.use(stripBoldInHeadings()); - } - - scribe.use(scribePluginSanitizer({ - tags: tags, - skipSanitization: skipSanitization - })); - scribe.use(pasteFromWord()); - scribe.use(pasteSanitize()); - scribe.use(pasteStripNewlines()); - scribe.use(pasteStripNbsps()); - // Word count - - if (options.statsContainer) { - setInterval(function () { - $(options.statsContainer).html( - $(scribe.el).text().split(' ').length - ); - }, 3000); - } - - // Per-Element Export Filtering - scribe.use(filterForExport()); - - - /* This is necessary for a few dumb reasons. Scribe's transaction manager doesn't work when there - ins't a selection inside of the editor. This means any changes made when the editor ins't in focus, - like adding an image, stuff breaks. This works around that particular issue. - - I'm not really sure the right way to fix this or how to avoid this problem. - - The scroll stuff is a consequence of this. - */ - scribe.updateContents = function(fn, skipFormatters) { - // Default is to skipFormatters. Only place this needs to be set to false is when updating links. - // We want formatters to run on links. Embeds & other shit seem to get sanitized - // despite there being safegaurds for that. - if (typeof skipFormatters === 'undefined') { - skipFormatters = true; - } - scribe._skipFormatters = skipFormatters; - var scrollY = window.scrollY; - setTimeout(function() { - scribe.el.focus(); - setTimeout(function() { - scribe.transactionManager.run(fn); - window.scrollTo(0, scrollY); - - // This should notify any changes that happen outside of typing - scribe.trigger('content-changed'); - }, 20); - }, 20); - }; - - scribe.use(scribePluginCurlyQuotes()); - scribe.use(scribePluginKeyboardShortcuts(Object.freeze(keyCommands))); - - //TODO: kill this existing toolbar & replace w/ Medium style selection toolbar - if (options.multiline) { - scribe.use(scribePluginToolbar($('.document-tools .toolbar-contents', element.parentNode)[0])); - } - else { - $('.document-tools .toolbar-contents', element.parentNode).hide(); - } - - // a little hacky to prevent deletion of images and other inline elements via the backspace key. - scribe.el.addEventListener('keydown', function(event) { - if (event.keyCode === 8) { - // is the previous immediate child of editor an inline item? - var sel = new scribe.api.Selection(); - var prev = $(sel.selection.anchorNode).closest('.editor>*').prev(); - if (prev.hasClass('inline') - && sel.selection.anchorOffset === 0 - && sel.selection.isCollapsed) { - event.preventDefault(); - } - } - }); - - scribe.use(scribePluginFormatterPlainTextConvertNewLinesToHtml()); - - this.setChangeHandler = function(func) { - scribe.on('content-changed', func); - }; - - this.setContent = function(content) { - if (!content) { - content = '


    '; - } - scribe.setContent(content); - }; - - this.getContent = function() { - //todo: if multiline is false, only return contents of the paragraph - - var contents = scribe.getContent(); - - // Allow any plugins to clean up markup. Main use case is for embed plugin, atm. - return contents; - }; - - this.scribe = scribe; - return this; - } - - return OnionEditor; - -}); - - // wrap-end.frag - return require('onion-editor'); -})); \ No newline at end of file diff --git a/build/onion-editor.min.js b/build/onion-editor.min.js deleted file mode 100644 index 55b0707..0000000 --- a/build/onion-editor.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! onion-editor 2016-02-17 */ -!function(a,b){"function"==typeof define?define(b):"object"==typeof exports?module.exports=b():a.OnionEditor=b()}(this,function(){var a,b,c;return function(d){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(n=n.slice(0,n.length-1),a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,b){return function(){return n.apply(d,v.call(arguments,0).concat([a,b]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var b=r[a];delete r[a],t[a]=!0,m.apply(d,b)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,b,c,f){var h,k,l,m,n,s,u=[],v=typeof c;if(f=f||a,"undefined"===v||"function"===v){for(b=!b.length&&c.length?["require","exports","module"]:b,n=0;ne?0:e);++d2?a(c,17,b(arguments,2),null,d):a(c,1,null,null,d)}return c}),c("lodash-amd/modern/utilities/identity",[],function(){function a(a){return a}return a}),c("lodash-amd/modern/support",["./internals/isNative"],function(a){var b=/\bthis\b/,c={};return c.funcDecomp=!a(window.WinRTError)&&b.test(function(){return this}),c.funcNames="string"==typeof Function.name,c}),c("lodash-amd/modern/internals/baseCreateCallback",["../functions/bind","../utilities/identity","./setBindData","../support"],function(a,b,c,d){function e(e,i,j){if("function"!=typeof e)return b;if("undefined"==typeof i||!("prototype"in e))return e;var k=e.__bindData__;if("undefined"==typeof k&&(d.funcNames&&(k=!e.name),k=k||!d.funcDecomp,!k)){var l=h.call(e);d.funcNames||(k=!f.test(l)),k||(k=g.test(l),c(e,k))}if(k===!1||k!==!0&&1&k[1])return e;switch(j){case 1:return function(a){return e.call(i,a)};case 2:return function(a,b){return e.call(i,a,b)};case 3:return function(a,b,c){return e.call(i,a,b,c)};case 4:return function(a,b,c,d){return e.call(i,a,b,c,d)}}return a(e,i)}var f=/^\s*function[ \n\r\t]+\w/,g=/\bthis\b/,h=Function.prototype.toString;return e}),c("lodash-amd/modern/objects/forIn",["../internals/baseCreateCallback","../internals/objectTypes"],function(a,b){var c=function(c,d,e){var f,g=c,h=g;if(!g)return h;if(!b[typeof g])return h;d=d&&"undefined"==typeof e?d:a(d,e,3);for(f in g)if(d(g[f],f,c)===!1)return h;return h};return c}),c("lodash-amd/modern/internals/arrayPool",[],function(){var a=[];return a}),c("lodash-amd/modern/internals/getArray",["./arrayPool"],function(a){function b(){return a.pop()||[]}return b}),c("lodash-amd/modern/internals/maxPoolSize",[],function(){var a=40;return a}),c("lodash-amd/modern/internals/releaseArray",["./arrayPool","./maxPoolSize"],function(a,b){function c(c){c.length=0,a.length-1:void 0});return u.pop(),v.pop(),G&&(e(u),e(v)),w}var g="[object Arguments]",h="[object Array]",i="[object Boolean]",j="[object Date]",k="[object Number]",l="[object Object]",m="[object RegExp]",n="[object String]",o=Object.prototype,p=o.toString,q=o.hasOwnProperty;return f}),c("lodash-amd/modern/utilities/property",[],function(){function a(a){return function(b){return b[a]}}return a}),c("lodash-amd/modern/functions/createCallback",["../internals/baseCreateCallback","../internals/baseIsEqual","../objects/isObject","../objects/keys","../utilities/property"],function(a,b,c,d,e){function f(f,g,h){var i=typeof f;if(null==f||"function"==i)return a(f,g,h);if("object"!=i)return e(f);var j=d(f),k=j[0],l=f[k];return 1!=j.length||l!==l||c(l)?function(a){for(var c=j.length,d=!1;c--&&(d=b(a[j[c]],f[j[c]],null,!0)););return d}:function(a){var b=a[k];return l===b&&(0!==l||1/l==1/b)}}return f}),c("lodash-amd/modern/objects/forOwn",["../internals/baseCreateCallback","./keys","../internals/objectTypes"],function(a,b,c){var d=function(d,e,f){var g,h=d,i=h;if(!h)return i;if(!c[typeof h])return i;e=e&&"undefined"==typeof f?e:a(e,f,3);for(var j=-1,k=c[typeof h]&&b(h),l=k?k.length:0;++j0){var b=document.createElement(f.nodeName);a.forEach(function(a){b.appendChild(a)}),f.parentNode.insertBefore(b,f.nextElementSibling)}}if(this.queryState()){var d=new a.api.Selection,e=d.range,f=d.getContaining(function(a){return"OL"===a.nodeName||"UL"===a.nodeName}),g=d.getContaining(function(a){return"LI"===a.nodeName});a.transactionManager.run(function(){if(g){var b=new a.api.Node(g).nextAll();c(b),d.placeMarkers();var h=document.createElement("p");h.innerHTML=g.innerHTML,f.parentNode.insertBefore(h,f.nextElementSibling),g.parentNode.removeChild(g)}else{var i=Array.prototype.map.call(f.querySelectorAll("li"),function(a){return e.intersectsNode(a)&&a}).filter(function(a){return a}),j=i.slice(-1)[0],k=new a.api.Node(j).nextAll();c(k),d.placeMarkers();var l=document.createDocumentFragment();i.forEach(function(a){var b=document.createElement("p");b.innerHTML=a.innerHTML,l.appendChild(b)}),f.parentNode.insertBefore(l,f.nextElementSibling),i.forEach(function(a){a.parentNode.removeChild(a)})}0===f.childNodes.length&&f.parentNode.removeChild(f),d.selectMarkers()}.bind(this))}else a.api.Command.prototype.execute.call(this,b)},b.prototype.queryEnabled=function(){return a.api.Command.prototype.queryEnabled.call(this)&&a.allowsBlockElements()},a.commands.insertOrderedList=new b("insertOrderedList"),a.commands.insertUnorderedList=new b("insertUnorderedList")}}}),c("plugins/core/commands/outdent",[],function(){return function(){return function(a){var b=new a.api.Command("outdent");b.queryEnabled=function(){var b=new a.api.Selection,c=b.getContaining(function(a){return"UL"===a.nodeName||"OL"===a.nodeName});return a.api.Command.prototype.queryEnabled.call(this)&&a.allowsBlockElements()&&!c},a.commands.outdent=b}}}),c("plugins/core/commands/redo",[],function(){return function(){return function(a){var b=new a.api.Command("redo");b.execute=function(){var b=a.undoManager.redo();"undefined"!=typeof b&&a.restoreFromHistory(b)},b.queryEnabled=function(){return a.undoManager.position1},a.commands.undo=b,a.el.addEventListener("keydown",function(a){a.shiftKey||!a.metaKey&&!a.ctrlKey||90!==a.keyCode||(a.preventDefault(),b.execute())})}}}),c("plugins/core/commands",["./commands/indent","./commands/insert-list","./commands/outdent","./commands/redo","./commands/subscript","./commands/superscript","./commands/undo"],function(a,b,c,d,e,f,g){return{indent:a,insertList:b,outdent:c,redo:d,subscript:e,superscript:f,undo:g}}),c("lodash-amd/modern/internals/baseIndexOf",[],function(){function a(a,b,c){for(var d=(c||0)-1,e=a?a.length:0;++dh?f(0,k+h):h)||0,c(e)?l=j(e,g,h)>-1:"number"==typeof k?l=(d(e)?e.indexOf(g,h):j(e,g,h))>-1:b(e,function(a){return++i>=h?!(l=a===g):void 0}),l}var f=Math.max;return e}),c("lodash-amd/modern/objects/values",["./keys"],function(a){function b(b){for(var c=-1,d=a(b),e=d.length,f=Array(e);++c0;)a.insertBefore(b.childNodes[0],b);a.removeChild(b)}var e=["P","LI","DIV","BLOCKQUOTE","UL","OL","H1","H2","H3","H4","H5","H6"];return{isBlockElement:b,isSelectionMarkerNode:c,unwrap:d}}),c("scribe-common/src/node",[],function(){function a(a){return a.nodeType===Node.TEXT_NODE&&""===a.textContent}function b(a,b){return b.parentNode.insertBefore(a,b.nextSibling)}function c(a){return a.parentNode.removeChild(a)}return{isEmptyTextNode:a,insertAfter:b,removeNode:c}}),c("dom-observer",["lodash-amd/modern/arrays/flatten","lodash-amd/modern/collections/toArray","scribe-common/src/element","scribe-common/src/node"],function(a,b,c,d){function e(e,f){function g(e){var f=a(e.map(function(a){var c=b(a.addedNodes),d=b(a.removedNodes);return c.concat(d)})),g=f.filter(function(a){return!d.isEmptyTextNode(a)}).filter(function(a){return!c.isSelectionMarkerNode(a)});return g.length>0}var h=!1,i=new MutationObserver(function(a){if(!h&&g(a)){h=!0;try{f()}finally{setTimeout(function(){h=!1},0)}}});return i.observe(e,{attributes:!0,childList:!0,subtree:!0}),i}return e}),c("plugins/core/events",["lodash-amd/modern/collections/contains","../../dom-observer"],function(a,b){return function(){return function(c){function d(){var a=navigator.userAgent;return a.search("Safari")>=0&&a.search("Chrome")<0}var e=function(){setTimeout(function(){c.pushHistory()}.bind(c),0),c.el.removeEventListener("focus",e)}.bind(c);c.el.addEventListener("focus",e),c.el.addEventListener("focus",function(){function a(b){var c=document.createTreeWalker(b),d=c.currentNode;return c.firstChild()?"BR"===c.currentNode.nodeName?d:a(c.currentNode):c.currentNode}var b=new c.api.Selection;if(b.range){var d=c.allowsBlockElements()&&b.range.startContainer===c.el;if(d){var e=a(c.el.firstChild),f=b.range;f.setStart(e,0),f.setEnd(e,0),b.selection.removeAllRanges(),b.selection.addRange(f)}}}.bind(c));var f=function(){if(!c._skipFormatters){var a=new c.api.Selection,b=a.range,d=function(){b&&a.placeMarkers(),c.setHTML(c._htmlFormatterFactory.format(c.getHTML())),a.selectMarkers()}.bind(c);b?(c.undoManager.undo(),c.transactionManager.run(d)):d()}delete c._skipFormatters}.bind(c);b(c.el,f),c.allowsBlockElements()&&c.el.addEventListener("keydown",function(a){if(13===a.keyCode){var b=new c.api.Selection,d=b.range,e=b.getContaining(function(a){return/^(H[1-6])$/.test(a.nodeName)});if(e&&d.collapsed){var f=d.cloneRange();f.setEndAfter(e,0);var g=f.cloneContents();""===g.firstChild.textContent&&(a.preventDefault(),c.transactionManager.run(function(){var a=document.createElement("p"),c=document.createElement("br");a.appendChild(c),e.parentNode.insertBefore(a,e.nextElementSibling),d.setStart(a,0),d.setEnd(a,0),b.selection.removeAllRanges(),b.selection.addRange(d)}))}}}),c.allowsBlockElements()&&c.el.addEventListener("keydown",function(a){if(13===a.keyCode||8===a.keyCode){var b=new c.api.Selection,d=b.range;if(d.collapsed){var e=b.getContaining(function(a){return"LI"===a.nodeName});if(e&&""===e.textContent.trim()){a.preventDefault();var f=b.getContaining(function(a){return"UL"===a.nodeName||"OL"===a.nodeName}),g=c.getCommand("OL"===f.nodeName?"insertOrderedList":"insertUnorderedList");g.execute()}}}}),c.el.addEventListener("paste",function(b){if(!b.clipboardData||!a(b.clipboardData.types,"text/html")&&d()){var e=new c.api.Selection;e.placeMarkers();var f=document.createElement("div");document.body.appendChild(f),f.setAttribute("contenteditable",!0),f.focus(),setTimeout(function(){var a=f.innerHTML;f.parentNode.removeChild(f),e.selectMarkers(),c.el.focus(),a=c._htmlFormatterFactory.formatPaste(a),c.insertHTML(a)},1)}else if(b.preventDefault(),a(b.clipboardData.types,"text/html")){var g=b.clipboardData.getData("text/html");g=c._htmlFormatterFactory.formatPaste(g),c.insertHTML(g)}else c.insertPlainText(b.clipboardData.getData("text/plain"))})}}}),c("plugins/core/formatters/html/replace-nbsp-chars",[],function(){return function(){return function(a){var b=/(\s| )+/g;a.registerHTMLFormatter("export",function(a){return a.replace(b," ")})}}}),c("lodash-amd/modern/arrays/last",["../functions/createCallback","../internals/slice"],function(a,b){function c(c,f,g){var h=0,i=c?c.length:0;if("number"!=typeof f&&null!=f){var j=i;for(f=a(f,g,3);j--&&f(c[j],j,c);)h++}else if(h=f,null==h||g)return c?c[i-1]:d;return b(c,e(0,i-h))}var d,e=Math.max;return c}),c("plugins/core/formatters/html/enforce-p-elements",["lodash-amd/modern/arrays/last","scribe-common/src/element"],function(a,b){function c(c){var d=Array.prototype.reduce.call(c.childNodes,function(c,d){function e(){var a=[d];c.push(a)}var f=a(c);if(f){var g=b.isBlockElement(f[0]);g===b.isBlockElement(d)?f.push(d):e()}else e();return c},[]),e=d.filter(function(a){var c=b.isBlockElement(a[0]);return!c});e.forEach(function(a){var b=document.createElement("p");a[0].parentNode.insertBefore(b,a[0]),a.forEach(function(a){b.appendChild(a)})}),c._isWrapped=!0}function d(a){for(var b=document.createTreeWalker(a,NodeFilter.SHOW_ELEMENT),e=b.firstChild();e;){if("BLOCKQUOTE"===e.nodeName&&!e._isWrapped){c(e),d(a);break}e=b.nextSibling()}}return function(){return function(a){a.registerHTMLFormatter("normalize",function(a){var b=document.createElement("div");return b.innerHTML=a,c(b),d(b),b.innerHTML})}}}),c("plugins/core/formatters/html/ensure-selectable-containers",["scribe-common/src/element","lodash-amd/modern/collections/contains"],function(a,b){function c(e){function f(b){return 0===b.children.length||1===b.children.length&&a.isSelectionMarkerNode(b.children[0])}for(var g=e.firstElementChild;g;)a.isSelectionMarkerNode(g)||(f(g)&&""===g.textContent.trim()&&!b(d,g.nodeName)?g.appendChild(document.createElement("br")):g.children.length>0&&c(g)),g=g.nextElementSibling}var d=["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"];return function(){return function(a){a.registerHTMLFormatter("normalize",function(a){var b=document.createElement("div");return b.innerHTML=a,c(b),b.innerHTML})}}}),c("lodash-amd/modern/internals/htmlEscapes",[],function(){var a={"&":"&","<":"<",">":">",'"':""","'":"'"};return a}),c("lodash-amd/modern/internals/escapeHtmlChar",["./htmlEscapes"],function(a){function b(b){return a[b]}return b}),c("lodash-amd/modern/internals/reUnescapedHtml",["./htmlEscapes","../objects/keys"],function(a,b){var c=RegExp("["+b(a).join("")+"]","g");return c}),c("lodash-amd/modern/utilities/escape",["../internals/escapeHtmlChar","../objects/keys","../internals/reUnescapedHtml"],function(a,b,c){function d(b){return null==b?"":String(b).replace(c,a)}return d}),c("plugins/core/formatters/plain-text/escape-html-characters",["lodash-amd/modern/utilities/escape"],function(a){return function(){return function(b){b.registerPlainTextFormatter(a)}}}),c("plugins/core/inline-elements-mode",[],function(){function a(a){for(var b=document.createTreeWalker(a);b.nextNode();)if(b.currentNode&&(~["br"].indexOf(b.currentNode.nodeName.toLowerCase())||b.currentNode.length>0))return!0;return!1}return function(){return function(b){b.el.addEventListener("keydown",function(c){if(13===c.keyCode){var d=new b.api.Selection,e=d.range,f=d.getContaining(function(a){return"LI"===a.nodeName||/^(H[1-6])$/.test(a.nodeName)});f||(c.preventDefault(),b.transactionManager.run(function(){"BR"===b.el.lastChild.nodeName&&b.el.removeChild(b.el.lastChild);var c=document.createElement("br");e.insertNode(c),e.collapse(!1);var f=e.cloneRange();f.setEndAfter(b.el.lastChild,0);var g=f.cloneContents();if(!a(g)){var h=document.createElement("br");e.insertNode(h)}var i=e.cloneRange();i.setStartAfter(c,0),i.setEndAfter(c,0),d.selection.removeAllRanges(),d.selection.addRange(i)}))}}.bind(this)),""===b.getHTML().trim()&&b.setContent("")}}}),c("plugins/core/patches/commands/indent",[],function(){var a="\ufeff";return function(){return function(b){var c=new b.api.CommandPatch("indent");c.execute=function(c){b.transactionManager.run(function(){var d=new b.api.Selection,e=d.range,f="P"===e.commonAncestorContainer.nodeName&&"
    "===e.commonAncestorContainer.innerHTML;if(f){var g=document.createTextNode(a);e.insertNode(g),e.setStart(g,0),e.setEnd(g,0),d.selection.removeAllRanges(),d.selection.addRange(e)}b.api.CommandPatch.prototype.execute.call(this,c),d=new b.api.Selection;var h=d.getContaining(function(a){return"BLOCKQUOTE"===a.nodeName});h&&h.removeAttribute("style")}.bind(this))},b.commandPatches.indent=c}}}),c("plugins/core/patches/commands/insert-html",["scribe-common/src/element"],function(a){return function(){return function(b){var c=new b.api.CommandPatch("insertHTML");c.execute=function(c){b.transactionManager.run(function(){function d(b){var c=document.createTreeWalker(b,NodeFilter.SHOW_ELEMENT),e=c.firstChild();if(e)do"SPAN"===e.nodeName?a.unwrap(b,e):(e.style.lineHeight=null,""===e.getAttribute("style")&&e.removeAttribute("style")),d(e);while(e=c.nextSibling())}b.api.CommandPatch.prototype.execute.call(this,c),d(b.el)}.bind(this))},b.commandPatches.insertHTML=c}}}),c("plugins/core/patches/commands/insert-list",["scribe-common/src/element","scribe-common/src/node"],function(a,b){return function(){return function(c){var d=function(a){c.api.CommandPatch.call(this,a)};d.prototype=Object.create(c.api.CommandPatch.prototype),d.prototype.constructor=d,d.prototype.execute=function(d){c.transactionManager.run(function(){if(c.api.CommandPatch.prototype.execute.call(this,d),this.queryState()){var e=new c.api.Selection,f=e.getContaining(function(a){return"OL"===a.nodeName||"UL"===a.nodeName});if(f.nextElementSibling&&0===f.nextElementSibling.childNodes.length&&b.removeNode(f.nextElementSibling),f){var g=f.parentNode;g&&/^(H[1-6]|P)$/.test(g.nodeName)&&(e.placeMarkers(),b.insertAfter(f,g),e.selectMarkers(),2===g.childNodes.length&&b.isEmptyTextNode(g.firstChild)&&b.removeNode(g),0===g.childNodes.length&&b.removeNode(g))}var h=Array.prototype.slice.call(f.childNodes);h.forEach(function(b){var c=Array.prototype.slice.call(b.childNodes);c.forEach(function(c){if("SPAN"===c.nodeName){var d=c;a.unwrap(b,d)}else c.nodeType===Node.ELEMENT_NODE&&(c.style.lineHeight=null,""===c.getAttribute("style")&&c.removeAttribute("style"))})})}}.bind(this))},c.commandPatches.insertOrderedList=new d("insertOrderedList"),c.commandPatches.insertUnorderedList=new d("insertUnorderedList")}}}),c("plugins/core/patches/commands/outdent",[],function(){return function(){return function(a){var b=new a.api.CommandPatch("outdent");b.execute=function(){a.transactionManager.run(function(){var b=new a.api.Selection,c=b.range,d=b.getContaining(function(a){return"BLOCKQUOTE"===a.nodeName});if("BLOCKQUOTE"===c.commonAncestorContainer.nodeName){b.placeMarkers(),b.selectMarkers(!0);var e=c.cloneContents();d.parentNode.insertBefore(e,d),c.deleteContents(),b.selectMarkers(),""===d.textContent&&d.parentNode.removeChild(d)}else{var f=b.getContaining(function(a){return"P"===a.nodeName});if(f){var g=new a.api.Node(f).nextAll();if(g.length){var h=document.createElement(d.nodeName);g.forEach(function(a){h.appendChild(a)}),d.parentNode.insertBefore(h,d.nextElementSibling)}b.placeMarkers(),d.parentNode.insertBefore(f,d.nextElementSibling),b.selectMarkers(),""===d.innerHTML&&d.parentNode.removeChild(d)}else a.api.CommandPatch.prototype.execute.call(this)}}.bind(this))},a.commandPatches.outdent=b}}}),c("plugins/core/patches/commands/create-link",[],function(){return function(){return function(a){var b=new a.api.CommandPatch("createLink");a.commandPatches.createLink=b,b.execute=function(b){var c=new a.api.Selection;if(c.selection.isCollapsed){var d=document.createElement("a");d.setAttribute("href",b),d.textContent=b,c.range.insertNode(d);var e=document.createRange();e.setStartBefore(d),e.setEndAfter(d),c.selection.removeAllRanges(),c.selection.addRange(e)}else a.api.CommandPatch.prototype.execute.call(this,b)}}}}),c("plugins/core/patches/events",["scribe-common/src/element"],function(a){return function(){return function(b){b.allowsBlockElements()&&b.el.addEventListener("keyup",function(c){if(8===c.keyCode||46===c.keyCode){var d=new b.api.Selection,e=d.getContaining(function(a){return"P"===a.nodeName});e&&(b.undoManager.undo(),b.transactionManager.run(function(){d.placeMarkers();var b=Array.prototype.slice.call(e.childNodes);b.forEach(function(b){if("SPAN"===b.nodeName){var c=b;a.unwrap(e,c)}else b.nodeType===Node.ELEMENT_NODE&&(b.style.lineHeight=null,""===b.getAttribute("style")&&b.removeAttribute("style"))}),d.selectMarkers()}))}})}}}),c("plugins/core/patches",["./patches/commands/indent","./patches/commands/insert-html","./patches/commands/insert-list","./patches/commands/outdent","./patches/commands/create-link","./patches/events"],function(a,b,c,d,e,f){return{commands:{indent:a,insertHTML:b,insertList:c,outdent:d,createLink:e},events:f}}),c("plugins/core/set-root-p-element",[],function(){return function(){return function(a){""===a.getHTML().trim()&&a.setContent("


    ")}}}),c("api/command-patch",[],function(){return function(a){function b(a){this.commandName=a}return b.prototype.execute=function(b){a.transactionManager.run(function(){document.execCommand(this.commandName,!1,b||null)}.bind(this))},b.prototype.queryState=function(){return"insertOrderedList"===this.commandName||"insertUnorderedList"==this.commandName?!1:document.queryCommandState(this.commandName)},b.prototype.queryEnabled=function(){return document.queryCommandEnabled(this.commandName)},b}}),c("api/command",[],function(){return function(a){function b(b){this.commandName=b,this.patch=a.commandPatches[this.commandName]}return b.prototype.execute=function(b){this.patch?this.patch.execute(b):a.transactionManager.run(function(){document.execCommand(this.commandName,!1,b||null)}.bind(this))},b.prototype.queryState=function(){return this.patch?this.patch.queryState():document.queryCommandState(this.commandName)},b.prototype.queryEnabled=function(){return this.patch?this.patch.queryEnabled():document.queryCommandEnabled(this.commandName)},b}}),c("api/node",[],function(){function a(a){this.node=a}return a.prototype.getAncestor=function(a){var b=function(a){return a&&a.attributes&&a.attributes.getNamedItem("contenteditable")};if(!b(this.node))for(var c=this.node.parentNode;c&&!b(c);){if(a(c))return c; -c=c.parentNode}},a.prototype.nextAll=function(){for(var a=[],b=this.node.nextSibling;b;)a.push(b),b=b.nextSibling;return a},a}),c("api/selection",[],function(){return function(a){function b(){this.selection=window.getSelection(),this.selection.rangeCount&&(this.range=this.selection.getRangeAt(0))}return b.prototype.getContaining=function(b){if(this.range){var c=new a.api.Node(this.range.commonAncestorContainer),d=c.node&&c.node.attributes&&c.node.attributes.getNamedItem("contenteditable");return!d&&b(c.node)?c.node:c.getAncestor(b)}},b.prototype.placeMarkers=function(){if(this.range){var a=document.createElement("em");a.classList.add("scribe-marker");var b=document.createElement("em");b.classList.add("scribe-marker");var c=this.range.cloneRange();if(c.collapse(!1),c.insertNode(b),b.nextSibling&&b.nextSibling.nodeType===Node.TEXT_NODE&&""===b.nextSibling.data&&b.parentNode.removeChild(b.nextSibling),b.previousSibling&&b.previousSibling.nodeType===Node.TEXT_NODE&&""===b.previousSibling.data&&b.parentNode.removeChild(b.previousSibling),!this.selection.isCollapsed){var d=this.range.cloneRange();d.collapse(!0),d.insertNode(a),a.nextSibling&&a.nextSibling.nodeType===Node.TEXT_NODE&&""===a.nextSibling.data&&a.parentNode.removeChild(a.nextSibling),a.previousSibling&&a.previousSibling.nodeType===Node.TEXT_NODE&&""===a.previousSibling.data&&a.parentNode.removeChild(a.previousSibling)}this.selection.removeAllRanges(),this.selection.addRange(this.range)}},b.prototype.getMarkers=function(){return a.el.querySelectorAll("em.scribe-marker")},b.prototype.removeMarkers=function(){var a=this.getMarkers();Array.prototype.forEach.call(a,function(a){a.parentNode.removeChild(a)})},b.prototype.selectMarkers=function(a){var b=this.getMarkers();if(b.length){var c=document.createRange();c.setStartBefore(b[0]),b.length>=2?c.setEndAfter(b[1]):c.setEndAfter(b[0]),a||this.removeMarkers(),this.selection.removeAllRanges(),this.selection.addRange(c)}},b.prototype.isCaretOnNewLine=function(){var a=this.getContaining(function(a){return"P"===a.nodeName});if(a){var b=a.innerHTML.trim();return"P"===a.nodeName&&("
    "===b||""===b)}return!1},b}}),c("api/simple-command",[],function(){return function(a,b){function c(a,c){b.api.Command.call(this,a),this.nodeName=c}return c.prototype=Object.create(a.Command.prototype),c.prototype.constructor=c,c.prototype.queryState=function(){var a=new b.api.Selection;return b.api.Command.prototype.queryState.call(this)&&!!a.getContaining(function(a){return a.nodeName===this.nodeName}.bind(this))},c}}),c("api",["./api/command-patch","./api/command","./api/node","./api/selection","./api/simple-command"],function(a,b,c,d,e){return function(f){this.CommandPatch=a(f),this.Command=b(f),this.Node=c,this.Selection=d(f),this.SimpleCommand=e(this,f)}}),c("lodash-amd/modern/objects/assign",["../internals/baseCreateCallback","./keys","../internals/objectTypes"],function(a,b,c){var d=function(d,e,f){var g,h=d,i=h;if(!h)return i;var j=arguments,k=0,l="number"==typeof f?2:j.length;if(l>3&&"function"==typeof j[l-2])var m=a(j[--l-1],j[l--],2);else l>2&&"function"==typeof j[l-1]&&(m=j[--l]);for(;++kthis.maxStackSize;)this.stack.shift(),--this.position},b.prototype.undo=function(){return this.position>0?this.stack[--this.position]:void 0},b.prototype.redo=function(){return this.position$/,""))},p.prototype.getTextContent=function(){return this.el.textContent},p.prototype.pushHistory=function(){var a=this.undoManager.stack[this.undoManager.position],b=a&&a.replace(//g,"").replace(/<\/em>/g,"");if(!a||a&&this.getContent()!==b){var c=new this.api.Selection;c.placeMarkers();var d=this.getHTML();return c.removeMarkers(),this.undoManager.push(d),!0}return!1},p.prototype.getCommand=function(a){return this.commands[a]||this.commandPatches[a]||new this.api.Command(a)},p.prototype.restoreFromHistory=function(a){this.setHTML(a,!0);var b=new this.api.Selection;b.selectMarkers(),this.trigger("content-changed")},p.prototype.allowsBlockElements=function(){return this.options.allowBlockElements},p.prototype.setContent=function(a){this.allowsBlockElements()||(a+="
    "),this.setHTML(a),this.trigger("content-changed")},p.prototype.insertPlainText=function(a){this.insertHTML("

    "+this._plainTextFormatterFactory.format(a)+"

    ")},p.prototype.insertHTML=function(a){this.getCommand("insertHTML").execute(this._htmlFormatterFactory.format(a))},p.prototype.isDebugModeEnabled=function(){return this.options.debug},p.prototype.registerHTMLFormatter=function(a,b){this._htmlFormatterFactory.formatters[a].push(b)},p.prototype.registerPlainTextFormatter=function(a){this._plainTextFormatterFactory.formatters.push(a)},q.prototype.format=function(a){var b=this.formatters.reduce(function(a,b){return b(a)},a);return b},r.prototype=Object.create(q.prototype),r.prototype.constructor=r,r.prototype.format=function(a){var c=b([this.formatters.sanitize,this.formatters.normalize]),d=c.reduce(function(a,b){return b(a)},a);return d},r.prototype.formatPaste=function(a){return this.formatters.paste.reduce(function(a,b){return b(a)},a)},r.prototype.formatForExport=function(a){return this.formatters["export"].reduce(function(a,b){return b(a)},a)},p}),c("scribe-plugin-blockquote-command",[],function(){return function(){return function(a){var b=new a.api.SimpleCommand("blockquote","BLOCKQUOTE");b.execute=function(){var b=a.getCommand(this.queryState()?"outdent":"indent");b.execute()},b.queryEnabled=function(){var b=a.getCommand(this.queryState()?"outdent":"indent");return b.queryEnabled()},b.queryState=function(){var b=new a.api.Selection,c=b.getContaining(function(a){return"BLOCKQUOTE"===a.nodeName});return a.allowsBlockElements()&&!!c},a.commands.blockquote=b,a.allowsBlockElements()&&a.el.addEventListener("keydown",function(b){if(13===b.keyCode){var c=a.getCommand("blockquote");if(c.queryState()){var d=new a.api.Selection;d.isCaretOnNewLine()&&(b.preventDefault(),c.execute())}}})}}}),c("scribe-plugin-curly-quotes",[],function(){return function(){var a={34:'"',39:"'"},b="“",c="”",d="‘",e="’";return function(f){function g(g){var i,j=a[g.charCode];'"'===j?i=h()?c:b:"'"===j&&(i=h()?e:d),i&&(g.preventDefault(),f.transactionManager.run(function(){var a=k(i);l(a)}))}function h(){var a=i()||"";return j(a)}function i(){var a=new f.api.Selection,b=a.range.commonAncestorContainer.textContent;return b[a.range.startOffset-1]}function j(a){return/[^\s()]/.test(a)}function k(a){var b=document.createTextNode(a),c=new f.api.Selection;return c.range.deleteContents(),c.range.insertNode(b),b}function l(a){var b=document.createRange();b.setStartAfter(a),b.setEndAfter(a);var c=new f.api.Selection;c.selection.removeAllRanges(),c.selection.addRange(b)}function m(a){var f=document.createElement("div");return f.innerHTML=a,o(f,function(a){var f=a.split(/(<[^>]+?>)/);return f.map(function(a){return"<"===a[0]?a:a.replace(/([\s\S])?'([\s\S])?/g,n(d,e)).replace(/([\s\S])?"([\s\S])?/g,n(b,c))}).join("")}),f.innerHTML}function n(a,b){return function(c,d,e){d=d||"",e=e||"";var f=!d,g=!e,h=j(d),i=j(e);return h||f&&!i&&!g?d+b+e:d+a+e}}function o(a,b){var c=document.createTreeWalker(a,NodeFilter.SHOW_TEXT),d=c.firstChild();if(d)do d.data=b(d.data);while(d=c.nextSibling());return d}f.el.addEventListener("keypress",g),f.registerHTMLFormatter("normalize",m)}}}),c("scribe-plugin-formatter-plain-text-convert-new-lines-to-html",[],function(){return function(){return function(a){a.registerPlainTextFormatter(function(a){return a.replace(/\n([ \t]*\n)+/g,"

    ").replace(/\n/g,"
    ")})}}}),c("scribe-plugin-heading-command",[],function(){return function(a){return function(b){var c="",d="H"+a,e="h"+a,f=new b.api.Command("formatBlock");f.execute=function(){this.queryState()?b.api.Command.prototype.execute.call(this,"

    "):b.api.Command.prototype.execute.call(this,c)},f.queryState=function(){var a=new b.api.Selection;return!!a.getContaining(function(a){return a.nodeName===d})},f.queryEnabled=function(){var a=new b.api.Selection,c=a.getContaining(function(a){return"OL"===a.nodeName||"UL"===a.nodeName});return b.api.Command.prototype.queryEnabled.apply(this,arguments)&&b.allowsBlockElements()&&!c},b.commands[e]=f}}}),c("scribe-plugin-intelligent-unlink-command",[],function(){return function(){return function(a){var b=new a.api.Command("unlink");b.execute=function(){var b=new a.api.Selection;b.selection.isCollapsed?a.transactionManager.run(function(){var c=b.getContaining(function(a){return"A"===a.nodeName});c&&new a.api.Element(c.parentNode).unwrap(c)}.bind(this)):a.api.Command.prototype.execute.apply(this,arguments)},b.queryEnabled=function(){var b=new a.api.Selection;return b.selection.isCollapsed?!!b.getContaining(function(a){return"A"===a.nodeName}):a.api.Command.prototype.queryEnabled.apply(this,arguments)},a.commands.unlink=b}}}),c("lodash-amd/modern/internals/isNative",[],function(){function a(a){return"function"==typeof a&&d.test(a)}var b=Object.prototype,c=b.toString,d=RegExp("^"+String(c).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/toString| for [^\]]+/g,".*?")+"$");return a}),c("lodash-amd/modern/internals/objectTypes",[],function(){var a={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1};return a}),c("lodash-amd/modern/objects/isObject",["../internals/objectTypes"],function(a){function b(b){return!(!b||!a[typeof b])}return b}),c("lodash-amd/modern/utilities/noop",[],function(){function a(){}return a}),c("lodash-amd/modern/internals/baseCreate",["./isNative","../objects/isObject","../utilities/noop"],function(a,b,c){function d(a,c){return b(a)?e(a):{}}var e=a(e=Object.create)&&e;return e||(d=function(){function a(){}return function(c){if(b(c)){a.prototype=c;var d=new a;a.prototype=null}return d||window.Object()}}()),d}),c("lodash-amd/modern/internals/setBindData",["./isNative","../utilities/noop"],function(a,b){var c={configurable:!1,enumerable:!1,value:null,writable:!1},d=function(){try{var b={},c=a(c=Object.defineProperty)&&c,d=c(b,b,b)&&c}catch(e){}return d}(),e=d?function(a,b){c.value=b,d(a,"__bindData__",c)}:b;return e}),c("lodash-amd/modern/internals/slice",[],function(){function a(a,b,c){b||(b=0),"undefined"==typeof c&&(c=a?a.length:0);for(var d=-1,e=c-b||0,f=Array(0>e?0:e);++d2?a(c,17,b(arguments,2),null,d):a(c,1,null,null,d)}return c}),c("lodash-amd/modern/utilities/identity",[],function(){function a(a){return a}return a}),c("lodash-amd/modern/support",["./internals/isNative"],function(a){var b=/\bthis\b/,c={};return c.funcDecomp=!a(window.WinRTError)&&b.test(function(){return this}),c.funcNames="string"==typeof Function.name,c}),c("lodash-amd/modern/internals/baseCreateCallback",["../functions/bind","../utilities/identity","./setBindData","../support"],function(a,b,c,d){function e(e,i,j){if("function"!=typeof e)return b;if("undefined"==typeof i||!("prototype"in e))return e;var k=e.__bindData__;if("undefined"==typeof k&&(d.funcNames&&(k=!e.name),k=k||!d.funcDecomp,!k)){var l=h.call(e);d.funcNames||(k=!f.test(l)),k||(k=g.test(l),c(e,k))}if(k===!1||k!==!0&&1&k[1])return e;switch(j){case 1:return function(a){return e.call(i,a)};case 2:return function(a,b){return e.call(i,a,b)};case 3:return function(a,b,c){return e.call(i,a,b,c)};case 4:return function(a,b,c,d){return e.call(i,a,b,c,d)}}return a(e,i)}var f=/^\s*function[ \n\r\t]+\w/,g=/\bthis\b/,h=Function.prototype.toString;return e}),c("lodash-amd/modern/objects/forIn",["../internals/baseCreateCallback","../internals/objectTypes"],function(a,b){var c=function(c,d,e){var f,g=c,h=g;if(!g)return h;if(!b[typeof g])return h;d=d&&"undefined"==typeof e?d:a(d,e,3);for(f in g)if(d(g[f],f,c)===!1)return h;return h};return c}),c("lodash-amd/modern/internals/arrayPool",[],function(){var a=[];return a}),c("lodash-amd/modern/internals/getArray",["./arrayPool"],function(a){function b(){return a.pop()||[]}return b}),c("lodash-amd/modern/internals/maxPoolSize",[],function(){var a=40;return a}),c("lodash-amd/modern/internals/releaseArray",["./arrayPool","./maxPoolSize"],function(a,b){function c(c){c.length=0,a.length-1:void 0});return u.pop(),v.pop(),G&&(e(u),e(v)),w}var g="[object Arguments]",h="[object Array]",i="[object Boolean]",j="[object Date]",k="[object Number]",l="[object Object]",m="[object RegExp]",n="[object String]",o=Object.prototype,p=o.toString,q=o.hasOwnProperty;return f}),c("lodash-amd/modern/internals/shimKeys",["./objectTypes"],function(a){var b=Object.prototype,c=b.hasOwnProperty,d=function(b){var d,e=b,f=[];if(!e)return f;if(!a[typeof b])return f;for(d in e)c.call(e,d)&&f.push(d);return f};return d}),c("lodash-amd/modern/objects/keys",["../internals/isNative","./isObject","../internals/shimKeys"],function(a,b,c){var d=a(d=Object.keys)&&d,e=d?function(a){return b(a)?d(a):[]}:c;return e}),c("lodash-amd/modern/utilities/property",[],function(){function a(a){return function(b){return b[a]}}return a}),c("lodash-amd/modern/functions/createCallback",["../internals/baseCreateCallback","../internals/baseIsEqual","../objects/isObject","../objects/keys","../utilities/property"],function(a,b,c,d,e){function f(f,g,h){var i=typeof f;if(null==f||"function"==i)return a(f,g,h);if("object"!=i)return e(f);var j=d(f),k=j[0],l=f[k];return 1!=j.length||l!==l||c(l)?function(a){for(var c=j.length,d=!1;c--&&(d=b(a[j[c]],f[j[c]],null,!0)););return d}:function(a){var b=a[k];return l===b&&(0!==l||1/l==1/b)}}return f}),c("lodash-amd/modern/objects/forOwn",["../internals/baseCreateCallback","./keys","../internals/objectTypes"],function(a,b,c){var d=function(d,e,f){var g,h=d,i=h;if(!h)return i;if(!c[typeof h])return i;e=e&&"undefined"==typeof f?e:a(e,f,3);for(var j=-1,k=c[typeof h]&&b(h),l=k?k.length:0;++j-1||a.indexOf("/")>-1||a.indexOf("www")>-1||a.indexOf("http://")>-1||a.indexOf("https://")>-1||""===a?!1:!0}function e(a){c(),k.show(),a.addClass("link-edit"),setTimeout(function(){$("body, .link-tools .close").bind("click",f),l.val(a.attr("href").replace(m,"")),l[0].focus()},10)}function f(a){0===$(a.target).closest(".link-tools").length&&g()}function g(){b.updateContents(function(){var a=l.val();""===a?h():$(".link-edit, [href="+m+"]").attr("href",a).removeClass("link-edit")},!1),$("body, .link-tools .close").unbind("click"),k.hide()}function h(){var a=$(".link-edit, [href*="+m+"]");a[0].outerHTML=a[0].innerHTML}var i=b.el.parentNode,j=new b.api.Command("createLink"),k=$(".link-tools",i),l=$(".link-tools input",i),m="#replaceme",n=$(".search-results",k),o=a.searchHandler||function(a,b){};j.nodeName="A",j.execute=function(){var a=this,c=new b.api.Selection;c.range.collapsed||(b._skipFormatters=!0,b.api.SimpleCommand.prototype.execute.call(a,m),e($("a[href*="+m+"]")))},$(".remove",k).click(function(){l.val(""),g()}),$(".ok",k).click(g),n.click(function(a){var b=$(a.target).closest("a");1===b.length&&(a.preventDefault(),l.val(b.attr("href")),c())}),l.bind("keyup",c).bind("keydown",function(a){(13===a.keyCode||27===a.keyCode)&&g()}),b.el.addEventListener("click",function(a){var c=(new b.api.Selection,$(a.target).closest("a"));1===c.length&&(e(c),a.preventDefault())});var p;j.queryState=function(){var a=new b.api.Selection;return!!a.getContaining(function(a){return a.nodeName===this.nodeName}.bind(this))},b.commands.linkUI=j}}}),function(a,b){"function"==typeof c&&c.amd?c("html-janitor",b):a.amdWeb=b()}(this,function(){function a(a){this.config=a}function b(a){return-1!==e.indexOf(a.nodeName)}function c(a){return-1!==f.indexOf(a.nodeName)}function d(a){return document.createTreeWalker(a,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT)}var e=["P","LI","DIV"],f=["A","B","DEL","I","U"];return a.prototype.clean=function(a){var b=document.createElement("div");return b.innerHTML=a,this._sanitize(b),b.innerHTML},a.prototype._sanitize=function(a){var e=d(a),f=e.firstChild();if(f)do{var g=f.nodeName.toLowerCase(),h=this.config.tags[g];if(!f._sanitized){if(this.config.skipSanitization(f))return;if(f.nodeType!==Node.TEXT_NODE){if(f.nodeType===Node.COMMENT_NODE){a.removeChild(f),this._sanitize(a);break}var i,j=c(f);j&&(i=Array.prototype.some.call(f.childNodes,b));var k=j&&i,l=!!a.parentNode,m=b(a)&&b(f)&&l;if(!this.config.tags[g]||k||m){if("SCRIPT"!==f.nodeName&&"STYLE"!==f.nodeName)for(;f.childNodes.length>0;)a.insertBefore(f.childNodes[0],f);a.removeChild(f),this._sanitize(a);break}for(var n=0;ne?0:e);++d2?a(c,17,b(arguments,2),null,d):a(c,1,null,null,d)}return c}),c("lodash-amd/modern/utilities/identity",[],function(){function a(a){return a}return a}),c("lodash-amd/modern/support",["./internals/isNative"],function(a){var b=/\bthis\b/,c={};return c.funcDecomp=!a(window.WinRTError)&&b.test(function(){return this}),c.funcNames="string"==typeof Function.name,c}),c("lodash-amd/modern/internals/baseCreateCallback",["../functions/bind","../utilities/identity","./setBindData","../support"],function(a,b,c,d){function e(e,i,j){if("function"!=typeof e)return b;if("undefined"==typeof i||!("prototype"in e))return e;var k=e.__bindData__;if("undefined"==typeof k&&(d.funcNames&&(k=!e.name),k=k||!d.funcDecomp,!k)){var l=h.call(e);d.funcNames||(k=!f.test(l)),k||(k=g.test(l),c(e,k))}if(k===!1||k!==!0&&1&k[1])return e;switch(j){case 1:return function(a){return e.call(i,a)};case 2:return function(a,b){return e.call(i,a,b)};case 3:return function(a,b,c){return e.call(i,a,b,c)};case 4:return function(a,b,c,d){return e.call(i,a,b,c,d)}}return a(e,i)}var f=/^\s*function[ \n\r\t]+\w/,g=/\bthis\b/,h=Function.prototype.toString;return e}),c("lodash-amd/modern/internals/shimKeys",["./objectTypes"],function(a){var b=Object.prototype,c=b.hasOwnProperty,d=function(b){var d,e=b,f=[];if(!e)return f;if(!a[typeof b])return f;for(d in e)c.call(e,d)&&f.push(d);return f};return d}),c("lodash-amd/modern/objects/keys",["../internals/isNative","./isObject","../internals/shimKeys"],function(a,b,c){var d=a(d=Object.keys)&&d,e=d?function(a){return b(a)?d(a):[]}:c;return e}),c("lodash-amd/modern/objects/forOwn",["../internals/baseCreateCallback","./keys","../internals/objectTypes"],function(a,b,c){var d=function(d,e,f){var g,h=d,i=h;if(!h)return i;if(!c[typeof h])return i;e=e&&"undefined"==typeof f?e:a(e,f,3);for(var j=-1,k=c[typeof h]&&b(h),l=k?k.length:0;++j3&&"function"==typeof h[i-2])var j=a(h[--i-1],h[i--],2);else i>2&&"function"==typeof h[i-1]&&(j=h[--i]);for(var k=f(arguments,1,i),l=-1,m=c(),n=c();++l3&&"function"==typeof j[l-2])var m=a(j[--l-1],j[l--],2);else l>2&&"function"==typeof j[l-1]&&(m=j[--l]);for(;++ke?0:e);++d2?a(c,17,b(arguments,2),null,d):a(c,1,null,null,d)}return c}),c("lodash-amd/modern/utilities/identity",[],function(){function a(a){return a}return a}),c("lodash-amd/modern/support",["./internals/isNative"],function(a){var b=/\bthis\b/,c={};return c.funcDecomp=!a(window.WinRTError)&&b.test(function(){return this}),c.funcNames="string"==typeof Function.name,c}),c("lodash-amd/modern/internals/baseCreateCallback",["../functions/bind","../utilities/identity","./setBindData","../support"],function(a,b,c,d){function e(e,i,j){if("function"!=typeof e)return b;if("undefined"==typeof i||!("prototype"in e))return e;var k=e.__bindData__;if("undefined"==typeof k&&(d.funcNames&&(k=!e.name),k=k||!d.funcDecomp,!k)){var l=h.call(e);d.funcNames||(k=!f.test(l)),k||(k=g.test(l),c(e,k))}if(k===!1||k!==!0&&1&k[1])return e;switch(j){case 1:return function(a){return e.call(i,a)};case 2:return function(a,b){return e.call(i,a,b)};case 3:return function(a,b,c){return e.call(i,a,b,c)};case 4:return function(a,b,c,d){return e.call(i,a,b,c,d)}}return a(e,i)}var f=/^\s*function[ \n\r\t]+\w/,g=/\bthis\b/,h=Function.prototype.toString;return e}),c("lodash-amd/modern/internals/shimKeys",["./objectTypes"],function(a){var b=Object.prototype,c=b.hasOwnProperty,d=function(b){var d,e=b,f=[];if(!e)return f;if(!a[typeof b])return f;for(d in e)c.call(e,d)&&f.push(d);return f};return d}),c("lodash-amd/modern/objects/keys",["../internals/isNative","./isObject","../internals/shimKeys"],function(a,b,c){var d=a(d=Object.keys)&&d,e=d?function(a){return b(a)?d(a):[]}:c;return e}),c("lodash-amd/modern/objects/forOwn",["../internals/baseCreateCallback","./keys","../internals/objectTypes"],function(a,b,c){var d=function(d,e,f){var g,h=d,i=h;if(!h)return i;if(!c[typeof h])return i;e=e&&"undefined"==typeof f?e:a(e,f,3);for(var j=-1,k=c[typeof h]&&b(h),l=k?k.length:0;++jh?f(0,k+h):h)||0,c(e)?l=j(e,g,h)>-1:"number"==typeof k?l=(d(e)?e.indexOf(g,h):j(e,g,h))>-1:b(e,function(a){return++i>=h?!(l=a===g):void 0}),l}var f=Math.max;return e}),c("scribe-common/src/element",["lodash-amd/modern/collections/contains"],function(a){function b(b){return a(e,b.nodeName)}function c(a){return a.nodeType===Node.ELEMENT_NODE&&"scribe-marker"===a.className}function d(a,b){for(;b.childNodes.length>0;)a.insertBefore(b.childNodes[0],b);a.removeChild(b)}var e=["P","LI","DIV","BLOCKQUOTE","UL","OL","H1","H2","H3","H4","H5","H6"];return{isBlockElement:b,isSelectionMarkerNode:c,unwrap:d}}),c("scribe-plugin-smart-lists",["scribe-common/src/element"],function(a){return function(){function b(a){return"*"===a||"-"===a||"•"===a}function c(b){for(;b&&!a.isBlockElement(b);)b=b.parentNode;return b}var d={32:"Space",42:"*",45:"-",46:".",49:"1",8226:"•"};return function(a){function e(){var b,c=new a.api.Selection,d=c.selection.anchorNode;if(d.nodeType===Node.TEXT_NODE?b=d:d.firstChild.nodeType===Node.TEXT_NODE&&(b=d.firstChild),!b)throw new Error("Cannot empty non-text node!");var e=b.parentNode;b.previousSibling&&e.removeChild(b.previousSibling),e.removeChild(b)}function f(f){var j;g=h,h=i,i=d[f.charCode];var k=new a.api.Selection,l=k.range.commonAncestorContainer,m=c(l);if(m&&"P"===m.tagName){var n=b(l.textContent[0]);b(h)&&"Space"===i&&n&&(j="insertUnorderedList");var o="1."===[l.previousSibling&&l.previousSibling.textContent,l.textContent].join("").slice(0,2);"1"===g&&"."===h&&"Space"===i&&o&&(j="insertOrderedList")}j&&(f.preventDefault(),a.transactionManager.run(function(){a.getCommand(j).execute(),e()}))}var g,h,i;a.el.addEventListener("keypress",f)}}}),c("scribe-plugin-toolbar",[],function(){return function(a){return function(b){var c=a.querySelectorAll("[data-command-name]");Array.prototype.forEach.call(c,function(a){function c(){var c=b.getCommand(a.dataset.commandName),d=new b.api.Selection;d.range&&c.queryState(a.dataset.commandValue)?a.classList.add("active"):a.classList.remove("active"),d.range&&c.queryEnabled()?a.removeAttribute("disabled"):a.setAttribute("disabled","disabled")}a.addEventListener("click",function(){var c=b.getCommand(a.dataset.commandName);b.el.focus(),c.execute(a.dataset.commandValue)}),b.el.addEventListener("keyup",c),b.el.addEventListener("mouseup",c),b.el.addEventListener("focus",c),b.el.addEventListener("blur",c),b.on("content-changed",c)})}}}),c("scribe-plugin-inline-objects",[],function(){return function(a){return function(b){function c(a){n=a,$(".embed-button",q).click(d),$(".inline-tools button",q.parentNode).click(function(a){var b=$(a.target).data("commandName");"function"==typeof r[b]&&r[b]()})}function d(a){var c,d,g=$(".embed-fly-out").height(),h=$(".embed-button").height(),i=$(a.target).closest("button").data("commandName");"embed-before"===i?(c=o.position().top-g/2+h/2,d="before"):(c=o.position().top+o.height()+parseInt(o.css("margin-top"))-g/2+h/2,d="after"),$(".embed-fly-out",q).css({top:c,left:$(b.el).css("padding-left")}).show();var j=o;$(".embed-fly-out button").bind("click.inline",function(a){var b=$(a.target).closest("button").data("commandName");f(b,j,d)}),$("body").bind("click.inline",function(a){0===$(a.target).closest(".embed-tools").length&&e()})}function e(){$("body").unbind("click.inline"),$(".embed-fly-out button").unbind("click.inline"),$(".embed-fly-out").hide()}function f(a,c,d){b.trigger("inline:insert:"+a,[function(e){b.updateContents(function(){var f=$(m(n[a].template,$.extend(n[a].defaults,e)));$(c)[d](f),$(".inline",q).attr("contenteditable",!1),b.trigger("inline:insert:"+a+":done",[f])})}]),$(".embed-tools",q).removeClass("active")}function g(){$(".inline-tools").hide(),$(q).removeClass("inline-active")}function h(){var a=$(p),b=a.position();$(q).addClass("inline-active"),$(".inline-tools").attr("data-type",a.attr("data-type")),$(".inline-tools .size",q).html($(p).attr("data-size")),$(".inline-tools .crop",q).html($(p).attr("data-crop")),$(".inline-tools",q).css({top:b.top+parseInt(a.css("margin-top")),left:b.left+parseInt(a.css("margin-left"))+parseInt($(".editor",q).css("margin-left")),width:a.width(),height:a.height()}).show()}function i(){return n[$(p).attr("data-type")].size}function j(){return n[$(p).attr("data-type")].crop}function k(a,b){var c=$(p).attr("data-"+a),d=b.indexOf(c)+1;d>=b.length&&(d=0),l(a,b[d]),"function"==typeof window.picturefill&&setTimeout(function(){window.picturefill(p)},100)}function l(a,c){var d=$(p).attr("data-"+a);b.updateContents(function(){$(p).removeClass(a+"-"+d).addClass(a+"-"+c).attr("data-"+a,c),h()})}function m(a,b){for(var c in b)c&&(a=a.replace(new RegExp("{{"+c+"}}","g"),b[c]));return a}var n,o,p,q=b.el.parentNode;b.el.addEventListener("mouseover",function(a){var c=$(a.target).closest(".editor>*");1===c.length?($(".embed-tools",q).css({width:$(b.el).css("padding-left"),top:c.position().top+c.css("margin-top").replace(/[^-\d\.]/g,"")/2,height:c.height()}).addClass("active"),o=c):$(".embed-tools",q).removeClass("active")}),b.el.parentNode.addEventListener("mouseleave",function(a){g(),$(".embed-tools",q).removeClass("active")}),$(".embed-tools",q).mouseover(function(){$(".embed-tools",q).addClass("active")}),$(".editor",q).mouseover(function(a){var b=$(a.target).parents(".inline");1===b.length?(p=b[b.length-1],h()):g()});var r={inline_caption:function(){var a=prompt("Caption",$(".caption",p).html());(a||""===a)&&b.updateContents(function(){$(".caption",p).html(a)})},inline_size:function(){var a=i();k("size",a);var b=$(p).attr("data-crop"),c=j();-1===c.indexOf(b)&&l("crop",c[0])},inline_crop:function(){var a=n[$(p).attr("data-type")].crop;k("crop",a)},inline_up:function(){g();var a=$(p).prev()[0];if(a){var c=$(p).offset().top;b.updateContents(function(){$(p).after(a),setTimeout(function(){h();var a=$(p).offset().top;window.scrollBy(0,a-c)},0)})}},inline_down:function(){g();var a=$(p).next()[0];if(a){var c=$(p).offset().top;b.updateContents(function(){$(p).before(a),setTimeout(function(){h();var a=$(p).offset().top;window.scrollBy(0,a-c)},0)})}},inline_remove:function(){b.updateContents(function(){$(p).remove()}),g()},inline_edit:function(){b.trigger("inline:edit:"+$(p).attr("data-type"),[p,function(a,c){var d=$(a).attr("data-type");b.updateContents(function(){a.outerHTML=m(n[d].template,$.extend(n[d].defaults,c)),b.trigger("inline:edit:"+d+":done",[$(p)])})}])}};"string"==typeof a||a instanceof String?$.ajax(a,{success:c,dataType:"json"}):c(a)}}}),c("scribe-plugin-betty-cropper",[],function(){return function(a){return function(b){function c(b){a.insertDialog().then(function(a){var c;c=-1!==a.name.toUpperCase().indexOf("GIF")?"gif":"jpg",b({image_id:a.id,format:c}),window.picturefill&&setTimeout(function(){window.picturefill($("[data-image-id="+a.id+"]")[0])},100)},function(a){console.log(a)},function(a){console.log(a)})}function d(b,c){e=b.getAttribute("data-image-id");var d=$(".caption",b).html(),f=b.getAttribute("data-alt");a.editDialog({id:e,caption:d,alt:f}).then(function(a){null===a.id?$(b).remove():($(b).attr("data-image-id",a.id),$(b).attr("data-alt",a.alt),$(".caption",b).html(a.caption),window.picturefill&&setTimeout(function(){window.picturefill($("[data-image-id="+a.id+"]")[0])},100))})}var e;b.on("inline:edit:image",d),b.on("inline:insert:image",c)}}}),c("scribe-plugin-youtube",[],function(){return function(a){return function(a){function b(a){if(!a)return!1;var b=/^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/,c=a.match(b);return c&&11==c[7].length?c[7]:!1}function c(a){var c=prompt("Youtube URL:"),d=b(c);d&&a({youtube_id:d,caption:""})}function d(a,c){var d=prompt("Youtube URL:",$(a).attr("data-youtube-id")||""),e=b(d);e&&c(a,{youtube_id:e,caption:$(".caption",a).html()})}a.on("inline:insert:youtube",c),a.on("inline:edit:youtube",d)}}}),c("scribe-plugin-embed",[],function(){return function(a){return function(a){function b(a,b){h.val(unescape($(a).attr("data-code"))),i.val($(".caption",a).text());var c=$(a).attr("data-size")+"-"+$(a).attr("data-crop");$("[value="+c+"]",g).attr("checked",!0),g.modal("show"),j.click(function(){var c=h.val();""===c.trim()?k.show():(k.hide(),b(a,{code:c,caption:i.val(),escaped_code:escape(c),size:d(),crop:e()}),g.modal("hide"))}),g.modal("show")}function c(a){h.val(""),i.val(""),g.modal("show"),j.click(function(){var b=h.val();""===b.trim()?k.show():(k.hide(),a({code:b,caption:i.val(),escaped_code:escape(b),size:d(),crop:e()}),g.modal("hide"))})}function d(){var a="original";return l.length>0&&l.val().split("-")[0],a}function e(){var a="original";return l.length>0&&l.val().split("-")[1],a}a.on("inline:insert:embed",c),a.on("inline:edit:embed",b);var f=a.el.parentNode,g=$(".embed-modal",f),h=$(".embed-body",g),i=$(".embed-caption",g),j=$(".set-embed-button",g),k=$(".embed-error",g),l=$("[name=size]",g);g.on("hide.bs.modal",function(){j.unbind("click"),k.hide()})}}}),c("scribe-plugin-embed-instagram",[],function(){return function(a){return function(a){var b=$(a.el.parentNode).find(".embed-modal"),c=b.find(".embed-caption"),d=b.find(".embed-error"),e=b.find(".embed-body"),f=b.find(".set-embed-button");b.on("hide.bs.modal",function(){f.off("click"),d.hide()});var g=function(a){e.val(""),c.val(""),f.on("click",function(){var f=e.val();f.trim()?(d.hide(),a({html:escape(f),caption:c.val()}),b.modal("hide")):d.show()}),b.modal("show")},h=function(a,g){var h=$(a),i=h.children(".embed-container"),j=i.instagramEmbedProcessor().data("pluginInstagramEmbedProcessor");e.val(j.html()),c.val(h.children(".caption").text()),f.on("click",function(){var f=e.val();f.trim()?(d.hide(),g(a,{html:escape(f),caption:c.val()}),b.modal("hide")):d.show()}),b.modal("show")},i=function(a){var b=a.find(".embed-container"),c=b.instagramEmbedProcessor().data("pluginInstagramEmbedProcessor");c.prep()};a.on("inline:insert:embed-instagram",g),a.on("inline:insert:embed-instagram:done",i),a.on("inline:edit:embed-instagram",h),a.on("inline:edit:embed-instagram:done",i)}}}),c("scribe-plugin-onion-video",[],function(){return function(a){return function(b){function c(c){function d(){}function e(){}return a.insertDialog().then(function(d){b.updateContents(function(){c({embed_url:a.videoEmbedUrl,video_id:d.attrs.id})})},function(a){e(a)},function(a){d(a)})}function d(b,c){var d=$(b).attr("data-video-id")||$(b).attr("data-videoid");a.editDialog(d)}b.on("inline:edit:onion-video",d),b.on("inline:insert:onion-video",c)}}}),c("scribe-plugin-hr",[],function(){return function(a){return function(a){function b(a){a({})}a.on("inline:insert:hr",b)}}}),c("scribe-plugin-placeholder",[],function(){return function(a){return function(b){function c(){var c=b.getContent();"


    "===c||""===c?a.container.style.display="":a.container.style.display="none"}b.on("content-changed",c),a.container.innerHTML=a.text}}}),c("link-formatter",["scribe-common/src/element","lodash-amd/modern/collections/contains"],function(a,b){"use strict";return function(a){return function(b){function c(b){return b=b.trim(),b=e(b),a.domain&&(b=d(b,a.domain)),b}function d(a,b){var c=document.createElement("a");c.href=a;var d=c.hostname;return d.indexOf(b)>-1&&c.pathname.length>1&&(a=c.pathname+c.search+c.hash),a}function e(a){return"http://"!==a.substr(0,7)&&"https://"!==a.substr(0,8)&&"mailto:"!==a.substr(0,7)&&"/"!==a.substr(0,1)?-1!=a.indexOf("@")?"mailto:"+a:"http://"+a:a}function f(a){for(var b=a.firstElementChild;b;)"A"===b.nodeName?b.hasAttribute("href")&&b.setAttribute("href",c(b.getAttribute("href"))):b.children.length>0&&f(b),b=b.nextElementSibling}b.registerHTMLFormatter("sanitize",function(a){var b=document.createElement("div");return b.innerHTML=a,f(b),b.innerHTML})}}}),c("only-trailing-brs",[],function(){"use strict";return function(){return function(a){a.registerHTMLFormatter("normalize",function(a){return a.replace(/
    (.)/g," $1")})}}}),c("paste-strip-newlines",[],function(){"use strict";return function(){return function(a){a.registerHTMLFormatter("paste",function(a){return a.replace(/\n/g," ")})}}}),c("paste-strip-nbsps",[],function(){"use strict";return function(){return function(a){a.registerHTMLFormatter("paste",function(a){return a.replace(/ /g," ")}),a.registerHTMLFormatter("normalize",function(a){return a.replace(/ /g," ")})}}}),c("paste-from-word",["scribe-common/src/element"],function(a){"use strict";return function(){return function(b){function c(a){return/0&&d(c),"A"===c.nodeName&&(c.href||a.unwrap(b,c)),c=e}}b.registerHTMLFormatter("paste",function(a){if(!c(a))return a;a=a.replace(//gi,""),a=a.replace(/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,"");var b=document.createElement("div");return b.innerHTML=a,d(b),b.innerHTML})}}}),c("paste-sanitize",["scribe-common/src/element"],function(a){"use strict";return function(){return function(b){function c(b){for(var d=b.firstElementChild;d;){var e=d.nextElementSibling;d.children.length>0&&c(d),d.hasAttribute("style")&&d.removeAttribute("style"),"P"===d.nodeName&&""===d.textContent.trim()&&b.removeChild(d),"SPAN"===d.nodeName&&a.unwrap(b,d),d=e}}b.registerHTMLFormatter("paste",function(a){var b=document.createElement("div");b.innerHTML=a;var d=[].slice.call(b.childNodes);return d.forEach(function(a){3===a.nodeType&&""===a.textContent.trim()&&b.removeChild(a)}),c(b),b.innerHTML})}}}),c("remove-a-styles",["scribe-common/src/element"],function(a){"use strict";return function(){return function(a){function b(a){for(var c=a.firstElementChild;c;)"A"===c.nodeName&&c.hasAttribute("style")?c.removeAttribute("style"):c.children.length>0&&b(c),c=c.nextElementSibling}a.registerHTMLFormatter("sanitize",function(a){var c=document.createElement("div");return c.innerHTML=a,b(c),c.innerHTML})}}}),c("strip-bold-in-headings",["scribe-common/src/element"],function(a){"use strict";return function(){return function(b){function c(b){for(var d=b.firstElementChild;d;)"B"===d.nodeName&&/^(H[1-6])$/.test(b.nodeName)?a.unwrap(b,d):d.children.length>0&&c(d),d=d.nextElementSibling}b.registerHTMLFormatter("sanitize",function(a){var b=document.createElement("div");return b.innerHTML=a,c(b),b.innerHTML})}}}),c("scribe-plugin-anchor",[],function(){return function(a){return function(a){function b(a){return a.toString().toLowerCase().replace(/\s+/g,"-").replace(/[^\w\-]+/g,"").replace(/\-\-+/g,"-").trim()}var c=new a.api.Command("anchor");c.queryEnabled=function(){var b=new a.api.Selection,c=b.getContaining(function(a){return!0});return void 0!==c},c.queryState=function(b){var c=new a.api.Selection,d=c.getContaining(function(a){return 3!==a.nodeType});return void 0===d?!1:!!d.id},c.execute=function(){var c=new a.api.Selection;console.log(c);var d=c.getContaining(function(a){return 3!==a.nodeType});console.log(d),a.transactionManager.run(function(){d.id?d.removeAttribute("id"):d.id=b(d.textContent)}.bind(this))},a.commands.toggleAnchor=c}}}),c("our-ensure-selectable-containers",["scribe-common/src/element","lodash-amd/modern/collections/contains"],function(a,b){"use strict";function c(e,f){function g(b){return 0===b.children.length||1===b.children.length&&a.isSelectionMarkerNode(b.children[0])}for(var h=e.firstElementChild;h;)a.isSelectionMarkerNode(h)||(g(h)&&""===h.textContent.trim()&&!b(d,h.nodeName)&&a.isBlockElement(h)?h.appendChild(document.createElement("br")):h.children.length>0&&(f.skipElement&&f.skipElement&&f.skipElement(h)||c(h,f))),h=h.nextElementSibling}var d=["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"];return function(a){return function(b){b.registerHTMLFormatter("normalize",function(b){var d=document.createElement("div");return d.innerHTML=b,c(d,a),d.innerHTML})}}}),c("enforce-p-elements",["lodash-amd/modern/arrays/last","scribe-common/src/element"],function(a,b){"use strict";function c(c){var d=Array.prototype.reduce.call(c.childNodes,function(c,d){function e(){var a=[d];c.push(a)}var f=a(c);if(f){var g=b.isBlockElement(f[0]);g===b.isBlockElement(d)?f.push(d):e()}else e();return c},[]),e=d.filter(function(a){var c=b.isBlockElement(a[0]);return!c});e.forEach(function(a){var b=document.createElement("p");a[0].parentNode.insertBefore(b,a[0]),a.forEach(function(a){b.appendChild(a)})}),c._isWrapped=!0}function d(a){for(var b=document.createTreeWalker(a,NodeFilter.SHOW_ELEMENT),e=b.firstChild();e;){if("BLOCKQUOTE"===e.nodeName&&!e._isWrapped){c(e),d(a);break}e=b.nextSibling()}}return function(){return function(a){a.registerHTMLFormatter("normalize",function(a){var b=document.createElement("div");return b.innerHTML=a,c(b),d(b),b.innerHTML})}}}),c("filter-for-export",["scribe-common/src/element"],function(a){"user strict";return function(){return function(a){function b(a){for(var c=a.firstElementChild;c;)c.filterForExport&&c.filterForExport(),c.children.length>0&&b(c),c=c.nextElementSibling}a.registerHTMLFormatter("export",function(a){var c=document.createElement("div");return c.innerHTML=a,b(c),c.innerHTML})}}}),c("onion-editor",["scribe","scribe-plugin-blockquote-command","scribe-plugin-curly-quotes","scribe-plugin-formatter-plain-text-convert-new-lines-to-html","scribe-plugin-heading-command","scribe-plugin-intelligent-unlink-command","scribe-plugin-keyboard-shortcuts","scribe-plugin-link-ui","scribe-plugin-sanitizer","scribe-plugin-smart-lists","scribe-plugin-toolbar","scribe-plugin-inline-objects","scribe-plugin-betty-cropper","scribe-plugin-youtube","scribe-plugin-embed","scribe-plugin-embed-instagram","scribe-plugin-onion-video","scribe-plugin-hr","scribe-plugin-placeholder","link-formatter","only-trailing-brs","paste-strip-newlines","paste-strip-nbsps","paste-from-word","paste-sanitize","remove-a-styles","strip-bold-in-headings","scribe-plugin-anchor","our-ensure-selectable-containers","enforce-p-elements","filter-for-export"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E){"use strict";function F(u,F){function H(a){return $(a).is("div.inline")}F=$.extend(G,F),$(".inline",u).attr("contenteditable","false");var I=new a(u,{allowBlockElements:F.multiline});I._htmlFormatterFactory.formatters.normalize=[],I.allowsBlockElements()&&(I.use(D()),I.use(C({skipElement:H})));var J=new I.api.CommandPatch("insertHTML");J.execute=function(a){I.transactionManager.run(function(){function b(a){var c=document.createTreeWalker(a,NodeFilter.SHOW_ELEMENT),d=c.firstChild();if(d)do"SPAN"===d.nodeName&&-1===d.className.indexOf("inline")?u.unwrap(a,d):(d.style.lineHeight=null,""===d.getAttribute("style")&&d.removeAttribute("style")),b(d);while(d=c.nextSibling())}I.api.CommandPatch.prototype.execute.call(this,a),b(I.el)}.bind(this))},I.commandPatches.insertHTML=J,F.placeholder&&I.use(s(F.placeholder));var K=new I.api.CommandPatch("bold");K.execute=function(a){void 0===this.selection?document.execCommand(this.commandName,!1,a||null):I.transactionManager.run(function(){document.execCommand(this.commandName,!1,a||null)}.bind(this))},I.commandPatches.bold=K;var L=new I.api.CommandPatch("italic");L.execute=function(a){void 0===this.selection?document.execCommand(this.commandName,!1,a||null):I.transactionManager.run(function(){document.execCommand(this.commandName,!1,a||null)}.bind(this))},I.commandPatches.italic=L;var M=new I.api.CommandPatch("underline");M.execute=function(a){void 0===this.selection?document.execCommand(this.commandName,!1,a||null):I.transactionManager.run(function(){document.execCommand(this.commandName,!1,a||null)}.bind(this))},I.commandPatches.underline=M;var N={},O=function(a){return a.metaKey||a.ctrlKey},P={};return F.multiline&&(P.p={id:!0},P.br={},P.hr={}),-1!==F.formatting.indexOf("bold")&&(N.bold=function(a){return a.metaKey&&66===a.keyCode},P.b={id:!0}),-1!==F.formatting.indexOf("italic")&&(N.italic=function(a){return a.metaKey&&73===a.keyCode},P.i={id:!0},P.em={id:!0}),-1!==F.formatting.indexOf("strike")&&(N.strikeThrough=function(a){return a.altKey&&a.shiftKey&&83===a.keyCode},P.strike={id:!0}),-1!==F.formatting.indexOf("underline")&&(N.underline=function(a){return a.metaKey&&85===a.keyCode},P.u={id:!0}),N.removeFormat=function(a){return a.altKey&&a.shiftKey&&65===a.keyCode},F.multiline&&-1!==F.formatting.indexOf("link")&&(N.linkUI=function(a){return a.metaKey&&!a.shiftKey&&75===a.keyCode},N.unlink=function(a){return a.metaKey&&a.shiftKey&&75===a.keyCode},I.use(f()),I.use(h(F.link)),I.use(t(F.link)),P.a={href:!0,target:!0,id:!0}),F.multiline&&-1!==F.formatting.indexOf("list")&&(N.insertUnorderedList=function(a){return a.altKey&&a.shiftKey&&66===a.keyCode},N.insertOrderedList=function(a){return a.altKey&&a.shiftKey&&78===a.keyCode},I.use(j()),P.ol={id:!0},P.ul={id:!0},P.li={id:!0}),F.multiline&&-1!==F.formatting.indexOf("blockquote")&&(N.blockquote=function(a){return a.altKey&&a.shiftKey&&87===a.keyCode},I.use(b()),P.blockquote={id:!0}),F.multiline&&-1!==F.formatting.indexOf("heading")&&(N.h3=function(a){return O(a)&&50===a.keyCode},N.h4=function(a){return O(a)&&51===a.keyCode},I.use(e(3)),I.use(e(4)),P.h3={id:!0},P.h4={id:!0}),F.multiline&&F.inlineObjects&&(I.use(l(F.inlineObjects)),I.use(m(F.image)),I.use(n()),I.use(o()),I.use(p()),I.use(r()),I.use(B()),I.use(q(F.video)),I.use(z()),I.use(A())),I.use(i({tags:P,skipSanitization:H})),I.use(x()),I.use(y()),I.use(v()),I.use(w()),F.statsContainer&&setInterval(function(){$(F.statsContainer).html($(I.el).text().split(" ").length)},3e3),I.use(E()),I.updateContents=function(a,b){"undefined"==typeof b&&(b=!0),I._skipFormatters=b;var c=window.scrollY;setTimeout(function(){I.el.focus(),setTimeout(function(){I.transactionManager.run(a),window.scrollTo(0,c),I.trigger("content-changed")},20)},20)},I.use(c()),I.use(g(Object.freeze(N))),F.multiline?I.use(k($(".document-tools .toolbar-contents",u.parentNode)[0])):$(".document-tools .toolbar-contents",u.parentNode).hide(),I.el.addEventListener("keydown",function(a){if(8===a.keyCode){var b=new I.api.Selection,c=$(b.selection.anchorNode).closest(".editor>*").prev();c.hasClass("inline")&&0===b.selection.anchorOffset&&b.selection.isCollapsed&&a.preventDefault()}}),I.use(d()),this.setChangeHandler=function(a){I.on("content-changed",a)},this.setContent=function(a){a||(a="


    "),I.setContent(a)},this.getContent=function(){var a=I.getContent();return a},this.scribe=I,this}var G={multiline:!0,formatting:["link","bold","italic","blockquote","heading","list","underline"],link:{domain:"avclub.com"},video:{videoEmbedUrl:"http://example.com?videoid=",insertDialog:function(){},editDialog:function(){}},image:{insertDialog:function(){},editDialog:function(){}}};return F}),b("onion-editor")}); \ No newline at end of file diff --git a/src/less/editor/toolbar.less b/src/less/editor/toolbar.less index 7989d68..7011209 100644 --- a/src/less/editor/toolbar.less +++ b/src/less/editor/toolbar.less @@ -1,258 +1,234 @@ /* Menus + Buttons */ -.inline-active .toolbar { - /*display:none; */ -} - -.inline-active .inline-tools.toolbar{ - display:block; +.document-tools, embed-tools { + font-family: Helvetica, Arial, sans-serif; } -.toolbar-contents { - position: absolute; - z-index: 100; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: moz-none; - -ms-user-select: none; - user-select: none; - padding: 4px 4px; - font-size: 12px; - background-color: #EEEEEE; - border: 1px #DADADA solid; - border-radius: 4px; - width: auto; - white-space:nowrap; +.inline-active { + .inline-tools { + &.toolbar { + display:block; + } + } } -.toolbar button { - border:1px transparent solid; - color: #4A4A4A; +.toolbar { + button { background-clip: padding-box; - background-color:transparent; - border-radius:2px; - text-align:center; - display:inline-block; - line-height:25px; - font-size:14px; - width:25px; - height:25px; - cursor:pointer; - border-radius: 3px; -} - -.toolbar button.text { - font-size: 11px; - width: auto; - padding: 0 4px; -} -.toolbar button { - width:auto; - display:block; - font-size:14px; - width: 100%; - text-align:left; - padding:4px 8px; - height:auto; -} - - -.heading-icon { - font-family:Georgia; - text-align:center; - width: 20px; - font-size: 15px; - -} - -.heading-icon sub { - bottom:0px; -} - -.toolbar .hiddenbydefault { - display:none; -} -.toolbar:hover .hiddenbydefault { - display:block; -} - - -.toolbar button.active { + background-color: transparent; + border-radius: 2px; + border: 1px transparent solid; + color: #4A4A4A; + cursor: pointer; display:block; - background-color: #ddd; -} - -.toolbar button:hover { + font-size: 14px; + height: auto; + line-height: 25px; + padding: 4px 8px; + text-align: left; + width: auto; + [class^="icon-"], + [class*=" icon-"] { + display: inline-block; + text-align:center; + width: 15px; + } + &.text { + font-size: 11px; + padding: 0 4px; + width: auto; + } + &.active { + background-color: #ddd; + display: block; + } + } + .hiddenbydefault { + display: none; + } + .btn-label { + display: none; + } + .link-tools { + .toggle-filter { + background: rgb(200, 200, 200); + display: inline-block; + margin: 9px 5px; + &.active { + background: rgb(150, 150, 150); + } + } + } + &:hover { background-color: #ccc; - -} -.toolbar button:hover.active { - display:block; - background-color: #333; - color:#f1f1f1; -} - -.toolbar .btn-label { - display:none; -} - -.toolbar:hover .btn-label { - display:inline; - margin-left: 10px; - font-size: 12px; - line-height: 16px; -} - -.toolbar.link-tools .toggle-filter { - background: rgb(200, 200, 200); - display: inline-block; - margin: 9px 5px; + .hiddenbydefault { + display: block; + } + .btn-label { + display:inline; + font-size: 12px; + line-height: 16px; + margin-left: 10px; + } + &.active { + background-color: #333; + color: #f1f1f1; + display: block; + } + } } -.toolbar.link-tools .toggle-filter.active { - background: rgb(150, 150, 150); +.toolbar-contents { + -khtml-user-select: none; + -moz-user-select: moz-none; + -ms-user-select: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + background-color: #EEEEEE; + border-radius: 4px; + border: 1px #DADADA solid; + font-size: 12px; + padding: 4px 4px; + position: absolute; + user-select: none; + white-space: nowrap; + width: auto; } -.document-tools>.toolbar-contents { - top: 100px; - position:fixed; - left:50%; - text-align:center; - margin-left:-480px; +.heading-icon { + font-family: Georgia; + font-size: 15px; + text-align: center; + width: 20px; + sub { + bottom: 0px; + } +} + +.document-tools { + z-index: 1; + .toolbar-contents { display: block; + left: 50%; + margin-left: -480px; opacity: 1; + position: fixed; + text-align: center; + top: 100px; + .primary { + background-color: #EEEEEE; + color: #4A4A4A; + float: right; + font-size: 14px; + position: relative; + z-index: 100; + } + } } +/* Inline Tools */ - -.toolbar button [class^="icon-"], .toolbar button [class*=" icon-"] { - width: 15px; - display: inline-block; - text-align:center; -} - -.toolbar-contents .primary { - font-size: 14px; - color: #4A4A4A; - float:right; - position:relative; - z-index:100; - background-color: #EEEEEE; -} - - - -/* inline tools */ .inline-tools { - position:absolute; - display:none; - /*background-color: rgba(200,200,200,.5);*/ - z-index: 100; -} -.inline-tools button { - display:inline-block; - width:auto; -} - -.inline-tools span.inline-attribute { - font-size: 11px; - text-transform:uppercase; -} - -.inline-tools .remove { - position: absolute; - right: 10px; - bottom: 10px; - background-color: #930900; + display: none; + position: absolute; + z-index: 100; + button { + display: inline-block; + width: auto; + } + span { + &.inline-attribute { + font-size: 11px; + text-transform:uppercase; + } + } + .edit { + background-color: #333; border-radius: 4px; -} -.inline-tools .edit button, -.inline-tools .remove button { + bottom: 10px; color: white; -} - -.inline-tools .remove button:hover { - background-color: #C70A00; -} - -.inline-tools .edit { - position: absolute; left: 10px; - bottom: 10px; + position: absolute; + button:hover { + background-color: #444; + } + } + .remove { + background-color: #930900; border-radius: 4px; - background-color: #333; - color: white; -} - -.inline-tools .edit button:hover { - background-color: #444; -} - -.inline-tools .toolbar-contents { - margin-top: 20px; + bottom: 10px; + position: absolute; + right: 10px; + button:hover { + background-color: #C70A00; + } + } + .edit, + .remove { + button { + color: white; + } + } + .toolbar-contents { left: 50%; margin-left: -96px; -} + margin-top: 20px; + } + + /* Customize toolbar for various object types */ - -/* Customize toolbar for various object types */ - -.inline-tools[data-type="hr"] { + [data-type="hr"] { .edit, .size, .crop { - display:none; + display: none; } -} + } -/* size and crop are handled inside of the embed modal, for simplictiy */ -.inline-tools[data-type="embed"] { + /* size and crop are handled inside of the embed modal, for simplictiy */ + + [data-type="embed"] { .size, .crop { - display:none; + display: none; } + } } - span.highlight { - background-color: #EC7000; + background-color: #EC7000; } .find-replace-dialog { - position:fixed; - width: 820px; - margin: 0 auto; - height: 56px; - top:0px; - left: 50%; - margin-left: -410px; - background-color:#EEEEEE; - border:1px #DADADA solid; - border-radius: 4px; - z-index:10000; - padding: 10px 20px; - box-shadow: 1px 3px 5px 0px rgba(50, 50, 50, 0.3); -} -.find-replace-dialog .close { - -} - -.find-replace-dialog>.btn { + background-color: #EEEEEE; + border-radius: 4px; + border:1px #DADADA solid; + box-shadow: 1px 3px 5px 0px rgba(50, 50, 50, 0.3); + height: 56px; + left: 50%; + margin-left: -410px; + margin: 0 auto; + padding: 10px 20px; + position: fixed; + top: 0px; + width: 820px; + z-index:10000; + >.btn { margin-top:-3px; -} - -.find-replace-dialog input { - width: 200px; + } + input { font-size: 14px; padding: 3px; + width: 200px; + } } -.editor span.searchResult { - background-color: #FFBB03; -} -.editor [contenteditable=false] span.searchResult { - background-color:transparent; +.editor { + span { + &.searchResult { + background-color: #FFBB03; + } + } + [contenteditable=false] span.searchResult { + background-color: transparent; + } } -.document-tools, embed-tools { - font-family: Helvetica, Arial, sans-serif; -}