instiki 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +174 -165
- data/README +68 -68
- data/app/controllers/admin_controller.rb +94 -94
- data/app/controllers/application.rb +135 -131
- data/app/controllers/file_controller.rb +129 -129
- data/app/controllers/wiki_controller.rb +354 -354
- data/app/helpers/application_helper.rb +68 -68
- data/app/models/author.rb +3 -3
- data/app/models/chunks/category.rb +33 -33
- data/app/models/chunks/chunk.rb +86 -86
- data/app/models/chunks/engines.rb +61 -54
- data/app/models/chunks/include.rb +41 -41
- data/app/models/chunks/literal.rb +31 -31
- data/app/models/chunks/nowiki.rb +28 -28
- data/app/models/chunks/test.rb +18 -18
- data/app/models/chunks/uri.rb +182 -182
- data/app/models/chunks/wiki.rb +141 -141
- data/app/models/file_yard.rb +58 -58
- data/app/models/page.rb +112 -112
- data/app/models/page_lock.rb +22 -22
- data/app/models/page_set.rb +89 -89
- data/app/models/revision.rb +123 -123
- data/app/models/web.rb +182 -176
- data/app/models/wiki_content.rb +207 -207
- data/app/models/wiki_service.rb +233 -233
- data/app/models/wiki_words.rb +23 -23
- data/app/views/admin/create_system.rhtml +83 -83
- data/app/views/admin/create_web.rhtml +69 -69
- data/app/views/admin/edit_web.rhtml +137 -136
- data/app/views/file/file.rhtml +18 -18
- data/app/views/file/import.rhtml +22 -22
- data/app/views/layouts/default.rhtml +86 -85
- data/app/views/markdown_help.rhtml +12 -12
- data/app/views/mixed_help.rhtml +6 -6
- data/app/views/navigation.rhtml +30 -30
- data/app/views/rdoc_help.rhtml +12 -12
- data/app/views/textile_help.rhtml +24 -24
- data/app/views/wiki/authors.rhtml +11 -11
- data/app/views/wiki/edit.rhtml +39 -39
- data/app/views/wiki/export.rhtml +12 -12
- data/app/views/wiki/feeds.rhtml +14 -14
- data/app/views/wiki/list.rhtml +64 -64
- data/app/views/wiki/locked.rhtml +23 -23
- data/app/views/wiki/login.rhtml +14 -14
- data/app/views/wiki/new.rhtml +31 -31
- data/app/views/wiki/page.rhtml +115 -115
- data/app/views/wiki/print.rhtml +14 -14
- data/app/views/wiki/published.rhtml +9 -9
- data/app/views/wiki/recently_revised.rhtml +26 -26
- data/app/views/wiki/revision.rhtml +103 -103
- data/app/views/wiki/rollback.rhtml +36 -36
- data/app/views/wiki/rss_feed.rhtml +22 -22
- data/app/views/wiki/search.rhtml +38 -38
- data/app/views/wiki/tex.rhtml +22 -22
- data/app/views/wiki/tex_web.rhtml +34 -34
- data/app/views/wiki/web_list.rhtml +18 -18
- data/app/views/wiki_words_help.rhtml +9 -9
- data/config/environment.rb +82 -82
- data/config/environments/development.rb +5 -5
- data/config/environments/production.rb +4 -4
- data/config/environments/test.rb +17 -17
- data/config/routes.rb +18 -18
- data/lib/active_record_stub.rb +31 -31
- data/lib/bluecloth_tweaked.rb +1127 -0
- data/lib/diff.rb +444 -444
- data/lib/instiki_errors.rb +14 -14
- data/lib/rdocsupport.rb +151 -151
- data/lib/redcloth_for_tex.rb +736 -736
- data/natives/osx/desktop_launcher/AppDelegate.h +18 -18
- data/natives/osx/desktop_launcher/AppDelegate.mm +109 -109
- data/natives/osx/desktop_launcher/Credits.html +15 -15
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +12 -12
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -24
- data/natives/osx/desktop_launcher/Info.plist +12 -12
- data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -592
- data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -7
- data/natives/osx/desktop_launcher/MakeDMG.sh +9 -9
- data/natives/osx/desktop_launcher/main.mm +14 -14
- data/natives/osx/desktop_launcher/version.plist +16 -16
- data/public/404.html +5 -5
- data/public/500.html +5 -5
- data/public/dispatch.rb +9 -9
- data/public/javascripts/edit_web.js +52 -52
- data/public/javascripts/prototype.js +336 -336
- data/public/stylesheets/instiki.css +222 -222
- data/script/breakpointer +4 -4
- data/script/server +93 -93
- metadata +4 -3
@@ -1,68 +1,68 @@
|
|
1
|
-
# The methods added to this helper will be available to all templates in the application.
|
2
|
-
module ApplicationHelper
|
3
|
-
|
4
|
-
# Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
|
5
|
-
# where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
|
6
|
-
# the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
|
7
|
-
# become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag.
|
8
|
-
#
|
9
|
-
# Examples (call, result):
|
10
|
-
# html_options([["Dollar", "$"], ["Kroner", "DKK"]])
|
11
|
-
# <option value="$">Dollar</option>\n<option value="DKK">Kroner</option>
|
12
|
-
#
|
13
|
-
# html_options([ "VISA", "Mastercard" ], "Mastercard")
|
14
|
-
# <option>VISA</option>\n<option selected>Mastercard</option>
|
15
|
-
#
|
16
|
-
# html_options({ "Basic" => "$20", "Plus" => "$40" }, "$40")
|
17
|
-
# <option value="$20">Basic</option>\n<option value="$40" selected>Plus</option>
|
18
|
-
def html_options(container, selected = nil)
|
19
|
-
container = container.to_a if Hash === container
|
20
|
-
|
21
|
-
html_options = container.inject([]) do |options, element|
|
22
|
-
if element.respond_to?(:first) && element.respond_to?(:last)
|
23
|
-
if element.last != selected
|
24
|
-
options << "<option value=\"#{element.last}\">#{element.first}</option>"
|
25
|
-
else
|
26
|
-
options << "<option value=\"#{element.last}\" selected>#{element.first}</option>"
|
27
|
-
end
|
28
|
-
else
|
29
|
-
options << ((element != selected) ? "<option>#{element}</option>" : "<option selected>#{element}</option>")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
html_options.join("\n")
|
34
|
-
end
|
35
|
-
|
36
|
-
# Creates a hyperlink to a Wiki page, without checking if the page exists or not
|
37
|
-
def link_to_existing_page(page, text = nil, html_options = {})
|
38
|
-
link_to(
|
39
|
-
text || page.name,
|
40
|
-
{:web => @web.address, :action => 'show', :id => page.name, :only_path => true},
|
41
|
-
html_options)
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
# Creates a hyperlink to a Wiki page, or to a "new page" form if the page doesn't exist yet
|
46
|
-
def link_to_page(page_name, web = @web, text = nil, options = {})
|
47
|
-
raise 'Web not defined' if web.nil?
|
48
|
-
home_page_url = url_for :web => web.address, :action => 'show', :id => 'HomePage', :only_path => true
|
49
|
-
base_url = home_page_url.sub(%r-/show/HomePage/?$-, '')
|
50
|
-
web.make_link(page_name, text, options.merge(:base_url => base_url))
|
51
|
-
end
|
52
|
-
|
53
|
-
# Creates a menu of categories
|
54
|
-
def categories_menu
|
55
|
-
if @categories.empty?
|
56
|
-
''
|
57
|
-
else
|
58
|
-
"<div id=\"categories\">\n" +
|
59
|
-
'<strong>Categories</strong>:' +
|
60
|
-
'[' + link_to_unless_current('Any', :web => @web.address, :action => @action_name) + "]\n" +
|
61
|
-
@categories.map { |c|
|
62
|
-
link_to_unless_current(c, :web => @web.address, :action => @action_name, :category => c)
|
63
|
-
}.join(', ') + "\n" +
|
64
|
-
'</div>'
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
1
|
+
# The methods added to this helper will be available to all templates in the application.
|
2
|
+
module ApplicationHelper
|
3
|
+
|
4
|
+
# Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
|
5
|
+
# where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
|
6
|
+
# the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
|
7
|
+
# become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag.
|
8
|
+
#
|
9
|
+
# Examples (call, result):
|
10
|
+
# html_options([["Dollar", "$"], ["Kroner", "DKK"]])
|
11
|
+
# <option value="$">Dollar</option>\n<option value="DKK">Kroner</option>
|
12
|
+
#
|
13
|
+
# html_options([ "VISA", "Mastercard" ], "Mastercard")
|
14
|
+
# <option>VISA</option>\n<option selected>Mastercard</option>
|
15
|
+
#
|
16
|
+
# html_options({ "Basic" => "$20", "Plus" => "$40" }, "$40")
|
17
|
+
# <option value="$20">Basic</option>\n<option value="$40" selected>Plus</option>
|
18
|
+
def html_options(container, selected = nil)
|
19
|
+
container = container.to_a if Hash === container
|
20
|
+
|
21
|
+
html_options = container.inject([]) do |options, element|
|
22
|
+
if element.respond_to?(:first) && element.respond_to?(:last)
|
23
|
+
if element.last != selected
|
24
|
+
options << "<option value=\"#{element.last}\">#{element.first}</option>"
|
25
|
+
else
|
26
|
+
options << "<option value=\"#{element.last}\" selected>#{element.first}</option>"
|
27
|
+
end
|
28
|
+
else
|
29
|
+
options << ((element != selected) ? "<option>#{element}</option>" : "<option selected>#{element}</option>")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
html_options.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Creates a hyperlink to a Wiki page, without checking if the page exists or not
|
37
|
+
def link_to_existing_page(page, text = nil, html_options = {})
|
38
|
+
link_to(
|
39
|
+
text || page.name,
|
40
|
+
{:web => @web.address, :action => 'show', :id => page.name, :only_path => true},
|
41
|
+
html_options)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Creates a hyperlink to a Wiki page, or to a "new page" form if the page doesn't exist yet
|
46
|
+
def link_to_page(page_name, web = @web, text = nil, options = {})
|
47
|
+
raise 'Web not defined' if web.nil?
|
48
|
+
home_page_url = url_for :web => web.address, :action => 'show', :id => 'HomePage', :only_path => true
|
49
|
+
base_url = home_page_url.sub(%r-/show/HomePage/?$-, '')
|
50
|
+
web.make_link(page_name, text, options.merge(:base_url => base_url))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Creates a menu of categories
|
54
|
+
def categories_menu
|
55
|
+
if @categories.empty?
|
56
|
+
''
|
57
|
+
else
|
58
|
+
"<div id=\"categories\">\n" +
|
59
|
+
'<strong>Categories</strong>:' +
|
60
|
+
'[' + link_to_unless_current('Any', :web => @web.address, :action => @action_name) + "]\n" +
|
61
|
+
@categories.map { |c|
|
62
|
+
link_to_unless_current(c, :web => @web.address, :action => @action_name, :category => c)
|
63
|
+
}.join(', ') + "\n" +
|
64
|
+
'</div>'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/app/models/author.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
class Author < String
|
2
|
-
attr_accessor :ip
|
3
|
-
def initialize(name, ip) @ip = ip; super(name) end
|
1
|
+
class Author < String
|
2
|
+
attr_accessor :ip
|
3
|
+
def initialize(name, ip) @ip = ip; super(name) end
|
4
4
|
end
|
@@ -1,33 +1,33 @@
|
|
1
|
-
require 'chunks/chunk'
|
2
|
-
|
3
|
-
# The category chunk looks for "category: news" on a line by
|
4
|
-
# itself and parses the terms after the ':' as categories.
|
5
|
-
# Other classes can search for Category chunks within
|
6
|
-
# rendered content to find out what categories this page
|
7
|
-
# should be in.
|
8
|
-
#
|
9
|
-
# Category lines can be hidden using ':category: news', for example
|
10
|
-
class Category < Chunk::Abstract
|
11
|
-
CATEGORY_PATTERN = /^(:)?category\s*:(.*)$/i
|
12
|
-
def self.pattern() CATEGORY_PATTERN end
|
13
|
-
|
14
|
-
attr_reader :hidden, :list
|
15
|
-
|
16
|
-
def initialize(match_data, content)
|
17
|
-
super(match_data, content)
|
18
|
-
@hidden = match_data[1]
|
19
|
-
@list = match_data[2].split(',').map { |c| c.strip }
|
20
|
-
@unmask_text = ''
|
21
|
-
if @hidden
|
22
|
-
@unmask_text = ''
|
23
|
-
else
|
24
|
-
category_urls = @list.map { |category| url(category) }.join(', ')
|
25
|
-
@unmask_text = '<div class="property"> category: ' + category_urls + '</div>'
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# TODO move presentation of page metadata to controller/view
|
30
|
-
def url(category)
|
31
|
-
%{<a class="category_link" href="../list/?category=#{category}">#{category}</a>}
|
32
|
-
end
|
33
|
-
end
|
1
|
+
require 'chunks/chunk'
|
2
|
+
|
3
|
+
# The category chunk looks for "category: news" on a line by
|
4
|
+
# itself and parses the terms after the ':' as categories.
|
5
|
+
# Other classes can search for Category chunks within
|
6
|
+
# rendered content to find out what categories this page
|
7
|
+
# should be in.
|
8
|
+
#
|
9
|
+
# Category lines can be hidden using ':category: news', for example
|
10
|
+
class Category < Chunk::Abstract
|
11
|
+
CATEGORY_PATTERN = /^(:)?category\s*:(.*)$/i
|
12
|
+
def self.pattern() CATEGORY_PATTERN end
|
13
|
+
|
14
|
+
attr_reader :hidden, :list
|
15
|
+
|
16
|
+
def initialize(match_data, content)
|
17
|
+
super(match_data, content)
|
18
|
+
@hidden = match_data[1]
|
19
|
+
@list = match_data[2].split(',').map { |c| c.strip }
|
20
|
+
@unmask_text = ''
|
21
|
+
if @hidden
|
22
|
+
@unmask_text = ''
|
23
|
+
else
|
24
|
+
category_urls = @list.map { |category| url(category) }.join(', ')
|
25
|
+
@unmask_text = '<div class="property"> category: ' + category_urls + '</div>'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# TODO move presentation of page metadata to controller/view
|
30
|
+
def url(category)
|
31
|
+
%{<a class="category_link" href="../list/?category=#{category}">#{category}</a>}
|
32
|
+
end
|
33
|
+
end
|
data/app/models/chunks/chunk.rb
CHANGED
@@ -1,86 +1,86 @@
|
|
1
|
-
require 'uri/common'
|
2
|
-
|
3
|
-
# A chunk is a pattern of text that can be protected
|
4
|
-
# and interrogated by a renderer. Each Chunk class has a
|
5
|
-
# +pattern+ that states what sort of text it matches.
|
6
|
-
# Chunks are initalized by passing in the result of a
|
7
|
-
# match by its pattern.
|
8
|
-
|
9
|
-
module Chunk
|
10
|
-
class Abstract
|
11
|
-
|
12
|
-
# automatically construct the array of derivatives of Chunk::Abstract
|
13
|
-
@derivatives = []
|
14
|
-
|
15
|
-
class << self
|
16
|
-
attr_reader :derivatives
|
17
|
-
end
|
18
|
-
|
19
|
-
def self::inherited( klass )
|
20
|
-
Abstract::derivatives << klass
|
21
|
-
end
|
22
|
-
|
23
|
-
# the class name part of the mask strings
|
24
|
-
def self.mask_string
|
25
|
-
self.to_s.delete(':').downcase
|
26
|
-
end
|
27
|
-
|
28
|
-
# a regexp that matches all chunk_types masks
|
29
|
-
def Abstract::mask_re(chunk_types)
|
30
|
-
tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
|
31
|
-
Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
|
32
|
-
end
|
33
|
-
|
34
|
-
attr_reader :text, :unmask_text, :unmask_mode
|
35
|
-
|
36
|
-
def initialize(match_data, content)
|
37
|
-
@text = match_data[0]
|
38
|
-
@content = content
|
39
|
-
@unmask_mode = :normal
|
40
|
-
end
|
41
|
-
|
42
|
-
# Find all the chunks of the given type in content
|
43
|
-
# Each time the pattern is matched, create a new
|
44
|
-
# chunk for it, and replace the occurance of the chunk
|
45
|
-
# in this content with its mask.
|
46
|
-
def self.apply_to(content)
|
47
|
-
content.gsub!( self.pattern ) do |match|
|
48
|
-
new_chunk = self.new($~, content)
|
49
|
-
content.add_chunk(new_chunk)
|
50
|
-
new_chunk.mask
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# should contain only [a-z0-9]
|
55
|
-
def mask
|
56
|
-
@mask ||="chunk#{@id}#{self.class.mask_string}chunk"
|
57
|
-
end
|
58
|
-
|
59
|
-
# We should not use object_id because object_id is not guarantied
|
60
|
-
# to be unique when we restart the wiki (new object ids can equal old ones
|
61
|
-
# that were restored form madeleine storage)
|
62
|
-
def id
|
63
|
-
@id ||= "#{@content.page_id}n#{@content.chunk_id}"
|
64
|
-
end
|
65
|
-
|
66
|
-
def unmask
|
67
|
-
@content.sub!(mask, @unmask_text)
|
68
|
-
end
|
69
|
-
|
70
|
-
def rendered?
|
71
|
-
@unmask_mode == :normal
|
72
|
-
end
|
73
|
-
|
74
|
-
def escaped?
|
75
|
-
@unmask_mode == :escape
|
76
|
-
end
|
77
|
-
|
78
|
-
def revert
|
79
|
-
@content.sub!(mask, @text)
|
80
|
-
# unregister
|
81
|
-
@content.delete_chunk(self)
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
1
|
+
require 'uri/common'
|
2
|
+
|
3
|
+
# A chunk is a pattern of text that can be protected
|
4
|
+
# and interrogated by a renderer. Each Chunk class has a
|
5
|
+
# +pattern+ that states what sort of text it matches.
|
6
|
+
# Chunks are initalized by passing in the result of a
|
7
|
+
# match by its pattern.
|
8
|
+
|
9
|
+
module Chunk
|
10
|
+
class Abstract
|
11
|
+
|
12
|
+
# automatically construct the array of derivatives of Chunk::Abstract
|
13
|
+
@derivatives = []
|
14
|
+
|
15
|
+
class << self
|
16
|
+
attr_reader :derivatives
|
17
|
+
end
|
18
|
+
|
19
|
+
def self::inherited( klass )
|
20
|
+
Abstract::derivatives << klass
|
21
|
+
end
|
22
|
+
|
23
|
+
# the class name part of the mask strings
|
24
|
+
def self.mask_string
|
25
|
+
self.to_s.delete(':').downcase
|
26
|
+
end
|
27
|
+
|
28
|
+
# a regexp that matches all chunk_types masks
|
29
|
+
def Abstract::mask_re(chunk_types)
|
30
|
+
tmp = chunk_types.map{|klass| klass.mask_string}.join("|")
|
31
|
+
Regexp.new("chunk([0-9a-f]+n\\d+)(#{tmp})chunk")
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :text, :unmask_text, :unmask_mode
|
35
|
+
|
36
|
+
def initialize(match_data, content)
|
37
|
+
@text = match_data[0]
|
38
|
+
@content = content
|
39
|
+
@unmask_mode = :normal
|
40
|
+
end
|
41
|
+
|
42
|
+
# Find all the chunks of the given type in content
|
43
|
+
# Each time the pattern is matched, create a new
|
44
|
+
# chunk for it, and replace the occurance of the chunk
|
45
|
+
# in this content with its mask.
|
46
|
+
def self.apply_to(content)
|
47
|
+
content.gsub!( self.pattern ) do |match|
|
48
|
+
new_chunk = self.new($~, content)
|
49
|
+
content.add_chunk(new_chunk)
|
50
|
+
new_chunk.mask
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# should contain only [a-z0-9]
|
55
|
+
def mask
|
56
|
+
@mask ||="chunk#{@id}#{self.class.mask_string}chunk"
|
57
|
+
end
|
58
|
+
|
59
|
+
# We should not use object_id because object_id is not guarantied
|
60
|
+
# to be unique when we restart the wiki (new object ids can equal old ones
|
61
|
+
# that were restored form madeleine storage)
|
62
|
+
def id
|
63
|
+
@id ||= "#{@content.page_id}n#{@content.chunk_id}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def unmask
|
67
|
+
@content.sub!(mask, @unmask_text)
|
68
|
+
end
|
69
|
+
|
70
|
+
def rendered?
|
71
|
+
@unmask_mode == :normal
|
72
|
+
end
|
73
|
+
|
74
|
+
def escaped?
|
75
|
+
@unmask_mode == :escape
|
76
|
+
end
|
77
|
+
|
78
|
+
def revert
|
79
|
+
@content.sub!(mask, @text)
|
80
|
+
# unregister
|
81
|
+
@content.delete_chunk(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -1,54 +1,61 @@
|
|
1
|
-
$: << File.dirname(__FILE__) + "../../lib"
|
2
|
-
|
3
|
-
require 'redcloth'
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
# to
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
1
|
+
$: << File.dirname(__FILE__) + "../../lib"
|
2
|
+
|
3
|
+
require 'redcloth'
|
4
|
+
require 'bluecloth_tweaked'
|
5
|
+
require 'rdocsupport'
|
6
|
+
require 'chunks/chunk'
|
7
|
+
|
8
|
+
# The markup engines are Chunks that call the one of RedCloth
|
9
|
+
# or RDoc to convert text. This markup occurs when the chunk is required
|
10
|
+
# to mask itself.
|
11
|
+
module Engines
|
12
|
+
class AbstractEngine < Chunk::Abstract
|
13
|
+
|
14
|
+
# Create a new chunk for the whole content and replace it with its mask.
|
15
|
+
def self.apply_to(content)
|
16
|
+
new_chunk = self.new(content)
|
17
|
+
content.replace(new_chunk.mask)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Never create engines by constructor - use apply_to instead
|
23
|
+
def initialize(content)
|
24
|
+
@content = content
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class Textile < AbstractEngine
|
30
|
+
def mask
|
31
|
+
redcloth = RedCloth.new(@content, [:hard_breaks] + @content.options[:engine_opts])
|
32
|
+
redcloth.filter_html = false
|
33
|
+
redcloth.no_span_caps = false
|
34
|
+
redcloth.to_html(:textile)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Markdown < AbstractEngine
|
39
|
+
def mask
|
40
|
+
BlueCloth.new(@content, @content.options[:engine_opts]).to_html
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Mixed < AbstractEngine
|
45
|
+
def mask
|
46
|
+
redcloth = RedCloth.new(@content, @content.options[:engine_opts])
|
47
|
+
redcloth.filter_html = false
|
48
|
+
redcloth.no_span_caps = false
|
49
|
+
redcloth.to_html
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class RDoc < AbstractEngine
|
54
|
+
def mask
|
55
|
+
RDocSupport::RDocFormatter.new(@content).to_html
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
MAP = { :textile => Textile, :markdown => Markdown, :mixed => Mixed, :rdoc => RDoc }
|
60
|
+
MAP.default = Textile
|
61
|
+
end
|