written 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/LICENSE +8 -0
  4. data/README.md +63 -0
  5. data/Rakefile +17 -27
  6. data/lib/written.rb +0 -8
  7. data/lib/written/app/assets/images/written/placeholder.png +0 -0
  8. data/lib/written/app/assets/javascripts/written.coffee +2 -0
  9. data/lib/written/app/assets/javascripts/written/core/content.coffee +53 -35
  10. data/lib/written/app/assets/javascripts/written/core/cursor.coffee +33 -12
  11. data/lib/written/app/assets/javascripts/written/core/document.coffee +16 -11
  12. data/lib/written/app/assets/javascripts/written/core/extensions/string.coffee +9 -0
  13. data/lib/written/app/assets/javascripts/written/core/extensions/text.coffee +2 -0
  14. data/lib/written/app/assets/javascripts/written/core/history.coffee +2 -0
  15. data/lib/written/app/assets/javascripts/written/core/observer.coffee +6 -2
  16. data/lib/written/app/assets/javascripts/written/core/stringify.coffee +15 -0
  17. data/lib/written/app/assets/javascripts/written/parsers/block.coffee +69 -0
  18. data/lib/written/app/assets/javascripts/written/parsers/block/code.coffee +79 -15
  19. data/lib/written/app/assets/javascripts/written/parsers/block/heading.coffee +60 -5
  20. data/lib/written/app/assets/javascripts/written/parsers/block/image.coffee +103 -9
  21. data/lib/written/app/assets/javascripts/written/parsers/block/olist.coffee +94 -12
  22. data/lib/written/app/assets/javascripts/written/parsers/block/paragraph.coffee +63 -5
  23. data/lib/written/app/assets/javascripts/written/parsers/block/quote.coffee +92 -0
  24. data/lib/written/app/assets/javascripts/written/parsers/block/ulist.coffee +93 -12
  25. data/lib/written/app/assets/javascripts/written/parsers/inline.coffee +81 -0
  26. data/lib/written/app/assets/javascripts/written/parsers/inline/code.coffee +57 -0
  27. data/lib/written/app/assets/javascripts/written/parsers/inline/italic.coffee +40 -7
  28. data/lib/written/app/assets/javascripts/written/parsers/inline/link.coffee +43 -13
  29. data/lib/written/app/assets/javascripts/written/parsers/inline/list.coffee +27 -0
  30. data/lib/written/app/assets/javascripts/written/parsers/inline/strong.coffee +41 -7
  31. data/lib/written/app/assets/javascripts/written/parsers/parsers.coffee +21 -107
  32. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/CustomElements.js +32 -0
  33. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/base.js +40 -0
  34. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/boot.js +124 -0
  35. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/observe.js +318 -0
  36. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/register.js +369 -0
  37. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/traverse.js +86 -0
  38. data/lib/written/app/assets/javascripts/written/polyfills/CustomElements/upgrade.js +130 -0
  39. data/lib/written/app/assets/javascripts/written/polyfills/MutationObserver/MutationObserver.js +575 -0
  40. data/lib/written/app/assets/javascripts/written/polyfills/WeakMap/WeakMap.js +49 -0
  41. data/lib/written/app/assets/javascripts/written/polyfills/base.coffee +10 -0
  42. data/lib/written/app/assets/javascripts/written/polyfills/dom.js +104 -0
  43. data/lib/written/app/assets/javascripts/written/uploaders/aws.coffee +125 -0
  44. data/lib/written/app/assets/stylesheets/written.scss +80 -11
  45. data/lib/written/version.rb +1 -1
  46. data/test/server/app/assets/javascripts/application.coffee +20 -2
  47. data/test/server/app/assets/stylesheets/application.scss +2 -2
  48. data/test/server/app/assets/stylesheets/prism.css +0 -1
  49. data/test/server/app/views/posts/show.html.erb +10 -3
  50. metadata +26 -20
  51. data/lib/written/app/assets/javascripts/written/core/ext.coffee +0 -109
  52. data/lib/written/app/assets/javascripts/written/core/extensions.coffee +0 -2
  53. data/lib/written/document.rb +0 -42
  54. data/lib/written/node.rb +0 -21
  55. data/lib/written/nodes/code.rb +0 -65
  56. data/lib/written/nodes/heading.rb +0 -15
  57. data/lib/written/nodes/image.rb +0 -14
  58. data/lib/written/nodes/ordered_list.rb +0 -18
  59. data/lib/written/nodes/unordered_list.rb +0 -19
  60. data/lib/written/parsers.rb +0 -11
  61. data/lib/written/parsers/base.rb +0 -26
  62. data/lib/written/parsers/code.rb +0 -60
  63. data/lib/written/parsers/heading.rb +0 -19
  64. data/lib/written/parsers/image.rb +0 -19
  65. data/lib/written/parsers/link.rb +0 -12
  66. data/lib/written/parsers/list.rb +0 -33
  67. data/lib/written/parsers/word.rb +0 -16
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4
+ * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5
+ * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6
+ * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7
+ * Code distributed by Google as part of the polymer project is also
8
+ * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9
+ */
10
+
11
+ if (typeof WeakMap === 'undefined') {
12
+ (function() {
13
+ var defineProperty = Object.defineProperty;
14
+ var counter = Date.now() % 1e9;
15
+
16
+ var WeakMap = function() {
17
+ this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
18
+ };
19
+
20
+ WeakMap.prototype = {
21
+ set: function(key, value) {
22
+ var entry = key[this.name];
23
+ if (entry && entry[0] === key)
24
+ entry[1] = value;
25
+ else
26
+ defineProperty(key, this.name, {value: [key, value], writable: true});
27
+ return this;
28
+ },
29
+ get: function(key) {
30
+ var entry;
31
+ return (entry = key[this.name]) && entry[0] === key ?
32
+ entry[1] : undefined;
33
+ },
34
+ delete: function(key) {
35
+ var entry = key[this.name];
36
+ if (!entry || entry[0] !== key) return false;
37
+ entry[0] = entry[1] = undefined;
38
+ return true;
39
+ },
40
+ has: function(key) {
41
+ var entry = key[this.name];
42
+ if (!entry) return false;
43
+ return entry[0] === key;
44
+ }
45
+ };
46
+
47
+ window.WeakMap = WeakMap;
48
+ })();
49
+ }
@@ -0,0 +1,10 @@
1
+ #= require './WeakMap/WeakMap'
2
+ #= require './MutationObserver/MutationObserver'
3
+ #= require './dom'
4
+ #= require './CustomElements/CustomElements'
5
+ #= require './CustomElements/base'
6
+ #= require './CustomElements/traverse'
7
+ #= require './CustomElements/observe'
8
+ #= require './CustomElements/upgrade'
9
+ #= require './CustomElements/register'
10
+ #= require './CustomElements/boot'
@@ -0,0 +1,104 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
4
+ * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5
+ * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6
+ * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7
+ * Code distributed by Google as part of the polymer project is also
8
+ * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9
+ */
10
+
11
+ (function(scope) {
12
+
13
+ 'use strict';
14
+
15
+ // polyfill performance.now
16
+
17
+ if (!window.performance) {
18
+ var start = Date.now();
19
+ // only at millisecond precision
20
+ window.performance = {now: function(){ return Date.now() - start; }};
21
+ }
22
+
23
+ // polyfill for requestAnimationFrame
24
+
25
+ if (!window.requestAnimationFrame) {
26
+ window.requestAnimationFrame = (function() {
27
+ var nativeRaf = window.webkitRequestAnimationFrame ||
28
+ window.mozRequestAnimationFrame;
29
+
30
+ return nativeRaf ?
31
+ function(callback) {
32
+ return nativeRaf(function() {
33
+ callback(performance.now());
34
+ });
35
+ } :
36
+ function( callback ){
37
+ return window.setTimeout(callback, 1000 / 60);
38
+ };
39
+ })();
40
+ }
41
+
42
+ if (!window.cancelAnimationFrame) {
43
+ window.cancelAnimationFrame = (function() {
44
+ return window.webkitCancelAnimationFrame ||
45
+ window.mozCancelAnimationFrame ||
46
+ function(id) {
47
+ clearTimeout(id);
48
+ };
49
+ })();
50
+ }
51
+
52
+ // defaultPrevented is broken in IE.
53
+ // https://connect.microsoft.com/IE/feedback/details/790389/event-defaultprevented-returns-false-after-preventdefault-was-called
54
+ var workingDefaultPrevented = (function() {
55
+ var e = document.createEvent('Event');
56
+ e.initEvent('foo', true, true);
57
+ e.preventDefault();
58
+ return e.defaultPrevented;
59
+ })();
60
+
61
+ if (!workingDefaultPrevented) {
62
+ var origPreventDefault = Event.prototype.preventDefault;
63
+ Event.prototype.preventDefault = function() {
64
+ if (!this.cancelable) {
65
+ return;
66
+ }
67
+
68
+ origPreventDefault.call(this);
69
+
70
+ Object.defineProperty(this, 'defaultPrevented', {
71
+ get: function() {
72
+ return true;
73
+ },
74
+ configurable: true
75
+ });
76
+ };
77
+ }
78
+
79
+ var isIE = /Trident/.test(navigator.userAgent);
80
+
81
+ // CustomEvent constructor shim
82
+ if (!window.CustomEvent || isIE && (typeof window.CustomEvent !== 'function')) {
83
+ window.CustomEvent = function(inType, params) {
84
+ params = params || {};
85
+ var e = document.createEvent('CustomEvent');
86
+ e.initCustomEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable), params.detail);
87
+ return e;
88
+ };
89
+ window.CustomEvent.prototype = window.Event.prototype;
90
+ }
91
+
92
+ // Event constructor shim
93
+ if (!window.Event || isIE && (typeof window.Event !== 'function')) {
94
+ var origEvent = window.Event;
95
+ window.Event = function(inType, params) {
96
+ params = params || {};
97
+ var e = document.createEvent('Event');
98
+ e.initEvent(inType, Boolean(params.bubbles), Boolean(params.cancelable));
99
+ return e;
100
+ };
101
+ window.Event.prototype = origEvent.prototype;
102
+ }
103
+
104
+ })(window.WebComponents);
@@ -0,0 +1,125 @@
1
+ class Written.Uploaders.AWS
2
+ constructor: (settings) ->
3
+ Images.settings = settings
4
+
5
+ initialize: (node, observer) =>
6
+ img = node.querySelector('img')
7
+ container = node.querySelector('div')
8
+
9
+ node.dataset.uploadable = true
10
+ node.addEventListener 'written:uploader:error', @error, true
11
+ node.addEventListener 'written:uploader:uploading', @progress, true
12
+ node.addEventListener 'written:uploader:completed', @uploaded, true
13
+ node.addEventListener 'change', @input.bind(this, node, observer), true
14
+
15
+ container.addEventListener 'click', @open.bind(this, node), true
16
+ image = Images.get(img.dataset.image)
17
+ if image
18
+ image.node = node
19
+
20
+ open: (node, e) =>
21
+ node.querySelector('input')?.click()
22
+
23
+ uploaded: (e) =>
24
+ caption = e.target.querySelector('figcaption')
25
+ img = e.target.querySelector('img')
26
+
27
+ text = caption.childNodes[caption.childNodes.length - 1]
28
+ text.textContent = "(#{e.image.url})"
29
+ img.src = e.image.url
30
+ selection = window.getSelection()
31
+ selection.removeAllRanges()
32
+ range = document.createRange()
33
+ range.setEnd(text, text.textContent.length - 1)
34
+ selection.addRange(range)
35
+
36
+ error: (e) =>
37
+ console.log(e)
38
+
39
+ input: (node, history, e) =>
40
+ file = e.target.files[0]
41
+ @process(file, node, history)
42
+
43
+ process: (file, node) =>
44
+ caption = node.querySelector('figcaption')
45
+ progress = node.querySelector('div.progress')
46
+ filename = [Images.settings.namespace, @hash(file.name)].join('/')
47
+
48
+ image = Images.get(filename)
49
+ if !image
50
+ image = Images.upload(filename, file)
51
+
52
+ image.node = node
53
+ progress.style.width = image.progress
54
+ node.dataset.status = image.status
55
+
56
+ text = caption.childNodes[caption.childNodes.length - 1]
57
+ text.textContent = "(#{filename})"
58
+ selection = window.getSelection()
59
+ selection.removeAllRanges()
60
+ range = document.createRange()
61
+ range.setEnd(text, text.textContent.length - 1)
62
+ selection.addRange(range)
63
+
64
+ hash: (filename) ->
65
+ hash = 0
66
+ for i in [0..filename.length - 1]
67
+ hash += filename.charCodeAt(i) ^ hash
68
+
69
+ hash.toString('16')
70
+
71
+ Images = new class
72
+ constructor: ->
73
+ @cache = {}
74
+
75
+ failed: (image, event) ->
76
+ image.status = 'failed'
77
+
78
+ if image.node?
79
+ event = new CustomEvent('written:uploader:error', {bubbles: true})
80
+ event.image = image
81
+ image.node.dispatchEvent(event)
82
+
83
+ update: (image, event) ->
84
+ image.status = 'completed'
85
+
86
+ if image.node?
87
+ event = new CustomEvent('written:uploader:completed', {bubbles: true})
88
+ event.image = image
89
+ image.node.dispatchEvent(event)
90
+
91
+ upload: (name, file) =>
92
+ image = {
93
+ url: "#{@settings.url}/#{name}"
94
+ name: name
95
+ status: 'uploading'
96
+ progress: 0
97
+ }
98
+
99
+ form = new FormData()
100
+ form.append('key', name)
101
+ form.append('acl', 'private')
102
+ form.append("AWSAccessKeyId", @settings.accessKey)
103
+ form.append('policy', @settings.policy)
104
+ form.append('signature', @settings.signature)
105
+ form.append('Content-Type', file.type)
106
+ form.append('file', file, name)
107
+
108
+
109
+ image.xhr = @send(form, @settings.url)
110
+ image.xhr.addEventListener('load', @update.bind(this, image))
111
+ image.xhr.addEventListener('error', @failed.bind(this, image))
112
+
113
+ @cache[image.name] = image
114
+
115
+
116
+ get: (name) ->
117
+ @cache[name]
118
+
119
+ send: (form, url) =>
120
+ xhr = new XMLHttpRequest()
121
+ xhr.open('POST', url)
122
+ xhr.send(form)
123
+ xhr
124
+
125
+
@@ -1,5 +1,6 @@
1
1
  [data-editor="written"] {
2
2
  white-space: pre-wrap;
3
+ padding: 1em;
3
4
 
4
5
  p {
5
6
  min-height: 1.2em;
@@ -13,20 +14,88 @@
13
14
  list-style-type: none;
14
15
  }
15
16
 
16
- figure {
17
- background: rgba(230,230,230,1);
17
+ blockquote {
18
+ background: #eee;
19
+ border-radius: 2px;
20
+ padding: 0.5em 1em;
18
21
 
19
- & > div {
20
- display: flex;
21
- min-height: 200px;
22
+ p {
23
+ margin: 0;
24
+ font-style: italic;
22
25
  }
26
+ }
27
+ }
23
28
 
24
- img {
25
- margin: auto;
26
- }
29
+ [data-editor="written"] figure > div {
30
+ position: relative;
31
+ display: flex;
32
+ padding: 4px;
27
33
 
28
- figcaption {
29
- padding: 4px;
30
- }
34
+ &[data-uploadable] {
35
+ cursor: pointer;
36
+ }
37
+ }
38
+
39
+ [data-editor="written"] figure > div > div.progress {
40
+ position: absolute;
41
+ top: 0;
42
+ left: 0;
43
+ transition: width 0.24s ease;
44
+ }
45
+
46
+ [data-editor="written"] figure[data-status='uploading'] div.progress {
47
+ background-color: green;
48
+ height: 1px;
49
+ }
50
+
51
+ [data-editor="written"] figure img {
52
+ border: 2px solid #eee;
53
+ min-height: 100px;
54
+ min-width: 100px;
55
+ max-width: 100%;
56
+ max-height: 100%;
57
+ margin: auto;
58
+
59
+ &.error {
60
+ border-color: #F32626
31
61
  }
32
62
  }
63
+
64
+ [data-editor="written"] figure figcaption {
65
+ text-align: center;
66
+ font-size: 0.8em;
67
+ padding: 4px;
68
+ }
69
+
70
+ [data-editor="written"] figure input[type='file'] {
71
+ display: none;
72
+ }
73
+
74
+ [data-editor="written"] written-pre {
75
+ background: #f5f2f0;
76
+ padding: 1em;
77
+ margin: .5em 0;
78
+ overflow: auto;
79
+ color: black;
80
+ background: none;
81
+ text-shadow: 0 1px white;
82
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
83
+ text-align: left;
84
+ white-space: pre;
85
+ word-spacing: normal;
86
+ word-break: normal;
87
+ word-wrap: normal;
88
+ line-height: 1.5;
89
+ -moz-tab-size: 4;
90
+ -o-tab-size: 4;
91
+ tab-size: 4;
92
+ -webkit-hyphens: none;
93
+ -moz-hyphens: none;
94
+ -ms-hyphens: none;
95
+ hyphens: none;
96
+ }
97
+
98
+ [data-editor="written"] written-pre > code {
99
+ display: block;
100
+ white-space: pre-line;
101
+ }
@@ -1,3 +1,3 @@
1
1
  module Written
2
- VERSION = '0.0.5'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -1,7 +1,25 @@
1
1
  #= require 'written'
2
2
  #= require 'prism'
3
3
 
4
- Written.Parsers.Block.get('Code').parseSyntax = (element) ->
4
+ code = Written.Parsers.Block.get('Code').prototype
5
+ code.highlight = (element) ->
5
6
  Prism.highlightElement(element, false)
6
7
 
7
- new Written(document.getElementById('Editor'))
8
+ code = Written.Parsers.Inline.get('Code').prototype
9
+ code.highlight = (element) ->
10
+ Prism.highlightElement(element, false)
11
+
12
+
13
+ if window.AWS?
14
+ uploader = new Written.Uploaders.AWS({
15
+ bucket: AWS.bucket,
16
+ accessKey: AWS.accessKey,
17
+ policy: AWS.policy,
18
+ signature: AWS.signature
19
+ })
20
+
21
+ Written.Parsers.Block.get('Image').uploader(uploader)
22
+
23
+ editor = new Written(document.getElementById('Editor'))
24
+ editor.initialize()
25
+
@@ -6,6 +6,6 @@
6
6
  min-height: 450px;
7
7
  border: 1px solid gray;
8
8
  outline: none;
9
-
10
- padding: 1em;
9
+
10
+ padding: 1em 1em 30vh 1em;
11
11
  }
@@ -106,7 +106,6 @@ pre[class*="language-"] {
106
106
  .language-css .token.string,
107
107
  .style .token.string {
108
108
  color: #a67f59;
109
- background: hsla(0, 0%, 100%, .5);
110
109
  }
111
110
 
112
111
  .token.atrule,