instiki 0.9.2 → 0.10.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.
Files changed (102) hide show
  1. data/CHANGELOG +165 -0
  2. data/README +68 -172
  3. data/app/controllers/admin_controller.rb +94 -0
  4. data/app/controllers/application.rb +131 -0
  5. data/app/controllers/file_controller.rb +129 -0
  6. data/app/controllers/wiki_controller.rb +354 -0
  7. data/{libraries/view_helper.rb → app/helpers/application_helper.rb} +68 -33
  8. data/app/models/author.rb +3 -3
  9. data/app/models/chunks/category.rb +33 -31
  10. data/app/models/chunks/chunk.rb +86 -20
  11. data/app/models/chunks/engines.rb +54 -38
  12. data/app/models/chunks/include.rb +41 -29
  13. data/app/models/chunks/literal.rb +31 -19
  14. data/app/models/chunks/nowiki.rb +28 -31
  15. data/app/models/chunks/test.rb +18 -18
  16. data/app/models/chunks/uri.rb +182 -97
  17. data/app/models/chunks/wiki.rb +141 -82
  18. data/app/models/file_yard.rb +58 -0
  19. data/app/models/page.rb +112 -86
  20. data/app/models/page_lock.rb +22 -23
  21. data/app/models/page_set.rb +89 -64
  22. data/app/models/revision.rb +123 -90
  23. data/app/models/web.rb +176 -89
  24. data/app/models/wiki_content.rb +207 -105
  25. data/app/models/wiki_service.rb +233 -83
  26. data/app/models/wiki_words.rb +23 -25
  27. data/app/views/{wiki/new_system.rhtml → admin/create_system.rhtml} +83 -78
  28. data/app/views/{wiki/new_web.rhtml → admin/create_web.rhtml} +69 -64
  29. data/app/views/admin/edit_web.rhtml +136 -0
  30. data/app/views/file/file.rhtml +19 -0
  31. data/app/views/file/import.rhtml +23 -0
  32. data/app/views/layouts/default.rhtml +85 -0
  33. data/app/views/markdown_help.rhtml +12 -16
  34. data/app/views/mixed_help.rhtml +7 -0
  35. data/app/views/navigation.rhtml +30 -19
  36. data/app/views/rdoc_help.rhtml +12 -16
  37. data/app/views/textile_help.rhtml +24 -28
  38. data/app/views/wiki/authors.rhtml +11 -13
  39. data/app/views/wiki/edit.rhtml +39 -31
  40. data/app/views/wiki/export.rhtml +12 -14
  41. data/app/views/wiki/feeds.rhtml +14 -10
  42. data/app/views/wiki/list.rhtml +64 -57
  43. data/app/views/wiki/locked.rhtml +23 -14
  44. data/app/views/wiki/login.rhtml +14 -11
  45. data/app/views/wiki/new.rhtml +31 -27
  46. data/app/views/wiki/page.rhtml +115 -81
  47. data/app/views/wiki/print.rhtml +14 -16
  48. data/app/views/wiki/published.rhtml +9 -10
  49. data/app/views/wiki/recently_revised.rhtml +27 -30
  50. data/app/views/wiki/revision.rhtml +103 -81
  51. data/app/views/wiki/rollback.rhtml +14 -9
  52. data/app/views/wiki/rss_feed.rhtml +22 -22
  53. data/app/views/wiki/search.rhtml +38 -15
  54. data/app/views/wiki/tex.rhtml +22 -22
  55. data/app/views/wiki/tex_web.rhtml +34 -34
  56. data/app/views/wiki/web_list.rhtml +18 -13
  57. data/app/views/wiki_words_help.rhtml +9 -8
  58. data/config/environment.rb +82 -0
  59. data/config/environments/development.rb +5 -0
  60. data/config/environments/production.rb +4 -0
  61. data/config/environments/test.rb +17 -0
  62. data/config/routes.rb +18 -0
  63. data/instiki +6 -67
  64. data/instiki.rb +3 -0
  65. data/lib/active_record_stub.rb +31 -0
  66. data/{libraries/diff → lib}/diff.rb +444 -475
  67. data/lib/instiki_errors.rb +15 -0
  68. data/{libraries → lib}/rdocsupport.rb +151 -155
  69. data/lib/redcloth_for_tex.rb +736 -0
  70. data/natives/osx/desktop_launcher/AppDelegate.h +18 -0
  71. data/natives/osx/desktop_launcher/AppDelegate.mm +109 -0
  72. data/natives/osx/desktop_launcher/Credits.html +16 -0
  73. data/natives/osx/desktop_launcher/English.lproj/InfoPlist.strings +0 -0
  74. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +13 -0
  75. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -0
  76. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib +0 -0
  77. data/natives/osx/desktop_launcher/Info.plist +13 -0
  78. data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -0
  79. data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -0
  80. data/natives/osx/desktop_launcher/MakeDMG.sh +9 -0
  81. data/natives/osx/desktop_launcher/main.mm +14 -0
  82. data/natives/osx/desktop_launcher/version.plist +16 -0
  83. data/public/404.html +6 -0
  84. data/public/500.html +6 -0
  85. data/public/dispatch.rb +10 -0
  86. data/public/favicon.ico +0 -0
  87. data/public/javascripts/edit_web.js +52 -0
  88. data/public/javascripts/prototype.js +336 -0
  89. data/{app/views/static_style_sheet.rhtml → public/stylesheets/instiki.css} +221 -198
  90. data/script/breakpointer +4 -0
  91. data/script/server +93 -0
  92. metadata +59 -32
  93. data/app/controllers/wiki.rb +0 -389
  94. data/app/models/chunks/match.rb +0 -19
  95. data/app/views/bottom.rhtml +0 -4
  96. data/app/views/top.rhtml +0 -49
  97. data/app/views/wiki/edit_web.rhtml +0 -138
  98. data/libraries/action_controller_servlet.rb +0 -177
  99. data/libraries/erb.rb +0 -490
  100. data/libraries/madeleine_service.rb +0 -68
  101. data/libraries/redcloth_for_tex.rb +0 -869
  102. data/libraries/web_controller_server.rb +0 -81
@@ -1,33 +1,68 @@
1
- module ViewHelper
2
- # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container
3
- # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and
4
- # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values
5
- # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag.
6
- #
7
- # Examples (call, result):
8
- # html_options([["Dollar", "$"], ["Kroner", "DKK"]])
9
- # <option value="$">Dollar</option>\n<option value="DKK">Kroner</option>
10
- #
11
- # html_options([ "VISA", "Mastercard" ], "Mastercard")
12
- # <option>VISA</option>\n<option selected>Mastercard</option>
13
- #
14
- # html_options({ "Basic" => "$20", "Plus" => "$40" }, "$40")
15
- # <option value="$20">Basic</option>\n<option value="$40" selected>Plus</option>
16
- def html_options(container, selected = nil)
17
- container = container.to_a if Hash === container
18
-
19
- html_options = container.inject([]) do |options, element|
20
- if element.respond_to?(:first) && element.respond_to?(:last)
21
- if element.last != selected
22
- options << "<option value=\"#{element.last}\">#{element.first}</option>"
23
- else
24
- options << "<option value=\"#{element.last}\" selected>#{element.first}</option>"
25
- end
26
- else
27
- options << ((element != selected) ? "<option>#{element}</option>" : "<option selected>#{element}</option>")
28
- end
29
- end
30
-
31
- html_options.join("\n")
32
- end
33
- 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
@@ -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,31 +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
- def self.pattern() return /^(:)?category\s*:(.*)$/i end
12
-
13
- attr_reader :hidden, :list
14
-
15
- def initialize(match_data)
16
- super(match_data)
17
- @hidden = match_data[1]
18
- @list = match_data[2].split(',').map { |c| c.strip }
19
- end
20
-
21
- # Mark this chunk's start and end points but allow the terms
22
- # after the ':' to be marked up.
23
- def mask(content) pre_mask + list.join(', ') + post_mask end
24
-
25
- # If the chunk is hidden, erase the mask and return this chunk
26
- # otherwise, surround it with a 'div' block.
27
- def unmask(content)
28
- replacement = ( hidden ? '' : '<div class="property">category:\1</div>' )
29
- self if content.sub!( Regexp.new( pre_mask+'(.*)?'+post_mask ), replacement )
30
- end
31
- 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
@@ -1,20 +1,86 @@
1
- require 'digest/md5'
2
- require 'uri/common'
3
-
4
- # A chunk is a pattern of text that can be protected
5
- # and interrogated by a renderer. Each Chunk class has a
6
- # +pattern+ that states what sort of text it matches.
7
- # Chunks are initalized by passing in the result of a
8
- # match by its pattern.
9
- module Chunk
10
- class Abstract
11
- attr_reader :text
12
-
13
- def initialize(match_data) @text = match_data[0] end
14
- def pre_mask() "chunk#{self.object_id}start " end
15
- def post_mask() " chunk#{self.object_id}end" end
16
- def mask(content) "chunk#{self.object_id}chunk" end
17
- def revert(content) content.sub!( Regexp.new(mask(content)), text ) end
18
- def unmask(content) self if revert(content) end
19
- end
20
- 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,38 +1,54 @@
1
- $: << File.dirname(__FILE__) + "../../libraries"
2
-
3
- require 'redcloth'
4
- require 'bluecloth'
5
- require 'rdocsupport'
6
- require 'chunks/chunk'
7
-
8
- # The markup engines are Chunks that call the one of RedCloth, BlueCloth
9
- # or RDoc to convert text. This markup occurs when the chunk is required
10
- # to mask itself.
11
- module Engines
12
- class Textile < Chunk::Abstract
13
- def self.pattern() /^(.*)$/m end
14
- def mask(content)
15
- RedCloth.new(text,content.options[:engine_opts]).to_html
16
- end
17
- def unmask(content) self end
18
- end
19
-
20
- class Markdown < Chunk::Abstract
21
- def self.pattern() /^(.*)$/m end
22
- def mask(content)
23
- BlueCloth.new(text,content.options[:engine_opts]).to_html
24
- end
25
- def unmask(content) self end
26
- end
27
-
28
- class RDoc < Chunk::Abstract
29
- def self.pattern() /^(.*)$/m end
30
- def mask(content)
31
- RDocSupport::RDocFormatter.new(text).to_html
32
- end
33
- def unmask(content) self end
34
- end
35
-
36
- MAP = { :textile => Textile, :markdown => Markdown, :rdoc => RDoc }
37
- end
38
-
1
+ $: << File.dirname(__FILE__) + "../../lib"
2
+
3
+ require 'redcloth'
4
+ require 'rdocsupport'
5
+ require 'chunks/chunk'
6
+
7
+ # The markup engines are Chunks that call the one of RedCloth
8
+ # or RDoc to convert text. This markup occurs when the chunk is required
9
+ # to mask itself.
10
+ module Engines
11
+ class AbstractEngine < Chunk::Abstract
12
+
13
+ # Create a new chunk for the whole content and replace it with its mask.
14
+ def self.apply_to(content)
15
+ new_chunk = self.new(content)
16
+ content.replace(new_chunk.mask)
17
+ end
18
+
19
+ private
20
+
21
+ # Never create engines by constructor - use apply_to instead
22
+ def initialize(content)
23
+ @content = content
24
+ end
25
+
26
+ end
27
+
28
+ class Textile < AbstractEngine
29
+ def mask
30
+ RedCloth.new(@content, @content.options[:engine_opts]).to_html(:textile)
31
+ end
32
+ end
33
+
34
+ class Markdown < AbstractEngine
35
+ def mask
36
+ RedCloth.new(@content, @content.options[:engine_opts]).to_html(:markdown)
37
+ end
38
+ end
39
+
40
+ class Mixed < AbstractEngine
41
+ def mask
42
+ RedCloth.new(@content, @content.options[:engine_opts]).to_html
43
+ end
44
+ end
45
+
46
+ class RDoc < AbstractEngine
47
+ def mask
48
+ RDocSupport::RDocFormatter.new(@content).to_html
49
+ end
50
+ end
51
+
52
+ MAP = { :textile => Textile, :markdown => Markdown, :mixed => Mixed, :rdoc => RDoc, }
53
+ MAP.default = Textile
54
+ end
@@ -1,29 +1,41 @@
1
- require 'chunks/wiki'
2
-
3
- # Includes the contents of another page for rendering.
4
- # The include command looks like this: "[[!include PageName]]".
5
- # It is a WikiLink since it refers to another page (PageName)
6
- # and the wiki content using this command must be notified
7
- # of changes to that page.
8
- # If the included page could not be found, a warning is displayed.
9
- class Include < WikiChunk::WikiLink
10
- def self.pattern() /^\[\[!include(.*)\]\]\s*$/i end
11
-
12
- attr_reader :page_name
13
-
14
- def initialize(match_data)
15
- super(match_data)
16
- @page_name = match_data[1].strip
17
- end
18
-
19
- # This replaces the [[!include PageName]] text with
20
- # the contents of PageName if it exists. Otherwise
21
- # a warning is displayed.
22
- def mask(content)
23
- page = content.web.pages[page_name]
24
- (page ? page.content : "<em>Could not include #{page_name}</em>")
25
- end
26
-
27
- # Keep this chunk regardless of what happens.
28
- def unmask(content) self end
29
- end
1
+ require 'chunks/wiki'
2
+
3
+ # Includes the contents of another page for rendering.
4
+ # The include command looks like this: "[[!include PageName]]".
5
+ # It is a WikiReference since it refers to another page (PageName)
6
+ # and the wiki content using this command must be notified
7
+ # of changes to that page.
8
+ # If the included page could not be found, a warning is displayed.
9
+
10
+ class Include < WikiChunk::WikiReference
11
+
12
+ INCLUDE_PATTERN = /\[\[!include(.*)\]\]\s*/i
13
+ def self.pattern() INCLUDE_PATTERN end
14
+
15
+
16
+ def initialize(match_data, content)
17
+ super
18
+ @page_name = match_data[1].strip
19
+ @unmask_text = get_unmask_text_avoiding_recursion_loops
20
+ end
21
+
22
+ private
23
+
24
+ def get_unmask_text_avoiding_recursion_loops
25
+ if refpage then
26
+ if refpage.wiki_includes.include?(@content.page_name)
27
+ # this will break the recursion
28
+ @content.delete_chunk(self)
29
+ refpage.clear_display_cache
30
+ return "<em>Recursive include detected; #{@page_name} --> #{@content.page_name} " +
31
+ "--> #{@page_name}</em>\n"
32
+ else
33
+ @content.merge_chunks(refpage.display_content)
34
+ return refpage.display_content.pre_rendered
35
+ end
36
+ else
37
+ return "<em>Could not include #{@page_name}</em>\n"
38
+ end
39
+ end
40
+
41
+ end
@@ -1,19 +1,31 @@
1
- require 'chunks/chunk'
2
-
3
- # These are basic chunks that have a pattern and can be protected.
4
- # They are used by rendering process to prevent wiki rendering
5
- # occuring within literal areas such as <code> and <pre> blocks
6
- # and within HTML tags.
7
- module Literal
8
- # A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
9
- class Pre < Chunk::Abstract
10
- PRE_BLOCKS = "a|pre|code"
11
- def self.pattern() Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?</\1>', Regexp::MULTILINE) end
12
- end
13
-
14
- # A literal chunk that protects HTML tags from wiki rendering.
15
- class Tags < Chunk::Abstract
16
- TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
17
- def self.pattern() Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE) end
18
- end
19
- end
1
+ require 'chunks/chunk'
2
+
3
+ # These are basic chunks that have a pattern and can be protected.
4
+ # They are used by rendering process to prevent wiki rendering
5
+ # occuring within literal areas such as <code> and <pre> blocks
6
+ # and within HTML tags.
7
+ module Literal
8
+
9
+ class AbstractLiteral < Chunk::Abstract
10
+
11
+ def initialize(match_data, content)
12
+ super
13
+ @unmask_text = @text
14
+ end
15
+
16
+ end
17
+
18
+ # A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
19
+ class Pre < AbstractLiteral
20
+ PRE_BLOCKS = "a|pre|code"
21
+ PRE_PATTERN = Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?</\1>', Regexp::MULTILINE)
22
+ def self.pattern() PRE_PATTERN end
23
+ end
24
+
25
+ # A literal chunk that protects HTML tags from wiki rendering.
26
+ class Tags < AbstractLiteral
27
+ TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
28
+ TAGS_PATTERN = Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE)
29
+ def self.pattern() TAGS_PATTERN end
30
+ end
31
+ end