instiki 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +165 -0
- data/README +68 -172
- data/app/controllers/admin_controller.rb +94 -0
- data/app/controllers/application.rb +131 -0
- data/app/controllers/file_controller.rb +129 -0
- data/app/controllers/wiki_controller.rb +354 -0
- data/{libraries/view_helper.rb → app/helpers/application_helper.rb} +68 -33
- data/app/models/author.rb +3 -3
- data/app/models/chunks/category.rb +33 -31
- data/app/models/chunks/chunk.rb +86 -20
- data/app/models/chunks/engines.rb +54 -38
- data/app/models/chunks/include.rb +41 -29
- data/app/models/chunks/literal.rb +31 -19
- data/app/models/chunks/nowiki.rb +28 -31
- data/app/models/chunks/test.rb +18 -18
- data/app/models/chunks/uri.rb +182 -97
- data/app/models/chunks/wiki.rb +141 -82
- data/app/models/file_yard.rb +58 -0
- data/app/models/page.rb +112 -86
- data/app/models/page_lock.rb +22 -23
- data/app/models/page_set.rb +89 -64
- data/app/models/revision.rb +123 -90
- data/app/models/web.rb +176 -89
- data/app/models/wiki_content.rb +207 -105
- data/app/models/wiki_service.rb +233 -83
- data/app/models/wiki_words.rb +23 -25
- data/app/views/{wiki/new_system.rhtml → admin/create_system.rhtml} +83 -78
- data/app/views/{wiki/new_web.rhtml → admin/create_web.rhtml} +69 -64
- data/app/views/admin/edit_web.rhtml +136 -0
- data/app/views/file/file.rhtml +19 -0
- data/app/views/file/import.rhtml +23 -0
- data/app/views/layouts/default.rhtml +85 -0
- data/app/views/markdown_help.rhtml +12 -16
- data/app/views/mixed_help.rhtml +7 -0
- data/app/views/navigation.rhtml +30 -19
- data/app/views/rdoc_help.rhtml +12 -16
- data/app/views/textile_help.rhtml +24 -28
- data/app/views/wiki/authors.rhtml +11 -13
- data/app/views/wiki/edit.rhtml +39 -31
- data/app/views/wiki/export.rhtml +12 -14
- data/app/views/wiki/feeds.rhtml +14 -10
- data/app/views/wiki/list.rhtml +64 -57
- data/app/views/wiki/locked.rhtml +23 -14
- data/app/views/wiki/login.rhtml +14 -11
- data/app/views/wiki/new.rhtml +31 -27
- data/app/views/wiki/page.rhtml +115 -81
- data/app/views/wiki/print.rhtml +14 -16
- data/app/views/wiki/published.rhtml +9 -10
- data/app/views/wiki/recently_revised.rhtml +27 -30
- data/app/views/wiki/revision.rhtml +103 -81
- data/app/views/wiki/rollback.rhtml +14 -9
- data/app/views/wiki/rss_feed.rhtml +22 -22
- data/app/views/wiki/search.rhtml +38 -15
- 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 -13
- data/app/views/wiki_words_help.rhtml +9 -8
- data/config/environment.rb +82 -0
- data/config/environments/development.rb +5 -0
- data/config/environments/production.rb +4 -0
- data/config/environments/test.rb +17 -0
- data/config/routes.rb +18 -0
- data/instiki +6 -67
- data/instiki.rb +3 -0
- data/lib/active_record_stub.rb +31 -0
- data/{libraries/diff → lib}/diff.rb +444 -475
- data/lib/instiki_errors.rb +15 -0
- data/{libraries → lib}/rdocsupport.rb +151 -155
- data/lib/redcloth_for_tex.rb +736 -0
- data/natives/osx/desktop_launcher/AppDelegate.h +18 -0
- data/natives/osx/desktop_launcher/AppDelegate.mm +109 -0
- data/natives/osx/desktop_launcher/Credits.html +16 -0
- data/natives/osx/desktop_launcher/English.lproj/InfoPlist.strings +0 -0
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +13 -0
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -0
- data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib +0 -0
- data/natives/osx/desktop_launcher/Info.plist +13 -0
- data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -0
- data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -0
- data/natives/osx/desktop_launcher/MakeDMG.sh +9 -0
- data/natives/osx/desktop_launcher/main.mm +14 -0
- data/natives/osx/desktop_launcher/version.plist +16 -0
- data/public/404.html +6 -0
- data/public/500.html +6 -0
- data/public/dispatch.rb +10 -0
- data/public/favicon.ico +0 -0
- data/public/javascripts/edit_web.js +52 -0
- data/public/javascripts/prototype.js +336 -0
- data/{app/views/static_style_sheet.rhtml → public/stylesheets/instiki.css} +221 -198
- data/script/breakpointer +4 -0
- data/script/server +93 -0
- metadata +59 -32
- data/app/controllers/wiki.rb +0 -389
- data/app/models/chunks/match.rb +0 -19
- data/app/views/bottom.rhtml +0 -4
- data/app/views/top.rhtml +0 -49
- data/app/views/wiki/edit_web.rhtml +0 -138
- data/libraries/action_controller_servlet.rb +0 -177
- data/libraries/erb.rb +0 -490
- data/libraries/madeleine_service.rb +0 -68
- data/libraries/redcloth_for_tex.rb +0 -869
- data/libraries/web_controller_server.rb +0 -81
@@ -1,33 +1,68 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
options << "<option value=\"#{element.last}\"
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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,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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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,20 +1,86 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
module Chunk
|
10
|
-
class Abstract
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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__) + "../../
|
2
|
-
|
3
|
-
require 'redcloth'
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
def
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
class
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
9
|
-
class
|
10
|
-
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|