Line ending cleanup. Most of these are svn propsets which should make

the files check out appropriately in the future.  The three files in
app/models had inconsitent line endings, so they had to be fixed by
hand.
This commit is contained in:
Ben Bleything 2005-08-15 19:17:32 +00:00
parent 4849ca62fb
commit b29c59e470
14 changed files with 1578 additions and 1578 deletions

372
CHANGELOG
View file

@ -1,186 +1,186 @@
* 0.10.2:
Upgraded to Rails 0.13.1
Fixed HTML export
Added layout=no option to the export_html action (it exports page contents processed
by the markup engine, but without the default layout - so that they can be wrapped in
some other layout)
<nowiki> tag can span several lines (before it was applied when both opening and closing
tags were on the same line only)
Resolved the "endless redirection loop" condition and otherwise improved handling of
errors in the rendering engines
Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
* 0.10.1:
Upgraded Rails to 0.12.0
Upgraded rubyzip to version 0.5.8
BlueCloth is back (RedCloth didn't do pure Markdown well enough)
Handling of line breaks in Textile is as in 0.9 (inserts <br/> tag)
Fixed HTML export (to enclose the output in <html> tags, include the stylesheet etc)
Corrected some compatibility issues with storages from earlier Instiki versions
Some other bug fixes
* 0.10.0:
Ported to ActionPack
RedCloth 3.0.3
BlueCloth is phased out, Markdown is rendered by RedCloth
Mix markup option understands both Textile and Markdown on the same page
Instiki can serve static content (such as HTML or plain-text files) from ./public
directory
Much friendlier admin interface
Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
"textile link":LinkToSomePlace will not look insane.
RSS feeds accept query parameters, sush as
http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
RSS feed with page contents for a password-protected web behaves as follows:
if the web is published, RSS feed links to the published version of the web
otherwise, the feed is not available
Madeleine will check every hour if there are new commands in the log or 24 hours have
passed since last snapshot, and take snapshot if either of these conditions is true
Madeleine will also not log read-only operations, resulting in a better performance
Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
Wiki search handles multibyte (UTF-8) characters correctly
Local hyperlinks in published pages point to published pages [Michael DeHaan]
Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
restart
Fixed parsing of URIs with a port number (http://someplace.org:8080)
Instiki will not fork itself on a *nix, unless explicitly asked to
Instiki can bind to IPs other than 127.0.0.1 (command-line option)
Revisions that do not change anything on the page are rejected
Automated tests for all controller actions
category: lines are presented as links to "All Pages" for relevant categories
Search looks at page titles, as well as content
Multiple other usability enhancements and bug fixes
* 0.9.2:
Rollback takes the user to an edit form. The form has to be submitted for the change to
take place.
Changed to use inline style on published pages
Fixed "forward in time" on the last revision before current page
Instiki won't log bogus error messages when creating a new Wiki
Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
Madeleine upgraded to 0.7.1
Madeleine snapshots are compressed
Packaged as a gem
* 0.9.1:
Added performance improvements for updating existing pages
Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
* 0.9.0:
Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
Added include other page content with [[!include TableOfContents]] [Mark Reid]
Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
Added logging of IP address for authors (who's behind the rollback wars)
Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
Added option to use bracket-style wiki links only (and hence ban WikiWords)
Added command-line option to specify different storage path
Added print view without navigation
Added character and page (2275 characters including spaces) counter (important for student papers)
Off by default, activate it on the Edit Web screen
Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
Use the home page as a table of contents with a unordered list to control sections
Added limit of 15 to the number of pages included in RSS feed
Moved static parts of stylesheet to separate file [Lau TŒrnskov]
Fixed better semantics for revision movement [Ryan Singer]
Fixed color diffs to work much better [Xen/Mertz/Atkins]
Fixed performance problems for All Pages list [Dennis Mertz]
Fixed lots of rendering bugs [Mark Reid]
Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
* 0.8.9:
Added color diffs to see changes between revisions [Bill Atkins]
They're aren't quite perfect yet as new paragraphs split the <ins> tags (hence 0.8.9, not 0.9.0)
Added redirect to edit if content of page generates an error
(so the page doesn't become unusable on bugs in the markup engines)
Fixed update Web with different address bug [Denis Metz]
Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
* 0.8.5:
Instiki can now serve as a CMS by running a password-protected web with a published front
Added version check at startup (Instiki needs Ruby 1.8.1)
* 0.8.1:
Actually included RedCloth 2.0.7 in the release
* 0.8.0:
NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
Many thanks to Guan Yang for building the higher- and lower-case lookup tables
And thanks to Simon Arnaud for the initial patch that got the work started
Changed charset to UTF-8
Cut down on command-line options and replaced them with an per-web config screen
Added option to extend the stylesheet on a per-web basis to tweak the look in details
Added simple color options for variety
Added option to add/remove password protection on each web
Added the wiki name of the author locking a given page (instead of just "someone")
Removed single/multi-web distinction -- all Instikis are now multi-web
Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
Keeps the author cookie forever, so you don't have to enter your name again and again
Fixed XHTML so it validates [Bruce D'Arcus]
Authors are no longer listed under orphan pages
Added export to markup (great for backups, potentially for switching wiki engine)
Don't link wiki words that proceeds from either /, = or ?
(http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
Accessing an unexisting page redirects to a different url (/new/PageName)
Increased snapshot time to just once a day (cuts down on disk storage requirements)
Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
Added convinient redirect from /wiki/ to /wiki/show/HomePage
Fixed BlueCloth bug with backticks at start of line
Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
* 0.7.0:
Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
Added password-login through URL (so you can subscribe to feed on a protected web)
Added web passwords to the feed links for protected webs, so they work without manual login
Added the web name in small letters above all pages within a web
Polished authors and recently revised
Updated to RedCloth 2.0.6
Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
Changed searching to be case insensitive
Changed HomePage to display the name of the web instead
Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
Fixed broken recently revised
* 0.6.0:
Fixed Windows compatibility [Florian]
Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
Added export entire web as HTML in a zip file
Added RSS feeds
Added proper getops support for the growing number of options [Florian]
Added safe mode that forbids style options in RedCloth [Florian]
Updated RedCloth to 2.0.5
* 0.5.0:
NOTE: 0.5.0 is NOT compatible with databases from earlier versions
Added revisions
Added multiple webs
Added password protection for webs on multi-web setups
Added the notion of authors (that are saved in a cookie)
Added command-line option for not running as a Daemon on Unix
* 0.3.1:
Added option to escape wiki words with \
* 0.3.0:
Brought all files into common style (including Textile help on the edit page)
Added page locking (if someone already is editing a page there's a warning)
Added daemon abilities on Unix (keep Instiki running after you close the terminal)
Made port 2500 the default port, so Instiki can be launched by dobbelt-click
Added Textile cache to speed-up rendering of large pages
Made WikiWords look like "Wiki Words"
Updated RedCloth to 2.0.4
* 0.2.5:
Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
Windows problems are gone. Also fixed a problem with wikiwords
that used part of other wikiwords.
* 0.2.0:
First public release
* 0.10.2:
Upgraded to Rails 0.13.1
Fixed HTML export
Added layout=no option to the export_html action (it exports page contents processed
by the markup engine, but without the default layout - so that they can be wrapped in
some other layout)
<nowiki> tag can span several lines (before it was applied when both opening and closing
tags were on the same line only)
Resolved the "endless redirection loop" condition and otherwise improved handling of
errors in the rendering engines
Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
* 0.10.1:
Upgraded Rails to 0.12.0
Upgraded rubyzip to version 0.5.8
BlueCloth is back (RedCloth didn't do pure Markdown well enough)
Handling of line breaks in Textile is as in 0.9 (inserts <br/> tag)
Fixed HTML export (to enclose the output in <html> tags, include the stylesheet etc)
Corrected some compatibility issues with storages from earlier Instiki versions
Some other bug fixes
* 0.10.0:
Ported to ActionPack
RedCloth 3.0.3
BlueCloth is phased out, Markdown is rendered by RedCloth
Mix markup option understands both Textile and Markdown on the same page
Instiki can serve static content (such as HTML or plain-text files) from ./public
directory
Much friendlier admin interface
Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
"textile link":LinkToSomePlace will not look insane.
RSS feeds accept query parameters, sush as
http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
RSS feed with page contents for a password-protected web behaves as follows:
if the web is published, RSS feed links to the published version of the web
otherwise, the feed is not available
Madeleine will check every hour if there are new commands in the log or 24 hours have
passed since last snapshot, and take snapshot if either of these conditions is true
Madeleine will also not log read-only operations, resulting in a better performance
Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
Wiki search handles multibyte (UTF-8) characters correctly
Local hyperlinks in published pages point to published pages [Michael DeHaan]
Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
restart
Fixed parsing of URIs with a port number (http://someplace.org:8080)
Instiki will not fork itself on a *nix, unless explicitly asked to
Instiki can bind to IPs other than 127.0.0.1 (command-line option)
Revisions that do not change anything on the page are rejected
Automated tests for all controller actions
category: lines are presented as links to "All Pages" for relevant categories
Search looks at page titles, as well as content
Multiple other usability enhancements and bug fixes
* 0.9.2:
Rollback takes the user to an edit form. The form has to be submitted for the change to
take place.
Changed to use inline style on published pages
Fixed "forward in time" on the last revision before current page
Instiki won't log bogus error messages when creating a new Wiki
Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
Madeleine upgraded to 0.7.1
Madeleine snapshots are compressed
Packaged as a gem
* 0.9.1:
Added performance improvements for updating existing pages
Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
* 0.9.0:
Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
Added include other page content with [[!include TableOfContents]] [Mark Reid]
Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
Added logging of IP address for authors (who's behind the rollback wars)
Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
Added option to use bracket-style wiki links only (and hence ban WikiWords)
Added command-line option to specify different storage path
Added print view without navigation
Added character and page (2275 characters including spaces) counter (important for student papers)
Off by default, activate it on the Edit Web screen
Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
Use the home page as a table of contents with a unordered list to control sections
Added limit of 15 to the number of pages included in RSS feed
Moved static parts of stylesheet to separate file [Lau TŒrnskov]
Fixed better semantics for revision movement [Ryan Singer]
Fixed color diffs to work much better [Xen/Mertz/Atkins]
Fixed performance problems for All Pages list [Dennis Mertz]
Fixed lots of rendering bugs [Mark Reid]
Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
* 0.8.9:
Added color diffs to see changes between revisions [Bill Atkins]
They're aren't quite perfect yet as new paragraphs split the <ins> tags (hence 0.8.9, not 0.9.0)
Added redirect to edit if content of page generates an error
(so the page doesn't become unusable on bugs in the markup engines)
Fixed update Web with different address bug [Denis Metz]
Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
* 0.8.5:
Instiki can now serve as a CMS by running a password-protected web with a published front
Added version check at startup (Instiki needs Ruby 1.8.1)
* 0.8.1:
Actually included RedCloth 2.0.7 in the release
* 0.8.0:
NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
Many thanks to Guan Yang for building the higher- and lower-case lookup tables
And thanks to Simon Arnaud for the initial patch that got the work started
Changed charset to UTF-8
Cut down on command-line options and replaced them with an per-web config screen
Added option to extend the stylesheet on a per-web basis to tweak the look in details
Added simple color options for variety
Added option to add/remove password protection on each web
Added the wiki name of the author locking a given page (instead of just "someone")
Removed single/multi-web distinction -- all Instikis are now multi-web
Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
Keeps the author cookie forever, so you don't have to enter your name again and again
Fixed XHTML so it validates [Bruce D'Arcus]
Authors are no longer listed under orphan pages
Added export to markup (great for backups, potentially for switching wiki engine)
Don't link wiki words that proceeds from either /, = or ?
(http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
Accessing an unexisting page redirects to a different url (/new/PageName)
Increased snapshot time to just once a day (cuts down on disk storage requirements)
Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
Added convinient redirect from /wiki/ to /wiki/show/HomePage
Fixed BlueCloth bug with backticks at start of line
Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
* 0.7.0:
Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
Added password-login through URL (so you can subscribe to feed on a protected web)
Added web passwords to the feed links for protected webs, so they work without manual login
Added the web name in small letters above all pages within a web
Polished authors and recently revised
Updated to RedCloth 2.0.6
Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
Changed searching to be case insensitive
Changed HomePage to display the name of the web instead
Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
Fixed broken recently revised
* 0.6.0:
Fixed Windows compatibility [Florian]
Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
Added export entire web as HTML in a zip file
Added RSS feeds
Added proper getops support for the growing number of options [Florian]
Added safe mode that forbids style options in RedCloth [Florian]
Updated RedCloth to 2.0.5
* 0.5.0:
NOTE: 0.5.0 is NOT compatible with databases from earlier versions
Added revisions
Added multiple webs
Added password protection for webs on multi-web setups
Added the notion of authors (that are saved in a cookie)
Added command-line option for not running as a Daemon on Unix
* 0.3.1:
Added option to escape wiki words with \
* 0.3.0:
Brought all files into common style (including Textile help on the edit page)
Added page locking (if someone already is editing a page there's a warning)
Added daemon abilities on Unix (keep Instiki running after you close the terminal)
Made port 2500 the default port, so Instiki can be launched by dobbelt-click
Added Textile cache to speed-up rendering of large pages
Made WikiWords look like "Wiki Words"
Updated RedCloth to 2.0.4
* 0.2.5:
Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
Windows problems are gone. Also fixed a problem with wikiwords
that used part of other wikiwords.
* 0.2.0:
First public release

140
README
View file

@ -1,70 +1,70 @@
===What is Instiki?
Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
on simplicity of installation and running:
Step 1. Download
Step 2. Run "instiki"
Step 3. Chuckle... "There's no step three!" (TM)
You're now running a perfectly suitable wiki on port 2500
that'll present you with one-step setup, followed by a textarea for the home page
on http://localhost:2500.
Instiki lowers the barriers of interest for when you might consider
using a wiki. It's so simple to get running that you'll find yourself
using it for anything -- taking notes, brainstorming, organizing a
gathering.
===Features:
* Regular expression search: Find deep stuff really fast
* Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
* Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
* RSS feeds to track recently revised pages
* Multiple webs: Create separate wikis with their own namespace
* Password-protected webs: Keep it private
* Authors: Each revision is associated with an author, so you can see who changed what
* Reference tracker: Which other pages are pointing to the current?
* Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
* Three markup choices: Textile[http://www.textism.com/tools/textile]
(default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
* Embedded webserver: Through WEBrick[http://www.webrick.org]
* Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
* Color diffs: Track changes through revisions
===Missing:
* File attachments
===Install from gem:
* Install rubygems
* Run "gem install instiki"
* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
instiki --storage ~/instiki/storage
===Command-line options:
* Run "instiki --help"
===History:
* See CHANGELOG
===Download latest from:
* http://rubyforge.org/project/showfiles.php?group_id=186
===Visit the official Instiki wiki:
* http://www.instiki.org
===License:
* same as Ruby's
---
Author:: David Heinemeier Hansson
Email:: david@loudthinking.com
Weblog:: http://www.loudthinking.com
===What is Instiki?
Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
on simplicity of installation and running:
Step 1. Download
Step 2. Run "instiki"
Step 3. Chuckle... "There's no step three!" (TM)
You're now running a perfectly suitable wiki on port 2500
that'll present you with one-step setup, followed by a textarea for the home page
on http://localhost:2500.
Instiki lowers the barriers of interest for when you might consider
using a wiki. It's so simple to get running that you'll find yourself
using it for anything -- taking notes, brainstorming, organizing a
gathering.
===Features:
* Regular expression search: Find deep stuff really fast
* Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
* Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
* RSS feeds to track recently revised pages
* Multiple webs: Create separate wikis with their own namespace
* Password-protected webs: Keep it private
* Authors: Each revision is associated with an author, so you can see who changed what
* Reference tracker: Which other pages are pointing to the current?
* Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
* Three markup choices: Textile[http://www.textism.com/tools/textile]
(default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
* Embedded webserver: Through WEBrick[http://www.webrick.org]
* Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
* Color diffs: Track changes through revisions
===Missing:
* File attachments
===Install from gem:
* Install rubygems
* Run "gem install instiki"
* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
instiki --storage ~/instiki/storage
===Command-line options:
* Run "instiki --help"
===History:
* See CHANGELOG
===Download latest from:
* http://rubyforge.org/project/showfiles.php?group_id=186
===Visit the official Instiki wiki:
* http://www.instiki.org
===License:
* same as Ruby's
---
Author:: David Heinemeier Hansson
Email:: david@loudthinking.com
Weblog:: http://www.loudthinking.com

View file

@ -1,137 +1,137 @@
class Page < ActiveRecord::Base
belongs_to :web
has_many :revisions, :order => 'id'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
def revise(content, time, author)
revisions_size = new_record? ? 0 : revisions.size
if (revisions_size > 0) and content == current_revision.content
raise Instiki::ValidationError.new(
"You have tried to save page '#{name}' without changing its content")
end
author = Author.new(author.to_s) unless author.is_a?(Author)
# Try to render content to make sure that markup engine can take it,
Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
# 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
# by the same author, not more than 30 minutes ago, then update the last revision instead of
# creating a new one
if (revisions_size > 0) && continous_revision?(time, author)
current_revision.update_attributes(:content => content, :revised_at => time)
else
Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
end
save
web.refresh_pages_with_references(name) if revisions_size == 0
self
end
def rollback(revision_number, time, author_ip = nil)
roll_back_revision = self.revisions[revision_number]
if roll_back_revision.nil?
raise Instiki::ValidationError.new("Revision #{revision_number} not found")
end
revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
end
def revisions?
revisions.size > 1
end
def previous_revision(revision)
revision_index = revisions.each_with_index do |rev, index|
if rev.id == revision.id
break index
else
nil
end
end
if revision_index.nil? or revision_index == 0
nil
else
revisions[revision_index - 1]
end
end
def in_category?(cat)
cat.nil? || cat.empty? || categories.include?(cat)
end
def categories
display_content.find_chunks(Category).map { |cat| cat.list }.flatten
end
def authors
revisions.collect { |rev| rev.author }
end
def references
web.select.pages_that_reference(name)
end
def linked_from
web.select.pages_that_link_to(name)
end
def included_from
web.select.pages_that_include(name)
end
# Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
def plain_name
web.brackets_only? ? name : WikiWords.separate(name)
end
# used to build chunk ids.
#def id
# @id ||= name.unpack('H*').first
#end
def link(options = {})
web.make_link(name, nil, options)
end
def author_link(options = {})
web.make_link(author, nil, options)
end
LOCKING_PERIOD = 30.minutes
def lock(time, locked_by)
update_attributes(:locked_at => time, :locked_by => locked_by)
end
def lock_duration(time)
((time - locked_at) / 60).to_i unless locked_at.nil?
end
def unlock
update_attribute(:locked_at, nil)
end
def locked?(comparison_time)
locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
end
private
def continous_revision?(time, author)
(current_revision.author == author) && (revised_at + 30.minutes > time)
end
# Forward method calls to the current revision, so the page responds to all revision calls
def method_missing(method_id, *args, &block)
method_name = method_id.to_s
# Perform a hand-off to AR::Base#method_missing
if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
super(method_id, *args, &block)
else
current_revision.send(method_id)
end
end
class Page < ActiveRecord::Base
belongs_to :web
has_many :revisions, :order => 'id'
has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
def revise(content, time, author)
revisions_size = new_record? ? 0 : revisions.size
if (revisions_size > 0) and content == current_revision.content
raise Instiki::ValidationError.new(
"You have tried to save page '#{name}' without changing its content")
end
author = Author.new(author.to_s) unless author.is_a?(Author)
# Try to render content to make sure that markup engine can take it,
Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
# 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
# by the same author, not more than 30 minutes ago, then update the last revision instead of
# creating a new one
if (revisions_size > 0) && continous_revision?(time, author)
current_revision.update_attributes(:content => content, :revised_at => time)
else
Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
end
save
web.refresh_pages_with_references(name) if revisions_size == 0
self
end
def rollback(revision_number, time, author_ip = nil)
roll_back_revision = self.revisions[revision_number]
if roll_back_revision.nil?
raise Instiki::ValidationError.new("Revision #{revision_number} not found")
end
revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
end
def revisions?
revisions.size > 1
end
def previous_revision(revision)
revision_index = revisions.each_with_index do |rev, index|
if rev.id == revision.id
break index
else
nil
end
end
if revision_index.nil? or revision_index == 0
nil
else
revisions[revision_index - 1]
end
end
def in_category?(cat)
cat.nil? || cat.empty? || categories.include?(cat)
end
def categories
display_content.find_chunks(Category).map { |cat| cat.list }.flatten
end
def authors
revisions.collect { |rev| rev.author }
end
def references
web.select.pages_that_reference(name)
end
def linked_from
web.select.pages_that_link_to(name)
end
def included_from
web.select.pages_that_include(name)
end
# Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
def plain_name
web.brackets_only? ? name : WikiWords.separate(name)
end
# used to build chunk ids.
#def id
# @id ||= name.unpack('H*').first
#end
def link(options = {})
web.make_link(name, nil, options)
end
def author_link(options = {})
web.make_link(author, nil, options)
end
LOCKING_PERIOD = 30.minutes
def lock(time, locked_by)
update_attributes(:locked_at => time, :locked_by => locked_by)
end
def lock_duration(time)
((time - locked_at) / 60).to_i unless locked_at.nil?
end
def unlock
update_attribute(:locked_at, nil)
end
def locked?(comparison_time)
locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
end
private
def continous_revision?(time, author)
(current_revision.author == author) && (revised_at + 30.minutes > time)
end
# Forward method calls to the current revision, so the page responds to all revision calls
def method_missing(method_id, *args, &block)
method_name = method_id.to_s
# Perform a hand-off to AR::Base#method_missing
if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
super(method_id, *args, &block)
else
current_revision.send(method_id)
end
end
end

View file

@ -1,105 +1,105 @@
require 'diff'
class Revision < ActiveRecord::Base
belongs_to :page
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
# Returns an array of all the WikiIncludes present in the content of this revision.
def wiki_includes
unless @wiki_includes_cache
chunks = display_content.find_chunks(Include)
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_includes_cache
end
# Returns an array of all the WikiReferences present in the content of this revision.
def wiki_references
unless @wiki_references_cache
chunks = display_content.find_chunks(WikiChunk::WikiReference)
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_references_cache
end
# Returns an array of all the WikiWords present in the content of this revision.
def wiki_words
unless @wiki_words_cache
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_words_cache
end
# Returns an array of all the WikiWords present in the content of this revision.
# that already exists as a page in the web.
def existing_pages
wiki_words.select { |wiki_word| page.web.page(wiki_word) }
end
# 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.
def unexisting_pages
wiki_words - existing_pages
end
# Explicit check for new type of display cache with chunks_by_type method.
# Ensures new version works with older snapshots.
def display_content
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
@display_cache = WikiContent.new(self)
@display_cache.render!
end
@display_cache
end
# TODO this probably doesn't belong in revision (because it has to call back the page)
def display_diff
previous_revision = page.previous_revision(self)
if previous_revision
HTMLDiff.diff(previous_revision.display_content, display_content)
else
display_content
end
end
def clear_display_cache
@wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
@wiki_references_cache = nil
end
def display_published
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
@published_cache = WikiContent.new(self, {:mode => :publish})
@published_cache.render!
end
@published_cache
end
def display_content_for_export
WikiContent.new(self, {:mode => :export} ).render!
end
def force_rendering
begin
display_content.render!
rescue => e
logger.error "Failed rendering page #{@name}"
logger.error e
message = e.message
# substitute content with an error message
self.content = <<-EOL
<p>Markup engine has failed to render this page, raising the following error:</p>
<p>#{message}</p>
<pre>#{self.content}</pre>
EOL
clear_display_cache
raise e
end
end
protected
after_create :force_rendering
after_save :clear_display_cache
require 'diff'
class Revision < ActiveRecord::Base
belongs_to :page
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
# Returns an array of all the WikiIncludes present in the content of this revision.
def wiki_includes
unless @wiki_includes_cache
chunks = display_content.find_chunks(Include)
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_includes_cache
end
# Returns an array of all the WikiReferences present in the content of this revision.
def wiki_references
unless @wiki_references_cache
chunks = display_content.find_chunks(WikiChunk::WikiReference)
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_references_cache
end
# Returns an array of all the WikiWords present in the content of this revision.
def wiki_words
unless @wiki_words_cache
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
end
@wiki_words_cache
end
# Returns an array of all the WikiWords present in the content of this revision.
# that already exists as a page in the web.
def existing_pages
wiki_words.select { |wiki_word| page.web.page(wiki_word) }
end
# 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.
def unexisting_pages
wiki_words - existing_pages
end
# Explicit check for new type of display cache with chunks_by_type method.
# Ensures new version works with older snapshots.
def display_content
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
@display_cache = WikiContent.new(self)
@display_cache.render!
end
@display_cache
end
# TODO this probably doesn't belong in revision (because it has to call back the page)
def display_diff
previous_revision = page.previous_revision(self)
if previous_revision
HTMLDiff.diff(previous_revision.display_content, display_content)
else
display_content
end
end
def clear_display_cache
@wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
@wiki_references_cache = nil
end
def display_published
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
@published_cache = WikiContent.new(self, {:mode => :publish})
@published_cache.render!
end
@published_cache
end
def display_content_for_export
WikiContent.new(self, {:mode => :export} ).render!
end
def force_rendering
begin
display_content.render!
rescue => e
logger.error "Failed rendering page #{@name}"
logger.error e
message = e.message
# substitute content with an error message
self.content = <<-EOL
<p>Markup engine has failed to render this page, raising the following error:</p>
<p>#{message}</p>
<pre>#{self.content}</pre>
EOL
clear_display_cache
raise e
end
end
protected
after_create :force_rendering
after_save :clear_display_cache
end

View file

@ -1,173 +1,173 @@
require 'cgi'
class Web < ActiveRecord::Base
has_many :pages#, :include => [:current_revision, :web]
def wiki
Wiki.new
end
def file_yard
@file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
end
def settings_changed?(markup, safe_mode, brackets_only)
self.markup != markup ||
self.safe_mode != safe_mode ||
self.brackets_only != brackets_only
end
def add_page(name, content, time, author)
page = page(name) || Page.new(:web => self, :name => name)
page.revise(content, time, author)
end
def authors
select.authors
end
def categories
select.map { |page| page.categories }.flatten.uniq.sort
end
def page(name)
pages.find(:first, :conditions => ['name = ?', name])
end
def has_page?(name)
Page.count(['web_id = ? AND name = ?', id, name]) > 0
end
def has_file?(name)
wiki.file_yard(self).has_file?(name)
end
def markup
read_attribute('markup').to_sym
end
def make_file_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode
when :export
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
else "<span class=\"newWikiWord\">#{text}</span>" end
when :publish
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{base_url}/published/#{link}\">#{text}</a>"
else "<span class=\"newWikiWord\">#{text}</span>" end
else
if has_file?(name)
"<a class=\"existingWikiWord\" href=\"#{base_url}/file/#{link}\">#{text}</a>"
else
"<span class=\"newWikiWord\">#{text}<a href=\"#{base_url}/file/#{link}\">?</a></span>"
end
end
end
# Create a link for the given page name and link text based
# on the render mode in options and whether the page exists
# in the this web.
# The links a relative, and will work only if displayed on another WikiPage.
# It should not be used in menus, templates and such - instead, use link_to_page helper
def make_link(name, text = nil, options = {})
text = CGI.escapeHTML(text || WikiWords.separate(name))
mode = options[:mode] || :show
base_url = options[:base_url] || '..'
link_type = options[:link_type] || :show
case link_type.to_sym
when :show
make_page_link(mode, name, text, base_url)
when :file
make_file_link(mode, name, text, base_url)
when :pic
make_pic_link(mode, name, text, base_url)
else
raise "Unknown link type: #{link_type}"
end
end
def make_page_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode.to_sym
when :export
if has_page?(name) then %{<a class="existingWikiWord" href="#{link}.html">#{text}</a>}
else %{<span class="newWikiWord">#{text}</span>} end
when :publish
if has_page?(name) then %{<a class="existingWikiWord" href="#{base_url}/published/#{link}">#{text}</a>}
else %{<span class="newWikiWord">#{text}</span>} end
else
if has_page?(name)
%{<a class="existingWikiWord" href="#{base_url}/show/#{link}">#{text}</a>}
else
%{<span class="newWikiWord">#{text}<a href="#{base_url}/show/#{link}">?</a></span>}
end
end
end
def make_pic_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode.to_sym
when :export
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
else %{<img alt="#{text}" src="no image" />} end
when :publish
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
else %{<span class="newWikiWord">#{text}</span>} end
else
if has_file?(name) then %{<img alt="#{text}" src="#{base_url}/pic/#{link}" />}
else %{<span class="newWikiWord">#{text}<a href="#{base_url}/pic/#{link}">?</a></span>} end
end
end
# Clears the display cache for all the pages with references to
def refresh_pages_with_references(page_name)
#select.pages_that_reference(page_name).each { |page|
# page.revisions.each { |revision| revision.clear_display_cache }
#}
end
def refresh_revisions
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
end
def remove_pages(pages_to_be_removed)
pages_to_be_removed.each { |p| p.destroy }
end
def revised_at
select.most_recent_revision
end
def select(&condition)
PageSet.new(self, pages, condition)
end
private
# Returns an array of all the wiki words in any current revision
def wiki_words
pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
end
# Returns an array of all the page names on this web
def page_names
pages.map { |p| p.name }
end
protected
before_save :sanitize_markup
before_validation :validate_address
validates_uniqueness_of :address
validates_length_of :color, :in => 3..6
def sanitize_markup
self.markup = markup.to_s
end
def validate_address
unless address == CGI.escape(address)
self.errors.add(:address, 'should contain only valid URI characters')
raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
end
end
require 'cgi'
class Web < ActiveRecord::Base
has_many :pages#, :include => [:current_revision, :web]
def wiki
Wiki.new
end
def file_yard
@file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
end
def settings_changed?(markup, safe_mode, brackets_only)
self.markup != markup ||
self.safe_mode != safe_mode ||
self.brackets_only != brackets_only
end
def add_page(name, content, time, author)
page = page(name) || Page.new(:web => self, :name => name)
page.revise(content, time, author)
end
def authors
select.authors
end
def categories
select.map { |page| page.categories }.flatten.uniq.sort
end
def page(name)
pages.find(:first, :conditions => ['name = ?', name])
end
def has_page?(name)
Page.count(['web_id = ? AND name = ?', id, name]) > 0
end
def has_file?(name)
wiki.file_yard(self).has_file?(name)
end
def markup
read_attribute('markup').to_sym
end
def make_file_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode
when :export
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
else "<span class=\"newWikiWord\">#{text}</span>" end
when :publish
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{base_url}/published/#{link}\">#{text}</a>"
else "<span class=\"newWikiWord\">#{text}</span>" end
else
if has_file?(name)
"<a class=\"existingWikiWord\" href=\"#{base_url}/file/#{link}\">#{text}</a>"
else
"<span class=\"newWikiWord\">#{text}<a href=\"#{base_url}/file/#{link}\">?</a></span>"
end
end
end
# Create a link for the given page name and link text based
# on the render mode in options and whether the page exists
# in the this web.
# The links a relative, and will work only if displayed on another WikiPage.
# It should not be used in menus, templates and such - instead, use link_to_page helper
def make_link(name, text = nil, options = {})
text = CGI.escapeHTML(text || WikiWords.separate(name))
mode = options[:mode] || :show
base_url = options[:base_url] || '..'
link_type = options[:link_type] || :show
case link_type.to_sym
when :show
make_page_link(mode, name, text, base_url)
when :file
make_file_link(mode, name, text, base_url)
when :pic
make_pic_link(mode, name, text, base_url)
else
raise "Unknown link type: #{link_type}"
end
end
def make_page_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode.to_sym
when :export
if has_page?(name) then %{<a class="existingWikiWord" href="#{link}.html">#{text}</a>}
else %{<span class="newWikiWord">#{text}</span>} end
when :publish
if has_page?(name) then %{<a class="existingWikiWord" href="#{base_url}/published/#{link}">#{text}</a>}
else %{<span class="newWikiWord">#{text}</span>} end
else
if has_page?(name)
%{<a class="existingWikiWord" href="#{base_url}/show/#{link}">#{text}</a>}
else
%{<span class="newWikiWord">#{text}<a href="#{base_url}/show/#{link}">?</a></span>}
end
end
end
def make_pic_link(mode, name, text, base_url)
link = CGI.escape(name)
case mode.to_sym
when :export
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
else %{<img alt="#{text}" src="no image" />} end
when :publish
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
else %{<span class="newWikiWord">#{text}</span>} end
else
if has_file?(name) then %{<img alt="#{text}" src="#{base_url}/pic/#{link}" />}
else %{<span class="newWikiWord">#{text}<a href="#{base_url}/pic/#{link}">?</a></span>} end
end
end
# Clears the display cache for all the pages with references to
def refresh_pages_with_references(page_name)
#select.pages_that_reference(page_name).each { |page|
# page.revisions.each { |revision| revision.clear_display_cache }
#}
end
def refresh_revisions
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
end
def remove_pages(pages_to_be_removed)
pages_to_be_removed.each { |p| p.destroy }
end
def revised_at
select.most_recent_revision
end
def select(&condition)
PageSet.new(self, pages, condition)
end
private
# Returns an array of all the wiki words in any current revision
def wiki_words
pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
end
# Returns an array of all the page names on this web
def page_names
pages.map { |p| p.name }
end
protected
before_save :sanitize_markup
before_validation :validate_address
validates_uniqueness_of :address
validates_length_of :color, :in => 3..6
def sanitize_markup
self.markup = markup.to_s
end
def validate_address
unless address == CGI.escape(address)
self.errors.add(:address, 'should contain only valid URI characters')
raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
end
end
end

View file

@ -1,44 +1,44 @@
$__instiki_source_patterns = [
'[A-Z]*', 'instiki', 'instiki.rb', 'app/**/*', 'lib/**/*', 'vendor/**/*',
'public/**/*', 'natives/**/*', 'config/**/*', 'script/**/*'
]
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = 'instiki'
s.version = "0.10.2"
s.summary = 'Easy to install WikiClone running on WEBrick and SQLite'
s.description = <<-EOF
Instiki is a Wiki Clone written in Ruby that ships with an embedded
webserver. You can setup up an Instiki in just a few steps.
Possibly the simplest wiki setup ever.
EOF
s.author = 'David Heinemeier Hansson'
s.email = 'david@loudthinking.com'
s.rubyforge_project = 'instiki'
s.homepage = 'http://www.instiki.org'
s.bindir = '.'
s.executables = ['instiki']
s.default_executable = 'instiki'
s.has_rdoc = false
s.add_dependency('RedCloth', '= 3.0.3')
s.add_dependency('rubyzip', '= 0.5.8')
s.add_dependency('rails', '= 0.13.1')
s.add_dependency('sqlite3-ruby', '= 1.1.0')
s.requirements << 'none'
s.require_path = 'lib'
s.files = $__instiki_source_patterns.inject([]) { |list, glob|
list << Dir[glob].delete_if { |path|
File.directory?(path) or
path.include?('.svn/') or
path.include?('vendor/') or
path.include?('test/') or
path.include?('_test.rb')
}
}.flatten
end
$__instiki_source_patterns = [
'[A-Z]*', 'instiki', 'instiki.rb', 'app/**/*', 'lib/**/*', 'vendor/**/*',
'public/**/*', 'natives/**/*', 'config/**/*', 'script/**/*'
]
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = 'instiki'
s.version = "0.10.2"
s.summary = 'Easy to install WikiClone running on WEBrick and SQLite'
s.description = <<-EOF
Instiki is a Wiki Clone written in Ruby that ships with an embedded
webserver. You can setup up an Instiki in just a few steps.
Possibly the simplest wiki setup ever.
EOF
s.author = 'David Heinemeier Hansson'
s.email = 'david@loudthinking.com'
s.rubyforge_project = 'instiki'
s.homepage = 'http://www.instiki.org'
s.bindir = '.'
s.executables = ['instiki']
s.default_executable = 'instiki'
s.has_rdoc = false
s.add_dependency('RedCloth', '= 3.0.3')
s.add_dependency('rubyzip', '= 0.5.8')
s.add_dependency('rails', '= 0.13.1')
s.add_dependency('sqlite3-ruby', '= 1.1.0')
s.requirements << 'none'
s.require_path = 'lib'
s.files = $__instiki_source_patterns.inject([]) { |list, glob|
list << Dir[glob].delete_if { |path|
File.directory?(path) or
path.include?('.svn/') or
path.include?('vendor/') or
path.include?('test/') or
path.include?('_test.rb')
}
}.flatten
end

View file

@ -1,46 +1,46 @@
require 'erb'
def create_options
if @db == 'mysql'
'ENGINE = ' + (mysql_engine rescue @mysql_engine)
end
end
def db_quote(column)
case @db
when 'postgresql'
return "\"#{column}\""
when 'sqlite', 'sqlite3'
return "'#{column}'"
when 'mysql'
return "`#{column}`"
end
end
def db_structure(db)
db.downcase!
@db = db
case db
when 'postgresql'
@pk = 'SERIAL PRIMARY KEY'
@datetime = 'TIMESTAMP'
@boolean = "BOOLEAN"
when 'sqlite', 'sqlite3'
@pk = 'INTEGER PRIMARY KEY'
@datetime = 'DATETIME'
@boolean = "INTEGER"
when 'mysql'
@pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
@datetime = 'DATETIME'
@boolean = "TINYINT"
@mysql_engine = 'InnoDB'
else
raise "Unknown db type #{db}"
end
s = ''
Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
s += ERB.new(File.read(filename)).result
end
s
end
require 'erb'
def create_options
if @db == 'mysql'
'ENGINE = ' + (mysql_engine rescue @mysql_engine)
end
end
def db_quote(column)
case @db
when 'postgresql'
return "\"#{column}\""
when 'sqlite', 'sqlite3'
return "'#{column}'"
when 'mysql'
return "`#{column}`"
end
end
def db_structure(db)
db.downcase!
@db = db
case db
when 'postgresql'
@pk = 'SERIAL PRIMARY KEY'
@datetime = 'TIMESTAMP'
@boolean = "BOOLEAN"
when 'sqlite', 'sqlite3'
@pk = 'INTEGER PRIMARY KEY'
@datetime = 'DATETIME'
@boolean = "INTEGER"
when 'mysql'
@pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
@datetime = 'DATETIME'
@boolean = "TINYINT"
@mysql_engine = 'InnoDB'
else
raise "Unknown db type #{db}"
end
s = ''
Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
s += ERB.new(File.read(filename)).result
end
s
end

View file

@ -1,55 +1,55 @@
home_page:
id: 1
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
web_id: 1
name: HomePage
my_way:
id: 2
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
web_id: 1
name: MyWay
smart_engine:
id: 3
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
web_id: 1
name: SmartEngine
that_way:
id: 4
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
web_id: 1
name: ThatWay
no_wiki_word:
id: 5
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
web_id: 1
name: NoWikiWord
first_page:
id: 6
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
web_id: 1
name: FirstPage
oak:
id: 7
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
web_id: 1
name: Oak
elephant:
id: 8
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
web_id: 1
home_page:
id: 1
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
web_id: 1
name: HomePage
my_way:
id: 2
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
web_id: 1
name: MyWay
smart_engine:
id: 3
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
web_id: 1
name: SmartEngine
that_way:
id: 4
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
web_id: 1
name: ThatWay
no_wiki_word:
id: 5
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
web_id: 1
name: NoWikiWord
first_page:
id: 6
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
web_id: 1
name: FirstPage
oak:
id: 7
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
web_id: 1
name: Oak
elephant:
id: 8
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
web_id: 1
name: Elephant

View file

@ -1,83 +1,83 @@
home_page_first_revision:
id: 1
created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
revised_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
page_id: 1
content: First revision of the HomePage end
author: AnAuthor
ip: 127.0.0.1
my_way_first_revision:
id: 2
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
revised_at: <%= 9.days.ago.to_formatted_s(:db) %>
page_id: 2
content: MyWay
author: Me
smart_engine_first_revision:
id: 3
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
revised_at: <%= 8.days.ago.to_formatted_s(:db) %>
page_id: 3
content: SmartEngine
author: Me
that_way_first_revision:
id: 4
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
revised_at: <%= 7.days.ago.to_formatted_s(:db) %>
page_id: 4
content: ThatWay
author: Me
no_wiki_word_first_revision:
id: 5
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
revised_at: <%= 6.days.ago.to_formatted_s(:db) %>
page_id: 5
content: hey you
author: Me
home_page_second_revision:
id: 6
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
revised_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
page_id: 1
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
author: DavidHeinemeierHansson
first_page_first_revision:
id: 7
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
revised_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
page_id: 6
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
author: DavidHeinemeierHansson
oak_first_revision:
id: 8
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
revised_at: <%= 5.days.ago.to_formatted_s(:db) %>
page_id: 7
content: "All about oak.\ncategory: trees"
author: TreeHugger
ip: 127.0.0.2
elephant_first_revision:
id: 9
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
revised_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
page_id: 8
content: "All about elephants.\ncategory: animals"
author: Guest
ip: 127.0.0.2
home_page_first_revision:
id: 1
created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
revised_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
page_id: 1
content: First revision of the HomePage end
author: AnAuthor
ip: 127.0.0.1
my_way_first_revision:
id: 2
created_at: <%= 9.days.ago.to_formatted_s(:db) %>
updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
revised_at: <%= 9.days.ago.to_formatted_s(:db) %>
page_id: 2
content: MyWay
author: Me
smart_engine_first_revision:
id: 3
created_at: <%= 8.days.ago.to_formatted_s(:db) %>
updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
revised_at: <%= 8.days.ago.to_formatted_s(:db) %>
page_id: 3
content: SmartEngine
author: Me
that_way_first_revision:
id: 4
created_at: <%= 7.days.ago.to_formatted_s(:db) %>
updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
revised_at: <%= 7.days.ago.to_formatted_s(:db) %>
page_id: 4
content: ThatWay
author: Me
no_wiki_word_first_revision:
id: 5
created_at: <%= 6.days.ago.to_formatted_s(:db) %>
updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
revised_at: <%= 6.days.ago.to_formatted_s(:db) %>
page_id: 5
content: hey you
author: Me
home_page_second_revision:
id: 6
created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
revised_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
page_id: 1
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
author: DavidHeinemeierHansson
first_page_first_revision:
id: 7
created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
revised_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
page_id: 6
content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
author: DavidHeinemeierHansson
oak_first_revision:
id: 8
created_at: <%= 5.days.ago.to_formatted_s(:db) %>
updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
revised_at: <%= 5.days.ago.to_formatted_s(:db) %>
page_id: 7
content: "All about oak.\ncategory: trees"
author: TreeHugger
ip: 127.0.0.2
elephant_first_revision:
id: 9
created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
revised_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
page_id: 8
content: "All about elephants.\ncategory: animals"
author: Guest
ip: 127.0.0.2

View file

@ -1,15 +1,15 @@
test_wiki:
id: 1
created_at: 2004-08-01
updated_at: 2005-08-01
name: wiki1
address: wiki1
markup: textile
instiki:
id: 2
created_at: 2004-08-01
updated_at: 2005-08-01
name: Instiki
address: instiki
test_wiki:
id: 1
created_at: 2004-08-01
updated_at: 2005-08-01
name: wiki1
address: wiki1
markup: textile
instiki:
id: 2
created_at: 2004-08-01
updated_at: 2005-08-01
name: Instiki
address: instiki
markup: textile

View file

@ -1,106 +1,106 @@
ENV["RAILS_ENV"] = "test"
# Expand the path to environment so that Ruby does not load it multiple times
# File.expand_path can be removed if Ruby 1.9 is in use.
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'application'
require 'test/unit'
require 'active_record/fixtures'
require 'action_controller/test_process'
require 'action_web_service/test_invoke'
require 'breakpoint'
require 'wiki_content'
# Uncomment these and hang on, because the tests will be FAST
#Test::Unit::TestCase.pre_loaded_fixtures = false
#Test::Unit::TestCase.use_transactional_fixtures = true
Test::Unit::TestCase.use_instantiated_fixtures = false
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
class Test::Unit::TestCase
def create_fixtures(*table_names)
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
end
# Add more helper methods to be used by all tests here...
def set_web_property(property, value)
@web.update_attribute(property, value)
@page = Page.find(@page.id)
@wiki.webs[@web.name] = @web
end
def setup_wiki_with_30_pages
ActiveRecord::Base.silence do
(1..30).each do |i|
@wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
end
end
@web = Web.find(@web.id)
end
def use_blank_wiki
Revision.destroy_all
Page.destroy_all
Web.destroy_all
end
end
# 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
# and any the values of any fields that should be set after a match.
class ContentStub < String
include ChunkManager
def initialize(str)
super
init_chunk_manager
end
def page_link(*); end
end
module ChunkMatch
# Asserts a number of tests for the given type and text.
def match(chunk_type, test_text, expected_chunk_state)
if chunk_type.respond_to? :pattern
assert_match(chunk_type.pattern, test_text)
end
content = ContentStub.new(test_text)
chunk_type.apply_to(content)
# Test if requested parts are correct.
expected_chunk_state.each_pair do |a_method, expected_value|
assert content.chunks.last.kind_of?(chunk_type)
assert_respond_to(content.chunks.last, a_method)
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
"Wrong #{a_method} value")
end
end
# Asserts that test_text doesn't match the chunk_type
def no_match(chunk_type, test_text)
if chunk_type.respond_to? :pattern
assert_no_match(chunk_type.pattern, test_text)
end
end
end
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
module Test
module Unit
module Assertions
unless method_defined? :__assert_success_before_override_by_instiki
alias :__assert_success_before_override_by_instiki :assert_success
end
def assert_success
__assert_success_before_override_by_instiki
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
end
end
end
end
end
ENV["RAILS_ENV"] = "test"
# Expand the path to environment so that Ruby does not load it multiple times
# File.expand_path can be removed if Ruby 1.9 is in use.
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'application'
require 'test/unit'
require 'active_record/fixtures'
require 'action_controller/test_process'
require 'action_web_service/test_invoke'
require 'breakpoint'
require 'wiki_content'
# Uncomment these and hang on, because the tests will be FAST
#Test::Unit::TestCase.pre_loaded_fixtures = false
#Test::Unit::TestCase.use_transactional_fixtures = true
Test::Unit::TestCase.use_instantiated_fixtures = false
Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
class Test::Unit::TestCase
def create_fixtures(*table_names)
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
end
# Add more helper methods to be used by all tests here...
def set_web_property(property, value)
@web.update_attribute(property, value)
@page = Page.find(@page.id)
@wiki.webs[@web.name] = @web
end
def setup_wiki_with_30_pages
ActiveRecord::Base.silence do
(1..30).each do |i|
@wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
end
end
@web = Web.find(@web.id)
end
def use_blank_wiki
Revision.destroy_all
Page.destroy_all
Web.destroy_all
end
end
# 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
# and any the values of any fields that should be set after a match.
class ContentStub < String
include ChunkManager
def initialize(str)
super
init_chunk_manager
end
def page_link(*); end
end
module ChunkMatch
# Asserts a number of tests for the given type and text.
def match(chunk_type, test_text, expected_chunk_state)
if chunk_type.respond_to? :pattern
assert_match(chunk_type.pattern, test_text)
end
content = ContentStub.new(test_text)
chunk_type.apply_to(content)
# Test if requested parts are correct.
expected_chunk_state.each_pair do |a_method, expected_value|
assert content.chunks.last.kind_of?(chunk_type)
assert_respond_to(content.chunks.last, a_method)
assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
"Wrong #{a_method} value")
end
end
# Asserts that test_text doesn't match the chunk_type
def no_match(chunk_type, test_text)
if chunk_type.respond_to? :pattern
assert_no_match(chunk_type.pattern, test_text)
end
end
end
if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
module Test
module Unit
module Assertions
unless method_defined? :__assert_success_before_override_by_instiki
alias :__assert_success_before_override_by_instiki :assert_success
end
def assert_success
__assert_success_before_override_by_instiki
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
end
end
end
end
end

View file

@ -1,88 +1,88 @@
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class PageTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
@page = pages(:first_page)
end
def test_lock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
@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, 17, 1))
@page.unlock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
end
def test_lock_duration
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
end
def test_plain_name
assert_equal "First Page", @page.plain_name
end
def test_revise
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
@page.reload
assert_equal 2, @page.revisions.length, 'Should have two revisions'
assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
end
def test_revise_continous_revision
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda lame', @page.content
# consecutive revision by the same author within 30 minutes doesn't create a new revision
@page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda update', @page.content
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
# but consecutive revision by another author results in a new revision
@page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
@page.reload
assert_equal 3, @page.revisions.length
assert_equal 'HisWay would be MyWay in the house', @page.content
# consecutive update after 30 minutes since the last one also creates a new revision,
# even when it is by the same author
@page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
@page.reload
assert_equal 4, @page.revisions.length
end
def test_revise_content_unchanged
last_revision_before = @page.current_revision
revisions_number_before = @page.revisions.size
assert_raises(Instiki::ValidationError) {
@page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
}
assert_equal last_revision_before, @page.current_revision(true)
assert_equal revisions_number_before, @page.revisions.size
end
def test_rollback
@page.revise("spot two", Time.now, "David")
@page.revise("spot three", Time.now + 2000, "David")
assert_equal 3, @page.revisions(true).length, "Should have three revisions"
@page.current_revision(true)
@page.rollback(0, Time.now)
assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
end
end
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class PageTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
@page = pages(:first_page)
end
def test_lock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
@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, 17, 1))
@page.unlock
assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
end
def test_lock_duration
@page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
end
def test_plain_name
assert_equal "First Page", @page.plain_name
end
def test_revise
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
@page.reload
assert_equal 2, @page.revisions.length, 'Should have two revisions'
assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
end
def test_revise_continous_revision
@page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda lame', @page.content
# consecutive revision by the same author within 30 minutes doesn't create a new revision
@page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
@page.reload
assert_equal 2, @page.revisions.length
assert_equal 'HisWay would be MyWay in kinda update', @page.content
assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
# but consecutive revision by another author results in a new revision
@page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
@page.reload
assert_equal 3, @page.revisions.length
assert_equal 'HisWay would be MyWay in the house', @page.content
# consecutive update after 30 minutes since the last one also creates a new revision,
# even when it is by the same author
@page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
@page.reload
assert_equal 4, @page.revisions.length
end
def test_revise_content_unchanged
last_revision_before = @page.current_revision
revisions_number_before = @page.revisions.size
assert_raises(Instiki::ValidationError) {
@page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
}
assert_equal last_revision_before, @page.current_revision(true)
assert_equal revisions_number_before, @page.revisions.size
end
def test_rollback
@page.revise("spot two", Time.now, "David")
@page.revise("spot three", Time.now + 2000, "David")
assert_equal 3, @page.revisions(true).length, "Should have three revisions"
@page.current_revision(true)
@page.rollback(0, Time.now)
assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
end
end

View file

@ -1,317 +1,317 @@
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class RevisionTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
@wiki = Wiki.new
@web = webs(:test_wiki)
@page = pages(:home_page)
@revision = revisions(:home_page_second_revision)
end
def test_wiki_words
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
end
def test_existing_pages
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
end
def test_unexisting_pages
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
end
def test_content_with_wiki_links
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 ' +
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere&#8212;see ' +
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
'<span class="newWikiWord">Smart Engine GUI' +
'<a href="../show/SmartEngineGUI">?</a></span></p>',
@revision.display_content
end
def test_markdown
set_web_property :markup, :markdown
assert_markup_parsed_as(
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
"My Headline\n===========\n\nthat SmartEngineGUI")
code_block = [
'This is a code block:',
'',
' def a_method(arg)',
' return ThatWay',
'',
'Nice!'
].join("\n")
assert_markup_parsed_as(
%{<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>},
code_block)
end
def test_markdown_hyperlink_with_slash
# in response to a bug, see http://dev.instiki.org/attachment/ticket/177
set_web_property :markup, :markdown
assert_markup_parsed_as(
'<p><a href="http://example/with/slash">text</a></p>',
'[text](http://example/with/slash)')
end
def test_mixed_formatting
textile_and_markdown = [
'Markdown heading',
'================',
'',
'h2. Textile heading',
'',
'*some* **text** _with_ -styles-',
'',
'* list 1',
'* list 2'
].join("\n")
set_web_property :markup, :markdown
assert_markup_parsed_as(
"<h1>Markdown heading</h1>\n\n" +
"<p>h2. Textile heading</p>\n\n" +
"<p><em>some</em> <strong>text</strong> <em>with</em> -styles-</p>\n\n" +
"<ul>\n<li>list 1</li>\n<li>list 2</li>\n</ul>",
textile_and_markdown)
set_web_property :markup, :textile
assert_markup_parsed_as(
"<p>Markdown heading<br />================</p>\n\n\n\t<h2>Textile heading</h2>" +
"\n\n\n\t<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>" +
"\n\n\n\t<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
textile_and_markdown)
set_web_property :markup, :mixed
assert_markup_parsed_as(
"<h1>Markdown heading</h1>\n\n\n\t<h2>Textile heading</h2>\n\n\n\t" +
"<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>\n\n\n\t" +
"<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
textile_and_markdown)
end
def test_rdoc
set_web_property :markup, :rdoc
@revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
:author => Author.new('DavidHeinemeierHansson'))
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
end
def test_content_with_auto_links
assert_markup_parsed_as(
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
end
def test_content_with_aliased_links
assert_markup_parsed_as(
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
'</a> go by any other name?</p>',
'Would a [[SmartEngine|clever motor]] go by any other name?')
end
def test_content_with_wikiword_in_em
assert_markup_parsed_as(
'<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>' +
'</span> </em></p>',
'_should we go ThatWay or ThisWay _')
end
def test_content_with_wikiword_in_tag
assert_markup_parsed_as(
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
'That is some <em style="WikiWord">Stylish Emphasis</em>')
end
def test_content_with_escaped_wikiword
# there should be no wiki link
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
end
def test_content_with_pre_blocks
assert_markup_parsed_as(
'<p>A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre></p>',
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
end
def test_content_with_autolink_in_parentheses
assert_markup_parsed_as(
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
'http://www.w3c.org</a>) sets web standards</p>',
'The W3C body (http://www.w3c.org) sets web standards')
end
def test_content_with_link_in_parentheses
assert_markup_parsed_as(
'<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)')
end
def test_content_with_image_link
assert_markup_parsed_as(
'<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.')
end
def test_content_with_inlined_img_tag
assert_markup_parsed_as(
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.</p>',
'This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.')
assert_markup_parsed_as(
'<p>This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.</p>',
'This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.')
end
def test_nowiki_tag
assert_markup_parsed_as(
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
'or <nowiki>http://www.thislink.com</nowiki>.')
end
def test_multiline_nowiki_tag
assert_markup_parsed_as(
"<p>Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
'<span class="newWikiWord">this<a href="../show/this">?</a></span></p>',
"Do not <nowiki>mark \n up [[this text]] \n" +
"and http://this.url.com </nowiki> but markup [[this]]")
end
def test_content_with_bracketted_wiki_word
set_web_property :brackets_only, true
assert_markup_parsed_as(
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
end
def test_content_for_export
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="ThatWay.html">That Way</a> in ' +
'<span class="newWikiWord">His Way</span> though ' +
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere&#8212;see ' +
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
'<span class="newWikiWord">Smart Engine GUI</span></p>',
@revision.display_content_for_export
end
def test_double_replacing
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
assert_equal '<p><span class="newWikiWord">Version History' +
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
'</span></p>',
@revision.display_content
@revision.clear_display_cache
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
assert_equal "<p>f<br /><span class=\"newWikiWord\">Version History" +
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
"</span></p>",
@revision.display_content
end
def test_difficult_wiki_words
@revision.content = "[[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>",
@revision.display_content
end
def test_revisions_diff
Revision.create(:page => @page, :content => 'What a blue and lovely morning',
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
Revision.create(:page => @page, :content => 'What a red and lovely morning today',
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
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 " +
"today</ins></p>", @page.revisions.last.display_diff
end
def test_link_to_file
assert_markup_parsed_as(
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
'[[doc.pdf:file]]')
end
def test_link_to_pic
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
assert_markup_parsed_as(
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
'[[square.jpg|Square:pic]]')
assert_markup_parsed_as(
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
'[[square.jpg:pic]]')
end
def test_link_to_non_existant_pic
assert_markup_parsed_as(
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
'</span></p>',
'[[NonExistant.jpg|NonExistant:pic]]')
assert_markup_parsed_as(
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
'</span></p>',
'[[NonExistant.jpg:pic]]')
end
def test_wiki_link_with_colon
assert_markup_parsed_as(
'<p><span class="newWikiWord">With:Colon<a href="../show/With%3AColon">?</a></span></p>',
'[[With:Colon]]')
end
# 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)
def test_list_with_tildas
list_with_tildas = <<-EOL
* "a":~b
* c~ d
EOL
assert_markup_parsed_as(
"<ul>\n\t<li><a href=\"~b\">a</a></li>\n\t\t<li>c~ d</li>\n\t</ul>",
list_with_tildas)
end
def test_textile_image_in_mixed_wiki
set_web_property :markup, :mixed
assert_markup_parsed_as(
"<p><img src=\"http://google.com\" alt=\"\" />\nss</p>",
"!http://google.com!\r\nss")
end
def assert_markup_parsed_as(expected_output, input)
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
end
end
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class RevisionTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
@wiki = Wiki.new
@web = webs(:test_wiki)
@page = pages(:home_page)
@revision = revisions(:home_page_second_revision)
end
def test_wiki_words
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
end
def test_existing_pages
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
end
def test_unexisting_pages
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
end
def test_content_with_wiki_links
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 ' +
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere&#8212;see ' +
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
'<span class="newWikiWord">Smart Engine GUI' +
'<a href="../show/SmartEngineGUI">?</a></span></p>',
@revision.display_content
end
def test_markdown
set_web_property :markup, :markdown
assert_markup_parsed_as(
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
"My Headline\n===========\n\nthat SmartEngineGUI")
code_block = [
'This is a code block:',
'',
' def a_method(arg)',
' return ThatWay',
'',
'Nice!'
].join("\n")
assert_markup_parsed_as(
%{<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>},
code_block)
end
def test_markdown_hyperlink_with_slash
# in response to a bug, see http://dev.instiki.org/attachment/ticket/177
set_web_property :markup, :markdown
assert_markup_parsed_as(
'<p><a href="http://example/with/slash">text</a></p>',
'[text](http://example/with/slash)')
end
def test_mixed_formatting
textile_and_markdown = [
'Markdown heading',
'================',
'',
'h2. Textile heading',
'',
'*some* **text** _with_ -styles-',
'',
'* list 1',
'* list 2'
].join("\n")
set_web_property :markup, :markdown
assert_markup_parsed_as(
"<h1>Markdown heading</h1>\n\n" +
"<p>h2. Textile heading</p>\n\n" +
"<p><em>some</em> <strong>text</strong> <em>with</em> -styles-</p>\n\n" +
"<ul>\n<li>list 1</li>\n<li>list 2</li>\n</ul>",
textile_and_markdown)
set_web_property :markup, :textile
assert_markup_parsed_as(
"<p>Markdown heading<br />================</p>\n\n\n\t<h2>Textile heading</h2>" +
"\n\n\n\t<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>" +
"\n\n\n\t<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
textile_and_markdown)
set_web_property :markup, :mixed
assert_markup_parsed_as(
"<h1>Markdown heading</h1>\n\n\n\t<h2>Textile heading</h2>\n\n\n\t" +
"<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>\n\n\n\t" +
"<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
textile_and_markdown)
end
def test_rdoc
set_web_property :markup, :rdoc
@revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
:author => Author.new('DavidHeinemeierHansson'))
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
end
def test_content_with_auto_links
assert_markup_parsed_as(
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
end
def test_content_with_aliased_links
assert_markup_parsed_as(
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
'</a> go by any other name?</p>',
'Would a [[SmartEngine|clever motor]] go by any other name?')
end
def test_content_with_wikiword_in_em
assert_markup_parsed_as(
'<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>' +
'</span> </em></p>',
'_should we go ThatWay or ThisWay _')
end
def test_content_with_wikiword_in_tag
assert_markup_parsed_as(
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
'That is some <em style="WikiWord">Stylish Emphasis</em>')
end
def test_content_with_escaped_wikiword
# there should be no wiki link
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
end
def test_content_with_pre_blocks
assert_markup_parsed_as(
'<p>A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre></p>',
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
end
def test_content_with_autolink_in_parentheses
assert_markup_parsed_as(
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
'http://www.w3c.org</a>) sets web standards</p>',
'The W3C body (http://www.w3c.org) sets web standards')
end
def test_content_with_link_in_parentheses
assert_markup_parsed_as(
'<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)')
end
def test_content_with_image_link
assert_markup_parsed_as(
'<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.')
end
def test_content_with_inlined_img_tag
assert_markup_parsed_as(
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.</p>',
'This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.')
assert_markup_parsed_as(
'<p>This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.</p>',
'This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.')
end
def test_nowiki_tag
assert_markup_parsed_as(
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
'or <nowiki>http://www.thislink.com</nowiki>.')
end
def test_multiline_nowiki_tag
assert_markup_parsed_as(
"<p>Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
'<span class="newWikiWord">this<a href="../show/this">?</a></span></p>',
"Do not <nowiki>mark \n up [[this text]] \n" +
"and http://this.url.com </nowiki> but markup [[this]]")
end
def test_content_with_bracketted_wiki_word
set_web_property :brackets_only, true
assert_markup_parsed_as(
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
end
def test_content_for_export
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="ThatWay.html">That Way</a> in ' +
'<span class="newWikiWord">His Way</span> though ' +
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere&#8212;see ' +
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
'<span class="newWikiWord">Smart Engine GUI</span></p>',
@revision.display_content_for_export
end
def test_double_replacing
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
assert_equal '<p><span class="newWikiWord">Version History' +
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
'</span></p>',
@revision.display_content
@revision.clear_display_cache
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
assert_equal "<p>f<br /><span class=\"newWikiWord\">Version History" +
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
"</span></p>",
@revision.display_content
end
def test_difficult_wiki_words
@revision.content = "[[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>",
@revision.display_content
end
def test_revisions_diff
Revision.create(:page => @page, :content => 'What a blue and lovely morning',
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
Revision.create(:page => @page, :content => 'What a red and lovely morning today',
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
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 " +
"today</ins></p>", @page.revisions.last.display_diff
end
def test_link_to_file
assert_markup_parsed_as(
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
'[[doc.pdf:file]]')
end
def test_link_to_pic
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
assert_markup_parsed_as(
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
'[[square.jpg|Square:pic]]')
assert_markup_parsed_as(
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
'[[square.jpg:pic]]')
end
def test_link_to_non_existant_pic
assert_markup_parsed_as(
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
'</span></p>',
'[[NonExistant.jpg|NonExistant:pic]]')
assert_markup_parsed_as(
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
'</span></p>',
'[[NonExistant.jpg:pic]]')
end
def test_wiki_link_with_colon
assert_markup_parsed_as(
'<p><span class="newWikiWord">With:Colon<a href="../show/With%3AColon">?</a></span></p>',
'[[With:Colon]]')
end
# 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)
def test_list_with_tildas
list_with_tildas = <<-EOL
* "a":~b
* c~ d
EOL
assert_markup_parsed_as(
"<ul>\n\t<li><a href=\"~b\">a</a></li>\n\t\t<li>c~ d</li>\n\t</ul>",
list_with_tildas)
end
def test_textile_image_in_mixed_wiki
set_web_property :markup, :mixed
assert_markup_parsed_as(
"<p><img src=\"http://google.com\" alt=\"\" />\nss</p>",
"!http://google.com!\r\nss")
end
def assert_markup_parsed_as(expected_output, input)
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
end
end

View file

@ -1,158 +1,158 @@
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class WebTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
@web = webs(:instiki)
end
def test_wiki_word_linking
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
Time.now, 'DavidHeinemeierHansson')
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
'<a href="../show/EverBeenHated">?</a></span></p>',
@web.page("SecondPage").display_content)
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
'DavidHeinemeierHansson')
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
@web.page("SecondPage").display_content)
end
def test_pages_by_revision
add_sample_pages
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
end
def test_pages_by_match
add_sample_pages
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
end
def test_references
add_sample_pages
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
end
def test_delete
add_sample_pages
assert_equal 2, @web.pages.length
@web.remove_pages([ @web.page('EverBeenInLove') ])
assert_equal 1, @web.pages(true).length
end
def test_make_link
add_sample_pages
existing_page_wiki_url =
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
existing_page_published_url =
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
existing_page_static_url =
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
new_page_wiki_url =
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
new_page_published_url =
new_page_static_url =
'<span class="newWikiWord">Unknown Word</span>'
# no options
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
# :mode => :export
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
# :mode => :publish
assert_equal existing_page_published_url,
@web.make_link('EverBeenInLove', nil, :mode => :publish)
# new page, no options
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
# new page, :mode => :export
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
# new page, :mode => :publish
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
# Escaping special characters in the name
assert_equal(
'<span class="newWikiWord">Smith &amp; Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
@web.make_link('Smith & Wesson'))
# optionally using text as the link text
assert_equal(
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))
end
def test_initialize
web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
assert_equal 'Wiki2', web.name
assert_equal 'wiki2', web.address
assert_equal '123', web.password
# new web should be set for maximum features enabled
assert_equal :textile, web.markup
assert_equal '008B26', web.color
assert !web.safe_mode?
assert_equal([], web.pages)
assert web.allow_uploads?
assert_nil web.additional_style
assert !web.published?
assert !web.brackets_only?
assert !web.count_pages?
assert_equal 100, web.max_upload_size
end
def test_initialize_invalid_name
assert_raises(Instiki::ValidationError) {
Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
}
end
def test_new_page_linked_from_mother_page
# this was a bug in revision 204
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
@web.add_page('AnotherPage', 'This is \AnotherPage',
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
@web.pages(true)
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
end
def test_orphaned_pages
add_sample_pages
home = @web.add_page('HomePage',
'This is a home page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
author = @web.add_page('AlexeyVerkhovsky',
'This is an author page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
self_linked = @web.add_page('SelfLinked',
'I am me SelfLinked and link to EverBeenInLove',
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
# page that links to itself, and nobody else links to it must be an orphan
assert_equal ['EverBeenHated', 'SelfLinked'],
@web.select.orphaned_pages.collect{ |page| page.name }.sort
end
private
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
end
end
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
class WebTest < Test::Unit::TestCase
fixtures :webs, :pages, :revisions, :system
def setup
@web = webs(:instiki)
end
def test_wiki_word_linking
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
Time.now, 'DavidHeinemeierHansson')
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
'<a href="../show/EverBeenHated">?</a></span></p>',
@web.page("SecondPage").display_content)
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
'DavidHeinemeierHansson')
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
@web.page("SecondPage").display_content)
end
def test_pages_by_revision
add_sample_pages
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
end
def test_pages_by_match
add_sample_pages
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
end
def test_references
add_sample_pages
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
end
def test_delete
add_sample_pages
assert_equal 2, @web.pages.length
@web.remove_pages([ @web.page('EverBeenInLove') ])
assert_equal 1, @web.pages(true).length
end
def test_make_link
add_sample_pages
existing_page_wiki_url =
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
existing_page_published_url =
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
existing_page_static_url =
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
new_page_wiki_url =
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
new_page_published_url =
new_page_static_url =
'<span class="newWikiWord">Unknown Word</span>'
# no options
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
# :mode => :export
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
# :mode => :publish
assert_equal existing_page_published_url,
@web.make_link('EverBeenInLove', nil, :mode => :publish)
# new page, no options
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
# new page, :mode => :export
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
# new page, :mode => :publish
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
# Escaping special characters in the name
assert_equal(
'<span class="newWikiWord">Smith &amp; Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
@web.make_link('Smith & Wesson'))
# optionally using text as the link text
assert_equal(
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))
end
def test_initialize
web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
assert_equal 'Wiki2', web.name
assert_equal 'wiki2', web.address
assert_equal '123', web.password
# new web should be set for maximum features enabled
assert_equal :textile, web.markup
assert_equal '008B26', web.color
assert !web.safe_mode?
assert_equal([], web.pages)
assert web.allow_uploads?
assert_nil web.additional_style
assert !web.published?
assert !web.brackets_only?
assert !web.count_pages?
assert_equal 100, web.max_upload_size
end
def test_initialize_invalid_name
assert_raises(Instiki::ValidationError) {
Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
}
end
def test_new_page_linked_from_mother_page
# this was a bug in revision 204
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
@web.add_page('AnotherPage', 'This is \AnotherPage',
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
@web.pages(true)
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
end
def test_orphaned_pages
add_sample_pages
home = @web.add_page('HomePage',
'This is a home page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
author = @web.add_page('AlexeyVerkhovsky',
'This is an author page, it should not be an orphan',
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
self_linked = @web.add_page('SelfLinked',
'I am me SelfLinked and link to EverBeenInLove',
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
# page that links to itself, and nobody else links to it must be an orphan
assert_equal ['EverBeenHated', 'SelfLinked'],
@web.select.orphaned_pages.collect{ |page| page.name }.sort
end
private
def add_sample_pages
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
end
end