ecrire 0.22.1 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +5 -0
- data/Gemfile +19 -0
- data/README.md +2 -0
- data/Rakefile +1 -1
- data/lib/ecrire/app/assets/javascripts/admin/editor/content.coffee +46 -76
- data/lib/ecrire/app/assets/javascripts/admin/editor/ext.coffee +3 -0
- data/lib/ecrire/app/assets/javascripts/admin/editor/extensions/clipboard.coffee +2 -1
- data/lib/ecrire/app/assets/javascripts/admin/editor/extensions/code.coffee +1 -2
- data/lib/ecrire/app/assets/javascripts/admin/editor/extensions/image.coffee +73 -1
- data/lib/ecrire/app/assets/javascripts/admin/editor/parsers/image.coffee +6 -115
- data/lib/ecrire/app/assets/javascripts/admin/editor.coffee +1 -0
- data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/delete.js.coffee +1 -2
- data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/draft.js.coffee +1 -3
- data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/help.js.coffee +1 -1
- data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/save.js.coffee +2 -2
- data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/sticky.js.coffee +1 -2
- data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/toggle.js.coffee +1 -2
- data/lib/ecrire/app/assets/javascripts/admin/posts/header.coffee +96 -40
- data/lib/ecrire/app/assets/javascripts/admin/posts/new.js.coffee +1 -2
- data/lib/ecrire/app/assets/javascripts/admin/posts/tag.js.coffee +7 -0
- data/lib/ecrire/app/assets/javascripts/admin/posts/tags.js.coffee +15 -0
- data/lib/ecrire/app/assets/javascripts/admin/posts/title.coffee +38 -9
- data/lib/ecrire/app/assets/javascripts/admin/tags/list.js.coffee +34 -0
- data/lib/ecrire/app/assets/javascripts/admin.js +1 -1
- data/lib/ecrire/app/assets/javascripts/application.js +2 -3
- data/lib/ecrire/app/assets/javascripts/shared/overlay.js.coffee +1 -2
- data/lib/ecrire/app/assets/javascripts/shared/popup.js.coffee +1 -2
- data/lib/ecrire/app/assets/stylesheets/admin/base.css.scss +1 -2
- data/lib/ecrire/app/assets/stylesheets/admin/editor/base.css.scss +0 -7
- data/lib/ecrire/app/assets/stylesheets/admin/editor/content.css.scss +30 -12
- data/lib/ecrire/app/assets/stylesheets/admin/editor/header.css.scss +154 -32
- data/lib/ecrire/app/assets/stylesheets/admin/posts.css.scss +8 -1
- data/lib/ecrire/app/assets/stylesheets/admin/tags.css.scss +78 -0
- data/lib/ecrire/app/assets/stylesheets/admin/title.css.scss +51 -0
- data/lib/ecrire/app/assets/stylesheets/admin/variables.css.scss +3 -0
- data/lib/ecrire/app/assets/stylesheets/shared/popup.css.scss +2 -0
- data/lib/ecrire/app/controllers/admin/application_controller.rb +6 -0
- data/lib/ecrire/app/controllers/admin/images_controller.rb +5 -6
- data/lib/ecrire/app/controllers/admin/posts/tags_controller.rb +35 -0
- data/lib/ecrire/app/controllers/admin/posts_controller.rb +13 -12
- data/lib/ecrire/app/controllers/admin/tags_controller.rb +4 -0
- data/lib/ecrire/app/controllers/admin/titles_controller.rb +39 -0
- data/lib/ecrire/app/controllers/application_controller.rb +13 -3
- data/lib/ecrire/app/controllers/ecrire/posts_controller.rb +6 -5
- data/lib/ecrire/app/helpers/posts_helper.rb +0 -12
- data/lib/ecrire/app/models/admin/image.rb +4 -7
- data/lib/ecrire/app/models/admin/post.rb +2 -7
- data/lib/ecrire/app/models/admin/tag.rb +4 -0
- data/lib/ecrire/app/models/admin/title.rb +4 -0
- data/lib/ecrire/app/models/post.rb +30 -22
- data/lib/ecrire/app/models/tag.rb +5 -0
- data/lib/ecrire/app/models/title.rb +62 -0
- data/lib/ecrire/app/views/admin/images/errors.json.jbuilder +1 -0
- data/lib/ecrire/app/views/admin/posts/edit.html.erb +61 -21
- data/lib/ecrire/app/views/admin/posts/header/_dropping.html.erb +12 -0
- data/lib/ecrire/app/views/admin/posts/header/_error.html.erb +18 -0
- data/lib/ecrire/app/views/admin/posts/header/_uploading.html.erb +21 -0
- data/lib/ecrire/app/views/admin/posts/new.html.erb +23 -0
- data/lib/ecrire/app/views/admin/posts/tags/_tag.html.erb +10 -0
- data/lib/ecrire/app/views/admin/posts/tags/create.js.erb +1 -0
- data/lib/ecrire/app/views/admin/posts/tags/dialog/_tag.html.erb +3 -0
- data/lib/ecrire/app/views/admin/posts/tags/dialog/_tags.html.erb +12 -0
- data/lib/ecrire/app/views/admin/posts/tags/index.js.erb +1 -0
- data/lib/ecrire/app/views/admin/posts/tags/update.js.erb +2 -0
- data/lib/ecrire/app/views/admin/titles/_title.html.erb +11 -0
- data/lib/ecrire/app/views/admin/titles/_titles.html.erb +22 -0
- data/lib/ecrire/app/views/admin/titles/create.js.erb +1 -0
- data/lib/ecrire/app/views/admin/titles/edit.js.erb +1 -0
- data/lib/ecrire/app/views/admin/titles/errors.js.erb +5 -0
- data/lib/ecrire/app/views/admin/titles/index.js.erb +1 -0
- data/lib/ecrire/app/views/admin/titles/update.js.erb +1 -0
- data/lib/ecrire/app/views/layouts/admin/application.html.erb +1 -1
- data/lib/ecrire/app/views/sessions/_navigation.html.erb +1 -1
- data/lib/ecrire/application.rb +1 -1
- data/lib/ecrire/config/routes.rb +2 -2
- data/lib/ecrire/db/migrate/20150305123321_move_labels_to_titles.rb +27 -0
- data/lib/ecrire/db/migrate/20150318549479_create_tags.rb +13 -0
- data/lib/ecrire/db/schema.rb +25 -22
- data/lib/ecrire/onboarding/assets/javascripts/base.js +1 -1
- data/lib/ecrire/onboarding/assets/javascripts/databases/information.js.coffee +1 -1
- data/lib/ecrire/onboarding/assets/javascripts/message.js.coffee +1 -1
- data/lib/ecrire/template/Gemfile +4 -3
- data/lib/ecrire/template/assets/javascripts/base.js.coffee +1 -0
- data/lib/ecrire/version.rb +1 -1
- data/test/editor/controllers/base_controller_test.rb +1 -0
- data/test/editor/models/post_test.rb +26 -56
- data/test/editor/models/title_test.rb +31 -0
- data/test/editor/test_helper.rb +2 -0
- data/test/fixtures/posts.yml +0 -4
- data/test/fixtures/tags.yml +2 -0
- data/test/fixtures/titles.yml +11 -0
- data/test/initializations/railtie_test.rb +2 -2
- data/test/themes/template/secrets.yml +6 -0
- metadata +49 -24
- data/lib/ecrire/app/assets/stylesheets/admin/editor/image.css.scss +0 -58
- data/lib/ecrire/app/controllers/admin/labels_controller.rb +0 -18
- data/lib/ecrire/app/models/label.rb +0 -3
- data/lib/ecrire/app/views/admin/images/errors.js.erb +0 -1
- data/lib/ecrire/app/views/admin/posts/title.html.erb +0 -10
- data/test/editor/controllers/admin/images_controller_test.rb +0 -6
- data/test/editor/controllers/admin/posts_controller_test.rb +0 -90
- data/test/editor/controllers/images_controller_test.rb +0 -2
- data/test/editor/controllers/partials_controller_test.rb +0 -2
- data/test/editor/controllers/posts_controller_test.rb +0 -21
- data/test/editor/helpers/posts_helper_test.rb +0 -3
- data/test/editor/models/partial_test.rb +0 -4
- data/test/fixtures/partials.yml +0 -9
- /data/lib/ecrire/app/views/admin/images/{update.js.erb → create.js.erb} +0 -0
- /data/{lib/ecrire/template/assets/javascripts/post.js.coffee → test/themes/onboarding/.keep} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f76b1ffb5a76e8b346bdd15ab2fc6b2b9ddffcbf
|
4
|
+
data.tar.gz: 996185339a3a617b693bc5781891d926d3334f73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36e7377ebb0b601c51dfeed39a3b12a8eb4af0bf5068cb2acd2e5b033969473e4560a8b374b6ffca757259e9dcd8ea6768840327b9abbefbee9fa36d02656c9b
|
7
|
+
data.tar.gz: d8bf17c5c38fb86e482d44f8d30e809142617a81decd9a2340ba5c4b4378ee45c195d7589843f2538a6b3688617a1361ead70f23105141225012c83620c831a2
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -2,3 +2,22 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
+
gem 'rails', '~> 4.2'
|
6
|
+
gem 'observejs', git: 'https://github.com/pothibo/observejs.git'
|
7
|
+
gem 'warden', '~> 1.2'
|
8
|
+
gem 'bcrypt', '~> 3.1'
|
9
|
+
gem 'nokogiri', '~> 1.6'
|
10
|
+
gem 's3', '~> 0.3'
|
11
|
+
gem 'pg', '~> 0.17'
|
12
|
+
gem 'kaminari', '~> 0.15'
|
13
|
+
gem 'kramdown', '~> 1.5'
|
14
|
+
|
15
|
+
gem 'sprockets-rails', '~> 2.1'
|
16
|
+
gem 'sass-rails', '~> 4.0', '>= 4.0.3'
|
17
|
+
gem 'coffee-rails', '~> 4.0'
|
18
|
+
gem 'turbolinks', '~> 2.2'
|
19
|
+
gem 'bourbon', '~> 3.2'
|
20
|
+
gem 'uglifier', '~> 2.5'
|
21
|
+
gem 'jbuilder', '~> 2.2'
|
22
|
+
|
23
|
+
gem 'byebug'
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Ecrire
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/pothibo/ecrire.svg?branch=master)](https://travis-ci.org/pothibo/ecrire)
|
4
|
+
|
3
5
|
Ecrire is a blog built *on top* of Ruby on Rails. The goal of this blog engine is to make it **easy** to start a blog while keeping control over the content. You can see this as an alternative to WordPress.
|
4
6
|
|
5
7
|
## The editor
|
data/Rakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
ObserveJS.bind 'Editor.Content', class @Editor
|
2
2
|
|
3
3
|
loaded: =>
|
4
4
|
@on 'keydown', @linefeed
|
@@ -38,13 +38,11 @@ Joint.bind 'Editor.Content', class @Editor
|
|
38
38
|
|
39
39
|
|
40
40
|
|
41
|
-
outdated: (
|
41
|
+
outdated: (observedMutations) =>
|
42
42
|
@observer.hold =>
|
43
|
-
|
44
|
-
|
45
|
-
@
|
46
|
-
if mutation.type == 'characterData'
|
47
|
-
@update mutation.target
|
43
|
+
mutations = new Mutations(observedMutations, @element())
|
44
|
+
if mutations.target?
|
45
|
+
@updated(mutations)
|
48
46
|
|
49
47
|
event = new CustomEvent('Editor:updated', {bubbles: true})
|
50
48
|
@element().dispatchEvent(event)
|
@@ -83,7 +81,11 @@ Joint.bind 'Editor.Content', class @Editor
|
|
83
81
|
|
84
82
|
|
85
83
|
|
86
|
-
|
84
|
+
updated: (mutations) ->
|
85
|
+
if mutations.target.contentEditable == 'false'
|
86
|
+
return
|
87
|
+
|
88
|
+
node = mutations.target
|
87
89
|
while node? && node.parentElement != @element()
|
88
90
|
node = node.parentElement
|
89
91
|
|
@@ -92,7 +94,10 @@ Joint.bind 'Editor.Content', class @Editor
|
|
92
94
|
walker = @walker(node)
|
93
95
|
|
94
96
|
sel = window.getSelection()
|
95
|
-
|
97
|
+
if sel.type == 'None'
|
98
|
+
offset = 0
|
99
|
+
else
|
100
|
+
offset = @lineOffset(node, (sel.focusNode || node), sel.focusOffset)
|
96
101
|
|
97
102
|
if node.previousElementSibling?
|
98
103
|
node = node.previousElementSibling
|
@@ -106,66 +111,6 @@ Joint.bind 'Editor.Content', class @Editor
|
|
106
111
|
cursor.update(@walker(line))
|
107
112
|
@scrollLineIntoView(cursor.focus())
|
108
113
|
|
109
|
-
|
110
|
-
removed: (node, line) =>
|
111
|
-
while line? && line.parentElement != @element()
|
112
|
-
line = line.parentElement
|
113
|
-
|
114
|
-
if node.nodeType != 1 || (node instanceof HTMLBRElement && node.parentElement?)
|
115
|
-
node.remove()
|
116
|
-
|
117
|
-
if line?
|
118
|
-
sel = window.getSelection()
|
119
|
-
offset = @lineOffset(line, sel.focusNode, sel.focusOffset)
|
120
|
-
cursor = new Editor.Cursor(offset)
|
121
|
-
|
122
|
-
lines = @parse(@cloneNodesFrom(line))
|
123
|
-
|
124
|
-
@observer.hold =>
|
125
|
-
line = cursor.focus(@updateDOM(line, lines)[0])
|
126
|
-
cursor.update(@walker(line))
|
127
|
-
|
128
|
-
if @element().childNodes.length == 0
|
129
|
-
p = "<p>".toHTML()
|
130
|
-
@element().appendChild(p)
|
131
|
-
cursor = new Editor.Cursor(offset)
|
132
|
-
cursor.update(@walker(p), 0)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
appended: (node) =>
|
137
|
-
el = node
|
138
|
-
while el? && el.parentElement != @element()
|
139
|
-
el = el.parentElement
|
140
|
-
|
141
|
-
return unless el?
|
142
|
-
|
143
|
-
elements = el.querySelectorAll('[contenteditable=false]')
|
144
|
-
|
145
|
-
for element in elements
|
146
|
-
if element.contains(node)
|
147
|
-
return
|
148
|
-
|
149
|
-
if node instanceof HTMLBRElement
|
150
|
-
node.remove()
|
151
|
-
return
|
152
|
-
|
153
|
-
node = el
|
154
|
-
|
155
|
-
sel = window.getSelection()
|
156
|
-
offset = @lineOffset(el, sel.focusNode, sel.focusOffset)
|
157
|
-
cursor = new Editor.Cursor(offset)
|
158
|
-
|
159
|
-
lines = @parse(@cloneNodesFrom(node))
|
160
|
-
|
161
|
-
@observer.hold =>
|
162
|
-
lines = @updateDOM(node, lines)
|
163
|
-
if node != lines[0]
|
164
|
-
cursor.update(@walker(lines[0]))
|
165
|
-
@scrollLineIntoView(lines[0])
|
166
|
-
|
167
|
-
|
168
|
-
|
169
114
|
scrollLineIntoView: (line) =>
|
170
115
|
height = window.innerHeight
|
171
116
|
rect = line.getBoundingClientRect()
|
@@ -263,18 +208,11 @@ Joint.bind 'Editor.Content', class @Editor
|
|
263
208
|
node1 = node1.cloneNode(true)
|
264
209
|
node2 = node2.cloneNode(true)
|
265
210
|
|
266
|
-
for el in node1.querySelectorAll('[contenteditable=false]')
|
267
|
-
el.remove()
|
268
|
-
|
269
|
-
for el in node2.querySelectorAll('[contenteditable=false]')
|
270
|
-
el.remove()
|
271
|
-
|
272
211
|
node1.nodeName == node2.nodeName &&
|
273
212
|
node1.innerHTML.trim() == node2.innerHTML.trim()
|
274
213
|
|
275
214
|
|
276
215
|
|
277
|
-
|
278
216
|
parse: (fragment) =>
|
279
217
|
for p in @parsers
|
280
218
|
line = fragment.firstChild
|
@@ -380,5 +318,37 @@ class LineFeed
|
|
380
318
|
@fragment.appendChild(node)
|
381
319
|
|
382
320
|
|
321
|
+
class Mutations
|
322
|
+
constructor: (mutations, editor) ->
|
323
|
+
@removed = []
|
324
|
+
@appended = []
|
325
|
+
@updated = []
|
326
|
+
|
327
|
+
for mutation in mutations
|
328
|
+
@setTarget(mutation.target, editor)
|
329
|
+
if mutation.addedNodes.length > 0
|
330
|
+
@appended.push mutation.target
|
331
|
+
else if mutation.type == 'characterData'
|
332
|
+
@updated.push mutation.target
|
333
|
+
else
|
334
|
+
@removed.push mutation.target
|
335
|
+
|
336
|
+
setTarget: (target, editor) ->
|
337
|
+
return unless target.parentElement? && target != editor
|
338
|
+
if @target? && @target.compareDocumentPosition(target) & Node.DOCUMENT_POSITION_FOLLOWING
|
339
|
+
@target = target
|
340
|
+
else
|
341
|
+
@target = target
|
342
|
+
|
343
|
+
status: =>
|
344
|
+
if @appended.length > 0
|
345
|
+
"appended"
|
346
|
+
else if @updated.length > 0
|
347
|
+
'updated'
|
348
|
+
else if @removed.length > 0
|
349
|
+
'removed'
|
350
|
+
else
|
351
|
+
'none'
|
352
|
+
|
383
353
|
Editor.Parsers = []
|
384
354
|
Editor.Extensions = []
|
@@ -105,8 +105,9 @@ Editor.Extensions.push class ClipBoard
|
|
105
105
|
for n in line.childNodes
|
106
106
|
if n == node
|
107
107
|
break
|
108
|
-
else if n.
|
108
|
+
else if n.contains(node)
|
109
109
|
offset += @nodeOffset(node, n)
|
110
|
+
break
|
110
111
|
else
|
111
112
|
offset += n.textContent.length
|
112
113
|
|
@@ -1,8 +1,14 @@
|
|
1
|
-
|
1
|
+
ObserveJS.bind 'Editor.Image', class
|
2
2
|
loaded: =>
|
3
3
|
@element().addEventListener 'dragover', @over
|
4
4
|
@element().addEventListener 'dragleave', @cancel
|
5
5
|
@element().addEventListener 'drop', @drop
|
6
|
+
@on 'click', @container(), @open
|
7
|
+
@on 'change', @element().querySelector('input'), @upload
|
8
|
+
if @element().querySelector('figcaption').hasAttribute('name')
|
9
|
+
@show()
|
10
|
+
else
|
11
|
+
@placehold()
|
6
12
|
|
7
13
|
over: (e) =>
|
8
14
|
e.preventDefault()
|
@@ -15,5 +21,71 @@ Joint.bind 'Editor.Image', class
|
|
15
21
|
drop: (e) =>
|
16
22
|
e.preventDefault()
|
17
23
|
@element().classList.remove 'dropping'
|
24
|
+
e.file = e.dataTransfer.files[0]
|
25
|
+
@upload(e)
|
18
26
|
|
27
|
+
show: =>
|
28
|
+
img = @retrieve('img')
|
29
|
+
img.src = @element().querySelector('figcaption').getAttribute('name')
|
30
|
+
@container().appendChild(img)
|
19
31
|
|
32
|
+
placehold: =>
|
33
|
+
placeholder = @retrieve('.placeholder')
|
34
|
+
@container().appendChild(placeholder)
|
35
|
+
|
36
|
+
container: =>
|
37
|
+
@container.element ||= @element().querySelector('div[contenteditable=false]')
|
38
|
+
|
39
|
+
open: =>
|
40
|
+
@container().querySelector('input').click()
|
41
|
+
|
42
|
+
uploaded: (e) =>
|
43
|
+
xml = new DOMParser().parseFromString(e.target.response, 'text/xml')
|
44
|
+
url = xml.querySelector('Location').textContent
|
45
|
+
img = @retrieve('img')
|
46
|
+
img.src = url
|
47
|
+
progressBar = @retrieve('.progressbar')
|
48
|
+
@container().insertBefore(img, progressBar)
|
49
|
+
progressBar.remove()
|
50
|
+
@retrieve('.placeholder').remove()
|
51
|
+
@element().querySelector('figcaption').lastChild.textContent = "(#{url})"
|
52
|
+
|
53
|
+
upload: (e) =>
|
54
|
+
@container().appendChild(@retrieve('.progressbar'))
|
55
|
+
unless e.file?
|
56
|
+
e.file = e.target.files[0]
|
57
|
+
id = PostBody.getAttribute('postid')
|
58
|
+
policy = PostBody.getAttribute('policy')
|
59
|
+
signature = PostBody.getAttribute('signature')
|
60
|
+
bucket = PostBody.getAttribute('bucket')
|
61
|
+
namespace = PostBody.getAttribute('namespace')
|
62
|
+
access_key = PostBody.getAttribute('access_key')
|
63
|
+
|
64
|
+
url = "https://s3.amazonaws.com/#{bucket}/"
|
65
|
+
dir = [id]
|
66
|
+
if namespace?
|
67
|
+
dir.splice(0,0, namespace)
|
68
|
+
|
69
|
+
dir = dir.join '/'
|
70
|
+
|
71
|
+
data = new FormData()
|
72
|
+
data.append 'AWSAccessKeyId', access_key
|
73
|
+
data.append 'success_action_status', 201
|
74
|
+
data.append 'acl', 'private'
|
75
|
+
data.append 'policy', policy
|
76
|
+
data.append 'signature', signature
|
77
|
+
data.append 'key', "#{dir}/#{e.file.name}"
|
78
|
+
data.append 'Content-Type', e.file.type
|
79
|
+
data.append 'file', e.file
|
80
|
+
|
81
|
+
xhr = new XMLHttpRequest()
|
82
|
+
xhr.open('POST', url, true)
|
83
|
+
xhr.onload = @uploaded
|
84
|
+
xhr.onprogress = @progress
|
85
|
+
xhr.send(data)
|
86
|
+
|
87
|
+
progress: (e) =>
|
88
|
+
return unless e.lengthComputable
|
89
|
+
percentComplete = e.loaded / e.total * 100.0;
|
90
|
+
progressBar = @retrieve('.progressbar')
|
91
|
+
progressBar.firstElementChild.style.width = "#{percentComplete}%";
|
@@ -9,121 +9,12 @@ Editor.Parsers.push class
|
|
9
9
|
@match?
|
10
10
|
|
11
11
|
render: =>
|
12
|
-
@
|
12
|
+
@figure = EditorElements.content.querySelector("[as='Editor.Image']").cloneNode(true)
|
13
13
|
|
14
|
-
@
|
15
|
-
|
16
|
-
|
17
|
-
@picture = "<div class='image' as='Editor.Image'>".toHTML()
|
18
|
-
|
19
|
-
@title = "<em></em>".toHTML()
|
20
|
-
@title.appendChild document.createTextNode(@match[1])
|
21
|
-
@title.appendChild document.createTextNode(@match[3])
|
14
|
+
@caption = @figure.querySelector('figcaption')
|
15
|
+
@caption.appendChild document.createTextNode(@match[1])
|
16
|
+
@caption.appendChild document.createTextNode(@match[3])
|
22
17
|
if @match[4]?
|
23
|
-
@
|
24
|
-
|
25
|
-
@picture.appendChild @container.toHTML(@match[4])
|
26
|
-
@picture.appendChild @title
|
27
|
-
|
28
|
-
@container.input.addEventListener 'change', @update
|
29
|
-
@picture.addEventListener 'drop', @drop
|
30
|
-
|
31
|
-
return @picture
|
32
|
-
|
33
|
-
show: (e, url) =>
|
34
|
-
@container.image(url)
|
35
|
-
@title.lastChild.textContent = "(#{url})"
|
36
|
-
|
37
|
-
update: (e) =>
|
38
|
-
unless e.file?
|
39
|
-
e.file = e.target.files[0]
|
40
|
-
@container.loading()
|
41
|
-
@uploader.send(e)
|
42
|
-
|
43
|
-
drop: (e) =>
|
44
|
-
e.preventDefault()
|
45
|
-
e.file = e.dataTransfer.files[0]
|
46
|
-
@update(e)
|
47
|
-
|
48
|
-
|
49
|
-
class Container
|
50
|
-
constructor: ->
|
51
|
-
@el = "<div contenteditable=false></div>".toHTML()
|
52
|
-
@el.addEventListener 'click', @open
|
53
|
-
|
54
|
-
if !(@input = @el.querySelector('input'))?
|
55
|
-
@input = "<input type='file'>".toHTML()
|
56
|
-
|
57
|
-
@el.appendChild(@input)
|
58
|
-
|
59
|
-
image: (url) =>
|
60
|
-
@el.style.backgroundImage = "url(#{url})"
|
61
|
-
@el.innerHTML = ''
|
62
|
-
@el.classList.remove 'loading'
|
63
|
-
|
64
|
-
loading: =>
|
65
|
-
@loading = =>
|
66
|
-
@el.classList.add 'loading'
|
67
|
-
@el.innerHTML = ''
|
68
|
-
|
69
|
-
@loading()
|
70
|
-
|
71
|
-
placeholder: =>
|
72
|
-
el = "<p>Drop an image or click here to upload a picture.</p>".toHTML()
|
73
|
-
@placeholder = =>
|
74
|
-
@el.innerHTML = ''
|
75
|
-
@el.appendChild(el)
|
76
|
-
|
77
|
-
@placeholder()
|
78
|
-
|
79
|
-
open: (e) =>
|
80
|
-
@input.click()
|
81
|
-
|
82
|
-
toHTML: (url) =>
|
83
|
-
if url?
|
84
|
-
@image(url)
|
85
|
-
else if @el.classList.contains('loading')
|
86
|
-
@loading()
|
87
|
-
else
|
88
|
-
@placeholder()
|
89
|
-
|
90
|
-
@el
|
91
|
-
|
92
|
-
|
93
|
-
class Editor.ImageUploader
|
94
|
-
constructor: (@callback) ->
|
95
|
-
|
96
|
-
uploaded: (e) =>
|
97
|
-
xml = new DOMParser().parseFromString(e.target.response, 'text/xml')
|
98
|
-
url = xml.querySelector('Location').textContent
|
99
|
-
@callback(e, url)
|
100
|
-
|
101
|
-
send: (e) =>
|
102
|
-
id = PostBody.getAttribute('postid')
|
103
|
-
policy = PostBody.getAttribute('policy')
|
104
|
-
signature = PostBody.getAttribute('signature')
|
105
|
-
bucket = PostBody.getAttribute('bucket')
|
106
|
-
namespace = PostBody.getAttribute('namespace')
|
107
|
-
access_key = PostBody.getAttribute('access_key')
|
108
|
-
|
109
|
-
url = "https://s3.amazonaws.com/#{bucket}/"
|
110
|
-
dir = [id]
|
111
|
-
if namespace?
|
112
|
-
dir.splice(0,0, namespace)
|
113
|
-
|
114
|
-
dir = dir.join '/'
|
115
|
-
|
116
|
-
data = new FormData()
|
117
|
-
data.append 'AWSAccessKeyId', access_key
|
118
|
-
data.append 'success_action_status', 201
|
119
|
-
data.append 'acl', 'private'
|
120
|
-
data.append 'policy', policy
|
121
|
-
data.append 'signature', signature
|
122
|
-
data.append 'key', "#{dir}/#{e.file.name}"
|
123
|
-
data.append 'Content-Type', e.file.type
|
124
|
-
data.append 'file', e.file
|
18
|
+
@caption.setAttribute('name', @match[4])
|
125
19
|
|
126
|
-
|
127
|
-
xhr.open('POST', url, true)
|
128
|
-
xhr.onload = @uploaded
|
129
|
-
xhr.send(data)
|
20
|
+
return @figure
|
@@ -0,0 +1 @@
|
|
1
|
+
#= require_tree ./editor
|
data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/delete.js.coffee
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
ObserveJS.bind 'Post.Delete', class
|
2
2
|
loaded: =>
|
3
3
|
@on 'change', @element().querySelector('input[type=checkbox]'), @toggle
|
4
4
|
|
@@ -8,4 +8,3 @@ Joint.bind 'Post.Delete', class
|
|
8
8
|
button.removeAttribute('disabled')
|
9
9
|
else
|
10
10
|
button.setAttribute('disabled', 'disabled')
|
11
|
-
|
data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/draft.js.coffee
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
ObserveJS.bind 'Editor.Draft', class
|
2
2
|
resetInterval: 4000
|
3
3
|
loaded: =>
|
4
4
|
@on 'Editor:updated', document, @update
|
@@ -38,5 +38,3 @@ Joint.bind 'Editor.Draft', class
|
|
38
38
|
unless @cached?
|
39
39
|
@cached = e.target.textContent
|
40
40
|
return
|
41
|
-
|
42
|
-
|
data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/save.js.coffee
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
ObserveJS.bind 'Editor.Save', class
|
2
2
|
loaded: =>
|
3
3
|
@button = @element().querySelector('button')
|
4
4
|
@time = @element().querySelector('div.update > p')
|
@@ -62,7 +62,7 @@ Joint.bind 'Editor.Save', class
|
|
62
62
|
e.stopPropagation()
|
63
63
|
|
64
64
|
form = document.querySelector("[as='Editor.Save']")
|
65
|
-
xhr = new
|
65
|
+
xhr = new ObserveJS.XHR(form)
|
66
66
|
xhr.data.set('post[content]', PostBody.instance.toString())
|
67
67
|
xhr.data.set('context', 'content')
|
68
68
|
xhr.send()
|
data/lib/ecrire/app/assets/javascripts/admin/{editor/navigation → navigation}/sticky.js.coffee
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
ObserveJS.bind 'Post.Sticky', class
|
2
2
|
loaded: =>
|
3
3
|
@on 'scroll', document, @scrolled
|
4
4
|
|
@@ -8,4 +8,3 @@ Joint.bind 'Post.Sticky', class
|
|
8
8
|
@element().style.paddingTop = "#{Math.abs(top)}px"
|
9
9
|
else
|
10
10
|
@element().style.paddingTop = ''
|
11
|
-
|