Pimki 1.3.092 → 1.4.092
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.
- 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
|