Line ending cleanup. Most of these are svn propsets which should make
the files check out appropriately in the future. The three files in app/models had inconsitent line endings, so they had to be fixed by hand.
This commit is contained in:
parent
4849ca62fb
commit
b29c59e470
372
CHANGELOG
372
CHANGELOG
|
@ -1,186 +1,186 @@
|
|||
* 0.10.2:
|
||||
Upgraded to Rails 0.13.1
|
||||
Fixed HTML export
|
||||
Added layout=no option to the export_html action (it exports page contents processed
|
||||
by the markup engine, but without the default layout - so that they can be wrapped in
|
||||
some other layout)
|
||||
<nowiki> tag can span several lines (before it was applied when both opening and closing
|
||||
tags were on the same line only)
|
||||
Resolved the "endless redirection loop" condition and otherwise improved handling of
|
||||
errors in the rendering engines
|
||||
Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
|
||||
|
||||
* 0.10.1:
|
||||
Upgraded Rails to 0.12.0
|
||||
Upgraded rubyzip to version 0.5.8
|
||||
BlueCloth is back (RedCloth didn't do pure Markdown well enough)
|
||||
Handling of line breaks in Textile is as in 0.9 (inserts <br/> tag)
|
||||
Fixed HTML export (to enclose the output in <html> tags, include the stylesheet etc)
|
||||
Corrected some compatibility issues with storages from earlier Instiki versions
|
||||
Some other bug fixes
|
||||
|
||||
* 0.10.0:
|
||||
Ported to ActionPack
|
||||
RedCloth 3.0.3
|
||||
BlueCloth is phased out, Markdown is rendered by RedCloth
|
||||
Mix markup option understands both Textile and Markdown on the same page
|
||||
Instiki can serve static content (such as HTML or plain-text files) from ./public
|
||||
directory
|
||||
Much friendlier admin interface
|
||||
Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
|
||||
"textile link":LinkToSomePlace will not look insane.
|
||||
RSS feeds accept query parameters, sush as
|
||||
http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
|
||||
RSS feed with page contents for a password-protected web behaves as follows:
|
||||
if the web is published, RSS feed links to the published version of the web
|
||||
otherwise, the feed is not available
|
||||
Madeleine will check every hour if there are new commands in the log or 24 hours have
|
||||
passed since last snapshot, and take snapshot if either of these conditions is true
|
||||
Madeleine will also not log read-only operations, resulting in a better performance
|
||||
Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
|
||||
Wiki search handles multibyte (UTF-8) characters correctly
|
||||
Local hyperlinks in published pages point to published pages [Michael DeHaan]
|
||||
Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
|
||||
restart
|
||||
Fixed parsing of URIs with a port number (http://someplace.org:8080)
|
||||
Instiki will not fork itself on a *nix, unless explicitly asked to
|
||||
Instiki can bind to IPs other than 127.0.0.1 (command-line option)
|
||||
Revisions that do not change anything on the page are rejected
|
||||
Automated tests for all controller actions
|
||||
category: lines are presented as links to "All Pages" for relevant categories
|
||||
Search looks at page titles, as well as content
|
||||
Multiple other usability enhancements and bug fixes
|
||||
|
||||
* 0.9.2:
|
||||
Rollback takes the user to an edit form. The form has to be submitted for the change to
|
||||
take place.
|
||||
Changed to use inline style on published pages
|
||||
Fixed "forward in time" on the last revision before current page
|
||||
Instiki won't log bogus error messages when creating a new Wiki
|
||||
Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
|
||||
Madeleine upgraded to 0.7.1
|
||||
Madeleine snapshots are compressed
|
||||
Packaged as a gem
|
||||
|
||||
* 0.9.1:
|
||||
Added performance improvements for updating existing pages
|
||||
Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
|
||||
Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
|
||||
|
||||
* 0.9.0:
|
||||
Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
|
||||
Added include other page content with [[!include TableOfContents]] [Mark Reid]
|
||||
Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
|
||||
Added logging of IP address for authors (who's behind the rollback wars)
|
||||
Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
|
||||
Added option to use bracket-style wiki links only (and hence ban WikiWords)
|
||||
Added command-line option to specify different storage path
|
||||
Added print view without navigation
|
||||
Added character and page (2275 characters including spaces) counter (important for student papers)
|
||||
Off by default, activate it on the Edit Web screen
|
||||
Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
|
||||
Use the home page as a table of contents with a unordered list to control sections
|
||||
Added limit of 15 to the number of pages included in RSS feed
|
||||
Moved static parts of stylesheet to separate file [Lau TŒrnskov]
|
||||
Fixed better semantics for revision movement [Ryan Singer]
|
||||
Fixed color diffs to work much better [Xen/Mertz/Atkins]
|
||||
Fixed performance problems for All Pages list [Dennis Mertz]
|
||||
Fixed lots of rendering bugs [Mark Reid]
|
||||
Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
|
||||
|
||||
* 0.8.9:
|
||||
Added color diffs to see changes between revisions [Bill Atkins]
|
||||
They're aren't quite perfect yet as new paragraphs split the <ins> tags (hence 0.8.9, not 0.9.0)
|
||||
Added redirect to edit if content of page generates an error
|
||||
(so the page doesn't become unusable on bugs in the markup engines)
|
||||
Fixed update Web with different address bug [Denis Metz]
|
||||
Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
|
||||
Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
|
||||
|
||||
* 0.8.5:
|
||||
Instiki can now serve as a CMS by running a password-protected web with a published front
|
||||
Added version check at startup (Instiki needs Ruby 1.8.1)
|
||||
|
||||
* 0.8.1:
|
||||
Actually included RedCloth 2.0.7 in the release
|
||||
|
||||
* 0.8.0:
|
||||
NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
|
||||
Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
|
||||
Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
|
||||
Many thanks to Guan Yang for building the higher- and lower-case lookup tables
|
||||
And thanks to Simon Arnaud for the initial patch that got the work started
|
||||
Changed charset to UTF-8
|
||||
Cut down on command-line options and replaced them with an per-web config screen
|
||||
Added option to extend the stylesheet on a per-web basis to tweak the look in details
|
||||
Added simple color options for variety
|
||||
Added option to add/remove password protection on each web
|
||||
Added the wiki name of the author locking a given page (instead of just "someone")
|
||||
Removed single/multi-web distinction -- all Instikis are now multi-web
|
||||
Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
|
||||
Keeps the author cookie forever, so you don't have to enter your name again and again
|
||||
Fixed XHTML so it validates [Bruce D'Arcus]
|
||||
Authors are no longer listed under orphan pages
|
||||
Added export to markup (great for backups, potentially for switching wiki engine)
|
||||
Don't link wiki words that proceeds from either /, = or ?
|
||||
(http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
|
||||
Accessing an unexisting page redirects to a different url (/new/PageName)
|
||||
Increased snapshot time to just once a day (cuts down on disk storage requirements)
|
||||
Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
|
||||
Added convinient redirect from /wiki/ to /wiki/show/HomePage
|
||||
Fixed BlueCloth bug with backticks at start of line
|
||||
Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
|
||||
|
||||
* 0.7.0:
|
||||
Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
|
||||
Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
|
||||
Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
|
||||
Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
|
||||
Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
|
||||
Added password-login through URL (so you can subscribe to feed on a protected web)
|
||||
Added web passwords to the feed links for protected webs, so they work without manual login
|
||||
Added the web name in small letters above all pages within a web
|
||||
Polished authors and recently revised
|
||||
Updated to RedCloth 2.0.6
|
||||
Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
|
||||
Changed searching to be case insensitive
|
||||
Changed HomePage to display the name of the web instead
|
||||
Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
|
||||
Fixed broken recently revised
|
||||
|
||||
* 0.6.0:
|
||||
Fixed Windows compatibility [Florian]
|
||||
Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
|
||||
Added export entire web as HTML in a zip file
|
||||
Added RSS feeds
|
||||
Added proper getops support for the growing number of options [Florian]
|
||||
Added safe mode that forbids style options in RedCloth [Florian]
|
||||
Updated RedCloth to 2.0.5
|
||||
|
||||
* 0.5.0:
|
||||
NOTE: 0.5.0 is NOT compatible with databases from earlier versions
|
||||
Added revisions
|
||||
Added multiple webs
|
||||
Added password protection for webs on multi-web setups
|
||||
Added the notion of authors (that are saved in a cookie)
|
||||
Added command-line option for not running as a Daemon on Unix
|
||||
|
||||
* 0.3.1:
|
||||
Added option to escape wiki words with \
|
||||
|
||||
* 0.3.0:
|
||||
Brought all files into common style (including Textile help on the edit page)
|
||||
Added page locking (if someone already is editing a page there's a warning)
|
||||
Added daemon abilities on Unix (keep Instiki running after you close the terminal)
|
||||
Made port 2500 the default port, so Instiki can be launched by dobbelt-click
|
||||
Added Textile cache to speed-up rendering of large pages
|
||||
Made WikiWords look like "Wiki Words"
|
||||
Updated RedCloth to 2.0.4
|
||||
|
||||
* 0.2.5:
|
||||
Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
|
||||
Windows problems are gone. Also fixed a problem with wikiwords
|
||||
that used part of other wikiwords.
|
||||
|
||||
* 0.2.0:
|
||||
First public release
|
||||
* 0.10.2:
|
||||
Upgraded to Rails 0.13.1
|
||||
Fixed HTML export
|
||||
Added layout=no option to the export_html action (it exports page contents processed
|
||||
by the markup engine, but without the default layout - so that they can be wrapped in
|
||||
some other layout)
|
||||
<nowiki> tag can span several lines (before it was applied when both opening and closing
|
||||
tags were on the same line only)
|
||||
Resolved the "endless redirection loop" condition and otherwise improved handling of
|
||||
errors in the rendering engines
|
||||
Fixed rendering of Markdown hyperlinks such as [Text](http://something.com/foo)
|
||||
|
||||
* 0.10.1:
|
||||
Upgraded Rails to 0.12.0
|
||||
Upgraded rubyzip to version 0.5.8
|
||||
BlueCloth is back (RedCloth didn't do pure Markdown well enough)
|
||||
Handling of line breaks in Textile is as in 0.9 (inserts <br/> tag)
|
||||
Fixed HTML export (to enclose the output in <html> tags, include the stylesheet etc)
|
||||
Corrected some compatibility issues with storages from earlier Instiki versions
|
||||
Some other bug fixes
|
||||
|
||||
* 0.10.0:
|
||||
Ported to ActionPack
|
||||
RedCloth 3.0.3
|
||||
BlueCloth is phased out, Markdown is rendered by RedCloth
|
||||
Mix markup option understands both Textile and Markdown on the same page
|
||||
Instiki can serve static content (such as HTML or plain-text files) from ./public
|
||||
directory
|
||||
Much friendlier admin interface
|
||||
Wiki link syntax doesn't conflict with Textile hyperlink syntax. Therefore
|
||||
"textile link":LinkToSomePlace will not look insane.
|
||||
RSS feeds accept query parameters, sush as
|
||||
http://localhost:2500/wiki/rss_with_headlines?start=2005-02-18&end=2005-02-19&limit=10
|
||||
RSS feed with page contents for a password-protected web behaves as follows:
|
||||
if the web is published, RSS feed links to the published version of the web
|
||||
otherwise, the feed is not available
|
||||
Madeleine will check every hour if there are new commands in the log or 24 hours have
|
||||
passed since last snapshot, and take snapshot if either of these conditions is true
|
||||
Madeleine will also not log read-only operations, resulting in a better performance
|
||||
Wiki extracts (to HTML and plain text) will leave only the last extract file in ./storage
|
||||
Wiki search handles multibyte (UTF-8) characters correctly
|
||||
Local hyperlinks in published pages point to published pages [Michael DeHaan]
|
||||
Fixed a bug that sometimes caused all past revisions of a page to be "forgotten" on
|
||||
restart
|
||||
Fixed parsing of URIs with a port number (http://someplace.org:8080)
|
||||
Instiki will not fork itself on a *nix, unless explicitly asked to
|
||||
Instiki can bind to IPs other than 127.0.0.1 (command-line option)
|
||||
Revisions that do not change anything on the page are rejected
|
||||
Automated tests for all controller actions
|
||||
category: lines are presented as links to "All Pages" for relevant categories
|
||||
Search looks at page titles, as well as content
|
||||
Multiple other usability enhancements and bug fixes
|
||||
|
||||
* 0.9.2:
|
||||
Rollback takes the user to an edit form. The form has to be submitted for the change to
|
||||
take place.
|
||||
Changed to use inline style on published pages
|
||||
Fixed "forward in time" on the last revision before current page
|
||||
Instiki won't log bogus error messages when creating a new Wiki
|
||||
Fixed deprecation warning for Object.id (introduced in Ruby 1.8.2)
|
||||
Madeleine upgraded to 0.7.1
|
||||
Madeleine snapshots are compressed
|
||||
Packaged as a gem
|
||||
|
||||
* 0.9.1:
|
||||
Added performance improvements for updating existing pages
|
||||
Fixed IP logging and RSS feeds behind proxies [With help from Guan Yang]
|
||||
Fixed default storage directory (borked running on Windows) [Spotted by Curt Hibbs]
|
||||
|
||||
* 0.9.0:
|
||||
Added aliased links such as [[HomePage|that nice home page]] [Mark Reid]
|
||||
Added include other page content with [[!include TableOfContents]] [Mark Reid]
|
||||
Added delete orphan pages from the Edit Web screen [by inspiration from Simon Arnaud]
|
||||
Added logging of IP address for authors (who's behind the rollback wars)
|
||||
Added Categories pages through backlinks (use "categories: news, instiki" on start of line) [Mark Reid]
|
||||
Added option to use bracket-style wiki links only (and hence ban WikiWords)
|
||||
Added command-line option to specify different storage path
|
||||
Added print view without navigation
|
||||
Added character and page (2275 characters including spaces) counter (important for student papers)
|
||||
Off by default, activate it on the Edit Web screen
|
||||
Added LaTeX/PDF integration on Textile installations with pdflatex installed on system (EXPERIMENTAL)
|
||||
Use the home page as a table of contents with a unordered list to control sections
|
||||
Added limit of 15 to the number of pages included in RSS feed
|
||||
Moved static parts of stylesheet to separate file [Lau TŒrnskov]
|
||||
Fixed better semantics for revision movement [Ryan Singer]
|
||||
Fixed color diffs to work much better [Xen/Mertz/Atkins]
|
||||
Fixed performance problems for All Pages list [Dennis Mertz]
|
||||
Fixed lots of rendering bugs [Mark Reid]
|
||||
Upgraded to RedCloth 2.0.11 [integrating the fine work of Dennis Mertz]
|
||||
|
||||
* 0.8.9:
|
||||
Added color diffs to see changes between revisions [Bill Atkins]
|
||||
They're aren't quite perfect yet as new paragraphs split the <ins> tags (hence 0.8.9, not 0.9.0)
|
||||
Added redirect to edit if content of page generates an error
|
||||
(so the page doesn't become unusable on bugs in the markup engines)
|
||||
Fixed update Web with different address bug [Denis Metz]
|
||||
Fixed a bunch of wiki word rendering issues by doing wiki word detection and replacment at once
|
||||
Upgraded to BlueCloth 0.0.3b (should fix loads of problems on Markdown wikis)
|
||||
|
||||
* 0.8.5:
|
||||
Instiki can now serve as a CMS by running a password-protected web with a published front
|
||||
Added version check at startup (Instiki needs Ruby 1.8.1)
|
||||
|
||||
* 0.8.1:
|
||||
Actually included RedCloth 2.0.7 in the release
|
||||
|
||||
* 0.8.0:
|
||||
NOTE: Single-web wikis created in versions prior to 0.8.0 have "instiki" as their system password
|
||||
Accepts wiki words in bracket style. Ex: [[wiki word]], [[c]], [[We could'nt have done it!]]
|
||||
Accepts camel-case wiki words in all latin, greek, cyrillian, and armenian unicode characters
|
||||
Many thanks to Guan Yang for building the higher- and lower-case lookup tables
|
||||
And thanks to Simon Arnaud for the initial patch that got the work started
|
||||
Changed charset to UTF-8
|
||||
Cut down on command-line options and replaced them with an per-web config screen
|
||||
Added option to extend the stylesheet on a per-web basis to tweak the look in details
|
||||
Added simple color options for variety
|
||||
Added option to add/remove password protection on each web
|
||||
Added the wiki name of the author locking a given page (instead of just "someone")
|
||||
Removed single/multi-web distinction -- all Instikis are now multi-web
|
||||
Load libraries from an unshifted load path, so that old installed libraries doesn't clash [Emiel van de Laar]
|
||||
Keeps the author cookie forever, so you don't have to enter your name again and again
|
||||
Fixed XHTML so it validates [Bruce D'Arcus]
|
||||
Authors are no longer listed under orphan pages
|
||||
Added export to markup (great for backups, potentially for switching wiki engine)
|
||||
Don't link wiki words that proceeds from either /, = or ?
|
||||
(http://c2.com/cgi/wiki?WikiWikiClones, /show/HomePage, cgi.pl?show=WikiWord without escaping)
|
||||
Accessing an unexisting page redirects to a different url (/new/PageName)
|
||||
Increased snapshot time to just once a day (cuts down on disk storage requirements)
|
||||
Made RDoc support work better with 1.8.1 [Mauricio Fern‡ndez]
|
||||
Added convinient redirect from /wiki/ to /wiki/show/HomePage
|
||||
Fixed BlueCloth bug with backticks at start of line
|
||||
Updated to RedCloth 2.0.7 (and linked to the new Textile reference)
|
||||
|
||||
* 0.7.0:
|
||||
Added Markdown (BlueCloth) and RDoc [Mauricio Fern‡ndez] as command-line markup choices
|
||||
Added wanted and orphan page lists to All pages (only show up if there's actually orphan or wanted pages)
|
||||
Added ISO-8859-1 as XML encoding in RSS feeds (makes FeedReader among others happy for special entities)
|
||||
Added proper links in the RSS feed (but the body links are still relative, which NNW and others doesn't grok)
|
||||
Added access keys: E => Edit, H => HomePage, A => All Pages, U => Recently Revised, X => Export
|
||||
Added password-login through URL (so you can subscribe to feed on a protected web)
|
||||
Added web passwords to the feed links for protected webs, so they work without manual login
|
||||
Added the web name in small letters above all pages within a web
|
||||
Polished authors and recently revised
|
||||
Updated to RedCloth 2.0.6
|
||||
Changed content type for RSS feeds to text/xml (makes Mozilla Aggreg8 happy)
|
||||
Changed searching to be case insensitive
|
||||
Changed HomePage to display the name of the web instead
|
||||
Changed exported HTML pages to be valid XHTML (which can be preprocessed by XSLT)
|
||||
Fixed broken recently revised
|
||||
|
||||
* 0.6.0:
|
||||
Fixed Windows compatibility [Florian]
|
||||
Fixed bug that would prevent Madeleine from taking snapshots in Daemon mode
|
||||
Added export entire web as HTML in a zip file
|
||||
Added RSS feeds
|
||||
Added proper getops support for the growing number of options [Florian]
|
||||
Added safe mode that forbids style options in RedCloth [Florian]
|
||||
Updated RedCloth to 2.0.5
|
||||
|
||||
* 0.5.0:
|
||||
NOTE: 0.5.0 is NOT compatible with databases from earlier versions
|
||||
Added revisions
|
||||
Added multiple webs
|
||||
Added password protection for webs on multi-web setups
|
||||
Added the notion of authors (that are saved in a cookie)
|
||||
Added command-line option for not running as a Daemon on Unix
|
||||
|
||||
* 0.3.1:
|
||||
Added option to escape wiki words with \
|
||||
|
||||
* 0.3.0:
|
||||
Brought all files into common style (including Textile help on the edit page)
|
||||
Added page locking (if someone already is editing a page there's a warning)
|
||||
Added daemon abilities on Unix (keep Instiki running after you close the terminal)
|
||||
Made port 2500 the default port, so Instiki can be launched by dobbelt-click
|
||||
Added Textile cache to speed-up rendering of large pages
|
||||
Made WikiWords look like "Wiki Words"
|
||||
Updated RedCloth to 2.0.4
|
||||
|
||||
* 0.2.5:
|
||||
Upgraded to RedCloth 2.0.2 and Madeleine 0.6.1, which means the
|
||||
Windows problems are gone. Also fixed a problem with wikiwords
|
||||
that used part of other wikiwords.
|
||||
|
||||
* 0.2.0:
|
||||
First public release
|
||||
|
|
140
README
140
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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,105 +1,105 @@
|
|||
require 'diff'
|
||||
class Revision < ActiveRecord::Base
|
||||
belongs_to :page
|
||||
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
|
||||
|
||||
# Returns an array of all the WikiIncludes present in the content of this revision.
|
||||
def wiki_includes
|
||||
unless @wiki_includes_cache
|
||||
chunks = display_content.find_chunks(Include)
|
||||
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_includes_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiReferences present in the content of this revision.
|
||||
def wiki_references
|
||||
unless @wiki_references_cache
|
||||
chunks = display_content.find_chunks(WikiChunk::WikiReference)
|
||||
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_references_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision.
|
||||
def wiki_words
|
||||
unless @wiki_words_cache
|
||||
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
|
||||
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_words_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision.
|
||||
# that already exists as a page in the web.
|
||||
def existing_pages
|
||||
wiki_words.select { |wiki_word| page.web.page(wiki_word) }
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision
|
||||
# that *doesn't* already exists as a page in the web.
|
||||
def unexisting_pages
|
||||
wiki_words - existing_pages
|
||||
end
|
||||
|
||||
# Explicit check for new type of display cache with chunks_by_type method.
|
||||
# Ensures new version works with older snapshots.
|
||||
def display_content
|
||||
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
|
||||
@display_cache = WikiContent.new(self)
|
||||
@display_cache.render!
|
||||
end
|
||||
@display_cache
|
||||
end
|
||||
|
||||
# TODO this probably doesn't belong in revision (because it has to call back the page)
|
||||
def display_diff
|
||||
previous_revision = page.previous_revision(self)
|
||||
if previous_revision
|
||||
HTMLDiff.diff(previous_revision.display_content, display_content)
|
||||
else
|
||||
display_content
|
||||
end
|
||||
end
|
||||
|
||||
def clear_display_cache
|
||||
@wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
|
||||
@wiki_references_cache = nil
|
||||
end
|
||||
|
||||
def display_published
|
||||
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
|
||||
@published_cache = WikiContent.new(self, {:mode => :publish})
|
||||
@published_cache.render!
|
||||
end
|
||||
@published_cache
|
||||
end
|
||||
|
||||
def display_content_for_export
|
||||
WikiContent.new(self, {:mode => :export} ).render!
|
||||
end
|
||||
|
||||
def force_rendering
|
||||
begin
|
||||
display_content.render!
|
||||
rescue => e
|
||||
logger.error "Failed rendering page #{@name}"
|
||||
logger.error e
|
||||
message = e.message
|
||||
# substitute content with an error message
|
||||
self.content = <<-EOL
|
||||
<p>Markup engine has failed to render this page, raising the following error:</p>
|
||||
<p>#{message}</p>
|
||||
<pre>#{self.content}</pre>
|
||||
EOL
|
||||
clear_display_cache
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
after_create :force_rendering
|
||||
after_save :clear_display_cache
|
||||
|
||||
require 'diff'
|
||||
class Revision < ActiveRecord::Base
|
||||
belongs_to :page
|
||||
composed_of :author, :mapping => [ %w(author name), %w(ip ip) ]
|
||||
|
||||
# Returns an array of all the WikiIncludes present in the content of this revision.
|
||||
def wiki_includes
|
||||
unless @wiki_includes_cache
|
||||
chunks = display_content.find_chunks(Include)
|
||||
@wiki_includes_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_includes_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiReferences present in the content of this revision.
|
||||
def wiki_references
|
||||
unless @wiki_references_cache
|
||||
chunks = display_content.find_chunks(WikiChunk::WikiReference)
|
||||
@wiki_references_cache = chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_references_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision.
|
||||
def wiki_words
|
||||
unless @wiki_words_cache
|
||||
wiki_chunks = display_content.find_chunks(WikiChunk::WikiLink)
|
||||
@wiki_words_cache = wiki_chunks.map { |c| ( c.escaped? ? nil : c.page_name ) }.compact.uniq
|
||||
end
|
||||
@wiki_words_cache
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision.
|
||||
# that already exists as a page in the web.
|
||||
def existing_pages
|
||||
wiki_words.select { |wiki_word| page.web.page(wiki_word) }
|
||||
end
|
||||
|
||||
# Returns an array of all the WikiWords present in the content of this revision
|
||||
# that *doesn't* already exists as a page in the web.
|
||||
def unexisting_pages
|
||||
wiki_words - existing_pages
|
||||
end
|
||||
|
||||
# Explicit check for new type of display cache with chunks_by_type method.
|
||||
# Ensures new version works with older snapshots.
|
||||
def display_content
|
||||
unless @display_cache && @display_cache.respond_to?(:chunks_by_type)
|
||||
@display_cache = WikiContent.new(self)
|
||||
@display_cache.render!
|
||||
end
|
||||
@display_cache
|
||||
end
|
||||
|
||||
# TODO this probably doesn't belong in revision (because it has to call back the page)
|
||||
def display_diff
|
||||
previous_revision = page.previous_revision(self)
|
||||
if previous_revision
|
||||
HTMLDiff.diff(previous_revision.display_content, display_content)
|
||||
else
|
||||
display_content
|
||||
end
|
||||
end
|
||||
|
||||
def clear_display_cache
|
||||
@wiki_words_cache = @published_cache = @display_cache = @wiki_includes_cache =
|
||||
@wiki_references_cache = nil
|
||||
end
|
||||
|
||||
def display_published
|
||||
unless @published_cache && @published_cache.respond_to?(:chunks_by_type)
|
||||
@published_cache = WikiContent.new(self, {:mode => :publish})
|
||||
@published_cache.render!
|
||||
end
|
||||
@published_cache
|
||||
end
|
||||
|
||||
def display_content_for_export
|
||||
WikiContent.new(self, {:mode => :export} ).render!
|
||||
end
|
||||
|
||||
def force_rendering
|
||||
begin
|
||||
display_content.render!
|
||||
rescue => e
|
||||
logger.error "Failed rendering page #{@name}"
|
||||
logger.error e
|
||||
message = e.message
|
||||
# substitute content with an error message
|
||||
self.content = <<-EOL
|
||||
<p>Markup engine has failed to render this page, raising the following error:</p>
|
||||
<p>#{message}</p>
|
||||
<pre>#{self.content}</pre>
|
||||
EOL
|
||||
clear_display_cache
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
after_create :force_rendering
|
||||
after_save :clear_display_cache
|
||||
|
||||
end
|
||||
|
|
|
@ -1,173 +1,173 @@
|
|||
require 'cgi'
|
||||
|
||||
class Web < ActiveRecord::Base
|
||||
has_many :pages#, :include => [:current_revision, :web]
|
||||
|
||||
def wiki
|
||||
Wiki.new
|
||||
end
|
||||
|
||||
def file_yard
|
||||
@file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
|
||||
end
|
||||
|
||||
def settings_changed?(markup, safe_mode, brackets_only)
|
||||
self.markup != markup ||
|
||||
self.safe_mode != safe_mode ||
|
||||
self.brackets_only != brackets_only
|
||||
end
|
||||
|
||||
def add_page(name, content, time, author)
|
||||
page = page(name) || Page.new(:web => self, :name => name)
|
||||
page.revise(content, time, author)
|
||||
end
|
||||
|
||||
def authors
|
||||
select.authors
|
||||
end
|
||||
|
||||
def categories
|
||||
select.map { |page| page.categories }.flatten.uniq.sort
|
||||
end
|
||||
|
||||
def page(name)
|
||||
pages.find(:first, :conditions => ['name = ?', name])
|
||||
end
|
||||
|
||||
def has_page?(name)
|
||||
Page.count(['web_id = ? AND name = ?', id, name]) > 0
|
||||
end
|
||||
|
||||
def has_file?(name)
|
||||
wiki.file_yard(self).has_file?(name)
|
||||
end
|
||||
|
||||
def markup
|
||||
read_attribute('markup').to_sym
|
||||
end
|
||||
|
||||
def make_file_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode
|
||||
when :export
|
||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||
when :publish
|
||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{base_url}/published/#{link}\">#{text}</a>"
|
||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||
else
|
||||
if has_file?(name)
|
||||
"<a class=\"existingWikiWord\" href=\"#{base_url}/file/#{link}\">#{text}</a>"
|
||||
else
|
||||
"<span class=\"newWikiWord\">#{text}<a href=\"#{base_url}/file/#{link}\">?</a></span>"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create a link for the given page name and link text based
|
||||
# on the render mode in options and whether the page exists
|
||||
# in the this web.
|
||||
# The links a relative, and will work only if displayed on another WikiPage.
|
||||
# It should not be used in menus, templates and such - instead, use link_to_page helper
|
||||
def make_link(name, text = nil, options = {})
|
||||
text = CGI.escapeHTML(text || WikiWords.separate(name))
|
||||
mode = options[:mode] || :show
|
||||
base_url = options[:base_url] || '..'
|
||||
link_type = options[:link_type] || :show
|
||||
case link_type.to_sym
|
||||
when :show
|
||||
make_page_link(mode, name, text, base_url)
|
||||
when :file
|
||||
make_file_link(mode, name, text, base_url)
|
||||
when :pic
|
||||
make_pic_link(mode, name, text, base_url)
|
||||
else
|
||||
raise "Unknown link type: #{link_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def make_page_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode.to_sym
|
||||
when :export
|
||||
if has_page?(name) then %{<a class="existingWikiWord" href="#{link}.html">#{text}</a>}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
when :publish
|
||||
if has_page?(name) then %{<a class="existingWikiWord" href="#{base_url}/published/#{link}">#{text}</a>}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
else
|
||||
if has_page?(name)
|
||||
%{<a class="existingWikiWord" href="#{base_url}/show/#{link}">#{text}</a>}
|
||||
else
|
||||
%{<span class="newWikiWord">#{text}<a href="#{base_url}/show/#{link}">?</a></span>}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def make_pic_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode.to_sym
|
||||
when :export
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
|
||||
else %{<img alt="#{text}" src="no image" />} end
|
||||
when :publish
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
else
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{base_url}/pic/#{link}" />}
|
||||
else %{<span class="newWikiWord">#{text}<a href="#{base_url}/pic/#{link}">?</a></span>} end
|
||||
end
|
||||
end
|
||||
|
||||
# Clears the display cache for all the pages with references to
|
||||
def refresh_pages_with_references(page_name)
|
||||
#select.pages_that_reference(page_name).each { |page|
|
||||
# page.revisions.each { |revision| revision.clear_display_cache }
|
||||
#}
|
||||
end
|
||||
|
||||
def refresh_revisions
|
||||
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
|
||||
end
|
||||
|
||||
def remove_pages(pages_to_be_removed)
|
||||
pages_to_be_removed.each { |p| p.destroy }
|
||||
end
|
||||
|
||||
def revised_at
|
||||
select.most_recent_revision
|
||||
end
|
||||
|
||||
def select(&condition)
|
||||
PageSet.new(self, pages, condition)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns an array of all the wiki words in any current revision
|
||||
def wiki_words
|
||||
pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
||||
end
|
||||
|
||||
# Returns an array of all the page names on this web
|
||||
def page_names
|
||||
pages.map { |p| p.name }
|
||||
end
|
||||
|
||||
protected
|
||||
before_save :sanitize_markup
|
||||
before_validation :validate_address
|
||||
validates_uniqueness_of :address
|
||||
validates_length_of :color, :in => 3..6
|
||||
|
||||
def sanitize_markup
|
||||
self.markup = markup.to_s
|
||||
end
|
||||
|
||||
def validate_address
|
||||
unless address == CGI.escape(address)
|
||||
self.errors.add(:address, 'should contain only valid URI characters')
|
||||
raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
|
||||
end
|
||||
end
|
||||
require 'cgi'
|
||||
|
||||
class Web < ActiveRecord::Base
|
||||
has_many :pages#, :include => [:current_revision, :web]
|
||||
|
||||
def wiki
|
||||
Wiki.new
|
||||
end
|
||||
|
||||
def file_yard
|
||||
@file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size)
|
||||
end
|
||||
|
||||
def settings_changed?(markup, safe_mode, brackets_only)
|
||||
self.markup != markup ||
|
||||
self.safe_mode != safe_mode ||
|
||||
self.brackets_only != brackets_only
|
||||
end
|
||||
|
||||
def add_page(name, content, time, author)
|
||||
page = page(name) || Page.new(:web => self, :name => name)
|
||||
page.revise(content, time, author)
|
||||
end
|
||||
|
||||
def authors
|
||||
select.authors
|
||||
end
|
||||
|
||||
def categories
|
||||
select.map { |page| page.categories }.flatten.uniq.sort
|
||||
end
|
||||
|
||||
def page(name)
|
||||
pages.find(:first, :conditions => ['name = ?', name])
|
||||
end
|
||||
|
||||
def has_page?(name)
|
||||
Page.count(['web_id = ? AND name = ?', id, name]) > 0
|
||||
end
|
||||
|
||||
def has_file?(name)
|
||||
wiki.file_yard(self).has_file?(name)
|
||||
end
|
||||
|
||||
def markup
|
||||
read_attribute('markup').to_sym
|
||||
end
|
||||
|
||||
def make_file_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode
|
||||
when :export
|
||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{link}.html\">#{text}</a>"
|
||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||
when :publish
|
||||
if has_file?(name) then "<a class=\"existingWikiWord\" href=\"#{base_url}/published/#{link}\">#{text}</a>"
|
||||
else "<span class=\"newWikiWord\">#{text}</span>" end
|
||||
else
|
||||
if has_file?(name)
|
||||
"<a class=\"existingWikiWord\" href=\"#{base_url}/file/#{link}\">#{text}</a>"
|
||||
else
|
||||
"<span class=\"newWikiWord\">#{text}<a href=\"#{base_url}/file/#{link}\">?</a></span>"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create a link for the given page name and link text based
|
||||
# on the render mode in options and whether the page exists
|
||||
# in the this web.
|
||||
# The links a relative, and will work only if displayed on another WikiPage.
|
||||
# It should not be used in menus, templates and such - instead, use link_to_page helper
|
||||
def make_link(name, text = nil, options = {})
|
||||
text = CGI.escapeHTML(text || WikiWords.separate(name))
|
||||
mode = options[:mode] || :show
|
||||
base_url = options[:base_url] || '..'
|
||||
link_type = options[:link_type] || :show
|
||||
case link_type.to_sym
|
||||
when :show
|
||||
make_page_link(mode, name, text, base_url)
|
||||
when :file
|
||||
make_file_link(mode, name, text, base_url)
|
||||
when :pic
|
||||
make_pic_link(mode, name, text, base_url)
|
||||
else
|
||||
raise "Unknown link type: #{link_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def make_page_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode.to_sym
|
||||
when :export
|
||||
if has_page?(name) then %{<a class="existingWikiWord" href="#{link}.html">#{text}</a>}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
when :publish
|
||||
if has_page?(name) then %{<a class="existingWikiWord" href="#{base_url}/published/#{link}">#{text}</a>}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
else
|
||||
if has_page?(name)
|
||||
%{<a class="existingWikiWord" href="#{base_url}/show/#{link}">#{text}</a>}
|
||||
else
|
||||
%{<span class="newWikiWord">#{text}<a href="#{base_url}/show/#{link}">?</a></span>}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def make_pic_link(mode, name, text, base_url)
|
||||
link = CGI.escape(name)
|
||||
case mode.to_sym
|
||||
when :export
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
|
||||
else %{<img alt="#{text}" src="no image" />} end
|
||||
when :publish
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{link}" />}
|
||||
else %{<span class="newWikiWord">#{text}</span>} end
|
||||
else
|
||||
if has_file?(name) then %{<img alt="#{text}" src="#{base_url}/pic/#{link}" />}
|
||||
else %{<span class="newWikiWord">#{text}<a href="#{base_url}/pic/#{link}">?</a></span>} end
|
||||
end
|
||||
end
|
||||
|
||||
# Clears the display cache for all the pages with references to
|
||||
def refresh_pages_with_references(page_name)
|
||||
#select.pages_that_reference(page_name).each { |page|
|
||||
# page.revisions.each { |revision| revision.clear_display_cache }
|
||||
#}
|
||||
end
|
||||
|
||||
def refresh_revisions
|
||||
select.each { |page| page.revisions.each { |revision| revision.clear_display_cache } }
|
||||
end
|
||||
|
||||
def remove_pages(pages_to_be_removed)
|
||||
pages_to_be_removed.each { |p| p.destroy }
|
||||
end
|
||||
|
||||
def revised_at
|
||||
select.most_recent_revision
|
||||
end
|
||||
|
||||
def select(&condition)
|
||||
PageSet.new(self, pages, condition)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Returns an array of all the wiki words in any current revision
|
||||
def wiki_words
|
||||
pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq
|
||||
end
|
||||
|
||||
# Returns an array of all the page names on this web
|
||||
def page_names
|
||||
pages.map { |p| p.name }
|
||||
end
|
||||
|
||||
protected
|
||||
before_save :sanitize_markup
|
||||
before_validation :validate_address
|
||||
validates_uniqueness_of :address
|
||||
validates_length_of :color, :in => 3..6
|
||||
|
||||
def sanitize_markup
|
||||
self.markup = markup.to_s
|
||||
end
|
||||
|
||||
def validate_address
|
||||
unless address == CGI.escape(address)
|
||||
self.errors.add(:address, 'should contain only valid URI characters')
|
||||
raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
108
test/fixtures/pages.yml
vendored
108
test/fixtures/pages.yml
vendored
|
@ -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
|
166
test/fixtures/revisions.yml
vendored
166
test/fixtures/revisions.yml
vendored
|
@ -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
|
||||
|
|
28
test/fixtures/webs.yml
vendored
28
test/fixtures/webs.yml
vendored
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,317 +1,317 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class RevisionTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
@wiki = Wiki.new
|
||||
@web = webs(:test_wiki)
|
||||
@page = pages(:home_page)
|
||||
@revision = revisions(:home_page_second_revision)
|
||||
end
|
||||
|
||||
def test_wiki_words
|
||||
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
|
||||
|
||||
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
|
||||
assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
|
||||
end
|
||||
|
||||
def test_existing_pages
|
||||
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
|
||||
end
|
||||
|
||||
def test_unexisting_pages
|
||||
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
|
||||
end
|
||||
|
||||
def test_content_with_wiki_links
|
||||
assert_equal '<p><span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||
'would be <a class="existingWikiWord" href="../show/MyWay">My Way</a> in kinda ' +
|
||||
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
|
||||
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere—see ' +
|
||||
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
|
||||
'<span class="newWikiWord">Smart Engine GUI' +
|
||||
'<a href="../show/SmartEngineGUI">?</a></span></p>',
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_markdown
|
||||
set_web_property :markup, :markdown
|
||||
|
||||
assert_markup_parsed_as(
|
||||
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
|
||||
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
|
||||
"My Headline\n===========\n\nthat SmartEngineGUI")
|
||||
|
||||
code_block = [
|
||||
'This is a code block:',
|
||||
'',
|
||||
' def a_method(arg)',
|
||||
' return ThatWay',
|
||||
'',
|
||||
'Nice!'
|
||||
].join("\n")
|
||||
|
||||
assert_markup_parsed_as(
|
||||
%{<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\n} +
|
||||
%{return ThatWay\n</code></pre>\n\n<p>Nice!</p>},
|
||||
code_block)
|
||||
end
|
||||
|
||||
def test_markdown_hyperlink_with_slash
|
||||
# in response to a bug, see http://dev.instiki.org/attachment/ticket/177
|
||||
set_web_property :markup, :markdown
|
||||
|
||||
assert_markup_parsed_as(
|
||||
'<p><a href="http://example/with/slash">text</a></p>',
|
||||
'[text](http://example/with/slash)')
|
||||
end
|
||||
|
||||
def test_mixed_formatting
|
||||
textile_and_markdown = [
|
||||
'Markdown heading',
|
||||
'================',
|
||||
'',
|
||||
'h2. Textile heading',
|
||||
'',
|
||||
'*some* **text** _with_ -styles-',
|
||||
'',
|
||||
'* list 1',
|
||||
'* list 2'
|
||||
].join("\n")
|
||||
|
||||
set_web_property :markup, :markdown
|
||||
assert_markup_parsed_as(
|
||||
"<h1>Markdown heading</h1>\n\n" +
|
||||
"<p>h2. Textile heading</p>\n\n" +
|
||||
"<p><em>some</em> <strong>text</strong> <em>with</em> -styles-</p>\n\n" +
|
||||
"<ul>\n<li>list 1</li>\n<li>list 2</li>\n</ul>",
|
||||
textile_and_markdown)
|
||||
|
||||
set_web_property :markup, :textile
|
||||
assert_markup_parsed_as(
|
||||
"<p>Markdown heading<br />================</p>\n\n\n\t<h2>Textile heading</h2>" +
|
||||
"\n\n\n\t<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>" +
|
||||
"\n\n\n\t<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
|
||||
textile_and_markdown)
|
||||
|
||||
set_web_property :markup, :mixed
|
||||
assert_markup_parsed_as(
|
||||
"<h1>Markdown heading</h1>\n\n\n\t<h2>Textile heading</h2>\n\n\n\t" +
|
||||
"<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>\n\n\n\t" +
|
||||
"<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
|
||||
textile_and_markdown)
|
||||
end
|
||||
|
||||
def test_rdoc
|
||||
set_web_property :markup, :rdoc
|
||||
|
||||
@revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
|
||||
:author => Author.new('DavidHeinemeierHansson'))
|
||||
|
||||
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
|
||||
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
|
||||
end
|
||||
|
||||
def test_content_with_auto_links
|
||||
assert_markup_parsed_as(
|
||||
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
|
||||
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
|
||||
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
|
||||
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
|
||||
|
||||
end
|
||||
|
||||
def test_content_with_aliased_links
|
||||
assert_markup_parsed_as(
|
||||
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
|
||||
'</a> go by any other name?</p>',
|
||||
'Would a [[SmartEngine|clever motor]] go by any other name?')
|
||||
end
|
||||
|
||||
def test_content_with_wikiword_in_em
|
||||
assert_markup_parsed_as(
|
||||
'<p><em>should we go <a class="existingWikiWord" href="../show/ThatWay">' +
|
||||
'That Way</a> or <span class="newWikiWord">This Way<a href="../show/ThisWay">?</a>' +
|
||||
'</span> </em></p>',
|
||||
'_should we go ThatWay or ThisWay _')
|
||||
end
|
||||
|
||||
def test_content_with_wikiword_in_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
|
||||
'That is some <em style="WikiWord">Stylish Emphasis</em>')
|
||||
end
|
||||
|
||||
def test_content_with_escaped_wikiword
|
||||
# there should be no wiki link
|
||||
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
|
||||
end
|
||||
|
||||
def test_content_with_pre_blocks
|
||||
assert_markup_parsed_as(
|
||||
'<p>A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre></p>',
|
||||
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
|
||||
end
|
||||
|
||||
def test_content_with_autolink_in_parentheses
|
||||
assert_markup_parsed_as(
|
||||
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
|
||||
'http://www.w3c.org</a>) sets web standards</p>',
|
||||
'The W3C body (http://www.w3c.org) sets web standards')
|
||||
end
|
||||
|
||||
def test_content_with_link_in_parentheses
|
||||
assert_markup_parsed_as(
|
||||
'<p>(<a href="http://wiki.org/wiki.cgi?WhatIsWiki">What is a wiki?</a>)</p>',
|
||||
'("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
|
||||
end
|
||||
|
||||
def test_content_with_image_link
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is a Textile image link.</p>',
|
||||
'This !http://hobix.com/sample.jpg! is a Textile image link.')
|
||||
end
|
||||
|
||||
def test_content_with_inlined_img_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.</p>',
|
||||
'This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.')
|
||||
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.</p>',
|
||||
'This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.')
|
||||
end
|
||||
|
||||
def test_nowiki_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
|
||||
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
|
||||
'or <nowiki>http://www.thislink.com</nowiki>.')
|
||||
end
|
||||
|
||||
def test_multiline_nowiki_tag
|
||||
assert_markup_parsed_as(
|
||||
"<p>Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
|
||||
'<span class="newWikiWord">this<a href="../show/this">?</a></span></p>',
|
||||
"Do not <nowiki>mark \n up [[this text]] \n" +
|
||||
"and http://this.url.com </nowiki> but markup [[this]]")
|
||||
end
|
||||
|
||||
def test_content_with_bracketted_wiki_word
|
||||
set_web_property :brackets_only, true
|
||||
assert_markup_parsed_as(
|
||||
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
|
||||
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
|
||||
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
|
||||
end
|
||||
|
||||
def test_content_for_export
|
||||
assert_equal '<p><span class="newWikiWord">His Way</span> would be ' +
|
||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> in kinda ' +
|
||||
'<a class="existingWikiWord" href="ThatWay.html">That Way</a> in ' +
|
||||
'<span class="newWikiWord">His Way</span> though ' +
|
||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere—see ' +
|
||||
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
|
||||
'<span class="newWikiWord">Smart Engine GUI</span></p>',
|
||||
@revision.display_content_for_export
|
||||
end
|
||||
|
||||
def test_double_replacing
|
||||
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
|
||||
assert_equal '<p><span class="newWikiWord">Version History' +
|
||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
|
||||
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
|
||||
'</span></p>',
|
||||
@revision.display_content
|
||||
|
||||
@revision.clear_display_cache
|
||||
|
||||
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
|
||||
assert_equal "<p>f<br /><span class=\"newWikiWord\">Version History" +
|
||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
|
||||
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
|
||||
"</span></p>",
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_difficult_wiki_words
|
||||
@revision.content = "[[It's just awesome GUI!]]"
|
||||
assert_equal "<p><span class=\"newWikiWord\">It's just awesome GUI!" +
|
||||
"<a href=\"../show/It%27s+just+awesome+GUI%21\">?</a></span></p>",
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_revisions_diff
|
||||
Revision.create(:page => @page, :content => 'What a blue and lovely morning',
|
||||
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
|
||||
Revision.create(:page => @page, :content => 'What a red and lovely morning today',
|
||||
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
|
||||
|
||||
assert_equal "<p>What a <del class=\"diffmod\">blue </del><ins class=\"diffmod\">red " +
|
||||
"</ins>and lovely <del class=\"diffmod\">morning</del><ins class=\"diffmod\">morning " +
|
||||
"today</ins></p>", @page.revisions.last.display_diff
|
||||
end
|
||||
|
||||
def test_link_to_file
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
|
||||
'[[doc.pdf:file]]')
|
||||
end
|
||||
|
||||
def test_link_to_pic
|
||||
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
|
||||
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
|
||||
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
|
||||
assert_markup_parsed_as(
|
||||
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
|
||||
'[[square.jpg|Square:pic]]')
|
||||
assert_markup_parsed_as(
|
||||
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
|
||||
'[[square.jpg:pic]]')
|
||||
end
|
||||
|
||||
def test_link_to_non_existant_pic
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
|
||||
'</span></p>',
|
||||
'[[NonExistant.jpg|NonExistant:pic]]')
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
|
||||
'</span></p>',
|
||||
'[[NonExistant.jpg:pic]]')
|
||||
end
|
||||
|
||||
def test_wiki_link_with_colon
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">With:Colon<a href="../show/With%3AColon">?</a></span></p>',
|
||||
'[[With:Colon]]')
|
||||
end
|
||||
|
||||
# TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
|
||||
# also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
|
||||
def test_list_with_tildas
|
||||
list_with_tildas = <<-EOL
|
||||
* "a":~b
|
||||
* c~ d
|
||||
EOL
|
||||
|
||||
assert_markup_parsed_as(
|
||||
"<ul>\n\t<li><a href=\"~b\">a</a></li>\n\t\t<li>c~ d</li>\n\t</ul>",
|
||||
list_with_tildas)
|
||||
end
|
||||
|
||||
def test_textile_image_in_mixed_wiki
|
||||
set_web_property :markup, :mixed
|
||||
assert_markup_parsed_as(
|
||||
"<p><img src=\"http://google.com\" alt=\"\" />\nss</p>",
|
||||
"!http://google.com!\r\nss")
|
||||
end
|
||||
|
||||
def assert_markup_parsed_as(expected_output, input)
|
||||
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
|
||||
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
|
||||
end
|
||||
end
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class RevisionTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
@wiki = Wiki.new
|
||||
@web = webs(:test_wiki)
|
||||
@page = pages(:home_page)
|
||||
@revision = revisions(:home_page_second_revision)
|
||||
end
|
||||
|
||||
def test_wiki_words
|
||||
assert_equal %w( HisWay MyWay SmartEngine SmartEngineGUI ThatWay ), @revision.wiki_words.sort
|
||||
|
||||
@wiki.write_page('wiki1', 'NoWikiWord', 'hey you!', Time.now, 'Me')
|
||||
assert_equal [], @wiki.read_page('wiki1', 'NoWikiWord').wiki_words
|
||||
end
|
||||
|
||||
def test_existing_pages
|
||||
assert_equal %w( MyWay SmartEngine ThatWay ), @revision.existing_pages.sort
|
||||
end
|
||||
|
||||
def test_unexisting_pages
|
||||
assert_equal %w( HisWay SmartEngineGUI ), @revision.unexisting_pages.sort
|
||||
end
|
||||
|
||||
def test_content_with_wiki_links
|
||||
assert_equal '<p><span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||
'would be <a class="existingWikiWord" href="../show/MyWay">My Way</a> in kinda ' +
|
||||
'<a class="existingWikiWord" href="../show/ThatWay">That Way</a> in ' +
|
||||
'<span class="newWikiWord">His Way<a href="../show/HisWay">?</a></span> ' +
|
||||
'though <a class="existingWikiWord" href="../show/MyWay">My Way</a> OverThere—see ' +
|
||||
'<a class="existingWikiWord" href="../show/SmartEngine">Smart Engine</a> in that ' +
|
||||
'<span class="newWikiWord">Smart Engine GUI' +
|
||||
'<a href="../show/SmartEngineGUI">?</a></span></p>',
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_markdown
|
||||
set_web_property :markup, :markdown
|
||||
|
||||
assert_markup_parsed_as(
|
||||
%{<h1>My Headline</h1>\n\n<p>that <span class="newWikiWord">} +
|
||||
%{Smart Engine GUI<a href="../show/SmartEngineGUI">?</a></span></p>},
|
||||
"My Headline\n===========\n\nthat SmartEngineGUI")
|
||||
|
||||
code_block = [
|
||||
'This is a code block:',
|
||||
'',
|
||||
' def a_method(arg)',
|
||||
' return ThatWay',
|
||||
'',
|
||||
'Nice!'
|
||||
].join("\n")
|
||||
|
||||
assert_markup_parsed_as(
|
||||
%{<p>This is a code block:</p>\n\n<pre><code>def a_method(arg)\n} +
|
||||
%{return ThatWay\n</code></pre>\n\n<p>Nice!</p>},
|
||||
code_block)
|
||||
end
|
||||
|
||||
def test_markdown_hyperlink_with_slash
|
||||
# in response to a bug, see http://dev.instiki.org/attachment/ticket/177
|
||||
set_web_property :markup, :markdown
|
||||
|
||||
assert_markup_parsed_as(
|
||||
'<p><a href="http://example/with/slash">text</a></p>',
|
||||
'[text](http://example/with/slash)')
|
||||
end
|
||||
|
||||
def test_mixed_formatting
|
||||
textile_and_markdown = [
|
||||
'Markdown heading',
|
||||
'================',
|
||||
'',
|
||||
'h2. Textile heading',
|
||||
'',
|
||||
'*some* **text** _with_ -styles-',
|
||||
'',
|
||||
'* list 1',
|
||||
'* list 2'
|
||||
].join("\n")
|
||||
|
||||
set_web_property :markup, :markdown
|
||||
assert_markup_parsed_as(
|
||||
"<h1>Markdown heading</h1>\n\n" +
|
||||
"<p>h2. Textile heading</p>\n\n" +
|
||||
"<p><em>some</em> <strong>text</strong> <em>with</em> -styles-</p>\n\n" +
|
||||
"<ul>\n<li>list 1</li>\n<li>list 2</li>\n</ul>",
|
||||
textile_and_markdown)
|
||||
|
||||
set_web_property :markup, :textile
|
||||
assert_markup_parsed_as(
|
||||
"<p>Markdown heading<br />================</p>\n\n\n\t<h2>Textile heading</h2>" +
|
||||
"\n\n\n\t<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>" +
|
||||
"\n\n\n\t<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
|
||||
textile_and_markdown)
|
||||
|
||||
set_web_property :markup, :mixed
|
||||
assert_markup_parsed_as(
|
||||
"<h1>Markdown heading</h1>\n\n\n\t<h2>Textile heading</h2>\n\n\n\t" +
|
||||
"<p><strong>some</strong> <b>text</b> <em>with</em> <del>styles</del></p>\n\n\n\t" +
|
||||
"<ul>\n\t<li>list 1</li>\n\t\t<li>list 2</li>\n\t</ul>",
|
||||
textile_and_markdown)
|
||||
end
|
||||
|
||||
def test_rdoc
|
||||
set_web_property :markup, :rdoc
|
||||
|
||||
@revision = Revision.new(:page => @page, :content => '+hello+ that SmartEngineGUI',
|
||||
:author => Author.new('DavidHeinemeierHansson'))
|
||||
|
||||
assert_equal "<tt>hello</tt> that <span class=\"newWikiWord\">Smart Engine GUI" +
|
||||
"<a href=\"../show/SmartEngineGUI\">?</a></span>\n\n", @revision.display_content
|
||||
end
|
||||
|
||||
def test_content_with_auto_links
|
||||
assert_markup_parsed_as(
|
||||
'<p><a href="http://www.loudthinking.com/">http://www.loudthinking.com/</a> ' +
|
||||
'points to <a class="existingWikiWord" href="../show/ThatWay">That Way</a> from ' +
|
||||
'<a href="mailto:david@loudthinking.com">david@loudthinking.com</a></p>',
|
||||
'http://www.loudthinking.com/ points to ThatWay from david@loudthinking.com')
|
||||
|
||||
end
|
||||
|
||||
def test_content_with_aliased_links
|
||||
assert_markup_parsed_as(
|
||||
'<p>Would a <a class="existingWikiWord" href="../show/SmartEngine">clever motor' +
|
||||
'</a> go by any other name?</p>',
|
||||
'Would a [[SmartEngine|clever motor]] go by any other name?')
|
||||
end
|
||||
|
||||
def test_content_with_wikiword_in_em
|
||||
assert_markup_parsed_as(
|
||||
'<p><em>should we go <a class="existingWikiWord" href="../show/ThatWay">' +
|
||||
'That Way</a> or <span class="newWikiWord">This Way<a href="../show/ThisWay">?</a>' +
|
||||
'</span> </em></p>',
|
||||
'_should we go ThatWay or ThisWay _')
|
||||
end
|
||||
|
||||
def test_content_with_wikiword_in_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>That is some <em style="WikiWord">Stylish Emphasis</em></p>',
|
||||
'That is some <em style="WikiWord">Stylish Emphasis</em>')
|
||||
end
|
||||
|
||||
def test_content_with_escaped_wikiword
|
||||
# there should be no wiki link
|
||||
assert_markup_parsed_as('<p>WikiWord</p>', '\WikiWord')
|
||||
end
|
||||
|
||||
def test_content_with_pre_blocks
|
||||
assert_markup_parsed_as(
|
||||
'<p>A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre></p>',
|
||||
'A <code>class SmartEngine end</code> would not mark up <pre>CodeBlocks</pre>')
|
||||
end
|
||||
|
||||
def test_content_with_autolink_in_parentheses
|
||||
assert_markup_parsed_as(
|
||||
'<p>The <span class="caps">W3C</span> body (<a href="http://www.w3c.org">' +
|
||||
'http://www.w3c.org</a>) sets web standards</p>',
|
||||
'The W3C body (http://www.w3c.org) sets web standards')
|
||||
end
|
||||
|
||||
def test_content_with_link_in_parentheses
|
||||
assert_markup_parsed_as(
|
||||
'<p>(<a href="http://wiki.org/wiki.cgi?WhatIsWiki">What is a wiki?</a>)</p>',
|
||||
'("What is a wiki?":http://wiki.org/wiki.cgi?WhatIsWiki)')
|
||||
end
|
||||
|
||||
def test_content_with_image_link
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is a Textile image link.</p>',
|
||||
'This !http://hobix.com/sample.jpg! is a Textile image link.')
|
||||
end
|
||||
|
||||
def test_content_with_inlined_img_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.</p>',
|
||||
'This <img src="http://hobix.com/sample.jpg" alt="" /> is an inline image link.')
|
||||
|
||||
assert_markup_parsed_as(
|
||||
'<p>This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.</p>',
|
||||
'This <IMG SRC="http://hobix.com/sample.jpg" alt=""> is an inline image link.')
|
||||
end
|
||||
|
||||
def test_nowiki_tag
|
||||
assert_markup_parsed_as(
|
||||
'<p>Do not mark up [[this text]] or http://www.thislink.com.</p>',
|
||||
'Do not mark up <nowiki>[[this text]]</nowiki> ' +
|
||||
'or <nowiki>http://www.thislink.com</nowiki>.')
|
||||
end
|
||||
|
||||
def test_multiline_nowiki_tag
|
||||
assert_markup_parsed_as(
|
||||
"<p>Do not mark \n up [[this text]] \nand http://this.url.com but markup " +
|
||||
'<span class="newWikiWord">this<a href="../show/this">?</a></span></p>',
|
||||
"Do not <nowiki>mark \n up [[this text]] \n" +
|
||||
"and http://this.url.com </nowiki> but markup [[this]]")
|
||||
end
|
||||
|
||||
def test_content_with_bracketted_wiki_word
|
||||
set_web_property :brackets_only, true
|
||||
assert_markup_parsed_as(
|
||||
'<p>This is a WikiWord and a tricky name <span class="newWikiWord">' +
|
||||
'Sperberg-McQueen<a href="../show/Sperberg-McQueen">?</a></span>.</p>',
|
||||
'This is a WikiWord and a tricky name [[Sperberg-McQueen]].')
|
||||
end
|
||||
|
||||
def test_content_for_export
|
||||
assert_equal '<p><span class="newWikiWord">His Way</span> would be ' +
|
||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> in kinda ' +
|
||||
'<a class="existingWikiWord" href="ThatWay.html">That Way</a> in ' +
|
||||
'<span class="newWikiWord">His Way</span> though ' +
|
||||
'<a class="existingWikiWord" href="MyWay.html">My Way</a> OverThere—see ' +
|
||||
'<a class="existingWikiWord" href="SmartEngine.html">Smart Engine</a> in that ' +
|
||||
'<span class="newWikiWord">Smart Engine GUI</span></p>',
|
||||
@revision.display_content_for_export
|
||||
end
|
||||
|
||||
def test_double_replacing
|
||||
@revision.content = "VersionHistory\r\n\r\ncry VersionHistory"
|
||||
assert_equal '<p><span class="newWikiWord">Version History' +
|
||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
|
||||
'<span class="newWikiWord">Version History<a href="../show/VersionHistory">?</a>' +
|
||||
'</span></p>',
|
||||
@revision.display_content
|
||||
|
||||
@revision.clear_display_cache
|
||||
|
||||
@revision.content = "f\r\nVersionHistory\r\n\r\ncry VersionHistory"
|
||||
assert_equal "<p>f<br /><span class=\"newWikiWord\">Version History" +
|
||||
"<a href=\"../show/VersionHistory\">?</a></span></p>\n\n\n\t<p>cry " +
|
||||
"<span class=\"newWikiWord\">Version History<a href=\"../show/VersionHistory\">?</a>" +
|
||||
"</span></p>",
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_difficult_wiki_words
|
||||
@revision.content = "[[It's just awesome GUI!]]"
|
||||
assert_equal "<p><span class=\"newWikiWord\">It's just awesome GUI!" +
|
||||
"<a href=\"../show/It%27s+just+awesome+GUI%21\">?</a></span></p>",
|
||||
@revision.display_content
|
||||
end
|
||||
|
||||
def test_revisions_diff
|
||||
Revision.create(:page => @page, :content => 'What a blue and lovely morning',
|
||||
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
|
||||
Revision.create(:page => @page, :content => 'What a red and lovely morning today',
|
||||
:author => Author.new('DavidHeinemeierHansson'), :revised_at => Time.now)
|
||||
|
||||
assert_equal "<p>What a <del class=\"diffmod\">blue </del><ins class=\"diffmod\">red " +
|
||||
"</ins>and lovely <del class=\"diffmod\">morning</del><ins class=\"diffmod\">morning " +
|
||||
"today</ins></p>", @page.revisions.last.display_diff
|
||||
end
|
||||
|
||||
def test_link_to_file
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">doc.pdf<a href="../file/doc.pdf">?</a></span></p>',
|
||||
'[[doc.pdf:file]]')
|
||||
end
|
||||
|
||||
def test_link_to_pic
|
||||
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
|
||||
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
|
||||
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
|
||||
assert_markup_parsed_as(
|
||||
'<p><img alt="Square" src="../pic/square.jpg" /></p>',
|
||||
'[[square.jpg|Square:pic]]')
|
||||
assert_markup_parsed_as(
|
||||
'<p><img alt="square.jpg" src="../pic/square.jpg" /></p>',
|
||||
'[[square.jpg:pic]]')
|
||||
end
|
||||
|
||||
def test_link_to_non_existant_pic
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">NonExistant<a href="../pic/NonExistant.jpg">?</a>' +
|
||||
'</span></p>',
|
||||
'[[NonExistant.jpg|NonExistant:pic]]')
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">NonExistant.jpg<a href="../pic/NonExistant.jpg">?</a>' +
|
||||
'</span></p>',
|
||||
'[[NonExistant.jpg:pic]]')
|
||||
end
|
||||
|
||||
def test_wiki_link_with_colon
|
||||
assert_markup_parsed_as(
|
||||
'<p><span class="newWikiWord">With:Colon<a href="../show/With%3AColon">?</a></span></p>',
|
||||
'[[With:Colon]]')
|
||||
end
|
||||
|
||||
# TODO Remove the leading underscores from this test when upgrading to RedCloth 3.0.1;
|
||||
# also add a test for the "Unhappy Face" problem (another interesting RedCloth bug)
|
||||
def test_list_with_tildas
|
||||
list_with_tildas = <<-EOL
|
||||
* "a":~b
|
||||
* c~ d
|
||||
EOL
|
||||
|
||||
assert_markup_parsed_as(
|
||||
"<ul>\n\t<li><a href=\"~b\">a</a></li>\n\t\t<li>c~ d</li>\n\t</ul>",
|
||||
list_with_tildas)
|
||||
end
|
||||
|
||||
def test_textile_image_in_mixed_wiki
|
||||
set_web_property :markup, :mixed
|
||||
assert_markup_parsed_as(
|
||||
"<p><img src=\"http://google.com\" alt=\"\" />\nss</p>",
|
||||
"!http://google.com!\r\nss")
|
||||
end
|
||||
|
||||
def assert_markup_parsed_as(expected_output, input)
|
||||
revision = Revision.new(:page => @page, :content => input, :author => Author.new('AnAuthor'))
|
||||
assert_equal expected_output, revision.display_content, 'Textile output not as expected'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,158 +1,158 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class WebTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
@web = webs(:instiki)
|
||||
end
|
||||
|
||||
def test_wiki_word_linking
|
||||
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
|
||||
Time.now, 'DavidHeinemeierHansson')
|
||||
|
||||
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
|
||||
'<a href="../show/EverBeenHated">?</a></span></p>',
|
||||
@web.page("SecondPage").display_content)
|
||||
|
||||
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
|
||||
'DavidHeinemeierHansson')
|
||||
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
|
||||
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
|
||||
@web.page("SecondPage").display_content)
|
||||
end
|
||||
|
||||
def test_pages_by_revision
|
||||
add_sample_pages
|
||||
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
|
||||
end
|
||||
|
||||
def test_pages_by_match
|
||||
add_sample_pages
|
||||
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
|
||||
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
|
||||
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
|
||||
end
|
||||
|
||||
def test_references
|
||||
add_sample_pages
|
||||
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
|
||||
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
|
||||
end
|
||||
|
||||
def test_delete
|
||||
add_sample_pages
|
||||
assert_equal 2, @web.pages.length
|
||||
@web.remove_pages([ @web.page('EverBeenInLove') ])
|
||||
assert_equal 1, @web.pages(true).length
|
||||
end
|
||||
|
||||
def test_make_link
|
||||
add_sample_pages
|
||||
|
||||
existing_page_wiki_url =
|
||||
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
|
||||
existing_page_published_url =
|
||||
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
|
||||
existing_page_static_url =
|
||||
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
|
||||
new_page_wiki_url =
|
||||
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
|
||||
new_page_published_url =
|
||||
new_page_static_url =
|
||||
'<span class="newWikiWord">Unknown Word</span>'
|
||||
|
||||
# no options
|
||||
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
|
||||
|
||||
# :mode => :export
|
||||
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
|
||||
|
||||
# :mode => :publish
|
||||
assert_equal existing_page_published_url,
|
||||
@web.make_link('EverBeenInLove', nil, :mode => :publish)
|
||||
|
||||
# new page, no options
|
||||
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
|
||||
|
||||
# new page, :mode => :export
|
||||
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
|
||||
|
||||
# new page, :mode => :publish
|
||||
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
|
||||
|
||||
# Escaping special characters in the name
|
||||
assert_equal(
|
||||
'<span class="newWikiWord">Smith & Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
|
||||
@web.make_link('Smith & Wesson'))
|
||||
|
||||
# optionally using text as the link text
|
||||
assert_equal(
|
||||
existing_page_published_url.sub(/>Ever Been In Love</, ">Haven't you ever been in love?<"),
|
||||
@web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
|
||||
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
|
||||
|
||||
assert_equal 'Wiki2', web.name
|
||||
assert_equal 'wiki2', web.address
|
||||
assert_equal '123', web.password
|
||||
|
||||
# new web should be set for maximum features enabled
|
||||
assert_equal :textile, web.markup
|
||||
assert_equal '008B26', web.color
|
||||
assert !web.safe_mode?
|
||||
assert_equal([], web.pages)
|
||||
assert web.allow_uploads?
|
||||
assert_nil web.additional_style
|
||||
assert !web.published?
|
||||
assert !web.brackets_only?
|
||||
assert !web.count_pages?
|
||||
assert_equal 100, web.max_upload_size
|
||||
end
|
||||
|
||||
def test_initialize_invalid_name
|
||||
assert_raises(Instiki::ValidationError) {
|
||||
Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
|
||||
}
|
||||
end
|
||||
|
||||
def test_new_page_linked_from_mother_page
|
||||
# this was a bug in revision 204
|
||||
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
|
||||
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
|
||||
@web.add_page('AnotherPage', 'This is \AnotherPage',
|
||||
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
|
||||
|
||||
@web.pages(true)
|
||||
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
|
||||
end
|
||||
|
||||
def test_orphaned_pages
|
||||
add_sample_pages
|
||||
home = @web.add_page('HomePage',
|
||||
'This is a home page, it should not be an orphan',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
|
||||
author = @web.add_page('AlexeyVerkhovsky',
|
||||
'This is an author page, it should not be an orphan',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
|
||||
self_linked = @web.add_page('SelfLinked',
|
||||
'I am me SelfLinked and link to EverBeenInLove',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
|
||||
|
||||
# page that links to itself, and nobody else links to it must be an orphan
|
||||
assert_equal ['EverBeenHated', 'SelfLinked'],
|
||||
@web.select.orphaned_pages.collect{ |page| page.name }.sort
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_sample_pages
|
||||
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
|
||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
||||
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
|
||||
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
|
||||
end
|
||||
end
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class WebTest < Test::Unit::TestCase
|
||||
fixtures :webs, :pages, :revisions, :system
|
||||
|
||||
def setup
|
||||
@web = webs(:instiki)
|
||||
end
|
||||
|
||||
def test_wiki_word_linking
|
||||
@web.add_page('SecondPage', 'Yo, yo. Have you EverBeenHated',
|
||||
Time.now, 'DavidHeinemeierHansson')
|
||||
|
||||
assert_equal('<p>Yo, yo. Have you <span class="newWikiWord">Ever Been Hated' +
|
||||
'<a href="../show/EverBeenHated">?</a></span></p>',
|
||||
@web.page("SecondPage").display_content)
|
||||
|
||||
@web.add_page('EverBeenHated', 'Yo, yo. Have you EverBeenHated', Time.now,
|
||||
'DavidHeinemeierHansson')
|
||||
assert_equal('<p>Yo, yo. Have you <a class="existingWikiWord" ' +
|
||||
'href="../show/EverBeenHated">Ever Been Hated</a></p>',
|
||||
@web.page("SecondPage").display_content)
|
||||
end
|
||||
|
||||
def test_pages_by_revision
|
||||
add_sample_pages
|
||||
assert_equal 'EverBeenHated', @web.select.by_revision.first.name
|
||||
end
|
||||
|
||||
def test_pages_by_match
|
||||
add_sample_pages
|
||||
assert_equal 2, @web.select { |page| page.content =~ /me/i }.length
|
||||
assert_equal 1, @web.select { |page| page.content =~ /Who/i }.length
|
||||
assert_equal 0, @web.select { |page| page.content =~ /none/i }.length
|
||||
end
|
||||
|
||||
def test_references
|
||||
add_sample_pages
|
||||
assert_equal 1, @web.select.pages_that_reference('EverBeenHated').length
|
||||
assert_equal 0, @web.select.pages_that_reference('EverBeenInLove').length
|
||||
end
|
||||
|
||||
def test_delete
|
||||
add_sample_pages
|
||||
assert_equal 2, @web.pages.length
|
||||
@web.remove_pages([ @web.page('EverBeenInLove') ])
|
||||
assert_equal 1, @web.pages(true).length
|
||||
end
|
||||
|
||||
def test_make_link
|
||||
add_sample_pages
|
||||
|
||||
existing_page_wiki_url =
|
||||
'<a class="existingWikiWord" href="../show/EverBeenInLove">Ever Been In Love</a>'
|
||||
existing_page_published_url =
|
||||
'<a class="existingWikiWord" href="../published/EverBeenInLove">Ever Been In Love</a>'
|
||||
existing_page_static_url =
|
||||
'<a class="existingWikiWord" href="EverBeenInLove.html">Ever Been In Love</a>'
|
||||
new_page_wiki_url =
|
||||
'<span class="newWikiWord">Unknown Word<a href="../show/UnknownWord">?</a></span>'
|
||||
new_page_published_url =
|
||||
new_page_static_url =
|
||||
'<span class="newWikiWord">Unknown Word</span>'
|
||||
|
||||
# no options
|
||||
assert_equal existing_page_wiki_url, @web.make_link('EverBeenInLove')
|
||||
|
||||
# :mode => :export
|
||||
assert_equal existing_page_static_url, @web.make_link('EverBeenInLove', nil, :mode => :export)
|
||||
|
||||
# :mode => :publish
|
||||
assert_equal existing_page_published_url,
|
||||
@web.make_link('EverBeenInLove', nil, :mode => :publish)
|
||||
|
||||
# new page, no options
|
||||
assert_equal new_page_wiki_url, @web.make_link('UnknownWord')
|
||||
|
||||
# new page, :mode => :export
|
||||
assert_equal new_page_static_url, @web.make_link('UnknownWord', nil, :mode => :export)
|
||||
|
||||
# new page, :mode => :publish
|
||||
assert_equal new_page_published_url, @web.make_link('UnknownWord', nil, :mode => :publish)
|
||||
|
||||
# Escaping special characters in the name
|
||||
assert_equal(
|
||||
'<span class="newWikiWord">Smith & Wesson<a href="../show/Smith+%26+Wesson">?</a></span>',
|
||||
@web.make_link('Smith & Wesson'))
|
||||
|
||||
# optionally using text as the link text
|
||||
assert_equal(
|
||||
existing_page_published_url.sub(/>Ever Been In Love</, ">Haven't you ever been in love?<"),
|
||||
@web.make_link('EverBeenInLove', "Haven't you ever been in love?", :mode => :publish))
|
||||
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
web = Web.new(:name => 'Wiki2', :address => 'wiki2', :password => '123')
|
||||
|
||||
assert_equal 'Wiki2', web.name
|
||||
assert_equal 'wiki2', web.address
|
||||
assert_equal '123', web.password
|
||||
|
||||
# new web should be set for maximum features enabled
|
||||
assert_equal :textile, web.markup
|
||||
assert_equal '008B26', web.color
|
||||
assert !web.safe_mode?
|
||||
assert_equal([], web.pages)
|
||||
assert web.allow_uploads?
|
||||
assert_nil web.additional_style
|
||||
assert !web.published?
|
||||
assert !web.brackets_only?
|
||||
assert !web.count_pages?
|
||||
assert_equal 100, web.max_upload_size
|
||||
end
|
||||
|
||||
def test_initialize_invalid_name
|
||||
assert_raises(Instiki::ValidationError) {
|
||||
Web.create(:name => 'Wiki2', :address => "wiki\234", :password => '123')
|
||||
}
|
||||
end
|
||||
|
||||
def test_new_page_linked_from_mother_page
|
||||
# this was a bug in revision 204
|
||||
home = @web.add_page('HomePage', 'This page refers to AnotherPage',
|
||||
Time.local(2004, 4, 4, 16, 50), 'Alexey Verkhovsky')
|
||||
@web.add_page('AnotherPage', 'This is \AnotherPage',
|
||||
Time.local(2004, 4, 4, 16, 51), 'Alexey Verkhovsky')
|
||||
|
||||
@web.pages(true)
|
||||
assert_equal [home], @web.select.pages_that_link_to('AnotherPage')
|
||||
end
|
||||
|
||||
def test_orphaned_pages
|
||||
add_sample_pages
|
||||
home = @web.add_page('HomePage',
|
||||
'This is a home page, it should not be an orphan',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
|
||||
author = @web.add_page('AlexeyVerkhovsky',
|
||||
'This is an author page, it should not be an orphan',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AlexeyVerkhovsky')
|
||||
self_linked = @web.add_page('SelfLinked',
|
||||
'I am me SelfLinked and link to EverBeenInLove',
|
||||
Time.local(2004, 4, 4, 16, 50), 'AnonymousCoward')
|
||||
|
||||
# page that links to itself, and nobody else links to it must be an orphan
|
||||
assert_equal ['EverBeenHated', 'SelfLinked'],
|
||||
@web.select.orphaned_pages.collect{ |page| page.name }.sort
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_sample_pages
|
||||
@in_love = @web.add_page('EverBeenInLove', 'Who am I me',
|
||||
Time.local(2004, 4, 4, 16, 50), 'DavidHeinemeierHansson')
|
||||
@hated = @web.add_page('EverBeenHated', 'I am me EverBeenHated',
|
||||
Time.local(2004, 4, 4, 16, 51), 'DavidHeinemeierHansson')
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue