redactor-rails 0.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 +18 -0
- data/Gemfile +25 -0
- data/LICENSE +22 -0
- data/README.md +63 -0
- data/Rakefile +3 -0
- data/app/controller/redactor_rails/pictures_controller.rb +21 -0
- data/config/routes.rb +3 -0
- data/lib/generators/redactor/install_generator.rb +70 -0
- data/lib/generators/redactor/templates/active_record/carrierwave/migration.rb +27 -0
- data/lib/generators/redactor/templates/active_record/carrierwave/redactor/asset.rb +5 -0
- data/lib/generators/redactor/templates/active_record/carrierwave/redactor/attachment_file.rb +7 -0
- data/lib/generators/redactor/templates/active_record/carrierwave/redactor/picture.rb +7 -0
- data/lib/generators/redactor/templates/base/carrierwave/uploaders/redactor_rails_attachment_file_uploader.rb +42 -0
- data/lib/generators/redactor/templates/base/carrierwave/uploaders/redactor_rails_picture_uploader.rb +53 -0
- data/lib/redactor-rails.rb +30 -0
- data/lib/redactor-rails/backend/carrierwave.rb +64 -0
- data/lib/redactor-rails/configuration.rb +53 -0
- data/lib/redactor-rails/engine.rb +10 -0
- data/lib/redactor-rails/helper.rb +13 -0
- data/lib/redactor-rails/http.rb +89 -0
- data/lib/redactor-rails/orm/active_record.rb +26 -0
- data/lib/redactor-rails/orm/base.rb +37 -0
- data/lib/redactor-rails/version.rb +3 -0
- data/redactor-rails.gemspec +21 -0
- data/vendor/assets/javascripts/redactor-rails/css/docstyle.css +123 -0
- data/vendor/assets/javascripts/redactor-rails/css/style.css +119 -0
- data/vendor/assets/javascripts/redactor-rails/css/wym.css +136 -0
- data/vendor/assets/javascripts/redactor-rails/index.js +1 -0
- data/vendor/assets/javascripts/redactor-rails/langs/by.js +72 -0
- data/vendor/assets/javascripts/redactor-rails/langs/de.js +75 -0
- data/vendor/assets/javascripts/redactor-rails/langs/en.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/es.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/fr.js +74 -0
- data/vendor/assets/javascripts/redactor-rails/langs/hu.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/it.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/ja.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/lv.js +74 -0
- data/vendor/assets/javascripts/redactor-rails/langs/nl.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/pl.js +75 -0
- data/vendor/assets/javascripts/redactor-rails/langs/pt_br.js +81 -0
- data/vendor/assets/javascripts/redactor-rails/langs/ru.js +75 -0
- data/vendor/assets/javascripts/redactor-rails/langs/sq.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/tr.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/langs/ua.js +75 -0
- data/vendor/assets/javascripts/redactor-rails/langs/zh_cn.js +77 -0
- data/vendor/assets/javascripts/redactor-rails/langs/zh_tw.js +76 -0
- data/vendor/assets/javascripts/redactor-rails/plugins/file.html +3 -0
- data/vendor/assets/javascripts/redactor-rails/plugins/image.html +39 -0
- data/vendor/assets/javascripts/redactor-rails/plugins/image_edit.html +35 -0
- data/vendor/assets/javascripts/redactor-rails/plugins/link.html +74 -0
- data/vendor/assets/javascripts/redactor-rails/plugins/table.html +25 -0
- data/vendor/assets/javascripts/redactor-rails/plugins/video.html +15 -0
- data/vendor/assets/javascripts/redactor-rails/redactor.js +2259 -0
- data/vendor/assets/javascripts/redactor-rails/redactor.min.js +1 -0
- data/vendor/assets/javascripts/redactor-rails/toolbars/default.js +214 -0
- data/vendor/assets/javascripts/redactor-rails/toolbars/mini.js +103 -0
- data/vendor/assets/stylesheets/redactor-rails/css/redactor.css +368 -0
- data/vendor/assets/stylesheets/redactor-rails/img/icons.png +0 -0
- data/vendor/assets/stylesheets/redactor-rails/index.css +1 -0
- metadata +136 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module RedactorRails
|
2
|
+
class Configuration
|
3
|
+
class Function < String
|
4
|
+
def encode_json(encoder)
|
5
|
+
self
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.defaults
|
10
|
+
{
|
11
|
+
imageUpload: '/redactor_rails/pictures',
|
12
|
+
imageGetJson: '/redactor_rails/pictures'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :options
|
17
|
+
|
18
|
+
def initialize(options)
|
19
|
+
@options = options
|
20
|
+
end
|
21
|
+
|
22
|
+
def options_for_redactor
|
23
|
+
result = {}
|
24
|
+
|
25
|
+
options.each do |key, value|
|
26
|
+
if value.is_a?(Array) && value.all? { |v| v.is_a?(String) }
|
27
|
+
result[key] = value.join(",")
|
28
|
+
elsif value.to_s.starts_with?("function(")
|
29
|
+
result[key] = Function.new(value)
|
30
|
+
else
|
31
|
+
result[key] = value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
def merge(options)
|
39
|
+
self.class.new(self.options.merge(options))
|
40
|
+
end
|
41
|
+
|
42
|
+
def load(filename)
|
43
|
+
options.merge!(YAML::load(ERB.new(IO.read(filename)).result))
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.load(filename)
|
47
|
+
config = new(defaults)
|
48
|
+
config.load(filename) if File.exists?(filename)
|
49
|
+
config
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RedactorRails
|
2
|
+
module Helpers
|
3
|
+
def redactor(options={})
|
4
|
+
javascript_tag { redactor_javascript(options) }
|
5
|
+
end
|
6
|
+
|
7
|
+
# Returns the JavaScript code required to initialize RedactorRailsjs.
|
8
|
+
def redactor_javascript(options={})
|
9
|
+
configuration = RedactorRails.configuration.merge(options)
|
10
|
+
"$(document).ready(function(){$('.redactor').redactor(#{configuration.options_for_redactor.to_json});});".html_safe
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'mime/types'
|
4
|
+
|
5
|
+
module RedactorRails
|
6
|
+
module Http
|
7
|
+
# Create tempfile from hash
|
8
|
+
class UploadedFile
|
9
|
+
attr_accessor :original_filename, :content_type, :tempfile, :headers
|
10
|
+
|
11
|
+
def initialize(hash)
|
12
|
+
@original_filename = hash[:filename]
|
13
|
+
@content_type = hash[:type]
|
14
|
+
@headers = hash[:head]
|
15
|
+
@tempfile = hash[:tempfile]
|
16
|
+
raise(ArgumentError, ':tempfile is required') unless @tempfile
|
17
|
+
end
|
18
|
+
|
19
|
+
def open
|
20
|
+
@tempfile.open
|
21
|
+
end
|
22
|
+
|
23
|
+
def path
|
24
|
+
@tempfile.path
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(*args)
|
28
|
+
@tempfile.read(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def rewind
|
32
|
+
@tempfile.rewind
|
33
|
+
end
|
34
|
+
|
35
|
+
def size
|
36
|
+
@tempfile.size
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Usage (paperclip example)
|
41
|
+
# @asset.data = QqFile.new(params[:qqfile], request)
|
42
|
+
class QqFile < ::Tempfile
|
43
|
+
|
44
|
+
def initialize(filename, request, tmpdir = Dir::tmpdir)
|
45
|
+
@original_filename = filename
|
46
|
+
@request = request
|
47
|
+
|
48
|
+
super Digest::SHA1.hexdigest(filename), tmpdir
|
49
|
+
fetch
|
50
|
+
end
|
51
|
+
|
52
|
+
def fetch
|
53
|
+
self.write(body)
|
54
|
+
self.rewind
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def original_filename
|
59
|
+
@original_filename
|
60
|
+
end
|
61
|
+
|
62
|
+
def content_type
|
63
|
+
types = MIME::Types.type_for(original_filename)
|
64
|
+
types.empty? ? @request.content_type : types.first.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
def body
|
68
|
+
if @request.raw_post.respond_to?(:force_encoding)
|
69
|
+
@request.raw_post.force_encoding("UTF-8")
|
70
|
+
else
|
71
|
+
@request.raw_post
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Convert nested Hash to HashWithIndifferentAccess and replace
|
77
|
+
# file upload hash with UploadedFile objects
|
78
|
+
def self.normalize_param(*args)
|
79
|
+
value = args.first
|
80
|
+
if Hash === value && value.has_key?(:tempfile)
|
81
|
+
UploadedFile.new(value)
|
82
|
+
elsif value.is_a?(String)
|
83
|
+
QqFile.new(*args)
|
84
|
+
else
|
85
|
+
value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'redactor-rails/orm/base'
|
2
|
+
|
3
|
+
module RedactorRails
|
4
|
+
module Orm
|
5
|
+
module ActiveRecord
|
6
|
+
module AssetBase
|
7
|
+
def self.included(base)
|
8
|
+
base.send(:include, Base::AssetBase::InstanceMethods)
|
9
|
+
base.send(:extend, ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def self.extended(base)
|
14
|
+
base.class_eval do
|
15
|
+
self.table_name = "redactor_assets"
|
16
|
+
|
17
|
+
belongs_to :assetable, :polymorphic => true
|
18
|
+
|
19
|
+
attr_accessible :data, :assetable_type, :assetable_id, :assetable
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RedactorRails
|
2
|
+
module Orm
|
3
|
+
module Base
|
4
|
+
module AssetBase
|
5
|
+
module InstanceMethods
|
6
|
+
def has_dimensions?
|
7
|
+
respond_to?(:width) && respond_to?(:height)
|
8
|
+
end
|
9
|
+
|
10
|
+
def image?
|
11
|
+
RedactorRails::IMAGE_TYPES.include?(data_content_type)
|
12
|
+
end
|
13
|
+
|
14
|
+
def image
|
15
|
+
url
|
16
|
+
end
|
17
|
+
|
18
|
+
def thumb
|
19
|
+
url(:thumb)
|
20
|
+
end
|
21
|
+
|
22
|
+
def as_json_methods
|
23
|
+
[:image, :thumb]
|
24
|
+
end
|
25
|
+
|
26
|
+
def as_json(options = nil)
|
27
|
+
options = {
|
28
|
+
:methods => as_json_methods
|
29
|
+
}
|
30
|
+
|
31
|
+
super options
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/redactor-rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Sammy"]
|
6
|
+
gem.email = ["sammylintw@gmail.com"]
|
7
|
+
gem.description = "The redactor-rails gem integrates the Redactor editor"
|
8
|
+
gem.summary = ""
|
9
|
+
gem.homepage = "https://github.com/SammyLin/redactor-rails"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "redactor-rails"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = RedactorRails::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency("mime-types")
|
19
|
+
gem.add_dependency("orm_adapter")
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
html {
|
2
|
+
padding: 0;
|
3
|
+
margin: 0;
|
4
|
+
}
|
5
|
+
body {
|
6
|
+
font-family: "PT Sans", "Trebuchet MS", Verdana, Arial, Tahoma, sans-serif;
|
7
|
+
font-size: 17px;
|
8
|
+
margin: 0;
|
9
|
+
padding: 0;
|
10
|
+
overflow-x: hidden;
|
11
|
+
background: #f4f4f4;
|
12
|
+
}
|
13
|
+
#page {
|
14
|
+
max-width: 900px;
|
15
|
+
width: 74%;
|
16
|
+
margin: 20px auto;
|
17
|
+
padding: 15px 50px;
|
18
|
+
background: #fff;
|
19
|
+
border: 1px solid #ddd;
|
20
|
+
}
|
21
|
+
#page:focus {
|
22
|
+
outline: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
::selection {
|
26
|
+
background-color: #333;
|
27
|
+
color: #fff;
|
28
|
+
text-shadow: none;
|
29
|
+
}
|
30
|
+
|
31
|
+
div,
|
32
|
+
p,
|
33
|
+
ul,
|
34
|
+
ol,
|
35
|
+
table,
|
36
|
+
dl,
|
37
|
+
blockquote,
|
38
|
+
pre,
|
39
|
+
iframe,
|
40
|
+
object,
|
41
|
+
hr {
|
42
|
+
margin-bottom: 15px;
|
43
|
+
line-height: 1.5em;
|
44
|
+
}
|
45
|
+
blockquote {
|
46
|
+
margin-left: 3em;
|
47
|
+
font-style: italic;
|
48
|
+
color: #777;
|
49
|
+
}
|
50
|
+
ul, ol {
|
51
|
+
padding-left: 2em;
|
52
|
+
}
|
53
|
+
ul ul,
|
54
|
+
ol ol,
|
55
|
+
ul ol,
|
56
|
+
ol ul {
|
57
|
+
border: none;
|
58
|
+
margin: 2px !important;
|
59
|
+
padding: 0;
|
60
|
+
padding-left: 2em;
|
61
|
+
}
|
62
|
+
dl dt { font-weight: bold; }
|
63
|
+
dd { margin-left: 1em;}
|
64
|
+
|
65
|
+
table {
|
66
|
+
border-collapse: collapse;
|
67
|
+
font-size: 1em;
|
68
|
+
}
|
69
|
+
table td {
|
70
|
+
border: 1px solid #ddd;
|
71
|
+
padding: 5px;
|
72
|
+
}
|
73
|
+
table thead td {
|
74
|
+
border-bottom: 2px solid #000 !important;
|
75
|
+
font-weight: bold;
|
76
|
+
}
|
77
|
+
code, pre {
|
78
|
+
font-family: monospace sans-serif;
|
79
|
+
}
|
80
|
+
code {
|
81
|
+
background-color: #d8d7d7;
|
82
|
+
}
|
83
|
+
pre {
|
84
|
+
padding: 1em;
|
85
|
+
border: 1px dashed #ccc;
|
86
|
+
background: #f5f5f5;
|
87
|
+
overflow: auto;
|
88
|
+
}
|
89
|
+
hr {
|
90
|
+
display: block;
|
91
|
+
height: 1px;
|
92
|
+
border: 0;
|
93
|
+
border-top: 1px solid #ccc;
|
94
|
+
}
|
95
|
+
|
96
|
+
h1, h2, h3, h4,h5 {
|
97
|
+
font-weight: bold;
|
98
|
+
}
|
99
|
+
|
100
|
+
h1 {
|
101
|
+
font-size: 36px;
|
102
|
+
line-height: 40px;
|
103
|
+
margin-bottom: 10px;
|
104
|
+
}
|
105
|
+
h2 {
|
106
|
+
font-size: 30px;
|
107
|
+
line-height: 36px;
|
108
|
+
margin-bottom: 15px;
|
109
|
+
}
|
110
|
+
h3 {
|
111
|
+
font-size: 24px;
|
112
|
+
line-height: 30px;
|
113
|
+
margin-bottom: 10px;
|
114
|
+
}
|
115
|
+
h4 {
|
116
|
+
font-size: 18px;
|
117
|
+
line-height: 24px;
|
118
|
+
margin-bottom: 10px;
|
119
|
+
}
|
120
|
+
h4 {
|
121
|
+
font-size: 1em;
|
122
|
+
margin-bottom: 10px;
|
123
|
+
}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
html {
|
2
|
+
padding: 0;
|
3
|
+
margin: 0;
|
4
|
+
}
|
5
|
+
body {
|
6
|
+
font-family: "PT Sans", "Trebuchet MS", Verdana, Arial, Tahoma, sans-serif;
|
7
|
+
font-size: 17px;
|
8
|
+
margin: 0;
|
9
|
+
padding: 0;
|
10
|
+
overflow-x: hidden;
|
11
|
+
background: #fff;
|
12
|
+
}
|
13
|
+
#page {
|
14
|
+
margin: 20px;
|
15
|
+
background: #fff;
|
16
|
+
}
|
17
|
+
#page:focus {
|
18
|
+
outline: none;
|
19
|
+
}
|
20
|
+
|
21
|
+
::selection {
|
22
|
+
background-color: #333;
|
23
|
+
color: #fff;
|
24
|
+
text-shadow: none;
|
25
|
+
}
|
26
|
+
|
27
|
+
div,
|
28
|
+
p,
|
29
|
+
ul,
|
30
|
+
ol,
|
31
|
+
table,
|
32
|
+
dl,
|
33
|
+
blockquote,
|
34
|
+
pre,
|
35
|
+
iframe,
|
36
|
+
object,
|
37
|
+
hr {
|
38
|
+
margin-bottom: 15px;
|
39
|
+
line-height: 1.5em;
|
40
|
+
}
|
41
|
+
blockquote {
|
42
|
+
margin-left: 3em;
|
43
|
+
font-style: italic;
|
44
|
+
color: #777;
|
45
|
+
}
|
46
|
+
ul, ol {
|
47
|
+
padding-left: 2em;
|
48
|
+
}
|
49
|
+
ul ul,
|
50
|
+
ol ol,
|
51
|
+
ul ol,
|
52
|
+
ol ul {
|
53
|
+
border: none;
|
54
|
+
margin: 2px !important;
|
55
|
+
padding: 0;
|
56
|
+
padding-left: 2em;
|
57
|
+
}
|
58
|
+
dl dt { font-weight: bold; }
|
59
|
+
dd { margin-left: 1em;}
|
60
|
+
|
61
|
+
table {
|
62
|
+
border-collapse: collapse;
|
63
|
+
font-size: 1em;
|
64
|
+
}
|
65
|
+
table td {
|
66
|
+
border: 1px solid #ddd;
|
67
|
+
padding: 5px;
|
68
|
+
}
|
69
|
+
table thead td {
|
70
|
+
border-bottom: 2px solid #000 !important;
|
71
|
+
font-weight: bold;
|
72
|
+
}
|
73
|
+
code, pre {
|
74
|
+
font-family: monospace sans-serif;
|
75
|
+
}
|
76
|
+
code {
|
77
|
+
background-color: #d8d7d7;
|
78
|
+
}
|
79
|
+
pre {
|
80
|
+
padding: 1em;
|
81
|
+
border: 1px dashed #ccc;
|
82
|
+
background: #f5f5f5;
|
83
|
+
overflow: auto;
|
84
|
+
}
|
85
|
+
hr {
|
86
|
+
display: block;
|
87
|
+
height: 1px;
|
88
|
+
border: 0;
|
89
|
+
border-top: 1px solid #ccc;
|
90
|
+
}
|
91
|
+
|
92
|
+
h1, h2, h3, h4,h5 {
|
93
|
+
font-weight: bold;
|
94
|
+
}
|
95
|
+
|
96
|
+
h1 {
|
97
|
+
font-size: 36px;
|
98
|
+
line-height: 40px;
|
99
|
+
margin-bottom: 10px;
|
100
|
+
}
|
101
|
+
h2 {
|
102
|
+
font-size: 30px;
|
103
|
+
line-height: 36px;
|
104
|
+
margin-bottom: 15px;
|
105
|
+
}
|
106
|
+
h3 {
|
107
|
+
font-size: 24px;
|
108
|
+
line-height: 30px;
|
109
|
+
margin-bottom: 10px;
|
110
|
+
}
|
111
|
+
h4 {
|
112
|
+
font-size: 18px;
|
113
|
+
line-height: 24px;
|
114
|
+
margin-bottom: 10px;
|
115
|
+
}
|
116
|
+
h4 {
|
117
|
+
font-size: 1em;
|
118
|
+
margin-bottom: 10px;
|
119
|
+
}
|