From b29c59e4705a9de5c7be1de43cd726c3fc1d5a66 Mon Sep 17 00:00:00 2001
From: Ben Bleything Markup engine has failed to render this page, raising the following error: #{message} Markup engine has failed to render this page, raising the following error: #{message} His Way? ' +
- 'would be My Way in kinda ' +
- 'That Way in ' +
- 'His Way? ' +
- 'though My Way OverThere—see ' +
- 'Smart Engine in that ' +
- 'Smart Engine GUI' +
- '? that } +
- %{Smart Engine GUI? This is a code block: Nice! h2. Textile heading some text with -styles- Markdown heading some text with some text with http://www.loudthinking.com/ ' +
- 'points to That Way from ' +
- 'david@loudthinking.com Would a clever motor' +
- ' go by any other name? should we go ' +
- 'That Way or This Way?' +
- ' That is some Stylish Emphasis WikiWord A
tag)
- Fixed HTML export (to enclose the output in tags, include the stylesheet etc)
- Corrected some compatibility issues with storages from earlier Instiki versions
- Some other bug fixes
-
- * 0.10.0:
- Ported to ActionPack
- RedCloth 3.0.3
- BlueCloth is phased out, Markdown is rendered by RedCloth
- Mix markup option understands both Textile and Markdown on the same page
- Instiki can serve static content (such as HTML or plain-text files) from ./public
- directory
- Much friendlier admin interface
- Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
- "textile link":LinkToSomePlace will not look insane.
- RSS feeds accept query parameters, sush as
- http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
- RSS feed with page contents for a password-protected web behaves as follows:
- if the web is published, RSS feed links to the published version of the web
- otherwise, the feed is not available
- Madeleine will check every hour if there are new commands in the log or 24 hours have
- passed since last snapshot, and take snapshot if either of these conditions is true
- Madeleine will also not log read-only operations, resulting in a better performance
- Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
- Wiki search handles multibyte (UTF-8) characters correctly
- Local hyperlinks in published pages point to published pages [Michael DeHaan]
- Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
- restart
- Fixed parsing of URIs with a port number (http://someplace.org:8080)
- Instiki will not fork itself on a *nix, unless explicitly asked to
- Instiki can bind to IPs other than 127.0.0.1 (command-line option)
- Revisions that do not change anything on the page are rejected
- Automated tests for all controller actions
- category: lines are presented as links to "All Pages" for relevant categories
- Search looks at page titles, as well as content
- Multiple other usability enhancements and bug fixes
-
- * 0.9.2:
- Rollback takes the user to an edit form. The form has to be submitted for the change to
- take place.
- Changed to use inline style on published pages
- Fixed "forward in time" on the last revision before current page
- Instiki won't log bogus error messages when creating a new Wiki
- Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
- Madeleine upgraded to 0.7.1
- Madeleine snapshots are compressed
- Packaged as a gem
-
- * 0.9.1:
- Added performance improvements for updating existing pages
- Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
- Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
-
- * 0.9.0:
- Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
- Added include other page content with [[!include TableOfContents]] [Mark Reid]
- Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
- Added logging of IP address for authors (who's behind the rollback wars)
- Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
- Added option to use bracket-style wiki links only (and hence ban WikiWords)
- Added command-line option to specify different storage path
- Added print view without navigation
- Added character and page (2275 characters including spaces) counter (important for student papers)
- Off by default, activate it on the Edit Web screen
- Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
- Use the home page as a table of contents with a unordered list to control sections
- Added limit of 15 to the number of pages included in RSS feed
- Moved static parts of stylesheet to separate file [Lau TŒrnskov]
- Fixed better semantics for revision movement [Ryan Singer]
- Fixed color diffs to work much better [Xen/Mertz/Atkins]
- Fixed performance problems for All Pages list [Dennis Mertz]
- Fixed lots of rendering bugs [Mark Reid]
- Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
-
- * 0.8.9:
- Added color diffs to see changes between revisions [Bill Atkins]
- They're aren't quite perfect yet as new paragraphs split the tags (hence 0.8.9, not 0.9.0)
- Added redirect to edit if content of page generates an error
- (so the page doesn't become unusable on bugs in the markup engines)
- Fixed update Web with different address bug [Denis Metz]
- Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
- Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
-
- * 0.8.5:
- Instiki can now serve as a CMS by running a password-protected web with a published front
- Added version check at startup (Instiki needs Ruby 1.8.1)
-
- * 0.8.1:
- Actually included RedCloth 2.0.7 in the release
-
- * 0.8.0:
- NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
- Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
- Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
- Many thanks to Guan Yang for building the higher- and lower-case lookup tables
- And thanks to Simon Arnaud for the initial patch that got the work started
- Changed charset to UTF-8
- Cut down on command-line options and replaced them with an per-web config screen
- Added option to extend the stylesheet on a per-web basis to tweak the look in details
- Added simple color options for variety
- Added option to add/remove password protection on each web
- Added the wiki name of the author locking a given page (instead of just "someone")
- Removed single/multi-web distinction -- all Instikis are now multi-web
- Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
- Keeps the author cookie forever, so you don't have to enter your name again and again
- Fixed XHTML so it validates [Bruce D'Arcus]
- Authors are no longer listed under orphan pages
- Added export to markup (great for backups, potentially for switching wiki engine)
- Don't link wiki words that proceeds from either /, = or ?
- (http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
- Accessing an unexisting page redirects to a different url (/new/PageName)
- Increased snapshot time to just once a day (cuts down on disk storage requirements)
- Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
- Added convinient redirect from /wiki/ to /wiki/show/HomePage
- Fixed BlueCloth bug with backticks at start of line
- Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
-
- * 0.7.0:
- Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
- Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
- Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
- Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
- Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
- Added password-login through URL (so you can subscribe to feed on a protected web)
- Added web passwords to the feed links for protected webs, so they work without manual login
- Added the web name in small letters above all pages within a web
- Polished authors and recently revised
- Updated to RedCloth 2.0.6
- Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
- Changed searching to be case insensitive
- Changed HomePage to display the name of the web instead
- Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
- Fixed broken recently revised
-
- * 0.6.0:
- Fixed Windows compatibility [Florian]
- Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
- Added export entire web as HTML in a zip file
- Added RSS feeds
- Added proper getops support for the growing number of options [Florian]
- Added safe mode that forbids style options in RedCloth [Florian]
- Updated RedCloth to 2.0.5
-
- * 0.5.0:
- NOTE: 0.5.0 is NOT compatible with databases from earlier versions
- Added revisions
- Added multiple webs
- Added password protection for webs on multi-web setups
- Added the notion of authors (that are saved in a cookie)
- Added command-line option for not running as a Daemon on Unix
-
- * 0.3.1:
- Added option to escape wiki words with \
-
- * 0.3.0:
- Brought all files into common style (including Textile help on the edit page)
- Added page locking (if someone already is editing a page there's a warning)
- Added daemon abilities on Unix (keep Instiki running after you close the terminal)
- Made port 2500 the default port, so Instiki can be launched by dobbelt-click
- Added Textile cache to speed-up rendering of large pages
- Made WikiWords look like "Wiki Words"
- Updated RedCloth to 2.0.4
-
- * 0.2.5:
- Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
- Windows problems are gone. Also fixed a problem with wikiwords
- that used part of other wikiwords.
-
- * 0.2.0:
- First public release
+ * 0.10.2:
+ Upgraded to Rails 0.13.1
+ Fixed HTML export
+ Added layout=no option to the export_html action (it exports page contents processed
+ by the markup engine, but without the default layout - so that they can be wrapped in
+ some other layout)
+
tag)
+ Fixed HTML export (to enclose the output in tags, include the stylesheet etc)
+ Corrected some compatibility issues with storages from earlier Instiki versions
+ Some other bug fixes
+
+ * 0.10.0:
+ Ported to ActionPack
+ RedCloth 3.0.3
+ BlueCloth is phased out, Markdown is rendered by RedCloth
+ Mix markup option understands both Textile and Markdown on the same page
+ Instiki can serve static content (such as HTML or plain-text files) from ./public
+ directory
+ Much friendlier admin interface
+ Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
+ "textile link":LinkToSomePlace will not look insane.
+ RSS feeds accept query parameters, sush as
+ http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
+ RSS feed with page contents for a password-protected web behaves as follows:
+ if the web is published, RSS feed links to the published version of the web
+ otherwise, the feed is not available
+ Madeleine will check every hour if there are new commands in the log or 24 hours have
+ passed since last snapshot, and take snapshot if either of these conditions is true
+ Madeleine will also not log read-only operations, resulting in a better performance
+ Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
+ Wiki search handles multibyte (UTF-8) characters correctly
+ Local hyperlinks in published pages point to published pages [Michael DeHaan]
+ Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
+ restart
+ Fixed parsing of URIs with a port number (http://someplace.org:8080)
+ Instiki will not fork itself on a *nix, unless explicitly asked to
+ Instiki can bind to IPs other than 127.0.0.1 (command-line option)
+ Revisions that do not change anything on the page are rejected
+ Automated tests for all controller actions
+ category: lines are presented as links to "All Pages" for relevant categories
+ Search looks at page titles, as well as content
+ Multiple other usability enhancements and bug fixes
+
+ * 0.9.2:
+ Rollback takes the user to an edit form. The form has to be submitted for the change to
+ take place.
+ Changed to use inline style on published pages
+ Fixed "forward in time" on the last revision before current page
+ Instiki won't log bogus error messages when creating a new Wiki
+ Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
+ Madeleine upgraded to 0.7.1
+ Madeleine snapshots are compressed
+ Packaged as a gem
+
+ * 0.9.1:
+ Added performance improvements for updating existing pages
+ Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
+ Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
+
+ * 0.9.0:
+ Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
+ Added include other page content with [[!include TableOfContents]] [Mark Reid]
+ Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
+ Added logging of IP address for authors (who's behind the rollback wars)
+ Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
+ Added option to use bracket-style wiki links only (and hence ban WikiWords)
+ Added command-line option to specify different storage path
+ Added print view without navigation
+ Added character and page (2275 characters including spaces) counter (important for student papers)
+ Off by default, activate it on the Edit Web screen
+ Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
+ Use the home page as a table of contents with a unordered list to control sections
+ Added limit of 15 to the number of pages included in RSS feed
+ Moved static parts of stylesheet to separate file [Lau TŒrnskov]
+ Fixed better semantics for revision movement [Ryan Singer]
+ Fixed color diffs to work much better [Xen/Mertz/Atkins]
+ Fixed performance problems for All Pages list [Dennis Mertz]
+ Fixed lots of rendering bugs [Mark Reid]
+ Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
+
+ * 0.8.9:
+ Added color diffs to see changes between revisions [Bill Atkins]
+ They're aren't quite perfect yet as new paragraphs split the tags (hence 0.8.9, not 0.9.0)
+ Added redirect to edit if content of page generates an error
+ (so the page doesn't become unusable on bugs in the markup engines)
+ Fixed update Web with different address bug [Denis Metz]
+ Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
+ Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
+
+ * 0.8.5:
+ Instiki can now serve as a CMS by running a password-protected web with a published front
+ Added version check at startup (Instiki needs Ruby 1.8.1)
+
+ * 0.8.1:
+ Actually included RedCloth 2.0.7 in the release
+
+ * 0.8.0:
+ NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
+ Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
+ Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
+ Many thanks to Guan Yang for building the higher- and lower-case lookup tables
+ And thanks to Simon Arnaud for the initial patch that got the work started
+ Changed charset to UTF-8
+ Cut down on command-line options and replaced them with an per-web config screen
+ Added option to extend the stylesheet on a per-web basis to tweak the look in details
+ Added simple color options for variety
+ Added option to add/remove password protection on each web
+ Added the wiki name of the author locking a given page (instead of just "someone")
+ Removed single/multi-web distinction -- all Instikis are now multi-web
+ Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
+ Keeps the author cookie forever, so you don't have to enter your name again and again
+ Fixed XHTML so it validates [Bruce D'Arcus]
+ Authors are no longer listed under orphan pages
+ Added export to markup (great for backups, potentially for switching wiki engine)
+ Don't link wiki words that proceeds from either /, = or ?
+ (http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
+ Accessing an unexisting page redirects to a different url (/new/PageName)
+ Increased snapshot time to just once a day (cuts down on disk storage requirements)
+ Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
+ Added convinient redirect from /wiki/ to /wiki/show/HomePage
+ Fixed BlueCloth bug with backticks at start of line
+ Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
+
+ * 0.7.0:
+ Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
+ Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
+ Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
+ Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
+ Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
+ Added password-login through URL (so you can subscribe to feed on a protected web)
+ Added web passwords to the feed links for protected webs, so they work without manual login
+ Added the web name in small letters above all pages within a web
+ Polished authors and recently revised
+ Updated to RedCloth 2.0.6
+ Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
+ Changed searching to be case insensitive
+ Changed HomePage to display the name of the web instead
+ Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
+ Fixed broken recently revised
+
+ * 0.6.0:
+ Fixed Windows compatibility [Florian]
+ Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
+ Added export entire web as HTML in a zip file
+ Added RSS feeds
+ Added proper getops support for the growing number of options [Florian]
+ Added safe mode that forbids style options in RedCloth [Florian]
+ Updated RedCloth to 2.0.5
+
+ * 0.5.0:
+ NOTE: 0.5.0 is NOT compatible with databases from earlier versions
+ Added revisions
+ Added multiple webs
+ Added password protection for webs on multi-web setups
+ Added the notion of authors (that are saved in a cookie)
+ Added command-line option for not running as a Daemon on Unix
+
+ * 0.3.1:
+ Added option to escape wiki words with \
+
+ * 0.3.0:
+ Brought all files into common style (including Textile help on the edit page)
+ Added page locking (if someone already is editing a page there's a warning)
+ Added daemon abilities on Unix (keep Instiki running after you close the terminal)
+ Made port 2500 the default port, so Instiki can be launched by dobbelt-click
+ Added Textile cache to speed-up rendering of large pages
+ Made WikiWords look like "Wiki Words"
+ Updated RedCloth to 2.0.4
+
+ * 0.2.5:
+ Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
+ Windows problems are gone. Also fixed a problem with wikiwords
+ that used part of other wikiwords.
+
+ * 0.2.0:
+ First public release
diff --git a/README b/README
index b5df8534..09d29a9f 100755
--- a/README
+++ b/README
@@ -1,70 +1,70 @@
-===What is Instiki?
-
-Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
-on simplicity of installation and running:
-
-Step 1. Download
-
-Step 2. Run "instiki"
-
-Step 3. Chuckle... "There's no step three!" (TM)
-
-You're now running a perfectly suitable wiki on port 2500
-that'll present you with one-step setup, followed by a textarea for the home page
-on http://localhost:2500.
-
-Instiki lowers the barriers of interest for when you might consider
-using a wiki. It's so simple to get running that you'll find yourself
-using it for anything -- taking notes, brainstorming, organizing a
-gathering.
-
-===Features:
-* Regular expression search: Find deep stuff really fast
-* Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
-* Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
-* RSS feeds to track recently revised pages
-* Multiple webs: Create separate wikis with their own namespace
-* Password-protected webs: Keep it private
-* Authors: Each revision is associated with an author, so you can see who changed what
-* Reference tracker: Which other pages are pointing to the current?
-* Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
-* Three markup choices: Textile[http://www.textism.com/tools/textile]
- (default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
- Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
-* Embedded webserver: Through WEBrick[http://www.webrick.org]
-* Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
-* Color diffs: Track changes through revisions
-
-===Missing:
-* File attachments
-
-===Install from gem:
-* Install rubygems
-* Run "gem install instiki"
-* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
-* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
-
-Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
- instiki --storage ~/instiki/storage
-
-===Command-line options:
-* Run "instiki --help"
-
-===History:
- * See CHANGELOG
-
-===Download latest from:
-* http://rubyforge.org/project/showfiles.php?group_id=186
-
-===Visit the official Instiki wiki:
-* http://www.instiki.org
-
-===License:
-* same as Ruby's
-
----
-Author:: David Heinemeier Hansson
-Email:: david@loudthinking.com
-Weblog:: http://www.loudthinking.com
-
-
+===What is Instiki?
+
+Admitted, it's YetAnotherWikiClone[http://c2.com/cgi/wiki?WikiWikiClones], but with a strong focus
+on simplicity of installation and running:
+
+Step 1. Download
+
+Step 2. Run "instiki"
+
+Step 3. Chuckle... "There's no step three!" (TM)
+
+You're now running a perfectly suitable wiki on port 2500
+that'll present you with one-step setup, followed by a textarea for the home page
+on http://localhost:2500.
+
+Instiki lowers the barriers of interest for when you might consider
+using a wiki. It's so simple to get running that you'll find yourself
+using it for anything -- taking notes, brainstorming, organizing a
+gathering.
+
+===Features:
+* Regular expression search: Find deep stuff really fast
+* Revisions: Follow the changes on every page from birth. Rollback to an earlier rev
+* Export to HTML or markup in a zip: Take the entire wiki with you home or for reference
+* RSS feeds to track recently revised pages
+* Multiple webs: Create separate wikis with their own namespace
+* Password-protected webs: Keep it private
+* Authors: Each revision is associated with an author, so you can see who changed what
+* Reference tracker: Which other pages are pointing to the current?
+* Speed: Using Madelein[http://madeleine.sourceforge.net] for persistence (all pages are in memory)
+* Three markup choices: Textile[http://www.textism.com/tools/textile]
+ (default / RedCloth[http://www.whytheluckystiff.net/ruby/redcloth]),
+ Markdown (BlueCloth[http://bluecloth.rubyforge.org]), and RDoc[http://rdoc.sourceforge.net/doc]
+* Embedded webserver: Through WEBrick[http://www.webrick.org]
+* Internationalization: Wiki words in any latin, greek, cyrillian, or armenian characters
+* Color diffs: Track changes through revisions
+
+===Missing:
+* File attachments
+
+===Install from gem:
+* Install rubygems
+* Run "gem install instiki"
+* Change to a directory where you want Instiki to keep its data files (for example, ~/instiki/)
+* Run "instiki" - this will create a "storage" directory (for example, ~/instiki/storage), and start a new Wiki service
+
+Make sure that you always launch Instiki from the same working directory, or specify the storage directory in runtime parameters, such as:
+ instiki --storage ~/instiki/storage
+
+===Command-line options:
+* Run "instiki --help"
+
+===History:
+ * See CHANGELOG
+
+===Download latest from:
+* http://rubyforge.org/project/showfiles.php?group_id=186
+
+===Visit the official Instiki wiki:
+* http://www.instiki.org
+
+===License:
+* same as Ruby's
+
+---
+Author:: David Heinemeier Hansson
+Email:: david@loudthinking.com
+Weblog:: http://www.loudthinking.com
+
+
diff --git a/app/models/page.rb b/app/models/page.rb
index 8f2ef436..dfd5b87c 100644
--- a/app/models/page.rb
+++ b/app/models/page.rb
@@ -1,137 +1,137 @@
-class Page < ActiveRecord::Base
- belongs_to :web
- has_many :revisions, :order => 'id'
- has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
-
- def revise(content, time, author)
- revisions_size = new_record? ? 0 : revisions.size
- if (revisions_size > 0) and content == current_revision.content
- raise Instiki::ValidationError.new(
- "You have tried to save page '#{name}' without changing its content")
- end
-
- author = Author.new(author.to_s) unless author.is_a?(Author)
-
- # Try to render content to make sure that markup engine can take it,
- Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
-
- # A user may change a page, look at it and make some more changes - several times.
- # Not to record every such iteration as a new revision, if the previous revision was done
- # by the same author, not more than 30 minutes ago, then update the last revision instead of
- # creating a new one
- if (revisions_size > 0) && continous_revision?(time, author)
- current_revision.update_attributes(:content => content, :revised_at => time)
- else
- Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
- end
-
- save
- web.refresh_pages_with_references(name) if revisions_size == 0
-
- self
- end
-
- def rollback(revision_number, time, author_ip = nil)
- roll_back_revision = self.revisions[revision_number]
- if roll_back_revision.nil?
- raise Instiki::ValidationError.new("Revision #{revision_number} not found")
- end
- revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
- end
-
- def revisions?
- revisions.size > 1
- end
-
- def previous_revision(revision)
- revision_index = revisions.each_with_index do |rev, index|
- if rev.id == revision.id
- break index
- else
- nil
- end
- end
- if revision_index.nil? or revision_index == 0
- nil
- else
- revisions[revision_index - 1]
- end
- end
-
- def in_category?(cat)
- cat.nil? || cat.empty? || categories.include?(cat)
- end
-
- def categories
- display_content.find_chunks(Category).map { |cat| cat.list }.flatten
- end
-
- def authors
- revisions.collect { |rev| rev.author }
- end
-
- def references
- web.select.pages_that_reference(name)
- end
-
- def linked_from
- web.select.pages_that_link_to(name)
- end
-
- def included_from
- web.select.pages_that_include(name)
- end
-
- # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
- def plain_name
- web.brackets_only? ? name : WikiWords.separate(name)
- end
-
- # used to build chunk ids.
- #def id
- # @id ||= name.unpack('H*').first
- #end
-
- def link(options = {})
- web.make_link(name, nil, options)
- end
-
- def author_link(options = {})
- web.make_link(author, nil, options)
- end
-
- LOCKING_PERIOD = 30.minutes
-
- def lock(time, locked_by)
- update_attributes(:locked_at => time, :locked_by => locked_by)
- end
-
- def lock_duration(time)
- ((time - locked_at) / 60).to_i unless locked_at.nil?
- end
-
- def unlock
- update_attribute(:locked_at, nil)
- end
-
- def locked?(comparison_time)
- locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
- end
-
- private
-
- def continous_revision?(time, author)
- (current_revision.author == author) && (revised_at + 30.minutes > time)
- end
-
- # Forward method calls to the current revision, so the page responds to all revision calls
- def method_missing(method_id, *args, &block)
- method_name = method_id.to_s
- # Perform a hand-off to AR::Base#method_missing
- if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
- super(method_id, *args, &block)
- else
- current_revision.send(method_id)
- end
- end
+class Page < ActiveRecord::Base
+ belongs_to :web
+ has_many :revisions, :order => 'id'
+ has_one :current_revision, :class_name => 'Revision', :order => 'id DESC'
+
+ def revise(content, time, author)
+ revisions_size = new_record? ? 0 : revisions.size
+ if (revisions_size > 0) and content == current_revision.content
+ raise Instiki::ValidationError.new(
+ "You have tried to save page '#{name}' without changing its content")
+ end
+
+ author = Author.new(author.to_s) unless author.is_a?(Author)
+
+ # Try to render content to make sure that markup engine can take it,
+ Revision.new(:page => self, :content => content, :author => author, :revised_at => time).force_rendering
+
+ # A user may change a page, look at it and make some more changes - several times.
+ # Not to record every such iteration as a new revision, if the previous revision was done
+ # by the same author, not more than 30 minutes ago, then update the last revision instead of
+ # creating a new one
+ if (revisions_size > 0) && continous_revision?(time, author)
+ current_revision.update_attributes(:content => content, :revised_at => time)
+ else
+ Revision.create(:page => self, :content => content, :author => author, :revised_at => time)
+ end
+
+ save
+ web.refresh_pages_with_references(name) if revisions_size == 0
+
+ self
+ end
+
+ def rollback(revision_number, time, author_ip = nil)
+ roll_back_revision = self.revisions[revision_number]
+ if roll_back_revision.nil?
+ raise Instiki::ValidationError.new("Revision #{revision_number} not found")
+ end
+ revise(roll_back_revision.content, time, Author.new(roll_back_revision.author, author_ip))
+ end
+
+ def revisions?
+ revisions.size > 1
+ end
+
+ def previous_revision(revision)
+ revision_index = revisions.each_with_index do |rev, index|
+ if rev.id == revision.id
+ break index
+ else
+ nil
+ end
+ end
+ if revision_index.nil? or revision_index == 0
+ nil
+ else
+ revisions[revision_index - 1]
+ end
+ end
+
+ def in_category?(cat)
+ cat.nil? || cat.empty? || categories.include?(cat)
+ end
+
+ def categories
+ display_content.find_chunks(Category).map { |cat| cat.list }.flatten
+ end
+
+ def authors
+ revisions.collect { |rev| rev.author }
+ end
+
+ def references
+ web.select.pages_that_reference(name)
+ end
+
+ def linked_from
+ web.select.pages_that_link_to(name)
+ end
+
+ def included_from
+ web.select.pages_that_include(name)
+ end
+
+ # Returns the original wiki-word name as separate words, so "MyPage" becomes "My Page".
+ def plain_name
+ web.brackets_only? ? name : WikiWords.separate(name)
+ end
+
+ # used to build chunk ids.
+ #def id
+ # @id ||= name.unpack('H*').first
+ #end
+
+ def link(options = {})
+ web.make_link(name, nil, options)
+ end
+
+ def author_link(options = {})
+ web.make_link(author, nil, options)
+ end
+
+ LOCKING_PERIOD = 30.minutes
+
+ def lock(time, locked_by)
+ update_attributes(:locked_at => time, :locked_by => locked_by)
+ end
+
+ def lock_duration(time)
+ ((time - locked_at) / 60).to_i unless locked_at.nil?
+ end
+
+ def unlock
+ update_attribute(:locked_at, nil)
+ end
+
+ def locked?(comparison_time)
+ locked_at + LOCKING_PERIOD > comparison_time unless locked_at.nil?
+ end
+
+ private
+
+ def continous_revision?(time, author)
+ (current_revision.author == author) && (revised_at + 30.minutes > time)
+ end
+
+ # Forward method calls to the current revision, so the page responds to all revision calls
+ def method_missing(method_id, *args, &block)
+ method_name = method_id.to_s
+ # Perform a hand-off to AR::Base#method_missing
+ if @attributes.include?(method_name) or md = /(=|\?|_before_type_cast)$/.match(method_name)
+ super(method_id, *args, &block)
+ else
+ current_revision.send(method_id)
+ end
+ end
end
diff --git a/app/models/revision.rb b/app/models/revision.rb
index 9aab6370..56d818ce 100644
--- a/app/models/revision.rb
+++ b/app/models/revision.rb
@@ -1,105 +1,105 @@
-require 'diff'
-class Revision < ActiveRecord::Base
- belongs_to :page
- composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
-
- # Returns an array of all the WikiIncludes present in the content of this revision.
- def wiki_includes
- unless @wiki_includes_cache
- chunks = display_content.find_chunks(Include)
- @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_includes_cache
- end
-
- # Returns an array of all the WikiReferences present in the content of this revision.
- def wiki_references
- unless @wiki_references_cache
- chunks = display_content.find_chunks(WikiChunk::WikiReference)
- @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_references_cache
- end
-
- # Returns an array of all the WikiWords present in the content of this revision.
- def wiki_words
- unless @wiki_words_cache
- wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
- @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
- end
- @wiki_words_cache
- end
-
- # Returns an array of all the WikiWords present in the content of this revision.
- # that already exists as a page in the web.
- def existing_pages
- wiki_words.select { |wiki_word| page.web.page(wiki_word) }
- end
-
- # Returns an array of all the WikiWords present in the content of this revision
- # that *doesn't* already exists as a page in the web.
- def unexisting_pages
- wiki_words - existing_pages
- end
-
- # Explicit check for new type of display cache with chunks_by_type method.
- # Ensures new version works with older snapshots.
- def display_content
- unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
- @display_cache = WikiContent.new(self)
- @display_cache.render!
- end
- @display_cache
- end
-
- # TODO this probably doesn't belong in revision (because it has to call back the page)
- def display_diff
- previous_revision = page.previous_revision(self)
- if previous_revision
- HTMLDiff.diff(previous_revision.display_content, display_content)
- else
- display_content
- end
- end
-
- def clear_display_cache
- @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
- @wiki_references_cache = nil
- end
-
- def display_published
- unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
- @published_cache = WikiContent.new(self, {:mode => :publish})
- @published_cache.render!
- end
- @published_cache
- end
-
- def display_content_for_export
- WikiContent.new(self, {:mode => :export} ).render!
- end
-
- def force_rendering
- begin
- display_content.render!
- rescue => e
- logger.error "Failed rendering page #{@name}"
- logger.error e
- message = e.message
- # substitute content with an error message
- self.content = <<-EOL
- #{self.content}
- EOL
- clear_display_cache
- raise e
- end
- end
-
- protected
-
- after_create :force_rendering
- after_save :clear_display_cache
-
+require 'diff'
+class Revision < ActiveRecord::Base
+ belongs_to :page
+ composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
+
+ # Returns an array of all the WikiIncludes present in the content of this revision.
+ def wiki_includes
+ unless @wiki_includes_cache
+ chunks = display_content.find_chunks(Include)
+ @wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_includes_cache
+ end
+
+ # Returns an array of all the WikiReferences present in the content of this revision.
+ def wiki_references
+ unless @wiki_references_cache
+ chunks = display_content.find_chunks(WikiChunk::WikiReference)
+ @wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_references_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ def wiki_words
+ unless @wiki_words_cache
+ wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
+ @wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
+ end
+ @wiki_words_cache
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision.
+ # that already exists as a page in the web.
+ def existing_pages
+ wiki_words.select { |wiki_word| page.web.page(wiki_word) }
+ end
+
+ # Returns an array of all the WikiWords present in the content of this revision
+ # that *doesn't* already exists as a page in the web.
+ def unexisting_pages
+ wiki_words - existing_pages
+ end
+
+ # Explicit check for new type of display cache with chunks_by_type method.
+ # Ensures new version works with older snapshots.
+ def display_content
+ unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
+ @display_cache = WikiContent.new(self)
+ @display_cache.render!
+ end
+ @display_cache
+ end
+
+ # TODO this probably doesn't belong in revision (because it has to call back the page)
+ def display_diff
+ previous_revision = page.previous_revision(self)
+ if previous_revision
+ HTMLDiff.diff(previous_revision.display_content, display_content)
+ else
+ display_content
+ end
+ end
+
+ def clear_display_cache
+ @wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
+ @wiki_references_cache = nil
+ end
+
+ def display_published
+ unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
+ @published_cache = WikiContent.new(self, {:mode => :publish})
+ @published_cache.render!
+ end
+ @published_cache
+ end
+
+ def display_content_for_export
+ WikiContent.new(self, {:mode => :export} ).render!
+ end
+
+ def force_rendering
+ begin
+ display_content.render!
+ rescue => e
+ logger.error "Failed rendering page #{@name}"
+ logger.error e
+ message = e.message
+ # substitute content with an error message
+ self.content = <<-EOL
+ #{self.content}
+ EOL
+ clear_display_cache
+ raise e
+ end
+ end
+
+ protected
+
+ after_create :force_rendering
+ after_save :clear_display_cache
+
end
diff --git a/app/models/web.rb b/app/models/web.rb
index be520aba..13cb6f31 100644
--- a/app/models/web.rb
+++ b/app/models/web.rb
@@ -1,173 +1,173 @@
-require 'cgi'
-
-class Web < ActiveRecord::Base
- has_many :pages#, :include => [:current_revision, :web]
-
- def wiki
- Wiki.new
- end
-
- def file_yard
- @file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
- end
-
- def settings_changed?(markup, safe_mode, brackets_only)
- self.markup != markup ||
- self.safe_mode != safe_mode ||
- self.brackets_only != brackets_only
- end
-
- def add_page(name, content, time, author)
- page = page(name) || Page.new(:web => self, :name => name)
- page.revise(content, time, author)
- end
-
- def authors
- select.authors
- end
-
- def categories
- select.map { |page| page.categories }.flatten.uniq.sort
- end
-
- def page(name)
- pages.find(:first, :conditions => ['name = ?', name])
- end
-
- def has_page?(name)
- Page.count(['web_id = ? AND name = ?', id, name]) > 0
- end
-
- def has_file?(name)
- wiki.file_yard(self).has_file?(name)
- end
-
- def markup
- read_attribute('markup').to_sym
- end
-
- def make_file_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode
- when :export
- if has_file?(name) then "#{text}"
- else "#{text}" end
- when :publish
- if has_file?(name) then "#{text}"
- else "#{text}" end
- else
- if has_file?(name)
- "#{text}"
- else
- "#{text}?"
- end
- end
- end
-
- # Create a link for the given page name and link text based
- # on the render mode in options and whether the page exists
- # in the this web.
- # The links a relative, and will work only if displayed on another WikiPage.
- # It should not be used in menus, templates and such - instead, use link_to_page helper
- def make_link(name, text = nil, options = {})
- text = CGI.escapeHTML(text || WikiWords.separate(name))
- mode = options[:mode] || :show
- base_url = options[:base_url] || '..'
- link_type = options[:link_type] || :show
- case link_type.to_sym
- when :show
- make_page_link(mode, name, text, base_url)
- when :file
- make_file_link(mode, name, text, base_url)
- when :pic
- make_pic_link(mode, name, text, base_url)
- else
- raise "Unknown link type: #{link_type}"
- end
- end
-
- def make_page_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode.to_sym
- when :export
- if has_page?(name) then %{#{text}}
- else %{#{text}} end
- when :publish
- if has_page?(name) then %{#{text}}
- else %{#{text}} end
- else
- if has_page?(name)
- %{#{text}}
- else
- %{#{text}?}
- end
- end
- end
-
- def make_pic_link(mode, name, text, base_url)
- link = CGI.escape(name)
- case mode.to_sym
- when :export
- if has_file?(name) then %{}
- else %{} end
- when :publish
- if has_file?(name) then %{}
- else %{#{text}} end
- else
- if has_file?(name) then %{}
- else %{#{text}?} end
- end
- end
-
- # Clears the display cache for all the pages with references to
- def refresh_pages_with_references(page_name)
- #select.pages_that_reference(page_name).each { |page|
- # page.revisions.each { |revision| revision.clear_display_cache }
- #}
- end
-
- def refresh_revisions
- select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
- end
-
- def remove_pages(pages_to_be_removed)
- pages_to_be_removed.each { |p| p.destroy }
- end
-
- def revised_at
- select.most_recent_revision
- end
-
- def select(&condition)
- PageSet.new(self, pages, condition)
- end
-
- private
-
- # Returns an array of all the wiki words in any current revision
- def wiki_words
- pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
- end
-
- # Returns an array of all the page names on this web
- def page_names
- pages.map { |p| p.name }
- end
-
- protected
- before_save :sanitize_markup
- before_validation :validate_address
- validates_uniqueness_of :address
- validates_length_of :color, :in => 3..6
-
- def sanitize_markup
- self.markup = markup.to_s
- end
-
- def validate_address
- unless address == CGI.escape(address)
- self.errors.add(:address, 'should contain only valid URI characters')
- raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
- end
- end
+require 'cgi'
+
+class Web < ActiveRecord::Base
+ has_many :pages#, :include => [:current_revision, :web]
+
+ def wiki
+ Wiki.new
+ end
+
+ def file_yard
+ @file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
+ end
+
+ def settings_changed?(markup, safe_mode, brackets_only)
+ self.markup != markup ||
+ self.safe_mode != safe_mode ||
+ self.brackets_only != brackets_only
+ end
+
+ def add_page(name, content, time, author)
+ page = page(name) || Page.new(:web => self, :name => name)
+ page.revise(content, time, author)
+ end
+
+ def authors
+ select.authors
+ end
+
+ def categories
+ select.map { |page| page.categories }.flatten.uniq.sort
+ end
+
+ def page(name)
+ pages.find(:first, :conditions => ['name = ?', name])
+ end
+
+ def has_page?(name)
+ Page.count(['web_id = ? AND name = ?', id, name]) > 0
+ end
+
+ def has_file?(name)
+ wiki.file_yard(self).has_file?(name)
+ end
+
+ def markup
+ read_attribute('markup').to_sym
+ end
+
+ def make_file_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode
+ when :export
+ if has_file?(name) then "#{text}"
+ else "#{text}" end
+ when :publish
+ if has_file?(name) then "#{text}"
+ else "#{text}" end
+ else
+ if has_file?(name)
+ "#{text}"
+ else
+ "#{text}?"
+ end
+ end
+ end
+
+ # Create a link for the given page name and link text based
+ # on the render mode in options and whether the page exists
+ # in the this web.
+ # The links a relative, and will work only if displayed on another WikiPage.
+ # It should not be used in menus, templates and such - instead, use link_to_page helper
+ def make_link(name, text = nil, options = {})
+ text = CGI.escapeHTML(text || WikiWords.separate(name))
+ mode = options[:mode] || :show
+ base_url = options[:base_url] || '..'
+ link_type = options[:link_type] || :show
+ case link_type.to_sym
+ when :show
+ make_page_link(mode, name, text, base_url)
+ when :file
+ make_file_link(mode, name, text, base_url)
+ when :pic
+ make_pic_link(mode, name, text, base_url)
+ else
+ raise "Unknown link type: #{link_type}"
+ end
+ end
+
+ def make_page_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if has_page?(name) then %{#{text}}
+ else %{#{text}} end
+ when :publish
+ if has_page?(name) then %{#{text}}
+ else %{#{text}} end
+ else
+ if has_page?(name)
+ %{#{text}}
+ else
+ %{#{text}?}
+ end
+ end
+ end
+
+ def make_pic_link(mode, name, text, base_url)
+ link = CGI.escape(name)
+ case mode.to_sym
+ when :export
+ if has_file?(name) then %{}
+ else %{} end
+ when :publish
+ if has_file?(name) then %{}
+ else %{#{text}} end
+ else
+ if has_file?(name) then %{}
+ else %{#{text}?} end
+ end
+ end
+
+ # Clears the display cache for all the pages with references to
+ def refresh_pages_with_references(page_name)
+ #select.pages_that_reference(page_name).each { |page|
+ # page.revisions.each { |revision| revision.clear_display_cache }
+ #}
+ end
+
+ def refresh_revisions
+ select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
+ end
+
+ def remove_pages(pages_to_be_removed)
+ pages_to_be_removed.each { |p| p.destroy }
+ end
+
+ def revised_at
+ select.most_recent_revision
+ end
+
+ def select(&condition)
+ PageSet.new(self, pages, condition)
+ end
+
+ private
+
+ # Returns an array of all the wiki words in any current revision
+ def wiki_words
+ pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
+ end
+
+ # Returns an array of all the page names on this web
+ def page_names
+ pages.map { |p| p.name }
+ end
+
+ protected
+ before_save :sanitize_markup
+ before_validation :validate_address
+ validates_uniqueness_of :address
+ validates_length_of :color, :in => 3..6
+
+ def sanitize_markup
+ self.markup = markup.to_s
+ end
+
+ def validate_address
+ unless address == CGI.escape(address)
+ self.errors.add(:address, 'should contain only valid URI characters')
+ raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
+ end
+ end
end
diff --git a/instiki.gemspec b/instiki.gemspec
index adf1dd74..c65ac414 100755
--- a/instiki.gemspec
+++ b/instiki.gemspec
@@ -1,44 +1,44 @@
-$__instiki_source_patterns = [
- '[A-Z]*', 'instiki', 'instiki.rb', 'app/**/*', 'lib/**/*', 'vendor/**/*',
- 'public/**/*', 'natives/**/*', 'config/**/*', 'script/**/*'
-]
-
-spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = 'instiki'
- s.version = "0.10.2"
- s.summary = 'Easy to install WikiClone running on WEBrick and SQLite'
- s.description = <<-EOF
- Instiki is a Wiki Clone written in Ruby that ships with an embedded
- webserver. You can setup up an Instiki in just a few steps.
- Possibly the simplest wiki setup ever.
- EOF
- s.author = 'David Heinemeier Hansson'
- s.email = 'david@loudthinking.com'
- s.rubyforge_project = 'instiki'
- s.homepage = 'http://www.instiki.org'
-
- s.bindir = '.'
- s.executables = ['instiki']
- s.default_executable = 'instiki'
-
- s.has_rdoc = false
-
- s.add_dependency('RedCloth', '= 3.0.3')
- s.add_dependency('rubyzip', '= 0.5.8')
- s.add_dependency('rails', '= 0.13.1')
- s.add_dependency('sqlite3-ruby', '= 1.1.0')
- s.requirements << 'none'
- s.require_path = 'lib'
-
- s.files = $__instiki_source_patterns.inject([]) { |list, glob|
- list << Dir[glob].delete_if { |path|
- File.directory?(path) or
- path.include?('.svn/') or
- path.include?('vendor/') or
- path.include?('test/') or
- path.include?('_test.rb')
- }
- }.flatten
-
-end
+$__instiki_source_patterns = [
+ '[A-Z]*', 'instiki', 'instiki.rb', 'app/**/*', 'lib/**/*', 'vendor/**/*',
+ 'public/**/*', 'natives/**/*', 'config/**/*', 'script/**/*'
+]
+
+spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'instiki'
+ s.version = "0.10.2"
+ s.summary = 'Easy to install WikiClone running on WEBrick and SQLite'
+ s.description = <<-EOF
+ Instiki is a Wiki Clone written in Ruby that ships with an embedded
+ webserver. You can setup up an Instiki in just a few steps.
+ Possibly the simplest wiki setup ever.
+ EOF
+ s.author = 'David Heinemeier Hansson'
+ s.email = 'david@loudthinking.com'
+ s.rubyforge_project = 'instiki'
+ s.homepage = 'http://www.instiki.org'
+
+ s.bindir = '.'
+ s.executables = ['instiki']
+ s.default_executable = 'instiki'
+
+ s.has_rdoc = false
+
+ s.add_dependency('RedCloth', '= 3.0.3')
+ s.add_dependency('rubyzip', '= 0.5.8')
+ s.add_dependency('rails', '= 0.13.1')
+ s.add_dependency('sqlite3-ruby', '= 1.1.0')
+ s.requirements << 'none'
+ s.require_path = 'lib'
+
+ s.files = $__instiki_source_patterns.inject([]) { |list, glob|
+ list << Dir[glob].delete_if { |path|
+ File.directory?(path) or
+ path.include?('.svn/') or
+ path.include?('vendor/') or
+ path.include?('test/') or
+ path.include?('_test.rb')
+ }
+ }.flatten
+
+end
diff --git a/lib/db_structure.rb b/lib/db_structure.rb
index 09c212da..d92bb4e4 100644
--- a/lib/db_structure.rb
+++ b/lib/db_structure.rb
@@ -1,46 +1,46 @@
-require 'erb'
-
-def create_options
- if @db == 'mysql'
- 'ENGINE = ' + (mysql_engine rescue @mysql_engine)
- end
-end
-
-def db_quote(column)
- case @db
- when 'postgresql'
- return "\"#{column}\""
- when 'sqlite', 'sqlite3'
- return "'#{column}'"
- when 'mysql'
- return "`#{column}`"
- end
-end
-
-def db_structure(db)
- db.downcase!
- @db = db
- case db
- when 'postgresql'
- @pk = 'SERIAL PRIMARY KEY'
- @datetime = 'TIMESTAMP'
- @boolean = "BOOLEAN"
- when 'sqlite', 'sqlite3'
- @pk = 'INTEGER PRIMARY KEY'
- @datetime = 'DATETIME'
- @boolean = "INTEGER"
- when 'mysql'
- @pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
- @datetime = 'DATETIME'
- @boolean = "TINYINT"
- @mysql_engine = 'InnoDB'
- else
- raise "Unknown db type #{db}"
- end
-
- s = ''
- Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
- s += ERB.new(File.read(filename)).result
- end
- s
-end
+require 'erb'
+
+def create_options
+ if @db == 'mysql'
+ 'ENGINE = ' + (mysql_engine rescue @mysql_engine)
+ end
+end
+
+def db_quote(column)
+ case @db
+ when 'postgresql'
+ return "\"#{column}\""
+ when 'sqlite', 'sqlite3'
+ return "'#{column}'"
+ when 'mysql'
+ return "`#{column}`"
+ end
+end
+
+def db_structure(db)
+ db.downcase!
+ @db = db
+ case db
+ when 'postgresql'
+ @pk = 'SERIAL PRIMARY KEY'
+ @datetime = 'TIMESTAMP'
+ @boolean = "BOOLEAN"
+ when 'sqlite', 'sqlite3'
+ @pk = 'INTEGER PRIMARY KEY'
+ @datetime = 'DATETIME'
+ @boolean = "INTEGER"
+ when 'mysql'
+ @pk = 'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY'
+ @datetime = 'DATETIME'
+ @boolean = "TINYINT"
+ @mysql_engine = 'InnoDB'
+ else
+ raise "Unknown db type #{db}"
+ end
+
+ s = ''
+ Dir[RAILS_ROOT + '/db/*.erbsql'].each do |filename|
+ s += ERB.new(File.read(filename)).result
+ end
+ s
+end
diff --git a/test/fixtures/pages.yml b/test/fixtures/pages.yml
index f7add425..65fba487 100644
--- a/test/fixtures/pages.yml
+++ b/test/fixtures/pages.yml
@@ -1,55 +1,55 @@
-home_page:
- id: 1
- created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- web_id: 1
- name: HomePage
-
-my_way:
- id: 2
- created_at: <%= 9.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: MyWay
-
-smart_engine:
- id: 3
- created_at: <%= 8.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: SmartEngine
-
-that_way:
- id: 4
- created_at: <%= 7.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: ThatWay
-
-no_wiki_word:
- id: 5
- created_at: <%= 6.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: NoWikiWord
-
-first_page:
- id: 6
- created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- web_id: 1
- name: FirstPage
-
-oak:
- id: 7
- created_at: <%= 5.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
- web_id: 1
- name: Oak
-
-elephant:
- id: 8
- created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- web_id: 1
+home_page:
+ id: 1
+ created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ web_id: 1
+ name: HomePage
+
+my_way:
+ id: 2
+ created_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: MyWay
+
+smart_engine:
+ id: 3
+ created_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: SmartEngine
+
+that_way:
+ id: 4
+ created_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: ThatWay
+
+no_wiki_word:
+ id: 5
+ created_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: NoWikiWord
+
+first_page:
+ id: 6
+ created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ web_id: 1
+ name: FirstPage
+
+oak:
+ id: 7
+ created_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ web_id: 1
+ name: Oak
+
+elephant:
+ id: 8
+ created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ web_id: 1
name: Elephant
\ No newline at end of file
diff --git a/test/fixtures/revisions.yml b/test/fixtures/revisions.yml
index 77585e99..d65c2bd2 100644
--- a/test/fixtures/revisions.yml
+++ b/test/fixtures/revisions.yml
@@ -1,83 +1,83 @@
-home_page_first_revision:
- id: 1
- created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
- revised_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
- page_id: 1
- content: First revision of the HomePage end
- author: AnAuthor
- ip: 127.0.0.1
-
-my_way_first_revision:
- id: 2
- created_at: <%= 9.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 9.days.ago.to_formatted_s(:db) %>
- page_id: 2
- content: MyWay
- author: Me
-
-smart_engine_first_revision:
- id: 3
- created_at: <%= 8.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 8.days.ago.to_formatted_s(:db) %>
- page_id: 3
- content: SmartEngine
- author: Me
-
-that_way_first_revision:
- id: 4
- created_at: <%= 7.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 7.days.ago.to_formatted_s(:db) %>
- page_id: 4
- content: ThatWay
- author: Me
-
-no_wiki_word_first_revision:
- id: 5
- created_at: <%= 6.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 6.days.ago.to_formatted_s(:db) %>
- page_id: 5
- content: hey you
- author: Me
-
-home_page_second_revision:
- id: 6
- created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- revised_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
- page_id: 1
- content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
- author: DavidHeinemeierHansson
-
-first_page_first_revision:
- id: 7
- created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- revised_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
- page_id: 6
- content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
- author: DavidHeinemeierHansson
-
-oak_first_revision:
- id: 8
- created_at: <%= 5.days.ago.to_formatted_s(:db) %>
- updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
- revised_at: <%= 5.days.ago.to_formatted_s(:db) %>
- page_id: 7
- content: "All about oak.\ncategory: trees"
- author: TreeHugger
- ip: 127.0.0.2
-
-elephant_first_revision:
- id: 9
- created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- revised_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
- page_id: 8
- content: "All about elephants.\ncategory: animals"
- author: Guest
- ip: 127.0.0.2
+home_page_first_revision:
+ id: 1
+ created_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
+ revised_at: <%= Time.local(2004, 4, 4, 15, 50).to_formatted_s(:db) %>
+ page_id: 1
+ content: First revision of the HomePage end
+ author: AnAuthor
+ ip: 127.0.0.1
+
+my_way_first_revision:
+ id: 2
+ created_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 9.days.ago.to_formatted_s(:db) %>
+ page_id: 2
+ content: MyWay
+ author: Me
+
+smart_engine_first_revision:
+ id: 3
+ created_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 8.days.ago.to_formatted_s(:db) %>
+ page_id: 3
+ content: SmartEngine
+ author: Me
+
+that_way_first_revision:
+ id: 4
+ created_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 7.days.ago.to_formatted_s(:db) %>
+ page_id: 4
+ content: ThatWay
+ author: Me
+
+no_wiki_word_first_revision:
+ id: 5
+ created_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 6.days.ago.to_formatted_s(:db) %>
+ page_id: 5
+ content: hey you
+ author: Me
+
+home_page_second_revision:
+ id: 6
+ created_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ revised_at: <%= Time.local(2004, 4, 4, 16, 50).to_formatted_s(:db) %>
+ page_id: 1
+ content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \OverThere -- see SmartEngine in that SmartEngineGUI
+ author: DavidHeinemeierHansson
+
+first_page_first_revision:
+ id: 7
+ created_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ updated_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ revised_at: <%= Time.local(2004, 4, 4, 16, 55).to_formatted_s(:db) %>
+ page_id: 6
+ content: HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\OverThere -- see SmartEngine in that SmartEngineGUI
+ author: DavidHeinemeierHansson
+
+oak_first_revision:
+ id: 8
+ created_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ updated_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ revised_at: <%= 5.days.ago.to_formatted_s(:db) %>
+ page_id: 7
+ content: "All about oak.\ncategory: trees"
+ author: TreeHugger
+ ip: 127.0.0.2
+
+elephant_first_revision:
+ id: 9
+ created_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ updated_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ revised_at: <%= 10.minutes.ago.to_formatted_s(:db) %>
+ page_id: 8
+ content: "All about elephants.\ncategory: animals"
+ author: Guest
+ ip: 127.0.0.2
diff --git a/test/fixtures/webs.yml b/test/fixtures/webs.yml
index 29c89566..05437295 100644
--- a/test/fixtures/webs.yml
+++ b/test/fixtures/webs.yml
@@ -1,15 +1,15 @@
-test_wiki:
- id: 1
- created_at: 2004-08-01
- updated_at: 2005-08-01
- name: wiki1
- address: wiki1
- markup: textile
-
-instiki:
- id: 2
- created_at: 2004-08-01
- updated_at: 2005-08-01
- name: Instiki
- address: instiki
+test_wiki:
+ id: 1
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ name: wiki1
+ address: wiki1
+ markup: textile
+
+instiki:
+ id: 2
+ created_at: 2004-08-01
+ updated_at: 2005-08-01
+ name: Instiki
+ address: instiki
markup: textile
\ No newline at end of file
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 0b29f757..955b059e 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -1,106 +1,106 @@
-ENV["RAILS_ENV"] = "test"
-
-# Expand the path to environment so that Ruby does not load it multiple times
-# File.expand_path can be removed if Ruby 1.9 is in use.
-require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
-require 'application'
-
-require 'test/unit'
-require 'active_record/fixtures'
-require 'action_controller/test_process'
-require 'action_web_service/test_invoke'
-require 'breakpoint'
-require 'wiki_content'
-
-# Uncomment these and hang on, because the tests will be FAST
-#Test::Unit::TestCase.pre_loaded_fixtures = false
-#Test::Unit::TestCase.use_transactional_fixtures = true
-
-Test::Unit::TestCase.use_instantiated_fixtures = false
-Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
-
-class Test::Unit::TestCase
- def create_fixtures(*table_names)
- Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
- end
-
- # Add more helper methods to be used by all tests here...
- def set_web_property(property, value)
- @web.update_attribute(property, value)
- @page = Page.find(@page.id)
- @wiki.webs[@web.name] = @web
- end
-
- def setup_wiki_with_30_pages
- ActiveRecord::Base.silence do
- (1..30).each do |i|
- @wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
- Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
- end
- end
- @web = Web.find(@web.id)
- end
-
- def use_blank_wiki
- Revision.destroy_all
- Page.destroy_all
- Web.destroy_all
- end
-end
-
-# This module is to be included in unit tests that involve matching chunks.
-# It provides a easy way to test whether a chunk matches a particular string
-# and any the values of any fields that should be set after a match.
-class ContentStub < String
- include ChunkManager
- def initialize(str)
- super
- init_chunk_manager
- end
- def page_link(*); end
-end
-
-module ChunkMatch
-
- # Asserts a number of tests for the given type and text.
- def match(chunk_type, test_text, expected_chunk_state)
- if chunk_type.respond_to? :pattern
- assert_match(chunk_type.pattern, test_text)
- end
-
- content = ContentStub.new(test_text)
- chunk_type.apply_to(content)
-
- # Test if requested parts are correct.
- expected_chunk_state.each_pair do |a_method, expected_value|
- assert content.chunks.last.kind_of?(chunk_type)
- assert_respond_to(content.chunks.last, a_method)
- assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
- "Wrong #{a_method} value")
- end
- end
-
- # Asserts that test_text doesn't match the chunk_type
- def no_match(chunk_type, test_text)
- if chunk_type.respond_to? :pattern
- assert_no_match(chunk_type.pattern, test_text)
- end
- end
-end
-
-if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
- module Test
- module Unit
- module Assertions
- unless method_defined? :__assert_success_before_override_by_instiki
- alias :__assert_success_before_override_by_instiki :assert_success
- end
- def assert_success
- __assert_success_before_override_by_instiki
- if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
- else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
- end
- end
- end
- end
-end
+ENV["RAILS_ENV"] = "test"
+
+# Expand the path to environment so that Ruby does not load it multiple times
+# File.expand_path can be removed if Ruby 1.9 is in use.
+require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
+require 'application'
+
+require 'test/unit'
+require 'active_record/fixtures'
+require 'action_controller/test_process'
+require 'action_web_service/test_invoke'
+require 'breakpoint'
+require 'wiki_content'
+
+# Uncomment these and hang on, because the tests will be FAST
+#Test::Unit::TestCase.pre_loaded_fixtures = false
+#Test::Unit::TestCase.use_transactional_fixtures = true
+
+Test::Unit::TestCase.use_instantiated_fixtures = false
+Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
+
+class Test::Unit::TestCase
+ def create_fixtures(*table_names)
+ Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_names)
+ end
+
+ # Add more helper methods to be used by all tests here...
+ def set_web_property(property, value)
+ @web.update_attribute(property, value)
+ @page = Page.find(@page.id)
+ @wiki.webs[@web.name] = @web
+ end
+
+ def setup_wiki_with_30_pages
+ ActiveRecord::Base.silence do
+ (1..30).each do |i|
+ @wiki.write_page('wiki1', "page#{i}", "Test page #{i}\ncategory: test",
+ Time.local(1976, 10, i, 12, 00, 00), Author.new('Dema', '127.0.0.2'))
+ end
+ end
+ @web = Web.find(@web.id)
+ end
+
+ def use_blank_wiki
+ Revision.destroy_all
+ Page.destroy_all
+ Web.destroy_all
+ end
+end
+
+# This module is to be included in unit tests that involve matching chunks.
+# It provides a easy way to test whether a chunk matches a particular string
+# and any the values of any fields that should be set after a match.
+class ContentStub < String
+ include ChunkManager
+ def initialize(str)
+ super
+ init_chunk_manager
+ end
+ def page_link(*); end
+end
+
+module ChunkMatch
+
+ # Asserts a number of tests for the given type and text.
+ def match(chunk_type, test_text, expected_chunk_state)
+ if chunk_type.respond_to? :pattern
+ assert_match(chunk_type.pattern, test_text)
+ end
+
+ content = ContentStub.new(test_text)
+ chunk_type.apply_to(content)
+
+ # Test if requested parts are correct.
+ expected_chunk_state.each_pair do |a_method, expected_value|
+ assert content.chunks.last.kind_of?(chunk_type)
+ assert_respond_to(content.chunks.last, a_method)
+ assert_equal(expected_value, content.chunks.last.send(a_method.to_sym),
+ "Wrong #{a_method} value")
+ end
+ end
+
+ # Asserts that test_text doesn't match the chunk_type
+ def no_match(chunk_type, test_text)
+ if chunk_type.respond_to? :pattern
+ assert_no_match(chunk_type.pattern, test_text)
+ end
+ end
+end
+
+if defined? $validate_xml_in_assert_success and $validate_xml_in_assert_success == true
+ module Test
+ module Unit
+ module Assertions
+ unless method_defined? :__assert_success_before_override_by_instiki
+ alias :__assert_success_before_override_by_instiki :assert_success
+ end
+ def assert_success
+ __assert_success_before_override_by_instiki
+ if @response.body.kind_of?(Proc) then # it's a file download, not an HTML content
+ else assert_nothing_raised(@response.body) { REXML::Document.new(@response.body) } end
+ end
+ end
+ end
+ end
+end
diff --git a/test/unit/page_test.rb b/test/unit/page_test.rb
index 4f75d872..b3568271 100644
--- a/test/unit/page_test.rb
+++ b/test/unit/page_test.rb
@@ -1,88 +1,88 @@
-require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
-
-class PageTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
-
- def setup
- @page = pages(:first_page)
- end
-
- def test_lock
- assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
-
- @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
-
- assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
- assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
-
- @page.unlock
-
- assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
- end
-
- def test_lock_duration
- @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
-
- assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
- end
-
- def test_plain_name
- assert_equal "First Page", @page.plain_name
- end
-
- def test_revise
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
- @page.reload
-
- assert_equal 2, @page.revisions.length, 'Should have two revisions'
- assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
- assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
- end
-
- def test_revise_continous_revision
- @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
- @page.reload
- assert_equal 2, @page.revisions.length
- assert_equal 'HisWay would be MyWay in kinda lame', @page.content
-
- # consecutive revision by the same author within 30 minutes doesn't create a new revision
- @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
- @page.reload
- assert_equal 2, @page.revisions.length
- assert_equal 'HisWay would be MyWay in kinda update', @page.content
- assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
-
- # but consecutive revision by another author results in a new revision
- @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
- @page.reload
- assert_equal 3, @page.revisions.length
- assert_equal 'HisWay would be MyWay in the house', @page.content
-
- # consecutive update after 30 minutes since the last one also creates a new revision,
- # even when it is by the same author
- @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
- @page.reload
- assert_equal 4, @page.revisions.length
- end
-
- def test_revise_content_unchanged
- last_revision_before = @page.current_revision
- revisions_number_before = @page.revisions.size
-
- assert_raises(Instiki::ValidationError) {
- @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
- }
-
- assert_equal last_revision_before, @page.current_revision(true)
- assert_equal revisions_number_before, @page.revisions.size
- end
-
- def test_rollback
- @page.revise("spot two", Time.now, "David")
- @page.revise("spot three", Time.now + 2000, "David")
- assert_equal 3, @page.revisions(true).length, "Should have three revisions"
- @page.current_revision(true)
- @page.rollback(0, Time.now)
- assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
- end
-end
+require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
+
+class PageTest < Test::Unit::TestCase
+ fixtures :webs, :pages, :revisions, :system
+
+ def setup
+ @page = pages(:first_page)
+ end
+
+ def test_lock
+ assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
+
+ @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
+
+ assert @page.locked?(Time.local(2004, 4, 4, 16, 50))
+ assert !@page.locked?(Time.local(2004, 4, 4, 17, 1))
+
+ @page.unlock
+
+ assert !@page.locked?(Time.local(2004, 4, 4, 16, 50))
+ end
+
+ def test_lock_duration
+ @page.lock(Time.local(2004, 4, 4, 16, 30), "DavidHeinemeierHansson")
+
+ assert_equal 15, @page.lock_duration(Time.local(2004, 4, 4, 16, 45))
+ end
+
+ def test_plain_name
+ assert_equal "First Page", @page.plain_name
+ end
+
+ def test_revise
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ @page.reload
+
+ assert_equal 2, @page.revisions.length, 'Should have two revisions'
+ assert_equal 'MarianneSyhler', @page.current_revision.author.to_s, 'Mary should be the author now'
+ assert_equal 'DavidHeinemeierHansson', @page.revisions.first.author.to_s, 'David was the first author'
+ end
+
+ def test_revise_continous_revision
+ @page.revise('HisWay would be MyWay in kinda lame', Time.local(2004, 4, 4, 16, 55), 'MarianneSyhler')
+ @page.reload
+ assert_equal 2, @page.revisions.length
+ assert_equal 'HisWay would be MyWay in kinda lame', @page.content
+
+ # consecutive revision by the same author within 30 minutes doesn't create a new revision
+ @page.revise('HisWay would be MyWay in kinda update', Time.local(2004, 4, 4, 16, 57), 'MarianneSyhler')
+ @page.reload
+ assert_equal 2, @page.revisions.length
+ assert_equal 'HisWay would be MyWay in kinda update', @page.content
+ assert_equal Time.local(2004, 4, 4, 16, 57), @page.revised_at
+
+ # but consecutive revision by another author results in a new revision
+ @page.revise('HisWay would be MyWay in the house', Time.local(2004, 4, 4, 16, 58), 'DavidHeinemeierHansson')
+ @page.reload
+ assert_equal 3, @page.revisions.length
+ assert_equal 'HisWay would be MyWay in the house', @page.content
+
+ # consecutive update after 30 minutes since the last one also creates a new revision,
+ # even when it is by the same author
+ @page.revise('HisWay would be MyWay in my way', Time.local(2004, 4, 4, 17, 30), 'DavidHeinemeierHansson')
+ @page.reload
+ assert_equal 4, @page.revisions.length
+ end
+
+ def test_revise_content_unchanged
+ last_revision_before = @page.current_revision
+ revisions_number_before = @page.revisions.size
+
+ assert_raises(Instiki::ValidationError) {
+ @page.revise(@page.current_revision.content, Time.now, 'AlexeyVerkhovsky')
+ }
+
+ assert_equal last_revision_before, @page.current_revision(true)
+ assert_equal revisions_number_before, @page.revisions.size
+ end
+
+ def test_rollback
+ @page.revise("spot two", Time.now, "David")
+ @page.revise("spot three", Time.now + 2000, "David")
+ assert_equal 3, @page.revisions(true).length, "Should have three revisions"
+ @page.current_revision(true)
+ @page.rollback(0, Time.now)
+ assert_equal "HisWay would be MyWay in kinda ThatWay in HisWay though MyWay \\\\OverThere -- see SmartEngine in that SmartEngineGUI", @page.current_revision(true).content
+ end
+end
diff --git a/test/unit/revision_test.rb b/test/unit/revision_test.rb
index d563ccde..f22bfd5d 100644
--- a/test/unit/revision_test.rb
+++ b/test/unit/revision_test.rb
@@ -1,317 +1,317 @@
-require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
-
-class RevisionTest < Test::Unit::TestCase
- fixtures :webs, :pages, :revisions, :system
-
- def setup
- @wiki = Wiki.new
- @web = webs(:test_wiki)
- @page = pages(:home_page)
- @revision = revisions(:home_page_second_revision)
- end
-
- def test_wiki_words
- assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
-
- @wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
- assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
- end
-
- def test_existing_pages
- assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
- end
-
- def test_unexisting_pages
- assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
- end
-
- def test_content_with_wiki_links
- assert_equal 'My Headline
\n\n
\n\ndef a_method(arg)\n} +
- %{return ThatWay\n
Markdown heading
\n\n" +
- "\n
",
- textile_and_markdown)
-
- set_web_property :markup, :textile
- assert_markup_parsed_as(
- "
================Textile heading
" +
- "\n\n\n\tstyles\n\t
",
- textile_and_markdown)
-
- set_web_property :markup, :mixed
- assert_markup_parsed_as(
- "Markdown heading
\n\n\n\tTextile heading
\n\n\n\t" +
- "styles\n\t
",
- textile_and_markdown)
- end
-
- def test_rdoc
- set_web_property :markup, :rdoc
-
- @revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
- :author => Author.new('DavidHeinemeierHansson'))
-
- assert_equal "hello that Smart Engine GUI" +
- "?\n\n", @revision.display_content
- end
-
- def test_content_with_auto_links
- assert_markup_parsed_as(
- 'class SmartEngine end
would not mark up CodeBlocks
class SmartEngine end
would not mark up CodeBlocks') - end - - def test_content_with_autolink_in_parentheses - assert_markup_parsed_as( - '
The W3C body (' + - 'http://www.w3c.org) sets web standards
', - 'The W3C body (http://www.w3c.org) sets web standards') - end - - def test_content_with_link_in_parentheses - assert_markup_parsed_as( - '', - '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)') - end - - def test_content_with_image_link - assert_markup_parsed_as( - 'This is a Textile image link.
', - 'This !http://hobix.com/sample.jpg! is a Textile image link.') - end - - def test_content_with_inlined_img_tag - assert_markup_parsed_as( - 'This is an inline image link.
', - 'This is an inline image link.') - - assert_markup_parsed_as( - 'This is an inline image link.
', - 'This is an inline image link.') - end - - def test_nowiki_tag - assert_markup_parsed_as( - 'Do not mark up [[this text]] or http://www.thislink.com.
', - 'Do not mark upDo not mark \n up [[this text]] \nand http://this.url.com but markup " + - 'this?
', - "Do notThis is a WikiWord and a tricky name ' + - 'Sperberg-McQueen?.
', - 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].') - end - - def test_content_for_export - assert_equal 'His Way would be ' + - 'My Way in kinda ' + - 'That Way in ' + - 'His Way though ' + - 'My Way OverThere—see ' + - 'Smart Engine in that ' + - 'Smart Engine GUI
', - @revision.display_content_for_export - end - - def test_double_replacing - @revision.content = "VersionHistory\r\n\r\ncry VersionHistory" - assert_equal 'Version History' + - "?
\n\n\n\tcry " + - 'Version History?' + - '
', - @revision.display_content - - @revision.clear_display_cache - - @revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory" - assert_equal "f
Version History" +
- "?
cry " + - "Version History?" + - "
", - @revision.display_content - end - - def test_difficult_wiki_words - @revision.content = "[[It's just awesome GUI!]]" - assert_equal "It's just awesome GUI!" + - "?
", - @revision.display_content - end - - def test_revisions_diff - Revision.create(:page => @page, :content => 'What a blue and lovely morning', - :author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now) - Revision.create(:page => @page, :content => 'What a red and lovely morning today', - :author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now) - - assert_equal "What a blue red " +
- "and lovely morningmorning " +
- "today
doc.pdf?
', - '[[doc.pdf:file]]') - end - - def test_link_to_pic - FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1" - FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"]) - @wiki.file_yard(@web).upload_file('square.jpg', StringIO.new('')) - assert_markup_parsed_as( - '', - '[[square.jpg|Square:pic]]') - assert_markup_parsed_as( - '', - '[[square.jpg:pic]]') - end - - def test_link_to_non_existant_pic - assert_markup_parsed_as( - 'NonExistant?' + - '
', - '[[NonExistant.jpg|NonExistant:pic]]') - assert_markup_parsed_as( - 'NonExistant.jpg?' + - '
', - '[[NonExistant.jpg:pic]]') - end - - def test_wiki_link_with_colon - assert_markup_parsed_as( - 'With:Colon?
', - '[[With:Colon]]') - end - - # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1; - # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug) - def test_list_with_tildas - list_with_tildas = <<-EOL - * "a":~b - * c~ d - EOL - - assert_markup_parsed_as( - "\nss
", - "!http://google.com!\r\nss") - end - - def assert_markup_parsed_as(expected_output, input) - revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor')) - assert_equal expected_output, revision.display_content, 'Textile output not as expected' - end -end +require File.expand_path(File.dirname(__FILE__) + '/../test_helper') + +class RevisionTest < Test::Unit::TestCase + fixtures :webs, :pages, :revisions, :system + + def setup + @wiki = Wiki.new + @web = webs(:test_wiki) + @page = pages(:home_page) + @revision = revisions(:home_page_second_revision) + end + + def test_wiki_words + assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort + + @wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me') + assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words + end + + def test_existing_pages + assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort + end + + def test_unexisting_pages + assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort + end + + def test_content_with_wiki_links + assert_equal 'His Way? ' + + 'would be My Way in kinda ' + + 'That Way in ' + + 'His Way? ' + + 'though My Way OverThere—see ' + + 'Smart Engine in that ' + + 'Smart Engine GUI' + + '?
', + @revision.display_content + end + + def test_markdown + set_web_property :markup, :markdown + + assert_markup_parsed_as( + %{that } + + %{Smart Engine GUI?
}, + "My Headline\n===========\n\nthat SmartEngineGUI") + + code_block = [ + 'This is a code block:', + '', + ' def a_method(arg)', + ' return ThatWay', + '', + 'Nice!' + ].join("\n") + + assert_markup_parsed_as( + %{This is a code block:
\n\ndef a_method(arg)\n} +
+ %{return ThatWay\n
\n\nNice!
}, + code_block) + end + + def test_markdown_hyperlink_with_slash + # in response to a bug, see http://dev.instiki.org/attachment/ticket/177 + set_web_property :markup, :markdown + + assert_markup_parsed_as( + '', + '[text](http://example/with/slash)') + end + + def test_mixed_formatting + textile_and_markdown = [ + 'Markdown heading', + '================', + '', + 'h2. Textile heading', + '', + '*some* **text** _with_ -styles-', + '', + '* list 1', + '* list 2' + ].join("\n") + + set_web_property :markup, :markdown + assert_markup_parsed_as( + "h2. Textile heading
\n\n" + + "some text with -styles-
\n\n" + + "Markdown heading
================
some text with styles
some text with styles
http://www.loudthinking.com/ ' + + 'points to That Way from ' + + 'david@loudthinking.com
', + 'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com') + + end + + def test_content_with_aliased_links + assert_markup_parsed_as( + 'Would a clever motor' + + ' go by any other name?
', + 'Would a [[SmartEngine|clever motor]] go by any other name?') + end + + def test_content_with_wikiword_in_em + assert_markup_parsed_as( + 'should we go ' + + 'That Way or This Way?' + + '
', + '_should we go ThatWay or ThisWay _') + end + + def test_content_with_wikiword_in_tag + assert_markup_parsed_as( + 'That is some Stylish Emphasis
', + 'That is some Stylish Emphasis') + end + + def test_content_with_escaped_wikiword + # there should be no wiki link + assert_markup_parsed_as('WikiWord
', '\WikiWord') + end + + def test_content_with_pre_blocks + assert_markup_parsed_as( + 'A class SmartEngine end
would not mark up
CodeBlocks', + 'A
class SmartEngine end
would not mark up CodeBlocks') + end + + def test_content_with_autolink_in_parentheses + assert_markup_parsed_as( + '
The W3C body (' + + 'http://www.w3c.org) sets web standards
', + 'The W3C body (http://www.w3c.org) sets web standards') + end + + def test_content_with_link_in_parentheses + assert_markup_parsed_as( + '', + '("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)') + end + + def test_content_with_image_link + assert_markup_parsed_as( + 'This is a Textile image link.
', + 'This !http://hobix.com/sample.jpg! is a Textile image link.') + end + + def test_content_with_inlined_img_tag + assert_markup_parsed_as( + 'This is an inline image link.
', + 'This is an inline image link.') + + assert_markup_parsed_as( + 'This is an inline image link.
', + 'This is an inline image link.') + end + + def test_nowiki_tag + assert_markup_parsed_as( + 'Do not mark up [[this text]] or http://www.thislink.com.
', + 'Do not mark upDo not mark \n up [[this text]] \nand http://this.url.com but markup " + + 'this?
', + "Do notThis is a WikiWord and a tricky name ' + + 'Sperberg-McQueen?.
', + 'This is a WikiWord and a tricky name [[Sperberg-McQueen]].') + end + + def test_content_for_export + assert_equal 'His Way would be ' + + 'My Way in kinda ' + + 'That Way in ' + + 'His Way though ' + + 'My Way OverThere—see ' + + 'Smart Engine in that ' + + 'Smart Engine GUI
', + @revision.display_content_for_export + end + + def test_double_replacing + @revision.content = "VersionHistory\r\n\r\ncry VersionHistory" + assert_equal 'Version History' + + "?
\n\n\n\tcry " + + 'Version History?' + + '
', + @revision.display_content + + @revision.clear_display_cache + + @revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory" + assert_equal "f
Version History" +
+ "?
cry " + + "Version History?" + + "
", + @revision.display_content + end + + def test_difficult_wiki_words + @revision.content = "[[It's just awesome GUI!]]" + assert_equal "It's just awesome GUI!" + + "?
", + @revision.display_content + end + + def test_revisions_diff + Revision.create(:page => @page, :content => 'What a blue and lovely morning', + :author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now) + Revision.create(:page => @page, :content => 'What a red and lovely morning today', + :author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now) + + assert_equal "What a blue red " +
+ "and lovely morningmorning " +
+ "today
doc.pdf?
', + '[[doc.pdf:file]]') + end + + def test_link_to_pic + FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1" + FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"]) + @wiki.file_yard(@web).upload_file('square.jpg', StringIO.new('')) + assert_markup_parsed_as( + '', + '[[square.jpg|Square:pic]]') + assert_markup_parsed_as( + '', + '[[square.jpg:pic]]') + end + + def test_link_to_non_existant_pic + assert_markup_parsed_as( + 'NonExistant?' + + '
', + '[[NonExistant.jpg|NonExistant:pic]]') + assert_markup_parsed_as( + 'NonExistant.jpg?' + + '
', + '[[NonExistant.jpg:pic]]') + end + + def test_wiki_link_with_colon + assert_markup_parsed_as( + 'With:Colon?
', + '[[With:Colon]]') + end + + # TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1; + # also add a test for the "Unhappy Face" problem (another interesting RedCloth bug) + def test_list_with_tildas + list_with_tildas = <<-EOL + * "a":~b + * c~ d + EOL + + assert_markup_parsed_as( + "\nss
", + "!http://google.com!\r\nss") + end + + def assert_markup_parsed_as(expected_output, input) + revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor')) + assert_equal expected_output, revision.display_content, 'Textile output not as expected' + end +end diff --git a/test/unit/web_test.rb b/test/unit/web_test.rb index 433b579f..7e91bbed 100644 --- a/test/unit/web_test.rb +++ b/test/unit/web_test.rb @@ -1,158 +1,158 @@ -require File.expand_path(File.dirname(__FILE__) + '/../test_helper') - -class WebTest < Test::Unit::TestCase - fixtures :webs, :pages, :revisions, :system - - def setup - @web = webs(:instiki) - end - - def test_wiki_word_linking - @web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated', - Time.now, 'DavidHeinemeierHansson') - - assert_equal('Yo, yo. Have you Ever Been Hated' + - '?
', - @web.page("SecondPage").display_content) - - @web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now, - 'DavidHeinemeierHansson') - assert_equal('Yo, yo. Have you Ever Been Hated
', - @web.page("SecondPage").display_content) - end - - def test_pages_by_revision - add_sample_pages - assert_equal 'EverBeenHated', @web.select.by_revision.first.name - end - - def test_pages_by_match - add_sample_pages - assert_equal 2, @web.select { |page| page.content =~ /me/i }.length - assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length - assert_equal 0, @web.select { |page| page.content =~ /none/i }.length - end - - def test_references - add_sample_pages - assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length - assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length - end - - def test_delete - add_sample_pages - assert_equal 2, @web.pages.length - @web.remove_pages([ @web.page('EverBeenInLove') ]) - assert_equal 1, @web.pages(true).length - end - - def test_make_link - add_sample_pages - - existing_page_wiki_url = - 'Ever Been In Love' - existing_page_published_url = - 'Ever Been In Love' - existing_page_static_url = - 'Ever Been In Love' - new_page_wiki_url = - 'Unknown Word?' - new_page_published_url = - new_page_static_url = - 'Unknown Word' - - # no options - assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove') - - # :mode => :export - assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export) - - # :mode => :publish - assert_equal existing_page_published_url, - @web.make_link('EverBeenInLove', nil, :mode => :publish) - - # new page, no options - assert_equal new_page_wiki_url, @web.make_link('UnknownWord') - - # new page, :mode => :export - assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export) - - # new page, :mode => :publish - assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish) - - # Escaping special characters in the name - assert_equal( - 'Smith & Wesson?', - @web.make_link('Smith & Wesson')) - - # optionally using text as the link text - assert_equal( - existing_page_published_url.sub(/>Ever Been In Love, ">Haven't you ever been in love?<"), - @web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish)) - - end - - def test_initialize - web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123') - - assert_equal 'Wiki2', web.name - assert_equal 'wiki2', web.address - assert_equal '123', web.password - - # new web should be set for maximum features enabled - assert_equal :textile, web.markup - assert_equal '008B26', web.color - assert !web.safe_mode? - assert_equal([], web.pages) - assert web.allow_uploads? - assert_nil web.additional_style - assert !web.published? - assert !web.brackets_only? - assert !web.count_pages? - assert_equal 100, web.max_upload_size - end - - def test_initialize_invalid_name - assert_raises(Instiki::ValidationError) { - Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123') - } - end - - def test_new_page_linked_from_mother_page - # this was a bug in revision 204 - home = @web.add_page('HomePage', 'This page refers to AnotherPage', - Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky') - @web.add_page('AnotherPage', 'This is \AnotherPage', - Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky') - - @web.pages(true) - assert_equal [home], @web.select.pages_that_link_to('AnotherPage') - end - - def test_orphaned_pages - add_sample_pages - home = @web.add_page('HomePage', - 'This is a home page, it should not be an orphan', - Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky') - author = @web.add_page('AlexeyVerkhovsky', - 'This is an author page, it should not be an orphan', - Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky') - self_linked = @web.add_page('SelfLinked', - 'I am me SelfLinked and link to EverBeenInLove', - Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward') - - # page that links to itself, and nobody else links to it must be an orphan - assert_equal ['EverBeenHated', 'SelfLinked'], - @web.select.orphaned_pages.collect{ |page| page.name }.sort - end - - private - - def add_sample_pages - @in_love = @web.add_page('EverBeenInLove', 'Who am I me', - Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson') - @hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated', - Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson') - end -end +require File.expand_path(File.dirname(__FILE__) + '/../test_helper') + +class WebTest < Test::Unit::TestCase + fixtures :webs, :pages, :revisions, :system + + def setup + @web = webs(:instiki) + end + + def test_wiki_word_linking + @web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated', + Time.now, 'DavidHeinemeierHansson') + + assert_equal('Yo, yo. Have you Ever Been Hated' + + '?
', + @web.page("SecondPage").display_content) + + @web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now, + 'DavidHeinemeierHansson') + assert_equal('Yo, yo. Have you Ever Been Hated
', + @web.page("SecondPage").display_content) + end + + def test_pages_by_revision + add_sample_pages + assert_equal 'EverBeenHated', @web.select.by_revision.first.name + end + + def test_pages_by_match + add_sample_pages + assert_equal 2, @web.select { |page| page.content =~ /me/i }.length + assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length + assert_equal 0, @web.select { |page| page.content =~ /none/i }.length + end + + def test_references + add_sample_pages + assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length + assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length + end + + def test_delete + add_sample_pages + assert_equal 2, @web.pages.length + @web.remove_pages([ @web.page('EverBeenInLove') ]) + assert_equal 1, @web.pages(true).length + end + + def test_make_link + add_sample_pages + + existing_page_wiki_url = + 'Ever Been In Love' + existing_page_published_url = + 'Ever Been In Love' + existing_page_static_url = + 'Ever Been In Love' + new_page_wiki_url = + 'Unknown Word?' + new_page_published_url = + new_page_static_url = + 'Unknown Word' + + # no options + assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove') + + # :mode => :export + assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export) + + # :mode => :publish + assert_equal existing_page_published_url, + @web.make_link('EverBeenInLove', nil, :mode => :publish) + + # new page, no options + assert_equal new_page_wiki_url, @web.make_link('UnknownWord') + + # new page, :mode => :export + assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export) + + # new page, :mode => :publish + assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish) + + # Escaping special characters in the name + assert_equal( + 'Smith & Wesson?', + @web.make_link('Smith & Wesson')) + + # optionally using text as the link text + assert_equal( + existing_page_published_url.sub(/>Ever Been In Love, ">Haven't you ever been in love?<"), + @web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish)) + + end + + def test_initialize + web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123') + + assert_equal 'Wiki2', web.name + assert_equal 'wiki2', web.address + assert_equal '123', web.password + + # new web should be set for maximum features enabled + assert_equal :textile, web.markup + assert_equal '008B26', web.color + assert !web.safe_mode? + assert_equal([], web.pages) + assert web.allow_uploads? + assert_nil web.additional_style + assert !web.published? + assert !web.brackets_only? + assert !web.count_pages? + assert_equal 100, web.max_upload_size + end + + def test_initialize_invalid_name + assert_raises(Instiki::ValidationError) { + Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123') + } + end + + def test_new_page_linked_from_mother_page + # this was a bug in revision 204 + home = @web.add_page('HomePage', 'This page refers to AnotherPage', + Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky') + @web.add_page('AnotherPage', 'This is \AnotherPage', + Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky') + + @web.pages(true) + assert_equal [home], @web.select.pages_that_link_to('AnotherPage') + end + + def test_orphaned_pages + add_sample_pages + home = @web.add_page('HomePage', + 'This is a home page, it should not be an orphan', + Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky') + author = @web.add_page('AlexeyVerkhovsky', + 'This is an author page, it should not be an orphan', + Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky') + self_linked = @web.add_page('SelfLinked', + 'I am me SelfLinked and link to EverBeenInLove', + Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward') + + # page that links to itself, and nobody else links to it must be an orphan + assert_equal ['EverBeenHated', 'SelfLinked'], + @web.select.orphaned_pages.collect{ |page| page.name }.sort + end + + private + + def add_sample_pages + @in_love = @web.add_page('EverBeenInLove', 'Who am I me', + Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson') + @hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated', + Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson') + end +end