require 'wiki_words' require 'chunks/chunk' require 'cgi' # Contains all the methods for finding and replacing wiki related # links. module WikiChunk include Chunk # A wiki link is the top-level class for anything that refers to # another wiki page. class WikiLink < Chunk::Abstract # By default, no escaped text def escaped_text() nil end # Delimit the link text with markers to replace later unless # the word is escaped. In that case, just return the link text def mask(content) escaped_text || pre_mask + link_text + post_mask end def regexp() Regexp.new(pre_mask + '(.*)?' + post_mask) end def revert(content) content.sub!(regexp, text) end # Do not keep this chunk if it is escaped. # Otherwise, pass the link procedure a page_name and link_text and # get back a string of HTML to replace the mask with. def unmask(content) return nil if escaped_text return self if content.sub!(regexp) { |match| content.page_link(page_name, $1) } 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 def self.pattern Regexp.new('(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')()?', 0, "utf-8") end # (chunk\d+chunk)? attr_reader :page_name def initialize(match_data, revision) super(match_data, revision) @escaped = match_data[1] || match_data[3] @text.delete! '\\' if @escaped @page_name = @link_text = match_data[2] end def mask(content) pre_mask + post_mask; end def regexp() Regexp.new(pre_mask + post_mask) end def escaped_text() (@escaped.nil? ? nil : page_name) end def link_text() WikiWords.separate(page_name) 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 def self.pattern() /\[\[([^\]]+)\]\]/ end ALIASED_LINK_PATTERN= Regexp.new('^(.*)?\|(.*)$', 0, "utf-8") attr_reader :page_name, :link_text def initialize(match_data, revision) super(match_data, revision) # If the like is aliased, set the page name to the first bit # and the link text to the second, otherwise set both to the # contents of the double brackets. if match_data[1] =~ ALIASED_LINK_PATTERN @page_name, @link_text = $1, $2 else @page_name, @link_text = match_data[1], match_data[1] end end def mask(content) pre_mask + post_mask; end def regexp() Regexp.new(pre_mask + post_mask) end def escaped_text() (@escape.nil? ? nil : page_name) end # TODO: never set? def link_text() WikiWords.separate(page_name) end end # This chunk handles [bliki[entry name]]. # This format can be easily duplicated for any other pre-configured redirection. class BlikiLink < WikiLink def self.pattern() /\[bliki\[([\w\d\s]+)\]\]/ end attr_reader :page_name, :link_text, :entry def initialize(match_data, revision) super(match_data, revision) @page_name, @link_text = match_data[1], match_data[1] end def unmask(content) return self if content.sub!(regexp) { |match| web = revision.page.web entry = web.bliki[page_name] if entry.nil? "Unknown Bliki entry: '#{page_name}'" else "#{entry.name}" end } end end end