Pimki 1.3.092 → 1.4.092
Sign up to get free protection for your applications and to get access to all the features.
- data/README +145 -131
- data/README-PIMKI +15 -5
- data/app/controllers/wiki.rb +167 -54
- data/app/models/author.rb +3 -3
- data/app/models/chunks/chunk.rb +3 -3
- data/app/models/chunks/engines.rb +18 -21
- data/app/models/chunks/include.rb +29 -29
- data/app/models/chunks/literal.rb +20 -20
- data/app/models/chunks/match.rb +19 -19
- data/app/models/chunks/nowiki.rb +31 -31
- data/app/models/chunks/nowiki_test.rb +14 -14
- data/app/models/chunks/test.rb +18 -18
- data/app/models/chunks/todo.rb +44 -23
- data/app/models/chunks/uri.rb +97 -97
- data/app/models/chunks/uri_test.rb +92 -92
- data/app/models/chunks/wiki.rb +4 -4
- data/app/models/chunks/wiki_symbols.rb +22 -22
- data/app/models/chunks/wiki_test.rb +36 -36
- data/app/models/page.rb +39 -7
- data/app/models/page_lock.rb +23 -23
- data/app/models/page_set.rb +72 -72
- data/app/models/page_test.rb +75 -75
- data/app/models/revision.rb +1 -1
- data/app/models/revision_test.rb +251 -251
- data/app/models/web.rb +19 -6
- data/app/models/web_test.rb +52 -52
- data/app/models/wiki_content.rb +131 -119
- data/app/models/wiki_service.rb +31 -16
- data/app/models/wiki_service_test.rb +15 -15
- data/app/models/wiki_words.rb +1 -1
- data/app/models/wiki_words_test.rb +12 -12
- data/app/views/bottom.rhtml +3 -3
- data/app/views/markdown_help.rhtml +15 -15
- data/app/views/menu.rhtml +20 -20
- data/app/views/navigation.rhtml +26 -26
- data/app/views/rdoc_help.rhtml +15 -15
- data/app/views/static_style_sheet.rhtml +237 -237
- data/app/views/style.rhtml +178 -178
- data/app/views/textile_help.rhtml +27 -27
- data/app/views/top.rhtml +7 -2
- data/app/views/wiki/authors.rhtml +15 -15
- data/app/views/wiki/bliki.rhtml +101 -101
- data/app/views/wiki/bliki_edit.rhtml +3 -0
- data/app/views/wiki/bliki_new.rhtml +3 -0
- data/app/views/wiki/bliki_revision.rhtml +90 -90
- data/app/views/wiki/edit.rhtml +12 -3
- data/app/views/wiki/edit_menu.rhtml +64 -47
- data/app/views/wiki/edit_web.rhtml +65 -18
- data/app/views/wiki/export.rhtml +14 -14
- data/app/views/wiki/feeds.rhtml +10 -10
- data/app/views/wiki/list.rhtml +17 -15
- data/app/views/wiki/locked.rhtml +13 -13
- data/app/views/wiki/login.rhtml +10 -10
- data/app/views/wiki/mind.rhtml +0 -1
- data/app/views/wiki/new.rhtml +8 -3
- data/app/views/wiki/new_system.rhtml +77 -77
- data/app/views/wiki/new_web.rhtml +63 -63
- data/app/views/wiki/page.rhtml +88 -82
- data/app/views/wiki/print.rhtml +15 -15
- data/app/views/wiki/published.rhtml +2 -1
- data/app/views/wiki/recently_revised.rhtml +31 -31
- data/app/views/wiki/revision.rhtml +1 -7
- data/app/views/wiki/rollback.rhtml +31 -0
- data/app/views/wiki/rss_feed.rhtml +21 -21
- data/app/views/wiki/search.rhtml +48 -48
- data/app/views/wiki/tex.rhtml +22 -22
- data/app/views/wiki/tex_web.rhtml +34 -34
- data/app/views/wiki/todo.rhtml +90 -67
- data/app/views/wiki/web_list.rhtml +12 -12
- data/app/views/wiki_words_help.rhtml +1 -1
- data/favicon.png +0 -0
- data/libraries/action_controller_servlet.rb +17 -2
- data/libraries/bluecloth.rb +1127 -1127
- data/libraries/diff/diff.rb +474 -474
- data/libraries/diff/diff_test.rb +79 -79
- data/libraries/erb.rb +490 -490
- data/libraries/madeleine/automatic.rb +418 -357
- data/libraries/madeleine/clock.rb +94 -94
- data/libraries/madeleine/files.rb +19 -0
- data/libraries/madeleine/zmarshal.rb +60 -0
- data/libraries/madeleine_service.rb +14 -15
- data/libraries/rdocsupport.rb +155 -155
- data/libraries/redcloth_for_tex.rb +869 -869
- data/libraries/redcloth_for_tex_test.rb +40 -40
- data/libraries/view_helper.rb +32 -32
- data/libraries/web_controller_server.rb +96 -94
- data/pimki.rb +47 -6
- metadata +18 -4
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
|
data/app/models/chunks/chunk.rb
CHANGED
@@ -11,9 +11,9 @@ module Chunk
|
|
11
11
|
attr_reader :text, :revision
|
12
12
|
|
13
13
|
def initialize(match_data, revision) @text = match_data[0]; @revision = revision end
|
14
|
-
def pre_mask() "chunk#{self.
|
15
|
-
def post_mask() " chunk#{self.
|
16
|
-
def mask(content) "chunk#{self.
|
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
17
|
def revert(content) content.sub!( Regexp.new(mask(content)), text ) end
|
18
18
|
def unmask(content) self if revert(content) end
|
19
19
|
end
|
@@ -5,43 +5,40 @@ require 'chunks/chunk'
|
|
5
5
|
# or RDoc to convert text. This markup occurs when the chunk is required
|
6
6
|
# to mask itself.
|
7
7
|
module Engines
|
8
|
-
|
8
|
+
|
9
|
+
class MarkupEngine < Chunk::Abstract
|
9
10
|
def self.pattern() /^(.*)$/m end
|
11
|
+
def unmask(content) self end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Textile < MarkupEngine
|
10
15
|
def mask(content)
|
11
|
-
#RedCloth.new(text,content.options[:engine_opts]).to_html
|
12
16
|
rc = RedCloth.new(text,content.options[:engine_opts])
|
13
17
|
rc.rules = [:textile]
|
14
18
|
rc.to_html
|
15
19
|
end
|
16
|
-
def unmask(content) self end
|
17
20
|
end
|
18
21
|
|
19
|
-
class
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
rc = RedCloth.new(text,content.options[:engine_opts])
|
25
|
-
rc.rules = [:markdown]
|
26
|
-
rc.to_html
|
27
|
-
end
|
28
|
-
else
|
29
|
-
def mask(content)
|
30
|
-
BlueCloth.new(text,content.options[:engine_opts]).to_html
|
31
|
-
end
|
22
|
+
class RedMarkdown < MarkupEngine
|
23
|
+
def mask(content)
|
24
|
+
rc = RedCloth.new(text,content.options[:engine_opts])
|
25
|
+
rc.rules = [:markdown]
|
26
|
+
rc.to_html
|
32
27
|
end
|
28
|
+
end
|
33
29
|
|
34
|
-
|
30
|
+
class BlueMarkdown < MarkupEngine
|
31
|
+
def mask(content)
|
32
|
+
BlueCloth.new(text,content.options[:engine_opts]).to_html
|
33
|
+
end
|
35
34
|
end
|
36
35
|
|
37
|
-
class RDoc <
|
38
|
-
def self.pattern() /^(.*)$/m end
|
36
|
+
class RDoc < MarkupEngine
|
39
37
|
def mask(content)
|
40
38
|
RDocSupport::RDocFormatter.new(text).to_html
|
41
39
|
end
|
42
|
-
def unmask(content) self end
|
43
40
|
end
|
44
41
|
|
45
|
-
MAP = { :textile => Textile, :
|
42
|
+
MAP = { :textile => Textile, :red_markdown => RedMarkdown, :blue_markdown => BlueMarkdown, :rdoc => RDoc }
|
46
43
|
end
|
47
44
|
|
@@ -1,29 +1,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 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, revision)
|
15
|
-
super(match_data, revision)
|
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 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, revision)
|
15
|
+
super(match_data, revision)
|
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,20 +1,20 @@
|
|
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
|
20
|
-
|
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
|
20
|
+
|
data/app/models/chunks/match.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
# This module is to be included in unit tests that involve matching chunks.
|
2
|
-
# It provides a easy way to test whether a chunk matches a particular string
|
3
|
-
# and any the values of any fields that should be set after a match.
|
4
|
-
module ChunkMatch
|
5
|
-
|
6
|
-
# Asserts a number of tests for the given type and text.
|
7
|
-
def match(type, test_text, expected)
|
8
|
-
pattern = type.pattern
|
9
|
-
assert_match(pattern, test_text)
|
10
|
-
pattern =~ test_text # Previous assertion guarantees match
|
11
|
-
chunk = type.new($~)
|
12
|
-
|
13
|
-
# Test if requested parts are correct.
|
14
|
-
for method_sym, value in expected do
|
15
|
-
assert_respond_to(chunk, method_sym)
|
16
|
-
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
# This module is to be included in unit tests that involve matching chunks.
|
2
|
+
# It provides a easy way to test whether a chunk matches a particular string
|
3
|
+
# and any the values of any fields that should be set after a match.
|
4
|
+
module ChunkMatch
|
5
|
+
|
6
|
+
# Asserts a number of tests for the given type and text.
|
7
|
+
def match(type, test_text, expected)
|
8
|
+
pattern = type.pattern
|
9
|
+
assert_match(pattern, test_text)
|
10
|
+
pattern =~ test_text # Previous assertion guarantees match
|
11
|
+
chunk = type.new($~)
|
12
|
+
|
13
|
+
# Test if requested parts are correct.
|
14
|
+
for method_sym, value in expected do
|
15
|
+
assert_respond_to(chunk, method_sym)
|
16
|
+
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/app/models/chunks/nowiki.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
|
-
require 'chunks/chunk'
|
2
|
-
|
3
|
-
# This chunks allows certain parts of a wiki page to be hidden from the
|
4
|
-
# rest of the rendering pipeline. It should be run at the beginning
|
5
|
-
# of the pipeline in `wiki_content.rb`.
|
6
|
-
#
|
7
|
-
# An example use of this chunk is to markup double brackets or
|
8
|
-
# auto URI links:
|
9
|
-
# <nowiki>Here are [[double brackets]] and a URI: www.uri.org</nowiki>
|
10
|
-
#
|
11
|
-
# The contents of the chunks will not be processed by any other chunk
|
12
|
-
# so the `www.uri.org` and the double brackets will appear verbatim.
|
13
|
-
#
|
14
|
-
# Author: Mark Reid <mark at threewordslong dot com>
|
15
|
-
# Created: 8th June 2004
|
16
|
-
class NoWiki < Chunk::Abstract
|
17
|
-
|
18
|
-
def self.pattern() Regexp.new('<nowiki>(.*?)</nowiki>') end
|
19
|
-
|
20
|
-
attr_reader :plain_text
|
21
|
-
|
22
|
-
def initialize(match_data, revision)
|
23
|
-
super(match_data, revision)
|
24
|
-
@plain_text = match_data[1]
|
25
|
-
end
|
26
|
-
|
27
|
-
# The nowiki content is not unmasked. This means the chunk will be reverted
|
28
|
-
# using the plain text.
|
29
|
-
def unmask(content) nil end
|
30
|
-
def revert(content) content.sub!( Regexp.new(mask(content)), plain_text ) end
|
31
|
-
end
|
1
|
+
require 'chunks/chunk'
|
2
|
+
|
3
|
+
# This chunks allows certain parts of a wiki page to be hidden from the
|
4
|
+
# rest of the rendering pipeline. It should be run at the beginning
|
5
|
+
# of the pipeline in `wiki_content.rb`.
|
6
|
+
#
|
7
|
+
# An example use of this chunk is to markup double brackets or
|
8
|
+
# auto URI links:
|
9
|
+
# <nowiki>Here are [[double brackets]] and a URI: www.uri.org</nowiki>
|
10
|
+
#
|
11
|
+
# The contents of the chunks will not be processed by any other chunk
|
12
|
+
# so the `www.uri.org` and the double brackets will appear verbatim.
|
13
|
+
#
|
14
|
+
# Author: Mark Reid <mark at threewordslong dot com>
|
15
|
+
# Created: 8th June 2004
|
16
|
+
class NoWiki < Chunk::Abstract
|
17
|
+
|
18
|
+
def self.pattern() Regexp.new('<nowiki>(.*?)</nowiki>') end
|
19
|
+
|
20
|
+
attr_reader :plain_text
|
21
|
+
|
22
|
+
def initialize(match_data, revision)
|
23
|
+
super(match_data, revision)
|
24
|
+
@plain_text = match_data[1]
|
25
|
+
end
|
26
|
+
|
27
|
+
# The nowiki content is not unmasked. This means the chunk will be reverted
|
28
|
+
# using the plain text.
|
29
|
+
def unmask(content) nil end
|
30
|
+
def revert(content) content.sub!( Regexp.new(mask(content)), plain_text ) end
|
31
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require 'chunks/nowiki'
|
2
|
-
require 'chunks/match'
|
3
|
-
require 'test/unit'
|
4
|
-
|
5
|
-
class NoWikiTest < Test::Unit::TestCase
|
6
|
-
include ChunkMatch
|
7
|
-
|
8
|
-
def test_simple_nowiki
|
9
|
-
match(NoWiki, 'This sentence contains <nowiki>[[raw text]]</nowiki>. Do not touch!',
|
10
|
-
:plain_text => '[[raw text]]'
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
1
|
+
require 'chunks/nowiki'
|
2
|
+
require 'chunks/match'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class NoWikiTest < Test::Unit::TestCase
|
6
|
+
include ChunkMatch
|
7
|
+
|
8
|
+
def test_simple_nowiki
|
9
|
+
match(NoWiki, 'This sentence contains <nowiki>[[raw text]]</nowiki>. Do not touch!',
|
10
|
+
:plain_text => '[[raw text]]'
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/app/models/chunks/test.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
class ChunkTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
# Asserts a number of tests for the given type and text.
|
6
|
-
def match(type, test_text, expected)
|
7
|
-
pattern = type.pattern
|
8
|
-
assert_match(pattern, test_text)
|
9
|
-
pattern =~ test_text # Previous assertion guarantees match
|
10
|
-
chunk = type.new($~)
|
11
|
-
|
12
|
-
# Test if requested parts are correct.
|
13
|
-
for method_sym, value in expected do
|
14
|
-
assert_respond_to(chunk, method_sym)
|
15
|
-
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
class ChunkTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# Asserts a number of tests for the given type and text.
|
6
|
+
def match(type, test_text, expected)
|
7
|
+
pattern = type.pattern
|
8
|
+
assert_match(pattern, test_text)
|
9
|
+
pattern =~ test_text # Previous assertion guarantees match
|
10
|
+
chunk = type.new($~)
|
11
|
+
|
12
|
+
# Test if requested parts are correct.
|
13
|
+
for method_sym, value in expected do
|
14
|
+
assert_respond_to(chunk, method_sym)
|
15
|
+
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/app/models/chunks/todo.rb
CHANGED
@@ -1,23 +1,44 @@
|
|
1
|
-
require 'chunks/wiki'
|
2
|
-
require 'date'
|
3
|
-
require 'parsedate'
|
4
|
-
|
5
|
-
# ToDo items.
|
6
|
-
class Todo < Chunk::Abstract
|
7
|
-
def self.pattern() /todo
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
require 'chunks/wiki'
|
2
|
+
require 'date'
|
3
|
+
require 'parsedate'
|
4
|
+
|
5
|
+
# ToDo items.
|
6
|
+
class Todo < Chunk::Abstract
|
7
|
+
def self.pattern() /todo(@[\w,]+)?: (.*?)(?=<br|\r|\n|\z)/i end
|
8
|
+
|
9
|
+
attr_accessor :context, :due_date
|
10
|
+
|
11
|
+
def initialize(match_data, revision)
|
12
|
+
super(match_data, revision)
|
13
|
+
@context = match_data[1]
|
14
|
+
@context = @context.nil? || @context.empty? ? [] : @context.delete('@').split(',')
|
15
|
+
@text = match_data[2]
|
16
|
+
begin
|
17
|
+
d = ParseDate.parsedate(@text)
|
18
|
+
# see if there's a date in the todo:
|
19
|
+
if not d.all? { |x| x.nil? }
|
20
|
+
d = d[0..2]
|
21
|
+
# sanity check the order retured from ParseDate: stuff like 'Jan 2005'
|
22
|
+
# will be returned in inverse order to '12 Jan 2005'. (ie. no automatic bounds checking)
|
23
|
+
d.reverse! if d[2] > 31
|
24
|
+
# get the [year,month,date] with sane values if you miss the day/year.
|
25
|
+
# this should allow users to specify stuff like 'Dec 2005' or 'Dec 21'.
|
26
|
+
d = [ d[0] || Date.today.year, d[1], d[2] || 1 ]
|
27
|
+
@due_date = Date.new(*d)
|
28
|
+
end
|
29
|
+
rescue => detail
|
30
|
+
p ['==>', detail, @text]
|
31
|
+
@due_date = nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def escaped_text() nil end
|
36
|
+
|
37
|
+
def unmask(content)
|
38
|
+
return self if content.gsub!( Regexp.new(mask(content)),
|
39
|
+
# the style 'todo' is bright-red to be eye catching. It is not expected that
|
40
|
+
# there will be too many items on one page, but each is supposed to stand out.
|
41
|
+
# The ToDo special page differentiates between the 'todo' and 'todoFuture' styles.
|
42
|
+
"<todo-tag context='#{@context.join(',')}' due_date='#{@due_date}'><span class=\"todo\"><strong>TODO#{ " @ #{@context.join(', ')}" unless @context.empty?}:</strong> #{@text}</span></todo-tag>" )
|
43
|
+
end
|
44
|
+
end
|
data/app/models/chunks/uri.rb
CHANGED
@@ -1,97 +1,97 @@
|
|
1
|
-
require 'chunks/chunk'
|
2
|
-
|
3
|
-
# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
|
4
|
-
# It parses out a variety of fields that could be used by renderers to format
|
5
|
-
# the links in various ways (shortening domain names, hiding email addresses)
|
6
|
-
# It matches email addresses and host.com.au domains without schemes (http://)
|
7
|
-
# but adds these on as required.
|
8
|
-
#
|
9
|
-
# The heuristic used to match a URI is designed to err on the side of caution.
|
10
|
-
# That is, it is more likely to not autolink a URI than it is to accidently
|
11
|
-
# autolink something that is not a URI. The reason behind this is it is easier
|
12
|
-
# to force a URI link by prefixing 'http://' to it than it is to escape and
|
13
|
-
# incorrectly marked up non-URI.
|
14
|
-
#
|
15
|
-
# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
|
16
|
-
# The generic names are from www.bnoack.com/data/countrycode2.html)
|
17
|
-
# [iso3166]: http://geotags.com/iso3166/
|
18
|
-
class URIChunk < Chunk::Abstract
|
19
|
-
include URI::REGEXP::PATTERN
|
20
|
-
|
21
|
-
GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
|
22
|
-
COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
|
23
|
-
|
24
|
-
# These are needed otherwise HOST will match almost anything
|
25
|
-
TLDS = "\\.(?:#{GENERIC}|#{COUNTRY})\b"
|
26
|
-
|
27
|
-
# Redefine USERINFO so that it must have non-zero length
|
28
|
-
USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
|
29
|
-
|
30
|
-
# Pattern of legal URI endings to stop interference with some Textile
|
31
|
-
# markup. (Images: !URI!) and other punctuation eg, (http://wiki.com/)
|
32
|
-
URI_ENDING = '[)!]'
|
33
|
-
|
34
|
-
# The basic URI expression as a string
|
35
|
-
URI_PATTERN =
|
36
|
-
"(?:(#{SCHEME})://)?" + # Optional scheme:// (\1|\8)
|
37
|
-
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2|\9)
|
38
|
-
"(#{HOSTNAME}#{TLDS})" + # Mandatory host eg, HOST.com.au (\3|\10)
|
39
|
-
"(?::(#{PORT}))?" + # Optional :port (\4|\11)
|
40
|
-
"(#{ABS_PATH})?" + # Optional absolute path (\5|\12)
|
41
|
-
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6|\13)
|
42
|
-
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7|\14)
|
43
|
-
|
44
|
-
def self.pattern()
|
45
|
-
# This pattern first tries to match the URI_PATTERN that ends with
|
46
|
-
# punctuation that is a valid URI character (eg, ')', '!'). If
|
47
|
-
# such a match occurs, there should be no backtracking (hence the ?> ).
|
48
|
-
# If the string cannot match a URI ending with URI_ENDING, then a second
|
49
|
-
# attempt is tried.
|
50
|
-
Regexp.new("(?>#{URI_PATTERN}(?=#{URI_ENDING}))|#{URI_PATTERN}", Regexp::EXTENDED, 'N')
|
51
|
-
end
|
52
|
-
|
53
|
-
attr_reader :uri, :scheme, :user, :host, :port, :path, :query, :fragment, :link_text
|
54
|
-
|
55
|
-
def initialize(match_data, revision)
|
56
|
-
super(match_data, revision)
|
57
|
-
# Since the URI_PATTERN is tried twice, there are two sets of
|
58
|
-
# groups, one from \1 to \7 and the second from \8 to \14.
|
59
|
-
# The fields are set by which ever group matches.
|
60
|
-
@scheme = match_data[1] || match_data[8]
|
61
|
-
@user = match_data[2] || match_data[9]
|
62
|
-
@host = match_data[3] || match_data[10]
|
63
|
-
@port = match_data[4] || match_data[11]
|
64
|
-
@path = match_data[5] || match_data[12]
|
65
|
-
@query = match_data[6] || match_data[13]
|
66
|
-
@fragment = match_data[7] || match_data[14]
|
67
|
-
|
68
|
-
# If there is no scheme, add an appropriate one, otherwise
|
69
|
-
# set the URI to the matched text.
|
70
|
-
@text_scheme = scheme
|
71
|
-
@uri = (scheme ? match_data[0] : nil )
|
72
|
-
@scheme = scheme || ( user ? 'mailto' : 'http' )
|
73
|
-
@delimiter = ( scheme == 'mailto' ? ':' : '://' )
|
74
|
-
@uri ||= scheme + @delimiter + match_data[0]
|
75
|
-
|
76
|
-
# Build up the link text. Schemes are omitted unless explicitly given.
|
77
|
-
@link_text = ''
|
78
|
-
@link_text << "#{@scheme}#{@delimiter}" if @text_scheme
|
79
|
-
@link_text << "#{@user}@" if @user
|
80
|
-
@link_text << "#{@host}" if @host
|
81
|
-
@link_text << ":#{@port}" if @port
|
82
|
-
@link_text << "#{@path}" if @path
|
83
|
-
@link_text << "?#{@query}" if @query
|
84
|
-
end
|
85
|
-
|
86
|
-
# If the text should be escaped then don't keep this chunk.
|
87
|
-
# Otherwise only keep this chunk if it was substituted back into the
|
88
|
-
# content.
|
89
|
-
def unmask(content)
|
90
|
-
return nil if escaped_text
|
91
|
-
return self if content.sub!( Regexp.new(mask(content)), "<a href=\"#{uri}\">#{link_text}</a>" )
|
92
|
-
end
|
93
|
-
|
94
|
-
# If there is no hostname in the URI, do not render it
|
95
|
-
# It's probably only contains the scheme, eg 'something:'
|
96
|
-
def escaped_text() ( host.nil? ? @uri : nil ) end
|
97
|
-
end
|
1
|
+
require 'chunks/chunk'
|
2
|
+
|
3
|
+
# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
|
4
|
+
# It parses out a variety of fields that could be used by renderers to format
|
5
|
+
# the links in various ways (shortening domain names, hiding email addresses)
|
6
|
+
# It matches email addresses and host.com.au domains without schemes (http://)
|
7
|
+
# but adds these on as required.
|
8
|
+
#
|
9
|
+
# The heuristic used to match a URI is designed to err on the side of caution.
|
10
|
+
# That is, it is more likely to not autolink a URI than it is to accidently
|
11
|
+
# autolink something that is not a URI. The reason behind this is it is easier
|
12
|
+
# to force a URI link by prefixing 'http://' to it than it is to escape and
|
13
|
+
# incorrectly marked up non-URI.
|
14
|
+
#
|
15
|
+
# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
|
16
|
+
# The generic names are from www.bnoack.com/data/countrycode2.html)
|
17
|
+
# [iso3166]: http://geotags.com/iso3166/
|
18
|
+
class URIChunk < Chunk::Abstract
|
19
|
+
include URI::REGEXP::PATTERN
|
20
|
+
|
21
|
+
GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
|
22
|
+
COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
|
23
|
+
|
24
|
+
# These are needed otherwise HOST will match almost anything
|
25
|
+
TLDS = "\\.(?:#{GENERIC}|#{COUNTRY})\b"
|
26
|
+
|
27
|
+
# Redefine USERINFO so that it must have non-zero length
|
28
|
+
USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
|
29
|
+
|
30
|
+
# Pattern of legal URI endings to stop interference with some Textile
|
31
|
+
# markup. (Images: !URI!) and other punctuation eg, (http://wiki.com/)
|
32
|
+
URI_ENDING = '[)!]'
|
33
|
+
|
34
|
+
# The basic URI expression as a string
|
35
|
+
URI_PATTERN =
|
36
|
+
"(?:(#{SCHEME})://)?" + # Optional scheme:// (\1|\8)
|
37
|
+
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2|\9)
|
38
|
+
"(#{HOSTNAME}#{TLDS})" + # Mandatory host eg, HOST.com.au (\3|\10)
|
39
|
+
"(?::(#{PORT}))?" + # Optional :port (\4|\11)
|
40
|
+
"(#{ABS_PATH})?" + # Optional absolute path (\5|\12)
|
41
|
+
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6|\13)
|
42
|
+
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7|\14)
|
43
|
+
|
44
|
+
def self.pattern()
|
45
|
+
# This pattern first tries to match the URI_PATTERN that ends with
|
46
|
+
# punctuation that is a valid URI character (eg, ')', '!'). If
|
47
|
+
# such a match occurs, there should be no backtracking (hence the ?> ).
|
48
|
+
# If the string cannot match a URI ending with URI_ENDING, then a second
|
49
|
+
# attempt is tried.
|
50
|
+
Regexp.new("(?>#{URI_PATTERN}(?=#{URI_ENDING}))|#{URI_PATTERN}", Regexp::EXTENDED, 'N')
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_reader :uri, :scheme, :user, :host, :port, :path, :query, :fragment, :link_text
|
54
|
+
|
55
|
+
def initialize(match_data, revision)
|
56
|
+
super(match_data, revision)
|
57
|
+
# Since the URI_PATTERN is tried twice, there are two sets of
|
58
|
+
# groups, one from \1 to \7 and the second from \8 to \14.
|
59
|
+
# The fields are set by which ever group matches.
|
60
|
+
@scheme = match_data[1] || match_data[8]
|
61
|
+
@user = match_data[2] || match_data[9]
|
62
|
+
@host = match_data[3] || match_data[10]
|
63
|
+
@port = match_data[4] || match_data[11]
|
64
|
+
@path = match_data[5] || match_data[12]
|
65
|
+
@query = match_data[6] || match_data[13]
|
66
|
+
@fragment = match_data[7] || match_data[14]
|
67
|
+
|
68
|
+
# If there is no scheme, add an appropriate one, otherwise
|
69
|
+
# set the URI to the matched text.
|
70
|
+
@text_scheme = scheme
|
71
|
+
@uri = (scheme ? match_data[0] : nil )
|
72
|
+
@scheme = scheme || ( user ? 'mailto' : 'http' )
|
73
|
+
@delimiter = ( scheme == 'mailto' ? ':' : '://' )
|
74
|
+
@uri ||= scheme + @delimiter + match_data[0]
|
75
|
+
|
76
|
+
# Build up the link text. Schemes are omitted unless explicitly given.
|
77
|
+
@link_text = ''
|
78
|
+
@link_text << "#{@scheme}#{@delimiter}" if @text_scheme
|
79
|
+
@link_text << "#{@user}@" if @user
|
80
|
+
@link_text << "#{@host}" if @host
|
81
|
+
@link_text << ":#{@port}" if @port
|
82
|
+
@link_text << "#{@path}" if @path
|
83
|
+
@link_text << "?#{@query}" if @query
|
84
|
+
end
|
85
|
+
|
86
|
+
# If the text should be escaped then don't keep this chunk.
|
87
|
+
# Otherwise only keep this chunk if it was substituted back into the
|
88
|
+
# content.
|
89
|
+
def unmask(content)
|
90
|
+
return nil if escaped_text
|
91
|
+
return self if content.sub!( Regexp.new(mask(content)), "<a href=\"#{uri}\">#{link_text}</a>" )
|
92
|
+
end
|
93
|
+
|
94
|
+
# If there is no hostname in the URI, do not render it
|
95
|
+
# It's probably only contains the scheme, eg 'something:'
|
96
|
+
def escaped_text() ( host.nil? ? @uri : nil ) end
|
97
|
+
end
|