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: * 0.10.2:
Upgraded to Rails 0.13.1 Upgraded to Rails 0.13.1
Fixed HTML export Fixed HTML export
Added layout=no option to the export_html action (it exports page contents processed 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 by the markup engine, but without the default layout - so that they can be wrapped in
some other layout) some other layout)
<nowiki> tag can span several lines (before it was applied when both opening and closing <nowiki> tag can span several lines (before it was applied when both opening and closing
tags were on the same line only) tags were on the same line only)
Resolved the "endless redirection loop" condition and otherwise improved handling of Resolved the "endless redirection loop" condition and otherwise improved handling of
errors in the rendering engines errors in the rendering engines
Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo) Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
* 0.10.1: * 0.10.1:
Upgraded Rails to 0.12.0 Upgraded Rails to 0.12.0
Upgraded rubyzip to version 0.5.8 Upgraded rubyzip to version 0.5.8
BlueCloth is back (RedCloth didn't do pure Markdown well enough) 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) 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) Fixed HTML export (to enclose the output in <html> tags, include the stylesheet etc)
Corrected some compatibility issues with storages from earlier Instiki versions Corrected some compatibility issues with storages from earlier Instiki versions
Some other bug fixes Some other bug fixes
* 0.10.0: * 0.10.0:
Ported to ActionPack Ported to ActionPack
RedCloth 3.0.3 RedCloth 3.0.3
BlueCloth is phased out, Markdown is rendered by RedCloth BlueCloth is phased out, Markdown is rendered by RedCloth
Mix markup option understands both Textile and Markdown on the same page 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 Instiki can serve static content (such as HTML or plain-text files) from ./public
directory directory
Much friendlier admin interface Much friendlier admin interface
Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
"textile link":LinkToSomePlace will not look insane. "textile link":LinkToSomePlace will not look insane.
RSS feeds accept query parameters, sush as RSS feeds accept query parameters, sush as
http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10 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: 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 if the web is published, RSS feed links to the published version of the web
otherwise, the feed is not available otherwise, the feed is not available
Madeleine will check every hour if there are new commands in the log or 24 hours have 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 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 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 extracts (to HTML and plain text) will leave only the last extract file in ./storage
Wiki search handles multibyte (UTF-8) characters correctly Wiki search handles multibyte (UTF-8) characters correctly
Local hyperlinks in published pages point to published pages [Michael DeHaan] 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 Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
restart restart
Fixed parsing of URIs with a port number (http://someplace.org:8080) 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 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) 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 Revisions that do not change anything on the page are rejected
Automated tests for all controller actions Automated tests for all controller actions
category: lines are presented as links to "All Pages" for relevant categories category: lines are presented as links to "All Pages" for relevant categories
Search looks at page titles, as well as content Search looks at page titles, as well as content
Multiple other usability enhancements and bug fixes Multiple other usability enhancements and bug fixes
* 0.9.2: * 0.9.2:
Rollback takes the user to an edit form. The form has to be submitted for the change to Rollback takes the user to an edit form. The form has to be submitted for the change to
take place. take place.
Changed to use inline style on published pages Changed to use inline style on published pages
Fixed "forward in time" on the last revision before current page Fixed "forward in time" on the last revision before current page
Instiki won't log bogus error messages when creating a new Wiki Instiki won't log bogus error messages when creating a new Wiki
Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2) Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
Madeleine upgraded to 0.7.1 Madeleine upgraded to 0.7.1
Madeleine snapshots are compressed Madeleine snapshots are compressed
Packaged as a gem Packaged as a gem
* 0.9.1: * 0.9.1:
Added performance improvements for updating existing pages Added performance improvements for updating existing pages
Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang] 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] Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
* 0.9.0: * 0.9.0:
Added aliased links such as [[HomePage|that nice home page]] [Mark Reid] Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
Added include other page content with [[!include TableOfContents]] [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 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 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 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 option to use bracket-style wiki links only (and hence ban WikiWords)
Added command-line option to specify different storage path Added command-line option to specify different storage path
Added print view without navigation Added print view without navigation
Added character and page (2275 characters including spaces) counter (important for student papers) Added character and page (2275 characters including spaces) counter (important for student papers)
Off by default, activate it on the Edit Web screen Off by default, activate it on the Edit Web screen
Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL) 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 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 Added limit of 15 to the number of pages included in RSS feed
Moved static parts of stylesheet to separate file [Lau TŒrnskov] Moved static parts of stylesheet to separate file [Lau TŒrnskov]
Fixed better semantics for revision movement [Ryan Singer] Fixed better semantics for revision movement [Ryan Singer]
Fixed color diffs to work much better [Xen/Mertz/Atkins] Fixed color diffs to work much better [Xen/Mertz/Atkins]
Fixed performance problems for All Pages list [Dennis Mertz] Fixed performance problems for All Pages list [Dennis Mertz]
Fixed lots of rendering bugs [Mark Reid] Fixed lots of rendering bugs [Mark Reid]
Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz] Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
* 0.8.9: * 0.8.9:
Added color diffs to see changes between revisions [Bill Atkins] 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) 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 Added redirect to edit if content of page generates an error
(so the page doesn't become unusable on bugs in the markup engines) (so the page doesn't become unusable on bugs in the markup engines)
Fixed update Web with different address bug [Denis Metz] 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 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) Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
* 0.8.5: * 0.8.5:
Instiki can now serve as a CMS by running a password-protected web with a published front 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) Added version check at startup (Instiki needs Ruby 1.8.1)
* 0.8.1: * 0.8.1:
Actually included RedCloth 2.0.7 in the release Actually included RedCloth 2.0.7 in the release
* 0.8.0: * 0.8.0:
NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password 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 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 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 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 And thanks to Simon Arnaud for the initial patch that got the work started
Changed charset to UTF-8 Changed charset to UTF-8
Cut down on command-line options and replaced them with an per-web config screen 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 option to extend the stylesheet on a per-web basis to tweak the look in details
Added simple color options for variety Added simple color options for variety
Added option to add/remove password protection on each web 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") 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 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] 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 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] Fixed XHTML so it validates [Bruce D'Arcus]
Authors are no longer listed under orphan pages Authors are no longer listed under orphan pages
Added export to markup (great for backups, potentially for switching wiki engine) Added export to markup (great for backups, potentially for switching wiki engine)
Don't link wiki words that proceeds from either /, = or ? Don't link wiki words that proceeds from either /, = or ?
(http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping) (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) 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) 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] Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
Added convinient redirect from /wiki/ to /wiki/show/HomePage Added convinient redirect from /wiki/ to /wiki/show/HomePage
Fixed BlueCloth bug with backticks at start of line Fixed BlueCloth bug with backticks at start of line
Updated to RedCloth 2.0.7 (and linked to the new Textile reference) Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
* 0.7.0: * 0.7.0:
Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices 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 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 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 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 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 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 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 Added the web name in small letters above all pages within a web
Polished authors and recently revised Polished authors and recently revised
Updated to RedCloth 2.0.6 Updated to RedCloth 2.0.6
Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy) Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
Changed searching to be case insensitive Changed searching to be case insensitive
Changed HomePage to display the name of the web instead Changed HomePage to display the name of the web instead
Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT) Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
Fixed broken recently revised Fixed broken recently revised
* 0.6.0: * 0.6.0:
Fixed Windows compatibility [Florian] Fixed Windows compatibility [Florian]
Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
Added export entire web as HTML in a zip file Added export entire web as HTML in a zip file
Added RSS feeds Added RSS feeds
Added proper getops support for the growing number of options [Florian] Added proper getops support for the growing number of options [Florian]
Added safe mode that forbids style options in RedCloth [Florian] Added safe mode that forbids style options in RedCloth [Florian]
Updated RedCloth to 2.0.5 Updated RedCloth to 2.0.5
* 0.5.0: * 0.5.0:
NOTE: 0.5.0 is NOT compatible with databases from earlier versions NOTE: 0.5.0 is NOT compatible with databases from earlier versions
Added revisions Added revisions
Added multiple webs Added multiple webs
Added password protection for webs on multi-web setups Added password protection for webs on multi-web setups
Added the notion of authors (that are saved in a cookie) Added the notion of authors (that are saved in a cookie)
Added command-line option for not running as a Daemon on Unix Added command-line option for not running as a Daemon on Unix
* 0.3.1: * 0.3.1:
Added option to escape wiki words with \ Added option to escape wiki words with \
* 0.3.0: * 0.3.0:
Brought all files into common style (including Textile help on the edit page) 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 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) 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 Made port 2500 the default port, so Instiki can be launched by dobbelt-click
Added Textile cache to speed-up rendering of large pages Added Textile cache to speed-up rendering of large pages
Made WikiWords look like "Wiki Words" Made WikiWords look like "Wiki Words"
Updated RedCloth to 2.0.4 Updated RedCloth to 2.0.4
* 0.2.5: * 0.2.5:
Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
Windows problems are gone. Also fixed a problem with wikiwords Windows problems are gone. Also fixed a problem with wikiwords
that used part of other wikiwords. that used part of other wikiwords.
* 0.2.0: * 0.2.0:
First public release First public release

140
README
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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