redcloth-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Gemfile +8 -0
  2. data/LICENSE +21 -0
  3. data/README.textile +58 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/images/textile-editor/background.png +0 -0
  6. data/app/assets/images/textile-editor/blockquote.png +0 -0
  7. data/app/assets/images/textile-editor/bold.png +0 -0
  8. data/app/assets/images/textile-editor/center.png +0 -0
  9. data/app/assets/images/textile-editor/h1.png +0 -0
  10. data/app/assets/images/textile-editor/h2.png +0 -0
  11. data/app/assets/images/textile-editor/h3.png +0 -0
  12. data/app/assets/images/textile-editor/h4.png +0 -0
  13. data/app/assets/images/textile-editor/h5.png +0 -0
  14. data/app/assets/images/textile-editor/h6.png +0 -0
  15. data/app/assets/images/textile-editor/indent.png +0 -0
  16. data/app/assets/images/textile-editor/italic.png +0 -0
  17. data/app/assets/images/textile-editor/justify.png +0 -0
  18. data/app/assets/images/textile-editor/left.png +0 -0
  19. data/app/assets/images/textile-editor/list_bullets.png +0 -0
  20. data/app/assets/images/textile-editor/list_numbers.png +0 -0
  21. data/app/assets/images/textile-editor/omega.png +0 -0
  22. data/app/assets/images/textile-editor/outdent.png +0 -0
  23. data/app/assets/images/textile-editor/paragraph.png +0 -0
  24. data/app/assets/images/textile-editor/right.png +0 -0
  25. data/app/assets/images/textile-editor/strikethrough.png +0 -0
  26. data/app/assets/images/textile-editor/underline.png +0 -0
  27. data/app/assets/javascripts/textile-editor-config.js.coffee.erb +23 -0
  28. data/app/assets/javascripts/textile-editor.js.coffee +521 -0
  29. data/app/assets/stylesheets/textile-editor.css.scss +44 -0
  30. data/lib/rails/generators/textile_editor_config/USAGE +11 -0
  31. data/lib/rails/generators/textile_editor_config/templates/textile-editor-config.js.coffee.erb +23 -0
  32. data/lib/rails/generators/textile_editor_config/textile_editor_config_generator.rb +9 -0
  33. data/lib/redcloth-rails/engine.rb +18 -0
  34. data/lib/redcloth-rails/helpers/form_builder.rb +14 -0
  35. data/lib/redcloth-rails/helpers/form_helper.rb +137 -0
  36. data/lib/redcloth-rails/helpers/form_tag_helper.rb +49 -0
  37. data/lib/redcloth-rails/helpers.rb +9 -0
  38. data/lib/redcloth-rails/version.rb +5 -0
  39. data/lib/redcloth-rails.rb +15 -0
  40. data/redcloth-rails.gemspec +20 -0
  41. metadata +138 -0
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'RedCloth', '>= 4.2.0'
4
+ gem 'rails', '>= 3.1.0'
5
+ gem 'rdoc'
6
+ gem 'bundler'
7
+
8
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2013 emjot GmbH & Co. KG
2
+ Copyright (c) 2011 Thor Johnson
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,58 @@
1
+ h2. redcloth-rails
2
+
3
+ bq. Homepage: "Github":https://github.com/emjot/redcloth-rails
4
+ Author: emjot GmbH & Co. KG
5
+
6
+ p. The redcloth-rails gem enables "RedCloth":http://redcloth.org for rails (>= 3.1).
7
+ It provides helpers to integrate the _TextileEditor_ toolbar and its assets are pipeline ready ...
8
+
9
+ h4. History
10
+
11
+ p. The _TextileEditor_ was created by Dave Olsen (Javascript) and Chris Scharf (Ruby/Rails) of "West Virginia University Web Services":http://webservices.wvu.edu .
12
+ The rails 3.0 support and gemification was realized by ryanfelton (https://github.com/ryanfelton/textile-editor-helper).
13
+
14
+ h4. Dependencies
15
+
16
+ * RedCloth (>= 4.2)
17
+ * Rails (>= 3.1)
18
+ * Rails Asset Pipeline
19
+ * JQuery
20
+
21
+ h4. Installation (via Bundler)
22
+
23
+ pre. Gemfile:
24
+ gem "redcloth-rails"
25
+
26
+ h4. Setup
27
+
28
+ Generate a config file
29
+
30
+ pre. rails g textile_editor_config
31
+
32
+ Include the coffees script and scss files in your asset pipeline
33
+
34
+ pre. app/assets/javascripts/application.js:
35
+ (...)
36
+ //= require textile-editor
37
+ //= require ./textile-editor-config
38
+
39
+ pre. app/assets/stylesheets/application.css:
40
+ (...)
41
+ *= require textile-editor
42
+
43
+ h4. Usage
44
+
45
+ Enable the _TextileEditor_ for your attributes via:
46
+
47
+ pre. <%= textile_editor :content %>
48
+
49
+ Initialize the _TextileEditor_ afterwards via:
50
+
51
+ pre. <%= textile_editor_initialize %>
52
+
53
+ h4. Links
54
+
55
+ p(. "redcloth.org":http://redcloth.org
56
+ "textile_editor_helper (original)":http://slatecms.wvu.edu/open_source
57
+ "textile_editor_helper (upadated for rails 3)":https://github.com/ryanfelton/textile-editor-helper
58
+ "more info on textile":http://www.textism.com/tools/textile/
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+ require 'RedCloth'
3
+
4
+ Rake::TestTask.new do |test|
5
+ test.pattern = 'test/**/*_test.rb'
6
+ test.libs << 'test'
7
+ end
8
+
@@ -0,0 +1,23 @@
1
+ TextileEditor.setButtons(
2
+ [
3
+ new TextileEditorButton("ed_strong", "<%= asset_path('textile-editor/bold.png') %>", "*", "*", "b", "Bold", "s"),
4
+ new TextileEditorButton("ed_emphasis", "<%= asset_path('textile-editor/italic.png') %>", "_", "_", "i", "Italicize", "s"),
5
+ new TextileEditorButton("ed_underline", "<%= asset_path('textile-editor/underline.png') %>", "+", "+", "u", "Underline", "s"),
6
+ new TextileEditorButton("ed_strike", "<%= asset_path('textile-editor/strikethrough.png') %>", "-", "-", "s", "Strikethrough", "s"),
7
+ new TextileEditorButton("ed_ol", "<%= asset_path('textile-editor/list_numbers.png') %>", " # ", "\n", ",", "Numbered List"),
8
+ new TextileEditorButton("ed_ul", "<%= asset_path('textile-editor/list_bullets.png') %>", " * ", "\n", ".", "Bulleted List"),
9
+ new TextileEditorButton("ed_p", "<%= asset_path('textile-editor/paragraph.png') %>", "p", "\n", "p", "Paragraph"),
10
+ new TextileEditorButton("ed_h1", "<%= asset_path('textile-editor/h1.png') %>", "h1", "\n", "1", "Header 1"),
11
+ new TextileEditorButton("ed_h2", "<%= asset_path('textile-editor/h2.png') %>", "h2", "\n", "2", "Header 2"),
12
+ new TextileEditorButton("ed_h3", "<%= asset_path('textile-editor/h3.png') %>", "h3", "\n", "3", "Header 3"),
13
+ new TextileEditorButton("ed_h4", "<%= asset_path('textile-editor/h4.png') %>", "h4", "\n", "4", "Header 4"),
14
+ new TextileEditorButton("ed_block", "<%= asset_path('textile-editor/blockquote.png') %>", "bq", "\n", "q", "Blockquote"),
15
+ new TextileEditorButton("ed_outdent", "<%= asset_path('textile-editor/outdent.png') %>", ")", "\n", "]", "Outdent"),
16
+ new TextileEditorButton("ed_indent", "<%= asset_path('textile-editor/indent.png') %>", "(", "\n", "[", "Indent"),
17
+ new TextileEditorButton("ed_justifyl", "<%= asset_path('textile-editor/left.png') %>", "<", "\n", "l", "Left Justify"),
18
+ new TextileEditorButton("ed_justifyc", "<%= asset_path('textile-editor/center.png') %>", "=", "\n", "e", "Center Text"),
19
+ new TextileEditorButton("ed_justifyr", "<%= asset_path('textile-editor/right.png') %>", ">", "\n", "r", "Right Justify"),
20
+ new TextileEditorButton("ed_justify", "<%= asset_path('textile-editor/justify.png') %>", "<>", "\n", "j", "Justify"),
21
+ # new TextileEditorButton('ed_code','code','@','@','c','Code')
22
+ ]
23
+ )
@@ -0,0 +1,521 @@
1
+ #Textile Editor v0.2
2
+ #created by: dave olsen, wvu web services
3
+ #created on: march 17, 2007
4
+ #project page: slateinfo.blogs.wvu.edu
5
+ #
6
+ #inspired by:
7
+ # - Patrick Woods, http://www.hakjoon.com/code/38/textile-quicktags-redirect &
8
+ # - Alex King, http://alexking.org/projects/js-quicktags
9
+ #
10
+ #features:
11
+ # - supports: IE7, FF2, Safari2
12
+ # - ability to use "simple" vs. "extended" editor
13
+ # - supports all block elements in textile except footnote
14
+ # - supports all block modifier elements in textile
15
+ # - supports simple ordered and unordered lists
16
+ # - supports most of the phrase modifiers, very easy to add the missing ones
17
+ # - supports multiple-paragraph modification
18
+ # - can have multiple "editors" on one page, access key use in this environment is flaky
19
+ # - access key support
20
+ # - select text to add and remove tags, selection stays highlighted
21
+ # - seamlessly change between tags and modifiers
22
+ # - doesn't need to be in the body onload tag
23
+ # - can supply your own, custom IDs for the editor to be drawn around
24
+ #
25
+ #todo:
26
+ # - a clean way of providing image and link inserts
27
+ # - get the selection to properly show in IE
28
+ #
29
+ #more on textile:
30
+ # - Textism, http://www.textism.com/tools/textile/index.php
31
+ # - Textile Reference, http://hobix.com/textile/
32
+
33
+
34
+ class TextileEditorButton
35
+
36
+ constructor: (id, display, tagStart, tagEnd, access, title, sve, open) ->
37
+ @id = id # used to name the toolbar button
38
+ @display = display # label on button
39
+ @tagStart = tagStart # open tag
40
+ @tagEnd = tagEnd # close tag
41
+ @access = access # set to -1 if tag does not need to be closed
42
+ @title = title # sets the title attribute of the button to give 'tool tips'
43
+ @sve = sve # sve = simple vs. extended. add an 's' to make it show up in the simple toolbar
44
+ @open = open # set to -1 if tag does not need to be closed
45
+ @standard = true # this is a standard button
46
+ # this.framework = 'prototype'; // the JS framework used
47
+
48
+ window.TextileEditorButton = TextileEditorButton
49
+
50
+
51
+ class TextileEditorButtonSeparator
52
+
53
+ constructor: (sve) ->
54
+ @separator = true
55
+ @sve = sve
56
+
57
+ window.TextileEditorButtonSeparator = TextileEditorButtonSeparator
58
+
59
+ class TextileEditor
60
+
61
+ @setButtons: (buttons) ->
62
+ TextileEditor.buttons = buttons
63
+
64
+ @addButton: (button) ->
65
+ @getButtons().push(button)
66
+
67
+ @getButtons: () ->
68
+ TextileEditor.buttons || new Array()
69
+
70
+ constructor: (canvas, view) ->
71
+
72
+ toolbar = document.createElement("div")
73
+ toolbar.id = "textile-toolbar-" + canvas
74
+ toolbar.className = "textile-toolbar"
75
+ @canvas = document.getElementById(canvas)
76
+ @canvas.parentNode.insertBefore toolbar, @canvas
77
+ @openTags = new Array()
78
+
79
+ # Create the local Button array by assigning theButtons array to edButtons
80
+ edButtons = new Array()
81
+ edButtons = TextileEditor.getButtons()
82
+ standardButtons = new Array()
83
+ i = 0
84
+
85
+ while i < edButtons.length
86
+ thisButton = @prepareButton(edButtons[i])
87
+ if view is "s"
88
+ if edButtons[i].sve is "s"
89
+ toolbar.appendChild thisButton
90
+ standardButtons.push thisButton
91
+ else
92
+ if typeof thisButton is "string"
93
+ toolbar.innerHTML += thisButton
94
+ else
95
+ toolbar.appendChild thisButton
96
+ standardButtons.push thisButton
97
+ i++
98
+ # end for
99
+ te = this
100
+ buttons = toolbar.getElementsByTagName("button")
101
+ i = 0
102
+
103
+ while i < buttons.length
104
+
105
+ #$A(toolbar.getElementsByTagName('button')).each(function(button) {
106
+ unless buttons[i].onclick
107
+ buttons[i].onclick = ->
108
+ te.insertTag this
109
+ false
110
+ # end if
111
+ buttons[i].tagStart = buttons[i].getAttribute("tagStart")
112
+ buttons[i].tagEnd = buttons[i].getAttribute("tagEnd")
113
+ buttons[i].open = buttons[i].getAttribute("open")
114
+ buttons[i].textile_editor = te
115
+ buttons[i].canvas = te.canvas
116
+ i++
117
+
118
+ # draw individual buttons (edShowButton)
119
+ prepareButton: (button) ->
120
+ if button.separator
121
+ theButton = document.createElement("span")
122
+ theButton.className = "ed_sep"
123
+ return theButton
124
+ if button.standard
125
+ theButton = document.createElement("button")
126
+ theButton.id = button.id
127
+ theButton.setAttribute "class", "standard"
128
+ theButton.setAttribute "tagStart", button.tagStart
129
+ theButton.setAttribute "tagEnd", button.tagEnd
130
+ theButton.setAttribute "open", button.open
131
+ img = document.createElement("img")
132
+ img.src = button.display
133
+ theButton.appendChild img
134
+ else
135
+ return button
136
+ # end if !custom
137
+ theButton.accessKey = button.access
138
+ theButton.title = button.title
139
+ theButton
140
+
141
+ # if clicked, no selected text, tag not open highlight button
142
+ # (edAddTag)
143
+ addTag: (button) ->
144
+ unless button.tagEnd is ""
145
+ @openTags[@openTags.length] = button
146
+
147
+ #var el = document.getElementById(button.id);
148
+ #el.className = 'selected';
149
+ button.className = "selected"
150
+
151
+ # if clicked, no selected text, tag open lowlight button
152
+ # (edRemoveTag)
153
+ removeTag: (button) ->
154
+ i = 0
155
+ while i < @openTags.length
156
+ if @openTags[i] is button
157
+ @openTags.splice button, 1
158
+
159
+ #var el = document.getElementById(button.id);
160
+ #el.className = 'unselected';
161
+ button.className = "unselected"
162
+ i++
163
+
164
+ # see if there are open tags. for the remove tag bit...
165
+ # (edCheckOpenTags)
166
+ checkOpenTags: (button) ->
167
+ tag = 0
168
+ i = 0
169
+ while i < @openTags.length
170
+ tag++ if @openTags[i] is button
171
+ i++
172
+ if tag > 0
173
+ true # tag found
174
+ else
175
+ false # tag not found
176
+
177
+ # insert the tag. this is the bulk of the code.
178
+ # (edInsertTag)
179
+ insertTag: (button, tagStart, tagEnd) ->
180
+
181
+ #console.log(button);
182
+ myField = button.canvas
183
+ myField.focus()
184
+ if tagStart
185
+ button.tagStart = tagStart
186
+ button.tagEnd = (if tagEnd then tagEnd else "\n")
187
+ textSelected = false
188
+ finalText = ""
189
+ FF = false
190
+
191
+ # grab the text that's going to be manipulated, by browser
192
+ if document.selection # IE support
193
+ sel = document.selection.createRange()
194
+
195
+ # set-up the text vars
196
+ beginningText = ""
197
+ followupText = ""
198
+ selectedText = sel.text
199
+
200
+ # check if text has been selected
201
+ textSelected = true if sel.text.length > 0
202
+
203
+ # set-up newline regex's so we can swap tags across multiple paragraphs
204
+ newlineReplaceRegexClean = /\r\n\s\n/g
205
+ newlineReplaceRegexDirty = "\\r\\n\\s\\n"
206
+ newlineReplaceClean = "\r\n\n"
207
+ else if myField.selectionStart or myField.selectionStart is "0" # MOZ/FF/NS/S support
208
+
209
+ # figure out cursor and selection positions
210
+ startPos = myField.selectionStart
211
+ endPos = myField.selectionEnd
212
+ cursorPos = endPos
213
+ scrollTop = myField.scrollTop
214
+ FF = true # note that is is a FF/MOZ/NS/S browser
215
+
216
+ # set-up the text vars
217
+ beginningText = myField.value.substring(0, startPos)
218
+ followupText = myField.value.substring(endPos, myField.value.length)
219
+
220
+ # check if text has been selected
221
+ unless startPos is endPos
222
+ textSelected = true
223
+ selectedText = myField.value.substring(startPos, endPos)
224
+
225
+ # set-up newline regex's so we can swap tags across multiple paragraphs
226
+ newlineReplaceRegexClean = /\n\n/g
227
+ newlineReplaceRegexDirty = "\\n\\n"
228
+ newlineReplaceClean = "\n\n"
229
+
230
+ # if there is text that has been highlighted...
231
+ if textSelected
232
+
233
+ # set-up some defaults for how to handle bad new line characters
234
+ newlineStart = ""
235
+ newlineStartPos = 0
236
+ newlineEnd = ""
237
+ newlineEndPos = 0
238
+ newlineFollowup = ""
239
+
240
+ # set-up some defaults for how to handle placing the beginning and end of selection
241
+ posDiffPos = 0
242
+ posDiffNeg = 0
243
+ mplier = 1
244
+
245
+ # remove newline from the beginning of the selectedText.
246
+ if selectedText.match(/^\n/)
247
+ selectedText = selectedText.replace(/^\n/, "")
248
+ newlineStart = "\n"
249
+ newlineStartpos = 1
250
+
251
+ # remove newline from the end of the selectedText.
252
+ if selectedText.match(/\n$/g)
253
+ selectedText = selectedText.replace(/\n$/g, "")
254
+ newlineEnd = "\n"
255
+ newlineEndPos = 1
256
+
257
+ # no clue, i'm sure it made sense at the time i wrote it
258
+ if followupText.match(/^\n/)
259
+ newlineFollowup = ""
260
+ else
261
+ newlineFollowup = "\n\n"
262
+
263
+ # first off let's check if the user is trying to mess with lists
264
+ if (button.tagStart is " * ") or (button.tagStart is " # ")
265
+ listItems = 0 # sets up a default to be able to properly manipulate final selection
266
+
267
+ # set-up all of the regex's
268
+ re_start = new RegExp("^ (\\*|\\#) ", "g")
269
+ if button.tagStart is " # "
270
+ re_tag = new RegExp(" \\# ", "g") # because of JS regex stupidity i need an if/else to properly set it up, could have done it with a regex replace though
271
+ else
272
+ re_tag = new RegExp(" \\* ", "g")
273
+ re_replace = new RegExp(" (\\*|\\#) ", "g")
274
+
275
+ # try to remove bullets in text copied from ms word **Mac Only!**
276
+ re_word_bullet_m_s = new RegExp("• ", "g") # mac/safari
277
+ re_word_bullet_m_f = new RegExp("∑ ", "g") # mac/firefox
278
+ selectedText = selectedText.replace(re_word_bullet_m_s, "").replace(re_word_bullet_m_f, "")
279
+
280
+ # if the selected text starts with one of the tags we're working with...
281
+ if selectedText.match(re_start)
282
+
283
+ # if tag that begins the selection matches the one clicked, remove them all
284
+ if selectedText.match(re_tag)
285
+ finalText = beginningText + newlineStart + selectedText.replace(re_replace, "") + newlineEnd + followupText
286
+ listItems = matches.length if matches = selectedText.match(RegExp(" (\\*|\\#) ", "g"))
287
+ posDiffNeg = listItems * 3 # how many list items were there because that's 3 spaces to remove from final selection
288
+
289
+ # else replace the current tag type with the selected tag type
290
+ else
291
+ finalText = beginningText + newlineStart + selectedText.replace(re_replace, button.tagStart) + newlineEnd + followupText
292
+
293
+ # else try to create the list type
294
+ # NOTE: the items in a list will only be replaced if a newline starts with some character, not a space
295
+ else
296
+ finalText = beginningText + newlineStart + button.tagStart + selectedText.replace(newlineReplaceRegexClean, newlineReplaceClean + button.tagStart).replace(/\n(\S)/g, "\n" + button.tagStart + "$1") + newlineEnd + followupText
297
+ listItems = matches.length if matches = selectedText.match(/\n(\S)/g)
298
+ posDiffPos = 3 + listItems * 3
299
+
300
+ # now lets look and see if the user is trying to muck with a block or block modifier
301
+ else if button.tagStart.match(/^(h1|h2|h3|h4|h5|h6|bq|p|\>|\<\>|\<|\=|\(|\))/g)
302
+ insertTag = ""
303
+ insertModifier = ""
304
+ tagPartBlock = ""
305
+ tagPartModifier = ""
306
+ tagPartModifierOrig = "" # ugly hack but it's late
307
+ drawSwitch = ""
308
+ captureIndentStart = false
309
+ captureListStart = false
310
+ periodAddition = "\\. "
311
+ periodAdditionClean = ". "
312
+ listItemsAddition = 0
313
+ re_list_items = new RegExp("(\\*+|\\#+)", "g") # need this regex later on when checking indentation of lists
314
+ re_block_modifier = new RegExp("^(h1|h2|h3|h4|h5|h6|bq|p| [\\*]{1,} | [\\#]{1,} |)(\\>|\\<\\>|\\<|\\=|[\\(]{1,}|[\\)]{1,6}|)", "g")
315
+ if tagPartMatches = re_block_modifier.exec(selectedText)
316
+ tagPartBlock = tagPartMatches[1]
317
+ tagPartModifier = tagPartMatches[2]
318
+ tagPartModifierOrig = tagPartMatches[2]
319
+ tagPartModifierOrig = tagPartModifierOrig.replace(/\(/g, "\\(")
320
+
321
+ # if tag already up is the same as the tag provided replace the whole tag
322
+ if tagPartBlock is button.tagStart
323
+ insertTag = tagPartBlock + tagPartModifierOrig # use Orig because it's escaped for regex
324
+ drawSwitch = 0
325
+
326
+ # else if let's check to add/remove block modifier
327
+ else if (tagPartModifier is button.tagStart) or (newm = tagPartModifier.match(/[\(]{2,}/g))
328
+ if (button.tagStart is "(") or (button.tagStart is ")")
329
+ indentLength = tagPartModifier.length
330
+ if button.tagStart is "("
331
+ indentLength = indentLength + 1
332
+ else
333
+ indentLength = indentLength - 1
334
+ i = 0
335
+
336
+ while i < indentLength
337
+ insertModifier = insertModifier + "("
338
+ i++
339
+ insertTag = tagPartBlock + insertModifier
340
+ else
341
+ if button.tagStart is tagPartModifier
342
+ insertTag = tagPartBlock
343
+ # going to rely on the default empty insertModifier
344
+ else
345
+ if button.tagStart.match(/(\>|\<\>|\<|\=)/g)
346
+ insertTag = tagPartBlock + button.tagStart
347
+ else
348
+ insertTag = button.tagStart + tagPartModifier
349
+ drawSwitch = 1
350
+
351
+ # indentation of list items
352
+ else if listPartMatches = re_list_items.exec(tagPartBlock)
353
+ listTypeMatch = listPartMatches[1]
354
+ indentLength = tagPartBlock.length - 2
355
+ listInsert = ""
356
+ if button.tagStart is "("
357
+ indentLength = indentLength + 1
358
+ else
359
+ indentLength = indentLength - 1
360
+ if listTypeMatch.match(/[\*]{1,}/g)
361
+ listType = "*"
362
+ listReplace = "\\*"
363
+ else
364
+ listType = "#"
365
+ listReplace = "\\#"
366
+ i = 0
367
+
368
+ while i < indentLength
369
+ listInsert = listInsert + listType
370
+ i++
371
+ unless listInsert is ""
372
+ insertTag = " " + listInsert + " "
373
+ else
374
+ insertTag = ""
375
+ tagPartBlock = tagPartBlock.replace(/(\*|\#)/g, listReplace)
376
+ drawSwitch = 1
377
+ captureListStart = true
378
+ periodAddition = ""
379
+ periodAdditionClean = ""
380
+ listItemsAddition = matches.length if matches = selectedText.match(/\n\s/g)
381
+
382
+ # must be a block modification e.g. p>. to p<.
383
+ else
384
+
385
+ # if this is a block modification/addition
386
+ if button.tagStart.match(/(h1|h2|h3|h4|h5|h6|bq|p)/g)
387
+ if tagPartBlock is ""
388
+ drawSwitch = 2
389
+ else
390
+ drawSwitch = 1
391
+ insertTag = button.tagStart + tagPartModifier
392
+
393
+ # else this is a modifier modification/addition
394
+ else
395
+ if (tagPartModifier is "") and (tagPartBlock isnt "")
396
+ drawSwitch = 1
397
+ else if tagPartModifier is ""
398
+ drawSwitch = 2
399
+ else
400
+ drawSwitch = 1
401
+
402
+ # if no tag part block but a modifier we need at least the p tag
403
+ tagPartBlock = "p" if tagPartBlock is ""
404
+
405
+ #make sure to swap out outdent
406
+ if button.tagStart is ")"
407
+ tagPartModifier = ""
408
+ else
409
+ tagPartModifier = button.tagStart
410
+ captureIndentStart = true # ugly hack to fix issue with proper selection handling
411
+ insertTag = tagPartBlock + tagPartModifier
412
+ mplier = 0
413
+ if captureListStart or (tagPartModifier.match(/[\(\)]{1,}/g))
414
+ re_start = new RegExp(insertTag.escape + periodAddition, "g") # for tags that mimic regex properties, parens + list tags
415
+ else
416
+ re_start = new RegExp(insertTag + periodAddition, "g") # for tags that don't, why i can't just escape everything i have no clue
417
+ re_old = new RegExp(tagPartBlock + tagPartModifierOrig + periodAddition, "g")
418
+ re_middle = new RegExp(newlineReplaceRegexDirty + insertTag.escape + periodAddition.escape, "g")
419
+ re_tag = new RegExp(insertTag.escape + periodAddition.escape, "g")
420
+
421
+ # *************************************************************************************************************************
422
+ # this is where everything gets swapped around or inserted, bullets and single options have their own if/else statements
423
+ # *************************************************************************************************************************
424
+ if (drawSwitch is 0) or (drawSwitch is 1)
425
+ if drawSwitch is 0 # completely removing a tag
426
+ finalText = beginningText + newlineStart + selectedText.replace(re_start, "").replace(re_middle, newlineReplaceClean) + newlineEnd + followupText
427
+ mplier = mplier + matches.length if matches = selectedText.match(newlineReplaceRegexClean)
428
+ posDiffNeg = insertTag.length + 2 + (mplier * 4)
429
+ else # modifying a tag, though we do delete bullets here
430
+ finalText = beginningText + newlineStart + selectedText.replace(re_old, insertTag + periodAdditionClean) + newlineEnd + followupText
431
+ mplier = mplier + matches.length if matches = selectedText.match(newlineReplaceRegexClean)
432
+
433
+ # figure out the length of various elements to modify the selection position
434
+ if captureIndentStart # need to double-check that this wasn't the first indent
435
+ tagPreviousLength = tagPartBlock.length
436
+ tagCurrentLength = insertTag.length
437
+ else if captureListStart # if this is a list we're manipulating
438
+ if button.tagStart is "(" # if indenting
439
+ tagPreviousLength = listTypeMatch.length + 2
440
+ tagCurrentLength = insertTag.length + listItemsAddition
441
+ else if insertTag.match(/(\*|\#)/g) # if removing but still has bullets
442
+ tagPreviousLength = insertTag.length + listItemsAddition
443
+ tagCurrentLength = listTypeMatch.length
444
+ else # if removing last bullet
445
+ tagPreviousLength = insertTag.length + listItemsAddition
446
+ tagCurrentLength = listTypeMatch.length - (3 * listItemsAddition) - 1
447
+ else # everything else
448
+ tagPreviousLength = tagPartBlock.length + tagPartModifier.length
449
+ tagCurrentLength = insertTag.length
450
+ if tagCurrentLength > tagPreviousLength
451
+ posDiffPos = (tagCurrentLength - tagPreviousLength) + (mplier * (tagCurrentLength - tagPreviousLength))
452
+ else
453
+ posDiffNeg = (tagPreviousLength - tagCurrentLength) + (mplier * (tagPreviousLength - tagCurrentLength))
454
+ else # for adding tags other then bullets (have their own statement)
455
+ finalText = beginningText + newlineStart + insertTag + ". " + selectedText.replace(newlineReplaceRegexClean, button.tagEnd + "\n" + insertTag + ". ") + newlineFollowup + newlineEnd + followupText
456
+ mplier = mplier + matches.length if matches = selectedText.match(newlineReplaceRegexClean)
457
+ posDiffPos = insertTag.length + 2 + (mplier * 4)
458
+
459
+ # swap in and out the simple tags around a selection like bold
460
+ else
461
+ mplier = 1 # the multiplier for the tag length
462
+ re_start = new RegExp("^\\" + button.tagStart, "g")
463
+ re_end = new RegExp("\\" + button.tagEnd + "$", "g")
464
+ re_middle = new RegExp("\\" + button.tagEnd + newlineReplaceRegexDirty + "\\" + button.tagStart, "g")
465
+ if selectedText.match(re_start) and selectedText.match(re_end)
466
+ finalText = beginningText + newlineStart + selectedText.replace(re_start, "").replace(re_end, "").replace(re_middle, newlineReplaceClean) + newlineEnd + followupText
467
+ mplier = mplier + matches.length if matches = selectedText.match(newlineReplaceRegexClean)
468
+ posDiffNeg = button.tagStart.length * mplier + button.tagEnd.length * mplier
469
+ else
470
+ finalText = beginningText + newlineStart + button.tagStart + selectedText.replace(newlineReplaceRegexClean, button.tagEnd + newlineReplaceClean + button.tagStart) + button.tagEnd + newlineEnd + followupText
471
+ mplier = mplier + matches.length if matches = selectedText.match(newlineReplaceRegexClean)
472
+ posDiffPos = (button.tagStart.length * mplier) + (button.tagEnd.length * mplier)
473
+ cursorPos += button.tagStart.length + button.tagEnd.length
474
+
475
+ # just swap in and out single values, e.g. someone clicks b they'll get a *
476
+ else
477
+ buttonStart = ""
478
+ buttonEnd = ""
479
+ re_p = new RegExp("(\\<|\\>|\\=|\\<\\>|\\(|\\))", "g")
480
+ re_h = new RegExp("^(h1|h2|h3|h4|h5|h6|p|bq)", "g")
481
+ if not @checkOpenTags(button) or button.tagEnd is "" # opening tag
482
+ if button.tagStart.match(re_h)
483
+ buttonStart = button.tagStart + ". "
484
+ else
485
+ buttonStart = button.tagStart
486
+ if button.tagStart.match(re_p) # make sure that invoking block modifiers don't do anything
487
+ finalText = beginningText + followupText
488
+ cursorPos = startPos
489
+ else
490
+ finalText = beginningText + buttonStart + followupText
491
+ @addTag button
492
+ cursorPos = startPos + buttonStart.length
493
+ else # closing tag
494
+ if button.tagStart.match(re_p)
495
+ buttonEnd = "\n\n"
496
+ else if button.tagStart.match(re_h)
497
+ buttonEnd = "\n\n"
498
+ else
499
+ buttonEnd = button.tagEnd
500
+ finalText = beginningText + button.tagEnd + followupText
501
+ @removeTag button
502
+ cursorPos = startPos + button.tagEnd.length
503
+
504
+ # set the appropriate DOM value with the final text
505
+ if FF is true
506
+ myField.value = finalText
507
+ myField.scrollTop = scrollTop
508
+ else
509
+ sel.text = finalText
510
+
511
+ # build up the selection capture, doesn't work in IE
512
+ if textSelected
513
+ myField.selectionStart = startPos + newlineStartPos
514
+ myField.selectionEnd = endPos + posDiffPos - posDiffNeg - newlineEndPos
515
+
516
+ #alert('s: ' + myField.selectionStart + ' e: ' + myField.selectionEnd + ' sp: ' + startPos + ' ep: ' + endPos + ' pdp: ' + posDiffPos + ' pdn: ' + posDiffNeg)
517
+ else
518
+ myField.selectionStart = cursorPos
519
+ myField.selectionEnd = cursorPos
520
+
521
+ window.TextileEditor = TextileEditor
@@ -0,0 +1,44 @@
1
+ div.textile-toolbar {
2
+ span.ed_sep {
3
+ xposition: relative;
4
+ xtop: -4px;
5
+ padding: 0;
6
+ height: 6px;
7
+ width: 2px;
8
+ margin: 0 2px;
9
+ border-left: solid 1px #d5d5d5;
10
+ border-right: solid 1px #f5f5f5;
11
+ }
12
+ button {
13
+ margin: 0;
14
+ background-color: #f0f0ee;
15
+ background-repeat: no-repeat;
16
+ border: 1px solid #f0f0ee;
17
+ padding: 2px 0;
18
+ &.standard {
19
+ text-align: center;
20
+ width: 24px;
21
+ }
22
+ img {
23
+ vertical-align: text-bottom;
24
+ }
25
+ &:hover, &.unselected:hover {
26
+ border: 1px solid #999;
27
+ }
28
+ &.selected {
29
+ border: 1px solid #ce9100;
30
+ background-color: #ffffff;
31
+ }
32
+ &.unselected {
33
+ border: 1px solid #f0f0ee;
34
+ background-color: #f0f0ee;
35
+ }
36
+ &.publish {
37
+ padding: 5px;
38
+ display: block;
39
+ }
40
+ }
41
+ background-color: #f0f0ee;
42
+ padding: 3px;
43
+ margin-bottom: 4px;
44
+ }
@@ -0,0 +1,11 @@
1
+
2
+ Description:
3
+ The textile_editor_config generator creates a config file for the textile editor.
4
+
5
+ Example:
6
+ rails generate textile_editor_config
7
+
8
+ This will create:
9
+ A Javascript config file located at app/assets/javascripts/textile-editor-config.js.coffee.erb
10
+
11
+ More info on textile_editor_config can be found here: https://github.com/emjot/redcloth-rails
@@ -0,0 +1,23 @@
1
+ TextileEditor.setButtons(
2
+ [
3
+ new TextileEditorButton("ed_strong", "<%= asset_path('textile-editor/bold.png') %>", "*", "*", "b", "Bold", "s"),
4
+ new TextileEditorButton("ed_emphasis", "<%= asset_path('textile-editor/italic.png') %>", "_", "_", "i", "Italicize", "s"),
5
+ new TextileEditorButton("ed_underline", "<%= asset_path('textile-editor/underline.png') %>", "+", "+", "u", "Underline", "s"),
6
+ new TextileEditorButton("ed_strike", "<%= asset_path('textile-editor/strikethrough.png') %>", "-", "-", "s", "Strikethrough", "s"),
7
+ new TextileEditorButton("ed_ol", "<%= asset_path('textile-editor/list_numbers.png') %>", " # ", "\n", ",", "Numbered List"),
8
+ new TextileEditorButton("ed_ul", "<%= asset_path('textile-editor/list_bullets.png') %>", " * ", "\n", ".", "Bulleted List"),
9
+ new TextileEditorButton("ed_p", "<%= asset_path('textile-editor/paragraph.png') %>", "p", "\n", "p", "Paragraph"),
10
+ new TextileEditorButton("ed_h1", "<%= asset_path('textile-editor/h1.png') %>", "h1", "\n", "1", "Header 1"),
11
+ new TextileEditorButton("ed_h2", "<%= asset_path('textile-editor/h2.png') %>", "h2", "\n", "2", "Header 2"),
12
+ new TextileEditorButton("ed_h3", "<%= asset_path('textile-editor/h3.png') %>", "h3", "\n", "3", "Header 3"),
13
+ new TextileEditorButton("ed_h4", "<%= asset_path('textile-editor/h4.png') %>", "h4", "\n", "4", "Header 4"),
14
+ new TextileEditorButton("ed_block", "<%= asset_path('textile-editor/blockquote.png') %>", "bq", "\n", "q", "Blockquote"),
15
+ new TextileEditorButton("ed_outdent", "<%= asset_path('textile-editor/outdent.png') %>", ")", "\n", "]", "Outdent"),
16
+ new TextileEditorButton("ed_indent", "<%= asset_path('textile-editor/indent.png') %>", "(", "\n", "[", "Indent"),
17
+ new TextileEditorButton("ed_justifyl", "<%= asset_path('textile-editor/left.png') %>", "<", "\n", "l", "Left Justify"),
18
+ new TextileEditorButton("ed_justifyc", "<%= asset_path('textile-editor/center.png') %>", "=", "\n", "e", "Center Text"),
19
+ new TextileEditorButton("ed_justifyr", "<%= asset_path('textile-editor/right.png') %>", ">", "\n", "r", "Right Justify"),
20
+ new TextileEditorButton("ed_justify", "<%= asset_path('textile-editor/justify.png') %>", "<>", "\n", "j", "Justify"),
21
+ new TextileEditorButton("ed_code", "code", "@", "@", "c", "Code")
22
+ ]
23
+ )
@@ -0,0 +1,9 @@
1
+ class TextileEditorConfigGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ def copy_javascript
5
+ copy_file 'textile-editor-config.js.coffee.erb', 'app/assets/javascripts/textile-editor-config.js.coffee.erb'
6
+ end
7
+
8
+ end
9
+
@@ -0,0 +1,18 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers.rb')
2
+
3
+ module RedCloth
4
+ module Rails
5
+
6
+ class Engine < ::Rails::Engine
7
+ initializer "redcloth-rails.action_controller" do |app|
8
+ ActiveSupport.on_load :action_view do
9
+ ActionView::Helpers::FormBuilder.send :include, RedCloth::Rails::Helpers::FormBuilder
10
+
11
+ ActionView::Base.send :include, RedCloth::Rails::Helpers::FormHelper
12
+ ActionView::Base.send :include, RedCloth::Rails::Helpers::FormTagHelper
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module RedCloth
2
+ module Rails
3
+ module Helpers
4
+
5
+ module FormBuilder
6
+ # @see RedCloth::Rails::Helpers::FormHelper#textile_editor
7
+ def textile_editor(method, options = {})
8
+ @template.textile_editor(@object_name, method, options.merge(:object => @object))
9
+ end
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,137 @@
1
+ module RedCloth
2
+ module Rails
3
+ module Helpers
4
+
5
+ module FormHelper
6
+ # Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+)
7
+ # on an object assigned to the template (identified by +object+). Additional options on the input tag can be passed as a
8
+ # hash with +options+ and places the textile toolbar above it
9
+ #
10
+ # @param [Symbol] object_name name of the model
11
+ # @param [Symbol] method_name name of the models attribute
12
+ # @param [Hash] options HTML options to customize the textarea element
13
+ #
14
+ # Samples:
15
+ # textile_editor(:post, :body, :cols => 20, :rows => 40)
16
+ # # => <textarea cols="20" rows="40" id="post_body" name="post[body]">
17
+ # # #{@post.body}
18
+ # # </textarea>
19
+ #
20
+ # textile_editor(:comment, :text, :size => "20x30")
21
+ # # => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
22
+ # # #{@comment.text}
23
+ # # </textarea>
24
+ #
25
+ # textile_editor(:application, :notes, :cols => 40, :rows => 15, :class => 'app_input')
26
+ # # => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
27
+ # # #{@application.notes}
28
+ # # </textarea>
29
+ #
30
+ # textile_editor(:entry, :body, :size => "20x20", :disabled => 'disabled')
31
+ # # => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
32
+ # # #{@entry.body}
33
+ # # </textarea>
34
+ #
35
+ def textile_editor(object_name, method, options = {})
36
+ editor_id = options[:id] || '%s_%s' % [object_name, method]
37
+ mode = options.delete(:simple) ? 'simple' : 'extended'
38
+ (@textile_editor_ids ||= []) << [editor_id.to_s, mode.to_s]
39
+
40
+ ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_text_area_tag(options)
41
+ end
42
+
43
+ # Registers a further button on the TextileEditor toolbar.
44
+ # Must be called before the TextileEditor gets initialized.
45
+ #
46
+ # @param [String] text text to display (contents of button tag, so HTML is valid as well)
47
+ # @param [Hash] options options Hash as supported by +content_tag+ helper in Rails
48
+ #
49
+ # Example:
50
+ # Add a button labeled 'Greeting' which triggers an alert dialog.
51
+ #
52
+ # <% textile_editor_button 'Greeting', :onclick => "alert('Hello!')" %>
53
+ #
54
+ def textile_editor_button(text, options={})
55
+ return textile_editor_button_separator if text == :separator
56
+ button = content_tag(:button, text, options)
57
+ button = "TextileEditor.addButton(\"%s\");" % escape_javascript(button)
58
+ (@textile_editor_buttons ||= []) << button
59
+ return nil
60
+ end
61
+
62
+ # Registers a separator on the TextileEditor toolbar.
63
+ # Must be called before the TextileEditor gets initialized.
64
+ #
65
+ # @param [Hash] options
66
+ #
67
+ def textile_editor_button_separator(options={})
68
+ button = "TextileEditor.addButton(new TextileEditorButtonSeparator('%s'));" % (options[:simple] || '')
69
+ (@textile_editor_buttons ||= []) << button
70
+ return nil
71
+ end
72
+
73
+ # Initialize the TextileEditor. after the DOM was loaded.
74
+ #
75
+ # @param [Array] dom_ids
76
+ # @param [Hash] options
77
+ #
78
+ # Sample with jQuery DOM ready event:
79
+ # <script type="text/javascript">
80
+ # jQuery(document).ready(function() {
81
+ # TextileEditor.initialize('article_body', 'extended');
82
+ # TextileEditor.initialize('article_body_excerpt', 'simple');
83
+ # });
84
+ # </script>
85
+ #
86
+ # Sample for AJAX requests, the TextileEditor gets initialized without waiting for DOM.
87
+ # <script type="text/javascript">
88
+ # TextileEditor.initialize('article_body', 'extended');
89
+ # TextileEditor.initialize('article_body_excerpt', 'simple');
90
+ # </script>
91
+ #
92
+ def textile_editor_initialize(*dom_ids)
93
+ options = {}
94
+
95
+ # extract options from last argument if it's a hash
96
+ if dom_ids.last.is_a?(Hash)
97
+ hash = dom_ids.last.dup
98
+ options.merge! hash
99
+ end
100
+
101
+ editor_ids = (@textile_editor_ids || []) + textile_extract_dom_ids(*dom_ids)
102
+ editor_buttons = (@textile_editor_buttons || [])
103
+ output = []
104
+
105
+ output << '<script type="text/javascript">'
106
+ output << '/* <![CDATA[ */'
107
+
108
+ unless request.xhr?
109
+ output << %{jQuery(document).ready(function($) \{}
110
+ end
111
+
112
+ output << editor_buttons.join("\n") if editor_buttons.any?
113
+
114
+ editor_ids.each do |editor_id, mode|
115
+ output << %q{new TextileEditor('%s', '%s');} % [editor_id, mode || 'extended']
116
+ end
117
+
118
+ unless request.xhr?
119
+ output << '});'
120
+ end
121
+
122
+ output << '/* ]]> */'
123
+ output << '</script>'
124
+ output.join("\n").html_safe
125
+ end
126
+
127
+ def textile_extract_dom_ids(*dom_ids)
128
+ hash = dom_ids.last.is_a?(Hash) ? dom_ids.pop : {}
129
+ hash.inject(dom_ids) do |ids, (object, fields)|
130
+ ids + Array(fields).map { |field| "%s_%s" % [object, field] }
131
+ end
132
+ end
133
+ end
134
+
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,49 @@
1
+ module RedCloth
2
+ module Rails
3
+ module Helpers
4
+
5
+ module FormTagHelper
6
+ # Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions
7
+ # and includes the textile toolbar above it.
8
+ #
9
+ # @param [String] name
10
+ # @param [String] content
11
+ # @param [Hash] options
12
+ # @option options [String] :size String to specify the column and row dimensions (e.g., "25x10").
13
+ # @option options [Integer] :rows Specify the number of rows in the textarea
14
+ # @option options [Integer] :cols Specify the number of columns in the textarea
15
+ # @option options [Boolean] :disabled If set to true, the user will not be able to use this input.
16
+ #
17
+ # Any other option (key/value pair) will be used to create HTML attributes for the tag.
18
+ #
19
+ # Samples:
20
+ # textile_editor_tag 'post'
21
+ # # => <textarea id="post" name="post"></textarea>
22
+ #
23
+ # textile_editor_tag 'bio', @user.bio
24
+ # # => <textarea id="bio" name="bio">This is my biography.</textarea>
25
+ #
26
+ # textile_editor_tag 'body', nil, :rows => 10, :cols => 25
27
+ # # => <textarea cols="25" id="body" name="body" rows="10"></textarea>
28
+ #
29
+ # textile_editor_tag 'body', nil, :size => "25x10"
30
+ # # => <textarea name="body" id="body" cols="25" rows="10"></textarea>
31
+ #
32
+ # textile_editor_tag 'description', "Description goes here.", :disabled => true
33
+ # # => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
34
+ #
35
+ # textile_editor_tag 'comment', nil, :class => 'comment_input'
36
+ # # => <textarea class="comment_input" id="comment" name="comment"></textarea>
37
+ #
38
+ def textile_editor_tag(name, content = nil, options = {})
39
+ editor_id = options[:id] || name
40
+ mode = options.delete(:simple) ? 'simple' : 'extended'
41
+ (@textile_editor_ids ||= []) << [editor_id.to_s, mode.to_s]
42
+
43
+ text_area_tag(name, content, options)
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), 'helpers/form_builder.rb')
2
+ require File.join(File.dirname(__FILE__), 'helpers/form_helper.rb')
3
+ require File.join(File.dirname(__FILE__), 'helpers/form_tag_helper.rb')
4
+
5
+ module RedCloth
6
+ module Rails
7
+ module Helpers; end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module RedCloth
2
+ module Rails
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ unless defined?(RedCloth::Rails::Version)
2
+ require File.join(File.dirname(__FILE__), 'redcloth-rails/version.rb')
3
+ end
4
+
5
+ module RedCloth
6
+ module Rails
7
+
8
+ if defined?(::Rails) && ::Rails.version.to_f >= 3.1
9
+ require File.join(File.dirname(__FILE__), 'redcloth-rails/engine.rb')
10
+ else
11
+ raise 'Rails >= 3.1 is required'
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require File.join(File.dirname(__FILE__), "lib/redcloth-rails/version.rb")
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "redcloth-rails"
7
+ s.version = RedCloth::Rails::VERSION
8
+ s.authors = ["emjot"]
9
+ s.email = ["kontakt@emjot.de"]
10
+ s.homepage = "https://github.com/emjot/redcloth-rails"
11
+ s.summary = %q{rails 3 engine which enables RedCloth and provides helpers for the awesome TextileEditor.}
12
+
13
+ s.add_dependency('RedCloth', '>= 4.2.0')
14
+ s.add_dependency('rails', '>= 3.1.0')
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redcloth-rails
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - emjot
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-03-04 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: RedCloth
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 55
30
+ segments:
31
+ - 4
32
+ - 2
33
+ - 0
34
+ version: 4.2.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rails
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 3
48
+ - 1
49
+ - 0
50
+ version: 3.1.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description:
54
+ email:
55
+ - kontakt@emjot.de
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - Gemfile
64
+ - LICENSE
65
+ - README.textile
66
+ - Rakefile
67
+ - app/assets/images/textile-editor/background.png
68
+ - app/assets/images/textile-editor/blockquote.png
69
+ - app/assets/images/textile-editor/bold.png
70
+ - app/assets/images/textile-editor/center.png
71
+ - app/assets/images/textile-editor/h1.png
72
+ - app/assets/images/textile-editor/h2.png
73
+ - app/assets/images/textile-editor/h3.png
74
+ - app/assets/images/textile-editor/h4.png
75
+ - app/assets/images/textile-editor/h5.png
76
+ - app/assets/images/textile-editor/h6.png
77
+ - app/assets/images/textile-editor/indent.png
78
+ - app/assets/images/textile-editor/italic.png
79
+ - app/assets/images/textile-editor/justify.png
80
+ - app/assets/images/textile-editor/left.png
81
+ - app/assets/images/textile-editor/list_bullets.png
82
+ - app/assets/images/textile-editor/list_numbers.png
83
+ - app/assets/images/textile-editor/omega.png
84
+ - app/assets/images/textile-editor/outdent.png
85
+ - app/assets/images/textile-editor/paragraph.png
86
+ - app/assets/images/textile-editor/right.png
87
+ - app/assets/images/textile-editor/strikethrough.png
88
+ - app/assets/images/textile-editor/underline.png
89
+ - app/assets/javascripts/textile-editor-config.js.coffee.erb
90
+ - app/assets/javascripts/textile-editor.js.coffee
91
+ - app/assets/stylesheets/textile-editor.css.scss
92
+ - lib/rails/generators/textile_editor_config/USAGE
93
+ - lib/rails/generators/textile_editor_config/templates/textile-editor-config.js.coffee.erb
94
+ - lib/rails/generators/textile_editor_config/textile_editor_config_generator.rb
95
+ - lib/redcloth-rails.rb
96
+ - lib/redcloth-rails/engine.rb
97
+ - lib/redcloth-rails/helpers.rb
98
+ - lib/redcloth-rails/helpers/form_builder.rb
99
+ - lib/redcloth-rails/helpers/form_helper.rb
100
+ - lib/redcloth-rails/helpers/form_tag_helper.rb
101
+ - lib/redcloth-rails/version.rb
102
+ - redcloth-rails.gemspec
103
+ has_rdoc: true
104
+ homepage: https://github.com/emjot/redcloth-rails
105
+ licenses: []
106
+
107
+ post_install_message:
108
+ rdoc_options: []
109
+
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 3
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ requirements: []
131
+
132
+ rubyforge_project:
133
+ rubygems_version: 1.3.7
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: rails 3 engine which enables RedCloth and provides helpers for the awesome TextileEditor.
137
+ test_files: []
138
+