diff --git a/.gitignore b/.gitignore
index cc866ef02..3a9f4892a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,5 @@ bower_components
.DS_Store
# Builds
+dist/
export.sh
diff --git a/README.md b/README.md
index 1eb8a2d91..77a758000 100644
--- a/README.md
+++ b/README.md
@@ -3,25 +3,24 @@
A modern, minimalist WYSIWYG editor. (**[Demo](https://rawgit.com/ContentKit/content-kit-editor/master/demo/index.html)**)
![screenshot]
-(https://rawgit.com/ContentKit/content-kit-editor/master/demo/screenshot.png)
+(https://rawgit.com/ContentKit/content-kit-editor/master/screenshot.png)
-*ContentKit-Editor is under active development*
+*ContentKit-Editor is currently under heavy active development. API subject to change.*
----
-
-## About ContentKit
+## Building
+1. Install dependencies: `npm install`
+2. Build: `gulp build`
-ContentKit is a suite of tools used to create, parse, and render user generated content. ContentKit's core centers around parsing content into its own simple JSON format. By storing a set of simple data, you are no longer bound to the originally generated HTML. By separating the data from the presentation, you can render the same content in various different formats, layouts, and on various different platforms.
+## Playing
+1. Start the server: `npm start`
+2. Navigate to the demo at (http://localhost:5000)
+```
-#### Use-case example:
-You are developing a blogging platform. You allow authors to create posts using a ContentKit's WYSIWYG editor. ContentKit parses the post into its JSON format. Readers then visit the blog on the web and ContentKit renders the post's JSON data back to HTML for display on the page. Next, you decide to build mobile apps for your blogging platform. ContentKit renders the content natively on iOS and Android. Later, your power users want to use Markdown or HTML code to write their blogs posts. ContentKit can parse it while also cleaning up tags you may not want to allow. Later, you redesign the blog. Your original content is intact and is easily able to be rendered into your ambitious new layout.
+## Testing
+`gulp test`
-#### Current Tools:
-- An HTML parser/renderer to transform content to and from JSON/HTML [(ContentKit-Compiler)](https://github.com/ContentKit/content-kit-compiler)
-- A simple, modern WYSIWYG editor to generate content on the web [(ContentKit-Editor)](https://github.com/ContentKit/content-kit-editor)
+## Dev tips
+- `gulp watch` to auto build/test as you save files
+- Running the server is only necessary if you want image uploads and embeds. You can just open demo/index.html
-#### Future Tools:
-- A HTML renderer for Ruby, to pre-render HTML server-side
-- An iOS renderer to display content natively using `UILabel`/`NSAttributedString` [(reference)](https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/NSAttributedString_Class/Reference/Reference.html)
-- An Android renderer for to display content natively using `TextField`/`Spannable` [(reference)](http://developer.android.com/reference/android/text/Spannable.html)
-- A Markdown parser/renderer to transform content to and from JSON/Markdown
+---
diff --git a/demo/index.html b/demo/index.html
index 432332109..9456b7ad2 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -5,7 +5,7 @@
ContentKit Editor
-
+
@@ -70,20 +70,13 @@ Keyboard shortcuts:
-
-
+
+
diff --git a/dist/content-kit-editor.css b/dist/content-kit-editor.css
deleted file mode 100755
index 4d195959e..000000000
--- a/dist/content-kit-editor.css
+++ /dev/null
@@ -1,535 +0,0 @@
-/**
- * Editor
- */
-.ck-editor {
- font-family: Georgia, serif;
- margin: 1em 0;
- color: #454545;
- /*
- Chrome bug adds inline styles when backspacing to join 2 blocks.
- Fix: Apply font styles to parent element, or use % for font-size, line-height.
- http://stackoverflow.com/questions/15015019/prevent-chrome-from-wrapping-contents-of-joined-p-with-a-span
- */
- font-size: 120%;
- line-height: 160%;
-}
-.ck-editor:focus {
- outline: none;
-}
-.ck-editor:empty:before {
- content: attr(data-placeholder);
- color: #bbb;
-}
-.ck-editor a {
- color: #0b8bff;
-}
-.ck-editor blockquote {
- border-left: 4px solid #0b8bff;
- margin: 1em 0 1em -1.2em;
- padding-left: 1.05em;
- color: #a0a0a0;
-}
-.ck-editor img {
- display: block;
- max-width: 100%;
- margin: 0 auto;
-}
-.ck-editor div,
-.ck-editor iframe {
- max-width: 100%;
-}
-/**
- * Toolbar
- */
-.ck-toolbar {
- text-align: center;
- position: absolute;
- z-index: 1;
- background: -moz-linear-gradient(top, rgba(74, 74, 74, 0.97) 0%, #2b2b2b 100%);
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(74, 74, 74, 0.97)), color-stop(100%, #2b2b2b));
- background: -webkit-linear-gradient(top, rgba(74, 74, 74, 0.97) 0%, #2b2b2b 100%);
- background: -o-linear-gradient(top, rgba(74, 74, 74, 0.97) 0%, #2b2b2b 100%);
- background: -ms-linear-gradient(top, rgba(74, 74, 74, 0.97) 0%, #2b2b2b 100%);
- background: linear-gradient(to bottom, rgba(74, 74, 74, 0.97) 0%, #2b2b2b 100%);
- box-shadow: 0 1px 3px -1px rgba(0, 0, 0, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.12), inset 1px 1px 0 #282828, inset -1px -1px 0 #282828;
- border-radius: 3px;
- transition: left 0.1s, top 0.1s;
- margin-bottom: 0.45em;
-}
-.ck-toolbar:after {
- content: '';
- position: absolute;
- left: 50%;
- width: 0;
- height: 0;
- border-left: 0.45em solid transparent;
- border-right: 0.45em solid transparent;
- border-top: 0.45em solid #2b2b2b;
- bottom: -0.4em;
- margin: 0 0 0 -0.45em;
-}
-.ck-toolbar.right {
- margin: 0 0 0 0.5em;
-}
-.ck-toolbar.right:after {
- left: -0.4em;
- top: 50%;
- bottom: auto;
- margin: -0.45em 0 0 0;
- border-top: 0.45em solid transparent;
- border-bottom: 0.45em solid transparent;
- border-right: 0.45em solid #3d3d3d;
- border-left: none;
-}
-.ck-toolbar,
-.ck-toolbar-prompt {
- -webkit-animation: pop-up 0.25s;
- animation: pop-up 0.25s;
-}
-.ck-toolbar.right,
-.ck-toolbar.right .ck-toolbar-prompt {
- -webkit-animation: pop-right 0.25s;
- animation: pop-right 0.25s;
-}
-.ck-toolbar-buttons {
- border-radius: 5px;
- overflow: hidden;
-}
-.ck-toolbar-btn {
- display: inline-block;
- background-color: transparent;
- border: none;
- outline: none;
- color: #FFF;
- font-size: 18px;
- padding: 0;
- margin: 0;
- width: 48px;
- height: 44px;
- line-height: 42px;
- cursor: pointer;
- transition: background-color 0.1s linear;
- text-shadow: 0 1px 1px rgba(0, 0, 0, 0.65);
- -moz-user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
-}
-.ck-toolbar-btn:hover {
- background-color: rgba(43, 43, 43, 0.4);
-}
-.ck-toolbar-btn:active {
- background-color: rgba(43, 43, 43, 0.65);
-}
-.ck-toolbar-btn:active,
-.ck-toolbar-btn.active {
- color: #3ea3ff;
-}
-.ck-toolbar-prompt {
- display: none;
-}
-.ck-toolbar-prompt input {
- background: none;
- border: none;
- color: #f5f5f5;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
- padding: 0 16px;
- width: 288px;
- height: 44px;
- line-height: 1em;
-}
-.ck-toolbar-prompt input:focus {
- outline: none;
-}
-.ck-toolbar-prompt input::-ms-clear {
- display: none;
-}
-.ck-toolbar-prompt ::-webkit-input-placeholder {
- background-color: #a2a2a2;
- background-image: -webkit-gradient(linear, left top, right top, color-stop(0, #a2a2a2), color-stop(0.4, #a2a2a2), color-stop(0.5, #ffffff), color-stop(0.6, #a2a2a2), color-stop(1, #a2a2a2));
- background-repeat: no-repeat;
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- -webkit-animation: textGlimmer 4s infinite;
-}
-.ck-editor-hilite {
- position: absolute;
- z-index: -1;
- background-color: rgba(62, 163, 255, 0.05);
- border-bottom: 2px dotted #3ea3ff;
-}
-/**
- * Tooltip
- */
-.ck-tooltip {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 0.7em;
- white-space: nowrap;
- position: absolute;
- background-color: rgba(43, 43, 43, 0.9);
- border-radius: 3px;
- line-height: 1em;
- padding: 0.7em 0.9em;
- color: #FFF;
- -webkit-animation: fadeIn 0.2s;
- animation: fadeIn 0.2s;
-}
-.ck-tooltip:before {
- content: '';
- position: absolute;
- left: 50%;
- width: 0;
- height: 0;
- border-left: 0.4em solid transparent;
- border-right: 0.4em solid transparent;
- border-bottom: 0.4em solid rgba(43, 43, 43, 0.9);
- top: -0.4em;
- margin-left: -0.4em;
-}
-.ck-tooltip:after {
- /* help keeps mouseover state when moving from link to tooltip */
- content: '';
- position: absolute;
- left: 0;
- right: 0;
- top: -0.4em;
- height: 0.4em;
-}
-.ck-tooltip a {
- color: #FFF;
- text-decoration: none;
-}
-.ck-tooltip a:hover {
- text-decoration: underline;
-}
-/**
- * Embeds
- */
-.ck-embed-intent-btn {
- position: absolute;
- display: block;
- background: none;
- border: none;
- outline: none;
- margin: 0 0.4em 0 0;
- padding: 0;
- width: 1em;
- height: 1em;
- border: 2px solid #ccc;
- border-radius: 100%;
- color: #ccc;
- text-align: center;
- font-size: 2em;
- line-height: 0.7em;
- cursor: pointer;
- transition: color 0.1s, border-color 0.1s, transform 0.35s;
- -webkit-animation: pop-out 0.25s;
- animation: pop-out 0.25s;
-}
-.ck-embed-intent-btn:hover {
- color: #999;
- border-color: #999;
-}
-.ck-embed-intent-btn:active {
- color: #666;
- border-color: #666;
- transition: none;
-}
-.ck-embed-intent-btn:before {
- content: '+';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-}
-.ck-embed-intent-btn.activated {
- -webkit-transform: rotate(-135deg);
- transform: rotate(-135deg);
-}
-.ck-embed-loading {
- position: absolute;
- width: 1.5em;
- height: 1.5em;
- border-radius: 50%;
- border: 2px solid #ddd;
- border-top-color: #3ea3ff;
- animation: spin .5s linear infinite;
- -webkit-animation: spin .5s linear infinite;
-}
-.ck-file-input {
- display: none;
-}
-.ck-embed {
- text-align: center;
- margin: 1em 0;
- border: 2px solid transparent;
- border-radius: 2px;
-}
-.ck-embed.selected {
- border-color: #3ea3ff;
-}
-.ck-embed iframe {
- margin: 0 auto !important;
-}
-.ck-embed figure {
- position: relative;
- margin: 0;
-}
-.ck-embed figcaption {
- color: #999;
- font-size: 0.7em;
- line-height: 1.3em;
- font-style: italic;
- margin: 10px 0;
-}
-.ck-embed figcaption a {
- color: #999;
- text-decoration: underline;
-}
-.ck-embed figcaption a:hover {
- color: #666;
-}
-@media screen and (min-width: 1080px) {
- .ck-embed figcaption {
- position: absolute;
- top: 0;
- right: -130px;
- width: 130px;
- text-align: left;
- margin: 0;
- padding-left: 2em;
- }
-}
-.ck-video-container {
- position: relative;
- overflow: hidden;
- padding-top: 56.25%;
-}
-.ck-video-container iframe,
-.ck-video-container object,
-.ck-video-container embed {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-.ck-image-local img {
- filter: grayscale(100%);
- -webkit-filter: grayscale(100%);
- -moz-filter: grayscale(100%);
- -ms-filter: grayscale(100%);
- filter: gray;
- opacity: 0.85;
-}
-.ck-message {
- position: fixed;
- left: 0;
- right: 0;
- height: 3.125em;
- line-height: 3.125em;
- top: -3.125em;
- z-index: 2;
- padding: 0 1em;
- font-weight: 500;
- text-align: center;
- background-color: rgba(103, 182, 255, 0.98);
- border-bottom: 1px solid #4daaff;
- -webkit-animation: messageShowHide 3.2s;
- animation: messageShowHide 3.2s;
-}
-@-webkit-keyframes messageShowHide {
- 8% {
- top: 0;
- }
- 92% {
- top: 0;
- }
- 100% {
- top: -3.125em;
- }
-}
-@keyframes messageShowHide {
- 8% {
- top: 0;
- }
- 92% {
- top: 0;
- }
- 100% {
- top: -3.125em;
- }
-}
-/**
- * Icons
- */
-@font-face {
- font-family: 'ck-icons';
- src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMggi/LwAAAC8AAAAYGNtYXAaVcxdAAABHAAAAExnYXNwAAAAEAAAAWgAAAAIZ2x5Zl5vXY0AAAFwAAAIgGhlYWQBGRzWAAAJ8AAAADZoaGVhBAgCEAAACigAAAAkaG10eA3eACQAAApMAAAALGxvY2EH2AnkAAAKeAAAABhtYXhwABAAtgAACpAAAAAgbmFtZdoByAQAAAqwAAABWnBvc3QAAwAAAAAMDAAAACAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmBgHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYG//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAwAAAAABkgG3AE8AbgCNAAA/ATY3Njc2NzY3Njc0NzQ9ARAnJicmJyYnJiMmIycyNzYzMjMyMzIXFhcWFxYXFhUUBwYHBgcGBwYHFhcWFRQHBgcGBwYHBiMiJyYjIgcGIxMUFxYVFAcUFRQXFjMyNzY3Njc2NTQnJicmJyYjIgcTFBcWFxYzMjU0JyYnJicmJyYjJiMiBxQHFBUUFRQVAAEEFBQKAgIBAQEBAQcBBQUIBwcGCAcBARxFRSUHDQ0GFBMTEhINDQgIBQUGBgwMCQkPLB0dCgoQERcXGBgaDBoZDB85OQmYAQIBAQwTFxIRDg4HCAkIDg8QERMOFwIBAQMVE2sMBwoKCgkODQsKERQIAQAbAQMEBAQEBAUGBAQGBwMTARgNAgICAQEBAQEYAwMEBAgIDAwSEhYODQwICQgIBQQHChwdKh0XFg8OCgoEBAEBBAMBlg8cHQ8IDw8HDQcCBAMJCRERGBQPDwgIBAQD/r4LDQ0GCV8hEwwJCQQFAgMBAw8eHw4DEREKAAAAAAEAAAAAASUBtwBOAAA/ATI3Njc2NzQ3Njc2PQEmJyYnJiM3FhcWFxYzMjc2NzY3BgcGBwYHBgcGFQYHBhUGBwYHFAcGBwYHBhcVFhcGByIHIiMiJyYjIiMiBwYjAAUCFRYKCAQREg8PBwkIDAsFBQoZGBISEQ0PDhQVCAIECBUUCwICAgECAQgREgUDAwMDAgIBBTABBAMGBgMJEBEIJxQOGhsIARgGBgUKEwJQUUpLCgcEAgEBAR4BAQEBAQEBAQEBCw8CBgUEBgYHBQUICAQqTk0YAw4ODAsMDQQFAQgMEAEDAwIDAAAEAAAAAAIlAbcAFAApADEAQgAANxE0NzYzITIXFhURFAcGIyEiJyY1MxQXFjMhMjc2NRE0JyYjISIHBhURNzU3FzcXFSE1NDc2MzIXFhUUBwYjIicmNQANDhMByRMNDg4NE/43Ew4NJQIDBAHJBAIDAwIE/jcEAwIkXC2Tdv5uEBAXFxAQEBAXFxAQLgFbEw0ODg0T/qUTDg0NDhMEAwICAwQBWwQDAgIDBP6lGzdbLZJ3gO4XEBAQEBcXEBAQEBcAAAAAAwAFAAUB1wHXACgAVACAAAATND8BNhc2HwEWFRQHFzYXNh8BFhUUDwEGByYvASY1NDcnBgcmLwEmNRcUHwEWNxY3IicmJyYnJicmNTQ3NjcWMxYXFhcWFxY3NjU0LwEmByYPAQYVFxQfARY3Fj8BNjU0LwEmJwYHFBcWFxYXFhcWFRQHBicGJyInJicmJyYnBhUFGCoYIiIYOxgZGRgjIhg8GBgqGCIjGDsXGRkZIyIYOxg2CDwICwwJAQUEAgEDAwEBCAgMBAQDBAQBAgQFAQkIOwgLCwkqCMkIOwgMCwgqCAg7CAwMCAUFAQICAwEBCAgLBQMEAwQCAgQEAQoBWyIYKRkBARk7GCIkFxoaAQEZOxkhIxcrFgEBFzwXIyIaGBgBARc8FyMBCgk6CQEBCgUDAwEFAgUCBgoJBwEBAgIDAQIEBgEHDQsJOgkBAQkoCQvKCgk7CAEBCCkJCgwHPQcBAQgCBAUBAgMFAgUDDQcJAQECBAICAQUEAgoLAAAAAwANAAUCGAGNABoALwBKAAA3ND8BNjMyHwEWFRQPARcWFRQPAQYjIi8BJjUXEzY3Nh8BFhcWBwMGBwYvASYnJjc3ND8BJyY1ND8BNjMyHwEWFRQPAQYjIi8BJjUNA4UDAwQDDgMDcHADAw4DBAMDhQO+awEDBAMSBAECAWoCAwMEEQQCAgGmA3FxAwMPAgQEA4UDA4UDBAQCDwPJBAOFAwMOAwQEA3BwAwQDAw8CAoYCBLMBcQMCAgEFAQMEA/6PBAICAQUBBAMEPAQDcHADBAQDDgMDhQMEBAKGAgIPAwMAAAAAAQASAAAB7gG3ALMAABM0NzYzMhcWMzI3NjMyFxYVFAcGByIHBgcGHQEUFRY7ATI3NDU3NCcmIyInJjU0NzYzMhcWMzI3NjMyFxYVFAcGIyIHIgcGFREUFxYXFjMyFxYVFAcGIyInJiMiBwYjIicmNTQ3NjcyNzY3NjUnNDUmKwEiBxQdARQXFhcWMzIXFhUUBwYjIicmIyIHBiMiJyY1NDc2NzI3Njc2NSc1MDc0NSY1NCcmJyYnJicmIyYjIicmNRIDBAYOGhoODBgYDAcEAwUFBgYICAQKBAjHBwQBCgUMDAcHAwQHDRkZDQwYGQwHBAQFBQcGCQgECgoECQkGBwUFAwQGDRkaDA0ZGQ0HAwQFBQYGCAkECgEECsELBAoFCQkHCAUGBAMHDRsaDQ0YGAwHAwQEBQYGBwgECgEBAQEBAQECAgIFCAkGBwUFAaMHBwYBAQEBBgcHCQQDAQEBAwYnXAYDAQEDBlwnBgQEAwsHBwYBAQEBBgcHCQQEAQMHJ/7yIgYDAQEEBAkHBwYBAQEBBgYHCQQEAQIBAwYicAYDAQEDBmopBgMBAQQECQcHBgEBAQEGBgcIBQQBAgEDByIQ6QcHAwQHCAQFBgUEAwIDAQQECQAAAAIAAAAbAgEBewAlAEsAADcyHgIVFA4CIyIuAjUnND4CMxUiDgIHDgMHMjY6ATMhMh4CFRQOAiMiLgI1JzQ+AjMVIg4CBw4DBzI2OgEzcBcoHxESHygXGCgfEQEjPVIuEB8dGgsCBAQEAgIEBQQCASAXKB8REh8oFxgoHxEBIz1SLhAfHRoLAgQEBAICBAUEAvsRHygYFykeEhIeKRcQL1E9I0AGDBELAwQFBQIBER8oGBcpHhISHikXEC9RPSNABgwRCwMEBQUCAQAAAAEAAAABAABSja6rXw889QALAgAAAAAAz+ruAQAAAADP6u4BAAAAAAIlAdcAAAAIAAIAAAAAAAAAAQAAAeD/4AAAAiUAAP//AiUAAQAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAABAAAAAZMAAAElAAACJQAAAdwABQIlAA0CAAASAgAAAAAAAAAACgAUAB4A5gFaAbwCfALuA9oEQAABAAAACwC0AAQAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEAEAAAAAEAAAAAAAIADgBaAAEAAAAAAAMAHAAmAAEAAAAAAAQAEABoAAEAAAAAAAUAFgAQAAEAAAAAAAYACABCAAEAAAAAAAoANAB4AAMAAQQJAAEAEAAAAAMAAQQJAAIADgBaAAMAAQQJAAMAHAAmAAMAAQQJAAQAEABoAAMAAQQJAAUAFgAQAAMAAQQJAAYAEABKAAMAAQQJAAoANAB4AGMAawAtAGkAYwBvAG4AcwBWAGUAcgBzAGkAbwBuACAAMQAuADAAYwBrAC0AaQBjAG8AbgBzADoAIAAyADAAMQA0Y2staWNvbnMAYwBrAC0AaQBjAG8AbgBzAFIAZQBnAHUAbABhAHIAYwBrAC0AaQBjAG8AbgBzAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('truetype'), url(data:application/font-woff;charset=utf-8;base64,d09GRk9UVE8AAA1gAAoAAAAADRgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABDRkYgAAAA9AAACaoAAAmqfszNZk9TLzIAAAqgAAAAYAAAAGAIIvy8Y21hcAAACwAAAABMAAAATBpVzF1nYXNwAAALTAAAAAgAAAAIAAAAEGhlYWQAAAtUAAAANgAAADYBGRzWaGhlYQAAC4wAAAAkAAAAJAQIAhBobXR4AAALsAAAACwAAAAsDd4AJG1heHAAAAvcAAAABgAAAAYAC1AAbmFtZQAAC+QAAAFaAAABWtoByARwb3N0AAANQAAAACAAAAAgAAMAAAEABAQAAQEBCWNrLWljb25zAAECAAEAOvgcAvgbA/gYBB4KABlT/4uLHgoAGVP/i4sMB4tr+Ln4dAUdAAAAnQ8dAAAAohEdAAAACR0AAAmhEgAMAQEJERMVGB0iJywxNjtjay1pY29uc2NrLWljb25zdTB1MXUyMHVFNjAwdUU2MDF1RTYwMnVFNjAzdUU2MDR1RTYwNXVFNjA2AAACAYkACQALAgABAAQABwAKAA0ByAK/A5wFNwY+CHEI5fyUDvyUDvyUDvuUDvsBi4sVjKYFjYyUjJiNmI6VjZKOjI2NjoyOjI6MjouOjI+LjoyOi42Lj4yPi5CLjouNCIueBYv3T4nthpOLjImNh4yIjIaMhoyGjIeMhouHi4aMhouHjIiLiosIiqMFnYusjLmNuY2ujKSLkIuRi5SLlIuRi4+LmIuYiZiJmIiXh5eGl4WVhZSDk4OTgZB/CJB/jn6LfIuCiYGIg4iDh4SHhoeFhYaDhYOGhIaFiIWIg4eBh6iEo36feZ94lHOLbwiLeIh6hHuFfIJ/gIF/gX6DfIV8hHuHe4h7iHuKeYuDi36Leox7i36Mg4t3i22KZYgIZYl1ioWLCPcs+CoVi4GMfYt4jHeMfYuBi4aLg4qBi4GLhIuGi4KLhIyHk4qVipiLmouZjJeOlo2Wj5SRCJSRkpSQlpCWjpmLm4uYiJeFlYaVg5KCkYGRgY+AjYCOf4x+i4KLf4p7iQiN+9YVi4SLg4yCjIKMhY2HmYWYiJiL0ouvq4vKi6GHnIOYhpOFkoWRhJGFj4SOhY6DjoKMCIKNg4yEi4SMgouAi36LgYqGiYuBi3yKd4t3i3uLgouJi4WLf4uAi4KLhAgO+2+LjBWQowWMi5ONmY+aj5WOko+QkY+VjpiLjJGmlsGXwZa/lbyVvZCni5IIi5IFho6GjYWMhYyFi4OMhIuFjIiLCJCpBZKKloucipuKmYqXi5eLl4qWi5SLlIyVi5SLl4yYjJmMlIuRjIqDiYOIgYWKgoh9hwh+iICIhIiKh4mHioeKhoqHi4iKiIqHioWLhoqHi4iFb4NjgFd/WIRph3uLiYqFiYIIiYKJgomDiYSKg4mDioKLhouICIuGBY6KnYirhoqDioGIgYmLiIuHioeLiIuJi4WLg4yAjYCNg4yFi3GLd4t+i4KLfYp6igh5iYCKhYsIDrCLuRWL9+8Fi5iPlZSUlJSWkJiLCPhdiwWXi5aGlIKUgpCBi34Ii/vvBYt+hoCCgoKCgId/iwj8XYsFfouAj4KUgpSHlouYCLCLFYuIi4mNiY2JjYuOiwj4XYsFjYuNi42NjY2MjYuOCIv37wWLjoqNiY2JjImMiYsI/F2LBYiLiYqJiomJi4mLiAiL++8Fr6YVi8Ln5rhe9yf3JvcK+wuL+xT8JosFi/eCFYuakJiWlpaVmJGai5qLmIWWgZaAkH6LfIt8hn6AgICAfoZ8i3yLfpCAloCWhpiLmggOZ5D37xWLopOfm5oItbUFm5uek6KLooueg5t7CMZPBZt8k3eLdIt0gnd7ewikcgWbm5+Uoouii56Dm3sIx08Fm3uTeIt0i3SDeHt7CGFhBXt7d4R1i3SLd5N7mwhQxgV8m4Oei6KLopOfnJwIcqQFenp4g3OLdIt4k3ubCFDGBXubg5+LoQjBixWLhI6EkIYIx1AFkIWRiZOLk4uSjpGRiouJjYiOiI6JjYqMioyKjYmOiY2KjYqOi42KjouOi5KOkpCQCJGQkY6Ti46LjYuOio2KjYqOiY2KjYmMioyKjYmOiI6IjYmMi5GQjpKLk4uTiJKGkAhQxgWGkISOhIuDi4WIhYYIYWIFhoWIhYuDCPdd+10Vi4OOhZCGCMZPBZCGkomTi5KLko2QkAi1tQWQkI6Si5KLk4iRhpAIUMcFhZCFjoOLg4uEiIaFi4qNiY6IjoiNiYyKjIqNiYyJjYiMiYyJjIiLiYuIi4OIhYaFCIaGhIiEi4iLiIyJi4iMiYyJjYiNiYyKjIqMiY2IjoiOiY2LjISFiISLgwgOsJj3XRWLjoyNjY0I9xn3GQWNjY2MjYuOi42KjYkImX0FjYmMiIuJi4mKiImJCPsE+wT3BPsEBY2JjImLiIuJiomJiQh9fAWJiomKiIuJi4mMiYwI+xn3GgWJjIqOi40I91L7RxX2+AUFjI2MjY2MjoyNjI2KCJ2GBY2KjYqMiY2Ii4mKiQgh/AUFioiJiYmKiYqJi4iLCHqQBYiMiY2KjYqNi42Ljgj3OscVi46MjY2NCPcF9wT7BfcEBYmNio6LjYuNjI6NjQiamQWMjY6MjYuOi42KjYkI9xn7GQWNiYyJi4iLiYqIiYoI+xn7GgWJiomKiIuJi4iMiowIfJoFiY2KjYuNCA6d+DcVi5CMj42QjY+PjY+LlIuYi52KnYqYi5SLk4uXi5uMm4yXi5OLkIuOiY6HjYaMh4uGCIuFioeHiIiJh4mHi4eLhouGioaLh4mIiYSHiHyLcQiLLwWLh4uIi4mOi4+KkIsI91uLBZCLj4yNi4uNi46LjwiM5wWLpYeahY+HjoaMg4uDi4WNho2GjYmQi5KLkIyPjZCOj46NkIuUi5eLnIqcipeLlIsIk4uXi5uMnIyXi5OLkIuPiY2HjYaNh4uGi4WJh4iIh4mHiYeLh4uGi4WKhouHioiJCISGiHyLcQiL+6IFi3WOfZKHjomPipGKkYuQio+LkIuPiY6Jj4iMh4uFi4aKhomHiYeHiYeLgot/i3qMCHqMfouDi4KLf4t6inqKf4uCi4eLh42Jj4iPio+LkIuRjI+Pjo6Oj4yPjI+LkIyQjAiRjI+Mjo2Sj46Yi6IIivcEBYuPi46LjYmLhoyEiwj7VYsFhIuGioiLi4mLiIuHCIshBYtwjnuSh46JkIqRipGLkYqPi5CLj4qPiI+IjYeLhYuGioaIh4mHiImGi4KLfot5jAh6jH2Lg4uCi3+Le4p7in+Lg4uGi4iNiY+Ij4qPi5CLkYyPjo6Ojo+Mj4yPi4+MkIwIkIyPjI6NkpCOmIuiCIqbi/d9BYuLi46Mj4uPi4+LjYqOi4+Lj4uQi4+KjouPio6Kj4uPiY6KjYqNiY2KjIiNhoyGiwiFjIaLh4uGi4eMiI6HjoqPi5EIDvcF948VyIu+WYtNi05YWE6LTYtZvovICIqbBYv3EO/v9xCLCItLBWCLY3ttbYWFhoWGhJGMkYuRiwj3tIsVyIu+WYtNi05YWE6LTYtZvovICIqbBYv3EO/v9xCLCItLBWCLY3ttbYWFhoWGhJGMkYuRiwgO+JQU+JQViwwKAAAAAwIAAZAABQAAAUwBZgAAAEcBTAFmAAAA9QAZAIQAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADmBgHg/+D/4AHgACAAAAABAAAAAAAAAAAAAAAgAAAAAAACAAAAAwAAABQAAwABAAAAFAAEADgAAAAKAAgAAgACAAEAIOYG//3//wAAAAAAIOYA//3//wAB/+MaBAADAAEAAAAAAAAAAAAAAAEAAf//AA8AAQAAAAEAAGLPbdVfDzz1AAsCAAAAAADP6u4BAAAAAM/q7gEAAAAAAiUB1wAAAAgAAgAAAAAAAAABAAAB4P/gAAACJQAA//8CJQABAAAAAAAAAAAAAAAAAAAACwAAAAAAAAAAAAAAAAEAAAABkwAAASUAAAIlAAAB3AAFAiUADQIAABICAAAAAABQAAALAAAAAAAOAK4AAQAAAAAAAQAQAAAAAQAAAAAAAgAOAFoAAQAAAAAAAwAcACYAAQAAAAAABAAQAGgAAQAAAAAABQAWABAAAQAAAAAABgAIAEIAAQAAAAAACgA0AHgAAwABBAkAAQAQAAAAAwABBAkAAgAOAFoAAwABBAkAAwAcACYAAwABBAkABAAQAGgAAwABBAkABQAWABAAAwABBAkABgAQAEoAAwABBAkACgA0AHgAYwBrAC0AaQBjAG8AbgBzAFYAZQByAHMAaQBvAG4AIAAxAC4AMABjAGsALQBpAGMAbwBuAHMAOgAgADIAMAAxADRjay1pY29ucwBjAGsALQBpAGMAbwBuAHMAUgBlAGcAdQBsAGEAcgBjAGsALQBpAGMAbwBuAHMARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format('woff');
- font-weight: normal;
- font-style: normal;
-}
-.ck-icon-bold,
-.ck-icon-italic,
-.ck-icon-image,
-.ck-icon-link,
-.ck-icon-embed,
-.ck-icon-heading,
-.ck-icon-quote {
- font-family: 'ck-icons';
- speak: none;
- font-style: normal;
- font-weight: normal;
- font-variant: normal;
- text-transform: none;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-.ck-icon-bold:before {
- content: "\e600";
-}
-.ck-icon-italic:before {
- content: "\e601";
-}
-.ck-icon-image:before {
- content: "\e602";
-}
-.ck-icon-link:before {
- content: "\e603";
-}
-.ck-icon-embed:before {
- content: "\e604";
-}
-.ck-icon-heading:before {
- content: "\e605";
-}
-.ck-icon-quote:before {
- content: "\e606";
-}
-/**
- * Animations
- */
-@-webkit-keyframes fadeIn {
- 0% {
- opacity: 0;
- }
- 100% {
- opacity: 1;
- }
-}
-@keyframes fadeIn {
- 0% {
- opacity: 0;
- }
- 100% {
- opacity: 1;
- }
-}
-@-webkit-keyframes spin {
- to {
- -webkit-transform: rotate(360deg);
- }
-}
-@keyframes spin {
- to {
- transform: rotate(360deg);
- }
-}
-@-webkit-keyframes shake {
- 0%,
- 100% {
- -webkit-transform: translateX(0);
- }
- 20%,
- 60% {
- -webkit-transform: translateX(-10px);
- }
- 40%,
- 80% {
- -webkit-transform: translateX(10px);
- }
-}
-@keyframes shake {
- 0%,
- 100% {
- transform: translateX(0);
- }
- 20%,
- 60% {
- transform: translateX(-10px);
- }
- 40%,
- 80% {
- transform: translateX(10px);
- }
-}
-@-webkit-keyframes textGlimmer {
- 0% {
- background-position: -288px 0;
- }
- 100% {
- background-position: 288px 0;
- }
-}
-@-webkit-keyframes pop-out {
- 0% {
- opacity: 0.8;
- -webkit-transform: scale(0.8);
- }
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.1);
- }
-}
-@keyframes pop-out {
- 0% {
- opacity: 0.8;
- transform: scale(0.8);
- }
- 50% {
- opacity: 1;
- transform: scale(1.1);
- }
-}
-@-webkit-keyframes pop-up {
- 0% {
- opacity: 0.8;
- -webkit-transform: scale(0.9) translateY(14px);
- }
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.05) translateY(-4px);
- }
-}
-@keyframes pop-up {
- 0% {
- opacity: 0.8;
- transform: scale(0.9) translateY(14px);
- }
- 50% {
- opacity: 1;
- transform: scale(1.05) translateY(-4px);
- }
-}
-@-webkit-keyframes pop-right {
- 0% {
- opacity: 0.8;
- -webkit-transform: scale(0.9) translateX(-14px);
- }
- 50% {
- opacity: 1;
- -webkit-transform: scale(1.05) translateX(4px);
- }
-}
-@keyframes pop-right {
- 0% {
- opacity: 0.8;
- transform: scale(0.9) translateX(-14px);
- }
- 50% {
- opacity: 1;
- transform: scale(1.05) translateX(4px);
- }
-}
diff --git a/dist/content-kit-editor.js b/dist/content-kit-editor.js
deleted file mode 100755
index c3bc42e58..000000000
--- a/dist/content-kit-editor.js
+++ /dev/null
@@ -1,3189 +0,0 @@
-/*!
- * @overview ContentKit-Editor: A modern, minimalist WYSIWYG editor.
- * @version 0.1.0
- * @author Garth Poitras (http://garthpoitras.com/)
- * @license MIT
- * Last modified: Sep 11, 2014
- */
-
-(function(exports, document) {
-
-'use strict';
-
-define("content-kit",
- ["./content-kit-compiler/types/type","./content-kit-compiler/models/block","./content-kit-compiler/models/text","./content-kit-compiler/models/image","./content-kit-compiler/models/embed","./content-kit-compiler/compiler","./content-kit-compiler/parsers/html-parser","./content-kit-compiler/renderers/html-renderer","./content-kit-editor/editor/editor-factory","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
- "use strict";
- var Type = __dependency1__["default"];
- var BlockModel = __dependency2__["default"];
- var TextModel = __dependency3__["default"];
- var ImageModel = __dependency4__["default"];
- var EmbedModel = __dependency5__["default"];
- var Compiler = __dependency6__["default"];
- var HTMLParser = __dependency7__["default"];
- var HTMLRenderer = __dependency8__["default"];
-
- var EditorFactory = __dependency9__["default"];
-
- var ContentKit = {};
- ContentKit.Type = Type;
- ContentKit.BlockModel = BlockModel;
- ContentKit.TextModel = TextModel;
- ContentKit.ImageModel = ImageModel;
- ContentKit.EmbedModel = EmbedModel;
- ContentKit.Compiler = Compiler;
- ContentKit.HTMLParser = HTMLParser;
- ContentKit.HTMLRenderer = HTMLRenderer;
-
- ContentKit.Editor = EditorFactory;
-
- __exports__["default"] = ContentKit;
- });
-define("content-kit-compiler/compiler",
- ["./parsers/html-parser","./renderers/html-renderer","./types/default-types","../content-kit-utils/object-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var HTMLParser = __dependency1__["default"];
- var HTMLRenderer = __dependency2__["default"];
- var DefaultBlockTypeSet = __dependency3__.DefaultBlockTypeSet;
- var DefaultMarkupTypeSet = __dependency3__.DefaultMarkupTypeSet;
- var mergeWithOptions = __dependency4__.mergeWithOptions;
-
- /**
- * @class Compiler
- * @constructor
- * @param options
- */
- function Compiler(options) {
- var parser = new HTMLParser();
- var renderer = new HTMLRenderer();
- var defaults = {
- parser : parser,
- renderer : renderer,
- blockTypes : DefaultBlockTypeSet,
- markupTypes : DefaultMarkupTypeSet,
- includeTypeNames : false // true will output type_name: 'TEXT' etc. when parsing for easier debugging
- };
- mergeWithOptions(this, defaults, options);
-
- // Reference the compiler settings
- parser.blockTypes = renderer.blockTypes = this.blockTypes;
- parser.markupTypes = renderer.markupTypes = this.markupTypes;
- parser.includeTypeNames = this.includeTypeNames;
- }
-
- /**
- * @method parse
- * @param input
- * @return Array
- */
- Compiler.prototype.parse = function(input) {
- return this.parser.parse(input);
- };
-
- /**
- * @method render
- * @param data
- * @return String
- */
- Compiler.prototype.render = function(data) {
- return this.renderer.render(data);
- };
-
- /**
- * @method sanitize
- * @param input
- * @return String
- */
- Compiler.prototype.sanitize = function(input) {
- return this.render(this.parse(input));
- };
-
- /**
- * @method registerBlockType
- * @param {Type} type
- */
- Compiler.prototype.registerBlockType = function(type) {
- return this.blockTypes.addType(type);
- };
-
- /**
- * @method registerMarkupType
- * @param {Type} type
- */
- Compiler.prototype.registerMarkupType = function(type) {
- return this.markupTypes.addType(type);
- };
-
- __exports__["default"] = Compiler;
- });
-define("content-kit-editor/constants",
- ["../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Type = __dependency1__["default"];
-
- var Keycodes = {
- BKSP : 8,
- ENTER : 13,
- ESC : 27,
- DEL : 46
- };
-
- var RegEx = {
- NEWLINE : /[\r\n]/g,
- HTTP_PROTOCOL : /^https?:\/\//i,
- HEADING_TAG : /^(h1|h2|h3|h4|h5|h6)$/i
- };
-
- var SelectionDirection = {
- LEFT_TO_RIGHT : 1,
- RIGHT_TO_LEFT : 2,
- SAME_NODE : 3
- };
-
- var ToolbarDirection = {
- TOP : 1,
- RIGHT : 2
- };
-
- // TODO: remove, get from Compiler DefaultBlockTypeSet
- var RootTags = [
- Type.TEXT.tag,
- Type.HEADING.tag,
- Type.SUBHEADING.tag,
- Type.QUOTE.tag,
- Type.LIST.tag,
- Type.ORDERED_LIST.tag
- ];
-
- __exports__.Keycodes = Keycodes;
- __exports__.RegEx = RegEx;
- __exports__.SelectionDirection = SelectionDirection;
- __exports__.ToolbarDirection = ToolbarDirection;
- __exports__.RootTags = RootTags;
- });
-define("content-kit-utils/array-utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- * Converts an array-like object (i.e. NodeList) to Array
- * Note: could just use Array.prototype.slice but does not work in IE <= 8
- */
- function toArray(obj) {
- var array = [];
- var i = obj && obj.length >>> 0; // cast to Uint32
- while (i--) {
- array[i] = obj[i];
- }
- return array;
- }
-
- /**
- * Computes the sum of values in a (sparse) array
- */
- function sumSparseArray(array) {
- var sum = 0, i;
- for (i in array) { // 'for in' is better for sparse arrays
- if (array.hasOwnProperty(i)) {
- sum += array[i];
- }
- }
- return sum;
- }
-
- __exports__.toArray = toArray;
- __exports__.sumSparseArray = sumSparseArray;
- });
-define("content-kit-utils/node-utils",
- ["./string-utils","./array-utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var sanitizeWhitespace = __dependency1__.sanitizeWhitespace;
- var toArray = __dependency2__.toArray;
-
- /**
- * A document instance separate from the page's document. (if browser supports it)
- * Prevents images, scripts, and styles from executing while parsing nodes.
- */
- var standaloneDocument = (function() {
- var implementation = document.implementation;
- var createHTMLDocument = implementation.createHTMLDocument;
-
- if (createHTMLDocument) {
- return createHTMLDocument.call(implementation, '');
- }
- return document;
- })();
-
- /**
- * document.createElement with our lean, standalone document
- */
- function createElement(type) {
- return standaloneDocument.createElement(type);
- }
-
- /**
- * A reusable DOM Node for parsing html content.
- */
- var DOMParsingNode = createElement('div');
-
- /**
- * Returns plain-text of a `Node`
- */
- function textOfNode(node) {
- var text = node.textContent || node.innerText;
- return text ? sanitizeWhitespace(text) : '';
- }
-
- /**
- * Replaces a `Node` with its children
- */
- function unwrapNode(node) {
- var children = toArray(node.childNodes);
- var len = children.length;
- var parent = node.parentNode, i;
- for (i = 0; i < len; i++) {
- parent.insertBefore(children[i], node);
- }
- }
-
- /**
- * Extracts attributes of a `Node` to a hash of key/value pairs
- */
- function attributesForNode(node, blacklist) {
- var attrs = node.attributes;
- var len = attrs && attrs.length;
- var i, attr, name, hash;
-
- for (i = 0; i < len; i++) {
- attr = attrs[i];
- name = attr.name;
- if (attr.specified && attr.value) {
- if (blacklist && (name in blacklist)) { continue; }
- hash = hash || {};
- hash[name] = attr.value;
- }
- }
- return hash;
- }
-
- __exports__.createElement = createElement;
- __exports__.DOMParsingNode = DOMParsingNode;
- __exports__.textOfNode = textOfNode;
- __exports__.unwrapNode = unwrapNode;
- __exports__.attributesForNode = attributesForNode;
- });
-define("content-kit-utils/object-utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- * Merges defaults/options into an Object
- * Useful for constructors
- */
- function mergeWithOptions(original, updates, options) {
- options = options || {};
- for(var prop in updates) {
- if (options.hasOwnProperty(prop)) {
- original[prop] = options[prop];
- } else if (updates.hasOwnProperty(prop)) {
- original[prop] = updates[prop];
- }
- }
- return original;
- }
-
- /**
- * Merges properties of one object into another
- */
- function merge(original, updates) {
- return mergeWithOptions(original, updates);
- }
-
- /**
- * Prototype inheritance helper
- */
- function inherit(Subclass, Superclass) {
- if (typeof Object.create === 'function') {
- Subclass._super = Superclass;
- Subclass.prototype = Object.create(Superclass.prototype, {
- constructor: {
- value: Subclass,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- } else {
- for (var key in Superclass) {
- if (Superclass.hasOwnProperty(key)) {
- Subclass[key] = Superclass[key];
- }
- }
- Subclass.prototype = new Superclass();
- Subclass.constructor = Subclass;
- }
- }
-
- __exports__.mergeWithOptions = mergeWithOptions;
- __exports__.merge = merge;
- __exports__.inherit = inherit;
- });
-define("content-kit-utils/string-utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- var RegExpTrim = /^\s+|\s+$/g;
- var RegExpTrimLeft = /^\s+/;
- var RegExpWSChars = /(\r\n|\n|\r|\t|\u00A0)/gm;
- var RegExpMultiWS = /\s+/g;
- var RegExpNonAlphaNum = /[^a-zA-Z\d]/g;
-
- /**
- * String.prototype.trim polyfill
- * Removes whitespace at beginning and end of string
- */
- function trim(string) {
- return string ? (string + '').replace(RegExpTrim, '') : '';
- }
-
- /**
- * String.prototype.trimLeft polyfill
- * Removes whitespace at beginning of string
- */
- function trimLeft(string) {
- return string ? (string + '').replace(RegExpTrimLeft, '') : '';
- }
-
- /**
- * Replaces non-alphanumeric chars with underscores
- */
- function underscore(string) {
- return string ? trim(string + '').replace(RegExpNonAlphaNum, '_') : '';
- }
-
- /**
- * Cleans line breaks, tabs, non-breaking spaces, then multiple occuring whitespaces.
- */
- function sanitizeWhitespace(string) {
- return string ? (string + '').replace(RegExpWSChars, '').replace(RegExpMultiWS, ' ') : '';
- }
-
- /**
- * Injects a string into another string at the index specified
- */
- function injectIntoString(string, injection, index) {
- return string.substr(0, index) + injection + string.substr(index);
- }
-
- __exports__.trim = trim;
- __exports__.trimLeft = trimLeft;
- __exports__.underscore = underscore;
- __exports__.sanitizeWhitespace = sanitizeWhitespace;
- __exports__.injectIntoString = injectIntoString;
- });
-define("ext/content-kit-services",
- ["exports"],
- function(__exports__) {
- "use strict";
-
- function createXHR(options) {
- var xhr = new XMLHttpRequest();
- xhr.open(options.method, options.url);
- xhr.onload = function () {
- var response = xhr.responseText;
- if (xhr.status === 200) {
- return options.success.call(this, response);
- }
- options.error.call(this, response);
- };
- xhr.onerror = function (error) {
- options.error.call(this, error);
- };
- return xhr;
- }
-
- function xhrGet(options) {
- options.method = 'GET';
- var xhr = createXHR(options);
- try {
- xhr.send();
- } catch(error) {}
- }
-
- function xhrPost(options) {
- options.method = 'POST';
- var xhr = createXHR(options);
- var formData = new FormData();
- formData.append('file', options.data);
- try {
- xhr.send(formData);
- } catch(error) {}
- }
-
- function responseJSON(jsonString) {
- if (!jsonString) { return null; }
- try {
- return JSON.parse(jsonString);
- } catch(e) {
- return jsonString;
- }
- }
-
- // --------------------------------------------
-
- function FileUploader(options) {
- options = options || {};
- var url = options.url;
- var maxFileSize = options.maxFileSize;
- if (url) {
- this.url = url;
- } else {
- throw new Error('FileUploader: setting the `url` to an upload service is required');
- }
- if (maxFileSize) {
- this.maxFileSize = maxFileSize;
- }
- }
-
- FileUploader.prototype.upload = function(options) {
- if (!options) { return; }
-
- var fileInput = options.fileInput;
- var file = options.file || (fileInput && fileInput.files && fileInput.files[0]);
- var callback = options.complete;
- var maxFileSize = this.maxFileSize;
- if (!file || !(file instanceof window.File)) { return; }
-
- if (maxFileSize && file.size > maxFileSize) {
- if (callback) { callback.call(this, null, { message: 'max file size is ' + maxFileSize + ' bytes' }); }
- return;
- }
-
- xhrPost({
- url: this.url,
- data: file,
- success: function(response) {
- if (callback) { callback.call(this, responseJSON(response)); }
- },
- error: function(error) {
- if (callback) { callback.call(this, null, responseJSON(error)); }
- }
- });
- };
-
- function OEmbedder(options) {
- options = options || {};
- var url = options.url;
- if (url) {
- this.url = url;
- } else {
- throw new Error('OEmbedder: setting the `url` to an embed service is required');
- }
- }
-
- OEmbedder.prototype.fetch = function(options) {
- var callback = options.complete;
- xhrGet({
- url: this.url + "?url=" + encodeURI(options.url),
- success: function(response) {
- if (callback) { callback.call(this, responseJSON(response)); }
- },
- error: function(error) {
- if (callback) { callback.call(this, null, responseJSON(error)); }
- }
- });
- };
-
- __exports__.FileUploader = FileUploader;
- __exports__.OEmbedder = OEmbedder;
- });
-define("ext/loader",
- [],
- function() {
- "use strict";
- var define, requireModule, require, requirejs;
-
- (function() {
-
- var _isArray;
- if (!Array.isArray) {
- _isArray = function (x) {
- return Object.prototype.toString.call(x) === "[object Array]";
- };
- } else {
- _isArray = Array.isArray;
- }
-
- var registry = {}, seen = {};
- var FAILED = false;
-
- var uuid = 0;
-
- function tryFinally(tryable, finalizer) {
- try {
- return tryable();
- } finally {
- finalizer();
- }
- }
-
-
- function Module(name, deps, callback, exports) {
- var defaultDeps = ['require', 'exports', 'module'];
-
- this.id = uuid++;
- this.name = name;
- this.deps = !deps.length && callback.length ? defaultDeps : deps;
- this.exports = exports || { };
- this.callback = callback;
- this.state = undefined;
- }
-
- define = function(name, deps, callback) {
- if (!_isArray(deps)) {
- callback = deps;
- deps = [];
- }
-
- registry[name] = new Module(name, deps, callback);
- };
-
- define.amd = {};
-
- function reify(mod, name, seen) {
- var deps = mod.deps;
- var length = deps.length;
- var reified = new Array(length);
- var dep;
- // TODO: new Module
- // TODO: seen refactor
- var module = { };
-
- for (var i = 0, l = length; i < l; i++) {
- dep = deps[i];
- if (dep === 'exports') {
- module.exports = reified[i] = seen;
- } else if (dep === 'require') {
- reified[i] = require;
- } else if (dep === 'module') {
- mod.exports = seen;
- module = reified[i] = mod;
- } else {
- reified[i] = require(resolve(dep, name));
- }
- }
-
- return {
- deps: reified,
- module: module
- };
- }
-
- requirejs = require = requireModule = function(name) {
- var mod = registry[name];
- if (!mod) {
- throw new Error('Could not find module ' + name);
- }
-
- if (mod.state !== FAILED &&
- seen.hasOwnProperty(name)) {
- return seen[name];
- }
-
- var reified;
- var module;
- var loaded = false;
-
- seen[name] = { }; // placeholder for run-time cycles
-
- tryFinally(function() {
- reified = reify(mod, name, seen[name]);
- module = mod.callback.apply(this, reified.deps);
- loaded = true;
- }, function() {
- if (!loaded) {
- mod.state = FAILED;
- }
- });
-
- if (module === undefined && reified.module.exports) {
- return (seen[name] = reified.module.exports);
- } else {
- return (seen[name] = module);
- }
- };
-
- function resolve(child, name) {
- if (child.charAt(0) !== '.') { return child; }
-
- var parts = child.split('/');
- var nameParts = name.split('/');
- var parentBase = nameParts.slice(0, -1);
-
- for (var i = 0, l = parts.length; i < l; i++) {
- var part = parts[i];
-
- if (part === '..') { parentBase.pop(); }
- else if (part === '.') { continue; }
- else { parentBase.push(part); }
- }
-
- return parentBase.join('/');
- }
-
- requirejs.entries = requirejs._eak_seen = registry;
- requirejs.clear = function(){
- requirejs.entries = requirejs._eak_seen = registry = {};
- seen = state = {};
- };
- })();
- });
-define("content-kit-compiler/models/block",
- ["./model","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Model = __dependency1__["default"];
-
- /**
- * Ensures block markups at the same index are always in a specific order.
- * For example, so all bold links are consistently marked up
- * as text instead of text
- */
- function sortBlockMarkups(markups) {
- return markups.sort(function(a, b) {
- if (a.start === b.start && a.end === b.end) {
- return b.type - a.type;
- }
- return 0;
- });
- }
-
- /**
- * @class BlockModel
- * @constructor
- * @extends Model
- */
- function BlockModel(options) {
- options = options || {};
- Model.call(this, options);
- this.value = options.value || '';
- this.markup = sortBlockMarkups(options.markup || []);
- }
-
- __exports__["default"] = BlockModel;
- });
-define("content-kit-compiler/models/embed",
- ["../models/model","../types/type","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Model = __dependency1__["default"];
- var Type = __dependency2__["default"];
-
- /**
- * @class EmbedModel
- * @constructor
- * @extends Model
- * Massages data from an oEmbed response into an EmbedModel
- */
- function EmbedModel(options) {
- if (!options) { return null; }
-
- Model.call(this, {
- type: Type.EMBED.id,
- type_name: Type.EMBED.name,
- attributes: {}
- });
-
- var attributes = this.attributes;
- var embedType = options.type;
- var providerName = options.provider_name;
- var embedUrl = options.url;
- var embedTitle = options.title;
- var embedThumbnail = options.thumbnail_url;
- var embedHtml = options.html;
-
- if (embedType) { attributes.embed_type = embedType; }
- if (providerName) { attributes.provider_name = providerName; }
- if (embedUrl) { attributes.url = embedUrl; }
- if (embedTitle) { attributes.title = embedTitle; }
-
- if (embedType === 'photo') {
- attributes.thumbnail = options.media_url || embedUrl;
- } else if (embedThumbnail) {
- attributes.thumbnail = embedThumbnail;
- }
-
- if (embedHtml && embedType === 'rich') {
- attributes.html = embedHtml;
- }
- }
-
- __exports__["default"] = EmbedModel;
- });
-define("content-kit-compiler/models/image",
- ["./block","../types/type","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var BlockModel = __dependency1__["default"];
- var Type = __dependency2__["default"];
-
- /**
- * @class ImageModel
- * @constructor
- * @extends BlockModel
- * A simple BlockModel subclass representing an image
- */
- function ImageModel(options) {
- options = options || {};
- options.type = Type.IMAGE.id;
- options.type_name = Type.IMAGE.name;
- if (options.src) {
- options.attributes = { src: options.src };
- }
- BlockModel.call(this, options);
- }
-
- __exports__["default"] = ImageModel;
- });
-define("content-kit-compiler/models/markup",
- ["./model","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Model = __dependency1__["default"];
-
- /**
- * @class MarkupModel
- * @constructor
- * @extends Model
- */
- function MarkupModel(options) {
- options = options || {};
- Model.call(this, options);
- this.start = options.start || 0;
- this.end = options.end || 0;
- }
-
- __exports__["default"] = MarkupModel;
- });
-define("content-kit-compiler/models/model",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- * @class Model
- * @constructor
- * @private
- */
- function Model(options) {
- options = options || {};
- var type_name = options.type_name;
- var attributes = options.attributes;
-
- this.type = options.type || null;
- if (type_name) {
- this.type_name = type_name;
- }
- if (attributes) {
- this.attributes = attributes;
- }
- }
-
- __exports__["default"] = Model;
- });
-define("content-kit-compiler/models/text",
- ["./block","../types/type","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var BlockModel = __dependency1__["default"];
- var Type = __dependency2__["default"];
-
- /**
- * @class TextModel
- * @constructor
- * @extends BlockModel
- * A simple BlockModel subclass representing a paragraph of text
- */
- function TextModel(options) {
- options = options || {};
- options.type = Type.TEXT.id;
- options.type_name = Type.TEXT.name;
- BlockModel.call(this, options);
- }
-
- __exports__["default"] = TextModel;
- });
-define("content-kit-compiler/parsers/html-parser",
- ["../models/block","../models/markup","../types/default-types","../../content-kit-utils/object-utils","../../content-kit-utils/array-utils","../../content-kit-utils/string-utils","../../content-kit-utils/node-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) {
- "use strict";
- var BlockModel = __dependency1__["default"];
- var MarkupModel = __dependency2__["default"];
- var DefaultBlockTypeSet = __dependency3__.DefaultBlockTypeSet;
- var DefaultMarkupTypeSet = __dependency3__.DefaultMarkupTypeSet;
- var mergeWithOptions = __dependency4__.mergeWithOptions;
- var toArray = __dependency5__.toArray;
- var trim = __dependency6__.trim;
- var trimLeft = __dependency6__.trimLeft;
- var sanitizeWhitespace = __dependency6__.sanitizeWhitespace;
- var createElement = __dependency7__.createElement;
- var DOMParsingNode = __dependency7__.DOMParsingNode;
- var textOfNode = __dependency7__.textOfNode;
- var unwrapNode = __dependency7__.unwrapNode;
- var attributesForNode = __dependency7__.attributesForNode;
-
- var attributeBlacklist = { 'style': 1, 'class': 1 }; // filter out inline styles and classes
-
- /**
- * Gets the last block in the set or creates and return a default block if none exist yet.
- */
- function getLastBlockOrCreate(parser, blocks) {
- var block;
- if (blocks.length) {
- block = blocks[blocks.length - 1];
- } else {
- block = parser.parseBlock(createElement(DefaultBlockTypeSet.TEXT.tag));
- blocks.push(block);
- }
- return block;
- }
-
- /**
- * Helper to retain stray elements at the root of the html that aren't blocks
- */
- function handleNonBlockElementAtRoot(parser, elementNode, blocks) {
- var block = getLastBlockOrCreate(parser, blocks),
- markup = parser.parseElementMarkup(elementNode, block.value.length);
- if (markup) {
- block.markup.push(markup);
- }
- block.value += textOfNode(elementNode);
- }
-
- /**
- * @class HTMLParser
- * @constructor
- */
- function HTMLParser(options) {
- var defaults = {
- blockTypes : DefaultBlockTypeSet,
- markupTypes : DefaultMarkupTypeSet,
- includeTypeNames : false
- };
- mergeWithOptions(this, defaults, options);
- }
-
- /**
- * @method parse
- * @param html String of HTML content
- * @return Array Parsed JSON content array
- */
- HTMLParser.prototype.parse = function(html) {
- DOMParsingNode.innerHTML = sanitizeWhitespace(html);
-
- var children = toArray(DOMParsingNode.childNodes),
- len = children.length,
- blocks = [],
- i, currentNode, block, text;
-
- for (i = 0; i < len; i++) {
- currentNode = children[i];
- // All top level nodes *should be* `Element` nodes and supported block types.
- // We'll handle some cases if it isn't so we don't lose any content when parsing.
- // Parser assumes sane input (such as from the ContentKit Editor) and is not intended to be a full html sanitizer.
- if (currentNode.nodeType === 1) {
- block = this.parseBlock(currentNode);
- if (block) {
- blocks.push(block);
- } else {
- handleNonBlockElementAtRoot(this, currentNode, blocks);
- }
- } else if (currentNode.nodeType === 3) {
- text = currentNode.nodeValue;
- if (trim(text)) {
- block = getLastBlockOrCreate(this, blocks);
- block.value += text;
- }
- }
- }
-
- return blocks;
- };
-
- /**
- * @method parseBlock
- * @param node DOM node to parse
- * @return {BlockModel} parsed block model
- * Parses a single block type node into a model
- */
- HTMLParser.prototype.parseBlock = function(node) {
- var type = this.blockTypes.findByNode(node);
- if (type) {
- return new BlockModel({
- type : type.id,
- type_name : this.includeTypeNames && type.name,
- value : trim(textOfNode(node)),
- attributes : attributesForNode(node, attributeBlacklist),
- markup : this.parseBlockMarkup(node)
- });
- }
- };
-
- /**
- * @method parseBlockMarkup
- * @param node DOM node to parse
- * @return {Array} parsed markups
- * Parses a single block type node's markup
- */
- HTMLParser.prototype.parseBlockMarkup = function(node) {
- var processedText = '',
- markups = [],
- index = 0,
- currentNode, markup;
-
- // Clone the node since it will be recursively torn down
- node = node.cloneNode(true);
-
- while (node.hasChildNodes()) {
- currentNode = node.firstChild;
- if (currentNode.nodeType === 1) {
- markup = this.parseElementMarkup(currentNode, processedText.length);
- if (markup) {
- markups.push(markup);
- }
- // unwrap the element so we can process any children
- if (currentNode.hasChildNodes()) {
- unwrapNode(currentNode);
- }
- } else if (currentNode.nodeType === 3) {
- var text = sanitizeWhitespace(currentNode.nodeValue);
- if (index === 0) { text = trimLeft(text); }
- if (text) { processedText += text; }
- }
-
- // node has been processed, remove it
- currentNode.parentNode.removeChild(currentNode);
- index++;
- }
-
- return markups;
- };
-
- /**
- * @method parseElementMarkup
- * @param node DOM node to parse
- * @param startIndex DOM node to parse
- * @return {MarkupModel} parsed markup model
- * Parses markup of a single html element node
- */
- HTMLParser.prototype.parseElementMarkup = function(node, startIndex) {
- var type = this.markupTypes.findByNode(node),
- selfClosing, endIndex;
-
- if (type) {
- selfClosing = type.selfClosing;
- if (!selfClosing && !node.hasChildNodes()) { return; } // check for empty nodes
-
- endIndex = startIndex + (selfClosing ? 0 : textOfNode(node).length);
- if (endIndex > startIndex || (selfClosing && endIndex === startIndex)) { // check for empty nodes
- return new MarkupModel({
- type : type.id,
- type_name : this.includeTypeNames && type.name,
- start : startIndex,
- end : endIndex,
- attributes : attributesForNode(node, attributeBlacklist)
- });
- }
- }
- };
-
- __exports__["default"] = HTMLParser;
- });
-define("content-kit-compiler/renderers/html-element-renderer",
- ["../../content-kit-utils/string-utils","../../content-kit-utils/array-utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var injectIntoString = __dependency1__.injectIntoString;
- var sumSparseArray = __dependency2__.sumSparseArray;
-
- /**
- * Builds an opening html tag. i.e. ''
- */
- function createOpeningTag(tagName, attributes, selfClosing /*,blacklist*/) {
- var tag = '<' + tagName;
- for (var attr in attributes) {
- if (attributes.hasOwnProperty(attr)) {
- //if (blacklist && attr in blacklist) { continue; }
- tag += ' ' + attr + '="' + attributes[attr] + '"';
- }
- }
- if (selfClosing) { tag += '/'; }
- tag += '>';
- return tag;
- }
-
- /**
- * Builds a closing html tag. i.e. ''
- */
- function createCloseTag(tagName) {
- return '' + tagName + '>';
- }
-
- /**
- * @class HTMLElementRenderer
- * @constructor
- */
- function HTMLElementRenderer(options) {
- options = options || {};
- this.type = options.type;
- this.markupTypes = options.markupTypes;
- }
-
- /**
- * @method render
- * @param model a block model
- * @return String html
- * Renders a block model into a HTML string.
- */
- HTMLElementRenderer.prototype.render = function(model) {
- var html = '';
- var type = this.type;
- var tagName = type.tag;
- var selfClosing = type.selfClosing;
-
- if (tagName) {
- html += createOpeningTag(tagName, model.attributes, selfClosing);
- }
- if (!selfClosing) {
- html += this.renderMarkup(model.value, model.markup);
- if (tagName) {
- html += createCloseTag(tagName);
- }
- }
- return html;
- };
-
- /**
- * @method renderMarkup
- * @param text plain text to apply markup to
- * @param markup an array of markup models
- * @return String html
- * Renders a markup model into a HTML string.
- */
- HTMLElementRenderer.prototype.renderMarkup = function(text, markups) {
- var parsedTagsIndexes = [],
- len = markups && markups.length, i;
-
- for (i = 0; i < len; i++) {
- var markup = markups[i],
- markupMeta = this.markupTypes.findById(markup.type),
- tagName = markupMeta.tag,
- selfClosing = markupMeta.selfClosing,
- start = markup.start,
- end = markup.end,
- openTag = createOpeningTag(tagName, markup.attributes, selfClosing),
- parsedTagLengthAtIndex = parsedTagsIndexes[start] || 0,
- parsedTagLengthBeforeIndex = sumSparseArray(parsedTagsIndexes.slice(0, start + 1));
-
- text = injectIntoString(text, openTag, start + parsedTagLengthBeforeIndex);
- parsedTagsIndexes[start] = parsedTagLengthAtIndex + openTag.length;
-
- if (!selfClosing) {
- var closeTag = createCloseTag(tagName);
- parsedTagLengthAtIndex = parsedTagsIndexes[end] || 0;
- parsedTagLengthBeforeIndex = sumSparseArray(parsedTagsIndexes.slice(0, end));
- text = injectIntoString(text, closeTag, end + parsedTagLengthBeforeIndex);
- parsedTagsIndexes[end] = parsedTagLengthAtIndex + closeTag.length;
- }
- }
-
- return text;
- };
-
- __exports__["default"] = HTMLElementRenderer;
- });
-define("content-kit-compiler/renderers/html-embed-renderer",
- ["./embeds/youtube","./embeds/twitter","./embeds/instagram","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var YouTubeRenderer = __dependency1__["default"];
- var TwitterRenderer = __dependency2__["default"];
- var InstagramRenderer = __dependency3__["default"];
-
- /**
- * A dictionary of supported embed services
- */
- var services = {
- YOUTUBE : {
- id: 1,
- renderer: new YouTubeRenderer()
- },
- TWITTER : {
- id: 2,
- renderer: new TwitterRenderer()
- },
- INSTAGRAM : {
- id: 3,
- renderer: new InstagramRenderer()
- }
- };
-
- /**
- * @class EmbedRenderer
- * @constructor
- */
- function EmbedRenderer() {}
-
- /**
- * @method render
- * @param model
- * @return String html
- */
- EmbedRenderer.prototype.render = function(model) {
- var renderer = this.rendererFor(model);
- if (renderer) {
- return renderer.render(model);
- }
- var attrs = model.attributes;
- return attrs && attrs.html || '';
- };
-
- /**
- * @method rendererFor
- * @param model
- * @return service renderer
- */
- EmbedRenderer.prototype.rendererFor = function(model) {
- var provider = model.attributes.provider_name;
- var providerKey = provider && provider.toUpperCase();
- var service = services[providerKey];
- return service && service.renderer;
- };
-
- __exports__["default"] = EmbedRenderer;
- });
-define("content-kit-compiler/renderers/html-renderer",
- ["../types/type","./html-element-renderer","./html-embed-renderer","../types/default-types","../../content-kit-utils/object-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Type = __dependency1__["default"];
- var HTMLElementRenderer = __dependency2__["default"];
- var HTMLEmbedRenderer = __dependency3__["default"];
- var DefaultBlockTypeSet = __dependency4__.DefaultBlockTypeSet;
- var DefaultMarkupTypeSet = __dependency4__.DefaultMarkupTypeSet;
- var mergeWithOptions = __dependency5__.mergeWithOptions;
-
- /**
- * @class HTMLRenderer
- * @constructor
- */
- function HTMLRenderer(options) {
- var defaults = {
- blockTypes : DefaultBlockTypeSet,
- markupTypes : DefaultMarkupTypeSet,
- typeRenderers : {}
- };
- mergeWithOptions(this, defaults, options);
- }
-
- /**
- * @method willRenderType
- * @param type {Number|Type}
- * @param renderer the rendering function that returns a string of html
- * Registers custom rendering hooks for a type
- */
- HTMLRenderer.prototype.willRenderType = function(type, renderer) {
- if ('number' !== typeof type) {
- type = type.id;
- }
- this.typeRenderers[type] = renderer;
- };
-
- /**
- * @method rendererFor
- * @param model
- * @returns renderer
- * Returns an instance of a renderer for supplied model
- */
- HTMLRenderer.prototype.rendererFor = function(model) {
- var type = this.blockTypes.findById(model.type);
- if (type === Type.EMBED) {
- return new HTMLEmbedRenderer();
- }
- return new HTMLElementRenderer({ type: type, markupTypes: this.markupTypes });
- };
-
- /**
- * @method render
- * @param model
- * @return String html
- */
- HTMLRenderer.prototype.render = function(model) {
- var html = '';
- var len = model && model.length;
- var i, item, renderer, renderHook, itemHtml;
-
- for (i = 0; i < len; i++) {
- item = model[i];
- renderer = this.rendererFor(item);
- renderHook = this.typeRenderers[item.type];
- itemHtml = renderHook ? renderHook.call(renderer, item) : renderer.render(item);
- if (itemHtml) { html += itemHtml; }
- }
- return html;
- };
-
- __exports__["default"] = HTMLRenderer;
- });
-define("content-kit-compiler/types/default-types",
- ["./type-set","./type","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var TypeSet = __dependency1__["default"];
- var Type = __dependency2__["default"];
-
- /**
- * Default supported block types
- */
- var DefaultBlockTypeSet = new TypeSet([
- new Type({ tag: 'p', name: 'text' }),
- new Type({ tag: 'h2', name: 'heading' }),
- new Type({ tag: 'h3', name: 'subheading' }),
- new Type({ tag: 'img', name: 'image' }),
- new Type({ tag: 'blockquote', name: 'quote' }),
- new Type({ tag: 'ul', name: 'list' }),
- new Type({ tag: 'ol', name: 'ordered list' }),
- new Type({ name: 'embed' })
- ]);
-
- /**
- * Default supported markup types
- */
- var DefaultMarkupTypeSet = new TypeSet([
- new Type({ tag: 'b', name: 'bold' }),
- new Type({ tag: 'i', name: 'italic' }),
- new Type({ tag: 'u', name: 'underline' }),
- new Type({ tag: 'a', name: 'link' }),
- new Type({ tag: 'br', name: 'break' }),
- new Type({ tag: 'li', name: 'list item' }),
- new Type({ tag: 'sub', name: 'subscript' }),
- new Type({ tag: 'sup', name: 'superscript' })
- ]);
-
- __exports__.DefaultBlockTypeSet = DefaultBlockTypeSet;
- __exports__.DefaultMarkupTypeSet = DefaultMarkupTypeSet;
- });
-define("content-kit-compiler/types/type-set",
- ["./type","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Type = __dependency1__["default"];
-
- /**
- * @class TypeSet
- * @private
- * @constructor
- * A Set of Types
- */
- function TypeSet(types) {
- var len = types && types.length, i;
-
- this._autoId = 1; // Auto-increment id counter
- this.idLookup = {}; // Hash cache for finding by id
- this.tagLookup = {}; // Hash cache for finding by tag
-
- for (i = 0; i < len; i++) {
- this.addType(types[i]);
- }
- }
-
- TypeSet.prototype = {
- /**
- * Adds a type to the set
- */
- addType: function(type) {
- if (type instanceof Type) {
- this[type.name] = type;
- if (type.id === undefined) {
- type.id = this._autoId++;
- }
- this.idLookup[type.id] = type;
- if (type.tag) {
- this.tagLookup[type.tag] = type;
- }
- return type;
- }
- },
-
- /**
- * Returns type info for a given Node
- */
- findByNode: function(node) {
- if (node) {
- return this.findByTag(node.tagName);
- }
- },
- /**
- * Returns type info for a given tag
- */
- findByTag: function(tag) {
- if (tag) {
- return this.tagLookup[tag.toLowerCase()];
- }
- },
- /**
- * Returns type info for a given id
- */
- findById: function(id) {
- return this.idLookup[id];
- }
- };
-
- __exports__["default"] = TypeSet;
- });
-define("content-kit-compiler/types/type",
- ["../../content-kit-utils/string-utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var underscore = __dependency1__.underscore;
-
- /**
- * @class Type
- * @constructor
- * Contains meta info about a node type (id, name, tag, etc).
- */
- function Type(options) {
- if (options) {
- this.name = underscore(options.name || options.tag).toUpperCase();
- if (options.id !== undefined) {
- this.id = options.id;
- }
- if (options.tag) {
- this.tag = options.tag.toLowerCase();
- this.selfClosing = /^(br|img|hr|meta|link|embed)$/i.test(this.tag);
- }
-
- // Register the type as constant
- Type[this.name] = this;
- }
- }
-
- __exports__["default"] = Type;
- });
-define("content-kit-editor/commands/base",
- ["exports"],
- function(__exports__) {
- "use strict";
- function Command(options) {
- var command = this;
- var name = options.name;
- var prompt = options.prompt;
- command.name = name;
- command.button = options.button || name;
- if (prompt) { command.prompt = prompt; }
- }
-
- Command.prototype.exec = function() {};
-
- __exports__["default"] = Command;
- });
-define("content-kit-editor/commands/bold",
- ["./text-format","../constants","../utils/selection-utils","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var TextFormatCommand = __dependency1__["default"];
- var RegEx = __dependency2__.RegEx;
- var getSelectionBlockTagName = __dependency3__.getSelectionBlockTagName;
- var inherit = __dependency4__.inherit;
- var Type = __dependency5__["default"];
-
- function BoldCommand() {
- TextFormatCommand.call(this, {
- name: 'bold',
- tag: Type.BOLD.tag,
- button: ' '
- });
- }
- inherit(BoldCommand, TextFormatCommand);
-
- BoldCommand.prototype.exec = function() {
- // Don't allow executing bold command on heading tags
- if (!RegEx.HEADING_TAG.test(getSelectionBlockTagName())) {
- BoldCommand._super.prototype.exec.call(this);
- }
- };
-
- __exports__["default"] = BoldCommand;
- });
-define("content-kit-editor/commands/format-block",
- ["./text-format","../utils/selection-utils","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var TextFormatCommand = __dependency1__["default"];
- var getSelectionBlockElement = __dependency2__.getSelectionBlockElement;
- var selectNode = __dependency2__.selectNode;
- var inherit = __dependency3__.inherit;
- var Type = __dependency4__["default"];
-
- function FormatBlockCommand(options) {
- options.action = 'formatBlock';
- TextFormatCommand.call(this, options);
- }
- inherit(FormatBlockCommand, TextFormatCommand);
-
- FormatBlockCommand.prototype.exec = function() {
- var tag = this.tag;
- // Brackets neccessary for certain browsers
- var value = '<' + tag + '>';
- var blockElement = getSelectionBlockElement();
- // Allow block commands to be toggled back to a text block
- if(tag === blockElement.tagName.toLowerCase()) {
- value = Type.TEXT.tag;
- } else {
- // Flattens the selection before applying the block format.
- // Otherwise, undesirable nested blocks can occur.
- // TODO: would love to be able to remove this
- var flatNode = document.createTextNode(blockElement.textContent);
- blockElement.parentNode.insertBefore(flatNode, blockElement);
- blockElement.parentNode.removeChild(blockElement);
- selectNode(flatNode);
- }
-
- FormatBlockCommand._super.prototype.exec.call(this, value);
- };
-
- __exports__["default"] = FormatBlockCommand;
- });
-define("content-kit-editor/commands/heading",
- ["./format-block","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var FormatBlockCommand = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var Type = __dependency3__["default"];
-
- function HeadingCommand() {
- FormatBlockCommand.call(this, {
- name: 'heading',
- tag: Type.HEADING.tag,
- button: ' 1'
- });
- }
- inherit(HeadingCommand, FormatBlockCommand);
-
- __exports__["default"] = HeadingCommand;
- });
-define("content-kit-editor/commands/image",
- ["./base","../views/message","../../content-kit-compiler/models/image","../../content-kit-utils/object-utils","../../ext/content-kit-services","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var Command = __dependency1__["default"];
- var Message = __dependency2__["default"];
- var ImageModel = __dependency3__["default"];
- var inherit = __dependency4__.inherit;
- var FileUploader = __dependency5__.FileUploader;
-
- function createFileInput(command) {
- var fileInput = document.createElement('input');
- fileInput.type = 'file';
- fileInput.accept = 'image/*';
- fileInput.className = 'ck-file-input';
- fileInput.addEventListener('change', function(e) {
- command.handleFile(e);
- });
- return fileInput;
- }
-
- function insertImageWithSrc(src, editor) {
- var imageModel = new ImageModel({ src: src });
- var index = editor.getCurrentBlockIndex();
- editor.replaceBlockAt(imageModel, index);
- editor.syncVisualAt(index);
- }
-
- function renderFromFile(file, editor) {
- if (file && window.FileReader) {
- var reader = new FileReader();
- reader.onload = function(e) {
- var base64Src = e.target.result;
- insertImageWithSrc(base64Src, editor);
- };
- reader.readAsDataURL(file);
- }
- }
-
- function ImageCommand(options) {
- Command.call(this, {
- name: 'image',
- button: ' '
- });
- this.uploader = new FileUploader({ url: options.serviceUrl, maxFileSize: 5000000 });
- }
- inherit(ImageCommand, Command);
-
- ImageCommand.prototype = {
- exec: function() {
- ImageCommand._super.prototype.exec.call(this);
- var fileInput = this.fileInput;
- if (!fileInput) {
- fileInput = this.fileInput = createFileInput(this);
- document.body.appendChild(fileInput);
- }
- fileInput.dispatchEvent(new MouseEvent('click', { bubbles: false }));
- },
- handleFile: function(e) {
- var fileInput = e.target;
- var editor = this.editorContext;
- var embedIntent = this.embedIntent;
-
- embedIntent.showLoading();
- renderFromFile(fileInput.files && fileInput.files[0], editor); // render image immediately client-side
- this.uploader.upload({
- fileInput: fileInput,
- complete: function(response, error) {
- embedIntent.hideLoading();
- if (error || !response || !response.url) {
- setTimeout(function() {
- var failedIndex = editor.getCurrentBlockIndex();
- editor.removeBlockAt(failedIndex);
- editor.syncVisual();
- }, 1000);
- return new Message().show(error.message || 'Error uploading image');
- }
- insertImageWithSrc(response.url, editor);
- }
- });
- fileInput.value = null; // reset file input
- }
- };
-
- __exports__["default"] = ImageCommand;
- });
-define("content-kit-editor/commands/italic",
- ["./text-format","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var TextFormatCommand = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var Type = __dependency3__["default"];
-
- function ItalicCommand() {
- TextFormatCommand.call(this, {
- name: 'italic',
- tag: Type.ITALIC.tag,
- button: ' '
- });
- }
- inherit(ItalicCommand, TextFormatCommand);
-
- __exports__["default"] = ItalicCommand;
- });
-define("content-kit-editor/commands/link",
- ["./text-format","../views/prompt","../constants","../utils/selection-utils","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var TextFormatCommand = __dependency1__["default"];
- var Prompt = __dependency2__["default"];
- var RegEx = __dependency3__.RegEx;
- var getSelectionTagName = __dependency4__.getSelectionTagName;
- var inherit = __dependency5__.inherit;
- var Type = __dependency6__["default"];
-
- function LinkCommand() {
- TextFormatCommand.call(this, {
- name: 'link',
- tag: Type.LINK.tag,
- action: 'createLink',
- removeAction: 'unlink',
- button: ' ',
- prompt: new Prompt({
- command: this,
- placeholder: 'Enter a url, press return...'
- })
- });
- }
- inherit(LinkCommand, TextFormatCommand);
-
- LinkCommand.prototype.exec = function(url) {
- if(this.tag === getSelectionTagName()) {
- this.unexec();
- } else {
- if (!RegEx.HTTP_PROTOCOL.test(url)) {
- url = 'http://' + url;
- }
- LinkCommand._super.prototype.exec.call(this, url);
- }
- };
-
- __exports__["default"] = LinkCommand;
- });
-define("content-kit-editor/commands/list",
- ["./text-format","../utils/selection-utils","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var TextFormatCommand = __dependency1__["default"];
- var getSelectionBlockElement = __dependency2__.getSelectionBlockElement;
- var selectNode = __dependency2__.selectNode;
- var getSelectionTagName = __dependency2__.getSelectionTagName;
- var inherit = __dependency3__.inherit;
- var Type = __dependency4__["default"];
-
- function ListCommand(options) {
- TextFormatCommand.call(this, options);
- }
- inherit(ListCommand, TextFormatCommand);
-
- ListCommand.prototype.exec = function() {
- ListCommand._super.prototype.exec.call(this);
-
- // After creation, lists need to be unwrapped
- // TODO: eventually can remove this when direct model manipulation is ready
- var listElement = getSelectionBlockElement();
- var wrapperNode = listElement.parentNode;
- if (wrapperNode.firstChild === listElement) {
- var editorNode = wrapperNode.parentNode;
- editorNode.insertBefore(listElement, wrapperNode);
- editorNode.removeChild(wrapperNode);
- selectNode(listElement);
- }
- };
-
- ListCommand.prototype.checkAutoFormat = function(node) {
- // Creates unordered lists when node starts with '- '
- // or ordered list if node starts with '1. '
- var regex = this.autoFormatRegex, text;
- if (node && regex) {
- text = node.textContent;
- if (Type.LIST_ITEM.tag !== getSelectionTagName() && regex.test(text)) {
- this.exec();
- window.getSelection().anchorNode.textContent = text.replace(regex, '');
- return true;
- }
- }
- return false;
- };
-
- __exports__["default"] = ListCommand;
- });
-define("content-kit-editor/commands/oembed",
- ["./base","../views/prompt","../views/message","../../content-kit-compiler/models/embed","../../content-kit-utils/object-utils","../../ext/content-kit-services","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var Command = __dependency1__["default"];
- var Prompt = __dependency2__["default"];
- var Message = __dependency3__["default"];
- var EmbedModel = __dependency4__["default"];
- var inherit = __dependency5__.inherit;
- var OEmbedder = __dependency6__.OEmbedder;
-
- function loadTwitterWidgets(element) {
- if (window.twttr) {
- window.twttr.widgets.load(element);
- } else {
- var script = document.createElement('script');
- script.async = true;
- script.src = 'http://platform.twitter.com/widgets.js';
- document.head.appendChild(script);
- }
- }
-
- function OEmbedCommand(options) {
- Command.call(this, {
- name: 'embed',
- button: ' ',
- prompt: new Prompt({
- command: this,
- placeholder: 'Paste a YouTube or Twitter url...'
- })
- });
-
- this.embedService = new OEmbedder({ url: options.serviceUrl });
- }
- inherit(OEmbedCommand, Command);
-
- OEmbedCommand.prototype.exec = function(url) {
- var command = this;
- var editorContext = command.editorContext;
- var embedIntent = command.embedIntent;
- var index = editorContext.getCurrentBlockIndex();
-
- embedIntent.showLoading();
- this.embedService.fetch({
- url: url,
- complete: function(response, error) {
- embedIntent.hideLoading();
- if (error) {
- var errorMsg = error;
- if (error.target && error.target.status === 0) {
- errorMsg = 'Error: could not connect to embed service.';
- } else if (typeof error !== 'string') {
- errorMsg = 'Error: embeds are broken :/';
- }
- new Message().show(errorMsg);
- embedIntent.show();
- } else {
- var embedModel = new EmbedModel(response);
- editorContext.insertBlockAt(embedModel, index);
- editorContext.syncVisualAt(index);
- if (embedModel.attributes.provider_name.toLowerCase() === 'twitter') {
- loadTwitterWidgets(editorContext.element);
- }
- }
- }
- });
- };
-
- __exports__["default"] = OEmbedCommand;
- });
-define("content-kit-editor/commands/ordered-list",
- ["./list","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var ListCommand = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var Type = __dependency3__["default"];
-
- function OrderedListCommand() {
- ListCommand.call(this, {
- name: 'ordered list',
- tag: Type.ORDERED_LIST.tag,
- action: 'insertOrderedList'
- });
- }
- inherit(OrderedListCommand, ListCommand);
-
- OrderedListCommand.prototype.autoFormatRegex = /^1\.\s/;
-
- __exports__["default"] = OrderedListCommand;
- });
-define("content-kit-editor/commands/quote",
- ["./format-block","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var FormatBlockCommand = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var Type = __dependency3__["default"];
-
- function QuoteCommand() {
- FormatBlockCommand.call(this, {
- name: 'quote',
- tag: Type.QUOTE.tag,
- button: ' '
- });
- }
- inherit(QuoteCommand, FormatBlockCommand);
-
- __exports__["default"] = QuoteCommand;
- });
-define("content-kit-editor/commands/subheading",
- ["./format-block","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var FormatBlockCommand = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var Type = __dependency3__["default"];
-
- function SubheadingCommand() {
- FormatBlockCommand.call(this, {
- name: 'subheading',
- tag: Type.SUBHEADING.tag,
- button: ' 2'
- });
- }
- inherit(SubheadingCommand, FormatBlockCommand);
-
- __exports__["default"] = SubheadingCommand;
- });
-define("content-kit-editor/commands/text-format",
- ["./base","../../content-kit-utils/object-utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Command = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
-
- function TextFormatCommand(options) {
- Command.call(this, options);
- this.tag = options.tag;
- this.action = options.action || this.name;
- this.removeAction = options.removeAction || this.action;
- }
- inherit(TextFormatCommand, Command);
-
- TextFormatCommand.prototype = {
- exec: function(value) {
- document.execCommand(this.action, false, value || null);
- },
- unexec: function(value) {
- document.execCommand(this.removeAction, false, value || null);
- }
- };
-
- __exports__["default"] = TextFormatCommand;
- });
-define("content-kit-editor/commands/unordered-list",
- ["./list","../../content-kit-utils/object-utils","../../content-kit-compiler/types/type","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var ListCommand = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var Type = __dependency3__["default"];
-
- function UnorderedListCommand() {
- ListCommand.call(this, {
- name: 'list',
- tag: Type.LIST.tag,
- action: 'insertUnorderedList'
- });
- }
- inherit(UnorderedListCommand, ListCommand);
-
- UnorderedListCommand.prototype.autoFormatRegex = /^[-*]\s/;
-
- __exports__["default"] = UnorderedListCommand;
- });
-define("content-kit-editor/editor/editor-factory",
- ["./editor","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Editor = __dependency1__["default"];
-
- /**
- * @class EditorFactory
- * @private
- * `EditorFactory` is publically exposed as `Editor`
- * It takes an `element` param which can be a css selector, Node, or NodeList
- * and sets up indiviual `Editor` instances
- */
- function EditorFactory(element, options) {
- var editors = [];
- var elements, elementsLen, i;
-
- if (!element) {
- return new Editor(element, options);
- }
-
- if (typeof element === 'string') {
- elements = document.querySelectorAll(element);
- } else if (element && element.length) {
- elements = element;
- } else if (element) {
- elements = [element];
- }
-
- if (elements) {
- elementsLen = elements.length;
- for (i = 0; i < elementsLen; i++) {
- editors.push(new Editor(elements[i], options));
- }
- }
-
- return editors.length > 1 ? editors : editors[0];
- }
-
- EditorFactory.prototype = Editor.prototype;
-
- __exports__["default"] = EditorFactory;
- });
-define("content-kit-editor/editor/editor-html-renderer",
- ["../constants","../../content-kit-compiler/renderers/html-renderer","../../content-kit-compiler/types/type","../../content-kit-utils/object-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var RegEx = __dependency1__.RegEx;
- var HTMLRenderer = __dependency2__["default"];
- var Type = __dependency3__["default"];
- var inherit = __dependency4__.inherit;
-
- function embedRenderer(model) {
- var embedAttrs = model.attributes;
- var isVideo = embedAttrs.embed_type === 'video';
- return '' +
- '
' +
- (isVideo ? '' : '') + this.render(model) + (isVideo ? '
' : '') +
- '' + embedAttrs.provider_name + ': ' +
- '' + embedAttrs.title + ' ' +
- ' ' +
- ' ' +
- '
';
- }
-
- function imageRenderer(model) {
- var imagePersisted = RegEx.HTTP_PROTOCOL.test(model.attributes.src);
- return '' +
- '' + this.render(model) + ' ' +
- '
';
- }
-
- var typeRenderers = {};
- typeRenderers[Type.EMBED.id] = embedRenderer;
- typeRenderers[Type.IMAGE.id] = imageRenderer;
-
- /**
- * @class EditorHTMLRenderer
- * @constructor
- * Subclass of HTMLRenderer specifically for the Editor
- * Wraps interactive elements to add functionality
- */
- function EditorHTMLRenderer() {
- HTMLRenderer.call(this, {
- typeRenderers: typeRenderers
- });
- }
- inherit(EditorHTMLRenderer, HTMLRenderer);
-
- __exports__["default"] = EditorHTMLRenderer;
- });
-define("content-kit-editor/editor/editor",
- ["./editor-html-renderer","../views/text-format-toolbar","../views/tooltip","../views/embed-intent","../commands/bold","../commands/italic","../commands/link","../commands/quote","../commands/heading","../commands/subheading","../commands/unordered-list","../commands/ordered-list","../commands/image","../commands/oembed","../commands/text-format","../constants","../utils/selection-utils","../utils/event-emitter","../utils/paste-utils","../../content-kit-compiler/compiler","../../content-kit-compiler/models/text","../../content-kit-compiler/types/type","../../content-kit-utils/array-utils","../../content-kit-utils/object-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __exports__) {
- "use strict";
- var EditorHTMLRenderer = __dependency1__["default"];
- var TextFormatToolbar = __dependency2__["default"];
- var Tooltip = __dependency3__["default"];
- var EmbedIntent = __dependency4__["default"];
- var BoldCommand = __dependency5__["default"];
- var ItalicCommand = __dependency6__["default"];
- var LinkCommand = __dependency7__["default"];
- var QuoteCommand = __dependency8__["default"];
- var HeadingCommand = __dependency9__["default"];
- var SubheadingCommand = __dependency10__["default"];
- var UnorderedListCommand = __dependency11__["default"];
- var OrderedListCommand = __dependency12__["default"];
- var ImageCommand = __dependency13__["default"];
- var OEmbedCommand = __dependency14__["default"];
- var TextFormatCommand = __dependency15__["default"];
- var Keycodes = __dependency16__.Keycodes;
- var getSelectionBlockElement = __dependency17__.getSelectionBlockElement;
- var getSelectionBlockTagName = __dependency17__.getSelectionBlockTagName;
- var EventEmitter = __dependency18__["default"];
- var cleanPastedContent = __dependency19__.cleanPastedContent;
- var Compiler = __dependency20__["default"];
- var TextModel = __dependency21__["default"];
- var Type = __dependency22__["default"];
- var toArray = __dependency23__.toArray;
- var merge = __dependency24__.merge;
- var mergeWithOptions = __dependency24__.mergeWithOptions;
-
- var defaults = {
- placeholder: 'Write here...',
- spellcheck: true,
- autofocus: true,
- textFormatCommands: [
- new BoldCommand(),
- new ItalicCommand(),
- new LinkCommand(),
- new QuoteCommand(),
- new HeadingCommand(),
- new SubheadingCommand()
- ],
- embedCommands: [
- new ImageCommand({ serviceUrl: '/images' }),
- new OEmbedCommand({ serviceUrl: '/embed' })
- ],
- autoTypingCommands: [
- new UnorderedListCommand(),
- new OrderedListCommand()
- ],
- compiler: new Compiler({
- includeTypeNames: true, // outputs models with type names, i.e. 'BOLD', for easier debugging
- renderer: new EditorHTMLRenderer() // subclassed HTML renderer that adds dom structure for additional editor interactivity
- })
- };
-
- function bindContentEditableTypingCorrections(editor) {
- editor.element.addEventListener('keyup', function(e) {
- if(!e.shiftKey && e.which === Keycodes.ENTER) {
- var selectionTag = getSelectionBlockTagName();
- if (!selectionTag || selectionTag === Type.QUOTE.tag) {
- document.execCommand('formatBlock', false, Type.TEXT.tag);
- }
- } else if (e.which === Keycodes.BKSP) {
- if(!editor.element.innerHTML) {
- document.execCommand('formatBlock', false, Type.TEXT.tag);
- }
- }
- });
- }
-
- function bindPasteListener(editor) {
- editor.element.addEventListener('paste', function(e) {
- var cleanedContent = cleanPastedContent(e, Type.TEXT.tag);
- if (cleanedContent) {
- document.execCommand('insertHTML', false, cleanedContent);
- }
- });
- }
-
- function bindAutoTypingListeners(editor) {
- // Watch typing patterns for auto format commands (e.g. lists '- ', '1. ')
- editor.element.addEventListener('keyup', function(e) {
- var commands = editor.autoTypingCommands;
- var count = commands && commands.length;
- var selection, i;
-
- if (count) {
- selection = window.getSelection();
- for (i = 0; i < count; i++) {
- if (commands[i].checkAutoFormat(selection.anchorNode)) {
- e.stopPropagation();
- return;
- }
- }
- }
- });
- }
-
- function bindDragAndDrop() {
- // Use these to add/remove classes
- // window.addEventListener('dragenter', function(e) { });
- // window.addEventListener('dragleave', function(e) { });
-
- window.addEventListener('dragover', function(e) {
- e.preventDefault(); // prevents showing cursor where to drop
- });
-
- window.addEventListener('drop', function(e) {
- e.preventDefault(); // prevent page from redirecting
- });
- }
-
- function bindLiveUpdate(editor) {
- editor.element.addEventListener('input', function() {
- editor.syncModel();
- });
-
- // Experimental/buggy: parsing only the blocks where action took place
- // Not sure if this is even more efficient. Compiler is probably faster than dom/selection checks
- /*
- editor.element.addEventListener('input', function(e) {
- editor.syncModelAtSelection();
- });
- editor.element.addEventListener('keyup', function(e) {
- // When pressing enter: parse block before cursor too
- if(!e.shiftKey && e.which === Keycodes.ENTER) {
- editor.syncModelAt(editor.getCurrentBlockIndex()-1);
- }
- // When pressing backspace/del: parse block after cursor too
- else if(e.which === Keycodes.BKSP || e.which === Keycodes.DEL) {
- editor.syncModelAt(editor.getCurrentBlockIndex()+1);
- }
- });
- */
- }
-
- function initEmbedCommands(editor) {
- var commands = editor.embedCommands;
- if(commands) {
- return new EmbedIntent({
- editorContext: editor,
- commands: commands,
- rootElement: editor.element
- });
- }
- }
-
- function applyClassName(editorElement) {
- var editorClassName = 'ck-editor';
- var editorClassNameRegExp = new RegExp(editorClassName);
- var existingClassName = editorElement.className;
-
- if (!editorClassNameRegExp.test(existingClassName)) {
- existingClassName += (existingClassName ? ' ' : '') + editorClassName;
- }
- editorElement.className = existingClassName;
- }
-
- function applyPlaceholder(editorElement, placeholder) {
- var dataset = editorElement.dataset;
- if (placeholder && !dataset.placeholder) {
- dataset.placeholder = placeholder;
- }
- }
-
- /**
- * @class Editor
- * An individual Editor
- * @param element `Element` node
- * @param options hash of options
- */
- function Editor(element, options) {
- var editor = this;
- mergeWithOptions(editor, defaults, options);
-
- if (element) {
- applyClassName(element);
- applyPlaceholder(element, editor.placeholder);
- element.spellcheck = editor.spellcheck;
- element.setAttribute('contentEditable', true);
- editor.element = element;
-
- bindContentEditableTypingCorrections(editor);
- bindPasteListener(editor);
- bindAutoTypingListeners(editor);
- bindDragAndDrop(editor);
- bindLiveUpdate(editor);
- initEmbedCommands(editor);
-
- editor.textFormatToolbar = new TextFormatToolbar({ rootElement: element, commands: editor.textFormatCommands });
- editor.linkTooltips = new Tooltip({ rootElement: element, showForTag: Type.LINK.tag });
-
- editor.syncModel();
-
- if(editor.autofocus) { element.focus(); }
- }
- }
-
- // Add event emitter pub/sub functionality
- merge(Editor.prototype, EventEmitter);
-
- Editor.prototype.syncModel = function() {
- this.model = this.compiler.parse(this.element.innerHTML);
- this.trigger('update');
- };
-
- Editor.prototype.syncModelAt = function(index) {
- if (index > -1) {
- var blockElements = toArray(this.element.children);
- var parsedBlockModel = this.compiler.parser.parseBlock(blockElements[index]);
- if (parsedBlockModel) {
- this.model[index] = parsedBlockModel;
- } else {
- this.model.splice(index, 1);
- }
- this.trigger('update', { index: index });
- }
- };
-
- Editor.prototype.syncModelAtSelection = function() {
- var index = this.getCurrentBlockIndex();
- this.syncModelAt(index);
- };
-
- Editor.prototype.syncVisual = function() {
- var html = this.compiler.render(this.model);
- this.element.innerHTML = html;
- };
-
- Editor.prototype.syncVisualAt = function(index) {
- if (index > -1) {
- var blockModel = this.model[index];
- var html = this.compiler.render([blockModel]);
- var blockElements = toArray(this.element.children);
- var element = blockElements[index];
- element.innerHTML = html;
- }
- };
-
- Editor.prototype.getCurrentBlockIndex = function() {
- var selectionEl = getSelectionBlockElement();
- var blockElements = toArray(this.element.children);
- return blockElements.indexOf(selectionEl);
- };
-
- Editor.prototype.insertBlock = function(model) {
- this.insertBlockAt(model, this.getCurrentBlockIndex());
- this.trigger('update');
- };
-
- Editor.prototype.insertBlockAt = function(model, index) {
- model = model || new TextModel();
- this.model.splice(index, 0, model);
- this.trigger('update');
- };
-
- Editor.prototype.replaceBlockAt = function(model, index) {
- this.model[index] = model;
- this.trigger('update');
- };
-
- Editor.prototype.removeBlockAt = function(index) {
- this.model.splice(index, 1);
- this.trigger('update');
- };
-
- Editor.prototype.addTextFormat = function(opts) {
- var command = new TextFormatCommand(opts);
- this.compiler.registerMarkupType(new Type({
- name : opts.name,
- tag : opts.tag || opts.name
- }));
- this.textFormatCommands.push(command);
- this.textFormatToolbar.addCommand(command);
- };
-
- __exports__["default"] = Editor;
- });
-define("content-kit-editor/utils/element-utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- function createDiv(className) {
- var div = document.createElement('div');
- if (className) {
- div.className = className;
- }
- return div;
- }
-
- function hideElement(element) {
- element.style.display = 'none';
- }
-
- function showElement(element) {
- element.style.display = 'block';
- }
-
- function swapElements(elementToShow, elementToHide) {
- hideElement(elementToHide);
- showElement(elementToShow);
- }
-
- function getEventTargetMatchingTag(tag, target, container) {
- // Traverses up DOM from an event target to find the node matching specifed tag
- while (target && target !== container) {
- if (target.tagName.toLowerCase() === tag) {
- return target;
- }
- target = target.parentNode;
- }
- }
-
- function nodeIsDescendantOfElement(node, element) {
- var parentNode = node.parentNode;
- while(parentNode) {
- if (parentNode === element) {
- return true;
- }
- parentNode = parentNode.parentNode;
- }
- return false;
- }
-
- function elementContentIsEmpty(element) {
- var content = element && element.innerHTML;
- if (content) {
- return content === '' || content === ' ';
- }
- return false;
- }
-
- function getElementRelativeOffset(element) {
- var offset = { left: 0, top: -window.pageYOffset };
- var offsetParent = element.offsetParent;
- var offsetParentPosition = window.getComputedStyle(offsetParent).position;
- var offsetParentRect;
-
- if (offsetParentPosition === 'relative') {
- offsetParentRect = offsetParent.getBoundingClientRect();
- offset.left = offsetParentRect.left;
- offset.top = offsetParentRect.top;
- }
- return offset;
- }
-
- function getElementComputedStyleNumericProp(element, prop) {
- return parseFloat(window.getComputedStyle(element)[prop]);
- }
-
- function positionElementToRect(element, rect, topOffset, leftOffset) {
- var relativeOffset = getElementRelativeOffset(element);
- var style = element.style;
- var round = Math.round;
-
- topOffset = topOffset || 0;
- leftOffset = leftOffset || 0;
- style.left = round(rect.left - relativeOffset.left - leftOffset) + 'px';
- style.top = round(rect.top - relativeOffset.top - topOffset) + 'px';
- }
-
- function positionElementHorizontallyCenteredToRect(element, rect, topOffset) {
- var horizontalCenter = (element.offsetWidth / 2) - (rect.width / 2);
- positionElementToRect(element, rect, topOffset, horizontalCenter);
- }
-
- function positionElementCenteredAbove(element, aboveElement) {
- var elementMargin = getElementComputedStyleNumericProp(element, 'marginBottom');
- positionElementHorizontallyCenteredToRect(element, aboveElement.getBoundingClientRect(), element.offsetHeight + elementMargin);
- }
-
- function positionElementCenteredBelow(element, belowElement) {
- var elementMargin = getElementComputedStyleNumericProp(element, 'marginTop');
- positionElementHorizontallyCenteredToRect(element, belowElement.getBoundingClientRect(), -element.offsetHeight - elementMargin);
- }
-
- function positionElementCenteredIn(element, inElement) {
- var verticalCenter = (inElement.offsetHeight / 2) - (element.offsetHeight / 2);
- positionElementHorizontallyCenteredToRect(element, inElement.getBoundingClientRect(), -verticalCenter);
- }
-
- function positionElementToLeftOf(element, leftOfElement) {
- var verticalCenter = (leftOfElement.offsetHeight / 2) - (element.offsetHeight / 2);
- var elementMargin = getElementComputedStyleNumericProp(element, 'marginRight');
- positionElementToRect(element, leftOfElement.getBoundingClientRect(), -verticalCenter, element.offsetWidth + elementMargin);
- }
-
- function positionElementToRightOf(element, rightOfElement) {
- var verticalCenter = (rightOfElement.offsetHeight / 2) - (element.offsetHeight / 2);
- var elementMargin = getElementComputedStyleNumericProp(element, 'marginLeft');
- var rightOfElementRect = rightOfElement.getBoundingClientRect();
- positionElementToRect(element, rightOfElementRect, -verticalCenter, -rightOfElement.offsetWidth - elementMargin);
- }
-
- __exports__.createDiv = createDiv;
- __exports__.hideElement = hideElement;
- __exports__.showElement = showElement;
- __exports__.swapElements = swapElements;
- __exports__.getEventTargetMatchingTag = getEventTargetMatchingTag;
- __exports__.nodeIsDescendantOfElement = nodeIsDescendantOfElement;
- __exports__.elementContentIsEmpty = elementContentIsEmpty;
- __exports__.getElementRelativeOffset = getElementRelativeOffset;
- __exports__.getElementComputedStyleNumericProp = getElementComputedStyleNumericProp;
- __exports__.positionElementToRect = positionElementToRect;
- __exports__.positionElementHorizontallyCenteredToRect = positionElementHorizontallyCenteredToRect;
- __exports__.positionElementCenteredAbove = positionElementCenteredAbove;
- __exports__.positionElementCenteredBelow = positionElementCenteredBelow;
- __exports__.positionElementCenteredIn = positionElementCenteredIn;
- __exports__.positionElementToLeftOf = positionElementToLeftOf;
- __exports__.positionElementToRightOf = positionElementToRightOf;
- });
-define("content-kit-editor/utils/event-emitter",
- ["exports"],
- function(__exports__) {
- "use strict";
- // Based on https://github.com/jeromeetienne/microevent.js/blob/master/microevent.js
- // See also: https://github.com/allouis/minivents/blob/master/minivents.js
-
- var EventEmitter = {
- on : function(type, handler){
- var events = this.__events = this.__events || {};
- events[type] = events[type] || [];
- events[type].push(handler);
- },
- off : function(type, handler){
- var events = this.__events = this.__events || {};
- if (type in events) {
- events[type].splice(events[type].indexOf(handler), 1);
- }
- },
- trigger : function(type) {
- var events = this.__events = this.__events || {};
- var eventForTypeCount, i;
- if (type in events) {
- eventForTypeCount = events[type].length;
- for(i = 0; i < eventForTypeCount; i++) {
- events[type][i].apply(this, Array.prototype.slice.call(arguments, 1));
- }
- }
- }
- };
-
- __exports__["default"] = EventEmitter;
- });
-define("content-kit-editor/utils/paste-utils",
- ["../constants","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var RegEx = __dependency1__.RegEx;
-
- function plainTextToBlocks(plainText, tag) {
- var blocks = plainText.split(RegEx.NEWLINE),
- len = blocks.length,
- block, openTag, closeTag, content, i;
- if(len < 2) {
- return plainText;
- } else {
- content = '';
- openTag = '<' + tag + '>';
- closeTag = '' + tag + '>';
- for(i = 0; i < len; ++i) {
- block = blocks[i];
- if(block !== '') {
- content += openTag + block + closeTag;
- }
- }
- return content;
- }
- }
-
- function cleanPastedContent(event, defaultBlockTag) {
- event.preventDefault();
- var data = event.clipboardData, plainText;
- if(data && data.getData) {
- plainText = data.getData('text/plain');
- return plainTextToBlocks(plainText, defaultBlockTag);
- }
- }
-
- __exports__.cleanPastedContent = cleanPastedContent;
- });
-define("content-kit-editor/utils/selection-utils",
- ["../constants","./element-utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var SelectionDirection = __dependency1__.SelectionDirection;
- var RootTags = __dependency1__.RootTags;
- var nodeIsDescendantOfElement = __dependency2__.nodeIsDescendantOfElement;
-
- function getDirectionOfSelection(selection) {
- var node = selection.anchorNode;
- var position = node && node.compareDocumentPosition(selection.focusNode);
- if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
- return SelectionDirection.LEFT_TO_RIGHT;
- } else if (position & Node.DOCUMENT_POSITION_PRECEDING) {
- return SelectionDirection.RIGHT_TO_LEFT;
- }
- return SelectionDirection.SAME_NODE;
- }
-
- function getSelectionElement(selection) {
- selection = selection || window.getSelection();
- var node = getDirectionOfSelection(selection) === SelectionDirection.LEFT_TO_RIGHT ? selection.anchorNode : selection.focusNode;
- return node && (node.nodeType === 3 ? node.parentNode : node);
- }
-
- function getSelectionBlockElement(selection) {
- selection = selection || window.getSelection();
- var element = getSelectionElement();
- var tag = element && element.tagName.toLowerCase();
- while (tag && RootTags.indexOf(tag) === -1) {
- if (element.contentEditable === 'true') { return; } // Stop traversing up dom when hitting an editor element
- element = element.parentNode;
- tag = element.tagName && element.tagName.toLowerCase();
- }
- return element;
- }
-
- function getSelectionTagName() {
- var element = getSelectionElement();
- return element ? element.tagName.toLowerCase() : null;
- }
-
- function getSelectionBlockTagName() {
- var element = getSelectionBlockElement();
- return element ? element.tagName && element.tagName.toLowerCase() : null;
- }
-
- function tagsInSelection(selection) {
- var element = getSelectionElement(selection);
- var tags = [];
- if (!selection.isCollapsed) {
- while(element) {
- if (element.contentEditable === 'true') { break; } // Stop traversing up dom when hitting an editor element
- if (element.tagName) {
- tags.push(element.tagName.toLowerCase());
- }
- element = element.parentNode;
- }
- }
- return tags;
- }
-
- function selectionIsInElement(selection, element) {
- var node = selection.anchorNode;
- return node && nodeIsDescendantOfElement(node, element);
- }
-
- function selectionIsEditable(selection) {
- var el = getSelectionBlockElement(selection);
- return el.isContentEditable;
- }
-
- /*
- function saveSelection() {
- var sel = window.getSelection();
- var ranges = [], i;
- if (sel.rangeCount) {
- var rangeCount = sel.rangeCount;
- for (i = 0; i < rangeCount; i++) {
- ranges.push(sel.getRangeAt(i));
- }
- }
- return ranges;
- }
-
- function restoreSelection(savedSelection) {
- var sel = window.getSelection();
- var len = savedSelection.length, i;
- sel.removeAllRanges();
- for (i = 0; i < len; i++) {
- sel.addRange(savedSelection[i]);
- }
- }
- */
-
- function moveCursorToBeginningOfSelection(selection) {
- var range = document.createRange();
- var node = selection.anchorNode;
- range.setStart(node, 0);
- range.setEnd(node, 0);
- selection.removeAllRanges();
- selection.addRange(range);
- }
-
- function restoreRange(range) {
- var selection = window.getSelection();
- selection.removeAllRanges();
- selection.addRange(range);
- }
-
- function selectNode(node) {
- var range = document.createRange();
- var selection = window.getSelection();
- range.setStart(node, 0);
- range.setEnd(node, node.length);
- selection.removeAllRanges();
- selection.addRange(range);
- }
-
- __exports__.getDirectionOfSelection = getDirectionOfSelection;
- __exports__.getSelectionElement = getSelectionElement;
- __exports__.getSelectionBlockElement = getSelectionBlockElement;
- __exports__.getSelectionTagName = getSelectionTagName;
- __exports__.getSelectionBlockTagName = getSelectionBlockTagName;
- __exports__.tagsInSelection = tagsInSelection;
- __exports__.selectionIsInElement = selectionIsInElement;
- __exports__.selectionIsEditable = selectionIsEditable;
- __exports__.moveCursorToBeginningOfSelection = moveCursorToBeginningOfSelection;
- __exports__.restoreRange = restoreRange;
- __exports__.selectNode = selectNode;
- });
-define("content-kit-editor/views/embed-intent",
- ["./view","./toolbar","../../content-kit-utils/object-utils","../utils/selection-utils","../utils/element-utils","../constants","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var View = __dependency1__["default"];
- var Toolbar = __dependency2__["default"];
- var inherit = __dependency3__.inherit;
- var getSelectionBlockElement = __dependency4__.getSelectionBlockElement;
- var elementContentIsEmpty = __dependency5__.elementContentIsEmpty;
- var positionElementToLeftOf = __dependency5__.positionElementToLeftOf;
- var positionElementCenteredIn = __dependency5__.positionElementCenteredIn;
- var ToolbarDirection = __dependency6__.ToolbarDirection;
- var Keycodes = __dependency6__.Keycodes;
- var createDiv = __dependency5__.createDiv;
-
- var LayoutStyle = {
- GUTTER : 1,
- CENTERED : 2
- };
-
- function computeLayoutStyle(rootElement) {
- if (rootElement.getBoundingClientRect().left > 100) {
- return LayoutStyle.GUTTER;
- }
- return LayoutStyle.CENTERED;
- }
-
- function EmbedIntent(options) {
- var embedIntent = this;
- var rootElement = embedIntent.rootElement = options.rootElement;
- options.tagName = 'button';
- options.classNames = ['ck-embed-intent-btn'];
- View.call(embedIntent, options);
-
- embedIntent.editorContext = options.editorContext;
- embedIntent.loadingIndicator = createDiv('ck-embed-loading');
- embedIntent.element.title = 'Insert image or embed...';
- embedIntent.element.addEventListener('mouseup', function(e) {
- if (embedIntent.isActive) {
- embedIntent.deactivate();
- } else {
- embedIntent.activate();
- }
- e.stopPropagation();
- });
-
- embedIntent.toolbar = new Toolbar({ embedIntent: embedIntent, editor: embedIntent.editorContext, commands: options.commands, direction: ToolbarDirection.RIGHT });
- embedIntent.isActive = false;
-
- function embedIntentHandler() {
- var blockElement = getSelectionBlockElement();
- if (blockElement && elementContentIsEmpty(blockElement)) {
- embedIntent.showAt(blockElement);
- } else {
- embedIntent.hide();
- }
- }
-
- rootElement.addEventListener('keyup', embedIntentHandler);
- document.addEventListener('mouseup', function() {
- setTimeout(function() { embedIntentHandler(); });
- });
-
- document.addEventListener('keyup', function(e) {
- if (e.keyCode === Keycodes.ESC) {
- embedIntent.hide();
- }
- });
-
- window.addEventListener('resize', function() {
- if(embedIntent.isShowing) {
- embedIntent.reposition();
- if (embedIntent.toolbar.isShowing) {
- embedIntent.toolbar.positionToContent(embedIntent.element);
- }
- }
- });
- }
- inherit(EmbedIntent, View);
-
- EmbedIntent.prototype.hide = function() {
- if (EmbedIntent._super.prototype.hide.call(this)) {
- this.deactivate();
- }
- };
-
- EmbedIntent.prototype.showAt = function(node) {
- this.atNode = node;
- this.show();
- this.deactivate();
- this.reposition();
- };
-
- EmbedIntent.prototype.reposition = function() {
- if (computeLayoutStyle(this.rootElement) === LayoutStyle.GUTTER) {
- positionElementToLeftOf(this.element, this.atNode);
- } else {
- positionElementCenteredIn(this.element, this.atNode);
- }
- };
-
- EmbedIntent.prototype.activate = function() {
- if (!this.isActive) {
- this.addClass('activated');
- this.toolbar.show();
- this.toolbar.positionToContent(this.element);
- this.isActive = true;
- }
- };
-
- EmbedIntent.prototype.deactivate = function() {
- if (this.isActive) {
- this.removeClass('activated');
- this.toolbar.hide();
- this.isActive = false;
- }
- };
-
- EmbedIntent.prototype.showLoading = function() {
- var embedIntent = this;
- var loadingIndicator = embedIntent.loadingIndicator;
- embedIntent.hide();
- embedIntent.container.appendChild(loadingIndicator);
- positionElementCenteredIn(loadingIndicator, embedIntent.atNode);
- };
-
- EmbedIntent.prototype.hideLoading = function() {
- this.container.removeChild(this.loadingIndicator);
- };
-
- __exports__["default"] = EmbedIntent;
- });
-define("content-kit-editor/views/message",
- ["./view","../../content-kit-utils/object-utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var View = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
-
- function Message(options) {
- options = options || {};
- options.classNames = ['ck-message'];
- View.call(this, options);
- }
- inherit(Message, View);
-
- Message.prototype.show = function(message) {
- var messageView = this;
- messageView.element.innerHTML = message;
- Message._super.prototype.show.call(messageView);
- setTimeout(function() {
- messageView.hide();
- }, 3200);
- };
-
- __exports__["default"] = Message;
- });
-define("content-kit-editor/views/prompt",
- ["./view","../../content-kit-utils/object-utils","../utils/selection-utils","../utils/element-utils","../constants","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
- "use strict";
- var View = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var inherit = __dependency2__.inherit;
- var restoreRange = __dependency3__.restoreRange;
- var createDiv = __dependency4__.createDiv;
- var positionElementToRect = __dependency4__.positionElementToRect;
- var Keycodes = __dependency5__.Keycodes;
-
- var container = document.body;
- var hiliter = createDiv('ck-editor-hilite');
-
- function positionHiliteRange(range) {
- var rect = range.getBoundingClientRect();
- var style = hiliter.style;
- style.width = rect.width + 'px';
- style.height = rect.height + 'px';
- positionElementToRect(hiliter, rect);
- }
-
- function Prompt(options) {
- var prompt = this;
- options.tagName = 'input';
- View.call(prompt, options);
-
- prompt.command = options.command;
- prompt.element.placeholder = options.placeholder || '';
- prompt.element.addEventListener('mouseup', function(e) { e.stopPropagation(); }); // prevents closing prompt when clicking input
- prompt.element.addEventListener('keyup', function(e) {
- var entry = this.value;
- if(entry && prompt.range && !e.shiftKey && e.which === Keycodes.ENTER) {
- restoreRange(prompt.range);
- prompt.command.exec(entry);
- if (prompt.onComplete) { prompt.onComplete(); }
- }
- });
-
- window.addEventListener('resize', function() {
- var activeHilite = hiliter.parentNode;
- var range = prompt.range;
- if(activeHilite && range) {
- positionHiliteRange(range);
- }
- });
- }
- inherit(Prompt, View);
-
- Prompt.prototype.show = function(callback) {
- var prompt = this;
- var element = prompt.element;
- var selection = window.getSelection();
- var range = selection && selection.rangeCount && selection.getRangeAt(0);
- element.value = null;
- prompt.range = range || null;
- if (range) {
- container.appendChild(hiliter);
- positionHiliteRange(prompt.range);
- setTimeout(function(){ element.focus(); }); // defer focus (disrupts mouseup events)
- if (callback) { prompt.onComplete = callback; }
- }
- };
-
- Prompt.prototype.hide = function() {
- if (hiliter.parentNode) {
- container.removeChild(hiliter);
- }
- };
-
- __exports__["default"] = Prompt;
- });
-define("content-kit-editor/views/text-format-toolbar",
- ["./toolbar","../../content-kit-utils/object-utils","../utils/selection-utils","../constants","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Toolbar = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var selectionIsEditable = __dependency3__.selectionIsEditable;
- var selectionIsInElement = __dependency3__.selectionIsInElement;
- var Keycodes = __dependency4__.Keycodes;
-
- function handleTextSelection(toolbar) {
- var selection = window.getSelection();
- if (selection.isCollapsed || !selectionIsEditable(selection) || selection.toString().trim() === '' || !selectionIsInElement(selection, toolbar.rootElement)) {
- toolbar.hide();
- } else {
- toolbar.show();
- toolbar.updateForSelection(selection);
- }
- }
-
- function TextFormatToolbar(options) {
- var toolbar = this;
- Toolbar.call(this, options);
- toolbar.rootElement = options.rootElement;
- toolbar.rootElement.addEventListener('keyup', function() { handleTextSelection(toolbar); });
-
- document.addEventListener('mouseup', function() {
- setTimeout(function() {
- handleTextSelection(toolbar);
- });
- });
-
- document.addEventListener('keyup', function(e) {
- if (e.keyCode === Keycodes.ESC) {
- toolbar.hide();
- }
- });
-
- window.addEventListener('resize', function() {
- if(toolbar.isShowing) {
- var activePromptRange = toolbar.activePrompt && toolbar.activePrompt.range;
- toolbar.positionToContent(activePromptRange ? activePromptRange : window.getSelection().getRangeAt(0));
- }
- });
- }
- inherit(TextFormatToolbar, Toolbar);
-
- __exports__["default"] = TextFormatToolbar;
- });
-define("content-kit-editor/views/toolbar-button",
- ["../commands/base","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Command = __dependency1__["default"];
-
- var buttonClassName = 'ck-toolbar-btn';
-
- function ToolbarButton(options) {
- var button = this;
- var toolbar = options.toolbar;
- var command = options.command;
- var prompt = command.prompt;
- var element = document.createElement('button');
-
- if(typeof command === 'string') {
- command = Command.index[command];
- }
-
- button.element = element;
- button.command = command;
- button.isActive = false;
-
- element.title = command.name;
- element.className = buttonClassName;
- element.innerHTML = command.button;
- element.addEventListener('mouseup', function(e) {
- if (!button.isActive && prompt) {
- toolbar.displayPrompt(prompt);
- } else {
- command.exec();
- toolbar.updateForSelection();
- }
- e.stopPropagation();
- });
- }
-
- ToolbarButton.prototype = {
- setActive: function() {
- var button = this;
- if (!button.isActive) {
- button.element.className = buttonClassName + ' active';
- button.isActive = true;
- }
- },
- setInactive: function() {
- var button = this;
- if (button.isActive) {
- button.element.className = buttonClassName;
- button.isActive = false;
- }
- }
- };
-
- __exports__["default"] = ToolbarButton;
- });
-define("content-kit-editor/views/toolbar",
- ["./view","./toolbar-button","../../content-kit-utils/object-utils","../utils/selection-utils","../constants","../utils/element-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) {
- "use strict";
- var View = __dependency1__["default"];
- var ToolbarButton = __dependency2__["default"];
- var inherit = __dependency3__.inherit;
- var tagsInSelection = __dependency4__.tagsInSelection;
- var ToolbarDirection = __dependency5__.ToolbarDirection;
- var createDiv = __dependency6__.createDiv;
- var swapElements = __dependency6__.swapElements;
- var positionElementToRightOf = __dependency6__.positionElementToRightOf;
- var positionElementCenteredAbove = __dependency6__.positionElementCenteredAbove;
-
- function updateButtonsForSelection(buttons, selection) {
- var selectedTags = tagsInSelection(selection),
- len = buttons.length,
- i, button;
-
- for (i = 0; i < len; i++) {
- button = buttons[i];
- if (selectedTags.indexOf(button.command.tag) > -1) {
- button.setActive();
- } else {
- button.setInactive();
- }
- }
- }
-
- function Toolbar(options) {
- var toolbar = this;
- var commands = options.commands;
- var commandCount = commands && commands.length, i;
- options.classNames = ['ck-toolbar'];
- View.call(toolbar, options);
-
- toolbar.editor = options.editor || null;
- toolbar.embedIntent = options.embedIntent || null;
- toolbar.activePrompt = null;
- toolbar.buttons = [];
- toolbar.setDirection(options.direction || ToolbarDirection.TOP);
-
- toolbar.promptContainerElement = createDiv('ck-toolbar-prompt');
- toolbar.buttonContainerElement = createDiv('ck-toolbar-buttons');
- toolbar.element.appendChild(toolbar.promptContainerElement);
- toolbar.element.appendChild(toolbar.buttonContainerElement);
-
- for(i = 0; i < commandCount; i++) {
- this.addCommand(commands[i]);
- }
-
- // Closes prompt if displayed when changing selection
- document.addEventListener('mouseup', function() {
- toolbar.dismissPrompt();
- });
- }
- inherit(Toolbar, View);
-
- Toolbar.prototype.hide = function() {
- if (Toolbar._super.prototype.hide.call(this)) {
- var style = this.element.style;
- style.left = '';
- style.top = '';
- this.dismissPrompt();
- }
- };
-
- Toolbar.prototype.addCommand = function(command) {
- command.editorContext = this.editor;
- command.embedIntent = this.embedIntent;
- var button = new ToolbarButton({ command: command, toolbar: this });
- this.buttons.push(button);
- this.buttonContainerElement.appendChild(button.element);
- };
-
- Toolbar.prototype.displayPrompt = function(prompt) {
- var toolbar = this;
- swapElements(toolbar.promptContainerElement, toolbar.buttonContainerElement);
- toolbar.promptContainerElement.appendChild(prompt.element);
- prompt.show(function() {
- toolbar.dismissPrompt();
- toolbar.updateForSelection();
- });
- toolbar.activePrompt = prompt;
- };
-
- Toolbar.prototype.dismissPrompt = function() {
- var toolbar = this;
- var activePrompt = toolbar.activePrompt;
- if (activePrompt) {
- activePrompt.hide();
- swapElements(toolbar.buttonContainerElement, toolbar.promptContainerElement);
- toolbar.activePrompt = null;
- }
- };
-
- Toolbar.prototype.updateForSelection = function(selection) {
- var toolbar = this;
- selection = selection || window.getSelection();
- if (!selection.isCollapsed) {
- toolbar.positionToContent(selection.getRangeAt(0));
- updateButtonsForSelection(toolbar.buttons, selection);
- }
- };
-
- Toolbar.prototype.positionToContent = function(content) {
- var directions = ToolbarDirection;
- var positioningMethod;
- switch(this.direction) {
- case directions.RIGHT:
- positioningMethod = positionElementToRightOf;
- break;
- default:
- positioningMethod = positionElementCenteredAbove;
- }
- positioningMethod(this.element, content);
- };
-
- Toolbar.prototype.setDirection = function(direction) {
- this.direction = direction;
- if (direction === ToolbarDirection.RIGHT) {
- this.addClass('right');
- } else {
- this.removeClass('right');
- }
- };
-
- __exports__["default"] = Toolbar;
- });
-define("content-kit-editor/views/tooltip",
- ["./view","../../content-kit-utils/object-utils","../utils/element-utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var View = __dependency1__["default"];
- var inherit = __dependency2__.inherit;
- var positionElementCenteredBelow = __dependency3__.positionElementCenteredBelow;
- var getEventTargetMatchingTag = __dependency3__.getEventTargetMatchingTag;
-
- function Tooltip(options) {
- var tooltip = this;
- var rootElement = options.rootElement;
- var delay = options.delay || 200;
- var timeout;
- options.classNames = ['ck-tooltip'];
- View.call(tooltip, options);
-
- rootElement.addEventListener('mouseover', function(e) {
- var target = getEventTargetMatchingTag(options.showForTag, e.target, rootElement);
- if (target && target.isContentEditable) {
- timeout = setTimeout(function() {
- tooltip.showLink(target.href, target);
- }, delay);
- }
- });
-
- rootElement.addEventListener('mouseout', function(e) {
- clearTimeout(timeout);
- var toElement = e.toElement || e.relatedTarget;
- if (toElement && toElement.className !== tooltip.element.className) {
- tooltip.hide();
- }
- });
- }
- inherit(Tooltip, View);
-
- Tooltip.prototype.showMessage = function(message, element) {
- var tooltip = this;
- var tooltipElement = tooltip.element;
- tooltipElement.innerHTML = message;
- tooltip.show();
- positionElementCenteredBelow(tooltipElement, element);
- };
-
- Tooltip.prototype.showLink = function(link, element) {
- var message = ' ' + link + ' ';
- this.showMessage(message, element);
- };
-
- __exports__["default"] = Tooltip;
- });
-define("content-kit-editor/views/view",
- ["exports"],
- function(__exports__) {
- "use strict";
- function View(options) {
- this.tagName = options.tagName || 'div';
- this.classNames = options.classNames || [];
- this.element = document.createElement(this.tagName);
- this.element.className = this.classNames.join(' ');
- this.container = options.container || document.body;
- this.isShowing = false;
- }
-
- View.prototype = {
- show: function() {
- var view = this;
- if(!view.isShowing) {
- view.container.appendChild(view.element);
- view.isShowing = true;
- return true;
- }
- },
- hide: function() {
- var view = this;
- if(view.isShowing) {
- view.container.removeChild(view.element);
- view.isShowing = false;
- return true;
- }
- },
- focus: function() {
- this.element.focus();
- },
- addClass: function(className) {
- var index = this.classNames.indexOf(className);
- if (index === -1) {
- this.classNames.push(className);
- this.element.className = this.classNames.join(' ');
- }
- },
- removeClass: function(className) {
- var index = this.classNames.indexOf(className);
- if (index > -1) {
- this.classNames.splice(index, 1);
- this.element.className = this.classNames.join(' ');
- }
- }
- };
-
- __exports__["default"] = View;
- });
-define("content-kit-compiler/renderers/embeds/instagram",
- ["exports"],
- function(__exports__) {
- "use strict";
-
- function InstagramRenderer() {}
- InstagramRenderer.prototype.render = function(model) {
- return ' ';
- };
-
- __exports__["default"] = InstagramRenderer;
- });
-define("content-kit-compiler/renderers/embeds/link",
- ["exports"],
- function(__exports__) {
- "use strict";
-
- function LinkEmbedRenderer() {}
- LinkEmbedRenderer.prototype.render = function(model) {
- return ' ';
- };
-
- __exports__["default"] = LinkEmbedRenderer;
- });
-define("content-kit-compiler/renderers/embeds/photo",
- ["exports"],
- function(__exports__) {
- "use strict";
-
- function PhotoEmbedRenderer() {}
- PhotoEmbedRenderer.prototype.render = function(model) {
- return ' ';
- };
-
- __exports__["default"] = PhotoEmbedRenderer;
- });
-define("content-kit-compiler/renderers/embeds/twitter",
- ["exports"],
- function(__exports__) {
- "use strict";
-
- function TwitterRenderer() {}
- TwitterRenderer.prototype.render = function(model) {
- return '';
- };
-
- __exports__["default"] = TwitterRenderer;
- });
-define("content-kit-compiler/renderers/embeds/youtube",
- ["exports"],
- function(__exports__) {
- "use strict";
-
- var RegExVideoId = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/;
-
- function getVideoIdFromUrl(url) {
- var match = url && url.match(RegExVideoId);
- if (match && match[1].length === 11){
- return match[1];
- }
- return null;
- }
-
- function YouTubeRenderer() {}
- YouTubeRenderer.prototype.render = function(model) {
- var videoId = getVideoIdFromUrl(model.attributes.url);
- var embedUrl = 'http://www.youtube.com/embed/' + videoId + '?controls=2&showinfo=0&color=white&theme=light';
- return '';
- };
-
- __exports__["default"] = YouTubeRenderer;
- });
-}(this, document));
diff --git a/package.json b/package.json
index 3ec73e4fb..f7f321b64 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,8 @@
"repository": "https://github.com/ContentKit/content-kit-editor",
"main": "dist/content-kit-editor.js",
"scripts": {
- "test": "gulp test"
+ "start" : "node server/index.js",
+ "test" : "gulp test"
},
"keywords": [
"html",
@@ -16,6 +17,13 @@
],
"author": "Garth Poitras (http://garthpoitras.com/)",
"license": "MIT",
+ "dependencies": {
+ "aws-sdk": "^2.0.17",
+ "busboy": "^0.2.8",
+ "cors": "^2.4.1",
+ "embedly": "^1.0.2",
+ "express": "^4.9.0"
+ },
"devDependencies": {
"gulp": "^3.8.1",
"gulp-concat": "~2.1.7",
diff --git a/demo/screenshot.png b/screenshot.png
similarity index 100%
rename from demo/screenshot.png
rename to screenshot.png
diff --git a/server/config.json b/server/config.json
new file mode 100644
index 000000000..8cc8b42a2
--- /dev/null
+++ b/server/config.json
@@ -0,0 +1,15 @@
+{
+ "aws" : {
+ "accessKeyId" : null,
+ "secretAccessKey" : null,
+ "region" : "us-east-1"
+ },
+ "s3" : {
+ "bucketName" : null,
+ "maxFileSize" : 5000000
+ },
+ "embedlyKey" : null,
+ "cors" : {
+ "origin" : "*"
+ }
+}
\ No newline at end of file
diff --git a/server/index.js b/server/index.js
new file mode 100644
index 000000000..77fcfea67
--- /dev/null
+++ b/server/index.js
@@ -0,0 +1,27 @@
+var express = require('express');
+var cors = require('cors');
+var config = require('./config');
+var S3UploadService = require('./services/s3-uploader');
+var EmbedService = require('./services/embed');
+
+// Express app
+var app = express();
+app.use(cors(config.cors));
+
+// Demo setup
+app.use(express.static('demo'));
+app.use(express.static('dist'));
+app.use(express.static('ext'));
+app.get('/', function(req, res) {
+ res.sendFile('/');
+});
+
+// Routes
+app.post('/upload', S3UploadService);
+app.get('/embed', EmbedService);
+
+app.listen(5000, function() {
+ console.log('content-kit-editor server: listening on port %d', this.address().port);
+});
+
+module.exports = app;
diff --git a/server/services/embed.js b/server/services/embed.js
new file mode 100644
index 000000000..1fc370b7b
--- /dev/null
+++ b/server/services/embed.js
@@ -0,0 +1,35 @@
+var embedly = require('embedly');
+var util = require('util');
+
+var EMBEDLY_KEY = 'XXXXXX';
+
+module.exports = function(req, res) {
+
+ new embedly({key: EMBEDLY_KEY}, function(err, api) {
+ if (!!err) {
+ console.error('Error creating Embedly api');
+ console.error(err.stack, api);
+ return res.status(500).json(err);
+ }
+
+ var url = req.query.url;
+ if (!(/^https?:\/\//i).test(url)) {
+ url = 'http://' + url;
+ }
+
+ api.oembed({url: url}, function(err, objs) {
+ if (!!err) {
+ console.error(err.stack, objs);
+ return res.status(500).json(err);
+ }
+
+ if (objs[0].error_message) {
+ return res.status(500).json(objs[0].error_message);
+ }
+ console.log(util.inspect(objs[0]));
+ res.json(objs[0]);
+ });
+
+ });
+
+};
diff --git a/server/services/s3-uploader.js b/server/services/s3-uploader.js
new file mode 100644
index 000000000..06de47894
--- /dev/null
+++ b/server/services/s3-uploader.js
@@ -0,0 +1,84 @@
+var crypto = require('crypto');
+var Busboy = require('busboy');
+var AWS = require('aws-sdk');
+var config = require('../config');
+
+AWS.config = config.aws;
+var maxFileSize = config.s3.maxFileSize || 5000000;
+var uploadBucket = config.s3.bucketName;
+var s3 = new AWS.S3({ params: { Bucket: uploadBucket } });
+
+function readFileStream(req, res) {
+ var busboy = new Busboy({
+ headers: req.headers,
+ limits: { fileSize: maxFileSize }
+ });
+
+ busboy.on('file', function(fieldname, stream, filename, encoding, mimeType) {
+ if (!filename) {
+ stream.resume();
+ return res.json(500, { message: 'invalid file', status: 500 });
+ }
+ req.files = req.files || {};
+
+ stream.chunks = [];
+ stream.on('data', function(chunk) {
+ this.chunks.push(chunk);
+ });
+
+ stream.on('error', function(error) {
+ return res.json(500, { message: 'error reading file', status: 500 });
+ });
+
+ stream.on('end', function() {
+ if (this.truncated) {
+ return res.json(500, { message: 'max file size is ' + maxFileSize + ' bytes', status: 500 });
+ }
+ var finalBuffer = Buffer.concat(this.chunks);
+ var file = req.files[fieldname] = {
+ buffer : finalBuffer,
+ size : finalBuffer.length,
+ filename : renameFile(filename),
+ mimeType : mimeType
+ };
+ putFileBufferToS3(file, res);
+ });
+ });
+
+ req.pipe(busboy);
+}
+
+function renameFile(filename) {
+ var ext = filename.indexOf('.') > 0 ? '.' + filename.split('.').slice(-1)[0] : '';
+ var bareFilename = filename.replace(ext, '');
+ var randomString = filename + Date.now() + Math.random();
+ randomString = crypto.createHash('md5').update(randomString).digest('hex');
+ return randomString + ext;
+}
+
+function putFileBufferToS3(file, res) {
+ var key = file.filename;
+ var params = {
+ Key: key,
+ Body: file.buffer,
+ ContentType: file.mimeType,
+ ContentLength: file.size,
+ ACL: 'public-read'
+ };
+
+ var request = s3.putObject(params, function(error, data) {
+ if (error) {
+ return res.json(500, { message: 'error uploading to S3', status: 500 });
+ }
+ res.json({ url: 'https://s3.amazonaws.com/' + uploadBucket + '/' + key });
+ });
+
+ // Can we send this to the client?
+ /*
+ request.on('httpUploadProgress', function (progress) {
+ console.log('Uploaded', progress.loaded, 'of', progress.total, 'bytes');
+ });
+ */
+}
+
+module.exports = readFileStream;
diff --git a/src/js/ext/loader.js b/src/js/ext/loader.js
deleted file mode 100644
index aec6b8743..000000000
--- a/src/js/ext/loader.js
+++ /dev/null
@@ -1,136 +0,0 @@
-var define, requireModule, require, requirejs;
-
-(function() {
-
- var _isArray;
- if (!Array.isArray) {
- _isArray = function (x) {
- return Object.prototype.toString.call(x) === "[object Array]";
- };
- } else {
- _isArray = Array.isArray;
- }
-
- var registry = {}, seen = {};
- var FAILED = false;
-
- var uuid = 0;
-
- function tryFinally(tryable, finalizer) {
- try {
- return tryable();
- } finally {
- finalizer();
- }
- }
-
-
- function Module(name, deps, callback, exports) {
- var defaultDeps = ['require', 'exports', 'module'];
-
- this.id = uuid++;
- this.name = name;
- this.deps = !deps.length && callback.length ? defaultDeps : deps;
- this.exports = exports || { };
- this.callback = callback;
- this.state = undefined;
- }
-
- define = function(name, deps, callback) {
- if (!_isArray(deps)) {
- callback = deps;
- deps = [];
- }
-
- registry[name] = new Module(name, deps, callback);
- };
-
- define.amd = {};
-
- function reify(mod, name, seen) {
- var deps = mod.deps;
- var length = deps.length;
- var reified = new Array(length);
- var dep;
- // TODO: new Module
- // TODO: seen refactor
- var module = { };
-
- for (var i = 0, l = length; i < l; i++) {
- dep = deps[i];
- if (dep === 'exports') {
- module.exports = reified[i] = seen;
- } else if (dep === 'require') {
- reified[i] = require;
- } else if (dep === 'module') {
- mod.exports = seen;
- module = reified[i] = mod;
- } else {
- reified[i] = require(resolve(dep, name));
- }
- }
-
- return {
- deps: reified,
- module: module
- };
- }
-
- requirejs = require = requireModule = function(name) {
- var mod = registry[name];
- if (!mod) {
- throw new Error('Could not find module ' + name);
- }
-
- if (mod.state !== FAILED &&
- seen.hasOwnProperty(name)) {
- return seen[name];
- }
-
- var reified;
- var module;
- var loaded = false;
-
- seen[name] = { }; // placeholder for run-time cycles
-
- tryFinally(function() {
- reified = reify(mod, name, seen[name]);
- module = mod.callback.apply(this, reified.deps);
- loaded = true;
- }, function() {
- if (!loaded) {
- mod.state = FAILED;
- }
- });
-
- if (module === undefined && reified.module.exports) {
- return (seen[name] = reified.module.exports);
- } else {
- return (seen[name] = module);
- }
- };
-
- function resolve(child, name) {
- if (child.charAt(0) !== '.') { return child; }
-
- var parts = child.split('/');
- var nameParts = name.split('/');
- var parentBase = nameParts.slice(0, -1);
-
- for (var i = 0, l = parts.length; i < l; i++) {
- var part = parts[i];
-
- if (part === '..') { parentBase.pop(); }
- else if (part === '.') { continue; }
- else { parentBase.push(part); }
- }
-
- return parentBase.join('/');
- }
-
- requirejs.entries = requirejs._eak_seen = registry;
- requirejs.clear = function(){
- requirejs.entries = requirejs._eak_seen = registry = {};
- seen = state = {};
- };
-})();