phrasing 2.1.0
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.
- data/.gitignore +2 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +142 -0
- data/MIT-LICENSE +20 -0
- data/README.md +93 -0
- data/Rakefile +35 -0
- data/app/assets/fonts/icomoon.dev.svg +38 -0
- data/app/assets/fonts/icomoon.eot +0 -0
- data/app/assets/fonts/icomoon.svg +38 -0
- data/app/assets/fonts/icomoon.ttf +0 -0
- data/app/assets/fonts/icomoon.woff +0 -0
- data/app/assets/images/phrasing_information_icon.png +0 -0
- data/app/assets/javascripts/editor.js +318 -0
- data/app/assets/javascripts/head.js +423 -0
- data/app/assets/javascripts/phrasing.js.erb +148 -0
- data/app/assets/javascripts/spin.js +355 -0
- data/app/assets/stylesheets/phrasing.css.scss +240 -0
- data/app/assets/stylesheets/phrasing_edit_mode_bubble.css.scss +117 -0
- data/app/assets/stylesheets/phrasing_engine.css +470 -0
- data/app/assets/stylesheets/phrasing_fonts.css.scss +60 -0
- data/app/controllers/phrasing_phrases_controller.rb +126 -0
- data/app/helpers/inline_helper.rb +47 -0
- data/app/models/phrasing_phrase.rb +97 -0
- data/app/views/layouts/phrasing.html.haml +12 -0
- data/app/views/phrasing/_initializer.html.haml +25 -0
- data/app/views/phrasing/_menu.html.haml +8 -0
- data/app/views/phrasing/_messages.html.haml +4 -0
- data/app/views/phrasing/_production_warning.html.haml +4 -0
- data/app/views/phrasing_phrases/edit.html.haml +7 -0
- data/app/views/phrasing_phrases/help.html.haml +17 -0
- data/app/views/phrasing_phrases/import_export.html.haml +18 -0
- data/app/views/phrasing_phrases/index.html.haml +17 -0
- data/config/routes.rb +12 -0
- data/db/migrate/20120313191745_create_phrasing_phrases.rb +11 -0
- data/lib/phrasing.rb +72 -0
- data/lib/phrasing/ambiguous_phrases_error.rb +3 -0
- data/lib/phrasing/implementation.rb +19 -0
- data/lib/phrasing/phrasable_error_handler.rb +9 -0
- data/lib/phrasing/simple.rb +3 -0
- data/lib/phrasing/version.rb +3 -0
- data/lib/tasks/phrasing_tasks.rake +57 -0
- data/phrasing.gemspec +21 -0
- metadata +135 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
phrasing (0.9.1)
|
5
|
+
bootstrap-editable-rails
|
6
|
+
haml-rails
|
7
|
+
rails (>= 3.1.0)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
actionmailer (4.0.0)
|
13
|
+
actionpack (= 4.0.0)
|
14
|
+
mail (~> 2.5.3)
|
15
|
+
actionpack (4.0.0)
|
16
|
+
activesupport (= 4.0.0)
|
17
|
+
builder (~> 3.1.0)
|
18
|
+
erubis (~> 2.7.0)
|
19
|
+
rack (~> 1.5.2)
|
20
|
+
rack-test (~> 0.6.2)
|
21
|
+
activemodel (4.0.0)
|
22
|
+
activesupport (= 4.0.0)
|
23
|
+
builder (~> 3.1.0)
|
24
|
+
activerecord (4.0.0)
|
25
|
+
activemodel (= 4.0.0)
|
26
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
27
|
+
activesupport (= 4.0.0)
|
28
|
+
arel (~> 4.0.0)
|
29
|
+
activerecord-deprecated_finders (1.0.3)
|
30
|
+
activesupport (4.0.0)
|
31
|
+
i18n (~> 0.6, >= 0.6.4)
|
32
|
+
minitest (~> 4.2)
|
33
|
+
multi_json (~> 1.3)
|
34
|
+
thread_safe (~> 0.1)
|
35
|
+
tzinfo (~> 0.3.37)
|
36
|
+
arel (4.0.0)
|
37
|
+
atomic (1.1.13)
|
38
|
+
bootstrap-editable-rails (0.0.5)
|
39
|
+
railties (>= 3.1)
|
40
|
+
builder (3.1.4)
|
41
|
+
capybara (2.0.3)
|
42
|
+
mime-types (>= 1.16)
|
43
|
+
nokogiri (>= 1.3.3)
|
44
|
+
rack (>= 1.0.0)
|
45
|
+
rack-test (>= 0.5.4)
|
46
|
+
selenium-webdriver (~> 2.0)
|
47
|
+
xpath (~> 1.0.0)
|
48
|
+
childprocess (0.3.9)
|
49
|
+
ffi (~> 1.0, >= 1.0.11)
|
50
|
+
diff-lcs (1.2.4)
|
51
|
+
erubis (2.7.0)
|
52
|
+
factory_girl (4.2.0)
|
53
|
+
activesupport (>= 3.0.0)
|
54
|
+
factory_girl_rails (4.2.1)
|
55
|
+
factory_girl (~> 4.2.0)
|
56
|
+
railties (>= 3.0.0)
|
57
|
+
ffi (1.9.0)
|
58
|
+
haml (4.0.3)
|
59
|
+
tilt
|
60
|
+
haml-rails (0.4)
|
61
|
+
actionpack (>= 3.1, < 4.1)
|
62
|
+
activesupport (>= 3.1, < 4.1)
|
63
|
+
haml (>= 3.1, < 4.1)
|
64
|
+
railties (>= 3.1, < 4.1)
|
65
|
+
hike (1.2.3)
|
66
|
+
i18n (0.6.5)
|
67
|
+
mail (2.5.4)
|
68
|
+
mime-types (~> 1.16)
|
69
|
+
treetop (~> 1.4.8)
|
70
|
+
mime-types (1.24)
|
71
|
+
mini_portile (0.5.1)
|
72
|
+
minitest (4.7.5)
|
73
|
+
multi_json (1.7.9)
|
74
|
+
nokogiri (1.6.0)
|
75
|
+
mini_portile (~> 0.5.0)
|
76
|
+
polyglot (0.3.3)
|
77
|
+
rack (1.5.2)
|
78
|
+
rack-test (0.6.2)
|
79
|
+
rack (>= 1.0)
|
80
|
+
rails (4.0.0)
|
81
|
+
actionmailer (= 4.0.0)
|
82
|
+
actionpack (= 4.0.0)
|
83
|
+
activerecord (= 4.0.0)
|
84
|
+
activesupport (= 4.0.0)
|
85
|
+
bundler (>= 1.3.0, < 2.0)
|
86
|
+
railties (= 4.0.0)
|
87
|
+
sprockets-rails (~> 2.0.0)
|
88
|
+
railties (4.0.0)
|
89
|
+
actionpack (= 4.0.0)
|
90
|
+
activesupport (= 4.0.0)
|
91
|
+
rake (>= 0.8.7)
|
92
|
+
thor (>= 0.18.1, < 2.0)
|
93
|
+
rake (10.1.0)
|
94
|
+
rspec-core (2.14.5)
|
95
|
+
rspec-expectations (2.14.2)
|
96
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
97
|
+
rspec-mocks (2.14.3)
|
98
|
+
rspec-rails (2.14.0)
|
99
|
+
actionpack (>= 3.0)
|
100
|
+
activesupport (>= 3.0)
|
101
|
+
railties (>= 3.0)
|
102
|
+
rspec-core (~> 2.14.0)
|
103
|
+
rspec-expectations (~> 2.14.0)
|
104
|
+
rspec-mocks (~> 2.14.0)
|
105
|
+
rubyzip (0.9.9)
|
106
|
+
selenium-webdriver (2.35.0)
|
107
|
+
childprocess (>= 0.2.5)
|
108
|
+
multi_json (~> 1.0)
|
109
|
+
rubyzip
|
110
|
+
websocket (~> 1.0.4)
|
111
|
+
sprockets (2.10.0)
|
112
|
+
hike (~> 1.2)
|
113
|
+
multi_json (~> 1.0)
|
114
|
+
rack (~> 1.0)
|
115
|
+
tilt (~> 1.1, != 1.3.0)
|
116
|
+
sprockets-rails (2.0.0)
|
117
|
+
actionpack (>= 3.0)
|
118
|
+
activesupport (>= 3.0)
|
119
|
+
sprockets (~> 2.8)
|
120
|
+
sqlite3 (1.3.8)
|
121
|
+
thor (0.18.1)
|
122
|
+
thread_safe (0.1.2)
|
123
|
+
atomic
|
124
|
+
tilt (1.4.1)
|
125
|
+
treetop (1.4.15)
|
126
|
+
polyglot
|
127
|
+
polyglot (>= 0.3.1)
|
128
|
+
tzinfo (0.3.37)
|
129
|
+
websocket (1.0.7)
|
130
|
+
xpath (1.0.0)
|
131
|
+
nokogiri (~> 1.3)
|
132
|
+
|
133
|
+
PLATFORMS
|
134
|
+
ruby
|
135
|
+
|
136
|
+
DEPENDENCIES
|
137
|
+
capybara (~> 2.0.0)
|
138
|
+
factory_girl_rails
|
139
|
+
haml-rails
|
140
|
+
phrasing!
|
141
|
+
rspec-rails
|
142
|
+
sqlite3
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 Infinum
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# Phrasing!
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Phrasing is a gem for live editing phrases (copy) on websites.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Include the gem in your Gemfile
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem "phrasing"
|
13
|
+
```
|
14
|
+
|
15
|
+
Run the install script:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
rake phrasing:install
|
19
|
+
```
|
20
|
+
|
21
|
+
This will create a migration file and a config file where you can edit the name of the route to see all the phrases.
|
22
|
+
|
23
|
+
Migrate your database
|
24
|
+
```ruby
|
25
|
+
rake db:migrate
|
26
|
+
```
|
27
|
+
|
28
|
+
## Setup
|
29
|
+
|
30
|
+
The rake task will also generate a PhrasingHelper.rb file in your <tt>app/helpers</tt> folder where you will need to implement your <tt>can_edit_phrases?</tt> method. Example:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
module PhrasingHelper
|
34
|
+
|
35
|
+
def can_edit_phrases?
|
36
|
+
current_user.is_admin?
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
```
|
41
|
+
Include the phrasing **html** initializer at the top of your body
|
42
|
+
|
43
|
+
```haml
|
44
|
+
= render 'phrasing/initializer'
|
45
|
+
```
|
46
|
+
|
47
|
+
Include the required **javascript** file (most often in your application.js file):
|
48
|
+
|
49
|
+
```javascript
|
50
|
+
//= require phrasing
|
51
|
+
```
|
52
|
+
|
53
|
+
Include the required **stylesheet** file (most often in your application.css file):
|
54
|
+
|
55
|
+
```css
|
56
|
+
//= require phrasing
|
57
|
+
```
|
58
|
+
|
59
|
+
## How to use phrasing?
|
60
|
+
|
61
|
+
Start with adding your phrases simply by writting in your view file:
|
62
|
+
|
63
|
+
= phrase('my-first-phrase')
|
64
|
+
|
65
|
+
Apart from editing phrases (basically, Rails translations) you can also inline edit your models attributes, just use the `model_phrase` method:
|
66
|
+
|
67
|
+
= model_phrase(@post, :title)
|
68
|
+
|
69
|
+
Where <tt>@post</tt> is a object with a <tt>title</tt> attribute.
|
70
|
+
|
71
|
+
## Security
|
72
|
+
|
73
|
+
Since Phrasing can be used to update any attribute in any table (using the model_phrase method), special care must be taken into consideration from a security standpoint.
|
74
|
+
|
75
|
+
By default, Phrasing doesn't allow updating of any attribute apart from <<t>PhrasingPhrase.value</tt>. To be able to work with other attributes, you need to whitelist them.
|
76
|
+
|
77
|
+
In the <tt>config/initializers/phrasing.rb</tt> file you can whitelist your model attributes like this:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
Phrasing.white_list = ["Post.title", "Post.body"]
|
81
|
+
```
|
82
|
+
|
83
|
+
or you can whitelist all of them (not recommended) with:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
Phrasing.allow_update_on_all_models_and_attributes = true
|
87
|
+
```
|
88
|
+
|
89
|
+
## Authors
|
90
|
+
|
91
|
+
Copyright (c) 2013, Infinum
|
92
|
+
|
93
|
+
Phrasing relies heavily (or is built) on two other libraries: the Copycat gem and the ZenPen library. So thank you to the authors and all the contributors!
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rdoc/rdoc'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
RDoc::Task = Rake::RDocTask
|
14
|
+
end
|
15
|
+
|
16
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'Phrasing'
|
19
|
+
rdoc.options << '--line-numbers'
|
20
|
+
rdoc.rdoc_files.include('README.rdoc')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
25
|
+
load 'rails/tasks/engine.rake'
|
26
|
+
|
27
|
+
Bundler::GemHelper.install_tasks
|
28
|
+
|
29
|
+
|
30
|
+
require 'rspec/core/rake_task'
|
31
|
+
|
32
|
+
desc "Run all RSpec tests"
|
33
|
+
RSpec::Core::RakeTask.new(:spec)
|
34
|
+
|
35
|
+
task :default => :spec
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg">
|
4
|
+
<metadata>
|
5
|
+
This is a custom SVG font generated by IcoMoon.
|
6
|
+
<iconset grid="14"></iconset>
|
7
|
+
</metadata>
|
8
|
+
<defs>
|
9
|
+
<font id="icomoon" horiz-adv-x="448" >
|
10
|
+
<font-face units-per-em="448" ascent="384" descent="-64" />
|
11
|
+
<missing-glyph horiz-adv-x="448" />
|
12
|
+
<glyph class="hidden" unicode="" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
|
13
|
+
<glyph unicode="" d="M 448,384 L 448,216 L 387.511,276.489 L 294.761,183.739 L 247.739,230.761 L 340.489,323.511 L 280,384 ZM 107.511,323.511 L 200.261,230.761 L 153.239,183.739 L 60.489,276.489 L 0,216 L 0,384 L 168,384 ZM 387.511,43.511 L 448,104 L 448-64 L 280-64 L 340.489-3.511 L 247.739,89.239 L 294.761,136.261 ZM 200.261,89.239 L 107.511-3.511 L 168-64 L 0-64 L 0,104 L 60.489,43.511 L 153.239,136.261 Z" data-tags="expand, enlarge, maximize, fullscreen" />
|
14
|
+
<glyph unicode="" d="M 252.322,188.35l 81.046,0 c-10.276,39.704-41.342,70.798-81.046,81.046L 252.322,188.35 zM 252.322,131.65l0-81.018 c 39.704,10.22, 70.77,41.342, 81.046,81.018L 252.322,131.65 zM 195.622,188.35L 195.622,269.396 c-39.704-10.248-70.826-41.342-81.046-81.046L 195.622,188.35 zM 195.622,131.65L 114.576,131.65 c 10.22-39.676, 41.342-70.798, 81.046-81.018L 195.622,131.65 zM 252.322,327.258c 71.036-12.026, 126.868-67.872, 138.908-138.908L 448,188.35 C 435.036,290.704, 354.704,371.064, 252.322,384L 252.322,327.258 z
|
15
|
+
M 56.714,188.35C 68.74,259.4, 124.572,315.232, 195.622,327.258L 195.622,384 C 93.296,371.064, 12.908,290.704,0,188.35L 56.714,188.35 zM 195.622-7.23c-71.036,12.026-126.868,67.816-138.908,138.88L0,131.65 C 12.908,29.296, 93.296-51.092, 195.622-64
|
16
|
+
L 195.622-7.23 zM 391.23,131.65c-12.026-71.064-67.872-126.854-138.908-138.88L 252.322-64 C 354.704-51.092, 435.036,29.296, 448,131.65
|
17
|
+
L 391.23,131.65 z" data-tags="target, goal" />
|
18
|
+
<glyph unicode="" d="M 65.618,1.618c-87.486,87.472-87.486,229.306,0,316.778
|
19
|
+
c 87.472,87.486, 229.306,87.486, 316.778,0c 87.486-87.472, 87.486-229.306,0-316.778C 294.91-85.868, 153.090-85.868, 65.618,1.618z M 342.79,278.79
|
20
|
+
L 105.21,41.21c 65.618-65.618, 171.976-65.618, 237.594,0S 408.408,213.186, 342.79,278.79z" data-tags="contrast" />
|
21
|
+
<glyph unicode="" d="M 420-64L 28-64 c-15.456,0-28,12.544-28,28L0,356 c0,15.456, 12.544,28, 28,28l 336,0 l 84-84l0-336
|
22
|
+
C 448-51.456, 435.456-64, 420-64z M 112,6c0-7.742, 6.272-14, 14-14l 196,0 c 7.742,0, 14,6.258, 14,14l0,112 c0,7.742-6.258,14-14,14L 126,132 c-7.728,0-14-6.258-14-14L 112,6 z
|
23
|
+
M 308,314c0,7.742-6.258,14-14,14s-14-6.258-14-14l0-42 c0-7.742, 6.258-14, 14-14s 14,6.258, 14,14L 308,314 z M 392,286l-42,42l-14,0 l0-98 c0-7.742-6.258-14-14-14L 126,216
|
24
|
+
c-7.728,0-14,6.258-14,14L 112,328 L 70,328 C 62.272,328, 56,321.742, 56,314l0-308 c0-7.742, 6.272-14, 14-14l 14,0 L 84,146 c0,7.742, 6.272,14, 14,14l 252,0 c 7.742,0, 14-6.258, 14-14l0-154 l 14,0
|
25
|
+
c 7.742,0, 14,6.258, 14,14L 392,286 z" data-tags="floppy, disk, save, store" />
|
26
|
+
<glyph unicode="" d="M 28,132 L 196,132 L 196-36 L 135.511,24.489 L 47.136-63.886 L 0.114-16.864 L 88.489,71.511 ZM 359.511,71.511 L 447.886-16.864 L 400.864-63.886 L 312.489,24.489 L 252-36 L 252,132 L 420,132 ZM 420,188 L 252,188 L 252,356 L 312.489,295.511 L 400.864,383.886 L 447.886,336.864 L 359.511,248.489 ZM 135.511,295.511 L 196,356 L 196,188 L 28,188 L 88.489,248.489 L 0.114,336.864 L 47.136,383.886 Z" data-tags="contract, minimize, shrink, collapse" />
|
27
|
+
<glyph unicode="" d="M 417.111,351.344l-1.762,1.768c-41.19,41.184-108.585,41.184-149.768,0L 170.159,257.678
|
28
|
+
c-41.184-41.183-41.184-108.577,0-149.761l 1.761-1.761c 3.426-3.433, 7.064-6.529, 10.822-9.388l 34.934,34.934
|
29
|
+
c-4.070,2.404-7.93,5.281-11.426,8.776l-1.768,1.768c-22.362,22.355-22.362,58.744,0,81.108L 299.913,318.779
|
30
|
+
c 22.363,22.364, 58.745,22.364, 81.106,0l 1.768-1.76c 22.356-22.363, 22.356-58.753,0-81.108l-43.175-43.175
|
31
|
+
c 7.495-18.51, 11.046-38.238, 10.735-57.919l 66.764,66.764C 458.296,242.765, 458.296,310.159, 417.111,351.344zM 276.081,213.841c-3.426,3.426-7.064,6.528-10.822,9.38l-34.934-34.926c 4.071-2.405, 7.93-5.282, 11.426-8.777l 1.768-1.768
|
32
|
+
c 22.363-22.363, 22.363-58.744,0-81.107L 148.088,1.209c-22.364-22.357-58.746-22.357-81.107,0l-1.768,1.768
|
33
|
+
c-22.355,22.365-22.355,58.746,0,81.107l 43.176,43.175c-7.496,18.509-11.045,38.238-10.735,57.919l-66.763-66.762
|
34
|
+
c-41.184-41.183-41.184-108.578,0-149.767l 1.761-1.764c 41.191-41.181, 108.584-41.181, 149.768,0l 95.423,95.427
|
35
|
+
c 41.184,41.183, 41.184,108.585,0,149.768L 276.081,213.841z" data-tags="link, chain, url, uri, anchor" />
|
36
|
+
<glyph unicode="" d="M 334.75,182.25q 4.25-10.25 -3.5-17.5l-112-112q-4.5-4.75 -11.25-4.75t-11.25,4.75l-112,112q-7.75,7.25 -3.5,17.5q 4.25,9.75 14.75,9.75l 64,0 l0,112 q0,6.5 4.75,11.25t 11.25,4.75l 64,0 q 6.5,0 11.25-4.75t 4.75-11.25l0-112 l 64,0 q 10.5,0 14.75-9.75zM 408,128q 3.5,0 5.75-2.25t 2.25-5.75l0-144 q0-3.5 -2.25-5.75t-5.75-2.25l-400,0 q-3.5,0 -5.75,2.25t-2.25,5.75l0,144 q0,3.5 2.25,5.75 t 5.75,2.25l 48,0 q 3.5,0 5.75-2.25t 2.25-5.75l0-88 l 288,0 l0,88 q0,3.5 2.25,5.75t 5.75,2.25l 48,0 z" horiz-adv-x="416" data-tags="download-alt, arrow, store, save" />
|
37
|
+
<glyph unicode=" " horiz-adv-x="224" />
|
38
|
+
</font></defs></svg>
|
Binary file
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg">
|
4
|
+
<metadata>
|
5
|
+
This is a custom SVG font generated by IcoMoon.
|
6
|
+
<iconset grid="14"></iconset>
|
7
|
+
</metadata>
|
8
|
+
<defs>
|
9
|
+
<font id="icomoon" horiz-adv-x="448" >
|
10
|
+
<font-face units-per-em="448" ascent="384" descent="-64" />
|
11
|
+
<missing-glyph horiz-adv-x="448" />
|
12
|
+
<glyph class="hidden" unicode="" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
|
13
|
+
<glyph unicode="" d="M 448,384 L 448,216 L 387.511,276.489 L 294.761,183.739 L 247.739,230.761 L 340.489,323.511 L 280,384 ZM 107.511,323.511 L 200.261,230.761 L 153.239,183.739 L 60.489,276.489 L 0,216 L 0,384 L 168,384 ZM 387.511,43.511 L 448,104 L 448-64 L 280-64 L 340.489-3.511 L 247.739,89.239 L 294.761,136.261 ZM 200.261,89.239 L 107.511-3.511 L 168-64 L 0-64 L 0,104 L 60.489,43.511 L 153.239,136.261 Z" />
|
14
|
+
<glyph unicode="" d="M 252.322,188.35l 81.046,0 c-10.276,39.704-41.342,70.798-81.046,81.046L 252.322,188.35 zM 252.322,131.65l0-81.018 c 39.704,10.22, 70.77,41.342, 81.046,81.018L 252.322,131.65 zM 195.622,188.35L 195.622,269.396 c-39.704-10.248-70.826-41.342-81.046-81.046L 195.622,188.35 zM 195.622,131.65L 114.576,131.65 c 10.22-39.676, 41.342-70.798, 81.046-81.018L 195.622,131.65 zM 252.322,327.258c 71.036-12.026, 126.868-67.872, 138.908-138.908L 448,188.35 C 435.036,290.704, 354.704,371.064, 252.322,384L 252.322,327.258 z
|
15
|
+
M 56.714,188.35C 68.74,259.4, 124.572,315.232, 195.622,327.258L 195.622,384 C 93.296,371.064, 12.908,290.704,0,188.35L 56.714,188.35 zM 195.622-7.23c-71.036,12.026-126.868,67.816-138.908,138.88L0,131.65 C 12.908,29.296, 93.296-51.092, 195.622-64
|
16
|
+
L 195.622-7.23 zM 391.23,131.65c-12.026-71.064-67.872-126.854-138.908-138.88L 252.322-64 C 354.704-51.092, 435.036,29.296, 448,131.65
|
17
|
+
L 391.23,131.65 z" />
|
18
|
+
<glyph unicode="" d="M 65.618,1.618c-87.486,87.472-87.486,229.306,0,316.778
|
19
|
+
c 87.472,87.486, 229.306,87.486, 316.778,0c 87.486-87.472, 87.486-229.306,0-316.778C 294.91-85.868, 153.090-85.868, 65.618,1.618z M 342.79,278.79
|
20
|
+
L 105.21,41.21c 65.618-65.618, 171.976-65.618, 237.594,0S 408.408,213.186, 342.79,278.79z" />
|
21
|
+
<glyph unicode="" d="M 420-64L 28-64 c-15.456,0-28,12.544-28,28L0,356 c0,15.456, 12.544,28, 28,28l 336,0 l 84-84l0-336
|
22
|
+
C 448-51.456, 435.456-64, 420-64z M 112,6c0-7.742, 6.272-14, 14-14l 196,0 c 7.742,0, 14,6.258, 14,14l0,112 c0,7.742-6.258,14-14,14L 126,132 c-7.728,0-14-6.258-14-14L 112,6 z
|
23
|
+
M 308,314c0,7.742-6.258,14-14,14s-14-6.258-14-14l0-42 c0-7.742, 6.258-14, 14-14s 14,6.258, 14,14L 308,314 z M 392,286l-42,42l-14,0 l0-98 c0-7.742-6.258-14-14-14L 126,216
|
24
|
+
c-7.728,0-14,6.258-14,14L 112,328 L 70,328 C 62.272,328, 56,321.742, 56,314l0-308 c0-7.742, 6.272-14, 14-14l 14,0 L 84,146 c0,7.742, 6.272,14, 14,14l 252,0 c 7.742,0, 14-6.258, 14-14l0-154 l 14,0
|
25
|
+
c 7.742,0, 14,6.258, 14,14L 392,286 z" />
|
26
|
+
<glyph unicode="" d="M 28,132 L 196,132 L 196-36 L 135.511,24.489 L 47.136-63.886 L 0.114-16.864 L 88.489,71.511 ZM 359.511,71.511 L 447.886-16.864 L 400.864-63.886 L 312.489,24.489 L 252-36 L 252,132 L 420,132 ZM 420,188 L 252,188 L 252,356 L 312.489,295.511 L 400.864,383.886 L 447.886,336.864 L 359.511,248.489 ZM 135.511,295.511 L 196,356 L 196,188 L 28,188 L 88.489,248.489 L 0.114,336.864 L 47.136,383.886 Z" />
|
27
|
+
<glyph unicode="" d="M 417.111,351.344l-1.762,1.768c-41.19,41.184-108.585,41.184-149.768,0L 170.159,257.678
|
28
|
+
c-41.184-41.183-41.184-108.577,0-149.761l 1.761-1.761c 3.426-3.433, 7.064-6.529, 10.822-9.388l 34.934,34.934
|
29
|
+
c-4.070,2.404-7.93,5.281-11.426,8.776l-1.768,1.768c-22.362,22.355-22.362,58.744,0,81.108L 299.913,318.779
|
30
|
+
c 22.363,22.364, 58.745,22.364, 81.106,0l 1.768-1.76c 22.356-22.363, 22.356-58.753,0-81.108l-43.175-43.175
|
31
|
+
c 7.495-18.51, 11.046-38.238, 10.735-57.919l 66.764,66.764C 458.296,242.765, 458.296,310.159, 417.111,351.344zM 276.081,213.841c-3.426,3.426-7.064,6.528-10.822,9.38l-34.934-34.926c 4.071-2.405, 7.93-5.282, 11.426-8.777l 1.768-1.768
|
32
|
+
c 22.363-22.363, 22.363-58.744,0-81.107L 148.088,1.209c-22.364-22.357-58.746-22.357-81.107,0l-1.768,1.768
|
33
|
+
c-22.355,22.365-22.355,58.746,0,81.107l 43.176,43.175c-7.496,18.509-11.045,38.238-10.735,57.919l-66.763-66.762
|
34
|
+
c-41.184-41.183-41.184-108.578,0-149.767l 1.761-1.764c 41.191-41.181, 108.584-41.181, 149.768,0l 95.423,95.427
|
35
|
+
c 41.184,41.183, 41.184,108.585,0,149.768L 276.081,213.841z" />
|
36
|
+
<glyph unicode="" d="M 334.75,182.25q 4.25-10.25 -3.5-17.5l-112-112q-4.5-4.75 -11.25-4.75t-11.25,4.75l-112,112q-7.75,7.25 -3.5,17.5q 4.25,9.75 14.75,9.75l 64,0 l0,112 q0,6.5 4.75,11.25t 11.25,4.75l 64,0 q 6.5,0 11.25-4.75t 4.75-11.25l0-112 l 64,0 q 10.5,0 14.75-9.75zM 408,128q 3.5,0 5.75-2.25t 2.25-5.75l0-144 q0-3.5 -2.25-5.75t-5.75-2.25l-400,0 q-3.5,0 -5.75,2.25t-2.25,5.75l0,144 q0,3.5 2.25,5.75 t 5.75,2.25l 48,0 q 3.5,0 5.75-2.25t 2.25-5.75l0-88 l 288,0 l0,88 q0,3.5 2.25,5.75t 5.75,2.25l 48,0 z" horiz-adv-x="416" />
|
37
|
+
<glyph unicode=" " horiz-adv-x="224" />
|
38
|
+
</font></defs></svg>
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,318 @@
|
|
1
|
+
var editor = (function() {
|
2
|
+
|
3
|
+
// Editor elements
|
4
|
+
var headerField, contentField, cleanSlate, lastType, currentNodeList, savedSelection;
|
5
|
+
|
6
|
+
// Editor Bubble elements
|
7
|
+
var textOptions, optionsBox, boldButton, italicButton, quoteButton, urlButton, urlInput;
|
8
|
+
|
9
|
+
|
10
|
+
function init() {
|
11
|
+
if ($('#zenpenbubble').length){
|
12
|
+
lastRange = 0;
|
13
|
+
bindElements();
|
14
|
+
|
15
|
+
// Set cursor position
|
16
|
+
var range = document.createRange();
|
17
|
+
var selection = window.getSelection();
|
18
|
+
// range.setStart(headerField, 1);
|
19
|
+
selection.removeAllRanges();
|
20
|
+
selection.addRange(range);
|
21
|
+
|
22
|
+
createEventBindings();
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
function createEventBindings( on ) {
|
27
|
+
|
28
|
+
// Key up bindings
|
29
|
+
document.onkeyup = checkTextHighlighting;
|
30
|
+
|
31
|
+
// Mouse bindings
|
32
|
+
document.onmousedown = checkTextHighlighting;
|
33
|
+
document.onmouseup = function( event ) {
|
34
|
+
|
35
|
+
setTimeout( function() {
|
36
|
+
checkTextHighlighting( event );
|
37
|
+
}, 1);
|
38
|
+
};
|
39
|
+
|
40
|
+
// Window bindings
|
41
|
+
window.addEventListener( 'resize', function( event ) {
|
42
|
+
updateBubblePosition();
|
43
|
+
});
|
44
|
+
|
45
|
+
// Scroll bindings. We limit the events, to free the ui
|
46
|
+
// thread and prevent stuttering. See:
|
47
|
+
// http://ejohn.org/blog/learning-from-twitter
|
48
|
+
var scrollEnabled = true;
|
49
|
+
document.body.addEventListener( 'scroll', function() {
|
50
|
+
|
51
|
+
if ( !scrollEnabled ) {
|
52
|
+
return;
|
53
|
+
}
|
54
|
+
|
55
|
+
scrollEnabled = true;
|
56
|
+
|
57
|
+
updateBubblePosition();
|
58
|
+
|
59
|
+
return setTimeout((function() {
|
60
|
+
scrollEnabled = true;
|
61
|
+
}), 250);
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|
65
|
+
function bindElements() {
|
66
|
+
|
67
|
+
contentField = document.querySelector( '.content' );
|
68
|
+
textOptions = document.querySelector( '.text-options' );
|
69
|
+
|
70
|
+
optionsBox = textOptions.querySelector( '.options' );
|
71
|
+
|
72
|
+
boldButton = textOptions.querySelector( '.bold' );
|
73
|
+
boldButton.onclick = onBoldClick;
|
74
|
+
|
75
|
+
italicButton = textOptions.querySelector( '.italic' );
|
76
|
+
italicButton.onclick = onItalicClick;
|
77
|
+
|
78
|
+
// quoteButton = textOptions.querySelector( '.quote' );
|
79
|
+
// quoteButton.onclick = onQuoteClick;
|
80
|
+
|
81
|
+
urlButton = textOptions.querySelector( '.url' );
|
82
|
+
urlButton.onmousedown = onUrlClick;
|
83
|
+
|
84
|
+
urlInput = textOptions.querySelector( '.url-input' );
|
85
|
+
urlInput.onblur = onUrlInputBlur;
|
86
|
+
urlInput.onkeydown = onUrlInputKeyDown;
|
87
|
+
}
|
88
|
+
|
89
|
+
function checkTextHighlighting( event ) {
|
90
|
+
|
91
|
+
var selection = window.getSelection();
|
92
|
+
|
93
|
+
if (event.target.className === "url-input" || event.target.classList.contains( "url")) {
|
94
|
+
currentNodeList = findNodes( selection.focusNode );
|
95
|
+
updateBubbleStates();
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
|
99
|
+
if (event.target.parentNode.classList != null){
|
100
|
+
if (event.target.parentNode.classList.contains("ui-inputs")){
|
101
|
+
currentNodeList = findNodes( selection.focusNode );
|
102
|
+
updateBubbleStates();
|
103
|
+
return;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
// Check selections exist
|
108
|
+
if ( selection.isCollapsed === true && lastType === false ) {
|
109
|
+
onSelectorBlur();
|
110
|
+
}
|
111
|
+
|
112
|
+
// Text is selected
|
113
|
+
if ( selection.isCollapsed === false ) {
|
114
|
+
|
115
|
+
currentNodeList = findNodes( selection.focusNode );
|
116
|
+
// Find if highlighting is in the editable area
|
117
|
+
if (isContentEditable(selection.focusNode) == true) {
|
118
|
+
updateBubbleStates();
|
119
|
+
updateBubblePosition();
|
120
|
+
|
121
|
+
// Show the ui bubble
|
122
|
+
textOptions.className = "text-options active";
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
lastType = selection.isCollapsed;
|
127
|
+
}
|
128
|
+
|
129
|
+
function updateBubblePosition() {
|
130
|
+
var selection = window.getSelection();
|
131
|
+
var range = selection.getRangeAt(0);
|
132
|
+
var boundary = range.getBoundingClientRect();
|
133
|
+
|
134
|
+
textOptions.style.top = boundary.top - 5 + window.pageYOffset + "px";
|
135
|
+
textOptions.style.left = (boundary.left + boundary.right)/2 + "px";
|
136
|
+
}
|
137
|
+
|
138
|
+
function updateBubbleStates() {
|
139
|
+
|
140
|
+
// It would be possible to use classList here, but I feel that the
|
141
|
+
// browser support isn't quite there, and this functionality doesn't
|
142
|
+
// warrent a shim.
|
143
|
+
|
144
|
+
if ( hasNode( currentNodeList, 'B') ) {
|
145
|
+
boldButton.className = "bold active"
|
146
|
+
} else {
|
147
|
+
boldButton.className = "bold"
|
148
|
+
}
|
149
|
+
|
150
|
+
if ( hasNode( currentNodeList, 'I') ) {
|
151
|
+
italicButton.className = "italic active"
|
152
|
+
} else {
|
153
|
+
italicButton.className = "italic"
|
154
|
+
}
|
155
|
+
|
156
|
+
// if ( hasNode( currentNodeList, 'BLOCKQUOTE') ) {
|
157
|
+
// quoteButton.className = "quote active"
|
158
|
+
// } else {
|
159
|
+
// quoteButton.className = "quote"
|
160
|
+
// }
|
161
|
+
|
162
|
+
if ( hasNode( currentNodeList, 'A') ) {
|
163
|
+
urlButton.className = "url useicons active"
|
164
|
+
} else {
|
165
|
+
urlButton.className = "url useicons"
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
function onSelectorBlur() {
|
170
|
+
|
171
|
+
textOptions.className = "text-options fade";
|
172
|
+
setTimeout( function() {
|
173
|
+
|
174
|
+
if (textOptions.className == "text-options fade") {
|
175
|
+
|
176
|
+
textOptions.className = "text-options";
|
177
|
+
textOptions.style.top = '-999px';
|
178
|
+
textOptions.style.left = '-999px';
|
179
|
+
}
|
180
|
+
}, 260 )
|
181
|
+
}
|
182
|
+
|
183
|
+
function findNodes( element ) {
|
184
|
+
|
185
|
+
var nodeNames = {};
|
186
|
+
|
187
|
+
while ( element.parentNode ) {
|
188
|
+
|
189
|
+
nodeNames[element.nodeName] = true;
|
190
|
+
element = element.parentNode;
|
191
|
+
|
192
|
+
if ( element.nodeName === 'A' ) {
|
193
|
+
nodeNames.url = element.href;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
return nodeNames;
|
198
|
+
}
|
199
|
+
|
200
|
+
function isContentEditable(element){
|
201
|
+
//if any of its parents has the class of 'phrasable' go hooray
|
202
|
+
while ( element.parentNode ) {
|
203
|
+
if (element.className !== undefined){
|
204
|
+
if (element.className.indexOf("phrasable_on")>=0){
|
205
|
+
return true;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
element = element.parentNode;
|
209
|
+
}
|
210
|
+
return false;
|
211
|
+
}
|
212
|
+
|
213
|
+
function hasNode( nodeList, name ) {
|
214
|
+
return !!nodeList[ name ];
|
215
|
+
}
|
216
|
+
|
217
|
+
|
218
|
+
function onBoldClick() {
|
219
|
+
document.execCommand( 'bold', false );
|
220
|
+
}
|
221
|
+
|
222
|
+
function onItalicClick() {
|
223
|
+
document.execCommand( 'italic', false );
|
224
|
+
}
|
225
|
+
|
226
|
+
// function onQuoteClick() {
|
227
|
+
|
228
|
+
// var nodeNames = findNodes( window.getSelection().focusNode );
|
229
|
+
|
230
|
+
// if ( hasNode( nodeNames, 'BLOCKQUOTE' ) ) {
|
231
|
+
// document.execCommand( 'formatBlock', false, 'p' );
|
232
|
+
// document.execCommand( 'outdent' );
|
233
|
+
// } else {
|
234
|
+
// document.execCommand( 'formatBlock', false, 'blockquote' );
|
235
|
+
// }
|
236
|
+
// }
|
237
|
+
|
238
|
+
function onUrlClick() {
|
239
|
+
|
240
|
+
if ( optionsBox.className == 'options' ) {
|
241
|
+
|
242
|
+
optionsBox.className = 'options url-mode';
|
243
|
+
|
244
|
+
// Set timeout here to debounce the focus action
|
245
|
+
setTimeout( function() {
|
246
|
+
|
247
|
+
var nodeNames = findNodes( window.getSelection().focusNode );
|
248
|
+
|
249
|
+
if ( hasNode( nodeNames , "A" ) ) {
|
250
|
+
urlInput.value = nodeNames.url;
|
251
|
+
} else {
|
252
|
+
// Symbolize text turning into a link, which is temporary, and will never be seen.
|
253
|
+
document.execCommand( 'createLink', false, '/' );
|
254
|
+
}
|
255
|
+
|
256
|
+
// Since typing in the input box kills the highlighted text we need
|
257
|
+
// to save this selection, to add the url link if it is provided.
|
258
|
+
lastSelection = window.getSelection().getRangeAt(0);
|
259
|
+
lastType = false;
|
260
|
+
|
261
|
+
urlInput.focus();
|
262
|
+
|
263
|
+
}, 100);
|
264
|
+
|
265
|
+
} else {
|
266
|
+
|
267
|
+
optionsBox.className = 'options';
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
271
|
+
function onUrlInputKeyDown( event ) {
|
272
|
+
|
273
|
+
if ( event.keyCode === 13 ) {
|
274
|
+
event.preventDefault();
|
275
|
+
applyURL( urlInput.value );
|
276
|
+
urlInput.blur();
|
277
|
+
}
|
278
|
+
}
|
279
|
+
|
280
|
+
function onUrlInputBlur( event ) {
|
281
|
+
|
282
|
+
optionsBox.className = 'options';
|
283
|
+
applyURL( urlInput.value );
|
284
|
+
urlInput.value = '';
|
285
|
+
|
286
|
+
currentNodeList = findNodes( window.getSelection().focusNode );
|
287
|
+
updateBubbleStates();
|
288
|
+
}
|
289
|
+
|
290
|
+
function applyURL( url ) {
|
291
|
+
|
292
|
+
rehighlightLastSelection();
|
293
|
+
|
294
|
+
// Unlink any current links
|
295
|
+
document.execCommand( 'unlink', false );
|
296
|
+
|
297
|
+
if (url !== "") {
|
298
|
+
|
299
|
+
// Insert HTTP if it doesn't exist.
|
300
|
+
if ( !url.match("^(http|https)://") ) {
|
301
|
+
|
302
|
+
url = "http://" + url;
|
303
|
+
}
|
304
|
+
|
305
|
+
document.execCommand( 'createLink', false, url );
|
306
|
+
}
|
307
|
+
}
|
308
|
+
|
309
|
+
function rehighlightLastSelection() {
|
310
|
+
|
311
|
+
window.getSelection().addRange( lastSelection );
|
312
|
+
}
|
313
|
+
|
314
|
+
return {
|
315
|
+
init: init
|
316
|
+
}
|
317
|
+
|
318
|
+
})();
|