textile_editor_helper 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +20 -0
  2. data/Gemfile +5 -0
  3. data/README.md +130 -0
  4. data/Rakefile +7 -0
  5. data/features/copy_assets.feature +17 -0
  6. data/features/step_definitions/common_steps.rb +66 -0
  7. data/features/step_definitions/rails_setup_steps.rb +9 -0
  8. data/features/support/env.rb +0 -0
  9. data/features/support/setup.rb +0 -0
  10. data/lib/generators/textile_editor_helper/install_generator.rb +54 -0
  11. data/lib/textile_editor_helper.rb +204 -0
  12. data/lib/textile_editor_helper/version.rb +3 -0
  13. data/test/abstract_unit.rb +16 -0
  14. data/test/textile_editor_helper_test.rb +195 -0
  15. data/textile_editor_helper.gemspec +27 -0
  16. data/travis.yml +5 -0
  17. data/vendor/README +95 -0
  18. data/vendor/app/controllers/textile_preview_controller.rb +14 -0
  19. data/vendor/app/helpers/textile_preview_helper.rb +14 -0
  20. data/vendor/app/views/textile_preview/show.js.coffee +2 -0
  21. data/vendor/assets/images/textile-editor/background.png +0 -0
  22. data/vendor/assets/images/textile-editor/blockquote.png +0 -0
  23. data/vendor/assets/images/textile-editor/bold.png +0 -0
  24. data/vendor/assets/images/textile-editor/center.png +0 -0
  25. data/vendor/assets/images/textile-editor/h1.png +0 -0
  26. data/vendor/assets/images/textile-editor/h2.png +0 -0
  27. data/vendor/assets/images/textile-editor/h3.png +0 -0
  28. data/vendor/assets/images/textile-editor/h4.png +0 -0
  29. data/vendor/assets/images/textile-editor/h5.png +0 -0
  30. data/vendor/assets/images/textile-editor/h6.png +0 -0
  31. data/vendor/assets/images/textile-editor/indent.png +0 -0
  32. data/vendor/assets/images/textile-editor/italic.png +0 -0
  33. data/vendor/assets/images/textile-editor/justify.png +0 -0
  34. data/vendor/assets/images/textile-editor/left.png +0 -0
  35. data/vendor/assets/images/textile-editor/list_bullets.png +0 -0
  36. data/vendor/assets/images/textile-editor/list_numbers.png +0 -0
  37. data/vendor/assets/images/textile-editor/omega.png +0 -0
  38. data/vendor/assets/images/textile-editor/outdent.png +0 -0
  39. data/vendor/assets/images/textile-editor/paragraph.png +0 -0
  40. data/vendor/assets/images/textile-editor/right.png +0 -0
  41. data/vendor/assets/images/textile-editor/strikethrough.png +0 -0
  42. data/vendor/assets/images/textile-editor/underline.png +0 -0
  43. data/vendor/assets/javascripts/textile-editor-config.js +22 -0
  44. data/vendor/assets/javascripts/textile-editor.js +687 -0
  45. data/vendor/assets/stylesheets/textile-editor.css +53 -0
  46. metadata +186 -0
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ doc
19
+ testing
20
+ project
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem "rake"
4
+ # Specify your gem's dependencies in textile_editor_helper.gemspec
5
+ gemspec
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ Textile Editor Helper
2
+ ==========================
3
+
4
+ Textile Editor Helper is a plugin for Ruby on Rails to add a Textile toolbar above textareas
5
+
6
+ This version of Textile Editor Helper is a fork of the code found at http://svn.webtest.wvu.edu/repos/rails/plugins/textile_editor_helper/ to allow for use with the form_for method.
7
+
8
+ Dependency
9
+ ----------
10
+
11
+ To use Textile Editor Helper you must be using either the jQuery JavaScript library.
12
+
13
+ jQuery is required and make sure $(document).ready() method is called. Prototype is no longer supported.
14
+
15
+ For Rails 3.2, vendor/plugins was removed that is why this gem exists.
16
+
17
+ Travis CI Build Status
18
+ -----------------------
19
+
20
+ [![Build Status](https://secure.travis-ci.org/bridgeutopia/textile_editor_helper.png)](http://travis-ci.org/bridgeutopia/textile_editor_helper)
21
+
22
+
23
+ To use Textile Editor Helper
24
+ ----------------------------
25
+
26
+ Directions to get the helper up and running for your install:
27
+
28
+ First, you'll need to add the gems required. RedCloth and htmlentities are for the preview feature.
29
+
30
+ `gem 'textile_editor_helper'`
31
+
32
+ `gem 'RedCloth'`
33
+
34
+ `gem 'htmlentities'`
35
+
36
+ and do
37
+
38
+ `rails g textile_editor_helper:install`
39
+
40
+ To use the Textile-Editor-Helper with a specific text area, you can choose between the following options:
41
+
42
+ <%= f.textile_editor :description %>
43
+
44
+ <%= textile_editor :user, "website" %>
45
+
46
+ <%= textile_editor_tag 'description', :description %>
47
+
48
+ **Just like writing a text area tag!**
49
+
50
+ At the end of your form put in the following code:
51
+
52
+ <%= textile_editor_initialize %> **Important!**
53
+
54
+
55
+ Then, just save your view and check it out
56
+
57
+
58
+ Simple vs. Extended
59
+ ===================
60
+
61
+ TEH has a built-in mode to show only a sub-selection of available tags called simple.
62
+
63
+ Currently the _simple_ tags are: _bold_, _underline_, _italic_, _strikethrough_.
64
+
65
+ To create a text area that will only use the 'simple' tags create your text area with the following code:
66
+
67
+ <%= textile_editor 'object', 'field', :simple -%>
68
+
69
+
70
+ To Modify Textile Editor Helper
71
+ -------------------------------
72
+
73
+ Most of the options that you might want to modify (e.g. access keystroke or whether a tag is available in simple) are found in textile_editor_config.js. Pretty straightforward.
74
+
75
+ TESTING (Cucumber is required)
76
+ --------------------
77
+ bundle exec rake
78
+
79
+ TEH Preview
80
+ --------------------
81
+ Recently added a preview feature. To use:
82
+
83
+ <%= f.textile_editor :body, :preview=>true %>
84
+
85
+ <%= textile_editor_initialize :preview=>true %>
86
+
87
+ This is shown in detail on the wiki page. Check it out.
88
+
89
+ Styling TEH Preview
90
+ --------------------
91
+ Add this to your CSS file and modify as needed:
92
+
93
+ .textile-preview {
94
+ width:83%;
95
+ padding:20px;
96
+ margin:10px 0px;
97
+ border:5px dotted #eee;
98
+ display:block;
99
+ }
100
+
101
+
102
+ More Info on Textile
103
+ --------------------
104
+
105
+ To learn more about Textile check out: Textism, http://www.textism.com/tools/textile/index.php & Textile Reference, http://hobix.com/textile/
106
+
107
+
108
+ More Info on Slate
109
+ ------------------
110
+
111
+ slate is the CMS in development at West Virginia University that led to the development of Textile Editor Helper. Learn more at: http://slateinfo.blogs.wvu.edu
112
+
113
+
114
+ License
115
+ -------
116
+ Textile Editor Helper is released under the MIT license.
117
+
118
+
119
+ Credits
120
+ -------
121
+
122
+ Textile Editor Helper was created by Dave Olsen (Javascript) and Chris Scharf (Ruby/Rails) of West Virginia University Web Services (http://webservices.wvu.edu/)
123
+
124
+ The project is now, unofficially maintained by Nicolás Hock
125
+
126
+ Inspired by
127
+ -----------
128
+
129
+ Patrick Woods, http://www.hakjoon.com/code/38/textile-quicktags-redirect &
130
+ Alex King, http://alexking.org/projects/js-quicktags
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ task(:default).clear
4
+ task :default => [:cucumber]
5
+
6
+ require 'cucumber/rake/task'
7
+ Cucumber::Rake::Task.new
@@ -0,0 +1,17 @@
1
+ Feature: Copy Assets
2
+ In order to install the textile editor helper gem
3
+ As a rails developer
4
+ I want to copy the assets to respective directories
5
+
6
+
7
+ Scenario: Assets are copied to rails asset directories
8
+ Given a new Rails app
9
+ When I run "rails g textile_editor_helper:install"
10
+ Then I should see file "app/assets/stylesheets/textile-editor.css"
11
+ And I should see file "app/assets/javascripts/textile-editor-config.js"
12
+ And I should see file "app/assets/javascripts/textile-editor.js"
13
+ And I should see file "public/images/textile-editor/italic.png"
14
+ And I should see file "app/controllers/textile_preview_controller.rb"
15
+ And I should see file "app/helpers/textile_preview_helper.rb"
16
+ And I should see file "app/views/textile_preview/show.js.coffee"
17
+ And I should see "textile_preview" in file "config/routes.rb"
@@ -0,0 +1,66 @@
1
+ When /^I run "([^\"]*)"$/ do |command|
2
+ system("cd #{@current_directory} && #{command}").should be_true
3
+ end
4
+
5
+ When /^I add "([^\"]*)" to file "([^\"]*)"$/ do |content, short_path|
6
+ path = File.join(@current_directory, short_path)
7
+ File.should exist(path)
8
+ File.open(path, 'a') { |f| f.write(content + "\n") }
9
+ end
10
+
11
+ Then /^the file "([^"]*)" should contain:$/ do |file, content|
12
+ check_file_content(file, content, true)
13
+ end
14
+
15
+ When /^I replace "([^\"]*)" with "([^\"]*)" in file "([^\"]*)"$/ do |old_content, new_content, short_path|
16
+ path = File.join(@current_directory, short_path)
17
+ File.should exist(path)
18
+ content = File.read(path).gsub(old_content, new_content)
19
+ File.open(path, 'w') { |f| f.write(content) }
20
+ end
21
+
22
+ When /^I insert "([^\"]*)" into "([^\"]*)" after line (\d+)$/ do |content, short_path, after_line|
23
+ path = File.join(@current_directory, short_path)
24
+ File.should exist(path)
25
+ lines = File.read(path).split("\n")
26
+ lines[after_line.to_i, 0] = content
27
+ File.open(path, 'w') { |f| f.write(lines.join("\n")) }
28
+ end
29
+
30
+ Then /^I should see file "([^\"]*)"$/ do |path|
31
+ File.should exist(File.join(@current_directory, path))
32
+ end
33
+
34
+ Then /^I should see "(.*)" in file "([^\"]*)"$/ do |content, short_path|
35
+ path = File.join(@current_directory, short_path)
36
+ File.should exist(path)
37
+ File.readlines(path).join.should include(content)
38
+ end
39
+
40
+ Then /^I should not see "(.*)" in file "([^\"]*)"$/ do |content, short_path|
41
+ path = File.join(@current_directory, short_path)
42
+ File.should exist(path)
43
+ File.readlines(path).join.should_not include(content)
44
+ end
45
+
46
+ Then /^I should see the following files$/ do |table|
47
+ table.raw.flatten.each do |path|
48
+ File.should exist(File.join(@current_directory, path))
49
+ end
50
+ end
51
+
52
+ Then /^I should see the following in file "([^\"]*)"$/ do |short_path, table|
53
+ path = File.join(@current_directory, short_path)
54
+ File.should exist(path)
55
+ table.raw.flatten.each do |content|
56
+ File.readlines(path).join.should include(content)
57
+ end
58
+ end
59
+
60
+ Then /^I should successfully run "([^\"]*)"$/ do |command|
61
+ system("cd #{@current_directory} && #{command}").should be_true
62
+ end
63
+
64
+ Then /^I should see "([^\"]*)" when running "([^\"]*)"$/ do |expected_response, command|
65
+ `cd #{@current_directory} && #{command}`.should include(expected_response)
66
+ end
@@ -0,0 +1,9 @@
1
+ Given /^a new Rails app$/ do
2
+ FileUtils.mkdir_p("tmp")
3
+ system("rm -rf tmp/rails_app")
4
+ system("rails new tmp/rails_app")
5
+ system("ln -s ../../../lib/generators tmp/rails_app/lib")
6
+ system("rm -rf tmp/rails_app/vendor")
7
+ system("ln -s ../../vendor tmp/rails_app")
8
+ @current_directory = File.expand_path("tmp/rails_app")
9
+ end
File without changes
File without changes
@@ -0,0 +1,54 @@
1
+ module TextileEditorHelper
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../../../../vendor', __FILE__)
5
+
6
+ private
7
+
8
+ def self.asset_pipeline_enabled?
9
+ (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets || {}) : {})[:enabled]
10
+ end
11
+
12
+ def asset_pipeline_enabled?
13
+ self.class.asset_pipeline_enabled?
14
+ end
15
+
16
+ public
17
+
18
+ if asset_pipeline_enabled?
19
+ desc 'Creates a TextileEditorHelper initializer and copies assets to app/assets and public/images.'
20
+ else
21
+ desc 'Creates a TextileEditorHelper initializer and copies assets to public directories.'
22
+ end
23
+
24
+ def copy_javascript_asset
25
+ if asset_pipeline_enabled?
26
+ js_destination = 'app/assets/javascripts'
27
+ css_destination = 'app/assets/stylesheets'
28
+ else
29
+ js_destination = 'public/javascripts'
30
+ css_destination = 'public/stylesheets'
31
+ end
32
+
33
+ copy_file 'assets/javascripts/textile-editor.js', "#{js_destination}/textile-editor.js"
34
+ copy_file 'assets/javascripts/textile-editor-config.js', "#{js_destination}/textile-editor-config.js"
35
+ copy_file 'assets/stylesheets/textile-editor.css', "#{css_destination}/textile-editor.css"
36
+ copy_file 'app/controllers/textile_preview_controller.rb', "app/controllers/textile_preview_controller.rb"
37
+ copy_file 'app/helpers/textile_preview_helper.rb', "app/helpers/textile_preview_helper.rb"
38
+
39
+
40
+ lines = File.read("config/routes.rb").split("\n")
41
+ lines[3, 0] = "match 'textile_preview' => 'textile_preview#show'"
42
+ File.open("config/routes.rb", 'w') { |f| f.write(lines.join("\n")) }
43
+
44
+
45
+ directory 'app/views/textile_preview', 'app/views/textile_preview'
46
+ directory 'assets/images/textile-editor', 'public/images/textile-editor'
47
+
48
+ readme 'README' if behavior == :invoke
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,204 @@
1
+ require "textile_editor_helper/version"
2
+
3
+ module TextileEditorHelper
4
+ # Your code goes here...
5
+ end
6
+
7
+
8
+ module ActionView
9
+ module Helpers
10
+
11
+ class FormBuilder
12
+ def textile_editor(method, options = {})
13
+ @template.textile_editor(@object_name, method, options.merge(:object => @object))
14
+ end
15
+ end
16
+
17
+
18
+ module FormHelper
19
+
20
+ # Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+)
21
+ # on an object assigned to the template (identified by +object+). Additional options on the input tag can be passed as a
22
+ # hash with +options+ and places the textile toolbar above it
23
+ #
24
+ # ==== Examples
25
+ # textile_editor(:post, :body, :cols => 20, :rows => 40)
26
+ # # => <textarea cols="20" rows="40" id="post_body" name="post[body]">
27
+ # # #{@post.body}
28
+ # # </textarea>
29
+ #
30
+ # textile_editor(:comment, :text, :size => "20x30")
31
+ # # => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
32
+ # # #{@comment.text}
33
+ # # </textarea>
34
+ #
35
+ # textile_editor(:application, :notes, :cols => 40, :rows => 15, :class => 'app_input')
36
+ # # => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
37
+ # # #{@application.notes}
38
+ # # </textarea>
39
+ #
40
+ # textile_editor(:entry, :body, :size => "20x20", :disabled => 'disabled')
41
+ # # => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
42
+ # # #{@entry.body}
43
+ # # </textarea>
44
+ def textile_editor(object_name, method, options = {})
45
+ editor_id = options[:id] || '%s_%s' % [object_name, method]
46
+ mode = options.delete(:simple) ? 'simple' : 'extended'
47
+ (@textile_editor_ids ||= []) << [editor_id.to_s, mode.to_s]
48
+
49
+ output = []
50
+ output << InstanceTag.new(object_name, method, self, options.delete(:object)).to_text_area_tag(options)
51
+ output << %q{<div id="%s_destination" class="textile-preview"></div>} % [editor_id] if options[:preview]
52
+ output.join("\n").html_safe
53
+
54
+ end
55
+
56
+ def textile_editor_options(options={})
57
+ (@textile_editor_options ||= { :preview=>false }).merge! options
58
+ end
59
+
60
+ def textile_editor_support
61
+ output = []
62
+ output << stylesheet_link_tag('textile-editor')
63
+ output << javascript_include_tag('textile-editor')
64
+ output.join("\n").html_safe
65
+ end
66
+
67
+ # registers a new button for the Textile Editor toolbar
68
+ # Parameters:
69
+ # * +text+: text to display (contents of button tag, so HTML is valid as well)
70
+ # * +options+: options Hash as supported by +content_tag+ helper in Rails
71
+ #
72
+ # Example:
73
+ # The following example adds a button labeled 'Greeting' which triggers an
74
+ # alert:
75
+ #
76
+ # <% textile_editor_button 'Greeting', :onclick => "alert('Hello!')" %>
77
+ #
78
+ # *Note*: this method must be called before +textile_editor_initialize+
79
+ def textile_editor_button(text, options={})
80
+ return textile_editor_button_separator if text == :separator
81
+ button = content_tag(:button, text, options)
82
+ button = "TextileEditor.buttons.push(\"%s\");" % escape_javascript(button)
83
+ (@textile_editor_buttons ||= []) << button
84
+ end
85
+
86
+ def textile_editor_button_separator(options={})
87
+ button = "TextileEditor.buttons.push(new TextileEditorButtonSeparator('%s'));" % (options[:simple] || '')
88
+ (@textile_editor_buttons ||= []) << button
89
+ end
90
+
91
+ def textile_extract_dom_ids(*dom_ids)
92
+ hash = dom_ids.last.is_a?(Hash) ? dom_ids.pop : {}
93
+ hash.inject(dom_ids) do |ids, (object, fields)|
94
+ ids + Array(fields).map { |field| "%s_%s" % [object, field] }
95
+ end
96
+ end
97
+
98
+ # adds the necessary javascript include tags, stylesheet tags,
99
+ # and load event with necessary javascript to active textile editor(s)
100
+ # sample output:
101
+ # <link href="/stylesheets/textile-editor.css" media="screen" rel="stylesheet" type="text/css" />
102
+ # <script src="/javascripts/textile-editor.js" type="text/javascript"></script>
103
+ # <script type="text/javascript">
104
+ # document.observe('dom:loaded', function() {
105
+ # TextileEditor.initialize('article_body', 'extended');
106
+ # TextileEditor.initialize('article_body_excerpt', 'simple');
107
+ # });
108
+ # </script>
109
+ #
110
+ # Note: in the case of this helper being called via AJAX, the output will be reduced:
111
+ # <script type="text/javascript">
112
+ # TextileEditor.initialize('article_body', 'extended');
113
+ # TextileEditor.initialize('article_body_excerpt', 'simple');
114
+ # </script>
115
+ #
116
+ # This means that the support files must be loaded outside of the AJAX request, either
117
+ # via a call to this helper or the textile_editor_support() helper
118
+ def textile_editor_initialize(*dom_ids)
119
+ options = textile_editor_options.dup
120
+
121
+ # extract options from last argument if it's a hash
122
+ if dom_ids.last.is_a?(Hash)
123
+ hash = dom_ids.last.dup
124
+ options.merge! hash
125
+ dom_ids.last.delete :framework
126
+ end
127
+
128
+ editor_ids = (@textile_editor_ids || []) + textile_extract_dom_ids(*dom_ids)
129
+ editor_buttons = (@textile_editor_buttons || [])
130
+ output = []
131
+ output << textile_editor_support unless request.xhr?
132
+ output << '<script type="text/javascript">'
133
+ output << '/* <![CDATA[ */'
134
+
135
+ if !request.xhr?
136
+ output << %{$(document).ready(function() \{}
137
+ end
138
+
139
+ output << editor_buttons.join("\n") if editor_buttons.any?
140
+ editor_ids.each do |editor_id, mode|
141
+
142
+ output << %q{TextileEditor.initialize('%s', '%s');} % [editor_id, mode || 'extended']
143
+
144
+
145
+ output << %q{ $("#%s").keyup(function() {
146
+ var textile_string = $("#%s").val();
147
+ if($("#%s_destination")[0]) {
148
+
149
+ $.post("/textile_preview", { text_data: textile_string, id: "%s"} );
150
+ }
151
+ });
152
+
153
+ } % [editor_id, editor_id, editor_id, editor_id] if options[:preview]
154
+
155
+
156
+ end
157
+ output << '});' unless request.xhr?
158
+
159
+ output << '/* ]]> */'
160
+ output << '</script>'
161
+ output.join("\n").html_safe
162
+ end
163
+ end
164
+
165
+ module FormTagHelper
166
+ # Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions
167
+ # and includes the textile toolbar above it.
168
+ #
169
+ # ==== Options
170
+ # * <tt>:size</tt> - A string specifying the dimensions (columns by rows) of the textarea (e.g., "25x10").
171
+ # * <tt>:rows</tt> - Specify the number of rows in the textarea
172
+ # * <tt>:cols</tt> - Specify the number of columns in the textarea
173
+ # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
174
+ # * Any other key creates standard HTML attributes for the tag.
175
+ #
176
+ # ==== Examples
177
+ # textile_editor_tag 'post'
178
+ # # => <textarea id="post" name="post"></textarea>
179
+ #
180
+ # textile_editor_tag 'bio', @user.bio
181
+ # # => <textarea id="bio" name="bio">This is my biography.</textarea>
182
+ #
183
+ # textile_editor_tag 'body', nil, :rows => 10, :cols => 25
184
+ # # => <textarea cols="25" id="body" name="body" rows="10"></textarea>
185
+ #
186
+ # textile_editor_tag 'body', nil, :size => "25x10"
187
+ # # => <textarea name="body" id="body" cols="25" rows="10"></textarea>
188
+ #
189
+ # textile_editor_tag 'description', "Description goes here.", :disabled => true
190
+ # # => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
191
+ #
192
+ # textile_editor_tag 'comment', nil, :class => 'comment_input'
193
+ # # => <textarea class="comment_input" id="comment" name="comment"></textarea>
194
+ def textile_editor_tag(name, content = nil, options = {})
195
+ editor_id = options[:id] || name
196
+ mode = options.delete(:simple) ? 'simple' : 'extended'
197
+ (@textile_editor_ids ||= []) << [editor_id.to_s, mode.to_s]
198
+
199
+ text_area_tag(name, content, options)
200
+ end
201
+ end
202
+
203
+ end
204
+ end