Massive change of SVN properties to deal with EOL style problem
This commit is contained in:
parent
b747b611b3
commit
3b6566577c
|
@ -1,71 +1,71 @@
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'application'
|
require 'application'
|
||||||
require 'instiki_errors'
|
require 'instiki_errors'
|
||||||
|
|
||||||
class FileController < ApplicationController
|
class FileController < ApplicationController
|
||||||
|
|
||||||
layout 'default'
|
layout 'default'
|
||||||
|
|
||||||
before_filter :check_allow_uploads
|
before_filter :check_allow_uploads
|
||||||
|
|
||||||
def file
|
def file
|
||||||
check_path
|
check_path
|
||||||
|
|
||||||
if @params['file']
|
if @params['file']
|
||||||
# form supplied
|
# form supplied
|
||||||
file_yard.upload_file(@file_name, @params['file'])
|
file_yard.upload_file(@file_name, @params['file'])
|
||||||
flash[:info] = "File '#{@file_name}' successfully uploaded"
|
flash[:info] = "File '#{@file_name}' successfully uploaded"
|
||||||
@web.refresh_pages_with_references(@file_name)
|
@web.refresh_pages_with_references(@file_name)
|
||||||
return_to_last_remembered
|
return_to_last_remembered
|
||||||
elsif file_yard.has_file?(@file_name)
|
elsif file_yard.has_file?(@file_name)
|
||||||
send_file(file_yard.file_path(@file_name))
|
send_file(file_yard.file_path(@file_name))
|
||||||
else
|
else
|
||||||
logger.debug("File not found: #{file_yard.files_path}/#{@file_name}")
|
logger.debug("File not found: #{file_yard.files_path}/#{@file_name}")
|
||||||
# go to the template, which is a file upload form
|
# go to the template, which is a file upload form
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cancel_upload
|
def cancel_upload
|
||||||
return_to_last_remembered
|
return_to_last_remembered
|
||||||
end
|
end
|
||||||
|
|
||||||
def pic
|
def pic
|
||||||
check_path
|
check_path
|
||||||
if @params['file']
|
if @params['file']
|
||||||
# form supplied
|
# form supplied
|
||||||
file_yard.upload_file(@file_name, @params['file'])
|
file_yard.upload_file(@file_name, @params['file'])
|
||||||
flash[:info] = "Image '#{@file_name}' successfully uploaded"
|
flash[:info] = "Image '#{@file_name}' successfully uploaded"
|
||||||
@web.refresh_pages_with_references(@file_name)
|
@web.refresh_pages_with_references(@file_name)
|
||||||
return_to_last_remembered
|
return_to_last_remembered
|
||||||
elsif file_yard.has_file?(@file_name)
|
elsif file_yard.has_file?(@file_name)
|
||||||
send_file(file_yard.file_path(@file_name))
|
send_file(file_yard.file_path(@file_name))
|
||||||
else
|
else
|
||||||
logger.debug("Image not found: #{file_yard.files_path}/#{@file_name}")
|
logger.debug("Image not found: #{file_yard.files_path}/#{@file_name}")
|
||||||
render_action 'file'
|
render_action 'file'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def check_allow_uploads
|
def check_allow_uploads
|
||||||
unless @web.allow_uploads
|
unless @web.allow_uploads
|
||||||
render_text 'File uploads are blocked by the webmaster', '403 Forbidden'
|
render_text 'File uploads are blocked by the webmaster', '403 Forbidden'
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_path
|
def check_path
|
||||||
raise Instiki::ValidationError.new("Invalid path: no file name") unless @file_name
|
raise Instiki::ValidationError.new("Invalid path: no file name") unless @file_name
|
||||||
raise Instiki::ValidationError.new("Invalid path: no web name") unless @web_name
|
raise Instiki::ValidationError.new("Invalid path: no web name") unless @web_name
|
||||||
raise Instiki::ValidationError.new("Invalid path: unknown web name") unless @web
|
raise Instiki::ValidationError.new("Invalid path: unknown web name") unless @web
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_yard
|
def file_yard
|
||||||
@wiki.file_yard(@web)
|
@wiki.file_yard(@web)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
766
app/controllers/wiki_controller.rb
Executable file → Normal file
766
app/controllers/wiki_controller.rb
Executable file → Normal file
|
@ -1,383 +1,383 @@
|
||||||
require 'application'
|
require 'application'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'redcloth_for_tex'
|
require 'redcloth_for_tex'
|
||||||
|
|
||||||
class WikiController < ApplicationController
|
class WikiController < ApplicationController
|
||||||
|
|
||||||
layout 'default', :except => [:rss_feed, :rss_with_headlines, :tex, :export_tex, :export_html]
|
layout 'default', :except => [:rss_feed, :rss_with_headlines, :tex, :export_tex, :export_html]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
if @web_name
|
if @web_name
|
||||||
redirect_show 'HomePage'
|
redirect_show 'HomePage'
|
||||||
elsif not @wiki.setup?
|
elsif not @wiki.setup?
|
||||||
redirect_to :action => 'new_system'
|
redirect_to :action => 'new_system'
|
||||||
elsif @wiki.webs.length == 1
|
elsif @wiki.webs.length == 1
|
||||||
redirect_show 'HomePage', @wiki.webs.values.first.address
|
redirect_show 'HomePage', @wiki.webs.values.first.address
|
||||||
else
|
else
|
||||||
redirect_to :action => 'web_list'
|
redirect_to :action => 'web_list'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Administrating the Instiki setup --------------------------------------------
|
# Administrating the Instiki setup --------------------------------------------
|
||||||
|
|
||||||
def create_system
|
def create_system
|
||||||
@wiki.setup(@params['password'], @params['web_name'], @params['web_address']) unless @wiki.setup?
|
@wiki.setup(@params['password'], @params['web_name'], @params['web_address']) unless @wiki.setup?
|
||||||
redirect_show('HomePage', @params['web_address'])
|
redirect_show('HomePage', @params['web_address'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_web
|
def create_web
|
||||||
if @wiki.authenticate(@params['system_password'])
|
if @wiki.authenticate(@params['system_password'])
|
||||||
@wiki.create_web(@params['name'], @params['address'])
|
@wiki.create_web(@params['name'], @params['address'])
|
||||||
redirect_show('HomePage', @params['address'])
|
redirect_show('HomePage', @params['address'])
|
||||||
else
|
else
|
||||||
redirect_to :action => 'index'
|
redirect_to :action => 'index'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit_web
|
def edit_web
|
||||||
# to template
|
# to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_system
|
def new_system
|
||||||
redirect_to(:action => 'index') if wiki.setup?
|
redirect_to(:action => 'index') if wiki.setup?
|
||||||
# otherwise, to template
|
# otherwise, to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_web
|
def new_web
|
||||||
redirect_to :action => 'index' if wiki.system['password'].nil?
|
redirect_to :action => 'index' if wiki.system['password'].nil?
|
||||||
# otherwise, to template
|
# otherwise, to template
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Outside a single web --------------------------------------------------------
|
# Outside a single web --------------------------------------------------------
|
||||||
|
|
||||||
def authenticate
|
def authenticate
|
||||||
if password_check(@params['password'])
|
if password_check(@params['password'])
|
||||||
redirect_show('HomePage')
|
redirect_show('HomePage')
|
||||||
else
|
else
|
||||||
redirect_to :action => 'login'
|
redirect_to :action => 'login'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def login
|
def login
|
||||||
# to template
|
# to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def web_list
|
def web_list
|
||||||
@webs = wiki.webs.values.sort_by { |web| web.name }
|
@webs = wiki.webs.values.sort_by { |web| web.name }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Within a single web ---------------------------------------------------------
|
# Within a single web ---------------------------------------------------------
|
||||||
|
|
||||||
def authors
|
def authors
|
||||||
@authors = @web.select.authors
|
@authors = @web.select.authors
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_html
|
def export_html
|
||||||
export_pages_as_zip('html') { |page| @page = page; render_to_string 'wiki/print' }
|
export_pages_as_zip('html') { |page| @page = page; render_to_string 'wiki/print' }
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_markup
|
def export_markup
|
||||||
export_pages_as_zip(@web.markup) { |page| page.content }
|
export_pages_as_zip(@web.markup) { |page| page.content }
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_pdf
|
def export_pdf
|
||||||
file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}"
|
file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}"
|
||||||
file_path = @wiki.storage_path + file_name
|
file_path = @wiki.storage_path + file_name
|
||||||
|
|
||||||
export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex"
|
export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex"
|
||||||
convert_tex_to_pdf "#{file_path}.tex"
|
convert_tex_to_pdf "#{file_path}.tex"
|
||||||
send_file "#{file_path}.pdf"
|
send_file "#{file_path}.pdf"
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_tex
|
def export_tex
|
||||||
file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}.tex"
|
file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}.tex"
|
||||||
file_path = @wiki.storage_path + file_name
|
file_path = @wiki.storage_path + file_name
|
||||||
|
|
||||||
export_web_to_tex(file_path) unless FileTest.exists?(file_path)
|
export_web_to_tex(file_path) unless FileTest.exists?(file_path)
|
||||||
send_file file_path
|
send_file file_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def feeds
|
def feeds
|
||||||
# to template
|
# to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def list
|
def list
|
||||||
parse_category
|
parse_category
|
||||||
@pages_by_name = @pages_in_category.by_name
|
@pages_by_name = @pages_in_category.by_name
|
||||||
@page_names_that_are_wanted = @pages_in_category.wanted_pages
|
@page_names_that_are_wanted = @pages_in_category.wanted_pages
|
||||||
@pages_that_are_orphaned = @pages_in_category.orphaned_pages
|
@pages_that_are_orphaned = @pages_in_category.orphaned_pages
|
||||||
end
|
end
|
||||||
|
|
||||||
def recently_revised
|
def recently_revised
|
||||||
parse_category
|
parse_category
|
||||||
@pages_by_revision = @pages_in_category.by_revision
|
@pages_by_revision = @pages_in_category.by_revision
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_orphaned_pages
|
def remove_orphaned_pages
|
||||||
if wiki.authenticate(@params['system_password'])
|
if wiki.authenticate(@params['system_password'])
|
||||||
wiki.remove_orphaned_pages(@web_name)
|
wiki.remove_orphaned_pages(@web_name)
|
||||||
redirect_to :action => 'list'
|
redirect_to :action => 'list'
|
||||||
else
|
else
|
||||||
redirect_show 'HomePage'
|
redirect_show 'HomePage'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def rss_with_content
|
def rss_with_content
|
||||||
render_rss
|
render_rss
|
||||||
end
|
end
|
||||||
|
|
||||||
def rss_with_headlines
|
def rss_with_headlines
|
||||||
render_rss(hide_description = true)
|
render_rss(hide_description = true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search
|
def search
|
||||||
@query = @params['query']
|
@query = @params['query']
|
||||||
@results = @web.select { |page| page.content =~ /#{@query}/i }.sort
|
@results = @web.select { |page| page.content =~ /#{@query}/i }.sort
|
||||||
redirect_show(@results.first.name) if @results.length == 1
|
redirect_show(@results.first.name) if @results.length == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_web
|
def update_web
|
||||||
if wiki.authenticate(@params['system_password'])
|
if wiki.authenticate(@params['system_password'])
|
||||||
wiki.update_web(
|
wiki.update_web(
|
||||||
@web.address, @params['address'], @params['name'],
|
@web.address, @params['address'], @params['name'],
|
||||||
@params['markup'].intern,
|
@params['markup'].intern,
|
||||||
@params['color'], @params['additional_style'],
|
@params['color'], @params['additional_style'],
|
||||||
@params['safe_mode'] ? true : false,
|
@params['safe_mode'] ? true : false,
|
||||||
@params['password'].empty? ? nil : @params['password'],
|
@params['password'].empty? ? nil : @params['password'],
|
||||||
@params['published'] ? true : false,
|
@params['published'] ? true : false,
|
||||||
@params['brackets_only'] ? true : false,
|
@params['brackets_only'] ? true : false,
|
||||||
@params['count_pages'] ? true : false,
|
@params['count_pages'] ? true : false,
|
||||||
@params['allow_uploads'] ? true : false
|
@params['allow_uploads'] ? true : false
|
||||||
)
|
)
|
||||||
redirect_show('HomePage', @params['address'])
|
redirect_show('HomePage', @params['address'])
|
||||||
else
|
else
|
||||||
redirect_show('HomePage')
|
redirect_show('HomePage')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Within a single page --------------------------------------------------------
|
# Within a single page --------------------------------------------------------
|
||||||
|
|
||||||
def cancel_edit
|
def cancel_edit
|
||||||
@page.unlock
|
@page.unlock
|
||||||
redirect_show
|
redirect_show
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
if @page.nil?
|
if @page.nil?
|
||||||
redirect_to :action => 'index'
|
redirect_to :action => 'index'
|
||||||
elsif @page.locked?(Time.now) and not @params['break_lock']
|
elsif @page.locked?(Time.now) and not @params['break_lock']
|
||||||
redirect_to :web => @web_name, :action => 'locked', :id => @page_name
|
redirect_to :web => @web_name, :action => 'locked', :id => @page_name
|
||||||
else
|
else
|
||||||
@page.lock(Time.now, @author)
|
@page.lock(Time.now, @author)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def locked
|
def locked
|
||||||
# to template
|
# to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
# to template
|
# to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def pdf
|
def pdf
|
||||||
page = wiki.read_page(@web_name, @page_name)
|
page = wiki.read_page(@web_name, @page_name)
|
||||||
safe_page_name = @page.name.gsub(/\W/, '')
|
safe_page_name = @page.name.gsub(/\W/, '')
|
||||||
file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}"
|
file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}"
|
||||||
file_path = @wiki.storage_path + file_name
|
file_path = @wiki.storage_path + file_name
|
||||||
|
|
||||||
export_page_to_tex("#{file_path}.tex") unless FileTest.exists?("#{file_path}.tex")
|
export_page_to_tex("#{file_path}.tex") unless FileTest.exists?("#{file_path}.tex")
|
||||||
# NB: this is _very_ slow
|
# NB: this is _very_ slow
|
||||||
convert_tex_to_pdf("#{file_path}.tex")
|
convert_tex_to_pdf("#{file_path}.tex")
|
||||||
send_file "#{file_path}.pdf"
|
send_file "#{file_path}.pdf"
|
||||||
end
|
end
|
||||||
|
|
||||||
def print
|
def print
|
||||||
# to template
|
# to template
|
||||||
end
|
end
|
||||||
|
|
||||||
def published
|
def published
|
||||||
if @web.published
|
if @web.published
|
||||||
@page = wiki.read_page(@web_name, @page_name || 'HomePage')
|
@page = wiki.read_page(@web_name, @page_name || 'HomePage')
|
||||||
else
|
else
|
||||||
redirect_show('HomePage')
|
redirect_show('HomePage')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def revision
|
def revision
|
||||||
get_page_and_revision
|
get_page_and_revision
|
||||||
end
|
end
|
||||||
|
|
||||||
def rollback
|
def rollback
|
||||||
get_page_and_revision
|
get_page_and_revision
|
||||||
end
|
end
|
||||||
|
|
||||||
def save
|
def save
|
||||||
redirect_to :action => 'index' if @page_name.nil?
|
redirect_to :action => 'index' if @page_name.nil?
|
||||||
cookies['author'] = @params['author']
|
cookies['author'] = @params['author']
|
||||||
|
|
||||||
begin
|
begin
|
||||||
page = @web.pages[@page_name]
|
page = @web.pages[@page_name]
|
||||||
if @web.pages[@page_name]
|
if @web.pages[@page_name]
|
||||||
wiki.revise_page(
|
wiki.revise_page(
|
||||||
@web_name, @page_name, @params['content'], Time.now,
|
@web_name, @page_name, @params['content'], Time.now,
|
||||||
Author.new(@params['author'], remote_ip)
|
Author.new(@params['author'], remote_ip)
|
||||||
)
|
)
|
||||||
page.unlock
|
page.unlock
|
||||||
else
|
else
|
||||||
wiki.write_page(
|
wiki.write_page(
|
||||||
@web_name, @page_name, @params['content'], Time.now,
|
@web_name, @page_name, @params['content'], Time.now,
|
||||||
Author.new(@params['author'], remote_ip)
|
Author.new(@params['author'], remote_ip)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
redirect_show(@page_name)
|
redirect_show(@page_name)
|
||||||
rescue Instiki::ValidationError => e
|
rescue Instiki::ValidationError => e
|
||||||
page.unlock if defined? page
|
page.unlock if defined? page
|
||||||
flash[:error] = e
|
flash[:error] = e
|
||||||
return_to_last_remembered
|
return_to_last_remembered
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
if @page
|
if @page
|
||||||
begin
|
begin
|
||||||
render_action 'page'
|
render_action 'page'
|
||||||
# TODO this rescue should differentiate between errors due to rendering and errors in
|
# TODO this rescue should differentiate between errors due to rendering and errors in
|
||||||
# the application itself (for application errors, it's better not to rescue the error at all)
|
# the application itself (for application errors, it's better not to rescue the error at all)
|
||||||
rescue => e
|
rescue => e
|
||||||
logger.error e
|
logger.error e
|
||||||
if in_a_web?
|
if in_a_web?
|
||||||
redirect_to :web => @web_name, :action => 'edit',
|
redirect_to :web => @web_name, :action => 'edit',
|
||||||
:action_suffix => "#{CGI.escape(@page_name)}?msg=#{CGI.escape(e.message)}"
|
:action_suffix => "#{CGI.escape(@page_name)}?msg=#{CGI.escape(e.message)}"
|
||||||
else
|
else
|
||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
redirect_to :web => @web_name, :action => 'new', :id => CGI.escape(@page_name)
|
redirect_to :web => @web_name, :action => 'new', :id => CGI.escape(@page_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def tex
|
def tex
|
||||||
@tex_content = RedClothForTex.new(@page.content).to_tex
|
@tex_content = RedClothForTex.new(@page.content).to_tex
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def convert_tex_to_pdf(tex_path)
|
def convert_tex_to_pdf(tex_path)
|
||||||
# TODO remove earlier PDF files with the same prefix
|
# TODO remove earlier PDF files with the same prefix
|
||||||
# TODO handle gracefully situation where pdflatex is not available
|
# TODO handle gracefully situation where pdflatex is not available
|
||||||
logger.info `pdflatex --interaction=nonstopmode --output-directory #{File.dirname(tex_path)} #{File.basename(tex_path)}`
|
logger.info `pdflatex --interaction=nonstopmode --output-directory #{File.dirname(tex_path)} #{File.basename(tex_path)}`
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_page_to_tex(file_path)
|
def export_page_to_tex(file_path)
|
||||||
tex
|
tex
|
||||||
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex')) }
|
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex')) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_pages_as_zip(file_type, &block)
|
def export_pages_as_zip(file_type, &block)
|
||||||
|
|
||||||
file_prefix = "#{@web.address}-#{file_type}-"
|
file_prefix = "#{@web.address}-#{file_type}-"
|
||||||
timestamp = @web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')
|
timestamp = @web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')
|
||||||
file_path = @wiki.storage_path + file_prefix + timestamp + '.zip'
|
file_path = @wiki.storage_path + file_prefix + timestamp + '.zip'
|
||||||
tmp_path = "#{file_path}.tmp"
|
tmp_path = "#{file_path}.tmp"
|
||||||
|
|
||||||
Zip::ZipOutputStream.open(tmp_path) do |zip_out|
|
Zip::ZipOutputStream.open(tmp_path) do |zip_out|
|
||||||
@web.select.by_name.each do |page|
|
@web.select.by_name.each do |page|
|
||||||
zip_out.put_next_entry("#{page.name}.#{file_type}")
|
zip_out.put_next_entry("#{page.name}.#{file_type}")
|
||||||
zip_out.puts(block.call(page))
|
zip_out.puts(block.call(page))
|
||||||
end
|
end
|
||||||
# add an index file, if exporting to HTML
|
# add an index file, if exporting to HTML
|
||||||
if file_type.to_s.downcase == 'html'
|
if file_type.to_s.downcase == 'html'
|
||||||
zip_out.put_next_entry 'index.html'
|
zip_out.put_next_entry 'index.html'
|
||||||
zip_out.puts <<-EOL
|
zip_out.puts <<-EOL
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=HomePage.#{file_type}">
|
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=HomePage.#{file_type}">
|
||||||
</head>
|
</head>
|
||||||
</html>
|
</html>
|
||||||
EOL
|
EOL
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
FileUtils.rm_rf(Dir[@wiki.storage_path + file_prefix + '*.zip'])
|
FileUtils.rm_rf(Dir[@wiki.storage_path + file_prefix + '*.zip'])
|
||||||
FileUtils.mv(tmp_path, file_path)
|
FileUtils.mv(tmp_path, file_path)
|
||||||
send_file file_path
|
send_file file_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def export_web_to_tex(file_path)
|
def export_web_to_tex(file_path)
|
||||||
@tex_content = table_of_contents(@web.pages['HomePage'].content.dup, render_tex_web)
|
@tex_content = table_of_contents(@web.pages['HomePage'].content.dup, render_tex_web)
|
||||||
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
|
File.open(file_path, 'w') { |f| f.write(render_to_string('wiki/tex_web')) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_page_and_revision
|
def get_page_and_revision
|
||||||
@revision = @page.revisions[@params['rev'].to_i]
|
@revision = @page.revisions[@params['rev'].to_i]
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_category
|
def parse_category
|
||||||
@categories = @web.categories
|
@categories = @web.categories
|
||||||
@category = @params['category']
|
@category = @params['category']
|
||||||
if @categories.include?(@category)
|
if @categories.include?(@category)
|
||||||
@pages_in_category = @web.select { |page| page.in_category?(@category) }
|
@pages_in_category = @web.select { |page| page.in_category?(@category) }
|
||||||
@set_name = "category '#{@category}'"
|
@set_name = "category '#{@category}'"
|
||||||
else
|
else
|
||||||
@pages_in_category = PageSet.new(@web).by_name
|
@pages_in_category = PageSet.new(@web).by_name
|
||||||
@set_name = 'the web'
|
@set_name = 'the web'
|
||||||
end
|
end
|
||||||
@category_links = @categories.map { |c|
|
@category_links = @categories.map { |c|
|
||||||
if @category == c
|
if @category == c
|
||||||
%{<span class="selected">#{c}</span>}
|
%{<span class="selected">#{c}</span>}
|
||||||
else
|
else
|
||||||
%{<a href="?category=#{c}">#{c}</a>}
|
%{<a href="?category=#{c}">#{c}</a>}
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def password_check(password)
|
def password_check(password)
|
||||||
if password == @web.password
|
if password == @web.password
|
||||||
cookies['web_address'] = password
|
cookies['web_address'] = password
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirect_show(page_name = @page_name, web = @web_name)
|
def redirect_show(page_name = @page_name, web = @web_name)
|
||||||
redirect_to :web => web, :action => 'show', :id => CGI.escape(page_name)
|
redirect_to :web => web, :action => 'show', :id => CGI.escape(page_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remote_ip
|
def remote_ip
|
||||||
ip = @request.remote_ip
|
ip = @request.remote_ip
|
||||||
logger.info(ip)
|
logger.info(ip)
|
||||||
ip
|
ip
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_rss(hide_description = false)
|
def render_rss(hide_description = false)
|
||||||
@pages_by_revision = @web.select.by_revision.first(15)
|
@pages_by_revision = @web.select.by_revision.first(15)
|
||||||
@hide_description = hide_description
|
@hide_description = hide_description
|
||||||
@response.headers['Content-Type'] = 'text/xml'
|
@response.headers['Content-Type'] = 'text/xml'
|
||||||
render 'wiki/rss_feed'
|
render 'wiki/rss_feed'
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_tex_web
|
def render_tex_web
|
||||||
@web.select.by_name.inject({}) do |tex_web, page|
|
@web.select.by_name.inject({}) do |tex_web, page|
|
||||||
tex_web[page.name] = RedClothForTex.new(page.content).to_tex
|
tex_web[page.name] = RedClothForTex.new(page.content).to_tex
|
||||||
tex_web
|
tex_web
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_to_string(template_name)
|
def render_to_string(template_name)
|
||||||
add_variables_to_assigns
|
add_variables_to_assigns
|
||||||
render template_name
|
render template_name
|
||||||
@performed_render = false
|
@performed_render = false
|
||||||
@template.render_file(template_name)
|
@template.render_file(template_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def truncate(text, length = 30, truncate_string = '...')
|
def truncate(text, length = 30, truncate_string = '...')
|
||||||
if text.length > length then text[0..(length - 3)] + truncate_string else text end
|
if text.length > length then text[0..(length - 3)] + truncate_string else text end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
6
app/models/author.rb
Executable file → Normal file
6
app/models/author.rb
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
||||||
class Author < String
|
class Author < String
|
||||||
attr_accessor :ip
|
attr_accessor :ip
|
||||||
def initialize(name, ip) @ip = ip; super(name) end
|
def initialize(name, ip) @ip = ip; super(name) end
|
||||||
end
|
end
|
70
app/models/chunks/category.rb
Executable file → Normal file
70
app/models/chunks/category.rb
Executable file → Normal file
|
@ -1,35 +1,35 @@
|
||||||
require 'chunks/chunk'
|
require 'chunks/chunk'
|
||||||
|
|
||||||
# The category chunk looks for "category: news" on a line by
|
# The category chunk looks for "category: news" on a line by
|
||||||
# itself and parses the terms after the ':' as categories.
|
# itself and parses the terms after the ':' as categories.
|
||||||
# Other classes can search for Category chunks within
|
# Other classes can search for Category chunks within
|
||||||
# rendered content to find out what categories this page
|
# rendered content to find out what categories this page
|
||||||
# should be in.
|
# should be in.
|
||||||
#
|
#
|
||||||
# Category lines can be hidden using ':category: news', for example
|
# Category lines can be hidden using ':category: news', for example
|
||||||
class Category < Chunk::Abstract
|
class Category < Chunk::Abstract
|
||||||
def self.pattern() return /^(:)?category\s*:(.*)$/i end
|
def self.pattern() return /^(:)?category\s*:(.*)$/i end
|
||||||
|
|
||||||
attr_reader :hidden, :list
|
attr_reader :hidden, :list
|
||||||
|
|
||||||
def initialize(match_data)
|
def initialize(match_data)
|
||||||
super(match_data)
|
super(match_data)
|
||||||
@hidden = match_data[1]
|
@hidden = match_data[1]
|
||||||
@list = match_data[2].split(',').map { |c| c.strip }
|
@list = match_data[2].split(',').map { |c| c.strip }
|
||||||
end
|
end
|
||||||
|
|
||||||
# If the chunk is hidden, erase the mask and return this chunk
|
# If the chunk is hidden, erase the mask and return this chunk
|
||||||
# otherwise, surround it with a 'div' block.
|
# otherwise, surround it with a 'div' block.
|
||||||
def unmask(content)
|
def unmask(content)
|
||||||
return '' if hidden
|
return '' if hidden
|
||||||
|
|
||||||
category_urls = @list.map{|category| url(category) }.join(', ')
|
category_urls = @list.map{|category| url(category) }.join(', ')
|
||||||
replacement = '<div class="property"> category: ' + category_urls + '</div>'
|
replacement = '<div class="property"> category: ' + category_urls + '</div>'
|
||||||
self if content.sub!(mask(content), replacement)
|
self if content.sub!(mask(content), replacement)
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO move presentation of page metadata to controller/view
|
# TODO move presentation of page metadata to controller/view
|
||||||
def url(category)
|
def url(category)
|
||||||
%{<a class="category_link" href="../list/?category=#{category}">#{category}</a>}
|
%{<a class="category_link" href="../list/?category=#{category}">#{category}</a>}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
80
app/models/chunks/chunk.rb
Executable file → Normal file
80
app/models/chunks/chunk.rb
Executable file → Normal file
|
@ -1,40 +1,40 @@
|
||||||
require 'digest/md5'
|
require 'digest/md5'
|
||||||
require 'uri/common'
|
require 'uri/common'
|
||||||
|
|
||||||
# A chunk is a pattern of text that can be protected
|
# A chunk is a pattern of text that can be protected
|
||||||
# and interrogated by a renderer. Each Chunk class has a
|
# and interrogated by a renderer. Each Chunk class has a
|
||||||
# +pattern+ that states what sort of text it matches.
|
# +pattern+ that states what sort of text it matches.
|
||||||
# Chunks are initalized by passing in the result of a
|
# Chunks are initalized by passing in the result of a
|
||||||
# match by its pattern.
|
# match by its pattern.
|
||||||
module Chunk
|
module Chunk
|
||||||
class Abstract
|
class Abstract
|
||||||
attr_reader :text
|
attr_reader :text
|
||||||
|
|
||||||
def initialize(match_data) @text = match_data[0] end
|
def initialize(match_data) @text = match_data[0] end
|
||||||
|
|
||||||
# Find all the chunks of the given type in content
|
# Find all the chunks of the given type in content
|
||||||
# Each time the pattern is matched, create a new
|
# Each time the pattern is matched, create a new
|
||||||
# chunk for it, and replace the occurance of the chunk
|
# chunk for it, and replace the occurance of the chunk
|
||||||
# in this content with its mask.
|
# in this content with its mask.
|
||||||
def self.apply_to(content)
|
def self.apply_to(content)
|
||||||
content.gsub!( self.pattern ) do |match|
|
content.gsub!( self.pattern ) do |match|
|
||||||
new_chunk = self.new($~)
|
new_chunk = self.new($~)
|
||||||
content.chunks << new_chunk
|
content.chunks << new_chunk
|
||||||
new_chunk.mask(content)
|
new_chunk.mask(content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def mask(content)
|
def mask(content)
|
||||||
"chunk#{self.object_id}#{self.class.to_s.delete(':').downcase}chunk"
|
"chunk#{self.object_id}#{self.class.to_s.delete(':').downcase}chunk"
|
||||||
end
|
end
|
||||||
|
|
||||||
def revert(content)
|
def revert(content)
|
||||||
content.sub!( Regexp.new(mask(content)), text )
|
content.sub!( Regexp.new(mask(content)), text )
|
||||||
end
|
end
|
||||||
|
|
||||||
def unmask(content)
|
def unmask(content)
|
||||||
self if revert(content)
|
self if revert(content)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
76
app/models/chunks/engines.rb
Executable file → Normal file
76
app/models/chunks/engines.rb
Executable file → Normal file
|
@ -1,38 +1,38 @@
|
||||||
$: << File.dirname(__FILE__) + "../../libraries"
|
$: << File.dirname(__FILE__) + "../../libraries"
|
||||||
|
|
||||||
require 'redcloth'
|
require 'redcloth'
|
||||||
require 'bluecloth'
|
require 'bluecloth'
|
||||||
require 'rdocsupport'
|
require 'rdocsupport'
|
||||||
require 'chunks/chunk'
|
require 'chunks/chunk'
|
||||||
|
|
||||||
# The markup engines are Chunks that call the one of RedCloth, BlueCloth
|
# The markup engines are Chunks that call the one of RedCloth, BlueCloth
|
||||||
# or RDoc to convert text. This markup occurs when the chunk is required
|
# or RDoc to convert text. This markup occurs when the chunk is required
|
||||||
# to mask itself.
|
# to mask itself.
|
||||||
module Engines
|
module Engines
|
||||||
class Textile < Chunk::Abstract
|
class Textile < Chunk::Abstract
|
||||||
def self.pattern() /^(.*)$/m end
|
def self.pattern() /^(.*)$/m end
|
||||||
def mask(content)
|
def mask(content)
|
||||||
RedCloth.new(text,content.options[:engine_opts]).to_html
|
RedCloth.new(text,content.options[:engine_opts]).to_html
|
||||||
end
|
end
|
||||||
def unmask(content) self end
|
def unmask(content) self end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Markdown < Chunk::Abstract
|
class Markdown < Chunk::Abstract
|
||||||
def self.pattern() /^(.*)$/m end
|
def self.pattern() /^(.*)$/m end
|
||||||
def mask(content)
|
def mask(content)
|
||||||
BlueCloth.new(text,content.options[:engine_opts]).to_html
|
BlueCloth.new(text,content.options[:engine_opts]).to_html
|
||||||
end
|
end
|
||||||
def unmask(content) self end
|
def unmask(content) self end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RDoc < Chunk::Abstract
|
class RDoc < Chunk::Abstract
|
||||||
def self.pattern() /^(.*)$/m end
|
def self.pattern() /^(.*)$/m end
|
||||||
def mask(content)
|
def mask(content)
|
||||||
RDocSupport::RDocFormatter.new(text).to_html
|
RDocSupport::RDocFormatter.new(text).to_html
|
||||||
end
|
end
|
||||||
def unmask(content) self end
|
def unmask(content) self end
|
||||||
end
|
end
|
||||||
|
|
||||||
MAP = { :textile => Textile, :markdown => Markdown, :rdoc => RDoc }
|
MAP = { :textile => Textile, :markdown => Markdown, :rdoc => RDoc }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
58
app/models/chunks/include.rb
Executable file → Normal file
58
app/models/chunks/include.rb
Executable file → Normal file
|
@ -1,29 +1,29 @@
|
||||||
require 'chunks/wiki'
|
require 'chunks/wiki'
|
||||||
|
|
||||||
# Includes the contents of another page for rendering.
|
# Includes the contents of another page for rendering.
|
||||||
# The include command looks like this: "[[!include PageName]]".
|
# The include command looks like this: "[[!include PageName]]".
|
||||||
# It is a WikiLink since it refers to another page (PageName)
|
# It is a WikiLink since it refers to another page (PageName)
|
||||||
# and the wiki content using this command must be notified
|
# and the wiki content using this command must be notified
|
||||||
# of changes to that page.
|
# of changes to that page.
|
||||||
# If the included page could not be found, a warning is displayed.
|
# If the included page could not be found, a warning is displayed.
|
||||||
class Include < WikiChunk::WikiLink
|
class Include < WikiChunk::WikiLink
|
||||||
def self.pattern() /^\[\[!include(.*)\]\]\s*$/i end
|
def self.pattern() /^\[\[!include(.*)\]\]\s*$/i end
|
||||||
|
|
||||||
attr_reader :page_name
|
attr_reader :page_name
|
||||||
|
|
||||||
def initialize(match_data)
|
def initialize(match_data)
|
||||||
super(match_data)
|
super(match_data)
|
||||||
@page_name = match_data[1].strip
|
@page_name = match_data[1].strip
|
||||||
end
|
end
|
||||||
|
|
||||||
# This replaces the [[!include PageName]] text with
|
# This replaces the [[!include PageName]] text with
|
||||||
# the contents of PageName if it exists. Otherwise
|
# the contents of PageName if it exists. Otherwise
|
||||||
# a warning is displayed.
|
# a warning is displayed.
|
||||||
def mask(content)
|
def mask(content)
|
||||||
page = content.web.pages[page_name]
|
page = content.web.pages[page_name]
|
||||||
(page ? page.content : "<em>Could not include #{page_name}</em>")
|
(page ? page.content : "<em>Could not include #{page_name}</em>")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Keep this chunk regardless of what happens.
|
# Keep this chunk regardless of what happens.
|
||||||
def unmask(content) self end
|
def unmask(content) self end
|
||||||
end
|
end
|
||||||
|
|
38
app/models/chunks/literal.rb
Executable file → Normal file
38
app/models/chunks/literal.rb
Executable file → Normal file
|
@ -1,19 +1,19 @@
|
||||||
require 'chunks/chunk'
|
require 'chunks/chunk'
|
||||||
|
|
||||||
# These are basic chunks that have a pattern and can be protected.
|
# These are basic chunks that have a pattern and can be protected.
|
||||||
# They are used by rendering process to prevent wiki rendering
|
# They are used by rendering process to prevent wiki rendering
|
||||||
# occuring within literal areas such as <code> and <pre> blocks
|
# occuring within literal areas such as <code> and <pre> blocks
|
||||||
# and within HTML tags.
|
# and within HTML tags.
|
||||||
module Literal
|
module Literal
|
||||||
# A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
|
# A literal chunk that protects 'code' and 'pre' tags from wiki rendering.
|
||||||
class Pre < Chunk::Abstract
|
class Pre < Chunk::Abstract
|
||||||
PRE_BLOCKS = "a|pre|code"
|
PRE_BLOCKS = "a|pre|code"
|
||||||
def self.pattern() Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?</\1>', Regexp::MULTILINE) end
|
def self.pattern() Regexp.new('<('+PRE_BLOCKS+')\b[^>]*?>.*?</\1>', Regexp::MULTILINE) end
|
||||||
end
|
end
|
||||||
|
|
||||||
# A literal chunk that protects HTML tags from wiki rendering.
|
# A literal chunk that protects HTML tags from wiki rendering.
|
||||||
class Tags < Chunk::Abstract
|
class Tags < Chunk::Abstract
|
||||||
TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
|
TAGS = "a|img|em|strong|div|span|table|td|th|ul|ol|li|dl|dt|dd"
|
||||||
def self.pattern() Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE) end
|
def self.pattern() Regexp.new('<(?:'+TAGS+')[^>]*?>', Regexp::MULTILINE) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
62
app/models/chunks/nowiki.rb
Executable file → Normal file
62
app/models/chunks/nowiki.rb
Executable file → Normal file
|
@ -1,31 +1,31 @@
|
||||||
require 'chunks/chunk'
|
require 'chunks/chunk'
|
||||||
|
|
||||||
# This chunks allows certain parts of a wiki page to be hidden from the
|
# This chunks allows certain parts of a wiki page to be hidden from the
|
||||||
# rest of the rendering pipeline. It should be run at the beginning
|
# rest of the rendering pipeline. It should be run at the beginning
|
||||||
# of the pipeline in `wiki_content.rb`.
|
# of the pipeline in `wiki_content.rb`.
|
||||||
#
|
#
|
||||||
# An example use of this chunk is to markup double brackets or
|
# An example use of this chunk is to markup double brackets or
|
||||||
# auto URI links:
|
# auto URI links:
|
||||||
# <nowiki>Here are [[double brackets]] and a URI: www.uri.org</nowiki>
|
# <nowiki>Here are [[double brackets]] and a URI: www.uri.org</nowiki>
|
||||||
#
|
#
|
||||||
# The contents of the chunks will not be processed by any other chunk
|
# The contents of the chunks will not be processed by any other chunk
|
||||||
# so the `www.uri.org` and the double brackets will appear verbatim.
|
# so the `www.uri.org` and the double brackets will appear verbatim.
|
||||||
#
|
#
|
||||||
# Author: Mark Reid <mark at threewordslong dot com>
|
# Author: Mark Reid <mark at threewordslong dot com>
|
||||||
# Created: 8th June 2004
|
# Created: 8th June 2004
|
||||||
class NoWiki < Chunk::Abstract
|
class NoWiki < Chunk::Abstract
|
||||||
|
|
||||||
def self.pattern() Regexp.new('<nowiki>(.*?)</nowiki>') end
|
def self.pattern() Regexp.new('<nowiki>(.*?)</nowiki>') end
|
||||||
|
|
||||||
attr_reader :plain_text
|
attr_reader :plain_text
|
||||||
|
|
||||||
def initialize(match_data)
|
def initialize(match_data)
|
||||||
super(match_data)
|
super(match_data)
|
||||||
@plain_text = match_data[1]
|
@plain_text = match_data[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
# The nowiki content is not unmasked. This means the chunk will be reverted
|
# The nowiki content is not unmasked. This means the chunk will be reverted
|
||||||
# using the plain text.
|
# using the plain text.
|
||||||
def unmask(content) nil end
|
def unmask(content) nil end
|
||||||
def revert(content) content.sub!(mask(content), plain_text) end
|
def revert(content) content.sub!(mask(content), plain_text) end
|
||||||
end
|
end
|
||||||
|
|
36
app/models/chunks/test.rb
Executable file → Normal file
36
app/models/chunks/test.rb
Executable file → Normal file
|
@ -1,18 +1,18 @@
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
|
|
||||||
class ChunkTest < Test::Unit::TestCase
|
class ChunkTest < Test::Unit::TestCase
|
||||||
|
|
||||||
# Asserts a number of tests for the given type and text.
|
# Asserts a number of tests for the given type and text.
|
||||||
def match(type, test_text, expected)
|
def match(type, test_text, expected)
|
||||||
pattern = type.pattern
|
pattern = type.pattern
|
||||||
assert_match(pattern, test_text)
|
assert_match(pattern, test_text)
|
||||||
pattern =~ test_text # Previous assertion guarantees match
|
pattern =~ test_text # Previous assertion guarantees match
|
||||||
chunk = type.new($~)
|
chunk = type.new($~)
|
||||||
|
|
||||||
# Test if requested parts are correct.
|
# Test if requested parts are correct.
|
||||||
for method_sym, value in expected do
|
for method_sym, value in expected do
|
||||||
assert_respond_to(chunk, method_sym)
|
assert_respond_to(chunk, method_sym)
|
||||||
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
assert_equal(value, chunk.method(method_sym).call, "Checking value of '#{method_sym}'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
358
app/models/chunks/uri.rb
Executable file → Normal file
358
app/models/chunks/uri.rb
Executable file → Normal file
|
@ -1,179 +1,179 @@
|
||||||
require 'chunks/chunk'
|
require 'chunks/chunk'
|
||||||
|
|
||||||
# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
|
# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI modules.
|
||||||
# It parses out a variety of fields that could be used by renderers to format
|
# It parses out a variety of fields that could be used by renderers to format
|
||||||
# the links in various ways (shortening domain names, hiding email addresses)
|
# the links in various ways (shortening domain names, hiding email addresses)
|
||||||
# It matches email addresses and host.com.au domains without schemes (http://)
|
# It matches email addresses and host.com.au domains without schemes (http://)
|
||||||
# but adds these on as required.
|
# but adds these on as required.
|
||||||
#
|
#
|
||||||
# The heuristic used to match a URI is designed to err on the side of caution.
|
# The heuristic used to match a URI is designed to err on the side of caution.
|
||||||
# That is, it is more likely to not autolink a URI than it is to accidently
|
# That is, it is more likely to not autolink a URI than it is to accidently
|
||||||
# autolink something that is not a URI. The reason behind this is it is easier
|
# autolink something that is not a URI. The reason behind this is it is easier
|
||||||
# to force a URI link by prefixing 'http://' to it than it is to escape and
|
# to force a URI link by prefixing 'http://' to it than it is to escape and
|
||||||
# incorrectly marked up non-URI.
|
# incorrectly marked up non-URI.
|
||||||
#
|
#
|
||||||
# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
|
# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name suffixes.
|
||||||
# The generic names are from www.bnoack.com/data/countrycode2.html)
|
# The generic names are from www.bnoack.com/data/countrycode2.html)
|
||||||
# [iso3166]: http://geotags.com/iso3166/
|
# [iso3166]: http://geotags.com/iso3166/
|
||||||
class URIChunk < Chunk::Abstract
|
class URIChunk < Chunk::Abstract
|
||||||
include URI::REGEXP::PATTERN
|
include URI::REGEXP::PATTERN
|
||||||
|
|
||||||
# this condition is to get rid of pesky warnings in tests
|
# this condition is to get rid of pesky warnings in tests
|
||||||
unless defined? URIChunk::INTERNET_URI_REGEXP
|
unless defined? URIChunk::INTERNET_URI_REGEXP
|
||||||
|
|
||||||
GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
|
GENERIC = '(?:aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org)'
|
||||||
COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
|
COUNTRY = '(?:au|at|be|ca|ch|de|dk|fr|hk|in|ir|it|jp|nl|no|pt|ru|se|sw|tv|tw|uk|us)'
|
||||||
|
|
||||||
# These are needed otherwise HOST will match almost anything
|
# These are needed otherwise HOST will match almost anything
|
||||||
TLDS = "(?:#{GENERIC}|#{COUNTRY})"
|
TLDS = "(?:#{GENERIC}|#{COUNTRY})"
|
||||||
|
|
||||||
# Redefine USERINFO so that it must have non-zero length
|
# Redefine USERINFO so that it must have non-zero length
|
||||||
USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
|
USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})+"
|
||||||
|
|
||||||
# unreserved_no_ending = alphanum | mark, but URI_ENDING [)!] excluded
|
# unreserved_no_ending = alphanum | mark, but URI_ENDING [)!] excluded
|
||||||
UNRESERVED_NO_ENDING = "-_.~*'(#{ALNUM}"
|
UNRESERVED_NO_ENDING = "-_.~*'(#{ALNUM}"
|
||||||
|
|
||||||
# this ensures that query or fragment do not end with URI_ENDING
|
# this ensures that query or fragment do not end with URI_ENDING
|
||||||
# and enable us to use a much simpler self.pattern Regexp
|
# and enable us to use a much simpler self.pattern Regexp
|
||||||
|
|
||||||
# uric_no_ending = reserved | unreserved_no_ending | escaped
|
# uric_no_ending = reserved | unreserved_no_ending | escaped
|
||||||
URIC_NO_ENDING = "(?:[#{UNRESERVED_NO_ENDING}#{RESERVED}]|#{ESCAPED})"
|
URIC_NO_ENDING = "(?:[#{UNRESERVED_NO_ENDING}#{RESERVED}]|#{ESCAPED})"
|
||||||
# query = *uric
|
# query = *uric
|
||||||
QUERY = "#{URIC_NO_ENDING}*"
|
QUERY = "#{URIC_NO_ENDING}*"
|
||||||
# fragment = *uric
|
# fragment = *uric
|
||||||
FRAGMENT = "#{URIC_NO_ENDING}*"
|
FRAGMENT = "#{URIC_NO_ENDING}*"
|
||||||
|
|
||||||
# DOMLABEL is defined in the ruby uri library, TLDS is defined above
|
# DOMLABEL is defined in the ruby uri library, TLDS is defined above
|
||||||
INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
|
INTERNET_HOSTNAME = "(?:#{DOMLABEL}\\.)+#{TLDS}"
|
||||||
|
|
||||||
# Correct a typo bug in ruby 1.8.x lib/uri/common.rb
|
# Correct a typo bug in ruby 1.8.x lib/uri/common.rb
|
||||||
PORT = '\\d*'
|
PORT = '\\d*'
|
||||||
|
|
||||||
INTERNET_URI =
|
INTERNET_URI =
|
||||||
"(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1)
|
"(?:(#{SCHEME}):/{0,2})?" + # Optional scheme: (\1)
|
||||||
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
|
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
|
||||||
"(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3)
|
"(#{INTERNET_HOSTNAME})" + # Mandatory hostname (\3)
|
||||||
"(?::(#{PORT}))?" + # Optional :port (\4)
|
"(?::(#{PORT}))?" + # Optional :port (\4)
|
||||||
"(#{ABS_PATH})?" + # Optional absolute path (\5)
|
"(#{ABS_PATH})?" + # Optional absolute path (\5)
|
||||||
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
|
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
|
||||||
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7)
|
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7)
|
||||||
|
|
||||||
TEXTILE_SYNTAX_PREFIX = '(!)?'
|
TEXTILE_SYNTAX_PREFIX = '(!)?'
|
||||||
|
|
||||||
INTERNET_URI_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + INTERNET_URI, Regexp::EXTENDED, 'N')
|
INTERNET_URI_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + INTERNET_URI, Regexp::EXTENDED, 'N')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def URIChunk.pattern
|
def URIChunk.pattern
|
||||||
INTERNET_URI_REGEXP
|
INTERNET_URI_REGEXP
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :user, :host, :port, :path, :query, :fragment, :link_text
|
attr_reader :user, :host, :port, :path, :query, :fragment, :link_text
|
||||||
|
|
||||||
def self.apply_to(content)
|
def self.apply_to(content)
|
||||||
content.gsub!( self.pattern ) do |matched_text|
|
content.gsub!( self.pattern ) do |matched_text|
|
||||||
chunk = self.new($~)
|
chunk = self.new($~)
|
||||||
if chunk.textile_url? or chunk.textile_image?
|
if chunk.textile_url? or chunk.textile_image?
|
||||||
# do not substitute
|
# do not substitute
|
||||||
matched_text
|
matched_text
|
||||||
else
|
else
|
||||||
content.chunks << chunk
|
content.chunks << chunk
|
||||||
chunk.mask(content)
|
chunk.mask(content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(match_data)
|
def initialize(match_data)
|
||||||
super(match_data)
|
super(match_data)
|
||||||
@link_text = match_data[0]
|
@link_text = match_data[0]
|
||||||
@textile_prefix, @original_scheme, @user, @host, @port, @path, @query, @fragment =
|
@textile_prefix, @original_scheme, @user, @host, @port, @path, @query, @fragment =
|
||||||
match_data[1..-1]
|
match_data[1..-1]
|
||||||
treat_trailing_character
|
treat_trailing_character
|
||||||
end
|
end
|
||||||
|
|
||||||
def textile_url?
|
def textile_url?
|
||||||
@textile_prefix == '":'
|
@textile_prefix == '":'
|
||||||
end
|
end
|
||||||
|
|
||||||
def textile_image?
|
def textile_image?
|
||||||
@textile_prefix == '!' and @trailing_punctuation == '!'
|
@textile_prefix == '!' and @trailing_punctuation == '!'
|
||||||
end
|
end
|
||||||
|
|
||||||
def treat_trailing_character
|
def treat_trailing_character
|
||||||
# If the last character matched by URI pattern is in ! or ), this may be part of the markup,
|
# If the last character matched by URI pattern is in ! or ), this may be part of the markup,
|
||||||
# not a URL. We should handle it as such. It is possible to do it by a regexp, but
|
# not a URL. We should handle it as such. It is possible to do it by a regexp, but
|
||||||
# much easier to do programmatically
|
# much easier to do programmatically
|
||||||
last_char = @link_text[-1..-1]
|
last_char = @link_text[-1..-1]
|
||||||
if last_char == ')' or last_char == '!'
|
if last_char == ')' or last_char == '!'
|
||||||
@trailing_punctuation = last_char
|
@trailing_punctuation = last_char
|
||||||
@link_text.chop!
|
@link_text.chop!
|
||||||
[@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop!
|
[@original_scheme, @user, @host, @port, @path, @query, @fragment].compact.last.chop!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# If the text should be escaped then don't keep this chunk.
|
# If the text should be escaped then don't keep this chunk.
|
||||||
# Otherwise only keep this chunk if it was substituted back into the
|
# Otherwise only keep this chunk if it was substituted back into the
|
||||||
# content.
|
# content.
|
||||||
def unmask(content)
|
def unmask(content)
|
||||||
return nil if escaped_text
|
return nil if escaped_text
|
||||||
return self if content.sub!(mask(content), "<a href=\"#{uri}\">#{link_text}</a>")
|
return self if content.sub!(mask(content), "<a href=\"#{uri}\">#{link_text}</a>")
|
||||||
end
|
end
|
||||||
|
|
||||||
# If there is no hostname in the URI, do not render it
|
# If there is no hostname in the URI, do not render it
|
||||||
# It's probably only contains the scheme, eg 'something:'
|
# It's probably only contains the scheme, eg 'something:'
|
||||||
def escaped_text() ( host.nil? ? @uri : nil ) end
|
def escaped_text() ( host.nil? ? @uri : nil ) end
|
||||||
|
|
||||||
def scheme
|
def scheme
|
||||||
@original_scheme or (@user ? 'mailto' : 'http')
|
@original_scheme or (@user ? 'mailto' : 'http')
|
||||||
end
|
end
|
||||||
|
|
||||||
def scheme_delimiter
|
def scheme_delimiter
|
||||||
scheme == 'mailto' ? ':' : '://'
|
scheme == 'mailto' ? ':' : '://'
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_delimiter
|
def user_delimiter
|
||||||
'@' unless @user.nil?
|
'@' unless @user.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def port_delimiter
|
def port_delimiter
|
||||||
':' unless @port.nil?
|
':' unless @port.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def query_delimiter
|
def query_delimiter
|
||||||
'?' unless @query.nil?
|
'?' unless @query.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def uri
|
def uri
|
||||||
[scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path,
|
[scheme, scheme_delimiter, user, user_delimiter, host, port_delimiter, port, path,
|
||||||
query_delimiter, query].compact.join
|
query_delimiter, query].compact.join
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# uri with mandatory scheme but less restrictive hostname, like
|
# uri with mandatory scheme but less restrictive hostname, like
|
||||||
# http://localhost:2500/blah.html
|
# http://localhost:2500/blah.html
|
||||||
class LocalURIChunk < URIChunk
|
class LocalURIChunk < URIChunk
|
||||||
|
|
||||||
unless defined? LocalURIChunk::LOCAL_URI_REGEXP
|
unless defined? LocalURIChunk::LOCAL_URI_REGEXP
|
||||||
# hostname can be just a simple word like 'localhost'
|
# hostname can be just a simple word like 'localhost'
|
||||||
ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
|
ANY_HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
|
||||||
|
|
||||||
# The basic URI expression as a string
|
# The basic URI expression as a string
|
||||||
# Scheme and hostname are mandatory
|
# Scheme and hostname are mandatory
|
||||||
LOCAL_URI =
|
LOCAL_URI =
|
||||||
"(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1)
|
"(?:(#{SCHEME})://)+" + # Mandatory scheme:// (\1)
|
||||||
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
|
"(?:(#{USERINFO})@)?" + # Optional userinfo@ (\2)
|
||||||
"(#{ANY_HOSTNAME})" + # Mandatory hostname (\3)
|
"(#{ANY_HOSTNAME})" + # Mandatory hostname (\3)
|
||||||
"(?::(#{PORT}))?" + # Optional :port (\4)
|
"(?::(#{PORT}))?" + # Optional :port (\4)
|
||||||
"(#{ABS_PATH})?" + # Optional absolute path (\5)
|
"(#{ABS_PATH})?" + # Optional absolute path (\5)
|
||||||
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
|
"(?:\\?(#{QUERY}))?" + # Optional ?query (\6)
|
||||||
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7)
|
"(?:\\#(#{FRAGMENT}))?" # Optional #fragment (\7)
|
||||||
|
|
||||||
LOCAL_URI_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + LOCAL_URI, Regexp::EXTENDED, 'N')
|
LOCAL_URI_REGEXP = Regexp.new(TEXTILE_SYNTAX_PREFIX + LOCAL_URI, Regexp::EXTENDED, 'N')
|
||||||
end
|
end
|
||||||
|
|
||||||
def LocalURIChunk.pattern
|
def LocalURIChunk.pattern
|
||||||
LOCAL_URI_REGEXP
|
LOCAL_URI_REGEXP
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
284
app/models/chunks/wiki.rb
Executable file → Normal file
284
app/models/chunks/wiki.rb
Executable file → Normal file
|
@ -1,142 +1,142 @@
|
||||||
require 'wiki_words'
|
require 'wiki_words'
|
||||||
require 'chunks/chunk'
|
require 'chunks/chunk'
|
||||||
require 'chunks/wiki'
|
require 'chunks/wiki'
|
||||||
require 'cgi'
|
require 'cgi'
|
||||||
|
|
||||||
# Contains all the methods for finding and replacing wiki related links.
|
# Contains all the methods for finding and replacing wiki related links.
|
||||||
module WikiChunk
|
module WikiChunk
|
||||||
include Chunk
|
include Chunk
|
||||||
|
|
||||||
# A wiki link is the top-level class for anything that refers to
|
# A wiki link is the top-level class for anything that refers to
|
||||||
# another wiki page.
|
# another wiki page.
|
||||||
class WikiLink < Chunk::Abstract
|
class WikiLink < Chunk::Abstract
|
||||||
|
|
||||||
attr_reader :page_name, :link_text, :link_type
|
attr_reader :page_name, :link_text, :link_type
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
super
|
super
|
||||||
@link_type = 'show'
|
@link_type = 'show'
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.apply_to(content)
|
def self.apply_to(content)
|
||||||
content.gsub!( self.pattern ) do |matched_text|
|
content.gsub!( self.pattern ) do |matched_text|
|
||||||
chunk = self.new($~)
|
chunk = self.new($~)
|
||||||
if chunk.textile_url?
|
if chunk.textile_url?
|
||||||
# do not substitute
|
# do not substitute
|
||||||
matched_text
|
matched_text
|
||||||
else
|
else
|
||||||
content.chunks << chunk
|
content.chunks << chunk
|
||||||
chunk.mask(content)
|
chunk.mask(content)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def textile_url?
|
def textile_url?
|
||||||
not @textile_link_suffix.nil?
|
not @textile_link_suffix.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
# By default, no escaped text
|
# By default, no escaped text
|
||||||
def escaped_text() nil end
|
def escaped_text() nil end
|
||||||
|
|
||||||
# Replace link with a mask, but if the word is escaped, then don't replace it
|
# Replace link with a mask, but if the word is escaped, then don't replace it
|
||||||
def mask(content)
|
def mask(content)
|
||||||
escaped_text || super(content)
|
escaped_text || super(content)
|
||||||
end
|
end
|
||||||
|
|
||||||
def revert(content) content.sub!(mask(content), text) end
|
def revert(content) content.sub!(mask(content), text) end
|
||||||
|
|
||||||
# Do not keep this chunk if it is escaped.
|
# Do not keep this chunk if it is escaped.
|
||||||
# Otherwise, pass the link procedure a page_name and link_text and
|
# Otherwise, pass the link procedure a page_name and link_text and
|
||||||
# get back a string of HTML to replace the mask with.
|
# get back a string of HTML to replace the mask with.
|
||||||
def unmask(content)
|
def unmask(content)
|
||||||
if escaped_text
|
if escaped_text
|
||||||
return self
|
return self
|
||||||
else
|
else
|
||||||
chunk_found = content.sub!(mask(content)) do |match|
|
chunk_found = content.sub!(mask(content)) do |match|
|
||||||
content.page_link(page_name, link_text, link_type)
|
content.page_link(page_name, link_text, link_type)
|
||||||
end
|
end
|
||||||
if chunk_found
|
if chunk_found
|
||||||
return self
|
return self
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This chunk matches a WikiWord. WikiWords can be escaped
|
# This chunk matches a WikiWord. WikiWords can be escaped
|
||||||
# by prepending a '\'. When this is the case, the +escaped_text+
|
# by prepending a '\'. When this is the case, the +escaped_text+
|
||||||
# method will return the WikiWord instead of the usual +nil+.
|
# method will return the WikiWord instead of the usual +nil+.
|
||||||
# The +page_name+ method returns the matched WikiWord.
|
# The +page_name+ method returns the matched WikiWord.
|
||||||
class Word < WikiLink
|
class Word < WikiLink
|
||||||
unless defined? WIKI_LINK
|
unless defined? WIKI_LINK
|
||||||
WIKI_WORD = Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, "utf-8")
|
WIKI_WORD = Regexp.new('(":)?(\\\\)?(' + WikiWords::WIKI_WORD_PATTERN + ')\b', 0, "utf-8")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.pattern
|
def self.pattern
|
||||||
WIKI_WORD
|
WIKI_WORD
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(match_data)
|
def initialize(match_data)
|
||||||
super(match_data)
|
super(match_data)
|
||||||
@textile_link_suffix, @escape, @page_name = match_data[1..3]
|
@textile_link_suffix, @escape, @page_name = match_data[1..3]
|
||||||
end
|
end
|
||||||
|
|
||||||
def escaped_text
|
def escaped_text
|
||||||
page_name unless @escape.nil?
|
page_name unless @escape.nil?
|
||||||
end
|
end
|
||||||
def link_text() WikiWords.separate(page_name) end
|
def link_text() WikiWords.separate(page_name) end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This chunk handles [[bracketted wiki words]] and
|
# This chunk handles [[bracketted wiki words]] and
|
||||||
# [[AliasedWords|aliased wiki words]]. The first part of an
|
# [[AliasedWords|aliased wiki words]]. The first part of an
|
||||||
# aliased wiki word must be a WikiWord. If the WikiWord
|
# aliased wiki word must be a WikiWord. If the WikiWord
|
||||||
# is aliased, the +link_text+ field will contain the
|
# is aliased, the +link_text+ field will contain the
|
||||||
# alias, otherwise +link_text+ will contain the entire
|
# alias, otherwise +link_text+ will contain the entire
|
||||||
# contents within the double brackets.
|
# contents within the double brackets.
|
||||||
#
|
#
|
||||||
# NOTE: This chunk must be tested before WikiWord since
|
# NOTE: This chunk must be tested before WikiWord since
|
||||||
# a WikiWords can be a substring of a WikiLink.
|
# a WikiWords can be a substring of a WikiLink.
|
||||||
class Link < WikiLink
|
class Link < WikiLink
|
||||||
|
|
||||||
unless defined? WIKI_LINK
|
unless defined? WIKI_LINK
|
||||||
WIKI_LINK = /(":)?\[\[([^\]]+)\]\]/
|
WIKI_LINK = /(":)?\[\[([^\]]+)\]\]/
|
||||||
LINK_TYPE_SEPARATION = Regexp.new('^(.+):((file)|(pic))$', 0, 'utf-8')
|
LINK_TYPE_SEPARATION = Regexp.new('^(.+):((file)|(pic))$', 0, 'utf-8')
|
||||||
ALIAS_SEPARATION = Regexp.new('^(.+)\|(.+)$', 0, 'utf-8')
|
ALIAS_SEPARATION = Regexp.new('^(.+)\|(.+)$', 0, 'utf-8')
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.pattern() WIKI_LINK end
|
def self.pattern() WIKI_LINK end
|
||||||
|
|
||||||
def initialize(match_data)
|
def initialize(match_data)
|
||||||
super(match_data)
|
super(match_data)
|
||||||
@textile_link_suffix, @page_name = match_data[1..2]
|
@textile_link_suffix, @page_name = match_data[1..2]
|
||||||
@link_text = @page_name
|
@link_text = @page_name
|
||||||
separate_link_type
|
separate_link_type
|
||||||
separate_alias
|
separate_alias
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# if link wihin the brackets has a form of [[filename:file]] or [[filename:pic]],
|
# if link wihin the brackets has a form of [[filename:file]] or [[filename:pic]],
|
||||||
# this means a link to a picture or a file
|
# this means a link to a picture or a file
|
||||||
def separate_link_type
|
def separate_link_type
|
||||||
link_type_match = LINK_TYPE_SEPARATION.match(@page_name)
|
link_type_match = LINK_TYPE_SEPARATION.match(@page_name)
|
||||||
if link_type_match
|
if link_type_match
|
||||||
@link_text = @page_name = link_type_match[1]
|
@link_text = @page_name = link_type_match[1]
|
||||||
@link_type = link_type_match[2..3].compact[0]
|
@link_type = link_type_match[2..3].compact[0]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# link text may be different from page name. this will look like [[actual page|link text]]
|
# link text may be different from page name. this will look like [[actual page|link text]]
|
||||||
def separate_alias
|
def separate_alias
|
||||||
alias_match = ALIAS_SEPARATION.match(@page_name)
|
alias_match = ALIAS_SEPARATION.match(@page_name)
|
||||||
if alias_match
|
if alias_match
|
||||||
@page_name, @link_text = alias_match[1..2]
|
@page_name, @link_text = alias_match[1..2]
|
||||||
end
|
end
|
||||||
# note that [[filename|link text:file]] is also supported
|
# note that [[filename|link text:file]] is also supported
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
require 'instiki_errors'
|
require 'instiki_errors'
|
||||||
|
|
||||||
class FileYard
|
class FileYard
|
||||||
|
|
||||||
attr_reader :files_path
|
attr_reader :files_path
|
||||||
|
|
||||||
def initialize(files_path)
|
def initialize(files_path)
|
||||||
@files_path = files_path
|
@files_path = files_path
|
||||||
@files = Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path) }.compact
|
@files = Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path) }.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def upload_file(name, io)
|
def upload_file(name, io)
|
||||||
sanitize_file_name(name)
|
sanitize_file_name(name)
|
||||||
if io.kind_of?(Tempfile)
|
if io.kind_of?(Tempfile)
|
||||||
io.close
|
io.close
|
||||||
FileUtils.mv(io.path, file_path(name))
|
FileUtils.mv(io.path, file_path(name))
|
||||||
else
|
else
|
||||||
File.open(file_path(name), 'wb') { |f| f.write(io.read) }
|
File.open(file_path(name), 'wb') { |f| f.write(io.read) }
|
||||||
end
|
end
|
||||||
# just in case, restrict read access and prohibit write access to the uploaded file
|
# just in case, restrict read access and prohibit write access to the uploaded file
|
||||||
FileUtils.chmod(0440, file_path(name))
|
FileUtils.chmod(0440, file_path(name))
|
||||||
end
|
end
|
||||||
|
|
||||||
def files
|
def files
|
||||||
Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path)}.compact
|
Dir["#{files_path}/*"].collect{|path| File.basename(path) if File.file?(path)}.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_file?(name)
|
def has_file?(name)
|
||||||
files.include?(name)
|
files.include?(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_path(name)
|
def file_path(name)
|
||||||
"#{files_path}/#{name}"
|
"#{files_path}/#{name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
SANE_FILE_NAME = /[-_\.A-Za-z0-9]{1,255}/
|
SANE_FILE_NAME = /[-_\.A-Za-z0-9]{1,255}/
|
||||||
|
|
||||||
def sanitize_file_name(name)
|
def sanitize_file_name(name)
|
||||||
unless name =~ SANE_FILE_NAME
|
unless name =~ SANE_FILE_NAME
|
||||||
raise Instiki::ValidationError.new("Invalid file name: '#{name}'.\n" +
|
raise Instiki::ValidationError.new("Invalid file name: '#{name}'.\n" +
|
||||||
"Only latin characters, digits, dots, underscores and dashes are accepted.")
|
"Only latin characters, digits, dots, underscores and dashes are accepted.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
184
app/models/page.rb
Executable file → Normal file
184
app/models/page.rb
Executable file → Normal file
|
@ -1,92 +1,92 @@
|
||||||
require 'date'
|
require 'date'
|
||||||
require 'page_lock'
|
require 'page_lock'
|
||||||
require 'revision'
|
require 'revision'
|
||||||
require 'wiki_words'
|
require 'wiki_words'
|
||||||
require 'chunks/wiki'
|
require 'chunks/wiki'
|
||||||
|
|
||||||
class Page
|
class Page
|
||||||
include PageLock
|
include PageLock
|
||||||
|
|
||||||
attr_reader :name, :web
|
attr_reader :name, :web
|
||||||
attr_accessor :revisions
|
attr_accessor :revisions
|
||||||
|
|
||||||
def initialize(web, name, content, created_at, author)
|
def initialize(web, name, content, created_at, author)
|
||||||
@web, @name, @revisions = web, name, []
|
@web, @name, @revisions = web, name, []
|
||||||
revise(content, created_at, author)
|
revise(content, created_at, author)
|
||||||
end
|
end
|
||||||
|
|
||||||
def revise(content, created_at, author)
|
def revise(content, created_at, author)
|
||||||
|
|
||||||
if not @revisions.empty? and content == @revisions.last.content
|
if not @revisions.empty? and content == @revisions.last.content
|
||||||
raise Instiki::ValidationError.new(
|
raise Instiki::ValidationError.new(
|
||||||
"You have tried to save page '#{name}' without changing its content")
|
"You have tried to save page '#{name}' without changing its content")
|
||||||
end
|
end
|
||||||
|
|
||||||
# A user may change a page, look at it and make some more changes - several times.
|
# A user may change a page, look at it and make some more changes - several times.
|
||||||
# Not to record every such iteration as a new revision, if the previous revision was done
|
# Not to record every such iteration as a new revision, if the previous revision was done
|
||||||
# by the same author, not more than 30 minutes ago, then update the last revision instead of
|
# by the same author, not more than 30 minutes ago, then update the last revision instead of
|
||||||
# creating a new one
|
# creating a new one
|
||||||
if !@revisions.empty? && continous_revision?(created_at, author)
|
if !@revisions.empty? && continous_revision?(created_at, author)
|
||||||
@revisions.last.created_at = created_at
|
@revisions.last.created_at = created_at
|
||||||
@revisions.last.content = content
|
@revisions.last.content = content
|
||||||
@revisions.last.clear_display_cache
|
@revisions.last.clear_display_cache
|
||||||
else
|
else
|
||||||
@revisions << Revision.new(self, @revisions.length, content, created_at, author)
|
@revisions << Revision.new(self, @revisions.length, content, created_at, author)
|
||||||
end
|
end
|
||||||
|
|
||||||
web.refresh_pages_with_references(name) if @revisions.length == 1
|
web.refresh_pages_with_references(name) if @revisions.length == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def rollback(revision_number, created_at, author_ip = nil)
|
def rollback(revision_number, created_at, author_ip = nil)
|
||||||
roll_back_revision = @revisions[revision_number].dup
|
roll_back_revision = @revisions[revision_number].dup
|
||||||
revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
|
revise(roll_back_revision.content, created_at, Author.new(roll_back_revision.author, author_ip))
|
||||||
end
|
end
|
||||||
|
|
||||||
def revisions?
|
def revisions?
|
||||||
revisions.length > 1
|
revisions.length > 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def revised_on
|
def revised_on
|
||||||
created_on
|
created_on
|
||||||
end
|
end
|
||||||
|
|
||||||
def in_category?(cat)
|
def in_category?(cat)
|
||||||
cat.nil? || cat.empty? || categories.include?(cat)
|
cat.nil? || cat.empty? || categories.include?(cat)
|
||||||
end
|
end
|
||||||
|
|
||||||
def categories
|
def categories
|
||||||
display_content.find_chunks(Category).map { |cat| cat.list }.flatten
|
display_content.find_chunks(Category).map { |cat| cat.list }.flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
def authors
|
def authors
|
||||||
revisions.collect { |rev| rev.author }
|
revisions.collect { |rev| rev.author }
|
||||||
end
|
end
|
||||||
|
|
||||||
def references
|
def references
|
||||||
web.select.pages_that_reference(name)
|
web.select.pages_that_reference(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
|
# Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
|
||||||
def plain_name
|
def plain_name
|
||||||
web.brackets_only ? name : WikiWords.separate(name)
|
web.brackets_only ? name : WikiWords.separate(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def link(options = {})
|
def link(options = {})
|
||||||
web.make_link(name, nil, options)
|
web.make_link(name, nil, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def author_link(options = {})
|
def author_link(options = {})
|
||||||
web.make_link(author, nil, options)
|
web.make_link(author, nil, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def continous_revision?(created_at, author)
|
def continous_revision?(created_at, author)
|
||||||
@revisions.last.author == author && @revisions.last.created_at + 30.minutes > created_at
|
@revisions.last.author == author && @revisions.last.created_at + 30.minutes > created_at
|
||||||
end
|
end
|
||||||
|
|
||||||
# Forward method calls to the current revision, so the page responds to all revision calls
|
# Forward method calls to the current revision, so the page responds to all revision calls
|
||||||
def method_missing(method_symbol)
|
def method_missing(method_symbol)
|
||||||
revisions.last.send(method_symbol)
|
revisions.last.send(method_symbol)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
46
app/models/page_lock.rb
Executable file → Normal file
46
app/models/page_lock.rb
Executable file → Normal file
|
@ -1,24 +1,24 @@
|
||||||
# Contains all the lock methods to be mixed in with the page
|
# Contains all the lock methods to be mixed in with the page
|
||||||
module PageLock
|
module PageLock
|
||||||
LOCKING_PERIOD = 30 * 60 # 30 minutes
|
LOCKING_PERIOD = 30 * 60 # 30 minutes
|
||||||
|
|
||||||
def lock(time, locked_by)
|
def lock(time, locked_by)
|
||||||
@locked_at, @locked_by = time, locked_by
|
@locked_at, @locked_by = time, locked_by
|
||||||
end
|
end
|
||||||
|
|
||||||
def lock_duration(time)
|
def lock_duration(time)
|
||||||
((time - @locked_at) / 60).to_i unless @locked_at.nil?
|
((time - @locked_at) / 60).to_i unless @locked_at.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def unlock
|
def unlock
|
||||||
@locked_at = nil
|
@locked_at = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def locked?(comparison_time)
|
def locked?(comparison_time)
|
||||||
@locked_at + LOCKING_PERIOD > comparison_time unless @locked_at.nil?
|
@locked_at + LOCKING_PERIOD > comparison_time unless @locked_at.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def locked_by_link
|
def locked_by_link
|
||||||
web.make_link(@locked_by)
|
web.make_link(@locked_by)
|
||||||
end
|
end
|
||||||
end
|
end
|
144
app/models/page_set.rb
Executable file → Normal file
144
app/models/page_set.rb
Executable file → Normal file
|
@ -1,73 +1,73 @@
|
||||||
# Container for a set of pages with methods for manipulation.
|
# Container for a set of pages with methods for manipulation.
|
||||||
|
|
||||||
class PageSet < Array
|
class PageSet < Array
|
||||||
attr_reader :web
|
attr_reader :web
|
||||||
|
|
||||||
def initialize(web, pages = nil, condition = nil)
|
def initialize(web, pages = nil, condition = nil)
|
||||||
@web = web
|
@web = web
|
||||||
# if pages is not specified, make a list of all pages in the web
|
# if pages is not specified, make a list of all pages in the web
|
||||||
if pages.nil?
|
if pages.nil?
|
||||||
super(web.pages.values)
|
super(web.pages.values)
|
||||||
# otherwise use specified pages and condition to produce a set of pages
|
# otherwise use specified pages and condition to produce a set of pages
|
||||||
elsif condition.nil?
|
elsif condition.nil?
|
||||||
super(pages)
|
super(pages)
|
||||||
else
|
else
|
||||||
super(pages.select { |page| condition[page] })
|
super(pages.select { |page| condition[page] })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def most_recent_revision
|
def most_recent_revision
|
||||||
self.map { |page| page.created_at }.max || Time.at(0)
|
self.map { |page| page.created_at }.max || Time.at(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def by_name
|
def by_name
|
||||||
PageSet.new(@web, sort_by { |page| page.name })
|
PageSet.new(@web, sort_by { |page| page.name })
|
||||||
end
|
end
|
||||||
|
|
||||||
alias :sort :by_name
|
alias :sort :by_name
|
||||||
|
|
||||||
def by_revision
|
def by_revision
|
||||||
PageSet.new(@web, sort_by { |page| page.created_at }).reverse
|
PageSet.new(@web, sort_by { |page| page.created_at }).reverse
|
||||||
end
|
end
|
||||||
|
|
||||||
def pages_that_reference(page_name)
|
def pages_that_reference(page_name)
|
||||||
self.select { |page| page.wiki_words.include?(page_name) }
|
self.select { |page| page.wiki_words.include?(page_name) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def pages_authored_by(author)
|
def pages_authored_by(author)
|
||||||
self.select { |page| page.authors.include?(author) }
|
self.select { |page| page.authors.include?(author) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def characters
|
def characters
|
||||||
self.inject(0) { |chars,page| chars += page.content.size }
|
self.inject(0) { |chars,page| chars += page.content.size }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns all the orphaned pages in this page set. That is,
|
# Returns all the orphaned pages in this page set. That is,
|
||||||
# pages in this set for which there is no reference in the web.
|
# pages in this set for which there is no reference in the web.
|
||||||
# The HomePage and author pages are always assumed to have
|
# The HomePage and author pages are always assumed to have
|
||||||
# references and so cannot be orphans
|
# references and so cannot be orphans
|
||||||
def orphaned_pages
|
def orphaned_pages
|
||||||
references = web.select.wiki_words + ["HomePage"] + web.select.authors
|
references = web.select.wiki_words + ["HomePage"] + web.select.authors
|
||||||
self.reject { |page| references.include?(page.name) }
|
self.reject { |page| references.include?(page.name) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns all the wiki words in this page set for which
|
# Returns all the wiki words in this page set for which
|
||||||
# there are no pages in this page set's web
|
# there are no pages in this page set's web
|
||||||
def wanted_pages
|
def wanted_pages
|
||||||
wiki_words - web.select.names
|
wiki_words - web.select.names
|
||||||
end
|
end
|
||||||
|
|
||||||
def names
|
def names
|
||||||
self.map { |page| page.name }
|
self.map { |page| page.name }
|
||||||
end
|
end
|
||||||
|
|
||||||
def wiki_words
|
def wiki_words
|
||||||
self.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
self.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
def authors
|
def authors
|
||||||
self.inject([]) { |authors, page| authors << page.authors }.flatten.uniq.sort
|
self.inject([]) { |authors, page| authors << page.authors }.flatten.uniq.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
166
app/models/revision.rb
Executable file → Normal file
166
app/models/revision.rb
Executable file → Normal file
|
@ -1,83 +1,83 @@
|
||||||
require 'diff'
|
require 'diff'
|
||||||
require 'wiki_content'
|
require 'wiki_content'
|
||||||
require 'chunks/wiki'
|
require 'chunks/wiki'
|
||||||
require 'date'
|
require 'date'
|
||||||
require 'author'
|
require 'author'
|
||||||
require 'page'
|
require 'page'
|
||||||
|
|
||||||
class Revision
|
class Revision
|
||||||
|
|
||||||
attr_accessor :page, :number, :content, :created_at, :author
|
attr_accessor :page, :number, :content, :created_at, :author
|
||||||
|
|
||||||
def initialize(page, number, content, created_at, author)
|
def initialize(page, number, content, created_at, author)
|
||||||
@page, @number, @created_at, @author = page, number, created_at, author
|
@page, @number, @created_at, @author = page, number, created_at, author
|
||||||
self.content = content
|
self.content = content
|
||||||
end
|
end
|
||||||
|
|
||||||
def created_on
|
def created_on
|
||||||
Date.new(@created_at.year, @created_at.mon, @created_at.day)
|
Date.new(@created_at.year, @created_at.mon, @created_at.day)
|
||||||
end
|
end
|
||||||
|
|
||||||
def pretty_created_at
|
def pretty_created_at
|
||||||
# Must use DateTime because Time doesn't support %e on at least some platforms
|
# Must use DateTime because Time doesn't support %e on at least some platforms
|
||||||
DateTime.new(
|
DateTime.new(
|
||||||
@created_at.year, @created_at.mon, @created_at.day, @created_at.hour, @created_at.min
|
@created_at.year, @created_at.mon, @created_at.day, @created_at.hour, @created_at.min
|
||||||
).strftime "%B %e, %Y %H:%M"
|
).strftime "%B %e, %Y %H:%M"
|
||||||
end
|
end
|
||||||
|
|
||||||
def next_revision
|
def next_revision
|
||||||
page.revisions[number + 1]
|
page.revisions[number + 1]
|
||||||
end
|
end
|
||||||
|
|
||||||
def previous_revision
|
def previous_revision
|
||||||
number > 0 ? page.revisions[number - 1] : nil
|
number > 0 ? page.revisions[number - 1] : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of all the WikiWords present in the content of this revision.
|
# Returns an array of all the WikiWords present in the content of this revision.
|
||||||
def wiki_words
|
def wiki_words
|
||||||
unless @wiki_words_cache
|
unless @wiki_words_cache
|
||||||
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
|
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
|
||||||
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped_text ? nil : c.page_name ) }.compact.uniq
|
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped_text ? nil : c.page_name ) }.compact.uniq
|
||||||
end
|
end
|
||||||
@wiki_words_cache
|
@wiki_words_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of all the WikiWords present in the content of this revision.
|
# Returns an array of all the WikiWords present in the content of this revision.
|
||||||
# that already exists as a page in the web.
|
# that already exists as a page in the web.
|
||||||
def existing_pages
|
def existing_pages
|
||||||
wiki_words.select { |wiki_word| page.web.pages[wiki_word] }
|
wiki_words.select { |wiki_word| page.web.pages[wiki_word] }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of all the WikiWords present in the content of this revision
|
# Returns an array of all the WikiWords present in the content of this revision
|
||||||
# that *doesn't* already exists as a page in the web.
|
# that *doesn't* already exists as a page in the web.
|
||||||
def unexisting_pages
|
def unexisting_pages
|
||||||
wiki_words - existing_pages
|
wiki_words - existing_pages
|
||||||
end
|
end
|
||||||
|
|
||||||
# Explicit check for new type of display cache with find_chunks method.
|
# Explicit check for new type of display cache with find_chunks method.
|
||||||
# Ensures new version works with older snapshots.
|
# Ensures new version works with older snapshots.
|
||||||
def display_content
|
def display_content
|
||||||
unless @display_cache && @display_cache.respond_to?(:find_chunks)
|
unless @display_cache && @display_cache.respond_to?(:find_chunks)
|
||||||
@display_cache = WikiContent.new(self)
|
@display_cache = WikiContent.new(self)
|
||||||
end
|
end
|
||||||
@display_cache
|
@display_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_diff
|
def display_diff
|
||||||
previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
|
previous_revision ? HTMLDiff.diff(previous_revision.display_content, display_content) : display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear_display_cache
|
def clear_display_cache
|
||||||
@display_cache = @published_cache = @wiki_words_cache = nil
|
@display_cache = @published_cache = @wiki_words_cache = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_published
|
def display_published
|
||||||
@published_cache = WikiContent.new(self, {:mode => :publish}) if @published_cache.nil?
|
@published_cache = WikiContent.new(self, {:mode => :publish}) if @published_cache.nil?
|
||||||
@published_cache
|
@published_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_content_for_export
|
def display_content_for_export
|
||||||
WikiContent.new(self, {:mode => :export} )
|
WikiContent.new(self, {:mode => :export} )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
308
app/models/web.rb
Executable file → Normal file
308
app/models/web.rb
Executable file → Normal file
|
@ -1,155 +1,155 @@
|
||||||
require "cgi"
|
require "cgi"
|
||||||
require "page"
|
require "page"
|
||||||
require "page_set"
|
require "page_set"
|
||||||
require "wiki_words"
|
require "wiki_words"
|
||||||
require "zip/zip"
|
require "zip/zip"
|
||||||
|
|
||||||
class Web
|
class Web
|
||||||
attr_accessor :name, :address, :password, :markup, :color, :safe_mode, :pages
|
attr_accessor :name, :address, :password, :markup, :color, :safe_mode, :pages
|
||||||
attr_accessor :additional_style, :published, :brackets_only, :count_pages, :allow_uploads
|
attr_accessor :additional_style, :published, :brackets_only, :count_pages, :allow_uploads
|
||||||
|
|
||||||
def initialize(parent_wiki, name, address, password = nil)
|
def initialize(parent_wiki, name, address, password = nil)
|
||||||
@wiki, @name, @address, @password = parent_wiki, name, address, password
|
@wiki, @name, @address, @password = parent_wiki, name, address, password
|
||||||
|
|
||||||
# default values
|
# default values
|
||||||
@markup = :textile
|
@markup = :textile
|
||||||
@color = '008B26'
|
@color = '008B26'
|
||||||
@safe_mode = false
|
@safe_mode = false
|
||||||
@pages = {}
|
@pages = {}
|
||||||
@allow_uploads = true
|
@allow_uploads = true
|
||||||
@additional_style = nil
|
@additional_style = nil
|
||||||
@published = false
|
@published = false
|
||||||
@brackets_only = false
|
@brackets_only = false
|
||||||
@count_pages = false
|
@count_pages = false
|
||||||
@allow_uploads = true
|
@allow_uploads = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_page(page)
|
def add_page(page)
|
||||||
@pages[page.name] = page
|
@pages[page.name] = page
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_pages(pages_to_be_removed)
|
def remove_pages(pages_to_be_removed)
|
||||||
pages.delete_if { |page_name, page| pages_to_be_removed.include?(page) }
|
pages.delete_if { |page_name, page| pages_to_be_removed.include?(page) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def select(&condition)
|
def select(&condition)
|
||||||
PageSet.new(self, @pages.values, condition)
|
PageSet.new(self, @pages.values, condition)
|
||||||
end
|
end
|
||||||
|
|
||||||
def revised_on
|
def revised_on
|
||||||
select.most_recent_revision
|
select.most_recent_revision
|
||||||
end
|
end
|
||||||
|
|
||||||
def authors
|
def authors
|
||||||
select.authors
|
select.authors
|
||||||
end
|
end
|
||||||
|
|
||||||
def categories
|
def categories
|
||||||
select.map { |page| page.categories }.flatten.uniq.sort
|
select.map { |page| page.categories }.flatten.uniq.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create a link for the given page name and link text based
|
# Create a link for the given page name and link text based
|
||||||
# on the render mode in options and whether the page exists
|
# on the render mode in options and whether the page exists
|
||||||
# in the this web.
|
# in the this web.
|
||||||
def make_link(name, text = nil, options = {})
|
def make_link(name, text = nil, options = {})
|
||||||
text = CGI.escapeHTML(text || WikiWords.separate(name))
|
text = CGI.escapeHTML(text || WikiWords.separate(name))
|
||||||
mode = options[:mode]
|
mode = options[:mode]
|
||||||
link_type = options[:link_type] || 'show'
|
link_type = options[:link_type] || 'show'
|
||||||
case link_type
|
case link_type
|
||||||
when 'show'
|
when 'show'
|
||||||
make_page_link(mode, name, text)
|
make_page_link(mode, name, text)
|
||||||
when 'file'
|
when 'file'
|
||||||
make_file_link(mode, name, text)
|
make_file_link(mode, name, text)
|
||||||
when 'pic'
|
when 'pic'
|
||||||
make_pic_link(mode, name, text)
|
make_pic_link(mode, name, text)
|
||||||
else
|
else
|
||||||
raise "Unknown link type: #{link_type}"
|
raise "Unknown link type: #{link_type}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_page_link(mode, name, text)
|
def make_page_link(mode, name, text)
|
||||||
link = CGI.escape(name)
|
link = CGI.escape(name)
|
||||||
case mode
|
case mode
|
||||||
when :export
|
when :export
|
||||||
if has_page?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
if has_page?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
||||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||||
when :publish
|
when :publish
|
||||||
if has_page?(name) then "<a class=\"existingWikiWord\" href=\"../published/#{link}\">#{text}</a>"
|
if has_page?(name) then "<a class=\"existingWikiWord\" href=\"../published/#{link}\">#{text}</a>"
|
||||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||||
else
|
else
|
||||||
if has_page?(name)
|
if has_page?(name)
|
||||||
"<a class=\"existingWikiWord\" href=\"../show/#{link}\">#{text}</a>"
|
"<a class=\"existingWikiWord\" href=\"../show/#{link}\">#{text}</a>"
|
||||||
else
|
else
|
||||||
"<span class=\"newWikiWord\">#{text}<a href=\"../show/#{link}\">?</a></span>"
|
"<span class=\"newWikiWord\">#{text}<a href=\"../show/#{link}\">?</a></span>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_file_link(mode, name, text)
|
def make_file_link(mode, name, text)
|
||||||
link = CGI.escape(name)
|
link = CGI.escape(name)
|
||||||
case mode
|
case mode
|
||||||
when :export
|
when :export
|
||||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
||||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||||
when :publish
|
when :publish
|
||||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"../published/#{link}\">#{text}</a>"
|
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"../published/#{link}\">#{text}</a>"
|
||||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||||
else
|
else
|
||||||
if has_file?(name)
|
if has_file?(name)
|
||||||
"<a class=\"existingWikiWord\" href=\"../file/#{link}\">#{text}</a>"
|
"<a class=\"existingWikiWord\" href=\"../file/#{link}\">#{text}</a>"
|
||||||
else
|
else
|
||||||
"<span class=\"newWikiWord\">#{text}<a href=\"../file/#{link}\">?</a></span>"
|
"<span class=\"newWikiWord\">#{text}<a href=\"../file/#{link}\">?</a></span>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_pic_link(mode, name, text)
|
def make_pic_link(mode, name, text)
|
||||||
link = CGI.escape(name)
|
link = CGI.escape(name)
|
||||||
case mode
|
case mode
|
||||||
when :export
|
when :export
|
||||||
if has_file?(name) then "<img alt=\"#{text}\" src=\"#{link}\" />"
|
if has_file?(name) then "<img alt=\"#{text}\" src=\"#{link}\" />"
|
||||||
else "<img alt=\"#{text}\" src=\"no image\" />" end
|
else "<img alt=\"#{text}\" src=\"no image\" />" end
|
||||||
when :publish
|
when :publish
|
||||||
if has_file?(name) then "<img alt=\"#{text}\" src=\"#{link}\" />"
|
if has_file?(name) then "<img alt=\"#{text}\" src=\"#{link}\" />"
|
||||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||||
else
|
else
|
||||||
if has_file?(name) then "<img alt=\"#{text}\" src=\"../pic/#{link}\" />"
|
if has_file?(name) then "<img alt=\"#{text}\" src=\"../pic/#{link}\" />"
|
||||||
else "<span class=\"newWikiWord\">#{text}<a href=\"../pic/#{link}\">?</a></span>" end
|
else "<span class=\"newWikiWord\">#{text}<a href=\"../pic/#{link}\">?</a></span>" end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_page?(name)
|
def has_page?(name)
|
||||||
pages[name]
|
pages[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_file?(name)
|
def has_file?(name)
|
||||||
wiki.file_yard(self).has_file?(name)
|
wiki.file_yard(self).has_file?(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Clears the display cache for all the pages with references to
|
# Clears the display cache for all the pages with references to
|
||||||
def refresh_pages_with_references(page_name)
|
def refresh_pages_with_references(page_name)
|
||||||
select.pages_that_reference(page_name).each { |page|
|
select.pages_that_reference(page_name).each { |page|
|
||||||
page.revisions.each { |revision| revision.clear_display_cache }
|
page.revisions.each { |revision| revision.clear_display_cache }
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def refresh_revisions
|
def refresh_revisions
|
||||||
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
|
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
# Returns an array of all the wiki words in any current revision
|
# Returns an array of all the wiki words in any current revision
|
||||||
def wiki_words
|
def wiki_words
|
||||||
pages.values.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
pages.values.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns an array of all the page names on this web
|
# Returns an array of all the page names on this web
|
||||||
def page_names
|
def page_names
|
||||||
pages.keys
|
pages.keys
|
||||||
end
|
end
|
||||||
|
|
||||||
# This ensures compatibility with 0.9 storages
|
# This ensures compatibility with 0.9 storages
|
||||||
def wiki
|
def wiki
|
||||||
@wiki ||= WikiService.instance
|
@wiki ||= WikiService.instance
|
||||||
end
|
end
|
||||||
end
|
end
|
192
app/models/wiki_content.rb
Executable file → Normal file
192
app/models/wiki_content.rb
Executable file → Normal file
|
@ -1,97 +1,97 @@
|
||||||
require 'cgi'
|
require 'cgi'
|
||||||
require 'chunks/engines'
|
require 'chunks/engines'
|
||||||
require 'chunks/category'
|
require 'chunks/category'
|
||||||
require 'chunks/include'
|
require 'chunks/include'
|
||||||
require 'chunks/wiki'
|
require 'chunks/wiki'
|
||||||
require 'chunks/literal'
|
require 'chunks/literal'
|
||||||
require 'chunks/uri'
|
require 'chunks/uri'
|
||||||
require 'chunks/nowiki'
|
require 'chunks/nowiki'
|
||||||
|
|
||||||
# Wiki content is just a string that can process itself with a chain of
|
# Wiki content is just a string that can process itself with a chain of
|
||||||
# actions. The actions can modify wiki content so that certain parts of
|
# actions. The actions can modify wiki content so that certain parts of
|
||||||
# it are protected from being rendered by later actions.
|
# it are protected from being rendered by later actions.
|
||||||
#
|
#
|
||||||
# When wiki content is rendered, it can be interrogated to find out
|
# When wiki content is rendered, it can be interrogated to find out
|
||||||
# which chunks were rendered. This means things like categories, wiki
|
# which chunks were rendered. This means things like categories, wiki
|
||||||
# links, can be determined.
|
# links, can be determined.
|
||||||
#
|
#
|
||||||
# Exactly how wiki content is rendered is determined by a number of
|
# Exactly how wiki content is rendered is determined by a number of
|
||||||
# settings that are optionally passed in to a constructor. The current
|
# settings that are optionally passed in to a constructor. The current
|
||||||
# options are:
|
# options are:
|
||||||
# * :engine
|
# * :engine
|
||||||
# => The structural markup engine to use (Textile, Markdown, RDoc)
|
# => The structural markup engine to use (Textile, Markdown, RDoc)
|
||||||
# * :engine_opts
|
# * :engine_opts
|
||||||
# => A list of options to pass to the markup engines (safe modes, etc)
|
# => A list of options to pass to the markup engines (safe modes, etc)
|
||||||
# * :pre_engine_actions
|
# * :pre_engine_actions
|
||||||
# => A list of render actions or chunks to be processed before the
|
# => A list of render actions or chunks to be processed before the
|
||||||
# markup engine is applied. By default this is:
|
# markup engine is applied. By default this is:
|
||||||
# Category, Include, URIChunk, WikiChunk::Link, WikiChunk::Word
|
# Category, Include, URIChunk, WikiChunk::Link, WikiChunk::Word
|
||||||
# * :post_engine_actions
|
# * :post_engine_actions
|
||||||
# => A list of render actions or chunks to apply after the markup
|
# => A list of render actions or chunks to apply after the markup
|
||||||
# engine. By default these are:
|
# engine. By default these are:
|
||||||
# Literal::Pre, Literal::Tags
|
# Literal::Pre, Literal::Tags
|
||||||
# * :mode
|
# * :mode
|
||||||
# => How should the content be rendered? For normal display (:display),
|
# => How should the content be rendered? For normal display (:display),
|
||||||
# publishing (:publish) or export (:export)?
|
# publishing (:publish) or export (:export)?
|
||||||
#
|
#
|
||||||
# AUTHOR: Mark Reid <mark @ threewordslong . com>
|
# AUTHOR: Mark Reid <mark @ threewordslong . com>
|
||||||
# CREATED: 15th May 2004
|
# CREATED: 15th May 2004
|
||||||
# UPDATED: 22nd May 2004
|
# UPDATED: 22nd May 2004
|
||||||
class WikiContent < String
|
class WikiContent < String
|
||||||
|
|
||||||
PRE_ENGINE_ACTIONS = [ NoWiki, Category, Include, WikiChunk::Link, URIChunk, LocalURIChunk,
|
PRE_ENGINE_ACTIONS = [ NoWiki, Category, Include, WikiChunk::Link, URIChunk, LocalURIChunk,
|
||||||
WikiChunk::Word ]
|
WikiChunk::Word ]
|
||||||
POST_ENGINE_ACTIONS = [ Literal::Pre, Literal::Tags ]
|
POST_ENGINE_ACTIONS = [ Literal::Pre, Literal::Tags ]
|
||||||
DEFAULT_OPTS = {
|
DEFAULT_OPTS = {
|
||||||
:pre_engine_actions => PRE_ENGINE_ACTIONS,
|
:pre_engine_actions => PRE_ENGINE_ACTIONS,
|
||||||
:post_engine_actions => POST_ENGINE_ACTIONS,
|
:post_engine_actions => POST_ENGINE_ACTIONS,
|
||||||
:engine => Engines::Textile,
|
:engine => Engines::Textile,
|
||||||
:engine_opts => [],
|
:engine_opts => [],
|
||||||
:mode => [:display]
|
:mode => [:display]
|
||||||
}
|
}
|
||||||
|
|
||||||
attr_reader :web, :options, :rendered, :chunks
|
attr_reader :web, :options, :rendered, :chunks
|
||||||
|
|
||||||
# Create a new wiki content string from the given one.
|
# Create a new wiki content string from the given one.
|
||||||
# The options are explained at the top of this file.
|
# The options are explained at the top of this file.
|
||||||
def initialize(revision, options = {})
|
def initialize(revision, options = {})
|
||||||
@revision = revision
|
@revision = revision
|
||||||
@web = @revision.page.web
|
@web = @revision.page.web
|
||||||
|
|
||||||
# Deep copy of DEFAULT_OPTS to ensure that changes to PRE/POST_ENGINE_ACTIONS stay local
|
# Deep copy of DEFAULT_OPTS to ensure that changes to PRE/POST_ENGINE_ACTIONS stay local
|
||||||
@options = Marshal.load(Marshal.dump(DEFAULT_OPTS)).update(options)
|
@options = Marshal.load(Marshal.dump(DEFAULT_OPTS)).update(options)
|
||||||
@options[:engine] = Engines::MAP[@web.markup] || Engines::Textile
|
@options[:engine] = Engines::MAP[@web.markup] || Engines::Textile
|
||||||
@options[:engine_opts] = (@web.safe_mode ? [:filter_html, :filter_styles] : [])
|
@options[:engine_opts] = (@web.safe_mode ? [:filter_html, :filter_styles] : [])
|
||||||
|
|
||||||
@options[:pre_engine_actions].delete(WikiChunk::Word) if @web.brackets_only
|
@options[:pre_engine_actions].delete(WikiChunk::Word) if @web.brackets_only
|
||||||
|
|
||||||
super(@revision.content)
|
super(@revision.content)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
render!(@options[:pre_engine_actions] + [@options[:engine]] + @options[:post_engine_actions])
|
render!(@options[:pre_engine_actions] + [@options[:engine]] + @options[:post_engine_actions])
|
||||||
# FIXME this is where all the parsing problems were shoved under the carpet
|
# FIXME this is where all the parsing problems were shoved under the carpet
|
||||||
# rescue => e
|
# rescue => e
|
||||||
# @rendered = e.message
|
# @rendered = e.message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Call @web.page_link using current options.
|
# Call @web.page_link using current options.
|
||||||
def page_link(name, text, link_type)
|
def page_link(name, text, link_type)
|
||||||
@options[:link_type] = link_type || :show
|
@options[:link_type] = link_type || :show
|
||||||
@web.make_link(name, text, @options)
|
@web.make_link(name, text, @options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Find all the chunks of the given types
|
# Find all the chunks of the given types
|
||||||
def find_chunks(chunk_type)
|
def find_chunks(chunk_type)
|
||||||
rendered.select { |chunk| chunk.kind_of?(chunk_type) }
|
rendered.select { |chunk| chunk.kind_of?(chunk_type) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Render this content using the specified actions.
|
# Render this content using the specified actions.
|
||||||
def render!(chunk_types)
|
def render!(chunk_types)
|
||||||
@chunks = []
|
@chunks = []
|
||||||
chunk_types.each { |chunk_type| chunk_type.apply_to(self) }
|
chunk_types.each { |chunk_type| chunk_type.apply_to(self) }
|
||||||
@rendered = @chunks.map { |chunk| chunk.unmask(self) }.compact
|
@rendered = @chunks.map { |chunk| chunk.unmask(self) }.compact
|
||||||
(@chunks - @rendered).each { |chunk| chunk.revert(self) }
|
(@chunks - @rendered).each { |chunk| chunk.revert(self) }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
444
app/models/wiki_service.rb
Executable file → Normal file
444
app/models/wiki_service.rb
Executable file → Normal file
|
@ -1,222 +1,222 @@
|
||||||
require 'open-uri'
|
require 'open-uri'
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
require 'madeleine'
|
require 'madeleine'
|
||||||
require 'madeleine/automatic'
|
require 'madeleine/automatic'
|
||||||
require 'madeleine/zmarshal'
|
require 'madeleine/zmarshal'
|
||||||
|
|
||||||
require 'web'
|
require 'web'
|
||||||
require 'page'
|
require 'page'
|
||||||
require 'author'
|
require 'author'
|
||||||
require 'file_yard'
|
require 'file_yard'
|
||||||
|
|
||||||
module AbstractWikiService
|
module AbstractWikiService
|
||||||
|
|
||||||
attr_reader :webs, :system
|
attr_reader :webs, :system
|
||||||
|
|
||||||
def authenticate(password)
|
def authenticate(password)
|
||||||
password == (@system[:password] || 'instiki')
|
password == (@system[:password] || 'instiki')
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_web(name, address, password = nil)
|
def create_web(name, address, password = nil)
|
||||||
@webs[address] = Web.new(self, name, address, password) unless @webs[address]
|
@webs[address] = Web.new(self, name, address, password) unless @webs[address]
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_web(address)
|
def delete_web(address)
|
||||||
@webs[address] = nil
|
@webs[address] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_yard(web)
|
def file_yard(web)
|
||||||
raise "Web #{@web.name} does not belong to this wiki service" unless @webs.values.include?(web)
|
raise "Web #{@web.name} does not belong to this wiki service" unless @webs.values.include?(web)
|
||||||
# TODO cache FileYards
|
# TODO cache FileYards
|
||||||
FileYard.new("#{self.storage_path}/#{web.address}")
|
FileYard.new("#{self.storage_path}/#{web.address}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def init_wiki_service
|
def init_wiki_service
|
||||||
@webs = {}
|
@webs = {}
|
||||||
@system = {}
|
@system = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_page(web_address, page_name)
|
def read_page(web_address, page_name)
|
||||||
ApplicationController.logger.debug "Reading page '#{page_name}' from web '#{web_address}'"
|
ApplicationController.logger.debug "Reading page '#{page_name}' from web '#{web_address}'"
|
||||||
web = @webs[web_address]
|
web = @webs[web_address]
|
||||||
if web.nil?
|
if web.nil?
|
||||||
ApplicationController.logger.debug "Web '#{web_address}' not found"
|
ApplicationController.logger.debug "Web '#{web_address}' not found"
|
||||||
return nil
|
return nil
|
||||||
else
|
else
|
||||||
page = web.pages[page_name]
|
page = web.pages[page_name]
|
||||||
ApplicationController.logger.debug "Page '#{page_name}' #{page.nil? ? 'not' : ''} found"
|
ApplicationController.logger.debug "Page '#{page_name}' #{page.nil? ? 'not' : ''} found"
|
||||||
return page
|
return page
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_orphaned_pages(web_address)
|
def remove_orphaned_pages(web_address)
|
||||||
@webs[web_address].remove_pages(@webs[web_address].select.orphaned_pages)
|
@webs[web_address].remove_pages(@webs[web_address].select.orphaned_pages)
|
||||||
end
|
end
|
||||||
|
|
||||||
def revise_page(web_address, page_name, content, revised_on, author)
|
def revise_page(web_address, page_name, content, revised_on, author)
|
||||||
page = read_page(web_address, page_name)
|
page = read_page(web_address, page_name)
|
||||||
page.revise(content, revised_on, author)
|
page.revise(content, revised_on, author)
|
||||||
page
|
page
|
||||||
end
|
end
|
||||||
|
|
||||||
def rollback_page(web_address, page_name, revision_number, created_at, author_id = nil)
|
def rollback_page(web_address, page_name, revision_number, created_at, author_id = nil)
|
||||||
page = read_page(web_address, page_name)
|
page = read_page(web_address, page_name)
|
||||||
page.rollback(revision_number, created_at, author_id)
|
page.rollback(revision_number, created_at, author_id)
|
||||||
page
|
page
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup(password, web_name, web_address)
|
def setup(password, web_name, web_address)
|
||||||
@system[:password] = password
|
@system[:password] = password
|
||||||
create_web(web_name, web_address)
|
create_web(web_name, web_address)
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup?
|
def setup?
|
||||||
not (@webs.empty?)
|
not (@webs.empty?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_web(old_address, new_address, name, markup, color, additional_style, safe_mode = false,
|
def update_web(old_address, new_address, name, markup, color, additional_style, safe_mode = false,
|
||||||
password = nil, published = false, brackets_only = false, count_pages = false,
|
password = nil, published = false, brackets_only = false, count_pages = false,
|
||||||
allow_uploads = true)
|
allow_uploads = true)
|
||||||
if old_address != new_address
|
if old_address != new_address
|
||||||
@webs[new_address] = @webs[old_address]
|
@webs[new_address] = @webs[old_address]
|
||||||
@webs.delete(old_address)
|
@webs.delete(old_address)
|
||||||
@webs[new_address].address = new_address
|
@webs[new_address].address = new_address
|
||||||
end
|
end
|
||||||
|
|
||||||
web = @webs[new_address]
|
web = @webs[new_address]
|
||||||
web.refresh_revisions if settings_changed?(web, markup, safe_mode, brackets_only)
|
web.refresh_revisions if settings_changed?(web, markup, safe_mode, brackets_only)
|
||||||
|
|
||||||
web.name, web.markup, web.color, web.additional_style, web.safe_mode =
|
web.name, web.markup, web.color, web.additional_style, web.safe_mode =
|
||||||
name, markup, color, additional_style, safe_mode
|
name, markup, color, additional_style, safe_mode
|
||||||
|
|
||||||
web.password, web.published, web.brackets_only, web.count_pages, web.allow_uploads =
|
web.password, web.published, web.brackets_only, web.count_pages, web.allow_uploads =
|
||||||
password, published, brackets_only, count_pages, allow_uploads
|
password, published, brackets_only, count_pages, allow_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_page(web_address, page_name, content, written_on, author)
|
def write_page(web_address, page_name, content, written_on, author)
|
||||||
page = Page.new(@webs[web_address], page_name, content, written_on, author)
|
page = Page.new(@webs[web_address], page_name, content, written_on, author)
|
||||||
@webs[web_address].add_page(page)
|
@webs[web_address].add_page(page)
|
||||||
page
|
page
|
||||||
end
|
end
|
||||||
|
|
||||||
def storage_path
|
def storage_path
|
||||||
self.class.storage_path
|
self.class.storage_path
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def settings_changed?(web, markup, safe_mode, brackets_only)
|
def settings_changed?(web, markup, safe_mode, brackets_only)
|
||||||
web.markup != markup ||
|
web.markup != markup ||
|
||||||
web.safe_mode != safe_mode ||
|
web.safe_mode != safe_mode ||
|
||||||
web.brackets_only != brackets_only
|
web.brackets_only != brackets_only
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class WikiService
|
class WikiService
|
||||||
|
|
||||||
include AbstractWikiService
|
include AbstractWikiService
|
||||||
include Madeleine::Automatic::Interceptor
|
include Madeleine::Automatic::Interceptor
|
||||||
|
|
||||||
# These methods do not change the state of persistent objects, and
|
# These methods do not change the state of persistent objects, and
|
||||||
# should not be ogged by Madeleine
|
# should not be ogged by Madeleine
|
||||||
automatic_read_only :authenticate, :read_page, :setup?, :webs, :storage_path, :file_yard
|
automatic_read_only :authenticate, :read_page, :setup?, :webs, :storage_path, :file_yard
|
||||||
|
|
||||||
@@storage_path = './storage/'
|
@@storage_path = './storage/'
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
def storage_path=(storage_path)
|
def storage_path=(storage_path)
|
||||||
@@storage_path = storage_path
|
@@storage_path = storage_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def storage_path
|
def storage_path
|
||||||
@@storage_path
|
@@storage_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def clean_storage
|
def clean_storage
|
||||||
MadeleineServer.clean_storage(self)
|
MadeleineServer.clean_storage(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def instance
|
def instance
|
||||||
@madeleine ||= MadeleineServer.new(self)
|
@madeleine ||= MadeleineServer.new(self)
|
||||||
@system = @madeleine.system
|
@system = @madeleine.system
|
||||||
return @system
|
return @system
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot
|
def snapshot
|
||||||
@madeleine.snapshot
|
@madeleine.snapshot
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
init_wiki_service
|
init_wiki_service
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class MadeleineServer
|
class MadeleineServer
|
||||||
|
|
||||||
attr_reader :storage_path
|
attr_reader :storage_path
|
||||||
|
|
||||||
# Clears all the command_log and snapshot files located in the storage directory, so the
|
# Clears all the command_log and snapshot files located in the storage directory, so the
|
||||||
# database is essentially dropped and recreated as blank
|
# database is essentially dropped and recreated as blank
|
||||||
def self.clean_storage(service)
|
def self.clean_storage(service)
|
||||||
begin
|
begin
|
||||||
Dir.foreach(service.storage_path) do |file|
|
Dir.foreach(service.storage_path) do |file|
|
||||||
if file =~ /(command_log|snapshot)$/
|
if file =~ /(command_log|snapshot)$/
|
||||||
File.delete(File.join(service.storage_path, file))
|
File.delete(File.join(service.storage_path, file))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
Dir.mkdir(service.storage_path)
|
Dir.mkdir(service.storage_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(service)
|
def initialize(service)
|
||||||
@storage_path = service.storage_path
|
@storage_path = service.storage_path
|
||||||
@server = Madeleine::Automatic::AutomaticSnapshotMadeleine.new(service.storage_path,
|
@server = Madeleine::Automatic::AutomaticSnapshotMadeleine.new(service.storage_path,
|
||||||
Madeleine::ZMarshal.new) {
|
Madeleine::ZMarshal.new) {
|
||||||
service.new
|
service.new
|
||||||
}
|
}
|
||||||
start_snapshot_thread
|
start_snapshot_thread
|
||||||
end
|
end
|
||||||
|
|
||||||
def command_log_present?
|
def command_log_present?
|
||||||
not Dir[storage_path + '/*.command_log'].empty?
|
not Dir[storage_path + '/*.command_log'].empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot
|
def snapshot
|
||||||
@server.take_snapshot
|
@server.take_snapshot
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_snapshot_thread
|
def start_snapshot_thread
|
||||||
Thread.new(@server) {
|
Thread.new(@server) {
|
||||||
hours_since_last_snapshot = 0
|
hours_since_last_snapshot = 0
|
||||||
while true
|
while true
|
||||||
begin
|
begin
|
||||||
hours_since_last_snapshot += 1
|
hours_since_last_snapshot += 1
|
||||||
# Take a snapshot if there is a command log, or 24 hours
|
# Take a snapshot if there is a command log, or 24 hours
|
||||||
# have passed since the last snapshot
|
# have passed since the last snapshot
|
||||||
if command_log_present? or hours_since_last_snapshot >= 24
|
if command_log_present? or hours_since_last_snapshot >= 24
|
||||||
ActionController::Base.logger.info "[#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] " +
|
ActionController::Base.logger.info "[#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] " +
|
||||||
'Taking a Madeleine snapshot'
|
'Taking a Madeleine snapshot'
|
||||||
snapshot
|
snapshot
|
||||||
hours_since_last_snapshot = 0
|
hours_since_last_snapshot = 0
|
||||||
end
|
end
|
||||||
sleep(1.hour)
|
sleep(1.hour)
|
||||||
rescue => e
|
rescue => e
|
||||||
ActionController::Base.logger.error(e)
|
ActionController::Base.logger.error(e)
|
||||||
# wait for a minute (not to spoof the log with the same error)
|
# wait for a minute (not to spoof the log with the same error)
|
||||||
# and go back into the loop, to keep trying
|
# and go back into the loop, to keep trying
|
||||||
sleep(1.minute)
|
sleep(1.minute)
|
||||||
ActionController::Base.logger.info("Retrying to save a snapshot")
|
ActionController::Base.logger.info("Retrying to save a snapshot")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def system
|
def system
|
||||||
@server.system
|
@server.system
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
46
app/models/wiki_words.rb
Executable file → Normal file
46
app/models/wiki_words.rb
Executable file → Normal file
|
@ -1,23 +1,23 @@
|
||||||
# Contains all the methods for finding and replacing wiki words
|
# Contains all the methods for finding and replacing wiki words
|
||||||
module WikiWords
|
module WikiWords
|
||||||
# In order of appearance: Latin, greek, cyrillian, armenian
|
# In order of appearance: Latin, greek, cyrillian, armenian
|
||||||
I18N_HIGHER_CASE_LETTERS =
|
I18N_HIGHER_CASE_LETTERS =
|
||||||
"À<EFBFBD>?ÂÃÄÅĀĄĂÆÇĆČĈĊĎ<C48A>?ÈÉÊËĒĘĚĔĖĜĞĠĢĤĦÌ<C4A6>?Î<>?ĪĨĬĮİIJĴĶ<C4B4>?ĽĹĻĿÑŃŇŅŊÒÓÔÕÖØŌ<C398>?ŎŒŔŘŖŚŠŞŜȘŤŢŦȚÙÚÛÜŪŮŰŬŨŲŴ<C5B2>?ŶŸŹŽŻ" +
|
"À<EFBFBD>?ÂÃÄÅĀĄĂÆÇĆČĈĊĎ<C48A>?ÈÉÊËĒĘĚĔĖĜĞĠĢĤĦÌ<C4A6>?Î<>?ĪĨĬĮİIJĴĶ<C4B4>?ĽĹĻĿÑŃŇŅŊÒÓÔÕÖØŌ<C398>?ŎŒŔŘŖŚŠŞŜȘŤŢŦȚÙÚÛÜŪŮŰŬŨŲŴ<C5B2>?ŶŸŹŽŻ" +
|
||||||
"ΑΒΓΔΕΖΗΘΙΚΛΜ<EFBFBD>?ΞΟΠΡΣΤΥΦΧΨΩ" +
|
"ΑΒΓΔΕΖΗΘΙΚΛΜ<EFBFBD>?ΞΟΠΡΣΤΥΦΧΨΩ" +
|
||||||
"ΆΈΉΊΌΎ<EFBFBD>?ѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎ<D28C>?ҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾ<D2BC>?ӃӅӇӉӋ<D389>?<3F>?ӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӸЖ" +
|
"ΆΈΉΊΌΎ<EFBFBD>?ѠѢѤѦѨѪѬѮѰѲѴѶѸѺѼѾҀҊҌҎ<D28C>?ҒҔҖҘҚҜҞҠҢҤҦҨҪҬҮҰҲҴҶҸҺҼҾ<D2BC>?ӃӅӇӉӋ<D389>?<3F>?ӒӔӖӘӚӜӞӠӢӤӦӨӪӬӮӰӲӴӸЖ" +
|
||||||
"ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀ<EFBFBD>?ՂՃՄՅՆՇՈՉՊՋՌ<D58B>?<3F>?<3F>?ՑՒՓՔՕՖ"
|
"ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀ<EFBFBD>?ՂՃՄՅՆՇՈՉՊՋՌ<D58B>?<3F>?<3F>?ՑՒՓՔՕՖ"
|
||||||
|
|
||||||
I18N_LOWER_CASE_LETTERS =
|
I18N_LOWER_CASE_LETTERS =
|
||||||
"àáâãäå<EFBFBD>?ąăæçć<C3A7>?ĉċ<C489>?đèéêëēęěĕėƒ<C497>?ğġģĥħìíîïīĩĭįıijĵķĸłľĺļŀñńňņʼnŋòóôõöø<C3B6>?ő<>?œŕřŗśšş<C5A1>?șťţŧțùúûüūůűŭũųŵýÿŷžżźÞþßſ<C39F>?ð" +
|
"àáâãäå<EFBFBD>?ąăæçć<C3A7>?ĉċ<C489>?đèéêëēęěĕėƒ<C497>?ğġģĥħìíîïīĩĭįıijĵķĸłľĺļŀñńňņʼnŋòóôõöø<C3B6>?ő<>?œŕřŗśšş<C5A1>?șťţŧțùúûüūůűŭũųŵýÿŷžżźÞþßſ<C39F>?ð" +
|
||||||
"άέήίΰαβγδεζηθικλμνξοπ<EFBFBD>?ςστυφχψωϊϋό<CF8B>?ώ<>?" +
|
"άέήίΰαβγδεζηθικλμνξοπ<EFBFBD>?ςστυφχψωϊϋό<CF8B>?ώ<>?" +
|
||||||
"абвгдежзийклмнопр<EFBFBD>?туфхцчшщъыь<D18B>?ю<>?<3F>?ёђѓєѕіїјљћќ<D19B>?ўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿ<D1BD>?ҋ<>?<3F>?ґғҕҗҙқ<D299>?ҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӀӂӄӆӈӊӌӎӑӓӕӗәӛ<D399>?ӟӡӣӥӧөӫӭӯӱӳӵӹ" +
|
"абвгдежзийклмнопр<EFBFBD>?туфхцчшщъыь<D18B>?ю<>?<3F>?ёђѓєѕіїјљћќ<D19B>?ўџѡѣѥѧѩѫѭѯѱѳѵѷѹѻѽѿ<D1BD>?ҋ<>?<3F>?ґғҕҗҙқ<D299>?ҟҡңҥҧҩҫҭүұҳҵҷҹһҽҿӀӂӄӆӈӊӌӎӑӓӕӗәӛ<D399>?ӟӡӣӥӧөӫӭӯӱӳӵӹ" +
|
||||||
"աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտր<EFBFBD>?ւփքօֆև"
|
"աբգդեզէըթժիլխծկհձղճմյնշոչպջռսվտր<EFBFBD>?ւփքօֆև"
|
||||||
|
|
||||||
WIKI_WORD_PATTERN = '[A-Z' + I18N_HIGHER_CASE_LETTERS + '][a-z' + I18N_LOWER_CASE_LETTERS + ']+[A-Z' + I18N_HIGHER_CASE_LETTERS + ']\w+'
|
WIKI_WORD_PATTERN = '[A-Z' + I18N_HIGHER_CASE_LETTERS + '][a-z' + I18N_LOWER_CASE_LETTERS + ']+[A-Z' + I18N_HIGHER_CASE_LETTERS + ']\w+'
|
||||||
CAMEL_CASED_WORD_BORDER = /([a-z#{I18N_LOWER_CASE_LETTERS}])([A-Z#{I18N_HIGHER_CASE_LETTERS}])/u
|
CAMEL_CASED_WORD_BORDER = /([a-z#{I18N_LOWER_CASE_LETTERS}])([A-Z#{I18N_HIGHER_CASE_LETTERS}])/u
|
||||||
|
|
||||||
def self.separate(wiki_word)
|
def self.separate(wiki_word)
|
||||||
wiki_word.gsub(CAMEL_CASED_WORD_BORDER, '\1 \2')
|
wiki_word.gsub(CAMEL_CASED_WORD_BORDER, '\1 \2')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
<%
|
<%
|
||||||
@title = "Upload #{@file_name}"
|
@title = "Upload #{@file_name}"
|
||||||
@hide_navigatio = false
|
@hide_navigatio = false
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= form_tag({}, {:multipart => true}) %>
|
<%= form_tag({}, {:multipart => true}) %>
|
||||||
<p>
|
<p>
|
||||||
File to upload:
|
File to upload:
|
||||||
<br/>
|
<br/>
|
||||||
<input type="file" name="file" size="40" />
|
<input type="file" name="file" size="40" />
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input type="submit" value="Update" /> as
|
<input type="submit" value="Update" /> as
|
||||||
<input type="text" name="author" id="authorName" value="<%= @author %>"
|
<input type="text" name="author" id="authorName" value="<%= @author %>"
|
||||||
onClick="this.value == 'AnonymousCoward' ? this.value = '' : true" />
|
onClick="this.value == 'AnonymousCoward' ? this.value = '' : true" />
|
||||||
<% if @page %>
|
<% if @page %>
|
||||||
| <a href="../file/">Cancel</a> <small>(unlocks page)</small>
|
| <a href="../file/">Cancel</a> <small>(unlocks page)</small>
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<%= end_form_tag %>
|
<%= end_form_tag %>
|
||||||
</p>
|
</p>
|
|
@ -1,72 +1,72 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>
|
||||||
<% if @page and (@page.name == 'HomePage') and (%w( show published print ).include?(@action_name)) %>
|
<% if @page and (@page.name == 'HomePage') and (%w( show published print ).include?(@action_name)) %>
|
||||||
<%= @web.name %>
|
<%= @web.name %>
|
||||||
<% elsif @web %>
|
<% elsif @web %>
|
||||||
<%= @title %> in <%= @web.name %>
|
<%= @title %> in <%= @web.name %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= @title %>
|
<%= @title %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
h1#pageName, .newWikiWord a, a.existingWikiWord, .newWikiWord a:hover, #TextileHelp h3 {
|
h1#pageName, .newWikiWord a, a.existingWikiWord, .newWikiWord a:hover, #TextileHelp h3 {
|
||||||
color: #<%= @web ? @web.color : "393" %>;
|
color: #<%= @web ? @web.color : "393" %>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#Container, #Content {
|
#Container, #Content {
|
||||||
width: <%= @content_width || "600" %>px;
|
width: <%= @content_width || "600" %>px;
|
||||||
}
|
}
|
||||||
<%= File.read(RAILS_ROOT + '/public/stylesheets/instiki.css') if @inline_style %>
|
<%= File.read(RAILS_ROOT + '/public/stylesheets/instiki.css') if @inline_style %>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<link rel="Stylesheet" href="/stylesheets/instiki.css" type="text/css" media="screen" />
|
<link rel="Stylesheet" href="/stylesheets/instiki.css" type="text/css" media="screen" />
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
<%= @style_additions %>
|
<%= @style_additions %>
|
||||||
<%= @web ? @web.additional_style : '' %>
|
<%= @web ? @web.additional_style : '' %>
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="Container">
|
<div id="Container">
|
||||||
<div id="Content">
|
<div id="Content">
|
||||||
|
|
||||||
<h1 id="pageName">
|
<h1 id="pageName">
|
||||||
<% if @page and (@page.name == 'HomePage') and %w( show published print ).include?(@action_name) %>
|
<% if @page and (@page.name == 'HomePage') and %w( show published print ).include?(@action_name) %>
|
||||||
<%= @web.name %>
|
<%= @web.name %>
|
||||||
<% elsif @web %>
|
<% elsif @web %>
|
||||||
<small><%= @web.name %></small><br />
|
<small><%= @web.name %></small><br />
|
||||||
<%= @title %>
|
<%= @title %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= @title %>
|
<%= @title %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<% if @flash[:error] %> <div id="error">
|
<% if @flash[:error] %> <div id="error">
|
||||||
<hr/><p><%= @flash[:error].to_s %></p><hr/></div>
|
<hr/><p><%= @flash[:error].to_s %></p><hr/></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @flash[:info] %> <div id="info">
|
<% if @flash[:info] %> <div id="info">
|
||||||
<hr/><p><%= @flash[:info].to_s %></p><hr/></div>
|
<hr/><p><%= @flash[:info].to_s %></p><hr/></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render 'navigation' unless @web.nil? || @hide_navigation %>
|
<%= render 'navigation' unless @web.nil? || @hide_navigation %>
|
||||||
<%= @content_for_layout %>
|
<%= @content_for_layout %>
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<hr/>
|
<hr/>
|
||||||
<p>This site is running on <a href="http://instiki.org/">Instiki</a></p>
|
<p>This site is running on <a href="http://instiki.org/">Instiki</a></p>
|
||||||
<br/>
|
<br/>
|
||||||
<p>Powered by <a href="http://rubyonrails.com/">Ruby on Rails</a></p>
|
<p>Powered by <a href="http://rubyonrails.com/">Ruby on Rails</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div> <!-- Content -->
|
</div> <!-- Content -->
|
||||||
</div> <!-- Container -->
|
</div> <!-- Container -->
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
30
app/views/markdown_help.rhtml
Executable file → Normal file
30
app/views/markdown_help.rhtml
Executable file → Normal file
|
@ -1,16 +1,16 @@
|
||||||
<div id="TextileHelp" style="float: right; width: 250px; margin-top: 5px">
|
<div id="TextileHelp" style="float: right; width: 250px; margin-top: 5px">
|
||||||
<h3>Markdown formatting tips (<a target="_new" href="http://daringfireball.net/projects/markdown/syntax">advanced</a>)</h3>
|
<h3>Markdown formatting tips (<a target="_new" href="http://daringfireball.net/projects/markdown/syntax">advanced</a>)</h3>
|
||||||
<table cellspacing="0" cellpadding="0">
|
<table cellspacing="0" cellpadding="0">
|
||||||
<tr><td>_your text_</td><td class="arrow">→</td><td><em>your text</em></td></tr>
|
<tr><td>_your text_</td><td class="arrow">→</td><td><em>your text</em></td></tr>
|
||||||
<tr><td>**your text**</td><td class="arrow">→</td><td><strong>your text</strong></td></tr>
|
<tr><td>**your text**</td><td class="arrow">→</td><td><strong>your text</strong></td></tr>
|
||||||
<tr><td>`my code`</td><td class="arrow">→</td><td><code>my code</code></td></tr>
|
<tr><td>`my code`</td><td class="arrow">→</td><td><code>my code</code></td></tr>
|
||||||
<tr><td>* Bulleted list<br />* Second item</td><td class="arrow">→</td><td>• Bulleted list<br />• Second item</td></tr>
|
<tr><td>* Bulleted list<br />* Second item</td><td class="arrow">→</td><td>• Bulleted list<br />• Second item</td></tr>
|
||||||
<tr><td>1. Numbered list<br />1. Second item</td><td class="arrow">→</td><td>1. Numbered list<br />2. Second item</td></tr>
|
<tr><td>1. Numbered list<br />1. Second item</td><td class="arrow">→</td><td>1. Numbered list<br />2. Second item</td></tr>
|
||||||
<tr><td>[link name](URL)</td><td class="arrow">→</td><td><a href="URL">link name</a></td></tr>
|
<tr><td>[link name](URL)</td><td class="arrow">→</td><td><a href="URL">link name</a></td></tr>
|
||||||
<tr><td>***</td><td class="arrow">→</td><td>Horizontal ruler</td></tr>
|
<tr><td>***</td><td class="arrow">→</td><td>Horizontal ruler</td></tr>
|
||||||
<tr><td><http://url><br /><email@add.com></td><td class="arrow">→</td><td>Auto-linked</td></tr>
|
<tr><td><http://url><br /><email@add.com></td><td class="arrow">→</td><td>Auto-linked</td></tr>
|
||||||
<tr><td>![Alt text](URL)</td><td class="arrow">→</td><td>Image</td></tr>
|
<tr><td>![Alt text](URL)</td><td class="arrow">→</td><td>Image</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<%= render 'wiki_words_help' %>
|
<%= render 'wiki_words_help' %>
|
||||||
</div>
|
</div>
|
50
app/views/navigation.rhtml
Executable file → Normal file
50
app/views/navigation.rhtml
Executable file → Normal file
|
@ -1,25 +1,25 @@
|
||||||
<%
|
<%
|
||||||
def list_item(title, url, description, accesskey = nil)
|
def list_item(title, url, description, accesskey = nil)
|
||||||
if @title == title
|
if @title == title
|
||||||
"<b class=\"navOn\" title=\"#{description}\" accesskey=\"#{accesskey}\">#{title}</b>"
|
"<b class=\"navOn\" title=\"#{description}\" accesskey=\"#{accesskey}\">#{title}</b>"
|
||||||
else
|
else
|
||||||
"<a href=\"#{url}\" title=\"#{description}\" accesskey=\"#{accesskey}\">#{title}</a>"
|
"<a href=\"#{url}\" title=\"#{description}\" accesskey=\"#{accesskey}\">#{title}</a>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<form id="navigationForm" class="navigation" action="../search/" method="get" style="font-size: 10px">
|
<form id="navigationForm" class="navigation" action="../search/" method="get" style="font-size: 10px">
|
||||||
|
|
||||||
<% if @action_name != "published" then %>
|
<% if @action_name != "published" then %>
|
||||||
<%= list_item "Home Page", "../show/HomePage", "Home, Sweet Home", "H" %> |
|
<%= list_item "Home Page", "../show/HomePage", "Home, Sweet Home", "H" %> |
|
||||||
<%= list_item "All Pages", "../list/", "Alphabetically sorted list of pages", "A" %> |
|
<%= list_item "All Pages", "../list/", "Alphabetically sorted list of pages", "A" %> |
|
||||||
<%= list_item "Recently Revised", "../recently_revised/", "Pages sorted by when they were last changed", "U" %> |
|
<%= list_item "Recently Revised", "../recently_revised/", "Pages sorted by when they were last changed", "U" %> |
|
||||||
<%= list_item "Authors", "../authors/", "Who wrote what" %> |
|
<%= list_item "Authors", "../authors/", "Who wrote what" %> |
|
||||||
<%= list_item "Feeds", "../feeds/", "Subscribe to changes by RSS" %> |
|
<%= list_item "Feeds", "../feeds/", "Subscribe to changes by RSS" %> |
|
||||||
<%= list_item "Export", "../export/", "Download a zip with all the pages in this wiki", "X" %> |
|
<%= list_item "Export", "../export/", "Download a zip with all the pages in this wiki", "X" %> |
|
||||||
<input type="text" id="searchField" name="query" style="font-size: 10px" value="Search" onClick="this.value == 'Search' ? this.value = '' : true" />
|
<input type="text" id="searchField" name="query" style="font-size: 10px" value="Search" onClick="this.value == 'Search' ? this.value = '' : true" />
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= list_item "Home Page", "../published/HomePage", "Home, Sweet Home", "H" %> |
|
<%= list_item "Home Page", "../published/HomePage", "Home, Sweet Home", "H" %> |
|
||||||
<% end%>
|
<% end%>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
30
app/views/rdoc_help.rhtml
Executable file → Normal file
30
app/views/rdoc_help.rhtml
Executable file → Normal file
|
@ -1,16 +1,16 @@
|
||||||
<div id="TextileHelp" style="float: right; width: 250px; margin-top: 5px">
|
<div id="TextileHelp" style="float: right; width: 250px; margin-top: 5px">
|
||||||
<h3>RDoc formatting tips (<a target="_new" href="http://rdoc.sourceforge.net/doc/files/markup/simple_markup_rb.html">advanced</a>)</h3>
|
<h3>RDoc formatting tips (<a target="_new" href="http://rdoc.sourceforge.net/doc/files/markup/simple_markup_rb.html">advanced</a>)</h3>
|
||||||
<table cellspacing="0" cellpadding="0">
|
<table cellspacing="0" cellpadding="0">
|
||||||
<tr><td>_your text_</td><td class="arrow">→</td><td><em>your text</em></td></tr>
|
<tr><td>_your text_</td><td class="arrow">→</td><td><em>your text</em></td></tr>
|
||||||
<tr><td>*your text*</td><td class="arrow">→</td><td><strong>your text</strong></td></tr>
|
<tr><td>*your text*</td><td class="arrow">→</td><td><strong>your text</strong></td></tr>
|
||||||
<tr><td>* Bulleted list<br />* Second item</td><td class="arrow">→</td><td>• Bulleted list<br />• Second item</td></tr>
|
<tr><td>* Bulleted list<br />* Second item</td><td class="arrow">→</td><td>• Bulleted list<br />• Second item</td></tr>
|
||||||
<tr><td>1. Numbered list<br />2. Second item</td><td class="arrow">→</td><td>1. Numbered list<br />2. Second item</td></tr>
|
<tr><td>1. Numbered list<br />2. Second item</td><td class="arrow">→</td><td>1. Numbered list<br />2. Second item</td></tr>
|
||||||
<tr><td>+my_code+</td><td class="arrow">→</td><td><code>my_code</code></td></tr>
|
<tr><td>+my_code+</td><td class="arrow">→</td><td><code>my_code</code></td></tr>
|
||||||
<tr><td>---</td><td class="arrow">→</td><td>Horizontal ruler</td></tr>
|
<tr><td>---</td><td class="arrow">→</td><td>Horizontal ruler</td></tr>
|
||||||
<tr><td>[[URL linkname]]</td><td class="arrow">→</td><td><a href="URL">linkname</a></td></tr>
|
<tr><td>[[URL linkname]]</td><td class="arrow">→</td><td><a href="URL">linkname</a></td></tr>
|
||||||
<tr><td>http://url<br />mailto:e@add.com</td><td class="arrow">→</td><td>Auto-linked</td></tr>
|
<tr><td>http://url<br />mailto:e@add.com</td><td class="arrow">→</td><td>Auto-linked</td></tr>
|
||||||
<tr><td>imageURL</td><td class="arrow">→</td><td>Image</td></tr>
|
<tr><td>imageURL</td><td class="arrow">→</td><td>Image</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<%= render 'wiki_words_help' %>
|
<%= render 'wiki_words_help' %>
|
||||||
</div>
|
</div>
|
54
app/views/textile_help.rhtml
Executable file → Normal file
54
app/views/textile_help.rhtml
Executable file → Normal file
|
@ -1,28 +1,28 @@
|
||||||
<div id="TextileHelp" style="float: right; width: 250px; margin-top: 5px">
|
<div id="TextileHelp" style="float: right; width: 250px; margin-top: 5px">
|
||||||
<h3>Textile formatting tips (<a href="#" onClick="quickRedReference(); return false;">advanced</a>)</h3>
|
<h3>Textile formatting tips (<a href="#" onClick="quickRedReference(); return false;">advanced</a>)</h3>
|
||||||
<table cellspacing="0" cellpadding="0">
|
<table cellspacing="0" cellpadding="0">
|
||||||
<tr><td>_your text_</td><td class="arrow">→</td><td><em>your text</em></td></tr>
|
<tr><td>_your text_</td><td class="arrow">→</td><td><em>your text</em></td></tr>
|
||||||
<tr><td>*your text*</td><td class="arrow">→</td><td><strong>your text</strong></td></tr>
|
<tr><td>*your text*</td><td class="arrow">→</td><td><strong>your text</strong></td></tr>
|
||||||
<tr><td>%{color:red}hello%</td><td class="arrow">→</td><td><span style="color: red;">hello</span></td></tr>
|
<tr><td>%{color:red}hello%</td><td class="arrow">→</td><td><span style="color: red;">hello</span></td></tr>
|
||||||
<tr><td>* Bulleted list<br />* Second item</td><td class="arrow">→</td><td>• Bulleted list<br />• Second item</td></tr>
|
<tr><td>* Bulleted list<br />* Second item</td><td class="arrow">→</td><td>• Bulleted list<br />• Second item</td></tr>
|
||||||
<tr><td># Numbered list<br /># Second item</td><td class="arrow">→</td><td>1. Numbered list<br />2. Second item</td></tr>
|
<tr><td># Numbered list<br /># Second item</td><td class="arrow">→</td><td>1. Numbered list<br />2. Second item</td></tr>
|
||||||
<tr><td>"linkname":URL</td><td class="arrow">→</td><td><a href="URL">linkname</a></td></tr>
|
<tr><td>"linkname":URL</td><td class="arrow">→</td><td><a href="URL">linkname</a></td></tr>
|
||||||
<tr><td>|a|table|row|<br />|b|table|row|</td><td class="arrow">→</td><td>Table</td></tr>
|
<tr><td>|a|table|row|<br />|b|table|row|</td><td class="arrow">→</td><td>Table</td></tr>
|
||||||
<tr><td>http://url<br />email@address.com</td><td class="arrow">→</td><td>Auto-linked</td></tr>
|
<tr><td>http://url<br />email@address.com</td><td class="arrow">→</td><td>Auto-linked</td></tr>
|
||||||
<tr><td>!imageURL!</td><td class="arrow">→</td><td>Image</td></tr>
|
<tr><td>!imageURL!</td><td class="arrow">→</td><td>Image</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<%= render 'wiki_words_help' %>
|
<%= render 'wiki_words_help' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script language="JavaScript">
|
<script language="JavaScript">
|
||||||
function quickRedReference() {
|
function quickRedReference() {
|
||||||
window.open(
|
window.open(
|
||||||
"http://hobix.com/textile/quick.html",
|
"http://hobix.com/textile/quick.html",
|
||||||
"redRef",
|
"redRef",
|
||||||
"height=600,width=550,channelmode=0,dependent=0," +
|
"height=600,width=550,channelmode=0,dependent=0," +
|
||||||
"directories=0,fullscreen=0,location=0,menubar=0," +
|
"directories=0,fullscreen=0,location=0,menubar=0," +
|
||||||
"resizable=0,scrollbars=1,status=1,toolbar=0"
|
"resizable=0,scrollbars=1,status=1,toolbar=0"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
22
app/views/wiki/authors.rhtml
Executable file → Normal file
22
app/views/wiki/authors.rhtml
Executable file → Normal file
|
@ -1,11 +1,11 @@
|
||||||
<% @title = 'Authors' %>
|
<% @title = 'Authors' %>
|
||||||
|
|
||||||
<ul id="authorList">
|
<ul id="authorList">
|
||||||
<% for author in @authors %>
|
<% for author in @authors %>
|
||||||
<li>
|
<li>
|
||||||
<%= @web.make_link(author) %>
|
<%= @web.make_link(author) %>
|
||||||
co- or authored:
|
co- or authored:
|
||||||
<%= @web.select.pages_authored_by(author).collect { |page| page.link }.join ', ' %>
|
<%= @web.select.pages_authored_by(author).collect { |page| page.link }.join ', ' %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
58
app/views/wiki/edit.rhtml
Executable file → Normal file
58
app/views/wiki/edit.rhtml
Executable file → Normal file
|
@ -1,29 +1,29 @@
|
||||||
<%
|
<%
|
||||||
@title = "Editing #{@page.name}"
|
@title = "Editing #{@page.name}"
|
||||||
@content_width = 720
|
@content_width = 720
|
||||||
@hide_navigation = true
|
@hide_navigation = true
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= "<p style='color:red'>Please correct the error that caused this error in rendering:<br/><small>#{@params["msg"]}</small></p>" if @params["msg"] %>
|
<%= "<p style='color:red'>Please correct the error that caused this error in rendering:<br/><small>#{@params["msg"]}</small></p>" if @params["msg"] %>
|
||||||
|
|
||||||
<%= render("#{@web.markup}_help") if @web %>
|
<%= render("#{@web.markup}_help") if @web %>
|
||||||
|
|
||||||
<form id="editForm" action="../save/<%= @page.name %>" method="post" onSubmit="cleanAuthorName();">
|
<form id="editForm" action="../save/<%= @page.name %>" method="post" onSubmit="cleanAuthorName();">
|
||||||
<p>
|
<p>
|
||||||
<textarea name="content" style="width: 450px; height: 500px"><%= @page.content %></textarea>
|
<textarea name="content" style="width: 450px; height: 500px"><%= @page.content %></textarea>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input type="submit" value="Update" /> as
|
<input type="submit" value="Update" /> as
|
||||||
<input type="text" name="author" id="authorName" value="<%= @author %>"
|
<input type="text" name="author" id="authorName" value="<%= @author %>"
|
||||||
onClick="this.value == 'AnonymousCoward' ? this.value = '' : true" />
|
onClick="this.value == 'AnonymousCoward' ? this.value = '' : true" />
|
||||||
| <a href="../cancel_edit/<%= @page.name %>">Cancel</a> <small>(unlocks page)</small>
|
| <a href="../cancel_edit/<%= @page.name %>">Cancel</a> <small>(unlocks page)</small>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script language="JavaScript1.2">
|
<script language="JavaScript1.2">
|
||||||
function cleanAuthorName() {
|
function cleanAuthorName() {
|
||||||
if (document.getElementById('authorName').value == "") {
|
if (document.getElementById('authorName').value == "") {
|
||||||
document.getElementById('authorName').value = 'AnonymousCoward';
|
document.getElementById('authorName').value = 'AnonymousCoward';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
234
app/views/wiki/edit_web.rhtml
Executable file → Normal file
234
app/views/wiki/edit_web.rhtml
Executable file → Normal file
|
@ -1,117 +1,117 @@
|
||||||
<% @title = "Edit Web" %>
|
<% @title = "Edit Web" %>
|
||||||
|
|
||||||
<form action="../update_web" id="setup" method="post" onSubmit="cleanAddress(); return validateSetup()">
|
<form action="../update_web" id="setup" method="post" onSubmit="cleanAddress(); return validateSetup()">
|
||||||
<h2 style="margin-bottom: 3px">Name and address</h2>
|
<h2 style="margin-bottom: 3px">Name and address</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
The name of the web is included in the title on all pages.
|
The name of the web is included in the title on all pages.
|
||||||
The address is the base path that all pages within the web live beneath.
|
The address is the base path that all pages within the web live beneath.
|
||||||
Ex: the address "rails" gives URLs like <i>/rails/show/HomePage</i>.
|
Ex: the address "rails" gives URLs like <i>/rails/show/HomePage</i>.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inputBox, disableAutoComplete">
|
<div class="inputBox, disableAutoComplete">
|
||||||
Name: <input type="text" id="name" name="name" value="<%= @web.name %>"
|
Name: <input type="text" id="name" name="name" value="<%= @web.name %>"
|
||||||
onChange="proposeAddress();" />
|
onChange="proposeAddress();" />
|
||||||
Address: <input type="text" id="address" name="address" value="<%= @web.address %>"
|
Address: <input type="text" id="address" name="address" value="<%= @web.address %>"
|
||||||
onChange="cleanAddress();" />
|
onChange="cleanAddress();" />
|
||||||
<i>(Letters and digits only)</i>
|
<i>(Letters and digits only)</i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 style="margin-bottom: 3px">Specialize</h2>
|
<h2 style="margin-bottom: 3px">Specialize</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
Turning safe mode on will strip HTML tags and stylesheet options from the content of all pages.
|
Turning safe mode on will strip HTML tags and stylesheet options from the content of all pages.
|
||||||
Turning on "brackets only" will require all wiki words to be as [[wiki word]] and WikiWord
|
Turning on "brackets only" will require all wiki words to be as [[wiki word]] and WikiWord
|
||||||
won't work.
|
won't work.
|
||||||
Turning "allow uploads" on will let wiki users to upload pictures and other files to the wiki
|
Turning "allow uploads" on will let wiki users to upload pictures and other files to the wiki
|
||||||
and include them on wiki pages.
|
and include them on wiki pages.
|
||||||
Additions to the stylesheet take precedence over the existing styles.
|
Additions to the stylesheet take precedence over the existing styles.
|
||||||
<i>Hint:</i> View source on a page you want to style to find ID names on individual tags.
|
<i>Hint:</i> View source on a page you want to style to find ID names on individual tags.
|
||||||
<a href="#" onClick="document.getElementById('additionalStyle').style.display='block';return false;">
|
<a href="#" onClick="document.getElementById('additionalStyle').style.display='block';return false;">
|
||||||
See styles >>
|
See styles >>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="inputBox, disableAutoComplete">
|
<div class="inputBox, disableAutoComplete">
|
||||||
Markup:
|
Markup:
|
||||||
<select name="markup">
|
<select name="markup">
|
||||||
<%= html_options({"Textile" => :textile, "Markdown" => :markdown, "RDoc" => :rdoc },
|
<%= html_options({"Textile" => :textile, "Markdown" => :markdown, "RDoc" => :rdoc },
|
||||||
@web.markup) %>
|
@web.markup) %>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Color:
|
Color:
|
||||||
<select name="color">
|
<select name="color">
|
||||||
<%= html_options({ "Green" => "008B26", "Purple" => "504685", "Red" => "DA0006",
|
<%= html_options({ "Green" => "008B26", "Purple" => "504685", "Red" => "DA0006",
|
||||||
"Orange" => "FA6F00", "Grey" => "8BA2B0" }, @web.color) %>
|
"Orange" => "FA6F00", "Grey" => "8BA2B0" }, @web.color) %>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<small>
|
<small>
|
||||||
<input type="checkbox" name="safe_mode" <%= 'checked="on"' if @web.safe_mode %> /> Safe mode
|
<input type="checkbox" name="safe_mode" <%= 'checked="on"' if @web.safe_mode %> /> Safe mode
|
||||||
|
|
||||||
<input type="checkbox" name="brackets_only" <%= 'checked="on"' if @web.brackets_only %> />
|
<input type="checkbox" name="brackets_only" <%= 'checked="on"' if @web.brackets_only %> />
|
||||||
Brackets only
|
Brackets only
|
||||||
|
|
||||||
<input type="checkbox" name="count_pages" <%= 'checked="on"' if @web.count_pages %> /> Count pages
|
<input type="checkbox" name="count_pages" <%= 'checked="on"' if @web.count_pages %> /> Count pages
|
||||||
|
|
||||||
<input type="checkbox" name="allow_uploads" <%= 'checked="on"' if @web.allow_uploads %> /> Allow uploads
|
<input type="checkbox" name="allow_uploads" <%= 'checked="on"' if @web.allow_uploads %> /> Allow uploads
|
||||||
</small>
|
</small>
|
||||||
|
|
||||||
<textarea id="additionalStyle"
|
<textarea id="additionalStyle"
|
||||||
style="display: none; margin-top: 10px; margin-bottom: 5px; width: 560px; height: 200px"
|
style="display: none; margin-top: 10px; margin-bottom: 5px; width: 560px; height: 200px"
|
||||||
name="additional_style"><%= @web.additional_style %>
|
name="additional_style"><%= @web.additional_style %>
|
||||||
</textarea>
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 style="margin-bottom: 3px">Password protection for this web (<%= @web.name %>)</h2>
|
<h2 style="margin-bottom: 3px">Password protection for this web (<%= @web.name %>)</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
This is the password that visitors need to view and edit this web.
|
This is the password that visitors need to view and edit this web.
|
||||||
Setting the password to nothing will remove the password protection.
|
Setting the password to nothing will remove the password protection.
|
||||||
</div>
|
</div>
|
||||||
<div class="inputBox">
|
<div class="inputBox">
|
||||||
Password: <input class="disableAutoComplete" type="password" id="password"
|
Password: <input class="disableAutoComplete" type="password" id="password"
|
||||||
name="password" value="<%= @web.password %>" />
|
name="password" value="<%= @web.password %>" />
|
||||||
|
|
||||||
Verify: <input class="disableAutoComplete" type="password" id="password_check"
|
Verify: <input class="disableAutoComplete" type="password" id="password_check"
|
||||||
value="<%= @web.password %>" name="password_check" />
|
value="<%= @web.password %>" name="password_check" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 style="margin-bottom: 3px">Publish read-only version of this web (<%= @web.name %>)</h2>
|
<h2 style="margin-bottom: 3px">Publish read-only version of this web (<%= @web.name %>)</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
You can turn on a read-only version of this web that's accessible even when the regular web
|
You can turn on a read-only version of this web that's accessible even when the regular web
|
||||||
is password protected.
|
is password protected.
|
||||||
The published version is accessible through URLs like /wiki/published/HomePage.
|
The published version is accessible through URLs like /wiki/published/HomePage.
|
||||||
</div>
|
</div>
|
||||||
<div class="inputBox">
|
<div class="inputBox">
|
||||||
<input type="checkbox" name="published" <%= 'checked="on"' if @web.published %> /> Publish this web
|
<input type="checkbox" name="published" <%= 'checked="on"' if @web.published %> /> Publish this web
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p align="right">
|
<p align="right">
|
||||||
<small>
|
<small>
|
||||||
Enter system password
|
Enter system password
|
||||||
<input type="password" class="disableAutoComplete" id="system_password" name="system_password" />
|
<input type="password" class="disableAutoComplete" id="system_password" name="system_password" />
|
||||||
and
|
and
|
||||||
<input type="submit" value="Update Web" />
|
<input type="submit" value="Update Web" />
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
...or forget changes and <a href="/new_web/">create a new web</a>
|
...or forget changes and <a href="/new_web/">create a new web</a>
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<h1>Other administrative tasks</h1>
|
<h1>Other administrative tasks</h1>
|
||||||
|
|
||||||
<form action="../remove_orphaned_pages" id="remove_orphaned_pages" method="post">
|
<form action="../remove_orphaned_pages" id="remove_orphaned_pages" method="post">
|
||||||
<p align="right">
|
<p align="right">
|
||||||
<small>
|
<small>
|
||||||
Clean up by entering system password
|
Clean up by entering system password
|
||||||
<input type="password" id="system_password" name="system_password" />
|
<input type="password" id="system_password" name="system_password" />
|
||||||
and
|
and
|
||||||
<input type="submit" value="Delete Orphan Pages" />
|
<input type="submit" value="Delete Orphan Pages" />
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script type="text/javascript" src="/javascripts/edit_web.js" />
|
<script type="text/javascript" src="/javascripts/edit_web.js" />
|
||||||
<script type="text/javascript">overrideAutocomplete()</script>
|
<script type="text/javascript">overrideAutocomplete()</script>
|
||||||
|
|
24
app/views/wiki/export.rhtml
Executable file → Normal file
24
app/views/wiki/export.rhtml
Executable file → Normal file
|
@ -1,12 +1,12 @@
|
||||||
<% @title = "Export" %>
|
<% @title = "Export" %>
|
||||||
|
|
||||||
<p>You can export all the pages in this web as a zip file in either HTML (with working links and all) or the pure markup (to import in another wiki).</p>
|
<p>You can export all the pages in this web as a zip file in either HTML (with working links and all) or the pure markup (to import in another wiki).</p>
|
||||||
|
|
||||||
<ul id="feedsList">
|
<ul id="feedsList">
|
||||||
<li><a href="../export_html">HTML</a>
|
<li><a href="../export_html">HTML</a>
|
||||||
<li><a href="../export_markup">Markup (<%= @web.markup %>)</a>
|
<li><a href="../export_markup">Markup (<%= @web.markup %>)</a>
|
||||||
<% if OPTIONS[:pdflatex] && @web.markup == :textile %>
|
<% if OPTIONS[:pdflatex] && @web.markup == :textile %>
|
||||||
<li><a href="../export_tex">TeX</a>
|
<li><a href="../export_tex">TeX</a>
|
||||||
<li><a href="../export_pdf">PDF</a>
|
<li><a href="../export_pdf">PDF</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
16
app/views/wiki/feeds.rhtml
Executable file → Normal file
16
app/views/wiki/feeds.rhtml
Executable file → Normal file
|
@ -1,8 +1,8 @@
|
||||||
<% @title = "Feeds" %>
|
<% @title = "Feeds" %>
|
||||||
|
|
||||||
<p>You can subscribe to this wiki by RSS and get either just the headlines of the pages that change or the entire page.</p>
|
<p>You can subscribe to this wiki by RSS and get either just the headlines of the pages that change or the entire page.</p>
|
||||||
|
|
||||||
<ul id="feedsList">
|
<ul id="feedsList">
|
||||||
<li><a href="../rss_with_content<%= "?password=#{web.password}" if @web.password %>">Full content (RSS 2.0)</a>
|
<li><a href="../rss_with_content<%= "?password=#{web.password}" if @web.password %>">Full content (RSS 2.0)</a>
|
||||||
<li><a href="../rss_with_headlines<%= "?password=#{web.password}" if @web.password %>">Headlines (RSS 2.0)</a>
|
<li><a href="../rss_with_headlines<%= "?password=#{web.password}" if @web.password %>">Headlines (RSS 2.0)</a>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
114
app/views/wiki/list.rhtml
Executable file → Normal file
114
app/views/wiki/list.rhtml
Executable file → Normal file
|
@ -1,57 +1,57 @@
|
||||||
<% @title = "All Pages" %>
|
<% @title = "All Pages" %>
|
||||||
|
|
||||||
<% unless @categories.empty? %>
|
<% unless @categories.empty? %>
|
||||||
<div id="categories">
|
<div id="categories">
|
||||||
<strong>Categories</strong>:
|
<strong>Categories</strong>:
|
||||||
[<a href=".">Any</a>]
|
[<a href=".">Any</a>]
|
||||||
<%= @category_links.join(', ') %>
|
<%= @category_links.join(', ') %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div id="allPages" style="float: left; width: 280px; margin-right: 30px">
|
<div id="allPages" style="float: left; width: 280px; margin-right: 30px">
|
||||||
<% unless @pages_that_are_orphaned.empty? && @page_names_that_are_wanted.empty? %>
|
<% unless @pages_that_are_orphaned.empty? && @page_names_that_are_wanted.empty? %>
|
||||||
<h2>
|
<h2>
|
||||||
All Pages
|
All Pages
|
||||||
<br/><small style="font-size: 12px"><i>All pages in <%= @set_name %> listed alphabetically</i></small>
|
<br/><small style="font-size: 12px"><i>All pages in <%= @set_name %> listed alphabetically</i></small>
|
||||||
</h2>
|
</h2>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<ul><% for page in @pages_by_name %>
|
<ul><% for page in @pages_by_name %>
|
||||||
<li><a href="../show/<%= page.name %>"><%= truncate(page.plain_name, 35) %></a></li>
|
<li><a href="../show/<%= page.name %>"><%= truncate(page.plain_name, 35) %></a></li>
|
||||||
<% end %></ul>
|
<% end %></ul>
|
||||||
|
|
||||||
<% if @web.count_pages %>
|
<% if @web.count_pages %>
|
||||||
<% total_chars = @pages_in_category.characters %>
|
<% total_chars = @pages_in_category.characters %>
|
||||||
<p><small>All content: <%= total_chars %> chars / <%= sprintf("%-.1f", (total_chars / 2275 )) %> pages</small></p>
|
<p><small>All content: <%= total_chars %> chars / <%= sprintf("%-.1f", (total_chars / 2275 )) %> pages</small></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="float: left; width: 280px">
|
<div style="float: left; width: 280px">
|
||||||
<% unless @page_names_that_are_wanted.empty? %>
|
<% unless @page_names_that_are_wanted.empty? %>
|
||||||
<h2>
|
<h2>
|
||||||
Wanted Pages
|
Wanted Pages
|
||||||
<br/><small style="font-size: 12px"><i>Unexisting pages that other pages in <%= @set_name %> reference</i></small>
|
<br/><small style="font-size: 12px"><i>Unexisting pages that other pages in <%= @set_name %> reference</i></small>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<ul style="margin-bottom: 10px">
|
<ul style="margin-bottom: 10px">
|
||||||
<% for page_name in @page_names_that_are_wanted %>
|
<% for page_name in @page_names_that_are_wanted %>
|
||||||
<li>
|
<li>
|
||||||
<a href="../show/<%= page_name %>"><%= truncate(WikiWords.separate(page_name), 35) %></a>
|
<a href="../show/<%= page_name %>"><%= truncate(WikiWords.separate(page_name), 35) %></a>
|
||||||
wanted by
|
wanted by
|
||||||
<%= @web.select.pages_that_reference(page_name).collect { |page| page.link }.join(", ") %>
|
<%= @web.select.pages_that_reference(page_name).collect { |page| page.link }.join(", ") %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% unless @pages_that_are_orphaned.empty? %>
|
<% unless @pages_that_are_orphaned.empty? %>
|
||||||
<h2>
|
<h2>
|
||||||
Orphaned Pages
|
Orphaned Pages
|
||||||
<br/><small style="font-size: 12px"><i>Pages in <%= @set_name %> that no other page reference</i></small>
|
<br/><small style="font-size: 12px"><i>Pages in <%= @set_name %> that no other page reference</i></small>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<ul style="margin-bottom: 35px">
|
<ul style="margin-bottom: 35px">
|
||||||
<% for page in @pages_that_are_orphaned %><li><a href="../show/<%= page.name %>"><%= truncate(page.plain_name, 35) %></a></li><% end %>
|
<% for page in @pages_that_are_orphaned %><li><a href="../show/<%= page.name %>"><%= truncate(page.plain_name, 35) %></a></li><% end %>
|
||||||
</ul>
|
</ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
40
app/views/wiki/locked.rhtml
Executable file → Normal file
40
app/views/wiki/locked.rhtml
Executable file → Normal file
|
@ -1,20 +1,20 @@
|
||||||
<% @title = "#{@page.plain_name} is locked" %>
|
<% @title = "#{@page.plain_name} is locked" %>
|
||||||
|
|
||||||
<% if @page.lock_duration(Time.now) == 0 %>
|
<% if @page.lock_duration(Time.now) == 0 %>
|
||||||
<p><%= @page.locked_by_link %> just started editing this page.</p>
|
<p><%= @page.locked_by_link %> just started editing this page.</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p><%= @page.locked_by_link %> has been editing this page for <%= @page.lock_duration(Time.now) %> minutes.</p>
|
<p><%= @page.locked_by_link %> has been editing this page for <%= @page.lock_duration(Time.now) %> minutes.</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<%= link_to 'Edit the page anyway',
|
<%= link_to 'Edit the page anyway',
|
||||||
{:web => @web_name, :action => 'edit', :id => @page.name, :params => {'break_lock' => '1'} },
|
{:web => @web_name, :action => 'edit', :id => @page.name, :params => {'break_lock' => '1'} },
|
||||||
{:accesskey => 'E'}
|
{:accesskey => 'E'}
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= link_to 'Cancel',
|
<%= link_to 'Cancel',
|
||||||
{:web => @web_name, :action => 'show', :id => @page.name},
|
{:web => @web_name, :action => 'show', :id => @page.name},
|
||||||
{:accesskey => 'C'}
|
{:accesskey => 'C'}
|
||||||
%>
|
%>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
16
app/views/wiki/login.rhtml
Executable file → Normal file
16
app/views/wiki/login.rhtml
Executable file → Normal file
|
@ -1,8 +1,8 @@
|
||||||
<% @title = "#{@web_name} Login" %><% @hide_navigation = true %>
|
<% @title = "#{@web_name} Login" %><% @hide_navigation = true %>
|
||||||
|
|
||||||
<form action="authenticate" method="post">
|
<form action="authenticate" method="post">
|
||||||
<p>
|
<p>
|
||||||
<b>Password</b><br />
|
<b>Password</b><br />
|
||||||
<input type="password" name="password" />
|
<input type="password" name="password" />
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
50
app/views/wiki/new.rhtml
Executable file → Normal file
50
app/views/wiki/new.rhtml
Executable file → Normal file
|
@ -1,25 +1,25 @@
|
||||||
<%
|
<%
|
||||||
@title = "Creating #{WikiWords.separate(CGI.unescape(@page_name))}"
|
@title = "Creating #{WikiWords.separate(CGI.unescape(@page_name))}"
|
||||||
@content_width = 720
|
@content_width = 720
|
||||||
@hide_navigation = true
|
@hide_navigation = true
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= render("#{@web.markup}_help") if @web %>
|
<%= render("#{@web.markup}_help") if @web %>
|
||||||
|
|
||||||
<form action="../save/<%= @page_name %>" method="post" onSubmit="cleanAuthorName();">
|
<form action="../save/<%= @page_name %>" method="post" onSubmit="cleanAuthorName();">
|
||||||
<p>
|
<p>
|
||||||
<textarea name="content" style="width: 450px; height: 500px"></textarea>
|
<textarea name="content" style="width: 450px; height: 500px"></textarea>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<input type="submit" value="Create" /> as
|
<input type="submit" value="Create" /> as
|
||||||
<input type="text" name="author" id="authorName" value="<%= @author %>" onClick="this.value == 'AnonymousCoward' ? this.value = '' : true" />
|
<input type="text" name="author" id="authorName" value="<%= @author %>" onClick="this.value == 'AnonymousCoward' ? this.value = '' : true" />
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script language="JavaScript1.2">
|
<script language="JavaScript1.2">
|
||||||
function cleanAuthorName() {
|
function cleanAuthorName() {
|
||||||
if (document.getElementById('authorName').value == "") {
|
if (document.getElementById('authorName').value == "") {
|
||||||
document.getElementById('authorName').value = 'AnonymousCoward';
|
document.getElementById('authorName').value = 'AnonymousCoward';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
166
app/views/wiki/new_system.rhtml
Executable file → Normal file
166
app/views/wiki/new_system.rhtml
Executable file → Normal file
|
@ -1,83 +1,83 @@
|
||||||
<% @title = "Instiki Setup"; @content_width = 500 %>
|
<% @title = "Instiki Setup"; @content_width = 500 %>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Congratulations on succesfully installing and starting Instiki.
|
Congratulations on succesfully installing and starting Instiki.
|
||||||
Since this is the first time Instiki has been run on this port,
|
Since this is the first time Instiki has been run on this port,
|
||||||
you'll need to do a brief one-time setup.
|
you'll need to do a brief one-time setup.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form action="../create_system" id="setup" method="post" onSubmit="return validateSetup()">
|
<form action="../create_system" id="setup" method="post" onSubmit="return validateSetup()">
|
||||||
<ol class="setup">
|
<ol class="setup">
|
||||||
<li>
|
<li>
|
||||||
|
|
||||||
<h2 style="margin-bottom: 3px">Name and address for your first web</h2>
|
<h2 style="margin-bottom: 3px">Name and address for your first web</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
The name of the web is included in the title on all pages.
|
The name of the web is included in the title on all pages.
|
||||||
The address is the base path that all pages within the web live beneath.
|
The address is the base path that all pages within the web live beneath.
|
||||||
Ex: the address "rails" gives URLs like <i>/rails/show/HomePage</i>.
|
Ex: the address "rails" gives URLs like <i>/rails/show/HomePage</i>.
|
||||||
The address can only consist of letters and digits.
|
The address can only consist of letters and digits.
|
||||||
</div>
|
</div>
|
||||||
<div class="inputBox">
|
<div class="inputBox">
|
||||||
Name: <input type="text" id="web_name" name="web_name" value="Wiki"
|
Name: <input type="text" id="web_name" name="web_name" value="Wiki"
|
||||||
onChange="proposeAddress();" onClick="this.value == 'Wiki' ? this.value = '' : true" />
|
onChange="proposeAddress();" onClick="this.value == 'Wiki' ? this.value = '' : true" />
|
||||||
|
|
||||||
Address: <input type="text" id="web_address" name="web_address" onChange="cleanAddress();"
|
Address: <input type="text" id="web_address" name="web_address" onChange="cleanAddress();"
|
||||||
value="wiki" />
|
value="wiki" />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<h2 style="margin-bottom: 3px">Password for creating and changing webs</h2>
|
<h2 style="margin-bottom: 3px">Password for creating and changing webs</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
Administrative access allows you to make new webs and change existing ones.<br/>
|
Administrative access allows you to make new webs and change existing ones.<br/>
|
||||||
Everyone with this password will be able to do this, so pick it carefully.
|
Everyone with this password will be able to do this, so pick it carefully.
|
||||||
</div>
|
</div>
|
||||||
<div class="inputBox">
|
<div class="inputBox">
|
||||||
Password: <input type="password" id="password" name="password" />
|
Password: <input type="password" id="password" name="password" />
|
||||||
|
|
||||||
Verify: <input type="password" id="password_check" name="password_check" />
|
Verify: <input type="password" id="password_check" name="password_check" />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<p align="right">
|
<p align="right">
|
||||||
<input type="submit" value="Setup" style="margin-left: 40px" />
|
<input type="submit" value="Setup" style="margin-left: 40px" />
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function proposeAddress() {
|
function proposeAddress() {
|
||||||
document.getElementById('web_address').value =
|
document.getElementById('web_address').value =
|
||||||
document.getElementById('web_name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
document.getElementById('web_name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanAddress() {
|
function cleanAddress() {
|
||||||
document.getElementById('web_address').value =
|
document.getElementById('web_address').value =
|
||||||
document.getElementById('web_address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
document.getElementById('web_address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateSetup() {
|
function validateSetup() {
|
||||||
if (document.getElementById('web_name').value == "") {
|
if (document.getElementById('web_name').value == "") {
|
||||||
alert("You must pick a name for the first web");
|
alert("You must pick a name for the first web");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('web_address').value == "") {
|
if (document.getElementById('web_address').value == "") {
|
||||||
alert("You must pick an address for the first web");
|
alert("You must pick an address for the first web");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('password').value == "") {
|
if (document.getElementById('password').value == "") {
|
||||||
alert("You must pick a system password");
|
alert("You must pick a system password");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('password_check').value == "" ||
|
if (document.getElementById('password_check').value == "" ||
|
||||||
document.getElementById('password').value != document.getElementById('password_check').value) {
|
document.getElementById('password').value != document.getElementById('password_check').value) {
|
||||||
alert("The password and its verification doesn't match");
|
alert("The password and its verification doesn't match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
138
app/views/wiki/new_web.rhtml
Executable file → Normal file
138
app/views/wiki/new_web.rhtml
Executable file → Normal file
|
@ -1,69 +1,69 @@
|
||||||
<% @title = "New Wiki Web"; @content_width = 500 %>
|
<% @title = "New Wiki Web"; @content_width = 500 %>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Each web serves as an isolated name space for wiki pages,
|
Each web serves as an isolated name space for wiki pages,
|
||||||
so different subjects or projects can write about different <i>MuppetShows</i>.
|
so different subjects or projects can write about different <i>MuppetShows</i>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form action="../create_web" id="setup" method="post" onSubmit="cleanAddress();
|
<form action="../create_web" id="setup" method="post" onSubmit="cleanAddress();
|
||||||
return validateSetup()">
|
return validateSetup()">
|
||||||
|
|
||||||
<ol class="setup">
|
<ol class="setup">
|
||||||
<li>
|
<li>
|
||||||
<h2 style="margin-bottom: 3px">Name and address for your new web</h2>
|
<h2 style="margin-bottom: 3px">Name and address for your new web</h2>
|
||||||
<div class="help">
|
<div class="help">
|
||||||
The name of the web is included in the title on all pages.
|
The name of the web is included in the title on all pages.
|
||||||
The address is the base path that all pages within the web live beneath.
|
The address is the base path that all pages within the web live beneath.
|
||||||
Ex: the address "rails" gives URLs like <i>/rails/show/HomePage</i>.
|
Ex: the address "rails" gives URLs like <i>/rails/show/HomePage</i>.
|
||||||
The address can only consist of letters and digits.
|
The address can only consist of letters and digits.
|
||||||
</div>
|
</div>
|
||||||
<div class="inputBox">
|
<div class="inputBox">
|
||||||
Name: <input type="text" id="web_name" name="name" onChange="proposeAddress();" />
|
Name: <input type="text" id="web_name" name="name" onChange="proposeAddress();" />
|
||||||
|
|
||||||
Address: <input type="text" id="web_address" name="address" onChange="cleanAddress();" />
|
Address: <input type="text" id="web_address" name="address" onChange="cleanAddress();" />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
<p align="right">
|
<p align="right">
|
||||||
<small>
|
<small>
|
||||||
Enter system password
|
Enter system password
|
||||||
<input type="password" id="system_password" name="system_password" />
|
<input type="password" id="system_password" name="system_password" />
|
||||||
and
|
and
|
||||||
<input type="submit" value="Create Web" />
|
<input type="submit" value="Create Web" />
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function proposeAddress() {
|
function proposeAddress() {
|
||||||
document.getElementById('web_address').value =
|
document.getElementById('web_address').value =
|
||||||
document.getElementById('web_name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
document.getElementById('web_name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanAddress() {
|
function cleanAddress() {
|
||||||
document.getElementById('web_address').value =
|
document.getElementById('web_address').value =
|
||||||
document.getElementById('web_address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
document.getElementById('web_address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateSetup() {
|
function validateSetup() {
|
||||||
if (document.getElementById('web_name').value == "") {
|
if (document.getElementById('web_name').value == "") {
|
||||||
alert("You must pick a name for the new web");
|
alert("You must pick a name for the new web");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('web_address').value == "") {
|
if (document.getElementById('web_address').value == "") {
|
||||||
alert("You must pick an address for the new web");
|
alert("You must pick an address for the new web");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('system_password').value == "") {
|
if (document.getElementById('system_password').value == "") {
|
||||||
alert("You must enter the system password");
|
alert("You must enter the system password");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
156
app/views/wiki/page.rhtml
Executable file → Normal file
156
app/views/wiki/page.rhtml
Executable file → Normal file
|
@ -1,78 +1,78 @@
|
||||||
<% @title = @page.plain_name %>
|
<% @title = @page.plain_name %>
|
||||||
|
|
||||||
<div id="revision">
|
<div id="revision">
|
||||||
<%= @page.display_content %>
|
<%= @page.display_content %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="changes" style="display: none">
|
<div id="changes" style="display: none">
|
||||||
<p style="background: #eee; padding: 3px; border: 1px solid silver">
|
<p style="background: #eee; padding: 3px; border: 1px solid silver">
|
||||||
<small>
|
<small>
|
||||||
Showing changes from revision #<%= @page.number - 1 %> to #<%= @page.number %>:
|
Showing changes from revision #<%= @page.number - 1 %> to #<%= @page.number %>:
|
||||||
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
|
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<%= @page.display_diff %>
|
<%= @page.display_diff %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="byline">
|
<div class="byline">
|
||||||
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
|
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
|
||||||
by <%= @page.author_link %>
|
by <%= @page.author_link %>
|
||||||
<%= "(#{@page.author.ip})" if @page.author.respond_to?(:ip) %>
|
<%= "(#{@page.author.ip})" if @page.author.respond_to?(:ip) %>
|
||||||
<% if @web.count_pages %>
|
<% if @web.count_pages %>
|
||||||
<% total_chars = @page.content.length %>
|
<% total_chars = @page.content.length %>
|
||||||
(<%= total_chars %> characters / <%= sprintf("%-.1f", (total_chars / 2275 rescue 0)) %> pages)
|
(<%= total_chars %> characters / <%= sprintf("%-.1f", (total_chars / 2275 rescue 0)) %> pages)
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
<% if @page.name == "HomePage" %>
|
<% if @page.name == "HomePage" %>
|
||||||
<a href="../edit/<%= @page.name %>" class="navlink" accesskey="E">Edit Page</a>
|
<a href="../edit/<%= @page.name %>" class="navlink" accesskey="E">Edit Page</a>
|
||||||
| <a href="../edit_web/" class="navlink">Edit Web</a>
|
| <a href="../edit_web/" class="navlink">Edit Web</a>
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="../edit/<%= @page.name %>" class="navlink" accesskey="E">Edit</a>
|
<a href="../edit/<%= @page.name %>" class="navlink" accesskey="E">Edit</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @page.revisions.length > 1 %>
|
<% if @page.revisions.length > 1 %>
|
||||||
| <a href="../revision/<%= @page.name %>?rev=<%= @page.revisions.length - 2 %>" class="navlink" accesskey="R">Back in time</a>
|
| <a href="../revision/<%= @page.name %>?rev=<%= @page.revisions.length - 2 %>" class="navlink" accesskey="R">Back in time</a>
|
||||||
<small>(<%= @page.revisions.length - 1 %> revisions)</small>
|
<small>(<%= @page.revisions.length - 1 %> revisions)</small>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @page.revisions.length > 1 %>
|
<% if @page.revisions.length > 1 %>
|
||||||
<span id="show_changes">
|
<span id="show_changes">
|
||||||
| <a href="#" onClick="toggleChanges(); return false;">See changes</a>
|
| <a href="#" onClick="toggleChanges(); return false;">See changes</a>
|
||||||
</span>
|
</span>
|
||||||
<span id="hide_changes" style="display: none">
|
<span id="hide_changes" style="display: none">
|
||||||
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<small>
|
<small>
|
||||||
| Views: <a href="../print/<%= @page.name %>">Print</a>
|
| Views: <a href="../print/<%= @page.name %>">Print</a>
|
||||||
<% if defined? RedClothForTex and RedClothForTex.available? and @web.markup == :textile %>
|
<% if defined? RedClothForTex and RedClothForTex.available? and @web.markup == :textile %>
|
||||||
| <a href="../tex/<%= @page.name %>">TeX</a> | <a href="../pdf/<%= @page.name %>">PDF</a>
|
| <a href="../tex/<%= @page.name %>">TeX</a> | <a href="../pdf/<%= @page.name %>">PDF</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
</small>
|
</small>
|
||||||
|
|
||||||
<% if @page.references.length > 0 %>
|
<% if @page.references.length > 0 %>
|
||||||
<small>
|
<small>
|
||||||
| Linked from: <%= @page.references.collect { |ref| ref.link }.join(", ") %>
|
| Linked from: <%= @page.references.collect { |ref| ref.link }.join(", ") %>
|
||||||
</small>
|
</small>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script language="Javascript">
|
<script language="Javascript">
|
||||||
function toggleChanges() {
|
function toggleChanges() {
|
||||||
if (document.getElementById("changes").style.display == "none") {
|
if (document.getElementById("changes").style.display == "none") {
|
||||||
document.getElementById("changes").style.display = "block";
|
document.getElementById("changes").style.display = "block";
|
||||||
document.getElementById("revision").style.display = "none";
|
document.getElementById("revision").style.display = "none";
|
||||||
document.getElementById("show_changes").style.display = "none";
|
document.getElementById("show_changes").style.display = "none";
|
||||||
document.getElementById("hide_changes").style.display = "inline";
|
document.getElementById("hide_changes").style.display = "inline";
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("changes").style.display = "none";
|
document.getElementById("changes").style.display = "none";
|
||||||
document.getElementById("revision").style.display = "block";
|
document.getElementById("revision").style.display = "block";
|
||||||
document.getElementById("show_changes").style.display = "inline";
|
document.getElementById("show_changes").style.display = "inline";
|
||||||
document.getElementById("hide_changes").style.display = "none";
|
document.getElementById("hide_changes").style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
28
app/views/wiki/print.rhtml
Executable file → Normal file
28
app/views/wiki/print.rhtml
Executable file → Normal file
|
@ -1,14 +1,14 @@
|
||||||
<%
|
<%
|
||||||
@title = @page.plain_name
|
@title = @page.plain_name
|
||||||
@hide_navigation = true
|
@hide_navigation = true
|
||||||
@style_additions = ".newWikiWord { background-color: white; font-style: italic; }"
|
@style_additions = ".newWikiWord { background-color: white; font-style: italic; }"
|
||||||
@inline_style = true
|
@inline_style = true
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= @page.display_content_for_export %>
|
<%= @page.display_content_for_export %>
|
||||||
|
|
||||||
<div class="byline">
|
<div class="byline">
|
||||||
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
|
<%= @page.revisions? ? "Revised" : "Created" %> on <%= @page.pretty_created_at %>
|
||||||
by
|
by
|
||||||
<%= @page.author_link({ :mode => :export }) %>
|
<%= @page.author_link({ :mode => :export }) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
16
app/views/wiki/published.rhtml
Executable file → Normal file
16
app/views/wiki/published.rhtml
Executable file → Normal file
|
@ -1,8 +1,8 @@
|
||||||
<%
|
<%
|
||||||
@title = @page.plain_name
|
@title = @page.plain_name
|
||||||
@hide_navigation = false
|
@hide_navigation = false
|
||||||
@style_additions = ".newWikiWord { background-color: white; font-style: italic; }"
|
@style_additions = ".newWikiWord { background-color: white; font-style: italic; }"
|
||||||
@inline_style = true
|
@inline_style = true
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%= @page.display_published %>
|
<%= @page.display_published %>
|
||||||
|
|
64
app/views/wiki/recently_revised.rhtml
Executable file → Normal file
64
app/views/wiki/recently_revised.rhtml
Executable file → Normal file
|
@ -1,32 +1,32 @@
|
||||||
<% @title = "Recently Revised" %>
|
<% @title = "Recently Revised" %>
|
||||||
|
|
||||||
<% unless @categories.empty? %>
|
<% unless @categories.empty? %>
|
||||||
<div id="categories">
|
<div id="categories">
|
||||||
<strong>Categories</strong>:
|
<strong>Categories</strong>:
|
||||||
[<a href=".">Any</a>]
|
[<a href=".">Any</a>]
|
||||||
<%= @category_links.join(', ') %>
|
<%= @category_links.join(', ') %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% unless @pages_by_revision.empty? %>
|
<% unless @pages_by_revision.empty? %>
|
||||||
<% revision_date = @pages_by_revision.first.revised_on %>
|
<% revision_date = @pages_by_revision.first.revised_on %>
|
||||||
<h3><%= revision_date.strftime('%B %e, %Y') %></h3>
|
<h3><%= revision_date.strftime('%B %e, %Y') %></h3>
|
||||||
<ul>
|
<ul>
|
||||||
<% for page in @pages_by_revision %>
|
<% for page in @pages_by_revision %>
|
||||||
<% if page.revised_on < revision_date %>
|
<% if page.revised_on < revision_date %>
|
||||||
<% revision_date = page.revised_on %>
|
<% revision_date = page.revised_on %>
|
||||||
</ul>
|
</ul>
|
||||||
<h3><%= revision_date.strftime('%B %e, %Y') %></h3>
|
<h3><%= revision_date.strftime('%B %e, %Y') %></h3>
|
||||||
<ul>
|
<ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li>
|
<li>
|
||||||
<a href="../show/<%= page.name %>"><%= page.plain_name %></a>
|
<a href="../show/<%= page.name %>"><%= page.plain_name %></a>
|
||||||
<div class="byline" style="margin-bottom: 0px">
|
<div class="byline" style="margin-bottom: 0px">
|
||||||
by <%= page.author_link %>
|
by <%= page.author_link %>
|
||||||
at <%= page.created_at.strftime "%H:%M" %>
|
at <%= page.created_at.strftime "%H:%M" %>
|
||||||
<%= "from #{page.author.ip}" if page.author.respond_to?(:ip) %>
|
<%= "from #{page.author.ip}" if page.author.respond_to?(:ip) %>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
158
app/views/wiki/revision.rhtml
Executable file → Normal file
158
app/views/wiki/revision.rhtml
Executable file → Normal file
|
@ -1,79 +1,79 @@
|
||||||
<% @title = "#{@page.plain_name} (Rev ##{@revision.number})" %>
|
<% @title = "#{@page.plain_name} (Rev ##{@revision.number})" %>
|
||||||
|
|
||||||
<div id="revision">
|
<div id="revision">
|
||||||
<%= @revision.display_content %>
|
<%= @revision.display_content %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="changes" style="display: none">
|
<div id="changes" style="display: none">
|
||||||
<p style="background: #eee; padding: 3px; border: 1px solid silver">
|
<p style="background: #eee; padding: 3px; border: 1px solid silver">
|
||||||
<small>
|
<small>
|
||||||
Showing changes from revision #<%= @revision.number - 1 %> to #<%= @revision.number %>:
|
Showing changes from revision #<%= @revision.number - 1 %> to #<%= @revision.number %>:
|
||||||
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
|
<ins class="diffins">Added</ins> | <del class="diffdel">Removed</del>
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<%= @revision.display_diff %>
|
<%= @revision.display_diff %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="byline">
|
<div class="byline">
|
||||||
<%= "Revision from #{@revision.pretty_created_at} by" %>
|
<%= "Revision from #{@revision.pretty_created_at} by" %>
|
||||||
<%= @page.web.make_link(@revision.author) %>
|
<%= @page.web.make_link(@revision.author) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
|
|
||||||
<% if @revision.next_revision %>
|
<% if @revision.next_revision %>
|
||||||
<% if @revision.next_revision.number < (@page.revisions.length - 1) %>
|
<% if @revision.next_revision.number < (@page.revisions.length - 1) %>
|
||||||
<a href="../revision/<%= @page.name %>?rev=<%= @revision.next_revision.number %>" class="navlink">
|
<a href="../revision/<%= @page.name %>?rev=<%= @revision.next_revision.number %>" class="navlink">
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="../show/<%= @page.name %>" class="navlink">
|
<a href="../show/<%= @page.name %>" class="navlink">
|
||||||
<% end %>
|
<% end %>
|
||||||
Forward in time</a>
|
Forward in time</a>
|
||||||
(<%= @revision.page.revisions.length - @revision.next_revision.number %> more)
|
(<%= @revision.page.revisions.length - @revision.next_revision.number %> more)
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @revision.next_revision && @revision.previous_revision %>
|
<% if @revision.next_revision && @revision.previous_revision %>
|
||||||
|
|
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @revision.previous_revision %>
|
<% if @revision.previous_revision %>
|
||||||
<a href="../revision/<%= @page.name %>?rev=<%= @revision.previous_revision.number %>" class="navlink">Back in time</a>
|
<a href="../revision/<%= @page.name %>?rev=<%= @revision.previous_revision.number %>" class="navlink">Back in time</a>
|
||||||
(<%= @revision.previous_revision.number + 1 %> more)
|
(<%= @revision.previous_revision.number + 1 %> more)
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
| <a href="../show/<%= @page.name %>" class="navlink">See current</a>
|
| <a href="../show/<%= @page.name %>" class="navlink">See current</a>
|
||||||
|
|
||||||
<% if @revision.previous_revision %>
|
<% if @revision.previous_revision %>
|
||||||
<span id="show_changes">
|
<span id="show_changes">
|
||||||
| <a href="#" onClick="toggleChanges(); return false;">See changes</a>
|
| <a href="#" onClick="toggleChanges(); return false;">See changes</a>
|
||||||
</span>
|
</span>
|
||||||
<span id="hide_changes" style="display: none">
|
<span id="hide_changes" style="display: none">
|
||||||
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
| <a href="#" onClick="toggleChanges(); return false;">Hide changes</a>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
| <a href="../rollback/<%= @page.name %>?rev=<%= @revision.number %>" class="navlink">Rollback</a>
|
| <a href="../rollback/<%= @page.name %>?rev=<%= @revision.number %>" class="navlink">Rollback</a>
|
||||||
|
|
||||||
<% if @page.references.length > 0 %>
|
<% if @page.references.length > 0 %>
|
||||||
<small>
|
<small>
|
||||||
| Linked from: <%= @page.references.collect { |ref| "<a href='#{ref.name}'>#{ref.name}</a>" }.join(", ") %>
|
| Linked from: <%= @page.references.collect { |ref| "<a href='#{ref.name}'>#{ref.name}</a>" }.join(", ") %>
|
||||||
</small>
|
</small>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script language="Javascript">
|
<script language="Javascript">
|
||||||
function toggleChanges() {
|
function toggleChanges() {
|
||||||
if (document.getElementById("changes").style.display == "none") {
|
if (document.getElementById("changes").style.display == "none") {
|
||||||
document.getElementById("changes").style.display = "block";
|
document.getElementById("changes").style.display = "block";
|
||||||
document.getElementById("revision").style.display = "none";
|
document.getElementById("revision").style.display = "none";
|
||||||
document.getElementById("show_changes").style.display = "none";
|
document.getElementById("show_changes").style.display = "none";
|
||||||
document.getElementById("hide_changes").style.display = "inline";
|
document.getElementById("hide_changes").style.display = "inline";
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("changes").style.display = "none";
|
document.getElementById("changes").style.display = "none";
|
||||||
document.getElementById("revision").style.display = "block";
|
document.getElementById("revision").style.display = "block";
|
||||||
document.getElementById("show_changes").style.display = "inline";
|
document.getElementById("show_changes").style.display = "inline";
|
||||||
document.getElementById("hide_changes").style.display = "none";
|
document.getElementById("hide_changes").style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
0
app/views/wiki/rollback.rhtml
Executable file → Normal file
0
app/views/wiki/rollback.rhtml
Executable file → Normal file
44
app/views/wiki/rss_feed.rhtml
Executable file → Normal file
44
app/views/wiki/rss_feed.rhtml
Executable file → Normal file
|
@ -1,22 +1,22 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
<channel>
|
<channel>
|
||||||
<title><%= @web.name %></title>
|
<title><%= @web.name %></title>
|
||||||
<link><%= url_for :only_path => false, :web => @web_name, :action => 'show', :id => 'HomePage' %></link>
|
<link><%= url_for :only_path => false, :web => @web_name, :action => 'show', :id => 'HomePage' %></link>
|
||||||
<description>An Instiki wiki</description>
|
<description>An Instiki wiki</description>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<ttl>40</ttl>
|
<ttl>40</ttl>
|
||||||
<% for page in @pages_by_revision %>
|
<% for page in @pages_by_revision %>
|
||||||
<item>
|
<item>
|
||||||
<title><%= page.plain_name %></title>
|
<title><%= page.plain_name %></title>
|
||||||
<% unless @hide_description %>
|
<% unless @hide_description %>
|
||||||
<description><%= CGI.escapeHTML(page.display_content) %></description>
|
<description><%= CGI.escapeHTML(page.display_content) %></description>
|
||||||
<% end %>
|
<% end %>
|
||||||
<pubDate><%= page.created_at.strftime "%a, %e %b %Y %H:%M:%S %Z" %></pubDate>
|
<pubDate><%= page.created_at.strftime "%a, %e %b %Y %H:%M:%S %Z" %></pubDate>
|
||||||
<guid><%= url_for :only_path => false, :web => @web_name, :action => 'show', :id => page.name %></guid>
|
<guid><%= url_for :only_path => false, :web => @web_name, :action => 'show', :id => page.name %></guid>
|
||||||
<link><%= url_for :only_path => false, :web => @web_name, :action => 'show', :id => page.name %></link>
|
<link><%= url_for :only_path => false, :web => @web_name, :action => 'show', :id => page.name %></link>
|
||||||
<dc:creator><%= WikiWords.separate(page.author) %></dc:creator>
|
<dc:creator><%= WikiWords.separate(page.author) %></dc:creator>
|
||||||
</item>
|
</item>
|
||||||
<% end %>
|
<% end %>
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
|
|
26
app/views/wiki/search.rhtml
Executable file → Normal file
26
app/views/wiki/search.rhtml
Executable file → Normal file
|
@ -1,13 +1,13 @@
|
||||||
<% @title = @results.length > 0 ? "#{@results.length} pages contains \"#{@params["query"]}\"" : "No pages contains \"#{@query}\"" %>
|
<% @title = @results.length > 0 ? "#{@results.length} pages contains \"#{@params["query"]}\"" : "No pages contains \"#{@query}\"" %>
|
||||||
|
|
||||||
<% if @results.length > 0 %>
|
<% if @results.length > 0 %>
|
||||||
<ul>
|
<ul>
|
||||||
<% for page in @results %>
|
<% for page in @results %>
|
||||||
<li><a href="../show/<%= page.name %>"><%= page.plain_name %></a></li>
|
<li><a href="../show/<%= page.name %>"><%= page.plain_name %></a></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p>Perhaps you should try expanding your query. Remember that Instiki searches for entire phrases, so if you search for "all that jazz" it will not match pages that contain these words in separation—only as a sentence fragment.</p>
|
<p>Perhaps you should try expanding your query. Remember that Instiki searches for entire phrases, so if you search for "all that jazz" it will not match pages that contain these words in separation—only as a sentence fragment.</p>
|
||||||
|
|
||||||
<p>If you're a high-tech computer wizard, you might even want try constructing a regular expression. That's actually what Instiki uses, so go right ahead and flex your "[a-z]*Leet?RegExpSkill(s|z)"</p>
|
<p>If you're a high-tech computer wizard, you might even want try constructing a regular expression. That's actually what Instiki uses, so go right ahead and flex your "[a-z]*Leet?RegExpSkill(s|z)"</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
44
app/views/wiki/tex.rhtml
Executable file → Normal file
44
app/views/wiki/tex.rhtml
Executable file → Normal file
|
@ -1,23 +1,23 @@
|
||||||
\documentclass[12pt,titlepage]{article}
|
\documentclass[12pt,titlepage]{article}
|
||||||
|
|
||||||
\usepackage[danish]{babel} %danske tekster
|
\usepackage[danish]{babel} %danske tekster
|
||||||
\usepackage[OT1]{fontenc} %rigtige danske bogstaver...
|
\usepackage[OT1]{fontenc} %rigtige danske bogstaver...
|
||||||
\usepackage{a4}
|
\usepackage{a4}
|
||||||
\usepackage{graphicx}
|
\usepackage{graphicx}
|
||||||
\usepackage{ucs}
|
\usepackage{ucs}
|
||||||
\usepackage[utf8x]{inputenc}
|
\usepackage[utf8x]{inputenc}
|
||||||
\input epsf
|
\input epsf
|
||||||
|
|
||||||
%-------------------------------------------------------------------
|
%-------------------------------------------------------------------
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
|
||||||
\sloppy
|
\sloppy
|
||||||
|
|
||||||
%-------------------------------------------------------------------
|
%-------------------------------------------------------------------
|
||||||
|
|
||||||
\section*{<%= @page.name %>}
|
\section*{<%= @page.name %>}
|
||||||
|
|
||||||
<%= @tex_content %>
|
<%= @tex_content %>
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
68
app/views/wiki/tex_web.rhtml
Executable file → Normal file
68
app/views/wiki/tex_web.rhtml
Executable file → Normal file
|
@ -1,35 +1,35 @@
|
||||||
\documentclass[12pt,titlepage]{article}
|
\documentclass[12pt,titlepage]{article}
|
||||||
|
|
||||||
\usepackage{fancyhdr}
|
\usepackage{fancyhdr}
|
||||||
\pagestyle{fancy}
|
\pagestyle{fancy}
|
||||||
|
|
||||||
\fancyhead[LE,RO]{}
|
\fancyhead[LE,RO]{}
|
||||||
\fancyhead[LO,RE]{\nouppercase{\bfseries \leftmark}}
|
\fancyhead[LO,RE]{\nouppercase{\bfseries \leftmark}}
|
||||||
\fancyfoot[C]{\thepage}
|
\fancyfoot[C]{\thepage}
|
||||||
|
|
||||||
\usepackage[danish]{babel} %danske tekster
|
\usepackage[danish]{babel} %danske tekster
|
||||||
\usepackage{a4}
|
\usepackage{a4}
|
||||||
\usepackage{graphicx}
|
\usepackage{graphicx}
|
||||||
\usepackage{ucs}
|
\usepackage{ucs}
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
\input epsf
|
\input epsf
|
||||||
|
|
||||||
|
|
||||||
%-------------------------------------------------------------------
|
%-------------------------------------------------------------------
|
||||||
|
|
||||||
\title{<%= @web_name %>}
|
\title{<%= @web_name %>}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
|
||||||
\maketitle
|
\maketitle
|
||||||
|
|
||||||
\tableofcontents
|
\tableofcontents
|
||||||
\pagebreak
|
\pagebreak
|
||||||
|
|
||||||
\sloppy
|
\sloppy
|
||||||
|
|
||||||
%-------------------------------------------------------------------
|
%-------------------------------------------------------------------
|
||||||
|
|
||||||
<%= @tex_content %>
|
<%= @tex_content %>
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
36
app/views/wiki/web_list.rhtml
Executable file → Normal file
36
app/views/wiki/web_list.rhtml
Executable file → Normal file
|
@ -1,18 +1,18 @@
|
||||||
<% @title = "Wiki webs" %>
|
<% @title = "Wiki webs" %>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<% for web in @webs %>
|
<% for web in @webs %>
|
||||||
<li>
|
<li>
|
||||||
<% if web.published %>
|
<% if web.published %>
|
||||||
<%= web.make_link 'HomePage', web.name, :mode => :publish %> (read-only) /
|
<%= web.make_link 'HomePage', web.name, :mode => :publish %> (read-only) /
|
||||||
<%= web.make_link 'HomePage', 'editable version', :mode => :edit %> (requires login)
|
<%= web.make_link 'HomePage', 'editable version', :mode => :edit %> (requires login)
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= web.make_link 'HomePage', nil, :mode => :edit %>
|
<%= web.make_link 'HomePage', nil, :mode => :edit %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="byline" style="margin-bottom: 0px">
|
<div class="byline" style="margin-bottom: 0px">
|
||||||
<%= web.pages.length %> pages by <%= web.authors.length %> authors
|
<%= web.pages.length %> pages by <%= web.authors.length %> authors
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
18
app/views/wiki_words_help.rhtml
Executable file → Normal file
18
app/views/wiki_words_help.rhtml
Executable file → Normal file
|
@ -1,9 +1,9 @@
|
||||||
<h3>Wiki words</h3>
|
<h3>Wiki words</h3>
|
||||||
<p style="border-top: 1px dotted #ccc; margin-top: 0px">
|
<p style="border-top: 1px dotted #ccc; margin-top: 0px">
|
||||||
Two or more uppercase words stuck together (camel case) or any phrase surrounded by double
|
Two or more uppercase words stuck together (camel case) or any phrase surrounded by double
|
||||||
brackets is a wiki word. A camel-case wiki word can be escaped by putting \ in front of it.
|
brackets is a wiki word. A camel-case wiki word can be escaped by putting \ in front of it.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Wiki words: <i>HomePage, ThreeWordsTogether, [[C++]], [[Let's play again!]]</i><br/>
|
Wiki words: <i>HomePage, ThreeWordsTogether, [[C++]], [[Let's play again!]]</i><br/>
|
||||||
Not wiki words: <i>IBM, School</i>
|
Not wiki words: <i>IBM, School</i>
|
||||||
</p>
|
</p>
|
||||||
|
|
8
config/environments/development.rb
Executable file → Normal file
8
config/environments/development.rb
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
||||||
Dependencies.mechanism = :require
|
Dependencies.mechanism = :require
|
||||||
ActionController::Base.consider_all_requests_local = true
|
ActionController::Base.consider_all_requests_local = true
|
||||||
BREAKPOINT_SERVER_PORT = 42531
|
BREAKPOINT_SERVER_PORT = 42531
|
||||||
ActionController::Base.logger.level = Logger::DEBUG
|
ActionController::Base.logger.level = Logger::DEBUG
|
||||||
|
|
44
libraries/active_record_stub.rb
Executable file → Normal file
44
libraries/active_record_stub.rb
Executable file → Normal file
|
@ -1,23 +1,23 @@
|
||||||
# This project uses Railties, which has an external dependency on ActiveRecord
|
# This project uses Railties, which has an external dependency on ActiveRecord
|
||||||
# Since ActiveRecord may not be present in Instiki runtime environment, this
|
# Since ActiveRecord may not be present in Instiki runtime environment, this
|
||||||
# file provides a stub replacement for it
|
# file provides a stub replacement for it
|
||||||
|
|
||||||
unless defined? ActiveRecord::Base
|
unless defined? ActiveRecord::Base
|
||||||
|
|
||||||
module ActiveRecord
|
module ActiveRecord
|
||||||
class Base
|
class Base
|
||||||
|
|
||||||
# dependency in railties/lib/dispatcher.rb
|
# dependency in railties/lib/dispatcher.rb
|
||||||
def self.reset_column_information_and_inheritable_attributes_for_all_subclasses
|
def self.reset_column_information_and_inheritable_attributes_for_all_subclasses
|
||||||
# noop
|
# noop
|
||||||
end
|
end
|
||||||
|
|
||||||
# dependency in actionpack/lib/action_controller/benchmarking.rb
|
# dependency in actionpack/lib/action_controller/benchmarking.rb
|
||||||
def self.connected?
|
def self.connected?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
948
libraries/diff.rb
Executable file → Normal file
948
libraries/diff.rb
Executable file → Normal file
|
@ -1,475 +1,475 @@
|
||||||
# heavily based off difflib.py - see that file for documentation
|
# heavily based off difflib.py - see that file for documentation
|
||||||
# ported from Python by Bill Atkins
|
# ported from Python by Bill Atkins
|
||||||
|
|
||||||
# This does not support all features offered by difflib; it
|
# This does not support all features offered by difflib; it
|
||||||
# implements only the subset of features necessary
|
# implements only the subset of features necessary
|
||||||
# to support a Ruby version of HTML Differ. You're welcome to finish this off.
|
# to support a Ruby version of HTML Differ. You're welcome to finish this off.
|
||||||
|
|
||||||
# By default, String#each iterates by line. This isn't really appropriate
|
# By default, String#each iterates by line. This isn't really appropriate
|
||||||
# for diff, so often a string will be split by // to get an array of one-
|
# for diff, so often a string will be split by // to get an array of one-
|
||||||
# character strings.
|
# character strings.
|
||||||
|
|
||||||
# Some methods in Diff are untested and are not guaranteed to work. The
|
# Some methods in Diff are untested and are not guaranteed to work. The
|
||||||
# methods in HTMLDiff and any methods it calls should work quite well.
|
# methods in HTMLDiff and any methods it calls should work quite well.
|
||||||
|
|
||||||
# changes by DenisMertz
|
# changes by DenisMertz
|
||||||
# * main change:
|
# * main change:
|
||||||
# ** get the tag soup away
|
# ** get the tag soup away
|
||||||
# the tag soup problem was first reported with <p> tags, but it appeared also with
|
# the tag soup problem was first reported with <p> tags, but it appeared also with
|
||||||
# <li>, <ul> etc... tags
|
# <li>, <ul> etc... tags
|
||||||
# this version should mostly fix these problems
|
# this version should mostly fix these problems
|
||||||
# ** added a Builder class to manage the creation of the final htmldiff
|
# ** added a Builder class to manage the creation of the final htmldiff
|
||||||
# * minor changes:
|
# * minor changes:
|
||||||
# ** use symbols instead of string to represent opcodes
|
# ** use symbols instead of string to represent opcodes
|
||||||
# ** small fix to html2list
|
# ** small fix to html2list
|
||||||
#
|
#
|
||||||
|
|
||||||
module Enumerable
|
module Enumerable
|
||||||
def reduce(init)
|
def reduce(init)
|
||||||
result = init
|
result = init
|
||||||
each { |item| result = yield(result, item) }
|
each { |item| result = yield(result, item) }
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module Diff
|
module Diff
|
||||||
|
|
||||||
class SequenceMatcher
|
class SequenceMatcher
|
||||||
def initialize(a=[''], b=[''], isjunk=nil, byline=false)
|
def initialize(a=[''], b=[''], isjunk=nil, byline=false)
|
||||||
a = (!byline and a.kind_of? String) ? a.split(//) : a
|
a = (!byline and a.kind_of? String) ? a.split(//) : a
|
||||||
b = (!byline and b.kind_of? String) ? b.split(//) : b
|
b = (!byline and b.kind_of? String) ? b.split(//) : b
|
||||||
@isjunk = isjunk || proc {}
|
@isjunk = isjunk || proc {}
|
||||||
set_seqs a, b
|
set_seqs a, b
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_seqs(a, b)
|
def set_seqs(a, b)
|
||||||
set_seq_a a
|
set_seq_a a
|
||||||
set_seq_b b
|
set_seq_b b
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_seq_a(a)
|
def set_seq_a(a)
|
||||||
@a = a
|
@a = a
|
||||||
@matching_blocks = @opcodes = nil
|
@matching_blocks = @opcodes = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_seq_b(b)
|
def set_seq_b(b)
|
||||||
@b = b
|
@b = b
|
||||||
@matching_blocks = @opcodes = nil
|
@matching_blocks = @opcodes = nil
|
||||||
chain_b
|
chain_b
|
||||||
end
|
end
|
||||||
|
|
||||||
def chain_b
|
def chain_b
|
||||||
@fullbcount = nil
|
@fullbcount = nil
|
||||||
@b2j = {}
|
@b2j = {}
|
||||||
pophash = {}
|
pophash = {}
|
||||||
junkdict = {}
|
junkdict = {}
|
||||||
|
|
||||||
@b.each_with_index do |elt, i|
|
@b.each_with_index do |elt, i|
|
||||||
if @b2j.has_key? elt
|
if @b2j.has_key? elt
|
||||||
indices = @b2j[elt]
|
indices = @b2j[elt]
|
||||||
if @b.length >= 200 and indices.length * 100 > @b.length
|
if @b.length >= 200 and indices.length * 100 > @b.length
|
||||||
pophash[elt] = 1
|
pophash[elt] = 1
|
||||||
indices.clear
|
indices.clear
|
||||||
else
|
else
|
||||||
indices.push i
|
indices.push i
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@b2j[elt] = [i]
|
@b2j[elt] = [i]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
pophash.each_key { |elt| @b2j.delete elt }
|
pophash.each_key { |elt| @b2j.delete elt }
|
||||||
|
|
||||||
junkdict = {}
|
junkdict = {}
|
||||||
|
|
||||||
unless @isjunk.nil?
|
unless @isjunk.nil?
|
||||||
[pophash, @b2j].each do |d|
|
[pophash, @b2j].each do |d|
|
||||||
d.each_key do |elt|
|
d.each_key do |elt|
|
||||||
if @isjunk.call(elt)
|
if @isjunk.call(elt)
|
||||||
junkdict[elt] = 1
|
junkdict[elt] = 1
|
||||||
d.delete elt
|
d.delete elt
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@isbjunk = junkdict.method(:has_key?)
|
@isbjunk = junkdict.method(:has_key?)
|
||||||
@isbpopular = junkdict.method(:has_key?)
|
@isbpopular = junkdict.method(:has_key?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_longest_match(alo, ahi, blo, bhi)
|
def find_longest_match(alo, ahi, blo, bhi)
|
||||||
besti, bestj, bestsize = alo, blo, 0
|
besti, bestj, bestsize = alo, blo, 0
|
||||||
|
|
||||||
j2len = {}
|
j2len = {}
|
||||||
|
|
||||||
(alo..ahi).step do |i|
|
(alo..ahi).step do |i|
|
||||||
newj2len = {}
|
newj2len = {}
|
||||||
(@b2j[@a[i]] || []).each do |j|
|
(@b2j[@a[i]] || []).each do |j|
|
||||||
if j < blo
|
if j < blo
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
if j >= bhi
|
if j >= bhi
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
k = newj2len[j] = (j2len[j - 1] || 0) + 1
|
k = newj2len[j] = (j2len[j - 1] || 0) + 1
|
||||||
if k > bestsize
|
if k > bestsize
|
||||||
besti, bestj, bestsize = i - k + 1, j - k + 1, k
|
besti, bestj, bestsize = i - k + 1, j - k + 1, k
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
j2len = newj2len
|
j2len = newj2len
|
||||||
end
|
end
|
||||||
|
|
||||||
while besti > alo and bestj > blo and
|
while besti > alo and bestj > blo and
|
||||||
not @isbjunk.call(@b[bestj-1]) and
|
not @isbjunk.call(@b[bestj-1]) and
|
||||||
@a[besti-1] == @b[bestj-1]
|
@a[besti-1] == @b[bestj-1]
|
||||||
besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
|
besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
|
||||||
end
|
end
|
||||||
|
|
||||||
while besti+bestsize < ahi and bestj+bestsize < bhi and
|
while besti+bestsize < ahi and bestj+bestsize < bhi and
|
||||||
not @isbjunk.call(@b[bestj+bestsize]) and
|
not @isbjunk.call(@b[bestj+bestsize]) and
|
||||||
@a[besti+bestsize] == @b[bestj+bestsize]
|
@a[besti+bestsize] == @b[bestj+bestsize]
|
||||||
bestsize += 1
|
bestsize += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
while besti > alo and bestj > blo and
|
while besti > alo and bestj > blo and
|
||||||
@isbjunk.call(@b[bestj-1]) and
|
@isbjunk.call(@b[bestj-1]) and
|
||||||
@a[besti-1] == @b[bestj-1]
|
@a[besti-1] == @b[bestj-1]
|
||||||
besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
|
besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
|
||||||
end
|
end
|
||||||
|
|
||||||
while besti+bestsize < ahi and bestj+bestsize < bhi and
|
while besti+bestsize < ahi and bestj+bestsize < bhi and
|
||||||
@isbjunk.call(@b[bestj+bestsize]) and
|
@isbjunk.call(@b[bestj+bestsize]) and
|
||||||
@a[besti+bestsize] == @b[bestj+bestsize]
|
@a[besti+bestsize] == @b[bestj+bestsize]
|
||||||
bestsize += 1
|
bestsize += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
[besti, bestj, bestsize]
|
[besti, bestj, bestsize]
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_matching_blocks
|
def get_matching_blocks
|
||||||
return @matching_blocks unless @matching_blocks.nil? or
|
return @matching_blocks unless @matching_blocks.nil? or
|
||||||
@matching_blocks.empty?
|
@matching_blocks.empty?
|
||||||
|
|
||||||
@matching_blocks = []
|
@matching_blocks = []
|
||||||
la, lb = @a.length, @b.length
|
la, lb = @a.length, @b.length
|
||||||
match_block_helper(0, la, 0, lb, @matching_blocks)
|
match_block_helper(0, la, 0, lb, @matching_blocks)
|
||||||
@matching_blocks.push [la, lb, 0]
|
@matching_blocks.push [la, lb, 0]
|
||||||
end
|
end
|
||||||
|
|
||||||
def match_block_helper(alo, ahi, blo, bhi, answer)
|
def match_block_helper(alo, ahi, blo, bhi, answer)
|
||||||
i, j, k = x = find_longest_match(alo, ahi, blo, bhi)
|
i, j, k = x = find_longest_match(alo, ahi, blo, bhi)
|
||||||
if not k.zero?
|
if not k.zero?
|
||||||
if alo < i and blo < j
|
if alo < i and blo < j
|
||||||
match_block_helper(alo, i, blo, j, answer)
|
match_block_helper(alo, i, blo, j, answer)
|
||||||
end
|
end
|
||||||
answer.push x
|
answer.push x
|
||||||
if i + k < ahi and j + k < bhi
|
if i + k < ahi and j + k < bhi
|
||||||
match_block_helper(i + k, ahi, j + k, bhi, answer)
|
match_block_helper(i + k, ahi, j + k, bhi, answer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_opcodes
|
def get_opcodes
|
||||||
unless @opcodes.nil? or @opcodes.empty?
|
unless @opcodes.nil? or @opcodes.empty?
|
||||||
return @opcodes
|
return @opcodes
|
||||||
end
|
end
|
||||||
|
|
||||||
i = j = 0
|
i = j = 0
|
||||||
@opcodes = answer = []
|
@opcodes = answer = []
|
||||||
get_matching_blocks.each do |ai, bj, size|
|
get_matching_blocks.each do |ai, bj, size|
|
||||||
tag = if i < ai and j < bj
|
tag = if i < ai and j < bj
|
||||||
:replace
|
:replace
|
||||||
elsif i < ai
|
elsif i < ai
|
||||||
:delete
|
:delete
|
||||||
elsif j < bj
|
elsif j < bj
|
||||||
:insert
|
:insert
|
||||||
end
|
end
|
||||||
|
|
||||||
answer.push [tag, i, ai, j, bj] if tag
|
answer.push [tag, i, ai, j, bj] if tag
|
||||||
|
|
||||||
i, j = ai + size, bj + size
|
i, j = ai + size, bj + size
|
||||||
|
|
||||||
answer.push [:equal, ai, i, bj, j] unless size.zero?
|
answer.push [:equal, ai, i, bj, j] unless size.zero?
|
||||||
|
|
||||||
end
|
end
|
||||||
return answer
|
return answer
|
||||||
end
|
end
|
||||||
|
|
||||||
# XXX: untested
|
# XXX: untested
|
||||||
def get_grouped_opcodes(n=3)
|
def get_grouped_opcodes(n=3)
|
||||||
codes = get_opcodes
|
codes = get_opcodes
|
||||||
if codes[0][0] == :equal
|
if codes[0][0] == :equal
|
||||||
tag, i1, i2, j1, j2 = codes[0]
|
tag, i1, i2, j1, j2 = codes[0]
|
||||||
codes[0] = tag, [i1, i2 - n].max, i2, [j1, j2-n].max, j2
|
codes[0] = tag, [i1, i2 - n].max, i2, [j1, j2-n].max, j2
|
||||||
end
|
end
|
||||||
|
|
||||||
if codes[-1][0] == :equal
|
if codes[-1][0] == :equal
|
||||||
tag, i1, i2, j1, j2 = codes[-1]
|
tag, i1, i2, j1, j2 = codes[-1]
|
||||||
codes[-1] = tag, i1, min(i2, i1+n), j1, min(j2, j1+n)
|
codes[-1] = tag, i1, min(i2, i1+n), j1, min(j2, j1+n)
|
||||||
end
|
end
|
||||||
nn = n + n
|
nn = n + n
|
||||||
group = []
|
group = []
|
||||||
codes.each do |tag, i1, i2, j1, j2|
|
codes.each do |tag, i1, i2, j1, j2|
|
||||||
if tag == :equal and i2-i1 > nn
|
if tag == :equal and i2-i1 > nn
|
||||||
group.push [tag, i1, [i2, i1 + n].min, j1, [j2, j1 + n].min]
|
group.push [tag, i1, [i2, i1 + n].min, j1, [j2, j1 + n].min]
|
||||||
yield group
|
yield group
|
||||||
group = []
|
group = []
|
||||||
i1, j1 = [i1, i2-n].max, [j1, j2-n].max
|
i1, j1 = [i1, i2-n].max, [j1, j2-n].max
|
||||||
group.push [tag, i1, i2, j1 ,j2]
|
group.push [tag, i1, i2, j1 ,j2]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if group and group.length != 1 and group[0][0] == :equal
|
if group and group.length != 1 and group[0][0] == :equal
|
||||||
yield group
|
yield group
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def ratio
|
def ratio
|
||||||
matches = get_matching_blocks.reduce(0) do |sum, triple|
|
matches = get_matching_blocks.reduce(0) do |sum, triple|
|
||||||
sum + triple[-1]
|
sum + triple[-1]
|
||||||
end
|
end
|
||||||
Diff.calculate_ratio(matches, @a.length + @b.length)
|
Diff.calculate_ratio(matches, @a.length + @b.length)
|
||||||
end
|
end
|
||||||
|
|
||||||
def quick_ratio
|
def quick_ratio
|
||||||
if @fullbcount.nil? or @fullbcount.empty?
|
if @fullbcount.nil? or @fullbcount.empty?
|
||||||
@fullbcount = {}
|
@fullbcount = {}
|
||||||
@b.each do |elt|
|
@b.each do |elt|
|
||||||
@fullbcount[elt] = (@fullbcount[elt] || 0) + 1
|
@fullbcount[elt] = (@fullbcount[elt] || 0) + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
avail = {}
|
avail = {}
|
||||||
matches = 0
|
matches = 0
|
||||||
@a.each do |elt|
|
@a.each do |elt|
|
||||||
if avail.has_key? elt
|
if avail.has_key? elt
|
||||||
numb = avail[elt]
|
numb = avail[elt]
|
||||||
else
|
else
|
||||||
numb = @fullbcount[elt] || 0
|
numb = @fullbcount[elt] || 0
|
||||||
end
|
end
|
||||||
avail[elt] = numb - 1
|
avail[elt] = numb - 1
|
||||||
if numb > 0
|
if numb > 0
|
||||||
matches += 1
|
matches += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Diff.calculate_ratio matches, @a.length + @b.length
|
Diff.calculate_ratio matches, @a.length + @b.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def real_quick_ratio
|
def real_quick_ratio
|
||||||
la, lb = @a.length, @b.length
|
la, lb = @a.length, @b.length
|
||||||
Diff.calculate_ratio([la, lb].min, la + lb)
|
Diff.calculate_ratio([la, lb].min, la + lb)
|
||||||
end
|
end
|
||||||
|
|
||||||
protected :chain_b, :match_block_helper
|
protected :chain_b, :match_block_helper
|
||||||
end # end class SequenceMatcher
|
end # end class SequenceMatcher
|
||||||
|
|
||||||
def self.calculate_ratio(matches, length)
|
def self.calculate_ratio(matches, length)
|
||||||
return 1.0 if length.zero?
|
return 1.0 if length.zero?
|
||||||
2.0 * matches / length
|
2.0 * matches / length
|
||||||
end
|
end
|
||||||
|
|
||||||
# XXX: untested
|
# XXX: untested
|
||||||
def self.get_close_matches(word, possibilities, n=3, cutoff=0.6)
|
def self.get_close_matches(word, possibilities, n=3, cutoff=0.6)
|
||||||
unless n > 0
|
unless n > 0
|
||||||
raise "n must be > 0: #{n}"
|
raise "n must be > 0: #{n}"
|
||||||
end
|
end
|
||||||
unless 0.0 <= cutoff and cutoff <= 1.0
|
unless 0.0 <= cutoff and cutoff <= 1.0
|
||||||
raise "cutoff must be in (0.0..1.0): #{cutoff}"
|
raise "cutoff must be in (0.0..1.0): #{cutoff}"
|
||||||
end
|
end
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
s = SequenceMatcher.new
|
s = SequenceMatcher.new
|
||||||
s.set_seq_b word
|
s.set_seq_b word
|
||||||
possibilities.each do |x|
|
possibilities.each do |x|
|
||||||
s.set_seq_a x
|
s.set_seq_a x
|
||||||
if s.real_quick_ratio >= cutoff and
|
if s.real_quick_ratio >= cutoff and
|
||||||
s.quick_ratio >= cutoff and
|
s.quick_ratio >= cutoff and
|
||||||
s.ratio >= cutoff
|
s.ratio >= cutoff
|
||||||
result.push [s.ratio, x]
|
result.push [s.ratio, x]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless result.nil? or result.empty?
|
unless result.nil? or result.empty?
|
||||||
result.sort
|
result.sort
|
||||||
result.reverse!
|
result.reverse!
|
||||||
result = result[-n..-1]
|
result = result[-n..-1]
|
||||||
end
|
end
|
||||||
result.collect { |score, x| x }
|
result.collect { |score, x| x }
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.count_leading(line, ch)
|
def self.count_leading(line, ch)
|
||||||
i, n = 0, line.length
|
i, n = 0, line.length
|
||||||
while i < n and line[i].chr == ch
|
while i < n and line[i].chr == ch
|
||||||
i += 1
|
i += 1
|
||||||
end
|
end
|
||||||
i
|
i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module HTMLDiff
|
module HTMLDiff
|
||||||
include Diff
|
include Diff
|
||||||
class Builder
|
class Builder
|
||||||
VALID_METHODS = [:replace, :insert, :delete, :equal]
|
VALID_METHODS = [:replace, :insert, :delete, :equal]
|
||||||
def initialize(a, b)
|
def initialize(a, b)
|
||||||
@a = a
|
@a = a
|
||||||
@b = b
|
@b = b
|
||||||
@content = []
|
@content = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_op(opcode)
|
def do_op(opcode)
|
||||||
@opcode = opcode
|
@opcode = opcode
|
||||||
op = @opcode[0]
|
op = @opcode[0]
|
||||||
VALID_METHODS.include?(op) or raise(NameError, "Invalid opcode #{op}")
|
VALID_METHODS.include?(op) or raise(NameError, "Invalid opcode #{op}")
|
||||||
self.method(op).call
|
self.method(op).call
|
||||||
end
|
end
|
||||||
|
|
||||||
def result
|
def result
|
||||||
@content.join('')
|
@content.join('')
|
||||||
end
|
end
|
||||||
|
|
||||||
#this methods have to be called via do_op(opcode) so that @opcode is set properly
|
#this methods have to be called via do_op(opcode) so that @opcode is set properly
|
||||||
private
|
private
|
||||||
|
|
||||||
def replace
|
def replace
|
||||||
delete("diffmod")
|
delete("diffmod")
|
||||||
insert("diffmod")
|
insert("diffmod")
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert(tagclass="diffins")
|
def insert(tagclass="diffins")
|
||||||
op_helper("ins", tagclass, @b[@opcode[3]...@opcode[4]])
|
op_helper("ins", tagclass, @b[@opcode[3]...@opcode[4]])
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(tagclass="diffdel")
|
def delete(tagclass="diffdel")
|
||||||
op_helper("del", tagclass, @a[@opcode[1]...@opcode[2]])
|
op_helper("del", tagclass, @a[@opcode[1]...@opcode[2]])
|
||||||
end
|
end
|
||||||
|
|
||||||
def equal
|
def equal
|
||||||
@content += @b[@opcode[3]...@opcode[4]]
|
@content += @b[@opcode[3]...@opcode[4]]
|
||||||
end
|
end
|
||||||
|
|
||||||
# using this as op_helper would be equivalent to the first version of diff.rb by Bill Atkins
|
# using this as op_helper would be equivalent to the first version of diff.rb by Bill Atkins
|
||||||
def op_helper_simple(tagname, tagclass, to_add)
|
def op_helper_simple(tagname, tagclass, to_add)
|
||||||
@content << "<#{tagname} class=\"#{tagclass}\">"
|
@content << "<#{tagname} class=\"#{tagclass}\">"
|
||||||
@content += to_add
|
@content += to_add
|
||||||
@content << "</#{tagname}>"
|
@content << "</#{tagname}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
# this tries to put <p> tags or newline chars before the opening diff tags (<ins> or <del>)
|
# this tries to put <p> tags or newline chars before the opening diff tags (<ins> or <del>)
|
||||||
# or after the ending diff tags
|
# or after the ending diff tags
|
||||||
# as a result the diff tags should be the "more inside" possible.
|
# as a result the diff tags should be the "more inside" possible.
|
||||||
# this seems to work nice with html containing only paragraphs
|
# this seems to work nice with html containing only paragraphs
|
||||||
# but not sure it works if there are other tags (div, span ... ? ) around
|
# but not sure it works if there are other tags (div, span ... ? ) around
|
||||||
def op_helper(tagname, tagclass, to_add)
|
def op_helper(tagname, tagclass, to_add)
|
||||||
@content << to_add.shift while ( HTMLDiff.is_newline(to_add.first) or
|
@content << to_add.shift while ( HTMLDiff.is_newline(to_add.first) or
|
||||||
HTMLDiff.is_p_close_tag(to_add.first) or
|
HTMLDiff.is_p_close_tag(to_add.first) or
|
||||||
HTMLDiff.is_p_open_tag(to_add.first) )
|
HTMLDiff.is_p_open_tag(to_add.first) )
|
||||||
@content << "<#{tagname} class=\"#{tagclass}\">"
|
@content << "<#{tagname} class=\"#{tagclass}\">"
|
||||||
@content += to_add
|
@content += to_add
|
||||||
last_tags = []
|
last_tags = []
|
||||||
last_tags.unshift(@content.pop) while ( HTMLDiff.is_newline(@content.last) or
|
last_tags.unshift(@content.pop) while ( HTMLDiff.is_newline(@content.last) or
|
||||||
HTMLDiff.is_p_close_tag(@content.last) or
|
HTMLDiff.is_p_close_tag(@content.last) or
|
||||||
HTMLDiff.is_p_open_tag(@content.last) )
|
HTMLDiff.is_p_open_tag(@content.last) )
|
||||||
last_tags.unshift "</#{tagname}>"
|
last_tags.unshift "</#{tagname}>"
|
||||||
@content += last_tags
|
@content += last_tags
|
||||||
remove_empty_diff(tagname, tagclass)
|
remove_empty_diff(tagname, tagclass)
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_empty_diff(tagname, tagclass)
|
def remove_empty_diff(tagname, tagclass)
|
||||||
if @content[-2] == "<#{tagname} class=\"#{tagclass}\">" and @content[-1] == "</#{tagname}>" then
|
if @content[-2] == "<#{tagname} class=\"#{tagclass}\">" and @content[-1] == "</#{tagname}>" then
|
||||||
@content.pop
|
@content.pop
|
||||||
@content.pop
|
@content.pop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.is_newline(x)
|
def self.is_newline(x)
|
||||||
(x == "\n") or (x == "\r") or (x == "\t")
|
(x == "\n") or (x == "\r") or (x == "\t")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.is_p_open_tag(x)
|
def self.is_p_open_tag(x)
|
||||||
x =~ /\A<(p|li|ul|ol|dir|dt|dl)/
|
x =~ /\A<(p|li|ul|ol|dir|dt|dl)/
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.is_p_close_tag(x)
|
def self.is_p_close_tag(x)
|
||||||
x =~ %r!\A</(p|li|ul|ol|dir|dt|dl)!
|
x =~ %r!\A</(p|li|ul|ol|dir|dt|dl)!
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.diff(a, b)
|
def self.diff(a, b)
|
||||||
a, b = a.split(//), b.split(//) if a.kind_of? String and b.kind_of? String
|
a, b = a.split(//), b.split(//) if a.kind_of? String and b.kind_of? String
|
||||||
a, b = html2list(a), html2list(b)
|
a, b = html2list(a), html2list(b)
|
||||||
|
|
||||||
out = Builder.new(a, b)
|
out = Builder.new(a, b)
|
||||||
s = SequenceMatcher.new(a, b)
|
s = SequenceMatcher.new(a, b)
|
||||||
|
|
||||||
s.get_opcodes.each do |opcode|
|
s.get_opcodes.each do |opcode|
|
||||||
out.do_op(opcode)
|
out.do_op(opcode)
|
||||||
end
|
end
|
||||||
|
|
||||||
out.result
|
out.result
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.html2list(x, b=false)
|
def self.html2list(x, b=false)
|
||||||
mode = 'char'
|
mode = 'char'
|
||||||
cur = ''
|
cur = ''
|
||||||
out = []
|
out = []
|
||||||
|
|
||||||
x = x.split(//) if x.kind_of? String
|
x = x.split(//) if x.kind_of? String
|
||||||
|
|
||||||
x.each do |c|
|
x.each do |c|
|
||||||
if mode == 'tag'
|
if mode == 'tag'
|
||||||
if c == '>'
|
if c == '>'
|
||||||
if b
|
if b
|
||||||
cur += ']'
|
cur += ']'
|
||||||
else
|
else
|
||||||
cur += c
|
cur += c
|
||||||
end
|
end
|
||||||
out.push(cur)
|
out.push(cur)
|
||||||
cur = ''
|
cur = ''
|
||||||
mode = 'char'
|
mode = 'char'
|
||||||
else
|
else
|
||||||
cur += c
|
cur += c
|
||||||
end
|
end
|
||||||
elsif mode == 'char'
|
elsif mode == 'char'
|
||||||
if c == '<'
|
if c == '<'
|
||||||
out.push cur
|
out.push cur
|
||||||
if b
|
if b
|
||||||
cur = '['
|
cur = '['
|
||||||
else
|
else
|
||||||
cur = c
|
cur = c
|
||||||
end
|
end
|
||||||
mode = 'tag'
|
mode = 'tag'
|
||||||
elsif /\s/.match c
|
elsif /\s/.match c
|
||||||
out.push cur + c
|
out.push cur + c
|
||||||
cur = ''
|
cur = ''
|
||||||
else
|
else
|
||||||
cur += c
|
cur += c
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
out.push cur
|
out.push cur
|
||||||
# TODO: make something better here
|
# TODO: make something better here
|
||||||
out.each{|x| x.chomp! unless is_newline(x)}
|
out.each{|x| x.chomp! unless is_newline(x)}
|
||||||
out.find_all { |x| x != '' }
|
out.find_all { |x| x != '' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if __FILE__ == $0
|
if __FILE__ == $0
|
||||||
|
|
||||||
require 'pp'
|
require 'pp'
|
||||||
# a = "<p>this is the original string</p>" # \n<p>but around the world</p>"
|
# a = "<p>this is the original string</p>" # \n<p>but around the world</p>"
|
||||||
# b = "<p>this is the original </p><p>other parag</p><p>string</p>"
|
# b = "<p>this is the original </p><p>other parag</p><p>string</p>"
|
||||||
a = "<ul>\n\t<li>one</li>\n\t<li>two</li>\n</ul>"
|
a = "<ul>\n\t<li>one</li>\n\t<li>two</li>\n</ul>"
|
||||||
b = "<ul>\n\t<li>one</li>\n\t<li>two\n\t<ul><li>abc</li></ul></li>\n</ul>"
|
b = "<ul>\n\t<li>one</li>\n\t<li>two\n\t<ul><li>abc</li></ul></li>\n</ul>"
|
||||||
puts a
|
puts a
|
||||||
pp HTMLDiff.html2list(a)
|
pp HTMLDiff.html2list(a)
|
||||||
puts
|
puts
|
||||||
puts b
|
puts b
|
||||||
pp HTMLDiff.html2list(b)
|
pp HTMLDiff.html2list(b)
|
||||||
puts
|
puts
|
||||||
puts HTMLDiff.diff(a, b)
|
puts HTMLDiff.diff(a, b)
|
||||||
end
|
end
|
|
@ -1,15 +1,15 @@
|
||||||
# Model methods that want to rollback transactions gracefully
|
# Model methods that want to rollback transactions gracefully
|
||||||
# (i.e, returning the user back to the form from which the request was posted)
|
# (i.e, returning the user back to the form from which the request was posted)
|
||||||
# should raise Instiki::ValidationError.
|
# should raise Instiki::ValidationError.
|
||||||
#
|
#
|
||||||
# E.g. if a model object does
|
# E.g. if a model object does
|
||||||
# raise "Foo: '#{foo}' is not equal to Bar: '#{bar}'" if (foo != bar)
|
# raise "Foo: '#{foo}' is not equal to Bar: '#{bar}'" if (foo != bar)
|
||||||
#
|
#
|
||||||
# then the operation is not committed; Rails returns the user to the page
|
# then the operation is not committed; Rails returns the user to the page
|
||||||
# where s/he was entering foo and bar, and the error message will be displayed
|
# where s/he was entering foo and bar, and the error message will be displayed
|
||||||
# on the page
|
# on the page
|
||||||
|
|
||||||
module Instiki
|
module Instiki
|
||||||
class ValidationError < StandardError
|
class ValidationError < StandardError
|
||||||
end
|
end
|
||||||
end
|
end
|
302
libraries/rdocsupport.rb
Executable file → Normal file
302
libraries/rdocsupport.rb
Executable file → Normal file
|
@ -1,152 +1,152 @@
|
||||||
begin
|
begin
|
||||||
require "rdoc/markup/simple_markup"
|
require "rdoc/markup/simple_markup"
|
||||||
require 'rdoc/markup/simple_markup/to_html'
|
require 'rdoc/markup/simple_markup/to_html'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
# use old version if available
|
# use old version if available
|
||||||
require 'markup/simple_markup'
|
require 'markup/simple_markup'
|
||||||
require 'markup/simple_markup/to_html'
|
require 'markup/simple_markup/to_html'
|
||||||
end
|
end
|
||||||
|
|
||||||
module RDocSupport
|
module RDocSupport
|
||||||
|
|
||||||
# A simple +rdoc+ markup class which recognizes some additional
|
# A simple +rdoc+ markup class which recognizes some additional
|
||||||
# formatting commands suitable for Wiki use.
|
# formatting commands suitable for Wiki use.
|
||||||
class RDocMarkup < SM::SimpleMarkup
|
class RDocMarkup < SM::SimpleMarkup
|
||||||
def initialize
|
def initialize
|
||||||
super()
|
super()
|
||||||
|
|
||||||
pre = '(?:\\s|^|\\\\)'
|
pre = '(?:\\s|^|\\\\)'
|
||||||
|
|
||||||
# links of the form
|
# links of the form
|
||||||
# [[<url> description with spaces]]
|
# [[<url> description with spaces]]
|
||||||
add_special(/((\\)?\[\[\S+?\s+.+?\]\])/,:TIDYLINK)
|
add_special(/((\\)?\[\[\S+?\s+.+?\]\])/,:TIDYLINK)
|
||||||
|
|
||||||
# and external references
|
# and external references
|
||||||
add_special(/((\\)?(link:|anchor:|http:|mailto:|ftp:|img:|www\.)\S+\w\/?)/,
|
add_special(/((\\)?(link:|anchor:|http:|mailto:|ftp:|img:|www\.)\S+\w\/?)/,
|
||||||
:HYPERLINK)
|
:HYPERLINK)
|
||||||
|
|
||||||
# <br/>
|
# <br/>
|
||||||
add_special(%r{(#{pre}<br/>)}, :BR)
|
add_special(%r{(#{pre}<br/>)}, :BR)
|
||||||
|
|
||||||
# and <center> ... </center>
|
# and <center> ... </center>
|
||||||
add_html("center", :CENTER)
|
add_html("center", :CENTER)
|
||||||
end
|
end
|
||||||
|
|
||||||
def convert(text, handler)
|
def convert(text, handler)
|
||||||
super.sub(/^<p>\n/, '').sub(/<\/p>$/, '')
|
super.sub(/^<p>\n/, '').sub(/<\/p>$/, '')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Handle special hyperlinking requirments for RDoc formatted
|
# Handle special hyperlinking requirments for RDoc formatted
|
||||||
# entries. Requires RDoc
|
# entries. Requires RDoc
|
||||||
|
|
||||||
class HyperLinkHtml < SM::ToHtml
|
class HyperLinkHtml < SM::ToHtml
|
||||||
|
|
||||||
# Initialize the HyperLinkHtml object.
|
# Initialize the HyperLinkHtml object.
|
||||||
# [path] location of the node
|
# [path] location of the node
|
||||||
# [site] object representing the whole site (typically of class
|
# [site] object representing the whole site (typically of class
|
||||||
# +Site+)
|
# +Site+)
|
||||||
def initialize
|
def initialize
|
||||||
super()
|
super()
|
||||||
add_tag(:CENTER, "<center>", "</center>")
|
add_tag(:CENTER, "<center>", "</center>")
|
||||||
end
|
end
|
||||||
|
|
||||||
# handle <br/>
|
# handle <br/>
|
||||||
def handle_special_BR(special)
|
def handle_special_BR(special)
|
||||||
return "<br/>" if special.text[0,1] == '\\'
|
return "<br/>" if special.text[0,1] == '\\'
|
||||||
special.text
|
special.text
|
||||||
end
|
end
|
||||||
|
|
||||||
# We're invoked with a potential external hyperlink.
|
# We're invoked with a potential external hyperlink.
|
||||||
# [mailto:] just gets inserted.
|
# [mailto:] just gets inserted.
|
||||||
# [http:] links are checked to see if they
|
# [http:] links are checked to see if they
|
||||||
# reference an image. If so, that image gets inserted
|
# reference an image. If so, that image gets inserted
|
||||||
# using an <img> tag. Otherwise a conventional <a href>
|
# using an <img> tag. Otherwise a conventional <a href>
|
||||||
# is used.
|
# is used.
|
||||||
# [img:] insert a <tt><img></tt> tag
|
# [img:] insert a <tt><img></tt> tag
|
||||||
# [link:] used to insert arbitrary <tt><a></tt> references
|
# [link:] used to insert arbitrary <tt><a></tt> references
|
||||||
# [anchor:] used to create an anchor
|
# [anchor:] used to create an anchor
|
||||||
def handle_special_HYPERLINK(special)
|
def handle_special_HYPERLINK(special)
|
||||||
text = special.text.strip
|
text = special.text.strip
|
||||||
return text[1..-1] if text[0,1] == '\\'
|
return text[1..-1] if text[0,1] == '\\'
|
||||||
url = special.text.strip
|
url = special.text.strip
|
||||||
if url =~ /([A-Za-z]+):(.*)/
|
if url =~ /([A-Za-z]+):(.*)/
|
||||||
type = $1
|
type = $1
|
||||||
path = $2
|
path = $2
|
||||||
else
|
else
|
||||||
type = "http"
|
type = "http"
|
||||||
path = url
|
path = url
|
||||||
url = "http://#{url}"
|
url = "http://#{url}"
|
||||||
end
|
end
|
||||||
|
|
||||||
case type
|
case type
|
||||||
when "http"
|
when "http"
|
||||||
if url =~ /\.(gif|png|jpg|jpeg|bmp)$/
|
if url =~ /\.(gif|png|jpg|jpeg|bmp)$/
|
||||||
"<img src=\"#{url}\"/>"
|
"<img src=\"#{url}\"/>"
|
||||||
else
|
else
|
||||||
"<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
|
"<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
|
||||||
end
|
end
|
||||||
when "img"
|
when "img"
|
||||||
"<img src=\"#{path}\"/>"
|
"<img src=\"#{path}\"/>"
|
||||||
when "link"
|
when "link"
|
||||||
"<a href=\"#{path}\">#{path}</a>"
|
"<a href=\"#{path}\">#{path}</a>"
|
||||||
when "anchor"
|
when "anchor"
|
||||||
"<a name=\"#{path}\"></a>"
|
"<a name=\"#{path}\"></a>"
|
||||||
else
|
else
|
||||||
"<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
|
"<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Here's a hyperlink where the label is different to the URL
|
# Here's a hyperlink where the label is different to the URL
|
||||||
# [[url label that may contain spaces]]
|
# [[url label that may contain spaces]]
|
||||||
#
|
#
|
||||||
|
|
||||||
def handle_special_TIDYLINK(special)
|
def handle_special_TIDYLINK(special)
|
||||||
text = special.text.strip
|
text = special.text.strip
|
||||||
return text[1..-1] if text[0,1] == '\\'
|
return text[1..-1] if text[0,1] == '\\'
|
||||||
unless text =~ /\[\[(\S+?)\s+(.+?)\]\]/
|
unless text =~ /\[\[(\S+?)\s+(.+?)\]\]/
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
url = $1
|
url = $1
|
||||||
label = $2
|
label = $2
|
||||||
label = RDocFormatter.new(label).to_html
|
label = RDocFormatter.new(label).to_html
|
||||||
label = label.split.select{|x| x =~ /\S/}.
|
label = label.split.select{|x| x =~ /\S/}.
|
||||||
map{|x| x.chomp}.join(' ')
|
map{|x| x.chomp}.join(' ')
|
||||||
|
|
||||||
case url
|
case url
|
||||||
when /link:(\S+)/
|
when /link:(\S+)/
|
||||||
return %{<a href="#{$1}">#{label}</a>}
|
return %{<a href="#{$1}">#{label}</a>}
|
||||||
when /img:(\S+)/
|
when /img:(\S+)/
|
||||||
return %{<img src="http://#{$1}" alt="#{label}" />}
|
return %{<img src="http://#{$1}" alt="#{label}" />}
|
||||||
when /rubytalk:(\S+)/
|
when /rubytalk:(\S+)/
|
||||||
return %{<a href="http://ruby-talk.org/blade/#{$1}">#{label}</a>}
|
return %{<a href="http://ruby-talk.org/blade/#{$1}">#{label}</a>}
|
||||||
when /rubygarden:(\S+)/
|
when /rubygarden:(\S+)/
|
||||||
return %{<a href="http://www.rubygarden.org/ruby?#{$1}">#{label}</a>}
|
return %{<a href="http://www.rubygarden.org/ruby?#{$1}">#{label}</a>}
|
||||||
when /c2:(\S+)/
|
when /c2:(\S+)/
|
||||||
return %{<a href="http://c2.com/cgi/wiki?#{$1}">#{label}</a>}
|
return %{<a href="http://c2.com/cgi/wiki?#{$1}">#{label}</a>}
|
||||||
when /isbn:(\S+)/
|
when /isbn:(\S+)/
|
||||||
return %{<a href="http://search.barnesandnoble.com/bookSearch/} +
|
return %{<a href="http://search.barnesandnoble.com/bookSearch/} +
|
||||||
%{isbnInquiry.asp?isbn=#{$1}">#{label}</a>}
|
%{isbnInquiry.asp?isbn=#{$1}">#{label}</a>}
|
||||||
end
|
end
|
||||||
|
|
||||||
unless url =~ /\w+?:/
|
unless url =~ /\w+?:/
|
||||||
url = "http://#{url}"
|
url = "http://#{url}"
|
||||||
end
|
end
|
||||||
|
|
||||||
"<a href=\"#{url}\">#{label}</a>"
|
"<a href=\"#{url}\">#{label}</a>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RDocFormatter
|
class RDocFormatter
|
||||||
def initialize(text)
|
def initialize(text)
|
||||||
@text = text
|
@text = text
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_html
|
def to_html
|
||||||
markup = RDocMarkup.new
|
markup = RDocMarkup.new
|
||||||
h = HyperLinkHtml.new
|
h = HyperLinkHtml.new
|
||||||
markup.convert(@text, h)
|
markup.convert(@text, h)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
1466
libraries/redcloth_for_tex.rb
Executable file → Normal file
1466
libraries/redcloth_for_tex.rb
Executable file → Normal file
File diff suppressed because it is too large
Load diff
214
libraries/url_rewriting_hack.rb
Executable file → Normal file
214
libraries/url_rewriting_hack.rb
Executable file → Normal file
|
@ -1,107 +1,107 @@
|
||||||
# Below are some hacks to Rails internal classes that implement Instiki URLs scheme.
|
# Below are some hacks to Rails internal classes that implement Instiki URLs scheme.
|
||||||
# It is no doubt a bad practice to override internal implementation of anything.
|
# It is no doubt a bad practice to override internal implementation of anything.
|
||||||
# When Rails implements some way to do it in the framework, this code should be replaced
|
# When Rails implements some way to do it in the framework, this code should be replaced
|
||||||
# with something more legitimate.
|
# with something more legitimate.
|
||||||
|
|
||||||
# In Instiki URLs are mapped to the ActionPack actions, possibly performed on a particular
|
# In Instiki URLs are mapped to the ActionPack actions, possibly performed on a particular
|
||||||
# web (sub-wiki) and page within that web.
|
# web (sub-wiki) and page within that web.
|
||||||
#
|
#
|
||||||
# 1. Controller is determined by action name (default is 'wiki')
|
# 1. Controller is determined by action name (default is 'wiki')
|
||||||
# 2. '/name1/' maps to action 'name1', unspecified web
|
# 2. '/name1/' maps to action 'name1', unspecified web
|
||||||
# Example: http://localhost/new_system/
|
# Example: http://localhost/new_system/
|
||||||
# 3. Special case of above, URI '/wiki/' maps to action 'index', because Rails sets this address
|
# 3. Special case of above, URI '/wiki/' maps to action 'index', because Rails sets this address
|
||||||
# when default controller name is specified as 'wiki', and an application root
|
# when default controller name is specified as 'wiki', and an application root
|
||||||
# (http://localhost:2500/)is requested.
|
# (http://localhost:2500/)is requested.
|
||||||
# 4. '/name1/name2/' maps to web 'name1', action 'name2'
|
# 4. '/name1/name2/' maps to web 'name1', action 'name2'
|
||||||
# Example: http://localhost/mywiki/search/
|
# Example: http://localhost/mywiki/search/
|
||||||
# 5. '/name1/name2/name3/' maps to web 'name1', action 'name2',
|
# 5. '/name1/name2/name3/' maps to web 'name1', action 'name2',
|
||||||
# Example: http://localhost/mywiki/show/HomePage
|
# Example: http://localhost/mywiki/show/HomePage
|
||||||
|
|
||||||
|
|
||||||
require 'dispatcher'
|
require 'dispatcher'
|
||||||
|
|
||||||
# Overrides Rails DispatchServlet.parse_uri
|
# Overrides Rails DispatchServlet.parse_uri
|
||||||
class DispatchServlet
|
class DispatchServlet
|
||||||
|
|
||||||
def self.parse_uri(path)
|
def self.parse_uri(path)
|
||||||
result = parse_path(path)
|
result = parse_path(path)
|
||||||
if result
|
if result
|
||||||
result[:controller] = ActionMapper.map_to_controller(result[:action])
|
result[:controller] = ActionMapper.map_to_controller(result[:action])
|
||||||
result
|
result
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.parse_path(path)
|
def self.parse_path(path)
|
||||||
ApplicationController.logger.debug "Parsing URI '#{path}'"
|
ApplicationController.logger.debug "Parsing URI '#{path}'"
|
||||||
component = '([-_a-zA-Z0-9]+)'
|
component = '([-_a-zA-Z0-9]+)'
|
||||||
page_name = '(.*)'
|
page_name = '(.*)'
|
||||||
case path.sub(%r{^/(?:fcgi|mruby|cgi)/}, "/")
|
case path.sub(%r{^/(?:fcgi|mruby|cgi)/}, "/")
|
||||||
when '/wiki/'
|
when '/wiki/'
|
||||||
{ :web => nil, :controller => 'wiki', :action => 'index' }
|
{ :web => nil, :controller => 'wiki', :action => 'index' }
|
||||||
when %r{^/#{component}/?$}
|
when %r{^/#{component}/?$}
|
||||||
{ :web => nil, :controller => 'wiki', :action => $1 }
|
{ :web => nil, :controller => 'wiki', :action => $1 }
|
||||||
when %r{^/#{component}/#{component}/?$}
|
when %r{^/#{component}/#{component}/?$}
|
||||||
{ :web => $1, :controller => 'wiki', :action => $2 }
|
{ :web => $1, :controller => 'wiki', :action => $2 }
|
||||||
when %r{^/#{component}/#{component}/(.*)/?$}
|
when %r{^/#{component}/#{component}/(.*)/?$}
|
||||||
{ :web => $1, :controller => 'wiki', :action => $2, :id => drop_trailing_slash($3) }
|
{ :web => $1, :controller => 'wiki', :action => $2, :id => drop_trailing_slash($3) }
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.drop_trailing_slash(line)
|
def self.drop_trailing_slash(line)
|
||||||
if line[-1] == ?/
|
if line[-1] == ?/
|
||||||
line.chop
|
line.chop
|
||||||
else
|
else
|
||||||
line
|
line
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionMapper
|
class ActionMapper
|
||||||
|
|
||||||
@@action_to_controller_map = {
|
@@action_to_controller_map = {
|
||||||
'file' => 'file',
|
'file' => 'file',
|
||||||
'pic' => 'file'
|
'pic' => 'file'
|
||||||
}
|
}
|
||||||
|
|
||||||
def self.map_to_controller(action)
|
def self.map_to_controller(action)
|
||||||
@@action_to_controller_map[action] || 'wiki'
|
@@action_to_controller_map[action] || 'wiki'
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
require 'action_controller/url_rewriter.rb'
|
require 'action_controller/url_rewriter.rb'
|
||||||
|
|
||||||
# Overrides parts of AP UrlRewriter to achieve the Instiki's legacy URL scheme
|
# Overrides parts of AP UrlRewriter to achieve the Instiki's legacy URL scheme
|
||||||
module ActionController
|
module ActionController
|
||||||
class UrlRewriter
|
class UrlRewriter
|
||||||
|
|
||||||
VALID_OPTIONS << :web unless VALID_OPTIONS.include? :web
|
VALID_OPTIONS << :web unless VALID_OPTIONS.include? :web
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def resolve_aliases(options)
|
def resolve_aliases(options)
|
||||||
options[:controller_prefix] = options[:web] unless options[:web].nil?
|
options[:controller_prefix] = options[:web] unless options[:web].nil?
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
|
||||||
def controller_name(options, controller_prefix)
|
def controller_name(options, controller_prefix)
|
||||||
ensure_slash_suffix(options, :controller_prefix)
|
ensure_slash_suffix(options, :controller_prefix)
|
||||||
|
|
||||||
controller_name = case options[:controller_prefix]
|
controller_name = case options[:controller_prefix]
|
||||||
when String: options[:controller_prefix]
|
when String: options[:controller_prefix]
|
||||||
when false : ""
|
when false : ""
|
||||||
when nil : controller_prefix || ""
|
when nil : controller_prefix || ""
|
||||||
end
|
end
|
||||||
# In Instiki we don't need the controller name (there is only one comtroller, anyway)
|
# In Instiki we don't need the controller name (there is only one comtroller, anyway)
|
||||||
# therefore the below line is commented out
|
# therefore the below line is commented out
|
||||||
# controller_name << (options[:controller] + "/") if options[:controller]
|
# controller_name << (options[:controller] + "/") if options[:controller]
|
||||||
return controller_name
|
return controller_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
36
natives/osx/desktop_launcher/AppDelegate.h
Executable file → Normal file
36
natives/osx/desktop_launcher/AppDelegate.h
Executable file → Normal file
|
@ -1,18 +1,18 @@
|
||||||
/* AppDelegate */
|
/* AppDelegate */
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
@interface AppDelegate : NSObject
|
@interface AppDelegate : NSObject
|
||||||
{
|
{
|
||||||
IBOutlet NSMenu* statusMenu;
|
IBOutlet NSMenu* statusMenu;
|
||||||
NSTask* serverCommand;
|
NSTask* serverCommand;
|
||||||
int processID;
|
int processID;
|
||||||
BOOL shouldOpenUntitled;
|
BOOL shouldOpenUntitled;
|
||||||
|
|
||||||
NSNetService* service;
|
NSNetService* service;
|
||||||
}
|
}
|
||||||
- (IBAction)about:(id)sender;
|
- (IBAction)about:(id)sender;
|
||||||
- (IBAction)goToHomepage:(id)sender;
|
- (IBAction)goToHomepage:(id)sender;
|
||||||
- (IBAction)goToInstikiOrg:(id)sender;
|
- (IBAction)goToInstikiOrg:(id)sender;
|
||||||
- (IBAction)quit:(id)sender;
|
- (IBAction)quit:(id)sender;
|
||||||
@end
|
@end
|
||||||
|
|
218
natives/osx/desktop_launcher/AppDelegate.mm
Executable file → Normal file
218
natives/osx/desktop_launcher/AppDelegate.mm
Executable file → Normal file
|
@ -1,109 +1,109 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
int launch_ruby (char const* cmd)
|
int launch_ruby (char const* cmd)
|
||||||
{
|
{
|
||||||
int pId, parentID = getpid();
|
int pId, parentID = getpid();
|
||||||
if((pId = fork()) == 0) // child
|
if((pId = fork()) == 0) // child
|
||||||
{
|
{
|
||||||
NSLog(@"set child (%d) to pgrp %d", getpid(), parentID);
|
NSLog(@"set child (%d) to pgrp %d", getpid(), parentID);
|
||||||
setpgrp(0, parentID);
|
setpgrp(0, parentID);
|
||||||
system(cmd);
|
system(cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else // parent
|
else // parent
|
||||||
{
|
{
|
||||||
NSLog(@"started child process: %d", pId);
|
NSLog(@"started child process: %d", pId);
|
||||||
return pId;
|
return pId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
|
||||||
- (NSString*)storageDirectory
|
- (NSString*)storageDirectory
|
||||||
{
|
{
|
||||||
NSString* dir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Instiki"];
|
NSString* dir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Instiki"];
|
||||||
[[NSFileManager defaultManager] createDirectoryAtPath:dir attributes:nil];
|
[[NSFileManager defaultManager] createDirectoryAtPath:dir attributes:nil];
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)awakeFromNib
|
- (void)awakeFromNib
|
||||||
{
|
{
|
||||||
setpgrp(0, getpid());
|
setpgrp(0, getpid());
|
||||||
|
|
||||||
if([[[[NSBundle mainBundle] infoDictionary] objectForKey:@"LSUIElement"] isEqualToString:@"1"])
|
if([[[[NSBundle mainBundle] infoDictionary] objectForKey:@"LSUIElement"] isEqualToString:@"1"])
|
||||||
{
|
{
|
||||||
NSStatusBar* bar = [NSStatusBar systemStatusBar];
|
NSStatusBar* bar = [NSStatusBar systemStatusBar];
|
||||||
NSStatusItem* item = [[bar statusItemWithLength:NSVariableStatusItemLength] retain];
|
NSStatusItem* item = [[bar statusItemWithLength:NSVariableStatusItemLength] retain];
|
||||||
[item setTitle:@"Wiki"];
|
[item setTitle:@"Wiki"];
|
||||||
[item setHighlightMode:YES];
|
[item setHighlightMode:YES];
|
||||||
[item setMenu:statusMenu];
|
[item setMenu:statusMenu];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
|
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
|
||||||
NSString* ruby = [bundle pathForResource:@"ruby" ofType:nil];
|
NSString* ruby = [bundle pathForResource:@"ruby" ofType:nil];
|
||||||
NSString* script = [[bundle resourcePath] stringByAppendingPathComponent:@"rb_src/instiki.rb"];
|
NSString* script = [[bundle resourcePath] stringByAppendingPathComponent:@"rb_src/instiki.rb"];
|
||||||
if(ruby && script)
|
if(ruby && script)
|
||||||
{
|
{
|
||||||
NSString* cmd = [NSString stringWithFormat:
|
NSString* cmd = [NSString stringWithFormat:
|
||||||
@"%@ -I '%@' -I '%@' '%@' -s --storage='%@'",
|
@"%@ -I '%@' -I '%@' '%@' -s --storage='%@'",
|
||||||
ruby,
|
ruby,
|
||||||
[[bundle resourcePath] stringByAppendingPathComponent:@"lib/ruby/1.8"],
|
[[bundle resourcePath] stringByAppendingPathComponent:@"lib/ruby/1.8"],
|
||||||
[[bundle resourcePath] stringByAppendingPathComponent:@"lib/ruby/1.8/powerpc-darwin"],
|
[[bundle resourcePath] stringByAppendingPathComponent:@"lib/ruby/1.8/powerpc-darwin"],
|
||||||
script,
|
script,
|
||||||
[self storageDirectory]
|
[self storageDirectory]
|
||||||
];
|
];
|
||||||
NSLog(@"starting %@", cmd);
|
NSLog(@"starting %@", cmd);
|
||||||
processID = launch_ruby([cmd UTF8String]);
|
processID = launch_ruby([cmd UTF8String]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public the service using rendezvous */
|
/* public the service using rendezvous */
|
||||||
service = [[NSNetService alloc]
|
service = [[NSNetService alloc]
|
||||||
initWithDomain:@"" // default domain
|
initWithDomain:@"" // default domain
|
||||||
type:@"_http._tcp."
|
type:@"_http._tcp."
|
||||||
name:[NSString stringWithFormat:@"%@'s Instiki", NSFullUserName()]
|
name:[NSString stringWithFormat:@"%@'s Instiki", NSFullUserName()]
|
||||||
port:2500];
|
port:2500];
|
||||||
[service publish];
|
[service publish];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(NSNotification*)aNotification
|
- (void)applicationWillTerminate:(NSNotification*)aNotification
|
||||||
{
|
{
|
||||||
[service stop];
|
[service stop];
|
||||||
[service release];
|
[service release];
|
||||||
|
|
||||||
kill(0, SIGTERM);
|
kill(0, SIGTERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)about:(id)sender
|
- (IBAction)about:(id)sender
|
||||||
{
|
{
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
[NSApp orderFrontStandardAboutPanel:self];
|
[NSApp orderFrontStandardAboutPanel:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)goToHomepage:(id)sender
|
- (IBAction)goToHomepage:(id)sender
|
||||||
{
|
{
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://localhost:2500/"]];
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://localhost:2500/"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)goToInstikiOrg:(id)sender
|
- (IBAction)goToInstikiOrg:(id)sender
|
||||||
{
|
{
|
||||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.instiki.org/"]];
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.instiki.org/"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication*)sender
|
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication*)sender
|
||||||
{
|
{
|
||||||
return shouldOpenUntitled ?: (shouldOpenUntitled = YES, NO);
|
return shouldOpenUntitled ?: (shouldOpenUntitled = YES, NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)applicationOpenUntitledFile:(NSApplication*)theApplication
|
- (BOOL)applicationOpenUntitledFile:(NSApplication*)theApplication
|
||||||
{
|
{
|
||||||
return [self goToHomepage:self], YES;
|
return [self goToHomepage:self], YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)quit:(id)sender
|
- (IBAction)quit:(id)sender
|
||||||
{
|
{
|
||||||
[NSApp terminate:self];
|
[NSApp terminate:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
30
natives/osx/desktop_launcher/Credits.html
Executable file → Normal file
30
natives/osx/desktop_launcher/Credits.html
Executable file → Normal file
|
@ -1,16 +1,16 @@
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Engineering:</dt>
|
<dt>Engineering:</dt>
|
||||||
<dd>Some people</dd>
|
<dd>Some people</dd>
|
||||||
|
|
||||||
<dt>Human Interface Design:</dt>
|
<dt>Human Interface Design:</dt>
|
||||||
<dd>Some other people</dd>
|
<dd>Some other people</dd>
|
||||||
|
|
||||||
<dt>Testing:</dt>
|
<dt>Testing:</dt>
|
||||||
<dd>Hopefully not nobody</dd>
|
<dd>Hopefully not nobody</dd>
|
||||||
|
|
||||||
<dt>Documentation:</dt>
|
<dt>Documentation:</dt>
|
||||||
<dd>Whoever</dd>
|
<dd>Whoever</dd>
|
||||||
|
|
||||||
<dt>With special thanks to:</dt>
|
<dt>With special thanks to:</dt>
|
||||||
<dd>Mom</dd>
|
<dd>Mom</dd>
|
||||||
</dl>
|
</dl>
|
0
natives/osx/desktop_launcher/English.lproj/InfoPlist.strings
Executable file → Normal file
0
natives/osx/desktop_launcher/English.lproj/InfoPlist.strings
Executable file → Normal file
24
natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib
generated
Executable file → Normal file
24
natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib
generated
Executable file → Normal file
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
IBClasses = (
|
IBClasses = (
|
||||||
{
|
{
|
||||||
ACTIONS = {about = id; goToHomepage = id; goToInstikiOrg = id; quit = id; };
|
ACTIONS = {about = id; goToHomepage = id; goToInstikiOrg = id; quit = id; };
|
||||||
CLASS = AppDelegate;
|
CLASS = AppDelegate;
|
||||||
LANGUAGE = ObjC;
|
LANGUAGE = ObjC;
|
||||||
OUTLETS = {statusMenu = NSMenu; };
|
OUTLETS = {statusMenu = NSMenu; };
|
||||||
SUPERCLASS = NSObject;
|
SUPERCLASS = NSObject;
|
||||||
},
|
},
|
||||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||||
);
|
);
|
||||||
IBVersion = 1;
|
IBVersion = 1;
|
||||||
}
|
}
|
48
natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib
generated
Executable file → Normal file
48
natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib
generated
Executable file → Normal file
|
@ -1,24 +1,24 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>IBDocumentLocation</key>
|
<key>IBDocumentLocation</key>
|
||||||
<string>109 6 356 240 0 0 1440 878 </string>
|
<string>109 6 356 240 0 0 1440 878 </string>
|
||||||
<key>IBEditorPositions</key>
|
<key>IBEditorPositions</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>206</key>
|
<key>206</key>
|
||||||
<string>112 300 116 87 0 0 1440 878 </string>
|
<string>112 300 116 87 0 0 1440 878 </string>
|
||||||
<key>29</key>
|
<key>29</key>
|
||||||
<string>241 316 70 44 0 0 1440 878 </string>
|
<string>241 316 70 44 0 0 1440 878 </string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>IBFramework Version</key>
|
<key>IBFramework Version</key>
|
||||||
<string>349.0</string>
|
<string>349.0</string>
|
||||||
<key>IBOpenObjects</key>
|
<key>IBOpenObjects</key>
|
||||||
<array>
|
<array>
|
||||||
<integer>206</integer>
|
<integer>206</integer>
|
||||||
<integer>29</integer>
|
<integer>29</integer>
|
||||||
</array>
|
</array>
|
||||||
<key>IBSystem Version</key>
|
<key>IBSystem Version</key>
|
||||||
<string>7H63</string>
|
<string>7H63</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
0
natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib
generated
Executable file → Normal file
0
natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib
generated
Executable file → Normal file
24
natives/osx/desktop_launcher/Info.plist
Executable file → Normal file
24
natives/osx/desktop_launcher/Info.plist
Executable file → Normal file
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
CFBundleDevelopmentRegion = English;
|
CFBundleDevelopmentRegion = English;
|
||||||
CFBundleExecutable = Instiki;
|
CFBundleExecutable = Instiki;
|
||||||
CFBundleIconFile = "";
|
CFBundleIconFile = "";
|
||||||
CFBundleIdentifier = "com.nextangle.instiki";
|
CFBundleIdentifier = "com.nextangle.instiki";
|
||||||
CFBundleInfoDictionaryVersion = "6.0";
|
CFBundleInfoDictionaryVersion = "6.0";
|
||||||
CFBundlePackageType = APPL;
|
CFBundlePackageType = APPL;
|
||||||
CFBundleSignature = WIKI;
|
CFBundleSignature = WIKI;
|
||||||
CFBundleVersion = "0.9.0";
|
CFBundleVersion = "0.9.0";
|
||||||
LSUIElement = 1;
|
LSUIElement = 1;
|
||||||
NSMainNibFile = MainMenu;
|
NSMainNibFile = MainMenu;
|
||||||
NSPrincipalClass = NSApplication;
|
NSPrincipalClass = NSApplication;
|
||||||
}
|
}
|
1184
natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj
Executable file → Normal file
1184
natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj
Executable file → Normal file
File diff suppressed because it is too large
Load diff
14
natives/osx/desktop_launcher/Instiki_Prefix.pch
Executable file → Normal file
14
natives/osx/desktop_launcher/Instiki_Prefix.pch
Executable file → Normal file
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// Prefix header for all source files of the 'Instiki' target in the 'Instiki' project
|
// Prefix header for all source files of the 'Instiki' target in the 'Instiki' project
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifdef __OBJC__
|
#ifdef __OBJC__
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
18
natives/osx/desktop_launcher/MakeDMG.sh
Executable file → Normal file
18
natives/osx/desktop_launcher/MakeDMG.sh
Executable file → Normal file
|
@ -1,9 +1,9 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
hdiutil create -size 12m -fs HFS+ -volname Instiki -ov /tmp/Instiki_12MB.dmg
|
hdiutil create -size 12m -fs HFS+ -volname Instiki -ov /tmp/Instiki_12MB.dmg
|
||||||
hdiutil mount /tmp/Instiki_12MB.dmg
|
hdiutil mount /tmp/Instiki_12MB.dmg
|
||||||
# strip ~/ruby/instiki/natives/osx/build/Instiki.app/Contents/MacOS/Instiki
|
# strip ~/ruby/instiki/natives/osx/build/Instiki.app/Contents/MacOS/Instiki
|
||||||
ditto ~/ruby/instiki/natives/osx/desktop_launcher/build/Instiki.app /Volumes/Instiki/Instiki.app
|
ditto ~/ruby/instiki/natives/osx/desktop_launcher/build/Instiki.app /Volumes/Instiki/Instiki.app
|
||||||
hdiutil unmount /Volumes/Instiki
|
hdiutil unmount /Volumes/Instiki
|
||||||
hdiutil convert -format UDZO -o /tmp/Instiki.dmg /tmp/Instiki_12MB.dmg
|
hdiutil convert -format UDZO -o /tmp/Instiki.dmg /tmp/Instiki_12MB.dmg
|
||||||
hdiutil internet-enable -yes /tmp/Instiki.dmg
|
hdiutil internet-enable -yes /tmp/Instiki.dmg
|
||||||
|
|
28
natives/osx/desktop_launcher/main.mm
Executable file → Normal file
28
natives/osx/desktop_launcher/main.mm
Executable file → Normal file
|
@ -1,14 +1,14 @@
|
||||||
//
|
//
|
||||||
// main.mm
|
// main.mm
|
||||||
// Instiki
|
// Instiki
|
||||||
//
|
//
|
||||||
// Created by Allan Odgaard on Thu May 20 2004.
|
// Created by Allan Odgaard on Thu May 20 2004.
|
||||||
// Copyright (c) 2004 MacroMates. All rights reserved.
|
// Copyright (c) 2004 MacroMates. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
int main (int argc, char const* argv[])
|
int main (int argc, char const* argv[])
|
||||||
{
|
{
|
||||||
return NSApplicationMain(argc, argv);
|
return NSApplicationMain(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
32
natives/osx/desktop_launcher/version.plist
Executable file → Normal file
32
natives/osx/desktop_launcher/version.plist
Executable file → Normal file
|
@ -1,16 +1,16 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>BuildVersion</key>
|
<key>BuildVersion</key>
|
||||||
<string>17</string>
|
<string>17</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.1</string>
|
<string>0.1</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.1</string>
|
<string>0.1</string>
|
||||||
<key>ProjectName</key>
|
<key>ProjectName</key>
|
||||||
<string>NibPBTemplates</string>
|
<string>NibPBTemplates</string>
|
||||||
<key>SourceVersion</key>
|
<key>SourceVersion</key>
|
||||||
<string>1150000</string>
|
<string>1150000</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
0
public/images/.images_go_here
Executable file → Normal file
0
public/images/.images_go_here
Executable file → Normal file
|
@ -1,48 +1,48 @@
|
||||||
function proposeAddress() {
|
function proposeAddress() {
|
||||||
document.getElementById('address').value =
|
document.getElementById('address').value =
|
||||||
document.getElementById('name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
document.getElementById('name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanAddress() {
|
function cleanAddress() {
|
||||||
document.getElementById('address').value =
|
document.getElementById('address').value =
|
||||||
document.getElementById('address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
document.getElementById('address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateSetup() {
|
function validateSetup() {
|
||||||
if (document.getElementById('system_password').value == "") {
|
if (document.getElementById('system_password').value == "") {
|
||||||
alert("You must enter the system password");
|
alert("You must enter the system password");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('name').value == "") {
|
if (document.getElementById('name').value == "") {
|
||||||
alert("You must pick a name for the web");
|
alert("You must pick a name for the web");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('address').value == "") {
|
if (document.getElementById('address').value == "") {
|
||||||
alert("You must pick an address for the web");
|
alert("You must pick an address for the web");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.getElementById('password').value != "" &&
|
if (document.getElementById('password').value != "" &&
|
||||||
document.getElementById('password').value != document.getElementById('password_check').value) {
|
document.getElementById('password').value != document.getElementById('password_check').value) {
|
||||||
alert("The password and its verification doesn't match");
|
alert("The password and its verification doesn't match");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// overriding auto-complete by form managers
|
// overriding auto-complete by form managers
|
||||||
// code by Chris Holland, lifted from
|
// code by Chris Holland, lifted from
|
||||||
// http://chrisholland.blogspot.com/2004/11/banks-protect-privacy-disable.html
|
// http://chrisholland.blogspot.com/2004/11/banks-protect-privacy-disable.html
|
||||||
function overrideAutocomplete() {
|
function overrideAutocomplete() {
|
||||||
if (document.getElementsByTagName) {
|
if (document.getElementsByTagName) {
|
||||||
var inputElements = document.getElementsByTagName("input");
|
var inputElements = document.getElementsByTagName("input");
|
||||||
for (i=0; inputElements[i]; i++) {
|
for (i=0; inputElements[i]; i++) {
|
||||||
if (inputElements[i].className && (inputElements[i].className.indexOf("disableAutoComplete") != -1)) {
|
if (inputElements[i].className && (inputElements[i].className.indexOf("disableAutoComplete") != -1)) {
|
||||||
inputElements[i].setAttribute("autocomplete","off");
|
inputElements[i].setAttribute("autocomplete","off");
|
||||||
}//if current input element has the disableAutoComplete class set.
|
}//if current input element has the disableAutoComplete class set.
|
||||||
}//loop thru input elements
|
}//loop thru input elements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
442
public/stylesheets/instiki.css
Executable file → Normal file
442
public/stylesheets/instiki.css
Executable file → Normal file
|
@ -1,222 +1,222 @@
|
||||||
#Container {
|
#Container {
|
||||||
float: none;
|
float: none;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#Content {
|
#Content {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
body { background-color: #fff; color: #333; }
|
body { background-color: #fff; color: #333; }
|
||||||
|
|
||||||
body, p, ol, ul, td {
|
body, p, ol, ul, td {
|
||||||
font-family: verdana, arial, helvetica, sans-serif;
|
font-family: verdana, arial, helvetica, sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a { color: #000; }
|
a { color: #000; }
|
||||||
|
|
||||||
.newWikiWord { background-color: #eee; }
|
.newWikiWord { background-color: #eee; }
|
||||||
.newWikiWord a:hover { background-color: white; }
|
.newWikiWord a:hover { background-color: white; }
|
||||||
|
|
||||||
a:visited { color: #666; }
|
a:visited { color: #666; }
|
||||||
a:hover { color: #fff; background-color:#000; }
|
a:hover { color: #fff; background-color:#000; }
|
||||||
|
|
||||||
h1, h2, h3 { color: #333; font-family: georgia, verdana; }
|
h1, h2, h3 { color: #333; font-family: georgia, verdana; }
|
||||||
h1 { font-size: 28px }
|
h1 { font-size: 28px }
|
||||||
h2 { font-size: 19px }
|
h2 { font-size: 19px }
|
||||||
h3 { font-size: 16px }
|
h3 { font-size: 16px }
|
||||||
|
|
||||||
h1#pageName {
|
h1#pageName {
|
||||||
margin: 5px 0px 0px 0px;
|
margin: 5px 0px 0px 0px;
|
||||||
padding: 0px 0px 0px 0px;
|
padding: 0px 0px 0px 0px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1#pageName small {
|
h1#pageName small {
|
||||||
color: grey;
|
color: grey;
|
||||||
line-height: 10px;
|
line-height: 10px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.nav, a.nav:link, a.nav:visited { color: #000; }
|
a.nav, a.nav:link, a.nav:visited { color: #000; }
|
||||||
a.nav:hover { color: #fff; background-color:#000; }
|
a.nav:hover { color: #fff; background-color:#000; }
|
||||||
|
|
||||||
li { margin-bottom: 7px }
|
li { margin-bottom: 7px }
|
||||||
|
|
||||||
.navigation {
|
.navigation {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
font-size : 12px;
|
font-size : 12px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation a:hover { color: #fff; background-color:#000; }
|
.navigation a:hover { color: #fff; background-color:#000; }
|
||||||
|
|
||||||
.navigation a {
|
.navigation a {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: black;
|
color: black;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation small a {
|
.navigation small a {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navOn{
|
.navOn{
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: grey;
|
color: grey;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
font-family: verdana, arial, helvetica, sans-serif;
|
font-family: verdana, arial, helvetica, sans-serif;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputBox {
|
.inputBox {
|
||||||
font-family: verdana, arial, helvetica, sans-serif;
|
font-family: verdana, arial, helvetica, sans-serif;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0px 0px 20px 0px;
|
margin: 0px 0px 20px 0px;
|
||||||
padding: 0px 30px;
|
padding: 0px 30px;
|
||||||
font-size:11px;
|
font-size:11px;
|
||||||
line-height:17px;
|
line-height:17px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ol.setup {
|
ol.setup {
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
font-family: georgia, verdana;
|
font-family: georgia, verdana;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ol.setup li {
|
ol.setup li {
|
||||||
margin-bottom: 20px
|
margin-bottom: 20px
|
||||||
}
|
}
|
||||||
|
|
||||||
.byline {
|
.byline {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.references {
|
.references {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diffdel, del.diffmod {
|
.diffdel, del.diffmod {
|
||||||
background: pink;
|
background: pink;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diffins, ins.diffmod {
|
.diffins, ins.diffmod {
|
||||||
background: lightgreen;
|
background: lightgreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer {
|
#footer {
|
||||||
height: 14px;
|
height: 14px;
|
||||||
padding: .25em 0;
|
padding: .25em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer p {
|
#footer p {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
color: gray;
|
color: gray;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
float: right;
|
float: right;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
#error {
|
#error {
|
||||||
color: darkred;
|
color: darkred;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
width: 450px;
|
width: 450px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#info {
|
#info {
|
||||||
color: darkgreen;
|
color: darkgreen;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
width: 450px;
|
width: 450px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp table {
|
#TextileHelp table {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp table+h3 {
|
#TextileHelp table+h3 {
|
||||||
margin-top: 11px;
|
margin-top: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp table td {
|
#TextileHelp table td {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
border-top: 1px dotted #ccc;
|
border-top: 1px dotted #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp table td.arrow {
|
#TextileHelp table td.arrow {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp table td.label {
|
#TextileHelp table td.label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp h3 {
|
#TextileHelp h3 {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin: 0 0 5px 0;
|
margin: 0 0 5px 0;
|
||||||
padding: 5px 0 0 0;
|
padding: 5px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#TextileHelp p {
|
#TextileHelp p {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rightHandSide {
|
.rightHandSide {
|
||||||
float: right;
|
float: right;
|
||||||
width: 147px;
|
width: 147px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
border-left: 1px dotted #ccc;
|
border-left: 1px dotted #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rightHandSide p {
|
.rightHandSide p {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newsList {
|
.newsList {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newsList p {
|
.newsList p {
|
||||||
margin-bottom:30px
|
margin-bottom:30px
|
||||||
}
|
}
|
166
script/server
166
script/server
|
@ -1,83 +1,83 @@
|
||||||
#!/usr/bin/ruby
|
#!/usr/bin/ruby
|
||||||
|
|
||||||
require 'webrick'
|
require 'webrick'
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
pwd = File.expand_path(File.dirname(__FILE__) + "/..")
|
pwd = File.expand_path(File.dirname(__FILE__) + "/..")
|
||||||
|
|
||||||
OPTIONS = {
|
OPTIONS = {
|
||||||
|
|
||||||
# Overridable options
|
# Overridable options
|
||||||
:port => 2500,
|
:port => 2500,
|
||||||
:ip => '127.0.0.1',
|
:ip => '127.0.0.1',
|
||||||
:environment => 'production',
|
:environment => 'production',
|
||||||
:server_root => File.expand_path(File.dirname(__FILE__) + '/../public/'),
|
:server_root => File.expand_path(File.dirname(__FILE__) + '/../public/'),
|
||||||
:server_type => WEBrick::SimpleServer,
|
:server_type => WEBrick::SimpleServer,
|
||||||
:storage => "#{File.expand_path(FileUtils.pwd)}/storage",
|
:storage => "#{File.expand_path(FileUtils.pwd)}/storage",
|
||||||
}
|
}
|
||||||
|
|
||||||
ARGV.options do |opts|
|
ARGV.options do |opts|
|
||||||
script_name = File.basename($0)
|
script_name = File.basename($0)
|
||||||
opts.banner = "Usage: ruby #{script_name} [options]"
|
opts.banner = "Usage: ruby #{script_name} [options]"
|
||||||
|
|
||||||
opts.separator ''
|
opts.separator ''
|
||||||
|
|
||||||
opts.on('-p', '--port=port', Integer,
|
opts.on('-p', '--port=port', Integer,
|
||||||
'Runs Instiki on the specified port.',
|
'Runs Instiki on the specified port.',
|
||||||
'Default: 2500') { |OPTIONS[:port]| }
|
'Default: 2500') { |OPTIONS[:port]| }
|
||||||
opts.on('-b', '--binding=ip', String,
|
opts.on('-b', '--binding=ip', String,
|
||||||
'Binds Rails to the specified ip.',
|
'Binds Rails to the specified ip.',
|
||||||
'Default: 127.0.0.1') { |OPTIONS[:ip]| }
|
'Default: 127.0.0.1') { |OPTIONS[:ip]| }
|
||||||
opts.on('-i', '--index=controller', String,
|
opts.on('-i', '--index=controller', String,
|
||||||
'Specifies an index controller that requests for root will go to (instead of congratulations screen).'
|
'Specifies an index controller that requests for root will go to (instead of congratulations screen).'
|
||||||
) { |OPTIONS[:index_controller]| }
|
) { |OPTIONS[:index_controller]| }
|
||||||
opts.on('-e', '--environment=name', String,
|
opts.on('-e', '--environment=name', String,
|
||||||
'Specifies the environment to run this server under (test/development/production).',
|
'Specifies the environment to run this server under (test/development/production).',
|
||||||
'Default: production') { |OPTIONS[:environment]| }
|
'Default: production') { |OPTIONS[:environment]| }
|
||||||
opts.on('-d', '--daemon',
|
opts.on('-d', '--daemon',
|
||||||
'Make Rails run as a Daemon (only works if fork is available -- meaning on *nix).'
|
'Make Rails run as a Daemon (only works if fork is available -- meaning on *nix).'
|
||||||
) { OPTIONS[:server_type] = WEBrick::Daemon }
|
) { OPTIONS[:server_type] = WEBrick::Daemon }
|
||||||
opts.on('-s', '--simple', '--simple-server',
|
opts.on('-s', '--simple', '--simple-server',
|
||||||
'[deprecated] Forces Instiki not to run as a Daemon if fork is available.',
|
'[deprecated] Forces Instiki not to run as a Daemon if fork is available.',
|
||||||
'Since version 0.10.0 this option is ignored.'
|
'Since version 0.10.0 this option is ignored.'
|
||||||
) { puts "Warning: -s (--simple) option is deprecated. See instiki --help for details." }
|
) { puts "Warning: -s (--simple) option is deprecated. See instiki --help for details." }
|
||||||
opts.on('-t', '--storage=storage', String,
|
opts.on('-t', '--storage=storage', String,
|
||||||
'Makes Instiki use the specified directory for storage.',
|
'Makes Instiki use the specified directory for storage.',
|
||||||
'Default: ./storage/[port]') { |OPTIONS[:storage]| }
|
'Default: ./storage/[port]') { |OPTIONS[:storage]| }
|
||||||
opts.on('-v', '--verbose',
|
opts.on('-v', '--verbose',
|
||||||
'Enable debug-level logging'
|
'Enable debug-level logging'
|
||||||
) { OPTIONS[:verbose] = true }
|
) { OPTIONS[:verbose] = true }
|
||||||
|
|
||||||
opts.separator ''
|
opts.separator ''
|
||||||
|
|
||||||
opts.on('-h', '--help',
|
opts.on('-h', '--help',
|
||||||
'Show this help message.') { puts opts; exit }
|
'Show this help message.') { puts opts; exit }
|
||||||
|
|
||||||
opts.parse!
|
opts.parse!
|
||||||
end
|
end
|
||||||
|
|
||||||
ENV['RAILS_ENV'] = OPTIONS[:environment]
|
ENV['RAILS_ENV'] = OPTIONS[:environment]
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
|
require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
|
||||||
|
|
||||||
if OPTIONS[:verbose]
|
if OPTIONS[:verbose]
|
||||||
ActionController::Base.logger.level = Logger::DEBUG
|
ActionController::Base.logger.level = Logger::DEBUG
|
||||||
end
|
end
|
||||||
|
|
||||||
OPTIONS[:index_controller] = 'wiki'
|
OPTIONS[:index_controller] = 'wiki'
|
||||||
require 'webrick_server'
|
require 'webrick_server'
|
||||||
|
|
||||||
if OPTIONS[:environment] == 'production'
|
if OPTIONS[:environment] == 'production'
|
||||||
storage_path = OPTIONS[:storage] + "/" + OPTIONS[:port].to_s
|
storage_path = OPTIONS[:storage] + "/" + OPTIONS[:port].to_s
|
||||||
else
|
else
|
||||||
storage_path = OPTIONS[:storage] + "/" + OPTIONS[:environment] + "/" + OPTIONS[:port].to_s
|
storage_path = OPTIONS[:storage] + "/" + OPTIONS[:environment] + "/" + OPTIONS[:port].to_s
|
||||||
end
|
end
|
||||||
FileUtils.mkdir_p(storage_path)
|
FileUtils.mkdir_p(storage_path)
|
||||||
|
|
||||||
puts "=> Starting Instiki on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
|
puts "=> Starting Instiki on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}"
|
||||||
puts "=> Data files are stored in #{storage_path}"
|
puts "=> Data files are stored in #{storage_path}"
|
||||||
|
|
||||||
require 'application'
|
require 'application'
|
||||||
WikiService.storage_path = storage_path
|
WikiService.storage_path = storage_path
|
||||||
ApplicationController.wiki = WikiService.instance
|
ApplicationController.wiki = WikiService.instance
|
||||||
DispatchServlet.dispatch(OPTIONS)
|
DispatchServlet.dispatch(OPTIONS)
|
||||||
|
|
18
test/all_tests.rb
Normal file → Executable file
18
test/all_tests.rb
Normal file → Executable file
|
@ -1,9 +1,9 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
require 'find'
|
require 'find'
|
||||||
|
|
||||||
test_root = File.dirname(__FILE__)
|
test_root = File.dirname(__FILE__)
|
||||||
Find.find(test_root) { |path|
|
Find.find(test_root) { |path|
|
||||||
if File.file?(path) and path =~ /.*_test\.rb$/
|
if File.file?(path) and path =~ /.*_test\.rb$/
|
||||||
require path[(test_root.size + 1)..-4]
|
require path[(test_root.size + 1)..-4]
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
0
test/fixtures/rails.gif
vendored
Normal file → Executable file
0
test/fixtures/rails.gif
vendored
Normal file → Executable file
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
52
test/functional/application_test.rb
Normal file → Executable file
52
test/functional/application_test.rb
Normal file → Executable file
|
@ -1,26 +1,26 @@
|
||||||
# Unit tests for ApplicationController (the abstract controller class)
|
# Unit tests for ApplicationController (the abstract controller class)
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'wiki_controller'
|
require 'wiki_controller'
|
||||||
require 'rexml/document'
|
require 'rexml/document'
|
||||||
|
|
||||||
# Need some concrete class to test the abstract class features
|
# Need some concrete class to test the abstract class features
|
||||||
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
|
class WikiController; def rescue_action(e) logger.error(e); raise e end; end
|
||||||
|
|
||||||
class ApplicationTest < Test::Unit::TestCase
|
class ApplicationTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
setup_test_wiki
|
setup_test_wiki
|
||||||
setup_controller_test(WikiController)
|
setup_controller_test(WikiController)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tear_down
|
def tear_down
|
||||||
tear_down_wiki
|
tear_down_wiki
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_utf8_header
|
def test_utf8_header
|
||||||
r = process('show', 'web' => 'wiki1', 'id' => 'HomePage')
|
r = process('show', 'web' => 'wiki1', 'id' => 'HomePage')
|
||||||
assert_equal 'text/html; charset=UTF-8', r.headers['Content-Type']
|
assert_equal 'text/html; charset=UTF-8', r.headers['Content-Type']
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
254
test/functional/file_controller_test.rb
Normal file → Executable file
254
test/functional/file_controller_test.rb
Normal file → Executable file
|
@ -1,127 +1,127 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'file_controller'
|
require 'file_controller'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
# Raise errors beyond the default web-based presentation
|
# Raise errors beyond the default web-based presentation
|
||||||
class FileController; def rescue_action(e) logger.error(e); raise e end; end
|
class FileController; def rescue_action(e) logger.error(e); raise e end; end
|
||||||
|
|
||||||
class FileControllerTest < Test::Unit::TestCase
|
class FileControllerTest < Test::Unit::TestCase
|
||||||
|
|
||||||
FILE_AREA = RAILS_ROOT + '/storage/test/wiki1'
|
FILE_AREA = RAILS_ROOT + '/storage/test/wiki1'
|
||||||
FileUtils.mkdir_p(FILE_AREA) unless File.directory?(FILE_AREA)
|
FileUtils.mkdir_p(FILE_AREA) unless File.directory?(FILE_AREA)
|
||||||
FileUtils.rm(Dir["#{FILE_AREA}/*"])
|
FileUtils.rm(Dir["#{FILE_AREA}/*"])
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
setup_test_wiki
|
setup_test_wiki
|
||||||
setup_controller_test
|
setup_controller_test
|
||||||
end
|
end
|
||||||
|
|
||||||
def tear_down
|
def tear_down
|
||||||
tear_down_wiki
|
tear_down_wiki
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file
|
def test_file
|
||||||
process 'file', 'web' => 'wiki1', 'id' => 'foo.tgz'
|
process 'file', 'web' => 'wiki1', 'id' => 'foo.tgz'
|
||||||
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_rendered_file 'file/file'
|
assert_rendered_file 'file/file'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_download_text_file
|
def test_file_download_text_file
|
||||||
File.open("#{FILE_AREA}/foo.txt", 'wb') { |f| f.write "aaa\nbbb\n" }
|
File.open("#{FILE_AREA}/foo.txt", 'wb') { |f| f.write "aaa\nbbb\n" }
|
||||||
|
|
||||||
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.txt'
|
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.txt'
|
||||||
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_equal "aaa\nbbb\n", r.binary_content
|
assert_equal "aaa\nbbb\n", r.binary_content
|
||||||
assert_equal 'text/plain', r.headers['Content-Type']
|
assert_equal 'text/plain', r.headers['Content-Type']
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_download_pdf_file
|
def test_file_download_pdf_file
|
||||||
File.open("#{FILE_AREA}/foo.pdf", 'wb') { |f| f.write "aaa\nbbb\n" }
|
File.open("#{FILE_AREA}/foo.pdf", 'wb') { |f| f.write "aaa\nbbb\n" }
|
||||||
|
|
||||||
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.pdf'
|
r = process 'file', 'web' => 'wiki1', 'id' => 'foo.pdf'
|
||||||
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_equal "aaa\nbbb\n", r.binary_content
|
assert_equal "aaa\nbbb\n", r.binary_content
|
||||||
assert_equal 'application/pdf', r.headers['Content-Type']
|
assert_equal 'application/pdf', r.headers['Content-Type']
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_pic_download_gif
|
def test_pic_download_gif
|
||||||
FileUtils.cp("#{RAILS_ROOT}/test/fixtures/rails.gif", FILE_AREA)
|
FileUtils.cp("#{RAILS_ROOT}/test/fixtures/rails.gif", FILE_AREA)
|
||||||
|
|
||||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails.gif'
|
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails.gif'
|
||||||
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_equal File.size("#{FILE_AREA}/rails.gif"), r.binary_content.size
|
assert_equal File.size("#{FILE_AREA}/rails.gif"), r.binary_content.size
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_pic_unknown_pic
|
def test_pic_unknown_pic
|
||||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'non-existant.gif'
|
r = process 'pic', 'web' => 'wiki1', 'id' => 'non-existant.gif'
|
||||||
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_rendered_file 'file/file'
|
assert_rendered_file 'file/file'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_pic_upload_end_to_end
|
def test_pic_upload_end_to_end
|
||||||
# edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif'
|
# edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif'
|
||||||
@wiki.revise_page('wiki1', 'HomePage', '[[rails-e2e.gif:pic]]', Time.now, 'AnonymousBrave')
|
@wiki.revise_page('wiki1', 'HomePage', '[[rails-e2e.gif:pic]]', Time.now, 'AnonymousBrave')
|
||||||
assert_equal "<p><span class=\"newWikiWord\">rails-e2e.gif<a href=\"../pic/rails-e2e.gif\">" +
|
assert_equal "<p><span class=\"newWikiWord\">rails-e2e.gif<a href=\"../pic/rails-e2e.gif\">" +
|
||||||
"?</a></span></p>",
|
"?</a></span></p>",
|
||||||
@home.display_content
|
@home.display_content
|
||||||
|
|
||||||
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
|
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
|
||||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif'
|
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif'
|
||||||
assert_success
|
assert_success
|
||||||
assert_rendered_file 'file/file'
|
assert_rendered_file 'file/file'
|
||||||
|
|
||||||
# User uploads the picture
|
# User uploads the picture
|
||||||
picture = File.read("#{RAILS_ROOT}/test/fixtures/rails.gif")
|
picture = File.read("#{RAILS_ROOT}/test/fixtures/rails.gif")
|
||||||
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif', 'file' => StringIO.new(picture)
|
r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif', 'file' => StringIO.new(picture)
|
||||||
assert_redirect_url '/'
|
assert_redirect_url '/'
|
||||||
assert @wiki.file_yard(@web).has_file?('rails-e2e.gif')
|
assert @wiki.file_yard(@web).has_file?('rails-e2e.gif')
|
||||||
assert_equal(picture, File.read("#{RAILS_ROOT}/storage/test/wiki1/rails-e2e.gif"))
|
assert_equal(picture, File.read("#{RAILS_ROOT}/storage/test/wiki1/rails-e2e.gif"))
|
||||||
|
|
||||||
# this should refresh the page display content (cached)
|
# this should refresh the page display content (cached)
|
||||||
assert_equal "<p><img alt=\"rails-e2e.gif\" src=\"../pic/rails-e2e.gif\" /></p>",
|
assert_equal "<p><img alt=\"rails-e2e.gif\" src=\"../pic/rails-e2e.gif\" /></p>",
|
||||||
@home.display_content
|
@home.display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_pic_upload_end_to_end
|
def test_pic_upload_end_to_end
|
||||||
# edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif'
|
# edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif'
|
||||||
@wiki.revise_page('wiki1', 'HomePage', '[[instiki-e2e.txt:file]]', Time.now, 'AnonymousBrave')
|
@wiki.revise_page('wiki1', 'HomePage', '[[instiki-e2e.txt:file]]', Time.now, 'AnonymousBrave')
|
||||||
assert_equal "<p><span class=\"newWikiWord\">instiki-e2e.txt" +
|
assert_equal "<p><span class=\"newWikiWord\">instiki-e2e.txt" +
|
||||||
"<a href=\"../file/instiki-e2e.txt\">?</a></span></p>",
|
"<a href=\"../file/instiki-e2e.txt\">?</a></span></p>",
|
||||||
@home.display_content
|
@home.display_content
|
||||||
|
|
||||||
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
|
# rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form
|
||||||
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt'
|
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt'
|
||||||
assert_success
|
assert_success
|
||||||
assert_rendered_file 'file/file'
|
assert_rendered_file 'file/file'
|
||||||
|
|
||||||
# User uploads the picture
|
# User uploads the picture
|
||||||
file = "abcdefgh\n123"
|
file = "abcdefgh\n123"
|
||||||
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt', 'file' => StringIO.new(file)
|
r = process 'file', 'web' => 'wiki1', 'id' => 'instiki-e2e.txt', 'file' => StringIO.new(file)
|
||||||
assert_redirect_url '/'
|
assert_redirect_url '/'
|
||||||
assert @wiki.file_yard(@web).has_file?('instiki-e2e.txt')
|
assert @wiki.file_yard(@web).has_file?('instiki-e2e.txt')
|
||||||
assert_equal(file, File.read("#{RAILS_ROOT}/storage/test/wiki1/instiki-e2e.txt"))
|
assert_equal(file, File.read("#{RAILS_ROOT}/storage/test/wiki1/instiki-e2e.txt"))
|
||||||
|
|
||||||
# this should refresh the page display content (cached)
|
# this should refresh the page display content (cached)
|
||||||
assert_equal "<p><a class=\"existingWikiWord\" href=\"../file/instiki-e2e.txt\">" +
|
assert_equal "<p><a class=\"existingWikiWord\" href=\"../file/instiki-e2e.txt\">" +
|
||||||
"instiki-e2e.txt</a></p>",
|
"instiki-e2e.txt</a></p>",
|
||||||
@home.display_content
|
@home.display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_uploads_blocking
|
def test_uploads_blocking
|
||||||
@web.allow_uploads = true
|
@web.allow_uploads = true
|
||||||
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
|
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
@web.allow_uploads = false
|
@web.allow_uploads = false
|
||||||
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
|
r = process 'file', 'web' => 'wiki1', 'id' => 'filename'
|
||||||
assert_equal '403 Forbidden', r.headers['Status']
|
assert_equal '403 Forbidden', r.headers['Status']
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
File diff suppressed because it is too large
Load diff
226
test/test_helper.rb
Executable file → Normal file
226
test/test_helper.rb
Executable file → Normal file
|
@ -1,113 +1,113 @@
|
||||||
ENV['RAILS_ENV'] ||= 'test'
|
ENV['RAILS_ENV'] ||= 'test'
|
||||||
require File.dirname(__FILE__) + '/../config/environment'
|
require File.dirname(__FILE__) + '/../config/environment'
|
||||||
require 'application'
|
require 'application'
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'action_controller/test_process'
|
require 'action_controller/test_process'
|
||||||
|
|
||||||
# Uncomment this variable to have assert_success check that response bodies are valid XML
|
# Uncomment this variable to have assert_success check that response bodies are valid XML
|
||||||
$validate_xml_in_assert_success = true
|
$validate_xml_in_assert_success = true
|
||||||
|
|
||||||
# Convenient setup method for Test::Unit::TestCase
|
# Convenient setup method for Test::Unit::TestCase
|
||||||
class Test::Unit::TestCase
|
class Test::Unit::TestCase
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def setup_controller_test(controller_class = nil, host = nil)
|
def setup_controller_test(controller_class = nil, host = nil)
|
||||||
if controller_class
|
if controller_class
|
||||||
@controller = controller_class
|
@controller = controller_class
|
||||||
elsif self.class.to_s =~ /^(\w+Controller)Test$/
|
elsif self.class.to_s =~ /^(\w+Controller)Test$/
|
||||||
@controller = Object::const_get($1)
|
@controller = Object::const_get($1)
|
||||||
else
|
else
|
||||||
raise "Cannot derive the name of controller under test from class name #{self.class}"
|
raise "Cannot derive the name of controller under test from class name #{self.class}"
|
||||||
end
|
end
|
||||||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
|
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
|
||||||
@request.host = host || 'localhost'
|
@request.host = host || 'localhost'
|
||||||
return @request, @response
|
return @request, @response
|
||||||
end
|
end
|
||||||
|
|
||||||
# Wiki fixture for tests
|
# Wiki fixture for tests
|
||||||
|
|
||||||
def setup_test_wiki
|
def setup_test_wiki
|
||||||
@wiki = ApplicationController.wiki = WikiServiceWithNoPersistence.new
|
@wiki = ApplicationController.wiki = WikiServiceWithNoPersistence.new
|
||||||
@web = @wiki.create_web('Test Wiki 1', 'wiki1')
|
@web = @wiki.create_web('Test Wiki 1', 'wiki1')
|
||||||
@home = @wiki.write_page('wiki1', 'HomePage', 'First revision of the HomePage end', Time.now,
|
@home = @wiki.write_page('wiki1', 'HomePage', 'First revision of the HomePage end', Time.now,
|
||||||
Author.new('AnAuthor', '127.0.0.1'))
|
Author.new('AnAuthor', '127.0.0.1'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_wiki_with_three_pages
|
def setup_wiki_with_three_pages
|
||||||
@oak = @wiki.write_page('wiki1', 'Oak',
|
@oak = @wiki.write_page('wiki1', 'Oak',
|
||||||
"All about oak.\n" +
|
"All about oak.\n" +
|
||||||
"category: trees",
|
"category: trees",
|
||||||
5.minutes.ago, Author.new('TreeHugger', '127.0.0.2'))
|
5.minutes.ago, Author.new('TreeHugger', '127.0.0.2'))
|
||||||
@elephant = @wiki.write_page('wiki1', 'Elephant',
|
@elephant = @wiki.write_page('wiki1', 'Elephant',
|
||||||
"All about elephants.\n" +
|
"All about elephants.\n" +
|
||||||
"category: animals",
|
"category: animals",
|
||||||
10.minutes.ago, Author.new('Guest', '127.0.0.2'))
|
10.minutes.ago, Author.new('Guest', '127.0.0.2'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def tear_down_wiki
|
def tear_down_wiki
|
||||||
ApplicationController.wiki = nil
|
ApplicationController.wiki = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class WikiServiceWithNoPersistence
|
class WikiServiceWithNoPersistence
|
||||||
include AbstractWikiService
|
include AbstractWikiService
|
||||||
def initialize
|
def initialize
|
||||||
init_wiki_service
|
init_wiki_service
|
||||||
end
|
end
|
||||||
|
|
||||||
def storage_path
|
def storage_path
|
||||||
RAILS_ROOT + '/storage/test/'
|
RAILS_ROOT + '/storage/test/'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# This module is to be included in unit tests that involve matching chunks.
|
# This module is to be included in unit tests that involve matching chunks.
|
||||||
# It provides a easy way to test whether a chunk matches a particular string
|
# It provides a easy way to test whether a chunk matches a particular string
|
||||||
# and any the values of any fields that should be set after a match.
|
# and any the values of any fields that should be set after a match.
|
||||||
class ContentStub < String
|
class ContentStub < String
|
||||||
attr_reader :chunks, :content
|
attr_reader :chunks, :content
|
||||||
def initialize(str)
|
def initialize(str)
|
||||||
super
|
super
|
||||||
@chunks = []
|
@chunks = []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module ChunkMatch
|
module ChunkMatch
|
||||||
|
|
||||||
# Asserts a number of tests for the given type and text.
|
# Asserts a number of tests for the given type and text.
|
||||||
def match(chunk_type, test_text, expected_chunk_state)
|
def match(chunk_type, test_text, expected_chunk_state)
|
||||||
if chunk_type.respond_to? :pattern
|
if chunk_type.respond_to? :pattern
|
||||||
assert_match(chunk_type.pattern, test_text)
|
assert_match(chunk_type.pattern, test_text)
|
||||||
end
|
end
|
||||||
|
|
||||||
content = ContentStub.new(test_text)
|
content = ContentStub.new(test_text)
|
||||||
chunk_type.apply_to(content)
|
chunk_type.apply_to(content)
|
||||||
|
|
||||||
# Test if requested parts are correct.
|
# Test if requested parts are correct.
|
||||||
expected_chunk_state.each_pair do |a_method, expected_value|
|
expected_chunk_state.each_pair do |a_method, expected_value|
|
||||||
assert content.chunks.last.kind_of?(chunk_type)
|
assert content.chunks.last.kind_of?(chunk_type)
|
||||||
assert_respond_to(content.chunks.last, a_method)
|
assert_respond_to(content.chunks.last, a_method)
|
||||||
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
|
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
|
||||||
"Wrong #{a_method} value")
|
"Wrong #{a_method} value")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
|
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
|
||||||
module Test
|
module Test
|
||||||
module Unit
|
module Unit
|
||||||
module Assertions
|
module Assertions
|
||||||
unless method_defined? :__assert_success_before_ovverride_by_instiki
|
unless method_defined? :__assert_success_before_ovverride_by_instiki
|
||||||
alias :__assert_success_before_ovverride_by_instiki :assert_success
|
alias :__assert_success_before_ovverride_by_instiki :assert_success
|
||||||
end
|
end
|
||||||
def assert_success
|
def assert_success
|
||||||
__assert_success_before_ovverride_by_instiki
|
__assert_success_before_ovverride_by_instiki
|
||||||
if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
|
if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
|
||||||
else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
|
else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
#!/bin/env ruby
|
#!/bin/env ruby
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../../test_helper'
|
require File.dirname(__FILE__) + '/../../test_helper'
|
||||||
require 'chunks/category'
|
require 'chunks/category'
|
||||||
require 'chunks/match'
|
require 'chunks/match'
|
||||||
|
|
||||||
class CategoryTest < Test::Unit::TestCase
|
class CategoryTest < Test::Unit::TestCase
|
||||||
include ChunkMatch
|
include ChunkMatch
|
||||||
|
|
||||||
def test_single_category
|
def test_single_category
|
||||||
match(Category, 'category: test', :list => ['test'], :hidden => nil)
|
match(Category, 'category: test', :list => ['test'], :hidden => nil)
|
||||||
match(Category, 'category : chunk test ', :list => ['chunk test'], :hidden => nil)
|
match(Category, 'category : chunk test ', :list => ['chunk test'], :hidden => nil)
|
||||||
match(Category, ':category: test', :list => ['test'], :hidden => ':')
|
match(Category, ':category: test', :list => ['test'], :hidden => ':')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_multiple_categories
|
def test_multiple_categories
|
||||||
match(Category, 'category: test, multiple', :list => ['test', 'multiple'], :hidden => nil)
|
match(Category, 'category: test, multiple', :list => ['test', 'multiple'], :hidden => nil)
|
||||||
match(Category, 'category : chunk test , multi category,regression test case ',
|
match(Category, 'category : chunk test , multi category,regression test case ',
|
||||||
:list => ['chunk test','multi category','regression test case'], :hidden => nil
|
:list => ['chunk test','multi category','regression test case'], :hidden => nil
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#!/bin/env ruby
|
#!/bin/env ruby
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../../test_helper'
|
require File.dirname(__FILE__) + '/../../test_helper'
|
||||||
require 'chunks/nowiki'
|
require 'chunks/nowiki'
|
||||||
require 'chunks/match'
|
require 'chunks/match'
|
||||||
|
|
||||||
class NoWikiTest < Test::Unit::TestCase
|
class NoWikiTest < Test::Unit::TestCase
|
||||||
include ChunkMatch
|
include ChunkMatch
|
||||||
|
|
||||||
def test_simple_nowiki
|
def test_simple_nowiki
|
||||||
match(NoWiki, 'This sentence contains <nowiki>[[raw text]]</nowiki>. Do not touch!',
|
match(NoWiki, 'This sentence contains <nowiki>[[raw text]]</nowiki>. Do not touch!',
|
||||||
:plain_text => '[[raw text]]'
|
:plain_text => '[[raw text]]'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,81 +1,81 @@
|
||||||
#!/bin/env ruby
|
#!/bin/env ruby
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../../test_helper'
|
require File.dirname(__FILE__) + '/../../test_helper'
|
||||||
require 'chunks/wiki'
|
require 'chunks/wiki'
|
||||||
|
|
||||||
class WikiTest < Test::Unit::TestCase
|
class WikiTest < Test::Unit::TestCase
|
||||||
|
|
||||||
class ContentStub < String
|
class ContentStub < String
|
||||||
def chunks
|
def chunks
|
||||||
@chunks ||= []
|
@chunks ||= []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
include ChunkMatch
|
include ChunkMatch
|
||||||
|
|
||||||
def test_simple
|
def test_simple
|
||||||
match(WikiChunk::Word, 'This is a WikiWord okay?', :page_name => 'WikiWord')
|
match(WikiChunk::Word, 'This is a WikiWord okay?', :page_name => 'WikiWord')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_escaped
|
def test_escaped
|
||||||
match(WikiChunk::Word, 'Do not link to an \EscapedWord',
|
match(WikiChunk::Word, 'Do not link to an \EscapedWord',
|
||||||
:page_name => 'EscapedWord', :escaped_text => 'EscapedWord'
|
:page_name => 'EscapedWord', :escaped_text => 'EscapedWord'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_simple_brackets
|
def test_simple_brackets
|
||||||
match(WikiChunk::Link, 'This is a [[bracketted link]]',
|
match(WikiChunk::Link, 'This is a [[bracketted link]]',
|
||||||
:page_name => 'bracketted link', :escaped_text => nil
|
:page_name => 'bracketted link', :escaped_text => nil
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_complex_brackets
|
def test_complex_brackets
|
||||||
match(WikiChunk::Link, 'This is a tricky link [[Sperberg-McQueen]]',
|
match(WikiChunk::Link, 'This is a tricky link [[Sperberg-McQueen]]',
|
||||||
:page_name => 'Sperberg-McQueen', :escaped_text => nil
|
:page_name => 'Sperberg-McQueen', :escaped_text => nil
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_textile_link
|
def test_textile_link
|
||||||
textile_link = ContentStub.new('"Here is a special link":SpecialLink')
|
textile_link = ContentStub.new('"Here is a special link":SpecialLink')
|
||||||
WikiChunk::Word.apply_to(textile_link)
|
WikiChunk::Word.apply_to(textile_link)
|
||||||
assert_equal '"Here is a special link":SpecialLink', textile_link
|
assert_equal '"Here is a special link":SpecialLink', textile_link
|
||||||
assert textile_link.chunks.empty?
|
assert textile_link.chunks.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_types
|
def test_file_types
|
||||||
# only link
|
# only link
|
||||||
assert_link_parsed_as 'only text', 'only text', 'show', '[[only text]]'
|
assert_link_parsed_as 'only text', 'only text', 'show', '[[only text]]'
|
||||||
# link and text
|
# link and text
|
||||||
assert_link_parsed_as 'page name', 'link text', 'show', '[[page name|link text]]'
|
assert_link_parsed_as 'page name', 'link text', 'show', '[[page name|link text]]'
|
||||||
# link and type (file)
|
# link and type (file)
|
||||||
assert_link_parsed_as 'foo.tar.gz', 'foo.tar.gz', 'file', '[[foo.tar.gz:file]]'
|
assert_link_parsed_as 'foo.tar.gz', 'foo.tar.gz', 'file', '[[foo.tar.gz:file]]'
|
||||||
# link and type (pic)
|
# link and type (pic)
|
||||||
assert_link_parsed_as 'foo.tar.gz', 'foo.tar.gz', 'pic', '[[foo.tar.gz:pic]]'
|
assert_link_parsed_as 'foo.tar.gz', 'foo.tar.gz', 'pic', '[[foo.tar.gz:pic]]'
|
||||||
# link, text and type
|
# link, text and type
|
||||||
assert_link_parsed_as 'foo.tar.gz', 'FooTar', 'file', '[[foo.tar.gz|FooTar:file]]'
|
assert_link_parsed_as 'foo.tar.gz', 'FooTar', 'file', '[[foo.tar.gz|FooTar:file]]'
|
||||||
|
|
||||||
# NEGATIVE TEST CASES
|
# NEGATIVE TEST CASES
|
||||||
|
|
||||||
# empty page name
|
# empty page name
|
||||||
assert_link_parsed_as '|link text?', '|link text?', 'file', '[[|link text?:file]]'
|
assert_link_parsed_as '|link text?', '|link text?', 'file', '[[|link text?:file]]'
|
||||||
# empty link text
|
# empty link text
|
||||||
assert_link_parsed_as 'page name?|', 'page name?|', 'file', '[[page name?|:file]]'
|
assert_link_parsed_as 'page name?|', 'page name?|', 'file', '[[page name?|:file]]'
|
||||||
# empty link type
|
# empty link type
|
||||||
assert_link_parsed_as 'page name', 'link?:', 'show', '[[page name|link?:]]'
|
assert_link_parsed_as 'page name', 'link?:', 'show', '[[page name|link?:]]'
|
||||||
# unknown link type
|
# unknown link type
|
||||||
assert_link_parsed_as 'page name:create_system', 'page name:create_system', 'show',
|
assert_link_parsed_as 'page name:create_system', 'page name:create_system', 'show',
|
||||||
'[[page name:create_system]]'
|
'[[page name:create_system]]'
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_link_parsed_as(expected_page_name, expected_link_text, expected_link_type, link)
|
def assert_link_parsed_as(expected_page_name, expected_link_text, expected_link_type, link)
|
||||||
link_to_file = ContentStub.new(link)
|
link_to_file = ContentStub.new(link)
|
||||||
WikiChunk::Link.apply_to(link_to_file)
|
WikiChunk::Link.apply_to(link_to_file)
|
||||||
chunk = link_to_file.chunks.last
|
chunk = link_to_file.chunks.last
|
||||||
assert chunk
|
assert chunk
|
||||||
assert_equal expected_page_name, chunk.page_name
|
assert_equal expected_page_name, chunk.page_name
|
||||||
assert_equal expected_link_text, chunk.link_text
|
assert_equal expected_link_text, chunk.link_text
|
||||||
assert_equal expected_link_type, chunk.link_type
|
assert_equal expected_link_type, chunk.link_type
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,82 +1,82 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'diff'
|
require 'diff'
|
||||||
|
|
||||||
include Diff
|
include Diff
|
||||||
|
|
||||||
class DiffTest < Test::Unit::TestCase
|
class DiffTest < Test::Unit::TestCase
|
||||||
def test_init
|
def test_init
|
||||||
assert(1 == 1, "tests working")
|
assert(1 == 1, "tests working")
|
||||||
assert_nothing_raised("object created") do
|
assert_nothing_raised("object created") do
|
||||||
s = SequenceMatcher.new "private Thread currentThread;",
|
s = SequenceMatcher.new "private Thread currentThread;",
|
||||||
"private volatile Thread currentThread;",
|
"private volatile Thread currentThread;",
|
||||||
proc { |x| x == ' ' }
|
proc { |x| x == ' ' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_matching_blocks
|
def test_matching_blocks
|
||||||
s = SequenceMatcher.new "abxcd", "abcd"
|
s = SequenceMatcher.new "abxcd", "abcd"
|
||||||
assert(s.get_matching_blocks == [[0, 0, 2], [3, 2, 2], [5, 4, 0]],
|
assert(s.get_matching_blocks == [[0, 0, 2], [3, 2, 2], [5, 4, 0]],
|
||||||
"get_matching_blocks works")
|
"get_matching_blocks works")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_ratio
|
def test_ratio
|
||||||
s = SequenceMatcher.new "abcd", "bcde"
|
s = SequenceMatcher.new "abcd", "bcde"
|
||||||
assert(s.ratio == 0.75, "ratio works")
|
assert(s.ratio == 0.75, "ratio works")
|
||||||
assert(s.quick_ratio == 0.75, "quick_ratio works")
|
assert(s.quick_ratio == 0.75, "quick_ratio works")
|
||||||
assert(s.real_quick_ratio == 1.0, "real_quick_ratio works")
|
assert(s.real_quick_ratio == 1.0, "real_quick_ratio works")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_longest_match
|
def test_longest_match
|
||||||
s = SequenceMatcher.new(" abcd", "abcd abcd")
|
s = SequenceMatcher.new(" abcd", "abcd abcd")
|
||||||
assert(s.find_longest_match(0, 5, 0, 9) == [0, 4, 5],
|
assert(s.find_longest_match(0, 5, 0, 9) == [0, 4, 5],
|
||||||
"find_longest_match works")
|
"find_longest_match works")
|
||||||
s = SequenceMatcher.new()
|
s = SequenceMatcher.new()
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_opcodes
|
def test_opcodes
|
||||||
s = SequenceMatcher.new("qabxcd", "abycdf")
|
s = SequenceMatcher.new("qabxcd", "abycdf")
|
||||||
assert(s.get_opcodes == [
|
assert(s.get_opcodes == [
|
||||||
[:delete, 0, 1, 0, 0],
|
[:delete, 0, 1, 0, 0],
|
||||||
[:equal, 1, 3, 0, 2],
|
[:equal, 1, 3, 0, 2],
|
||||||
[:replace, 3, 4, 2, 3],
|
[:replace, 3, 4, 2, 3],
|
||||||
[:equal, 4, 6, 3, 5],
|
[:equal, 4, 6, 3, 5],
|
||||||
[:insert, 6, 6, 5, 6]], "get_opcodes works")
|
[:insert, 6, 6, 5, 6]], "get_opcodes works")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_count_leading
|
def test_count_leading
|
||||||
assert(Diff.count_leading(' abc', ' ') == 3,
|
assert(Diff.count_leading(' abc', ' ') == 3,
|
||||||
"count_leading works")
|
"count_leading works")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_html2list
|
def test_html2list
|
||||||
a = "here is the original text"
|
a = "here is the original text"
|
||||||
#p HTMLDiff.html2list(a)
|
#p HTMLDiff.html2list(a)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_html_diff
|
def test_html_diff
|
||||||
a = "this was the original string"
|
a = "this was the original string"
|
||||||
b = "this is the super string"
|
b = "this is the super string"
|
||||||
assert_equal 'this <del class="diffmod">was </del>' +
|
assert_equal 'this <del class="diffmod">was </del>' +
|
||||||
'<ins class="diffmod">is </ins>the ' +
|
'<ins class="diffmod">is </ins>the ' +
|
||||||
'<del class="diffmod">original </del>' +
|
'<del class="diffmod">original </del>' +
|
||||||
'<ins class="diffmod">super </ins>string',
|
'<ins class="diffmod">super </ins>string',
|
||||||
HTMLDiff.diff(a, b)
|
HTMLDiff.diff(a, b)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_html_diff_with_multiple_paragraphs
|
def test_html_diff_with_multiple_paragraphs
|
||||||
a = "<p>this was the original string</p>"
|
a = "<p>this was the original string</p>"
|
||||||
b = "<p>this is</p>\r\n<p>the super string</p>\r\n<p>around the world</p>"
|
b = "<p>this is</p>\r\n<p>the super string</p>\r\n<p>around the world</p>"
|
||||||
|
|
||||||
assert_equal(
|
assert_equal(
|
||||||
"<p>this <del class=\"diffmod\">was </del>" +
|
"<p>this <del class=\"diffmod\">was </del>" +
|
||||||
"<ins class=\"diffmod\">is</ins></p>\r\n<p>the " +
|
"<ins class=\"diffmod\">is</ins></p>\r\n<p>the " +
|
||||||
"<del class=\"diffmod\">original </del>" +
|
"<del class=\"diffmod\">original </del>" +
|
||||||
"<ins class=\"diffmod\">super </ins>string</p>\r\n" +
|
"<ins class=\"diffmod\">super </ins>string</p>\r\n" +
|
||||||
"<p><ins class=\"diffins\">around the world</ins></p>",
|
"<p><ins class=\"diffins\">around the world</ins></p>",
|
||||||
HTMLDiff.diff(a, b)
|
HTMLDiff.diff(a, b)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
68
test/unit/file_yard_test.rb
Normal file → Executable file
68
test/unit/file_yard_test.rb
Normal file → Executable file
|
@ -1,35 +1,35 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'file_yard'
|
require 'file_yard'
|
||||||
require 'stringio'
|
require 'stringio'
|
||||||
|
|
||||||
class FileYardTest < Test::Unit::TestCase
|
class FileYardTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
FileUtils.mkdir_p(file_path)
|
FileUtils.mkdir_p(file_path)
|
||||||
FileUtils.rm(Dir["#{file_path}/*"])
|
FileUtils.rm(Dir["#{file_path}/*"])
|
||||||
@yard = FileYard.new(file_path)
|
@yard = FileYard.new(file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_files
|
def test_files
|
||||||
assert_equal [], @yard.files
|
assert_equal [], @yard.files
|
||||||
|
|
||||||
# FileYard gets the list of files from directory in the constructor
|
# FileYard gets the list of files from directory in the constructor
|
||||||
@yard.upload_file('aaa', StringIO.new('file contents'))
|
@yard.upload_file('aaa', StringIO.new('file contents'))
|
||||||
assert_equal ["#{file_path}/aaa"], Dir["#{file_path}/*"]
|
assert_equal ["#{file_path}/aaa"], Dir["#{file_path}/*"]
|
||||||
assert_equal ['aaa'], @yard.files
|
assert_equal ['aaa'], @yard.files
|
||||||
assert @yard.has_file?('aaa')
|
assert @yard.has_file?('aaa')
|
||||||
assert_equal 'file contents', File.read(@yard.file_path('aaa'))
|
assert_equal 'file contents', File.read(@yard.file_path('aaa'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_path
|
def test_file_path
|
||||||
assert_equal "#{file_path}/abcd", @yard.file_path('abcd')
|
assert_equal "#{file_path}/abcd", @yard.file_path('abcd')
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_path
|
def file_path
|
||||||
"#{RAILS_ROOT}/storage/test/instiki"
|
"#{RAILS_ROOT}/storage/test/instiki"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -1,91 +1,91 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'web'
|
require 'web'
|
||||||
require 'page'
|
require 'page'
|
||||||
|
|
||||||
class PageTest < Test::Unit::TestCase
|
class PageTest < Test::Unit::TestCase
|
||||||
|
|
||||||
class MockWeb < Web
|
class MockWeb < Web
|
||||||
def initialize() super(nil, 'test','test') end
|
def initialize() super(nil, 'test','test') end
|
||||||
def [](wiki_word) %w( MyWay ThatWay SmartEngine ).include?(wiki_word) end
|
def [](wiki_word) %w( MyWay ThatWay SmartEngine ).include?(wiki_word) end
|
||||||
def refresh_pages_with_references(name) end
|
def refresh_pages_with_references(name) end
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@page = Page.new(
|
@page = Page.new(
|
||||||
MockWeb.new,
|
MockWeb.new,
|
||||||
"FirstPage",
|
"FirstPage",
|
||||||
"HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI",
|
"HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI",
|
||||||
Time.local(2004, 4, 4, 16, 50),
|
Time.local(2004, 4, 4, 16, 50),
|
||||||
"DavidHeinemeierHansson")
|
"DavidHeinemeierHansson")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_lock
|
def test_lock
|
||||||
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
|
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
|
||||||
|
|
||||||
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
|
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
|
||||||
|
|
||||||
assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
|
assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
|
||||||
assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
|
assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
|
||||||
|
|
||||||
@page.unlock
|
@page.unlock
|
||||||
|
|
||||||
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
|
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_lock_duration
|
def test_lock_duration
|
||||||
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
|
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
|
||||||
|
|
||||||
assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
|
assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_plain_name
|
def test_plain_name
|
||||||
assert_equal "First Page", @page.plain_name
|
assert_equal "First Page", @page.plain_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_revise
|
def test_revise
|
||||||
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
|
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
|
||||||
assert_equal 2, @page.revisions.length, 'Should have two revisions'
|
assert_equal 2, @page.revisions.length, 'Should have two revisions'
|
||||||
assert_equal 'MarianneSyhler', @page.author, 'Mary should be the author now'
|
assert_equal 'MarianneSyhler', @page.author, 'Mary should be the author now'
|
||||||
assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author, 'David was the first author'
|
assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author, 'David was the first author'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_revise_continous_revision
|
def test_revise_continous_revision
|
||||||
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
|
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
|
||||||
assert_equal 2, @page.revisions.length
|
assert_equal 2, @page.revisions.length
|
||||||
|
|
||||||
@page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
|
@page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
|
||||||
assert_equal 2, @page.revisions.length
|
assert_equal 2, @page.revisions.length
|
||||||
assert_equal 'HisWay would be MyWay in kinda update', @page.revisions.last.content
|
assert_equal 'HisWay would be MyWay in kinda update', @page.revisions.last.content
|
||||||
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revisions.last.created_at
|
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revisions.last.created_at
|
||||||
|
|
||||||
@page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
|
@page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
|
||||||
assert_equal 3, @page.revisions.length
|
assert_equal 3, @page.revisions.length
|
||||||
assert_equal 'HisWay would be MyWay in the house', @page.revisions.last.content
|
assert_equal 'HisWay would be MyWay in the house', @page.revisions.last.content
|
||||||
|
|
||||||
@page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
|
@page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
|
||||||
assert_equal 4, @page.revisions.length
|
assert_equal 4, @page.revisions.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_revise_content_unchanged
|
def test_revise_content_unchanged
|
||||||
last_revision_before = @page.revisions.last
|
last_revision_before = @page.revisions.last
|
||||||
revisions_number_before = @page.revisions.size
|
revisions_number_before = @page.revisions.size
|
||||||
|
|
||||||
assert_raises(Instiki::ValidationError) {
|
assert_raises(Instiki::ValidationError) {
|
||||||
@page.revise(@page.revisions.last.content.dup, Time.now, 'AlexeyVerkhovsky')
|
@page.revise(@page.revisions.last.content.dup, Time.now, 'AlexeyVerkhovsky')
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_same last_revision_before, @page.revisions.last
|
assert_same last_revision_before, @page.revisions.last
|
||||||
assert_equal revisions_number_before, @page.revisions.size
|
assert_equal revisions_number_before, @page.revisions.size
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_rollback
|
def test_rollback
|
||||||
@page.revise("spot two", Time.now, "David")
|
@page.revise("spot two", Time.now, "David")
|
||||||
@page.revise("spot three", Time.now + 2000, "David")
|
@page.revise("spot three", Time.now + 2000, "David")
|
||||||
assert_equal 3, @page.revisions.length, "Should have three revisions"
|
assert_equal 3, @page.revisions.length, "Should have three revisions"
|
||||||
@page.rollback(1, Time.now)
|
@page.rollback(1, Time.now)
|
||||||
assert_equal "spot two", @page.content
|
assert_equal "spot two", @page.content
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,69 +1,69 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'redcloth_for_tex'
|
require 'redcloth_for_tex'
|
||||||
|
|
||||||
class RedClothForTexTest < Test::Unit::TestCase
|
class RedClothForTexTest < Test::Unit::TestCase
|
||||||
def test_basics
|
def test_basics
|
||||||
assert_equal '{\bf First Page}', RedClothForTex.new("*First Page*").to_tex
|
assert_equal '{\bf First Page}', RedClothForTex.new("*First Page*").to_tex
|
||||||
assert_equal '{\em First Page}', RedClothForTex.new("_First Page_").to_tex
|
assert_equal '{\em First Page}', RedClothForTex.new("_First Page_").to_tex
|
||||||
assert_equal "\\begin{itemize}\n\t\\item A\n\t\t\\item B\n\t\t\\item C\n\t\\end{itemize}", RedClothForTex.new("* A\n* B\n* C").to_tex
|
assert_equal "\\begin{itemize}\n\t\\item A\n\t\t\\item B\n\t\t\\item C\n\t\\end{itemize}", RedClothForTex.new("* A\n* B\n* C").to_tex
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_blocks
|
def test_blocks
|
||||||
assert_equal '\section*{hello}', RedClothForTex.new("h1. hello").to_tex
|
assert_equal '\section*{hello}', RedClothForTex.new("h1. hello").to_tex
|
||||||
assert_equal '\subsection*{hello}', RedClothForTex.new("h2. hello").to_tex
|
assert_equal '\subsection*{hello}', RedClothForTex.new("h2. hello").to_tex
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_table_of_contents
|
def test_table_of_contents
|
||||||
|
|
||||||
source = <<EOL
|
source = <<EOL
|
||||||
* [[A]]
|
* [[A]]
|
||||||
** [[B]]
|
** [[B]]
|
||||||
** [[C]]
|
** [[C]]
|
||||||
* D
|
* D
|
||||||
** [[E]]
|
** [[E]]
|
||||||
*** F
|
*** F
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
expected_result = <<EOL
|
expected_result = <<EOL
|
||||||
\\pagebreak
|
\\pagebreak
|
||||||
|
|
||||||
\\section{A}
|
\\section{A}
|
||||||
Abe
|
Abe
|
||||||
|
|
||||||
\\subsection{B}
|
\\subsection{B}
|
||||||
Babe
|
Babe
|
||||||
|
|
||||||
\\subsection{C}
|
\\subsection{C}
|
||||||
\\pagebreak
|
\\pagebreak
|
||||||
|
|
||||||
\\section{D}
|
\\section{D}
|
||||||
|
|
||||||
\\subsection{E}
|
\\subsection{E}
|
||||||
|
|
||||||
\\subsubsection{F}
|
\\subsubsection{F}
|
||||||
EOL
|
EOL
|
||||||
expected_result.chop!
|
expected_result.chop!
|
||||||
assert_equal(expected_result, table_of_contents(source, 'A' => 'Abe', 'B' => 'Babe'))
|
assert_equal(expected_result, table_of_contents(source, 'A' => 'Abe', 'B' => 'Babe'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_entities
|
def test_entities
|
||||||
assert_equal "Beck \\& Fowler are 100\\% cool", RedClothForTex.new("Beck & Fowler are 100% cool").to_tex
|
assert_equal "Beck \\& Fowler are 100\\% cool", RedClothForTex.new("Beck & Fowler are 100% cool").to_tex
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_bracket_links
|
def test_bracket_links
|
||||||
assert_equal "such a Horrible Day, but I won't be Made Useless", RedClothForTex.new("such a [[Horrible Day]], but I won't be [[Made Useless]]").to_tex
|
assert_equal "such a Horrible Day, but I won't be Made Useless", RedClothForTex.new("such a [[Horrible Day]], but I won't be [[Made Useless]]").to_tex
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_footnotes_on_abbreviations
|
def test_footnotes_on_abbreviations
|
||||||
assert_equal(
|
assert_equal(
|
||||||
"such a Horrible Day\\footnote{1}, but I won't be Made Useless",
|
"such a Horrible Day\\footnote{1}, but I won't be Made Useless",
|
||||||
RedClothForTex.new("such a [[Horrible Day]][1], but I won't be [[Made Useless]]").to_tex
|
RedClothForTex.new("such a [[Horrible Day]][1], but I won't be [[Made Useless]]").to_tex
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_subsection_depth
|
def test_subsection_depth
|
||||||
assert_equal "\\subsubsection*{Hello}", RedClothForTex.new("h4. Hello").to_tex
|
assert_equal "\\subsubsection*{Hello}", RedClothForTex.new("h4. Hello").to_tex
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,255 +1,255 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'web'
|
require 'web'
|
||||||
require 'revision'
|
require 'revision'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
class RevisionTest < Test::Unit::TestCase
|
class RevisionTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
setup_test_wiki
|
setup_test_wiki
|
||||||
@web.markup = :textile
|
@web.markup = :textile
|
||||||
|
|
||||||
@page = @wiki.read_page('wiki1', 'HomePage')
|
@page = @wiki.read_page('wiki1', 'HomePage')
|
||||||
['MyWay', 'SmartEngine', 'ThatWay'].each do |page|
|
['MyWay', 'SmartEngine', 'ThatWay'].each do |page|
|
||||||
@wiki.write_page('wiki1', page, page, Time.now, 'Me')
|
@wiki.write_page('wiki1', page, page, Time.now, 'Me')
|
||||||
end
|
end
|
||||||
|
|
||||||
@revision = Revision.new(@page, 1,
|
@revision = Revision.new(@page, 1,
|
||||||
'HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- ' +
|
'HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- ' +
|
||||||
'see SmartEngine in that SmartEngineGUI',
|
'see SmartEngine in that SmartEngineGUI',
|
||||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_wiki_words
|
def test_wiki_words
|
||||||
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
|
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_existing_pages
|
def test_existing_pages
|
||||||
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
|
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_unexisting_pages
|
def test_unexisting_pages
|
||||||
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
|
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_wiki_links
|
def test_content_with_wiki_links
|
||||||
assert_equal '<p><span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
assert_equal '<p><span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||||
'would be <a class="existingWikiWord" href="../show/MyWay">My Way</a> in kinda ' +
|
'would be <a class="existingWikiWord" href="../show/MyWay">My Way</a> in kinda ' +
|
||||||
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
|
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
|
||||||
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||||
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere—see ' +
|
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere—see ' +
|
||||||
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
|
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
|
||||||
'<span class="newWikiWord">Smart Engine GUI' +
|
'<span class="newWikiWord">Smart Engine GUI' +
|
||||||
'<a href="../show/SmartEngineGUI">?</a></span></p>',
|
'<a href="../show/SmartEngineGUI">?</a></span></p>',
|
||||||
@revision.display_content
|
@revision.display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_bluecloth
|
def test_bluecloth
|
||||||
@web.markup = :markdown
|
@web.markup = :markdown
|
||||||
|
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
|
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
|
||||||
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
|
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
|
||||||
"My Headline\n===========\n\n that SmartEngineGUI")
|
"My Headline\n===========\n\n that SmartEngineGUI")
|
||||||
|
|
||||||
code_block = [
|
code_block = [
|
||||||
'This is a code block:',
|
'This is a code block:',
|
||||||
'',
|
'',
|
||||||
' def a_method(arg)',
|
' def a_method(arg)',
|
||||||
' return ThatWay',
|
' return ThatWay',
|
||||||
'',
|
'',
|
||||||
'Nice!'
|
'Nice!'
|
||||||
].join("\n")
|
].join("\n")
|
||||||
|
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
%{<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\n} +
|
%{<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\n} +
|
||||||
%{return ThatWay\n</code></pre>\n\n<p>Nice!</p>},
|
%{return ThatWay\n</code></pre>\n\n<p>Nice!</p>},
|
||||||
code_block)
|
code_block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_rdoc
|
def test_rdoc
|
||||||
@web.markup = :rdoc
|
@web.markup = :rdoc
|
||||||
|
|
||||||
@revision = Revision.new(@page, 1, '+hello+ that SmartEngineGUI',
|
@revision = Revision.new(@page, 1, '+hello+ that SmartEngineGUI',
|
||||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
||||||
|
|
||||||
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
|
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
|
||||||
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
|
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_auto_links
|
def test_content_with_auto_links
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
|
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
|
||||||
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
|
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
|
||||||
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
|
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
|
||||||
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
|
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_aliased_links
|
def test_content_with_aliased_links
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
|
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
|
||||||
'</a> go by any other name?</p>',
|
'</a> go by any other name?</p>',
|
||||||
'Would a [[SmartEngine|clever motor]] go by any other name?')
|
'Would a [[SmartEngine|clever motor]] go by any other name?')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_wikiword_in_em
|
def test_content_with_wikiword_in_em
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><em>should we go <a class="existingWikiWord" href="../show/ThatWay">' +
|
'<p><em>should we go <a class="existingWikiWord" href="../show/ThatWay">' +
|
||||||
'That Way</a> or <span class="newWikiWord">This Way<a href="../show/ThisWay">?</a>' +
|
'That Way</a> or <span class="newWikiWord">This Way<a href="../show/ThisWay">?</a>' +
|
||||||
'</span> </em></p>',
|
'</span> </em></p>',
|
||||||
'_should we go ThatWay or ThisWay _')
|
'_should we go ThatWay or ThisWay _')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_wikiword_in_tag
|
def test_content_with_wikiword_in_tag
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
|
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
|
||||||
'That is some <em style="WikiWord">Stylish Emphasis</em>')
|
'That is some <em style="WikiWord">Stylish Emphasis</em>')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_escaped_wikiword
|
def test_content_with_escaped_wikiword
|
||||||
# there should be no wiki link
|
# there should be no wiki link
|
||||||
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
|
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_pre_blocks
|
def test_content_with_pre_blocks
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>',
|
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>',
|
||||||
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
|
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_autolink_in_parentheses
|
def test_content_with_autolink_in_parentheses
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
|
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
|
||||||
'http://www.w3c.org</a>) sets web standards</p>',
|
'http://www.w3c.org</a>) sets web standards</p>',
|
||||||
'The W3C body (http://www.w3c.org) sets web standards')
|
'The W3C body (http://www.w3c.org) sets web standards')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_link_in_parentheses
|
def test_content_with_link_in_parentheses
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>(<a href="http://wiki.org/wiki.cgi?WhatIsWiki">What is a wiki?</a>)</p>',
|
'<p>(<a href="http://wiki.org/wiki.cgi?WhatIsWiki">What is a wiki?</a>)</p>',
|
||||||
'("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
|
'("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_image_link
|
def test_content_with_image_link
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is a Textile image link.</p>',
|
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is a Textile image link.</p>',
|
||||||
'This !http://hobix.com/sample.jpg! is a Textile image link.')
|
'This !http://hobix.com/sample.jpg! is a Textile image link.')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_nowiki_text
|
def test_content_with_nowiki_text
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
|
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
|
||||||
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
|
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
|
||||||
'or <nowiki>http://www.thislink.com</nowiki>.')
|
'or <nowiki>http://www.thislink.com</nowiki>.')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_with_bracketted_wiki_word
|
def test_content_with_bracketted_wiki_word
|
||||||
@web.brackets_only = true
|
@web.brackets_only = true
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
|
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
|
||||||
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
|
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
|
||||||
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
|
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_content_for_export
|
def test_content_for_export
|
||||||
assert_equal '<p><span class="newWikiWord">His Way</span> would be ' +
|
assert_equal '<p><span class="newWikiWord">His Way</span> would be ' +
|
||||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> in kinda ' +
|
'<a class="existingWikiWord" href="MyWay.html">My Way</a> in kinda ' +
|
||||||
'<a class="existingWikiWord" href="ThatWay.html">That Way</a> in ' +
|
'<a class="existingWikiWord" href="ThatWay.html">That Way</a> in ' +
|
||||||
'<span class="newWikiWord">His Way</span> though ' +
|
'<span class="newWikiWord">His Way</span> though ' +
|
||||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere—see ' +
|
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere—see ' +
|
||||||
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
|
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
|
||||||
'<span class="newWikiWord">Smart Engine GUI</span></p>',
|
'<span class="newWikiWord">Smart Engine GUI</span></p>',
|
||||||
@revision.display_content_for_export
|
@revision.display_content_for_export
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_double_replacing
|
def test_double_replacing
|
||||||
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
|
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
|
||||||
assert_equal '<p><span class="newWikiWord">Version History' +
|
assert_equal '<p><span class="newWikiWord">Version History' +
|
||||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\t<p>cry " +
|
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\t<p>cry " +
|
||||||
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
|
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
|
||||||
'</span></p>',
|
'</span></p>',
|
||||||
@revision.display_content
|
@revision.display_content
|
||||||
|
|
||||||
@revision.clear_display_cache
|
@revision.clear_display_cache
|
||||||
|
|
||||||
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
|
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
|
||||||
assert_equal "<p>f<br />\n<span class=\"newWikiWord\">Version History" +
|
assert_equal "<p>f<br />\n<span class=\"newWikiWord\">Version History" +
|
||||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\t<p>cry " +
|
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\t<p>cry " +
|
||||||
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
|
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
|
||||||
"</span></p>",
|
"</span></p>",
|
||||||
@revision.display_content
|
@revision.display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_difficult_wiki_words
|
def test_difficult_wiki_words
|
||||||
@revision.content = "[[It's just awesome GUI!]]"
|
@revision.content = "[[It's just awesome GUI!]]"
|
||||||
assert_equal "<p><span class=\"newWikiWord\">It's just awesome GUI!" +
|
assert_equal "<p><span class=\"newWikiWord\">It's just awesome GUI!" +
|
||||||
"<a href=\"../show/It%27s+just+awesome+GUI%21\">?</a></span></p>",
|
"<a href=\"../show/It%27s+just+awesome+GUI%21\">?</a></span></p>",
|
||||||
@revision.display_content
|
@revision.display_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_revisions_diff
|
def test_revisions_diff
|
||||||
|
|
||||||
@page.revisions = [
|
@page.revisions = [
|
||||||
Revision.new(@page, 0, 'What a blue and lovely morning',
|
Revision.new(@page, 0, 'What a blue and lovely morning',
|
||||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson'),
|
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson'),
|
||||||
Revision.new(@page, 1, 'What a red and lovely morning today',
|
Revision.new(@page, 1, 'What a red and lovely morning today',
|
||||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
||||||
]
|
]
|
||||||
|
|
||||||
assert_equal "<p>What a <del class=\"diffmod\">blue </del><ins class=\"diffmod\">red " +
|
assert_equal "<p>What a <del class=\"diffmod\">blue </del><ins class=\"diffmod\">red " +
|
||||||
"</ins>and lovely <del class=\"diffmod\">morning</del><ins class=\"diffmod\">morning " +
|
"</ins>and lovely <del class=\"diffmod\">morning</del><ins class=\"diffmod\">morning " +
|
||||||
"today</ins></p>", @page.revisions.last.display_diff
|
"today</ins></p>", @page.revisions.last.display_diff
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_link_to_file
|
def test_link_to_file
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
|
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
|
||||||
'[[doc.pdf:file]]')
|
'[[doc.pdf:file]]')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_link_to_pic
|
def test_link_to_pic
|
||||||
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
|
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
|
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
|
||||||
'[[square.jpg|Square:pic]]')
|
'[[square.jpg|Square:pic]]')
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
|
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
|
||||||
'[[square.jpg:pic]]')
|
'[[square.jpg:pic]]')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_link_to_non_existant_pic
|
def test_link_to_non_existant_pic
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
|
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
|
||||||
'</span></p>',
|
'</span></p>',
|
||||||
'[[NonExistant.jpg|NonExistant:pic]]')
|
'[[NonExistant.jpg|NonExistant:pic]]')
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
|
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
|
||||||
'</span></p>',
|
'</span></p>',
|
||||||
'[[NonExistant.jpg:pic]]')
|
'[[NonExistant.jpg:pic]]')
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
|
# TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
|
||||||
# also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
|
# also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
|
||||||
def __test_list_with_tildas
|
def __test_list_with_tildas
|
||||||
list_with_tildas = <<-EOL
|
list_with_tildas = <<-EOL
|
||||||
* "a":~b
|
* "a":~b
|
||||||
* c~ d
|
* c~ d
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
assert_markup_parsed_as(
|
assert_markup_parsed_as(
|
||||||
"<li><a href=\"~b\">a</a></li>\n" +
|
"<li><a href=\"~b\">a</a></li>\n" +
|
||||||
"<li>c~ d</li>\n",
|
"<li>c~ d</li>\n",
|
||||||
list_with_tildas)
|
list_with_tildas)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def assert_markup_parsed_as(expected_output, input)
|
def assert_markup_parsed_as(expected_output, input)
|
||||||
revision = Revision.new(@page, 1, input, Time.local(2004, 4, 4, 16, 50), 'AnAuthor')
|
revision = Revision.new(@page, 1, input, Time.local(2004, 4, 4, 16, 50), 'AnAuthor')
|
||||||
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
|
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,179 +1,179 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'chunks/uri'
|
require 'chunks/uri'
|
||||||
|
|
||||||
class URITest < Test::Unit::TestCase
|
class URITest < Test::Unit::TestCase
|
||||||
include ChunkMatch
|
include ChunkMatch
|
||||||
|
|
||||||
def test_non_matches
|
def test_non_matches
|
||||||
assert_conversion_does_not_apply(URIChunk, 'There is no URI here')
|
assert_conversion_does_not_apply(URIChunk, 'There is no URI here')
|
||||||
assert_conversion_does_not_apply(URIChunk,
|
assert_conversion_does_not_apply(URIChunk,
|
||||||
'One gemstone is the garnet:reddish in colour, like ruby')
|
'One gemstone is the garnet:reddish in colour, like ruby')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_simple_uri
|
def test_simple_uri
|
||||||
# Simplest case
|
# Simplest case
|
||||||
match(URIChunk, 'http://www.example.com',
|
match(URIChunk, 'http://www.example.com',
|
||||||
:scheme =>'http', :host =>'www.example.com', :path => nil,
|
:scheme =>'http', :host =>'www.example.com', :path => nil,
|
||||||
:link_text => 'http://www.example.com'
|
:link_text => 'http://www.example.com'
|
||||||
)
|
)
|
||||||
# With trailing slash
|
# With trailing slash
|
||||||
match(URIChunk, 'http://www.example.com/',
|
match(URIChunk, 'http://www.example.com/',
|
||||||
:scheme =>'http', :host =>'www.example.com', :path => '/',
|
:scheme =>'http', :host =>'www.example.com', :path => '/',
|
||||||
:link_text => 'http://www.example.com/'
|
:link_text => 'http://www.example.com/'
|
||||||
)
|
)
|
||||||
# Without http://
|
# Without http://
|
||||||
match(URIChunk, 'www.example.com',
|
match(URIChunk, 'www.example.com',
|
||||||
:scheme =>'http', :host =>'www.example.com', :link_text => 'www.example.com'
|
:scheme =>'http', :host =>'www.example.com', :link_text => 'www.example.com'
|
||||||
)
|
)
|
||||||
# two parts
|
# two parts
|
||||||
match(URIChunk, 'example.com',
|
match(URIChunk, 'example.com',
|
||||||
:scheme =>'http',:host =>'example.com', :link_text => 'example.com'
|
:scheme =>'http',:host =>'example.com', :link_text => 'example.com'
|
||||||
)
|
)
|
||||||
# "unusual" base domain (was a bug in an early version)
|
# "unusual" base domain (was a bug in an early version)
|
||||||
match(URIChunk, 'http://example.com.au/',
|
match(URIChunk, 'http://example.com.au/',
|
||||||
:scheme =>'http', :host =>'example.com.au', :link_text => 'http://example.com.au/'
|
:scheme =>'http', :host =>'example.com.au', :link_text => 'http://example.com.au/'
|
||||||
)
|
)
|
||||||
# "unusual" base domain without http://
|
# "unusual" base domain without http://
|
||||||
match(URIChunk, 'example.com.au',
|
match(URIChunk, 'example.com.au',
|
||||||
:scheme =>'http', :host =>'example.com.au', :link_text => 'example.com.au'
|
:scheme =>'http', :host =>'example.com.au', :link_text => 'example.com.au'
|
||||||
)
|
)
|
||||||
# Another "unusual" base domain
|
# Another "unusual" base domain
|
||||||
match(URIChunk, 'http://www.example.co.uk/',
|
match(URIChunk, 'http://www.example.co.uk/',
|
||||||
:scheme =>'http', :host =>'www.example.co.uk',
|
:scheme =>'http', :host =>'www.example.co.uk',
|
||||||
:link_text => 'http://www.example.co.uk/'
|
:link_text => 'http://www.example.co.uk/'
|
||||||
)
|
)
|
||||||
match(URIChunk, 'example.co.uk',
|
match(URIChunk, 'example.co.uk',
|
||||||
:scheme =>'http', :host =>'example.co.uk', :link_text => 'example.co.uk'
|
:scheme =>'http', :host =>'example.co.uk', :link_text => 'example.co.uk'
|
||||||
)
|
)
|
||||||
# With some path at the end
|
# With some path at the end
|
||||||
match(URIChunk, 'http://moinmoin.wikiwikiweb.de/HelpOnNavigation',
|
match(URIChunk, 'http://moinmoin.wikiwikiweb.de/HelpOnNavigation',
|
||||||
:scheme => 'http', :host => 'moinmoin.wikiwikiweb.de', :path => '/HelpOnNavigation',
|
:scheme => 'http', :host => 'moinmoin.wikiwikiweb.de', :path => '/HelpOnNavigation',
|
||||||
:link_text => 'http://moinmoin.wikiwikiweb.de/HelpOnNavigation'
|
:link_text => 'http://moinmoin.wikiwikiweb.de/HelpOnNavigation'
|
||||||
)
|
)
|
||||||
# With some path at the end, and withot http:// prefix
|
# With some path at the end, and withot http:// prefix
|
||||||
match(URIChunk, 'moinmoin.wikiwikiweb.de/HelpOnNavigation',
|
match(URIChunk, 'moinmoin.wikiwikiweb.de/HelpOnNavigation',
|
||||||
:scheme => 'http', :host => 'moinmoin.wikiwikiweb.de', :path => '/HelpOnNavigation',
|
:scheme => 'http', :host => 'moinmoin.wikiwikiweb.de', :path => '/HelpOnNavigation',
|
||||||
:link_text => 'moinmoin.wikiwikiweb.de/HelpOnNavigation'
|
:link_text => 'moinmoin.wikiwikiweb.de/HelpOnNavigation'
|
||||||
)
|
)
|
||||||
# With a port number
|
# With a port number
|
||||||
match(URIChunk, 'http://www.example.com:80',
|
match(URIChunk, 'http://www.example.com:80',
|
||||||
:scheme =>'http', :host =>'www.example.com', :port => '80', :path => nil,
|
:scheme =>'http', :host =>'www.example.com', :port => '80', :path => nil,
|
||||||
:link_text => 'http://www.example.com:80')
|
:link_text => 'http://www.example.com:80')
|
||||||
# With a port number and a path
|
# With a port number and a path
|
||||||
match(URIChunk, 'http://www.example.com.tw:80/HelpOnNavigation',
|
match(URIChunk, 'http://www.example.com.tw:80/HelpOnNavigation',
|
||||||
:scheme =>'http', :host =>'www.example.com.tw', :port => '80', :path => '/HelpOnNavigation',
|
:scheme =>'http', :host =>'www.example.com.tw', :port => '80', :path => '/HelpOnNavigation',
|
||||||
:link_text => 'http://www.example.com.tw:80/HelpOnNavigation')
|
:link_text => 'http://www.example.com.tw:80/HelpOnNavigation')
|
||||||
# With a query
|
# With a query
|
||||||
match(URIChunk, 'http://www.example.com.tw:80/HelpOnNavigation?arg=val',
|
match(URIChunk, 'http://www.example.com.tw:80/HelpOnNavigation?arg=val',
|
||||||
:scheme =>'http', :host =>'www.example.com.tw', :port => '80', :path => '/HelpOnNavigation',
|
:scheme =>'http', :host =>'www.example.com.tw', :port => '80', :path => '/HelpOnNavigation',
|
||||||
:query => 'arg=val',
|
:query => 'arg=val',
|
||||||
:link_text => 'http://www.example.com.tw:80/HelpOnNavigation?arg=val')
|
:link_text => 'http://www.example.com.tw:80/HelpOnNavigation?arg=val')
|
||||||
# Query with two arguments
|
# Query with two arguments
|
||||||
match(URIChunk, 'http://www.example.com.tw:80/HelpOnNavigation?arg=val&arg2=val2',
|
match(URIChunk, 'http://www.example.com.tw:80/HelpOnNavigation?arg=val&arg2=val2',
|
||||||
:scheme =>'http', :host =>'www.example.com.tw', :port => '80', :path => '/HelpOnNavigation',
|
:scheme =>'http', :host =>'www.example.com.tw', :port => '80', :path => '/HelpOnNavigation',
|
||||||
:query => 'arg=val&arg2=val2',
|
:query => 'arg=val&arg2=val2',
|
||||||
:link_text => 'http://www.example.com.tw:80/HelpOnNavigation?arg=val&arg2=val2')
|
:link_text => 'http://www.example.com.tw:80/HelpOnNavigation?arg=val&arg2=val2')
|
||||||
# HTTPS
|
# HTTPS
|
||||||
match(URIChunk, 'https://www.example.com',
|
match(URIChunk, 'https://www.example.com',
|
||||||
:scheme =>'https', :host =>'www.example.com', :port => nil, :path => nil, :query => nil,
|
:scheme =>'https', :host =>'www.example.com', :port => nil, :path => nil, :query => nil,
|
||||||
:link_text => 'https://www.example.com')
|
:link_text => 'https://www.example.com')
|
||||||
# FTP
|
# FTP
|
||||||
match(URIChunk, 'ftp://www.example.com',
|
match(URIChunk, 'ftp://www.example.com',
|
||||||
:scheme =>'ftp', :host =>'www.example.com', :port => nil, :path => nil, :query => nil,
|
:scheme =>'ftp', :host =>'www.example.com', :port => nil, :path => nil, :query => nil,
|
||||||
:link_text => 'ftp://www.example.com')
|
:link_text => 'ftp://www.example.com')
|
||||||
# mailto
|
# mailto
|
||||||
match(URIChunk, 'mailto:jdoe123@example.com',
|
match(URIChunk, 'mailto:jdoe123@example.com',
|
||||||
:scheme =>'mailto', :host =>'example.com', :port => nil, :path => nil, :query => nil,
|
:scheme =>'mailto', :host =>'example.com', :port => nil, :path => nil, :query => nil,
|
||||||
:user => 'jdoe123', :link_text => 'mailto:jdoe123@example.com')
|
:user => 'jdoe123', :link_text => 'mailto:jdoe123@example.com')
|
||||||
# something nonexistant
|
# something nonexistant
|
||||||
match(URIChunk, 'foobar://www.example.com',
|
match(URIChunk, 'foobar://www.example.com',
|
||||||
:scheme =>'foobar', :host =>'www.example.com', :port => nil, :path => nil, :query => nil,
|
:scheme =>'foobar', :host =>'www.example.com', :port => nil, :path => nil, :query => nil,
|
||||||
:link_text => 'foobar://www.example.com')
|
:link_text => 'foobar://www.example.com')
|
||||||
|
|
||||||
# Soap opera (the most complex case imaginable... well, not really, there should be more evil)
|
# Soap opera (the most complex case imaginable... well, not really, there should be more evil)
|
||||||
match(URIChunk, 'http://www.example.com.tw:80/~jdoe123/Help%20Me%20?arg=val&arg2=val2',
|
match(URIChunk, 'http://www.example.com.tw:80/~jdoe123/Help%20Me%20?arg=val&arg2=val2',
|
||||||
:scheme =>'http', :host =>'www.example.com.tw', :port => '80',
|
:scheme =>'http', :host =>'www.example.com.tw', :port => '80',
|
||||||
:path => '/~jdoe123/Help%20Me%20', :query => 'arg=val&arg2=val2',
|
:path => '/~jdoe123/Help%20Me%20', :query => 'arg=val&arg2=val2',
|
||||||
:link_text => 'http://www.example.com.tw:80/~jdoe123/Help%20Me%20?arg=val&arg2=val2')
|
:link_text => 'http://www.example.com.tw:80/~jdoe123/Help%20Me%20?arg=val&arg2=val2')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_email_uri
|
def test_email_uri
|
||||||
match(URIChunk, 'mail@example.com',
|
match(URIChunk, 'mail@example.com',
|
||||||
:user => 'mail', :host => 'example.com', :link_text => 'mail@example.com'
|
:user => 'mail', :host => 'example.com', :link_text => 'mail@example.com'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_non_email
|
def test_non_email
|
||||||
# The @ is part of the normal text, but 'example.com' is marked up.
|
# The @ is part of the normal text, but 'example.com' is marked up.
|
||||||
match(URIChunk, 'Not an email: @example.com', :user => nil, :uri => 'http://example.com')
|
match(URIChunk, 'Not an email: @example.com', :user => nil, :uri => 'http://example.com')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_non_uri
|
def test_non_uri
|
||||||
assert_conversion_does_not_apply URIChunk, 'httpd.conf'
|
assert_conversion_does_not_apply URIChunk, 'httpd.conf'
|
||||||
assert_conversion_does_not_apply URIChunk, 'libproxy.so'
|
assert_conversion_does_not_apply URIChunk, 'libproxy.so'
|
||||||
assert_conversion_does_not_apply URIChunk, 'ld.so.conf'
|
assert_conversion_does_not_apply URIChunk, 'ld.so.conf'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_uri_in_text
|
def test_uri_in_text
|
||||||
match(URIChunk, 'Go to: http://www.example.com/', :host => 'www.example.com', :path =>'/')
|
match(URIChunk, 'Go to: http://www.example.com/', :host => 'www.example.com', :path =>'/')
|
||||||
match(URIChunk, 'http://www.example.com/ is a link.', :host => 'www.example.com')
|
match(URIChunk, 'http://www.example.com/ is a link.', :host => 'www.example.com')
|
||||||
match(URIChunk,
|
match(URIChunk,
|
||||||
'Email david@loudthinking.com',
|
'Email david@loudthinking.com',
|
||||||
:scheme =>'mailto', :user =>'david', :host =>'loudthinking.com')
|
:scheme =>'mailto', :user =>'david', :host =>'loudthinking.com')
|
||||||
# check that trailing punctuation is not included in the hostname
|
# check that trailing punctuation is not included in the hostname
|
||||||
match(URIChunk, '"link":http://fake.link.com.', :scheme => 'http', :host => 'fake.link.com')
|
match(URIChunk, '"link":http://fake.link.com.', :scheme => 'http', :host => 'fake.link.com')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_uri_in_parentheses
|
def test_uri_in_parentheses
|
||||||
match(URIChunk, 'URI (http://brackets.com.de) in brackets', :host => 'brackets.com.de')
|
match(URIChunk, 'URI (http://brackets.com.de) in brackets', :host => 'brackets.com.de')
|
||||||
match(URIChunk, 'because (as shown at research.net) the results', :host => 'research.net')
|
match(URIChunk, 'because (as shown at research.net) the results', :host => 'research.net')
|
||||||
match(URIChunk,
|
match(URIChunk,
|
||||||
'A wiki (http://wiki.org/wiki.cgi?WhatIsWiki) page',
|
'A wiki (http://wiki.org/wiki.cgi?WhatIsWiki) page',
|
||||||
:scheme => 'http', :host => 'wiki.org', :path => '/wiki.cgi', :query => 'WhatIsWiki'
|
:scheme => 'http', :host => 'wiki.org', :path => '/wiki.cgi', :query => 'WhatIsWiki'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_uri_list_item
|
def test_uri_list_item
|
||||||
match(
|
match(
|
||||||
URIChunk,
|
URIChunk,
|
||||||
'* http://www.btinternet.com/~mail2minh/SonyEricssonP80xPlatform.sis',
|
'* http://www.btinternet.com/~mail2minh/SonyEricssonP80xPlatform.sis',
|
||||||
:path => '/~mail2minh/SonyEricssonP80xPlatform.sis'
|
:path => '/~mail2minh/SonyEricssonP80xPlatform.sis'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_interesting_uri_with__comma
|
def test_interesting_uri_with__comma
|
||||||
# Counter-intuitively, this URL matches, but the query part includes the trailing comma.
|
# Counter-intuitively, this URL matches, but the query part includes the trailing comma.
|
||||||
# It has no way to know that the query does not include the comma.
|
# It has no way to know that the query does not include the comma.
|
||||||
match(
|
match(
|
||||||
URIChunk,
|
URIChunk,
|
||||||
"This text contains a URL http://someplace.org:8080/~person/stuff.cgi?arg=val, doesn't it?",
|
"This text contains a URL http://someplace.org:8080/~person/stuff.cgi?arg=val, doesn't it?",
|
||||||
:scheme => 'http', :host => 'someplace.org', :port => '8080', :path => '/~person/stuff.cgi',
|
:scheme => 'http', :host => 'someplace.org', :port => '8080', :path => '/~person/stuff.cgi',
|
||||||
:query => 'arg=val,')
|
:query => 'arg=val,')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_local_urls
|
def test_local_urls
|
||||||
# normal
|
# normal
|
||||||
match(LocalURIChunk, 'http://perforce:8001/toto.html',
|
match(LocalURIChunk, 'http://perforce:8001/toto.html',
|
||||||
:scheme => 'http', :host => 'perforce',
|
:scheme => 'http', :host => 'perforce',
|
||||||
:port => '8001', :link_text => 'http://perforce:8001/toto.html')
|
:port => '8001', :link_text => 'http://perforce:8001/toto.html')
|
||||||
|
|
||||||
# in parentheses
|
# in parentheses
|
||||||
match(LocalURIChunk, 'URI (http://localhost:2500) in brackets',
|
match(LocalURIChunk, 'URI (http://localhost:2500) in brackets',
|
||||||
:host => 'localhost', :port => '2500')
|
:host => 'localhost', :port => '2500')
|
||||||
match(LocalURIChunk, 'because (as shown at http://perforce:8001) the results',
|
match(LocalURIChunk, 'because (as shown at http://perforce:8001) the results',
|
||||||
:host => 'perforce', :port => '8001')
|
:host => 'perforce', :port => '8001')
|
||||||
match(LocalURIChunk,
|
match(LocalURIChunk,
|
||||||
'A wiki (http://localhost:2500/wiki.cgi?WhatIsWiki) page',
|
'A wiki (http://localhost:2500/wiki.cgi?WhatIsWiki) page',
|
||||||
:scheme => 'http', :host => 'localhost', :path => '/wiki.cgi',
|
:scheme => 'http', :host => 'localhost', :path => '/wiki.cgi',
|
||||||
:port => '2500', :query => 'WhatIsWiki')
|
:port => '2500', :query => 'WhatIsWiki')
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_conversion_does_not_apply(chunk_type, str)
|
def assert_conversion_does_not_apply(chunk_type, str)
|
||||||
processed_str = str.dup
|
processed_str = str.dup
|
||||||
URIChunk.apply_to(processed_str)
|
URIChunk.apply_to(processed_str)
|
||||||
assert_equal(str, processed_str)
|
assert_equal(str, processed_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,92 +1,92 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'url_rewriting_hack'
|
require 'url_rewriting_hack'
|
||||||
|
|
||||||
class UrlRewritingHackTest < Test::Unit::TestCase
|
class UrlRewritingHackTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_parse_uri
|
def test_parse_uri
|
||||||
assert_equal({:controller => 'wiki', :action => 'x', :web => nil},
|
assert_equal({:controller => 'wiki', :action => 'x', :web => nil},
|
||||||
DispatchServlet.parse_uri('/x/'))
|
DispatchServlet.parse_uri('/x/'))
|
||||||
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y'},
|
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y'},
|
||||||
DispatchServlet.parse_uri('/x/y'))
|
DispatchServlet.parse_uri('/x/y'))
|
||||||
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y'},
|
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y'},
|
||||||
DispatchServlet.parse_uri('/x/y/'))
|
DispatchServlet.parse_uri('/x/y/'))
|
||||||
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y', :id => 'z'},
|
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y', :id => 'z'},
|
||||||
DispatchServlet.parse_uri('/x/y/z'))
|
DispatchServlet.parse_uri('/x/y/z'))
|
||||||
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y', :id => 'z'},
|
assert_equal({:web => 'x', :controller => 'wiki', :action => 'y', :id => 'z'},
|
||||||
DispatchServlet.parse_uri('/x/y/z/'))
|
DispatchServlet.parse_uri('/x/y/z/'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_uri_approot
|
def test_parse_uri_approot
|
||||||
assert_equal({:controller => 'wiki', :action => 'index', :web => nil},
|
assert_equal({:controller => 'wiki', :action => 'index', :web => nil},
|
||||||
DispatchServlet.parse_uri('/wiki/'))
|
DispatchServlet.parse_uri('/wiki/'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_uri_interestng_cases
|
def test_parse_uri_interestng_cases
|
||||||
|
|
||||||
assert_equal({:web => '_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery-long_web_',
|
assert_equal({:web => '_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery-long_web_',
|
||||||
:controller => 'wiki',
|
:controller => 'wiki',
|
||||||
:action => 'an_action', :id => 'HomePage'
|
:action => 'an_action', :id => 'HomePage'
|
||||||
},
|
},
|
||||||
DispatchServlet.parse_uri(
|
DispatchServlet.parse_uri(
|
||||||
'/_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery-long_web_/an_action/HomePage')
|
'/_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery-long_web_/an_action/HomePage')
|
||||||
)
|
)
|
||||||
|
|
||||||
assert_equal false, DispatchServlet.parse_uri('')
|
assert_equal false, DispatchServlet.parse_uri('')
|
||||||
assert_equal false, DispatchServlet.parse_uri('//')
|
assert_equal false, DispatchServlet.parse_uri('//')
|
||||||
assert_equal false, DispatchServlet.parse_uri('web')
|
assert_equal false, DispatchServlet.parse_uri('web')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_parse_uri_liberal_with_pagenames
|
def test_parse_uri_liberal_with_pagenames
|
||||||
|
|
||||||
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show', :id => '$HOME_PAGE'},
|
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show', :id => '$HOME_PAGE'},
|
||||||
DispatchServlet.parse_uri('/web/show/$HOME_PAGE'))
|
DispatchServlet.parse_uri('/web/show/$HOME_PAGE'))
|
||||||
|
|
||||||
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show',
|
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show',
|
||||||
:id => 'HomePage/something_else'},
|
:id => 'HomePage/something_else'},
|
||||||
DispatchServlet.parse_uri('/web/show/HomePage/something_else'))
|
DispatchServlet.parse_uri('/web/show/HomePage/something_else'))
|
||||||
|
|
||||||
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show',
|
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show',
|
||||||
:id => 'HomePage?arg1=value1&arg2=value2'},
|
:id => 'HomePage?arg1=value1&arg2=value2'},
|
||||||
DispatchServlet.parse_uri('/web/show/HomePage?arg1=value1&arg2=value2'))
|
DispatchServlet.parse_uri('/web/show/HomePage?arg1=value1&arg2=value2'))
|
||||||
|
|
||||||
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show',
|
assert_equal({:controller => 'wiki', :web => 'web', :action => 'show',
|
||||||
:id => 'Page+With+Spaces'},
|
:id => 'Page+With+Spaces'},
|
||||||
DispatchServlet.parse_uri('/web/show/Page+With+Spaces'))
|
DispatchServlet.parse_uri('/web/show/Page+With+Spaces'))
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_rewriting
|
def test_url_rewriting
|
||||||
request = ActionController::TestRequest.new
|
request = ActionController::TestRequest.new
|
||||||
ur = ActionController::UrlRewriter.new(request, 'wiki', 'show')
|
ur = ActionController::UrlRewriter.new(request, 'wiki', 'show')
|
||||||
|
|
||||||
assert_equal 'http://test.host/myweb/myaction',
|
assert_equal 'http://test.host/myweb/myaction',
|
||||||
ur.rewrite(:web => 'myweb', :controller => 'wiki', :action => 'myaction')
|
ur.rewrite(:web => 'myweb', :controller => 'wiki', :action => 'myaction')
|
||||||
|
|
||||||
assert_equal 'http://test.host/myOtherWeb/',
|
assert_equal 'http://test.host/myOtherWeb/',
|
||||||
ur.rewrite(:web => 'myOtherWeb', :controller => 'wiki')
|
ur.rewrite(:web => 'myOtherWeb', :controller => 'wiki')
|
||||||
|
|
||||||
assert_equal 'http://test.host/myaction',
|
assert_equal 'http://test.host/myaction',
|
||||||
ur.rewrite(:controller => 'wiki', :action => 'myaction')
|
ur.rewrite(:controller => 'wiki', :action => 'myaction')
|
||||||
|
|
||||||
assert_equal 'http://test.host/',
|
assert_equal 'http://test.host/',
|
||||||
ur.rewrite(:controller => 'wiki')
|
ur.rewrite(:controller => 'wiki')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_controller_mapping
|
def test_controller_mapping
|
||||||
request = ActionController::TestRequest.new
|
request = ActionController::TestRequest.new
|
||||||
ur = ActionController::UrlRewriter.new(request, 'wiki', 'show')
|
ur = ActionController::UrlRewriter.new(request, 'wiki', 'show')
|
||||||
|
|
||||||
assert_equal 'http://test.host/file',
|
assert_equal 'http://test.host/file',
|
||||||
ur.rewrite(:controller => 'file', :action => 'file')
|
ur.rewrite(:controller => 'file', :action => 'file')
|
||||||
assert_equal 'http://test.host/pic/abc.jpg',
|
assert_equal 'http://test.host/pic/abc.jpg',
|
||||||
ur.rewrite(:controller => 'file', :action => 'pic', :id => 'abc.jpg')
|
ur.rewrite(:controller => 'file', :action => 'pic', :id => 'abc.jpg')
|
||||||
assert_equal 'http://test.host/web/pic/abc.jpg',
|
assert_equal 'http://test.host/web/pic/abc.jpg',
|
||||||
ur.rewrite(:web => 'web', :controller => 'file', :action => 'pic', :id => 'abc.jpg')
|
ur.rewrite(:web => 'web', :controller => 'file', :action => 'pic', :id => 'abc.jpg')
|
||||||
|
|
||||||
# default option is wiki
|
# default option is wiki
|
||||||
assert_equal 'http://test.host/unknown_action',
|
assert_equal 'http://test.host/unknown_action',
|
||||||
ur.rewrite(:controller => 'wiki', :action => 'unknown_action')
|
ur.rewrite(:controller => 'wiki', :action => 'unknown_action')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -1,130 +1,130 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'wiki_service'
|
require 'wiki_service'
|
||||||
|
|
||||||
class WebTest < Test::Unit::TestCase
|
class WebTest < Test::Unit::TestCase
|
||||||
def setup
|
def setup
|
||||||
@web = Web.new nil, 'Instiki', 'instiki'
|
@web = Web.new nil, 'Instiki', 'instiki'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_wiki_word_linking
|
def test_wiki_word_linking
|
||||||
@web.add_page(Page.new(@web, 'SecondPage', 'Yo, yo. Have you EverBeenHated', Time.now,
|
@web.add_page(Page.new(@web, 'SecondPage', 'Yo, yo. Have you EverBeenHated', Time.now,
|
||||||
'DavidHeinemeierHansson'))
|
'DavidHeinemeierHansson'))
|
||||||
|
|
||||||
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
|
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
|
||||||
'<a href="../show/EverBeenHated">?</a></span></p>',
|
'<a href="../show/EverBeenHated">?</a></span></p>',
|
||||||
@web.pages["SecondPage"].display_content)
|
@web.pages["SecondPage"].display_content)
|
||||||
|
|
||||||
@web.add_page(Page.new(@web, 'EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
|
@web.add_page(Page.new(@web, 'EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
|
||||||
'DavidHeinemeierHansson'))
|
'DavidHeinemeierHansson'))
|
||||||
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
|
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
|
||||||
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
|
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
|
||||||
@web.pages['SecondPage'].display_content)
|
@web.pages['SecondPage'].display_content)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_pages_by_revision
|
def test_pages_by_revision
|
||||||
add_sample_pages
|
add_sample_pages
|
||||||
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
|
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_pages_by_match
|
def test_pages_by_match
|
||||||
add_sample_pages
|
add_sample_pages
|
||||||
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
|
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
|
||||||
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
|
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
|
||||||
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
|
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_references
|
def test_references
|
||||||
add_sample_pages
|
add_sample_pages
|
||||||
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
|
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
|
||||||
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
|
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_delete
|
def test_delete
|
||||||
add_sample_pages
|
add_sample_pages
|
||||||
assert_equal 2, @web.pages.length
|
assert_equal 2, @web.pages.length
|
||||||
@web.remove_pages([ @web.pages['EverBeenInLove'] ])
|
@web.remove_pages([ @web.pages['EverBeenInLove'] ])
|
||||||
assert_equal 1, @web.pages.length
|
assert_equal 1, @web.pages.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_make_link
|
def test_make_link
|
||||||
add_sample_pages
|
add_sample_pages
|
||||||
|
|
||||||
existing_page_wiki_url =
|
existing_page_wiki_url =
|
||||||
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
|
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
|
||||||
existing_page_published_url =
|
existing_page_published_url =
|
||||||
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
|
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
|
||||||
existing_page_static_url =
|
existing_page_static_url =
|
||||||
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
|
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
|
||||||
new_page_wiki_url =
|
new_page_wiki_url =
|
||||||
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
|
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
|
||||||
new_page_published_url =
|
new_page_published_url =
|
||||||
new_page_static_url =
|
new_page_static_url =
|
||||||
'<span class="newWikiWord">Unknown Word</span>'
|
'<span class="newWikiWord">Unknown Word</span>'
|
||||||
|
|
||||||
# no options
|
# no options
|
||||||
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
|
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
|
||||||
|
|
||||||
# :mode => :export
|
# :mode => :export
|
||||||
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
|
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
|
||||||
|
|
||||||
# :mode => :publish
|
# :mode => :publish
|
||||||
assert_equal existing_page_published_url,
|
assert_equal existing_page_published_url,
|
||||||
@web.make_link('EverBeenInLove', nil, :mode => :publish)
|
@web.make_link('EverBeenInLove', nil, :mode => :publish)
|
||||||
|
|
||||||
# new page, no options
|
# new page, no options
|
||||||
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
|
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
|
||||||
|
|
||||||
# new page, :mode => :export
|
# new page, :mode => :export
|
||||||
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
|
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
|
||||||
|
|
||||||
# new page, :mode => :publish
|
# new page, :mode => :publish
|
||||||
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
|
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
|
||||||
|
|
||||||
# Escaping special characters in the name
|
# Escaping special characters in the name
|
||||||
assert_equal(
|
assert_equal(
|
||||||
'<span class="newWikiWord">Smith & Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
|
'<span class="newWikiWord">Smith & Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
|
||||||
@web.make_link('Smith & Wesson'))
|
@web.make_link('Smith & Wesson'))
|
||||||
|
|
||||||
# optionally using text as the link text
|
# optionally using text as the link text
|
||||||
assert_equal(
|
assert_equal(
|
||||||
existing_page_published_url.sub(/>Ever Been In Love</, ">Haven't you ever been in love?<"),
|
existing_page_published_url.sub(/>Ever Been In Love</, ">Haven't you ever been in love?<"),
|
||||||
@web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
|
@web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_initialize
|
def test_initialize
|
||||||
wiki_stub = Object.new
|
wiki_stub = Object.new
|
||||||
|
|
||||||
web = Web.new(wiki_stub, 'Wiki2', 'wiki2', '123')
|
web = Web.new(wiki_stub, 'Wiki2', 'wiki2', '123')
|
||||||
|
|
||||||
assert_equal wiki_stub, web.wiki
|
assert_equal wiki_stub, web.wiki
|
||||||
assert_equal 'Wiki2', web.name
|
assert_equal 'Wiki2', web.name
|
||||||
assert_equal 'wiki2', web.address
|
assert_equal 'wiki2', web.address
|
||||||
assert_equal '123', web.password
|
assert_equal '123', web.password
|
||||||
|
|
||||||
# new web should be set for maximum features enabled
|
# new web should be set for maximum features enabled
|
||||||
assert_equal :textile, web.markup
|
assert_equal :textile, web.markup
|
||||||
assert_equal '008B26', web.color
|
assert_equal '008B26', web.color
|
||||||
assert !web.safe_mode
|
assert !web.safe_mode
|
||||||
assert_equal {}, web.pages
|
assert_equal {}, web.pages
|
||||||
assert web.allow_uploads
|
assert web.allow_uploads
|
||||||
assert_equal @wiki, web.parent_wiki
|
assert_equal @wiki, web.parent_wiki
|
||||||
assert_nil web.additional_style
|
assert_nil web.additional_style
|
||||||
assert !web.published
|
assert !web.published
|
||||||
assert !web.brackets_only
|
assert !web.brackets_only
|
||||||
assert !web.count_pages
|
assert !web.count_pages
|
||||||
assert web.allow_uploads
|
assert web.allow_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def add_sample_pages
|
def add_sample_pages
|
||||||
@web.add_page(Page.new(@web, 'EverBeenInLove', 'Who am I me',
|
@web.add_page(Page.new(@web, 'EverBeenInLove', 'Who am I me',
|
||||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson'))
|
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson'))
|
||||||
@web.add_page(Page.new(@web, 'EverBeenHated', 'I am me EverBeenHated',
|
@web.add_page(Page.new(@web, 'EverBeenHated', 'I am me EverBeenHated',
|
||||||
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson'))
|
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson'))
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,116 +1,116 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'wiki_service'
|
require 'wiki_service'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
class WikiServiceTest < Test::Unit::TestCase
|
class WikiServiceTest < Test::Unit::TestCase
|
||||||
|
|
||||||
# Clean the test storage directory before the run
|
# Clean the test storage directory before the run
|
||||||
unless defined? @@storage_cleaned
|
unless defined? @@storage_cleaned
|
||||||
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.command_log'])
|
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.command_log'])
|
||||||
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.snapshot'])
|
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.snapshot'])
|
||||||
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.tex'])
|
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.tex'])
|
||||||
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.zip'])
|
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.zip'])
|
||||||
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.pdf'])
|
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/*.pdf'])
|
||||||
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/instiki/*'])
|
FileUtils.rm(Dir[RAILS_ROOT + '/storage/test/instiki/*'])
|
||||||
@@cleaned_storage = true
|
@@cleaned_storage = true
|
||||||
WikiService.instance.setup('pswd', 'Wiki', 'wiki')
|
WikiService.instance.setup('pswd', 'Wiki', 'wiki')
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@s = WikiService.instance
|
@s = WikiService.instance
|
||||||
@s.create_web 'Instiki', 'instiki'
|
@s.create_web 'Instiki', 'instiki'
|
||||||
@web = @s.webs['instiki']
|
@web = @s.webs['instiki']
|
||||||
end
|
end
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
@s.delete_web 'instiki'
|
@s.delete_web 'instiki'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_read_write_page
|
def test_read_write_page
|
||||||
@s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
@s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
||||||
Time.now, 'DavidHeinemeierHansson'
|
Time.now, 'DavidHeinemeierHansson'
|
||||||
assert_equal "Electric shocks, I love 'em", @s.read_page('instiki', 'FirstPage').content
|
assert_equal "Electric shocks, I love 'em", @s.read_page('instiki', 'FirstPage').content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_read_only_operations
|
def test_read_only_operations
|
||||||
@s.write_page 'instiki', 'TestReadOnlyOperations', 'Read only operations dont change the' +
|
@s.write_page 'instiki', 'TestReadOnlyOperations', 'Read only operations dont change the' +
|
||||||
'state of any object, and therefore should not be logged by Madeleine!',
|
'state of any object, and therefore should not be logged by Madeleine!',
|
||||||
Time.now, 'AlexeyVerkhovsky'
|
Time.now, 'AlexeyVerkhovsky'
|
||||||
|
|
||||||
assert_doesnt_change_state_or_log :authenticate, 'pswd'
|
assert_doesnt_change_state_or_log :authenticate, 'pswd'
|
||||||
assert_doesnt_change_state_or_log :read_page, 'instiki', 'TestReadOnlyOperations'
|
assert_doesnt_change_state_or_log :read_page, 'instiki', 'TestReadOnlyOperations'
|
||||||
assert_doesnt_change_state_or_log :setup?
|
assert_doesnt_change_state_or_log :setup?
|
||||||
assert_doesnt_change_state_or_log :webs
|
assert_doesnt_change_state_or_log :webs
|
||||||
|
|
||||||
@s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
@s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
||||||
Time.now, 'DavidHeinemeierHansson'
|
Time.now, 'DavidHeinemeierHansson'
|
||||||
assert_equal "Electric shocks, I love 'em", @s.read_page('instiki', 'FirstPage').content
|
assert_equal "Electric shocks, I love 'em", @s.read_page('instiki', 'FirstPage').content
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_aborted_transaction
|
def test_aborted_transaction
|
||||||
@s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
@s.write_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
||||||
10.minutes.ago, 'DavidHeinemeierHansson'
|
10.minutes.ago, 'DavidHeinemeierHansson'
|
||||||
|
|
||||||
assert_doesnt_change_state('revise_page with unchanged content') {
|
assert_doesnt_change_state('revise_page with unchanged content') {
|
||||||
begin
|
begin
|
||||||
@s.revise_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
@s.revise_page 'instiki', 'FirstPage', "Electric shocks, I love 'em",
|
||||||
Time.now, 'DavidHeinemeierHansson'
|
Time.now, 'DavidHeinemeierHansson'
|
||||||
fail 'Expected Instiki::ValidationError not raised'
|
fail 'Expected Instiki::ValidationError not raised'
|
||||||
rescue Instiki::ValidationError
|
rescue Instiki::ValidationError
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_file_yard
|
def test_file_yard
|
||||||
file_yard = @s.file_yard(@web)
|
file_yard = @s.file_yard(@web)
|
||||||
assert_equal FileYard, file_yard.class
|
assert_equal FileYard, file_yard.class
|
||||||
assert_equal(@s.storage_path + '/instiki', file_yard.files_path)
|
assert_equal(@s.storage_path + '/instiki', file_yard.files_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Checks that a method call or a block doesn;t change the persisted state of the wiki
|
# Checks that a method call or a block doesn;t change the persisted state of the wiki
|
||||||
# Usage:
|
# Usage:
|
||||||
# assert_doesnt_change_state :read_page, 'instiki', 'TestReadOnlyOperations'
|
# assert_doesnt_change_state :read_page, 'instiki', 'TestReadOnlyOperations'
|
||||||
# or
|
# or
|
||||||
# assert_doesnt_change_state {|wiki| wiki.webs}
|
# assert_doesnt_change_state {|wiki| wiki.webs}
|
||||||
|
|
||||||
def assert_doesnt_change_state(method, *args, &block)
|
def assert_doesnt_change_state(method, *args, &block)
|
||||||
_assert_doesnt_change_state(including_command_log = false, method, *args, &block)
|
_assert_doesnt_change_state(including_command_log = false, method, *args, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Same as assert_doesnt_change_state, but also asserts that no vommand log is generated
|
# Same as assert_doesnt_change_state, but also asserts that no vommand log is generated
|
||||||
def assert_doesnt_change_state_or_log(method, *args, &block)
|
def assert_doesnt_change_state_or_log(method, *args, &block)
|
||||||
_assert_doesnt_change_state(including_command_log = true, method, *args, &block)
|
_assert_doesnt_change_state(including_command_log = true, method, *args, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def _assert_doesnt_change_state(including_log, method, *args)
|
def _assert_doesnt_change_state(including_log, method, *args)
|
||||||
WikiService.snapshot
|
WikiService.snapshot
|
||||||
last_snapshot_before = last_snapshot
|
last_snapshot_before = last_snapshot
|
||||||
|
|
||||||
if block_given?
|
if block_given?
|
||||||
yield @s
|
yield @s
|
||||||
else
|
else
|
||||||
@s.send(method, *args)
|
@s.send(method, *args)
|
||||||
end
|
end
|
||||||
|
|
||||||
if including_log
|
if including_log
|
||||||
command_logs = Dir[RAILS_ROOT + 'storage/test/*.command_log']
|
command_logs = Dir[RAILS_ROOT + 'storage/test/*.command_log']
|
||||||
assert command_logs.empty?, "Calls to #{method} should not be logged"
|
assert command_logs.empty?, "Calls to #{method} should not be logged"
|
||||||
end
|
end
|
||||||
|
|
||||||
last_snapshot_after = last_snapshot
|
last_snapshot_after = last_snapshot
|
||||||
assert last_snapshot_before == last_snapshot_after,
|
assert last_snapshot_before == last_snapshot_after,
|
||||||
'Calls to #{method} should not change the state of any persisted object'
|
'Calls to #{method} should not change the state of any persisted object'
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_snapshot
|
def last_snapshot
|
||||||
snapshots = Dir[RAILS_ROOT + '/storage/test/*.snapshot']
|
snapshots = Dir[RAILS_ROOT + '/storage/test/*.snapshot']
|
||||||
assert !snapshots.empty?, "No snapshots found at #{RAILS_ROOT}/storage/test/"
|
assert !snapshots.empty?, "No snapshots found at #{RAILS_ROOT}/storage/test/"
|
||||||
File.read(snapshots.last)
|
File.read(snapshots.last)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#!/bin/env ruby -w
|
#!/bin/env ruby -w
|
||||||
|
|
||||||
require File.dirname(__FILE__) + '/../test_helper'
|
require File.dirname(__FILE__) + '/../test_helper'
|
||||||
require 'wiki_words'
|
require 'wiki_words'
|
||||||
|
|
||||||
class WikiWordsTest < Test::Unit::TestCase
|
class WikiWordsTest < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_utf8_characters_in_wiki_word
|
def test_utf8_characters_in_wiki_word
|
||||||
assert_equal "Æåle Øen", WikiWords.separate("ÆåleØen")
|
assert_equal "Æåle Øen", WikiWords.separate("ÆåleØen")
|
||||||
assert_equal "ÆÅØle Øen", WikiWords.separate("ÆÅØleØen")
|
assert_equal "ÆÅØle Øen", WikiWords.separate("ÆÅØleØen")
|
||||||
assert_equal "Æe ÅØle Øen", WikiWords.separate("ÆeÅØleØen")
|
assert_equal "Æe ÅØle Øen", WikiWords.separate("ÆeÅØleØen")
|
||||||
assert_equal "Legetøj", WikiWords.separate("Legetøj")
|
assert_equal "Legetøj", WikiWords.separate("Legetøj")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
198
vendor/bluecloth-1.0.0/README
vendored
198
vendor/bluecloth-1.0.0/README
vendored
|
@ -1,99 +1,99 @@
|
||||||
|
|
||||||
BlueCloth
|
BlueCloth
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Version 1.0.0 - 2004/08/24
|
Version 1.0.0 - 2004/08/24
|
||||||
|
|
||||||
Original version by John Gruber <http://daringfireball.net/>.
|
Original version by John Gruber <http://daringfireball.net/>.
|
||||||
Ruby port by Michael Granger <http://www.deveiate.org/>.
|
Ruby port by Michael Granger <http://www.deveiate.org/>.
|
||||||
|
|
||||||
BlueCloth is a Ruby implementation of [Markdown][1], a text-to-HTML conversion
|
BlueCloth is a Ruby implementation of [Markdown][1], a text-to-HTML conversion
|
||||||
tool for web writers. To quote from the project page: Markdown allows you to
|
tool for web writers. To quote from the project page: Markdown allows you to
|
||||||
write using an easy-to-read, easy-to-write plain text format, then convert it to
|
write using an easy-to-read, easy-to-write plain text format, then convert it to
|
||||||
structurally valid XHTML (or HTML).
|
structurally valid XHTML (or HTML).
|
||||||
|
|
||||||
It borrows a naming convention and several helpings of interface from
|
It borrows a naming convention and several helpings of interface from
|
||||||
[Redcloth][2], [Why the Lucky Stiff][3]'s processor for a similar text-to-HTML
|
[Redcloth][2], [Why the Lucky Stiff][3]'s processor for a similar text-to-HTML
|
||||||
conversion syntax called [Textile][4].
|
conversion syntax called [Textile][4].
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
You can install this module either by running the included `install.rb` script,
|
You can install this module either by running the included `install.rb` script,
|
||||||
or by simply copying `lib/bluecloth.rb` to a directory in your load path.
|
or by simply copying `lib/bluecloth.rb` to a directory in your load path.
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
------------
|
------------
|
||||||
|
|
||||||
BlueCloth uses the `StringScanner` class from the `strscan` library, which comes
|
BlueCloth uses the `StringScanner` class from the `strscan` library, which comes
|
||||||
with Ruby 1.8.x and later or may be downloaded from the RAA for earlier
|
with Ruby 1.8.x and later or may be downloaded from the RAA for earlier
|
||||||
versions, and the `logger` library, which is also included in 1.8.x and later.
|
versions, and the `logger` library, which is also included in 1.8.x and later.
|
||||||
|
|
||||||
|
|
||||||
Example Usage
|
Example Usage
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The BlueCloth class is a subclass of Ruby's String, and can be used thusly:
|
The BlueCloth class is a subclass of Ruby's String, and can be used thusly:
|
||||||
|
|
||||||
bc = BlueCloth::new( str )
|
bc = BlueCloth::new( str )
|
||||||
puts bc.to_html
|
puts bc.to_html
|
||||||
|
|
||||||
This `README` file is an example of Markdown syntax. The sample program
|
This `README` file is an example of Markdown syntax. The sample program
|
||||||
`bluecloth` in the `bin/` directory can be used to convert this (or any other)
|
`bluecloth` in the `bin/` directory can be used to convert this (or any other)
|
||||||
file with Markdown syntax into HTML:
|
file with Markdown syntax into HTML:
|
||||||
|
|
||||||
$ bin/bluecloth README > README.html
|
$ bin/bluecloth README > README.html
|
||||||
|
|
||||||
|
|
||||||
Acknowledgements
|
Acknowledgements
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
This library is a port of the canonical Perl one, and so owes most of its
|
This library is a port of the canonical Perl one, and so owes most of its
|
||||||
functionality to its author, John Gruber. The bugs in this code are most
|
functionality to its author, John Gruber. The bugs in this code are most
|
||||||
certainly an artifact of my porting it and not an artifact of the excellent code
|
certainly an artifact of my porting it and not an artifact of the excellent code
|
||||||
from which it is derived.
|
from which it is derived.
|
||||||
|
|
||||||
It also, as mentioned before, borrows its API liberally from RedCloth, both for
|
It also, as mentioned before, borrows its API liberally from RedCloth, both for
|
||||||
compatibility's sake, and because I think Why's code is beautiful. His excellent
|
compatibility's sake, and because I think Why's code is beautiful. His excellent
|
||||||
code and peerless prose have been an inspiration to me, and this module is
|
code and peerless prose have been an inspiration to me, and this module is
|
||||||
intended as the sincerest flattery.
|
intended as the sincerest flattery.
|
||||||
|
|
||||||
Also contributing to any success this module may enjoy are those among my peers
|
Also contributing to any success this module may enjoy are those among my peers
|
||||||
who have taken the time to help out, either by submitting patches, testing, or
|
who have taken the time to help out, either by submitting patches, testing, or
|
||||||
offering suggestions and review:
|
offering suggestions and review:
|
||||||
|
|
||||||
* Martin Chase <stillflame@FaerieMUD.org>
|
* Martin Chase <stillflame@FaerieMUD.org>
|
||||||
* Florian Gross <flgr@ccan.de>
|
* Florian Gross <flgr@ccan.de>
|
||||||
|
|
||||||
|
|
||||||
Author/Legal
|
Author/Legal
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Original version:
|
Original version:
|
||||||
Copyright (c) 2003-2004 John Gruber
|
Copyright (c) 2003-2004 John Gruber
|
||||||
<http://daringfireball.net/>
|
<http://daringfireball.net/>
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Ruby version:
|
Ruby version:
|
||||||
Copyright (c) 2004 The FaerieMUD Consortium
|
Copyright (c) 2004 The FaerieMUD Consortium
|
||||||
|
|
||||||
BlueCloth is free software; you can redistribute it and/or modify it under the
|
BlueCloth is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the GNU General Public License as published by the Free Software
|
terms of the GNU General Public License as published by the Free Software
|
||||||
Foundation; either version 2 of the License, or (at your option) any later
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
version.
|
version.
|
||||||
|
|
||||||
BlueCloth is distributed in the hope that it will be useful, but WITHOUT ANY
|
BlueCloth is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
|
||||||
[1]: http://daringfireball.net/projects/markdown/
|
[1]: http://daringfireball.net/projects/markdown/
|
||||||
[2]: http://www.whytheluckystiff.net/ruby/redcloth/
|
[2]: http://www.whytheluckystiff.net/ruby/redcloth/
|
||||||
[3]: http://www.whytheluckystiff.net/
|
[3]: http://www.whytheluckystiff.net/
|
||||||
[4]: http://www.textism.com/tools/textile/
|
[4]: http://www.textism.com/tools/textile/
|
||||||
|
|
||||||
|
|
||||||
$Id: README,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
$Id: README,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
||||||
$URL: svn+ssh://svn.FaerieMUD.org/usr/local/svn/BlueCloth/trunk/README $
|
$URL: svn+ssh://svn.FaerieMUD.org/usr/local/svn/BlueCloth/trunk/README $
|
||||||
|
|
300
vendor/bluecloth-1.0.0/install.rb
vendored
300
vendor/bluecloth-1.0.0/install.rb
vendored
|
@ -1,150 +1,150 @@
|
||||||
#!/usr/bin/ruby
|
#!/usr/bin/ruby
|
||||||
#
|
#
|
||||||
# BlueCloth Module Install Script
|
# BlueCloth Module Install Script
|
||||||
# $Id: install.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
# $Id: install.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
||||||
#
|
#
|
||||||
# Thanks to Masatoshi SEKI for ideas found in his install.rb.
|
# Thanks to Masatoshi SEKI for ideas found in his install.rb.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2001-2004 The FaerieMUD Consortium.
|
# Copyright (c) 2001-2004 The FaerieMUD Consortium.
|
||||||
#
|
#
|
||||||
# This is free software. You may use, modify, and/or redistribute this
|
# This is free software. You may use, modify, and/or redistribute this
|
||||||
# software under the terms of the Perl Artistic License. (See
|
# software under the terms of the Perl Artistic License. (See
|
||||||
# http://language.perl.com/misc/Artistic.html)
|
# http://language.perl.com/misc/Artistic.html)
|
||||||
#
|
#
|
||||||
|
|
||||||
require './utils.rb'
|
require './utils.rb'
|
||||||
include UtilityFunctions
|
include UtilityFunctions
|
||||||
|
|
||||||
require 'rbconfig'
|
require 'rbconfig'
|
||||||
include Config
|
include Config
|
||||||
|
|
||||||
require 'find'
|
require 'find'
|
||||||
require 'ftools'
|
require 'ftools'
|
||||||
|
|
||||||
|
|
||||||
$version = %q$Revision: 1.1 $
|
$version = %q$Revision: 1.1 $
|
||||||
$rcsId = %q$Id: install.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
$rcsId = %q$Id: install.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
||||||
|
|
||||||
# Define required libraries
|
# Define required libraries
|
||||||
RequiredLibraries = [
|
RequiredLibraries = [
|
||||||
# libraryname, nice name, RAA URL, Download URL
|
# libraryname, nice name, RAA URL, Download URL
|
||||||
[ 'strscan', "StrScan",
|
[ 'strscan', "StrScan",
|
||||||
'http://raa.ruby-lang.org/list.rhtml?name=strscan',
|
'http://raa.ruby-lang.org/list.rhtml?name=strscan',
|
||||||
'http://i.loveruby.net/archive/strscan/strscan-0.6.7.tar.gz' ],
|
'http://i.loveruby.net/archive/strscan/strscan-0.6.7.tar.gz' ],
|
||||||
[ 'logger', "Devel-Logger",
|
[ 'logger', "Devel-Logger",
|
||||||
'http://raa.ruby-lang.org/list.rhtml?name=devel-logger',
|
'http://raa.ruby-lang.org/list.rhtml?name=devel-logger',
|
||||||
'http://rrr.jin.gr.jp/download/devel-logger-1_2_2.tar.gz' ],
|
'http://rrr.jin.gr.jp/download/devel-logger-1_2_2.tar.gz' ],
|
||||||
]
|
]
|
||||||
|
|
||||||
class Installer
|
class Installer
|
||||||
|
|
||||||
@@PrunePatterns = [
|
@@PrunePatterns = [
|
||||||
/CVS/,
|
/CVS/,
|
||||||
/~$/,
|
/~$/,
|
||||||
%r:(^|/)\.:,
|
%r:(^|/)\.:,
|
||||||
/\.tpl$/,
|
/\.tpl$/,
|
||||||
]
|
]
|
||||||
|
|
||||||
def initialize( testing=false )
|
def initialize( testing=false )
|
||||||
@ftools = (testing) ? self : File
|
@ftools = (testing) ? self : File
|
||||||
end
|
end
|
||||||
|
|
||||||
### Make the specified dirs (which can be a String or an Array of Strings)
|
### Make the specified dirs (which can be a String or an Array of Strings)
|
||||||
### with the specified mode.
|
### with the specified mode.
|
||||||
def makedirs( dirs, mode=0755, verbose=false )
|
def makedirs( dirs, mode=0755, verbose=false )
|
||||||
dirs = [ dirs ] unless dirs.is_a? Array
|
dirs = [ dirs ] unless dirs.is_a? Array
|
||||||
|
|
||||||
oldumask = File::umask
|
oldumask = File::umask
|
||||||
File::umask( 0777 - mode )
|
File::umask( 0777 - mode )
|
||||||
|
|
||||||
for dir in dirs
|
for dir in dirs
|
||||||
if @ftools == File
|
if @ftools == File
|
||||||
File::mkpath( dir, $verbose )
|
File::mkpath( dir, $verbose )
|
||||||
else
|
else
|
||||||
$stderr.puts "Make path %s with mode %o" % [ dir, mode ]
|
$stderr.puts "Make path %s with mode %o" % [ dir, mode ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
File::umask( oldumask )
|
File::umask( oldumask )
|
||||||
end
|
end
|
||||||
|
|
||||||
def install( srcfile, dstfile, mode=nil, verbose=false )
|
def install( srcfile, dstfile, mode=nil, verbose=false )
|
||||||
dstfile = File.catname(srcfile, dstfile)
|
dstfile = File.catname(srcfile, dstfile)
|
||||||
unless FileTest.exist? dstfile and File.cmp srcfile, dstfile
|
unless FileTest.exist? dstfile and File.cmp srcfile, dstfile
|
||||||
$stderr.puts " install #{srcfile} -> #{dstfile}"
|
$stderr.puts " install #{srcfile} -> #{dstfile}"
|
||||||
else
|
else
|
||||||
$stderr.puts " skipping #{dstfile}: unchanged"
|
$stderr.puts " skipping #{dstfile}: unchanged"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
public
|
public
|
||||||
|
|
||||||
def installFiles( src, dstDir, mode=0444, verbose=false )
|
def installFiles( src, dstDir, mode=0444, verbose=false )
|
||||||
directories = []
|
directories = []
|
||||||
files = []
|
files = []
|
||||||
|
|
||||||
if File.directory?( src )
|
if File.directory?( src )
|
||||||
Find.find( src ) {|f|
|
Find.find( src ) {|f|
|
||||||
Find.prune if @@PrunePatterns.find {|pat| f =~ pat}
|
Find.prune if @@PrunePatterns.find {|pat| f =~ pat}
|
||||||
next if f == src
|
next if f == src
|
||||||
|
|
||||||
if FileTest.directory?( f )
|
if FileTest.directory?( f )
|
||||||
directories << f.gsub( /^#{src}#{File::Separator}/, '' )
|
directories << f.gsub( /^#{src}#{File::Separator}/, '' )
|
||||||
next
|
next
|
||||||
|
|
||||||
elsif FileTest.file?( f )
|
elsif FileTest.file?( f )
|
||||||
files << f.gsub( /^#{src}#{File::Separator}/, '' )
|
files << f.gsub( /^#{src}#{File::Separator}/, '' )
|
||||||
|
|
||||||
else
|
else
|
||||||
Find.prune
|
Find.prune
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
files << File.basename( src )
|
files << File.basename( src )
|
||||||
src = File.dirname( src )
|
src = File.dirname( src )
|
||||||
end
|
end
|
||||||
|
|
||||||
dirs = [ dstDir ]
|
dirs = [ dstDir ]
|
||||||
dirs |= directories.collect {|d| File.join(dstDir,d)}
|
dirs |= directories.collect {|d| File.join(dstDir,d)}
|
||||||
makedirs( dirs, 0755, verbose )
|
makedirs( dirs, 0755, verbose )
|
||||||
files.each {|f|
|
files.each {|f|
|
||||||
srcfile = File.join(src,f)
|
srcfile = File.join(src,f)
|
||||||
dstfile = File.dirname(File.join( dstDir,f ))
|
dstfile = File.dirname(File.join( dstDir,f ))
|
||||||
|
|
||||||
if verbose
|
if verbose
|
||||||
if mode
|
if mode
|
||||||
$stderr.puts "Install #{srcfile} -> #{dstfile} (mode %o)" % mode
|
$stderr.puts "Install #{srcfile} -> #{dstfile} (mode %o)" % mode
|
||||||
else
|
else
|
||||||
$stderr.puts "Install #{srcfile} -> #{dstfile}"
|
$stderr.puts "Install #{srcfile} -> #{dstfile}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ftools.install( srcfile, dstfile, mode, verbose )
|
@ftools.install( srcfile, dstfile, mode, verbose )
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if $0 == __FILE__
|
if $0 == __FILE__
|
||||||
header "BlueCloth Installer #$version"
|
header "BlueCloth Installer #$version"
|
||||||
|
|
||||||
for lib in RequiredLibraries
|
for lib in RequiredLibraries
|
||||||
testForRequiredLibrary( *lib )
|
testForRequiredLibrary( *lib )
|
||||||
end
|
end
|
||||||
|
|
||||||
viewOnly = ARGV.include? '-n'
|
viewOnly = ARGV.include? '-n'
|
||||||
verbose = ARGV.include? '-v'
|
verbose = ARGV.include? '-v'
|
||||||
|
|
||||||
debugMsg "Sitelibdir = '#{CONFIG['sitelibdir']}'"
|
debugMsg "Sitelibdir = '#{CONFIG['sitelibdir']}'"
|
||||||
sitelibdir = CONFIG['sitelibdir']
|
sitelibdir = CONFIG['sitelibdir']
|
||||||
debugMsg "Sitearchdir = '#{CONFIG['sitearchdir']}'"
|
debugMsg "Sitearchdir = '#{CONFIG['sitearchdir']}'"
|
||||||
sitearchdir = CONFIG['sitearchdir']
|
sitearchdir = CONFIG['sitearchdir']
|
||||||
|
|
||||||
message "Installing\n"
|
message "Installing\n"
|
||||||
i = Installer.new( viewOnly )
|
i = Installer.new( viewOnly )
|
||||||
i.installFiles( "lib", sitelibdir, 0444, verbose )
|
i.installFiles( "lib", sitelibdir, 0444, verbose )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2288
vendor/bluecloth-1.0.0/lib/bluecloth.rb
vendored
2288
vendor/bluecloth-1.0.0/lib/bluecloth.rb
vendored
File diff suppressed because it is too large
Load diff
234
vendor/bluecloth-1.0.0/test.rb
vendored
234
vendor/bluecloth-1.0.0/test.rb
vendored
|
@ -1,117 +1,117 @@
|
||||||
#!/usr/bin/ruby
|
#!/usr/bin/ruby
|
||||||
#
|
#
|
||||||
# Test suite for BlueCloth classes
|
# Test suite for BlueCloth classes
|
||||||
# $Id: test.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
# $Id: test.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
||||||
#
|
#
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
$basedir = File::dirname( __FILE__ )
|
$basedir = File::dirname( __FILE__ )
|
||||||
["lib", "tests", "redist"].each do |subdir|
|
["lib", "tests", "redist"].each do |subdir|
|
||||||
$LOAD_PATH.unshift File::join( $basedir, subdir )
|
$LOAD_PATH.unshift File::join( $basedir, subdir )
|
||||||
end
|
end
|
||||||
|
|
||||||
require "#{$basedir}/utils"
|
require "#{$basedir}/utils"
|
||||||
include UtilityFunctions
|
include UtilityFunctions
|
||||||
}
|
}
|
||||||
|
|
||||||
verboseOff {
|
verboseOff {
|
||||||
require 'bctestcase'
|
require 'bctestcase'
|
||||||
require 'find'
|
require 'find'
|
||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'test/unit/testsuite'
|
require 'test/unit/testsuite'
|
||||||
require 'test/unit/ui/console/testrunner'
|
require 'test/unit/ui/console/testrunner'
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Turn off output buffering
|
# Turn off output buffering
|
||||||
$stderr.sync = $stdout.sync = true
|
$stderr.sync = $stdout.sync = true
|
||||||
$DebugPattern = nil
|
$DebugPattern = nil
|
||||||
|
|
||||||
# Initialize variables
|
# Initialize variables
|
||||||
safelevel = 0
|
safelevel = 0
|
||||||
patterns = []
|
patterns = []
|
||||||
requires = []
|
requires = []
|
||||||
|
|
||||||
# Parse command-line switches
|
# Parse command-line switches
|
||||||
ARGV.options {|oparser|
|
ARGV.options {|oparser|
|
||||||
oparser.banner = "Usage: #$0 [options] [TARGETS]\n"
|
oparser.banner = "Usage: #$0 [options] [TARGETS]\n"
|
||||||
|
|
||||||
oparser.on( "--debug[=PATTERN]", "-d[=PATTERN]", String,
|
oparser.on( "--debug[=PATTERN]", "-d[=PATTERN]", String,
|
||||||
"Turn debugging on (for tests which match PATTERN)" ) {|arg|
|
"Turn debugging on (for tests which match PATTERN)" ) {|arg|
|
||||||
if arg
|
if arg
|
||||||
$DebugPattern = Regexp::new( arg )
|
$DebugPattern = Regexp::new( arg )
|
||||||
puts "Turned debugging on for %p." % $DebugPattern
|
puts "Turned debugging on for %p." % $DebugPattern
|
||||||
else
|
else
|
||||||
$DEBUG = true
|
$DEBUG = true
|
||||||
debugMsg "Turned debugging on globally."
|
debugMsg "Turned debugging on globally."
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
oparser.on( "--verbose", "-v", TrueClass, "Make progress verbose" ) {
|
oparser.on( "--verbose", "-v", TrueClass, "Make progress verbose" ) {
|
||||||
$VERBOSE = true
|
$VERBOSE = true
|
||||||
debugMsg "Turned verbose on."
|
debugMsg "Turned verbose on."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Handle the 'help' option
|
# Handle the 'help' option
|
||||||
oparser.on( "--help", "-h", "Display this text." ) {
|
oparser.on( "--help", "-h", "Display this text." ) {
|
||||||
$stderr.puts oparser
|
$stderr.puts oparser
|
||||||
exit!(0)
|
exit!(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
oparser.parse!
|
oparser.parse!
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parse test patterns
|
# Parse test patterns
|
||||||
ARGV.each {|pat| patterns << Regexp::new( pat, Regexp::IGNORECASE )}
|
ARGV.each {|pat| patterns << Regexp::new( pat, Regexp::IGNORECASE )}
|
||||||
$stderr.puts "#{patterns.length} patterns given on the command line"
|
$stderr.puts "#{patterns.length} patterns given on the command line"
|
||||||
|
|
||||||
### Load all the tests from the tests dir
|
### Load all the tests from the tests dir
|
||||||
Find.find("#{$basedir}/tests") {|file|
|
Find.find("#{$basedir}/tests") {|file|
|
||||||
Find.prune if /\/\./ =~ file or /~$/ =~ file
|
Find.prune if /\/\./ =~ file or /~$/ =~ file
|
||||||
Find.prune if /TEMPLATE/ =~ file
|
Find.prune if /TEMPLATE/ =~ file
|
||||||
next if File.stat( file ).directory?
|
next if File.stat( file ).directory?
|
||||||
|
|
||||||
unless patterns.empty?
|
unless patterns.empty?
|
||||||
Find.prune unless patterns.find {|pat| pat =~ file}
|
Find.prune unless patterns.find {|pat| pat =~ file}
|
||||||
end
|
end
|
||||||
|
|
||||||
debugMsg "Considering '%s': " % file
|
debugMsg "Considering '%s': " % file
|
||||||
next unless file =~ /\.tests.rb$/
|
next unless file =~ /\.tests.rb$/
|
||||||
debugMsg "Requiring '%s'..." % file
|
debugMsg "Requiring '%s'..." % file
|
||||||
require "#{file}"
|
require "#{file}"
|
||||||
requires << file
|
requires << file
|
||||||
}
|
}
|
||||||
|
|
||||||
$stderr.puts "Required #{requires.length} files."
|
$stderr.puts "Required #{requires.length} files."
|
||||||
unless patterns.empty?
|
unless patterns.empty?
|
||||||
$stderr.puts "[" + requires.sort.join( ", " ) + "]"
|
$stderr.puts "[" + requires.sort.join( ", " ) + "]"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Build the test suite
|
# Build the test suite
|
||||||
class BlueClothTests
|
class BlueClothTests
|
||||||
class << self
|
class << self
|
||||||
def suite
|
def suite
|
||||||
suite = Test::Unit::TestSuite.new( "BlueCloth" )
|
suite = Test::Unit::TestSuite.new( "BlueCloth" )
|
||||||
|
|
||||||
if suite.respond_to?( :add )
|
if suite.respond_to?( :add )
|
||||||
ObjectSpace.each_object( Class ) {|klass|
|
ObjectSpace.each_object( Class ) {|klass|
|
||||||
suite.add( klass.suite ) if klass < BlueCloth::TestCase
|
suite.add( klass.suite ) if klass < BlueCloth::TestCase
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ObjectSpace.each_object( Class ) {|klass|
|
ObjectSpace.each_object( Class ) {|klass|
|
||||||
suite << klass.suite if klass < BlueCloth::TestCase
|
suite << klass.suite if klass < BlueCloth::TestCase
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
return suite
|
return suite
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
$SAFE = safelevel
|
$SAFE = safelevel
|
||||||
Test::Unit::UI::Console::TestRunner.new( BlueClothTests ).start
|
Test::Unit::UI::Console::TestRunner.new( BlueClothTests ).start
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
142
vendor/bluecloth-1.0.0/tests/00_Class.tests.rb
vendored
142
vendor/bluecloth-1.0.0/tests/00_Class.tests.rb
vendored
|
@ -1,71 +1,71 @@
|
||||||
#!/usr/bin/ruby
|
#!/usr/bin/ruby
|
||||||
#
|
#
|
||||||
# Unit test for the BlueCloth class object
|
# Unit test for the BlueCloth class object
|
||||||
# $Id: 00_Class.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
# $Id: 00_Class.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 2004 The FaerieMUD Consortium.
|
# Copyright (c) 2004 The FaerieMUD Consortium.
|
||||||
#
|
#
|
||||||
|
|
||||||
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
||||||
basedir = File::dirname( __FILE__ )
|
basedir = File::dirname( __FILE__ )
|
||||||
require File::join( basedir, 'bctestcase' )
|
require File::join( basedir, 'bctestcase' )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
### This test case tests ...
|
### This test case tests ...
|
||||||
class BlueClothClassTestCase < BlueCloth::TestCase
|
class BlueClothClassTestCase < BlueCloth::TestCase
|
||||||
|
|
||||||
TestString = "foo"
|
TestString = "foo"
|
||||||
|
|
||||||
def test_00_class_constant
|
def test_00_class_constant
|
||||||
printTestHeader "BlueCloth: Class Constant"
|
printTestHeader "BlueCloth: Class Constant"
|
||||||
|
|
||||||
assert Object::constants.include?( "BlueCloth" ),
|
assert Object::constants.include?( "BlueCloth" ),
|
||||||
"No BlueCloth constant in Object"
|
"No BlueCloth constant in Object"
|
||||||
assert_instance_of Class, BlueCloth
|
assert_instance_of Class, BlueCloth
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_01_instantiation
|
def test_01_instantiation
|
||||||
printTestHeader "BlueCloth: Instantiation"
|
printTestHeader "BlueCloth: Instantiation"
|
||||||
rval = nil
|
rval = nil
|
||||||
|
|
||||||
# With no argument... ("")
|
# With no argument... ("")
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
rval = BlueCloth::new
|
rval = BlueCloth::new
|
||||||
}
|
}
|
||||||
assert_instance_of BlueCloth, rval
|
assert_instance_of BlueCloth, rval
|
||||||
assert_kind_of String, rval
|
assert_kind_of String, rval
|
||||||
assert_equal "", rval
|
assert_equal "", rval
|
||||||
|
|
||||||
# String argument
|
# String argument
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
rval = BlueCloth::new TestString
|
rval = BlueCloth::new TestString
|
||||||
}
|
}
|
||||||
assert_instance_of BlueCloth, rval
|
assert_instance_of BlueCloth, rval
|
||||||
assert_kind_of String, rval
|
assert_kind_of String, rval
|
||||||
assert_equal TestString, rval
|
assert_equal TestString, rval
|
||||||
|
|
||||||
addSetupBlock {
|
addSetupBlock {
|
||||||
debugMsg "Creating a new BlueCloth"
|
debugMsg "Creating a new BlueCloth"
|
||||||
@obj = BlueCloth::new( TestString )
|
@obj = BlueCloth::new( TestString )
|
||||||
}
|
}
|
||||||
addTeardownBlock {
|
addTeardownBlock {
|
||||||
@obj = nil
|
@obj = nil
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_02_duplication
|
def test_02_duplication
|
||||||
printTestHeader "BlueCloth: Duplication"
|
printTestHeader "BlueCloth: Duplication"
|
||||||
rval = nil
|
rval = nil
|
||||||
|
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
rval = @obj.dup
|
rval = @obj.dup
|
||||||
}
|
}
|
||||||
assert_instance_of BlueCloth, rval
|
assert_instance_of BlueCloth, rval
|
||||||
assert_kind_of String, rval
|
assert_kind_of String, rval
|
||||||
assert_equal TestString, rval
|
assert_equal TestString, rval
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
3054
vendor/bluecloth-1.0.0/tests/05_Markdown.tests.rb
vendored
3054
vendor/bluecloth-1.0.0/tests/05_Markdown.tests.rb
vendored
File diff suppressed because it is too large
Load diff
114
vendor/bluecloth-1.0.0/tests/10_Bug.tests.rb
vendored
114
vendor/bluecloth-1.0.0/tests/10_Bug.tests.rb
vendored
|
@ -1,57 +1,57 @@
|
||||||
#!/usr/bin/ruby
|
#!/usr/bin/ruby
|
||||||
#
|
#
|
||||||
# Unit test for bugs found in BlueCloth
|
# Unit test for bugs found in BlueCloth
|
||||||
# $Id: 10_Bug.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
# $Id: 10_Bug.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 2004 The FaerieMUD Consortium.
|
# Copyright (c) 2004 The FaerieMUD Consortium.
|
||||||
#
|
#
|
||||||
|
|
||||||
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
||||||
basedir = File::dirname( __FILE__ )
|
basedir = File::dirname( __FILE__ )
|
||||||
require File::join( basedir, 'bctestcase' )
|
require File::join( basedir, 'bctestcase' )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
require 'timeout'
|
require 'timeout'
|
||||||
|
|
||||||
### This test case tests ...
|
### This test case tests ...
|
||||||
class BugsTestCase < BlueCloth::TestCase
|
class BugsTestCase < BlueCloth::TestCase
|
||||||
BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) )
|
BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) )
|
||||||
|
|
||||||
### Test to be sure the README file can be transformed.
|
### Test to be sure the README file can be transformed.
|
||||||
def test_00_slow_block_regex
|
def test_00_slow_block_regex
|
||||||
contents = File::read( File::join(BaseDir,"README") )
|
contents = File::read( File::join(BaseDir,"README") )
|
||||||
bcobj = BlueCloth::new( contents )
|
bcobj = BlueCloth::new( contents )
|
||||||
|
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
timeout( 2 ) do
|
timeout( 2 ) do
|
||||||
bcobj.to_html
|
bcobj.to_html
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
### :TODO: Add more documents and test their transforms.
|
### :TODO: Add more documents and test their transforms.
|
||||||
|
|
||||||
def test_10_regexp_engine_overflow_bug
|
def test_10_regexp_engine_overflow_bug
|
||||||
contents = File::read( File::join(BaseDir,"tests/data/re-overflow.txt") )
|
contents = File::read( File::join(BaseDir,"tests/data/re-overflow.txt") )
|
||||||
bcobj = BlueCloth::new( contents )
|
bcobj = BlueCloth::new( contents )
|
||||||
|
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
bcobj.to_html
|
bcobj.to_html
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_15_regexp_engine_overflow_bug2
|
def test_15_regexp_engine_overflow_bug2
|
||||||
contents = File::read( File::join(BaseDir,"tests/data/re-overflow2.txt") )
|
contents = File::read( File::join(BaseDir,"tests/data/re-overflow2.txt") )
|
||||||
bcobj = BlueCloth::new( contents )
|
bcobj = BlueCloth::new( contents )
|
||||||
|
|
||||||
assert_nothing_raised {
|
assert_nothing_raised {
|
||||||
bcobj.to_html
|
bcobj.to_html
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue