9e909d5be3
Update Bundler to 1.0.15. Update Rails to 2.3.12. Update rails_xss plugin. The latter two were the source of a considerable amount of grief, as rails_xss is now MUCH stricter about what string methods can be used. Also made it possible to use rake 0.9.x with Instiki. But you probably REALLY want to use ruby bundle exec rake ... instead of just saying rake ....
166 lines
4.7 KiB
Ruby
166 lines
4.7 KiB
Ruby
require 'chunks/chunk'
|
|
require 'instiki_stringsupport'
|
|
|
|
# Contains all the methods for finding and replacing wiki related links.
|
|
module WikiChunk
|
|
include Chunk
|
|
|
|
# A wiki reference is the top-level class for anything that refers to
|
|
# another wiki page.
|
|
class WikiReference < Chunk::Abstract
|
|
|
|
# Name of the referenced page
|
|
attr_reader :page_name
|
|
|
|
# Name of the referenced page
|
|
attr_reader :web_name
|
|
|
|
# the referenced page
|
|
def refpage
|
|
@content.web.page(@page_name)
|
|
end
|
|
|
|
end
|
|
|
|
# A wiki link is the top-level class for links that refers to
|
|
# another wiki page.
|
|
class WikiLink < WikiReference
|
|
|
|
attr_reader :link_text, :link_type
|
|
|
|
def initialize(match_data, content)
|
|
super
|
|
@link_type = :show
|
|
end
|
|
|
|
def self.apply_to(content)
|
|
text = content.as_utf8.to_str
|
|
text.gsub!( self.pattern ) do |matched_text|
|
|
chunk = self.new($~, content)
|
|
if chunk.textile_url?
|
|
# do not substitute
|
|
matched_text
|
|
else
|
|
content.add_chunk(chunk)
|
|
chunk.mask
|
|
end
|
|
end
|
|
content.replace text
|
|
end
|
|
|
|
def textile_url?
|
|
not @textile_link_suffix.nil?
|
|
end
|
|
|
|
def interweb_link?
|
|
not @web_name.nil? and Web.find_by_name(@web_name) or
|
|
Web.find_by_address(@web_name)
|
|
end
|
|
|
|
# replace any sequence of whitespace characters with a single space
|
|
def normalize_whitespace(line)
|
|
line.gsub(/\s+/, ' ')
|
|
end
|
|
|
|
end
|
|
|
|
# This chunk matches a WikiWord. WikiWords can be escaped
|
|
# by prepending a '\'. When this is the case, the +escaped_text+
|
|
# method will return the WikiWord instead of the usual +nil+.
|
|
# The +page_name+ method returns the matched WikiWord.
|
|
class Word < WikiLink
|
|
|
|
attr_reader :escaped_text
|
|
|
|
unless defined? WIKI_WORD
|
|
WIKI_WORD = ''.respond_to?(:force_encoding) ?
|
|
Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0) :
|
|
Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, 'u')
|
|
end
|
|
|
|
def self.pattern
|
|
WIKI_WORD
|
|
end
|
|
|
|
def initialize(match_data, content)
|
|
super
|
|
@textile_link_suffix, @escape, @page_name = match_data[1..3]
|
|
if @escape
|
|
@unmask_mode = :escape
|
|
@escaped_text = @page_name
|
|
else
|
|
@escaped_text = nil
|
|
end
|
|
@link_text = WikiWords.separate(@page_name)
|
|
@unmask_text = (@escaped_text || @content.page_link(@web_name, @page_name, @link_text, @link_type))
|
|
end
|
|
|
|
end
|
|
|
|
# This chunk handles [[bracketted wiki words]] and
|
|
# [[AliasedWords|aliased wiki words]]. The first part of an
|
|
# aliased wiki word must be a WikiWord. If the WikiWord
|
|
# is aliased, the +link_text+ field will contain the
|
|
# alias, otherwise +link_text+ will contain the entire
|
|
# contents within the double brackets.
|
|
#
|
|
# NOTE: This chunk must be tested before WikiWord since
|
|
# a WikiWords can be a substring of a WikiLink.
|
|
class Link < WikiLink
|
|
|
|
unless defined? WIKI_LINK
|
|
WIKI_LINK = /(":)?\[\[\s*([^\]\s][^\]]*?)\s*\]\]/
|
|
LINK_TYPE_SEPARATION = Regexp.new('^(.+):((file)|(pic)|(video)|(audio)|(delete))$', 0)
|
|
ALIAS_SEPARATION = Regexp.new('^(.+)\|(.+)$', 0)
|
|
WEB_SEPARATION = Regexp.new('^(.+):(.+)$', 0)
|
|
end
|
|
|
|
def self.pattern() WIKI_LINK end
|
|
|
|
def initialize(match_data, content)
|
|
super
|
|
@textile_link_suffix = match_data[1]
|
|
@link_text = @page_name = normalize_whitespace(match_data[2])
|
|
separate_link_type
|
|
separate_alias
|
|
separate_web
|
|
@unmask_text = @content.page_link(@web_name, @page_name, @link_text, @link_type)
|
|
end
|
|
|
|
private
|
|
|
|
# if link wihin the brackets has a form of [[filename:file]] or [[filename:pic]],
|
|
# this means a link to a picture or a file
|
|
def separate_link_type
|
|
link_type_match = LINK_TYPE_SEPARATION.match(@page_name)
|
|
if link_type_match
|
|
@link_text = @page_name = link_type_match[1]
|
|
@link_type = link_type_match[2..3].compact[0].to_sym
|
|
end
|
|
end
|
|
|
|
# link text may be different from page name. this will look like [[actual page|link text]]
|
|
def separate_alias
|
|
alias_match = ALIAS_SEPARATION.match(@page_name)
|
|
if alias_match
|
|
@page_name = normalize_whitespace(alias_match[1])
|
|
@link_text = alias_match[2]
|
|
end
|
|
# note that [[filename|link text:file]] is also supported
|
|
end
|
|
|
|
# Interweb links have the form [[Web Name:Page Name]] or
|
|
# [[address:PageName]]. Alternate text links of the form
|
|
# [[address:PageName|Other text]] are also supported.
|
|
def separate_web
|
|
web_match = WEB_SEPARATION.match(@page_name)
|
|
if web_match
|
|
@web_name = normalize_whitespace(web_match[1])
|
|
@page_name = web_match[2]
|
|
@link_text = @page_name if @link_text == web_match[0]
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|