ecrire 0.21.0 → 0.22.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9187d5d3cf47bd6d98975d2c7e98f78fca7e724
4
- data.tar.gz: bb54f17491247dfe317ca7ba9ef3fe78089936c7
3
+ metadata.gz: 1ca953837db65f9e27113c5399ce13c2353939bf
4
+ data.tar.gz: 2289e12808f0202798eb783bbd30fd055cbbc8e6
5
5
  SHA512:
6
- metadata.gz: d7887948635cf02da8caaed5c802c34e2f8ca0baa3e6d53f8cf04caccec39444a542a67a45a9b2026b739b9ca5ff290544f0908e9b3fefb96b4724e2ab8c9d60
7
- data.tar.gz: b12bfee9bd7bde93f8d37b514df86f01add1c972884998af6fa05a930aae3e610eee4b1f9000fe1c5ac281940dc0b42fa9f40bc288498c617c2741965e1375d5
6
+ metadata.gz: e64e5dd7ce4c0aba279e3385837b6e3d6057e29c6f2db4f221f0da51c59780575dbe872b82366a0d97e7fc73c9ac5a612f6ca44633f2558f662ef47b398ae2e8
7
+ data.tar.gz: e208f922deb272f90de0d89df47c7299c10a33ff267109589e0d1f83cdcc43eb19bde09e8a299a98b996fe9d21b0fec6234ec52caeaa9e2ccf2fc3879215ccc8
@@ -260,11 +260,21 @@ Joint.bind 'Editor.Content', class @Editor
260
260
 
261
261
 
262
262
  same: (node1, node2) =>
263
+ node1 = node1.cloneNode(true)
264
+ node2 = node2.cloneNode(true)
265
+
266
+ for el in node1.querySelectorAll('[contenteditable=false]')
267
+ el.remove()
268
+
269
+ for el in node2.querySelectorAll('[contenteditable=false]')
270
+ el.remove()
271
+
263
272
  node1.nodeName == node2.nodeName &&
264
273
  node1.innerHTML.trim() == node2.innerHTML.trim()
265
274
 
266
275
 
267
276
 
277
+
268
278
  parse: (fragment) =>
269
279
  for p in @parsers
270
280
  line = fragment.firstChild
@@ -74,7 +74,6 @@ Editor.Extensions.push class ClipBoard
74
74
 
75
75
 
76
76
  insert: (texts, sel) =>
77
-
78
77
  node = sel.anchorNode
79
78
  str = node.textContent
80
79
  text = texts.map((t) ->
@@ -89,7 +88,9 @@ Editor.Extensions.push class ClipBoard
89
88
  while line.parentElement != @editor.element()
90
89
  line = line.parentElement
91
90
 
92
- offset = @nodeOffset(node,line) + sel.anchorOffset + text.length
91
+ offset = sel.anchorOffset + text.length
92
+ if node != line
93
+ offset += @nodeOffset(node, line)
93
94
 
94
95
  fragment = @editor.parse(@editor.cloneNodesFrom(line))
95
96
 
@@ -99,15 +100,13 @@ Editor.Extensions.push class ClipBoard
99
100
  cursor.update(@editor.walker(cursor.focus(lines[0])), true)
100
101
 
101
102
  nodeOffset: (node, line) ->
102
- if !line.contains(node)
103
- raise "Looking for a node that is not inside the given line"
104
- return
105
-
106
103
  offset = 0
107
104
 
108
105
  for n in line.childNodes
109
106
  if n == node
110
107
  break
108
+ else if n.childNodes.length > 0
109
+ offset += @nodeOffset(node, n)
111
110
  else
112
111
  offset += n.textContent.length
113
112
 
@@ -3,6 +3,7 @@ Joint.bind 'Editor.Save', class
3
3
  @button = @element().querySelector('button')
4
4
  @time = @element().querySelector('div.update > p')
5
5
 
6
+ @on 'keydown', document, @shouldSave
6
7
  @on 'Editor:loaded', document, @cache
7
8
  @on 'Editor:updated', document, @update
8
9
  @on 'posts:update', document, @saved
@@ -32,11 +33,36 @@ Joint.bind 'Editor.Save', class
32
33
  cache
33
34
  @cache()
34
35
 
36
+ dirty: =>
37
+ @cache()? && @cache() != PostBody.instance.toString()
38
+
39
+ shouldSave: (e) =>
40
+ if e.metaKey isnt true || e.which isnt 83
41
+ return
42
+
43
+ e.preventDefault()
44
+ e.stopPropagation()
45
+
46
+ if @dirty()
47
+ @save(e)
48
+ else
49
+ @nudge()
50
+
51
+ nudge: =>
52
+ button = document.querySelector("[as='Editor.Save'] button")
53
+ clean = ->
54
+ button.classList.remove('nudge')
55
+
56
+ button.addEventListener 'animationend', clean
57
+ button.addEventListener 'webkitAnimationEnd', clean
58
+ button.classList.add('nudge')
59
+
35
60
  save: (e) =>
36
61
  e.preventDefault()
37
62
  e.stopPropagation()
38
63
 
39
- xhr = new Joint.XHR(e.target.form)
64
+ form = document.querySelector("[as='Editor.Save']")
65
+ xhr = new Joint.XHR(form)
40
66
  xhr.data.set('post[content]', PostBody.instance.toString())
41
67
  xhr.data.set('context', 'content')
42
68
  xhr.send()
@@ -48,11 +74,9 @@ Joint.bind 'Editor.Save', class
48
74
  @cache(true)
49
75
 
50
76
  update: (e) =>
51
- return unless @cache()?
52
- if @cache() != PostBody.instance.toString()
77
+ if @dirty()
53
78
  @button.removeAttribute('disabled')
54
79
  @button.textContent = @button.getAttribute('dirty')
55
80
  else
56
81
  @button.setAttribute('disabled', 'disabled')
57
82
  @button.textContent = @button.getAttribute('persisted')
58
-
@@ -6,27 +6,29 @@ body.edit.posts > main > section {
6
6
  padding-bottom: 10em;
7
7
 
8
8
  h1 {
9
- font-size: 2.6em;
9
+ font-size: 2.4em;
10
10
  }
11
11
 
12
12
  h2 {
13
- font-size: 2.3em;
13
+ font-size: 2.1em;
14
14
  }
15
15
 
16
16
  h3 {
17
- font-size: 2.0em;
17
+ font-size: 1.8em;
18
18
  }
19
19
 
20
20
  h4 {
21
- font-size: 1.7em;
21
+ font-size: 1.6em;
22
22
  }
23
23
 
24
24
  h5 {
25
- font-size: 1.6em;
25
+ font-weight: bold;
26
+ font-size: 1.4em;
26
27
  }
27
28
 
28
29
  h6 {
29
- font-size: 1.3em;
30
+ font-weight: bold;
31
+ font-size: 1.2em;
30
32
  }
31
33
 
32
34
  & > *, & > ul > li, & > ol > li {
@@ -29,6 +29,11 @@ body.posts > main > section > div.save {
29
29
  &:hover:not([disabled]) {
30
30
  background: #68B2A7;
31
31
  }
32
+
33
+ &.nudge {
34
+ @include animation(nudge 0.1s ease);
35
+ @include animation-iteration-count(2);
36
+ }
32
37
  }
33
38
 
34
39
  div.update {
@@ -42,3 +47,24 @@ body.posts > main > section > div.save {
42
47
  }
43
48
  }
44
49
 
50
+ @include keyframes(nudge) {
51
+ 0% {
52
+ margin-left: 0;
53
+ margin-right: 0;
54
+ }
55
+
56
+ 25% {
57
+ margin-left: 10px;
58
+ margin-right: 0;
59
+ }
60
+
61
+ 75% {
62
+ margin-left: 0;
63
+ margin-right: 10px;
64
+ }
65
+
66
+ 100% {
67
+ margin-left: 0;
68
+ margin-right: 0;
69
+ }
70
+ }
@@ -3,10 +3,3 @@
3
3
  @import 'shared/**/*';
4
4
  @import 'admin/navigation';
5
5
  @import 'sessions';
6
-
7
- ol, ul {
8
- list-style-type: none;
9
- margin: 0;
10
- padding: 0;
11
- }
12
-
@@ -10,16 +10,16 @@ module Admin
10
10
  href: admin_post_path(@post.id) do |div|
11
11
 
12
12
  if Rails.application.secrets.has_key?(:s3)
13
- div[:bucket] = Rails.application.secrets.s3['bucket'],
14
- div[:access_key] = Rails.application.secrets.s3['access_key'],
15
- div[:signature] = image_form_signature(image_form_policy(@post)),
13
+ div[:bucket] = Rails.application.secrets.s3['bucket']
14
+ div[:access_key] = Rails.application.secrets.s3['access_key']
15
+ div[:signature] = image_form_signature(image_form_policy(@post))
16
16
  div[:policy] = image_form_policy(@post)
17
17
  if Rails.application.secrets.s3.has_key?('namespace')
18
18
  div['namespace'] = Rails.application.secrets.s3['namespace']
19
19
  end
20
20
  end
21
21
 
22
- post.content
22
+ h(post.content)
23
23
  end
24
24
  end
25
25
  end
@@ -17,9 +17,14 @@ ActiveRecord::Schema.define(version: 20150120093481) do
17
17
  enable_extension "plpgsql"
18
18
  enable_extension "hstore"
19
19
 
20
+ create_table "abtests", force: :cascade do |t|
21
+ t.datetime "created_at"
22
+ t.datetime "updated_at"
23
+ end
24
+
20
25
  create_table "images", force: :cascade do |t|
21
- t.string "url"
22
- t.string "key"
26
+ t.string "url", limit: 255
27
+ t.string "key", limit: 255
23
28
  t.integer "post_id"
24
29
  t.datetime "created_at"
25
30
  t.datetime "updated_at"
@@ -27,7 +32,7 @@ ActiveRecord::Schema.define(version: 20150120093481) do
27
32
  end
28
33
 
29
34
  create_table "labels", force: :cascade do |t|
30
- t.string "name", null: false
35
+ t.string "name", limit: 255, null: false
31
36
  t.datetime "created_at"
32
37
  t.datetime "updated_at"
33
38
  end
@@ -37,15 +42,15 @@ ActiveRecord::Schema.define(version: 20150120093481) do
37
42
  create_table "partials", force: :cascade do |t|
38
43
  t.datetime "created_at"
39
44
  t.datetime "updated_at"
40
- t.string "title", null: false
45
+ t.string "title", limit: 255, null: false
41
46
  t.text "content"
42
47
  t.text "stylesheet"
43
48
  t.text "javascript"
44
49
  end
45
50
 
46
51
  create_table "posts", force: :cascade do |t|
47
- t.string "title", null: false
48
- t.string "slug", null: false
52
+ t.string "title", limit: 255, null: false
53
+ t.string "slug", limit: 255, null: false
49
54
  t.text "content"
50
55
  t.text "stylesheet"
51
56
  t.datetime "published_at"
@@ -60,8 +65,8 @@ ActiveRecord::Schema.define(version: 20150120093481) do
60
65
  add_index "posts", ["title"], name: "index_posts_on_title", unique: true, using: :btree
61
66
 
62
67
  create_table "users", force: :cascade do |t|
63
- t.string "email", null: false
64
- t.string "encrypted_password", null: false
68
+ t.string "email", limit: 255, null: false
69
+ t.string "encrypted_password", limit: 255, null: false
65
70
  t.datetime "created_at"
66
71
  t.datetime "updated_at"
67
72
  end
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'ecrire', path: '~/Develop/ecrire'
3
+ gem 'ecrire', git: 'https://github.com/pothibo/ecrire'
4
4
 
5
5
  group :required do
6
6
  gem 'rails', '~> 4.2'
@@ -1,3 +1,3 @@
1
1
  module Ecrire
2
- VERSION = '0.21.0'
2
+ VERSION = '0.22.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecrire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pier-Olivier Thibault
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-28 00:00:00.000000000 Z
11
+ date: 2015-03-08 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Blog engine on Rails
14
14
  email: pothibo@gmail.com
@@ -271,7 +271,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
271
  version: '0'
272
272
  requirements: []
273
273
  rubyforge_project:
274
- rubygems_version: 2.2.2
274
+ rubygems_version: 2.0.14
275
275
  signing_key:
276
276
  specification_version: 4
277
277
  summary: Blog engine