This repository has been archived by the owner on Feb 3, 2018. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Initial commit.
- Loading branch information
0 parents
commit 27a195a
Showing
28 changed files
with
5,040 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
doc/* | ||
*~ | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
= Introduction | ||
|
||
GreenCloth is derived from RedCloth, the defacto text to html converter for ruby. | ||
|
||
The purpose of GreenCloth is to add a bunch of new features to RedCloth that make | ||
it more suited for wiki markup. | ||
|
||
GreenCloth requires that RedCloth version > 4.0 is installed and that prior | ||
versions are NOT installed. | ||
|
||
= Changes from RedCloth | ||
|
||
New markup: | ||
|
||
* Crabgrass style links [my blog post -> meblogpretty.org/2008/4/5] | ||
* Autolinks | ||
* Additional way to specify code blocks | ||
* Markdown blockquotes (>) | ||
* Setext headers (h1 is formed by under line with ====, h2 underline with ----) | ||
* Allow embedded video tags, and sanitize these embeds. | ||
* Tables can use tabs in addition to pipes (|) | ||
* Insert table of contents with [[toc]] | ||
* Add unique clickable anchors to each heading (if to_html is passed option :outline) | ||
* Pass an optional callback block for rendering links (allows for dead link rendering) | ||
|
||
= Usage | ||
|
||
== Example usage | ||
|
||
You can use greencloth like so: | ||
|
||
greencloth = GreenCloth.new(body, context_name, [:outline]) | ||
greencloth.to_html | ||
|
||
Greencloth.new takes three argument: | ||
|
||
* The raw greencloth markup text | ||
* The context name for resolving links. The path for links are prefixed with this context. | ||
* an array of greencloth options. useful options include: | ||
* +:outline+ -- turn on the generation of outline data and markup. | ||
* +:lite_mode+ -- disable blocks, only allow some markup. | ||
|
||
== Passing a block to to_html() | ||
|
||
Greencloth.to_html can take a block. The block is passed data regarding every link | ||
that it encounteres while processing links. | ||
|
||
You can use this to do custom rendering of links. For example: | ||
|
||
html = GreenCloth.new(test_text,'mygroup').to_html() do |link_data| | ||
process_link(link_data) | ||
end | ||
|
||
+process_link+ should return either nil or an <a> tag. If nil, then the greencloth | ||
default is used. | ||
|
||
link_date is a hash that might include: url, label, context_name, page_name | ||
|
||
= Testing | ||
|
||
To run the all the tests: | ||
|
||
rake test | ||
|
||
Or to test the markup from a specific fixture: | ||
|
||
ruby test/markup_test.rb test/fixtures/images.yml | ||
|
||
|
||
== TODO | ||
|
||
sometimes the header detection for editing inline fails. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
require 'rake' | ||
require 'rake/testtask' | ||
require 'rake/rdoctask' | ||
|
||
desc 'Default: run unit tests.' | ||
task :default => :test | ||
|
||
desc 'Test greencloth.' | ||
Rake::TestTask.new(:test) do |t| | ||
#t.libs << File.dirname(__FILE__) | ||
#t.libs << File.dirname(File.dirname(__FILE__)) | ||
t.pattern = 'test/**/*_test.rb' | ||
t.verbose = true | ||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
## | ||
## GreenTree -- a nested tree used for building the outline | ||
## | ||
class GreenTree < Array | ||
attr_accessor :heading_level | ||
attr_accessor :tree_level | ||
attr_accessor :text | ||
attr_accessor :name | ||
attr_accessor :markup_index | ||
attr_accessor :type | ||
attr_accessor :parent | ||
|
||
def initialize(text=nil, name=nil, heading_level=nil, parent=nil) | ||
tree = super() | ||
tree.text = text | ||
tree.heading_level = heading_level | ||
tree.name = name | ||
tree.parent = parent | ||
tree | ||
end | ||
|
||
def inspect | ||
if leaf? | ||
%Q["#{text}"] | ||
else | ||
%Q["#{text||'root'}" -> [#{self.map{|i|i.inspect}.join(', ')}]] | ||
end | ||
end | ||
|
||
alias :to_s :inspect | ||
alias :leaf? :empty? | ||
alias :children= :concat | ||
alias :child :slice | ||
def children; self; end | ||
|
||
def add_child(txt, name, heading_level) | ||
self << GreenTree.new(txt, name, heading_level, self) | ||
end | ||
|
||
# returns the heading text for the one after the 'heading_name' | ||
def successor(heading_name) | ||
children.each_with_index do |node, i| | ||
if node.name == heading_name | ||
next_child = child(i+1) | ||
if self.parent.nil? | ||
return next_child | ||
else | ||
# go up a level to find the next element if we have to | ||
return next_child ? next_child : self.parent.successor(self.name) | ||
end | ||
elsif !node.leaf? | ||
found = node.successor(heading_name) | ||
return found unless found.nil? | ||
end | ||
end | ||
return nil # not found | ||
end | ||
|
||
# walks tree, looking for a node that matches | ||
def find(name) | ||
children.each do |node| | ||
if node.name == name | ||
return node | ||
elsif !node.leaf? | ||
node = node.find(name) | ||
return node unless node.nil? | ||
end | ||
end | ||
return nil # not found | ||
end | ||
|
||
# get the list of all the available heading names in this tree | ||
# makes no guarantee about ordering | ||
def heading_names | ||
names = [] | ||
names << self.name | ||
children.each do |child| | ||
names.concat child.heading_names | ||
end | ||
names.compact | ||
end | ||
|
||
# modifies markup | ||
# finds the location for each heading in the markup | ||
def prepare_markup_index!(markup) | ||
if self.text | ||
# find the first occurance of this node in the markup | ||
self.markup_index = markup.index(self.markup_regexp) | ||
if self.markup_index.nil? | ||
puts "GREENCLOTH ERROR: Can't find heading with text: '#{text}' in markup" | ||
else | ||
# modify the markup, so that it will no longer match | ||
# the markup_regexp at this position | ||
markup[self.markup_index] = "\000" | ||
end | ||
else | ||
self.markup_index = 0 | ||
end | ||
|
||
children.each do |node| | ||
node.prepare_markup_index!(markup) | ||
end | ||
end | ||
|
||
# returns a regexp that can be used to find the original markup for | ||
# this node in a body of greencloth text. it is a little iffy. | ||
# the text we have (self.text) has already been transformed by | ||
# greencloth (there is not a good way around this). So, we have | ||
# some transformed text, that we then need to match against original text. | ||
# yep, it is that ugly. | ||
def markup_regexp | ||
# take out carriage returns | ||
heading_text = Regexp.escape(self.text.gsub(/\r\n/, "\n")) | ||
|
||
# remove html entities, and let them match any character | ||
heading_text.gsub!(/&(\w{2,6}?|\\#[0-9A-Fa-f]{2,6});/,'.') | ||
|
||
# add back carriage returns as optional | ||
heading_text.gsub!('\\n', '\\r?\\n') | ||
|
||
Regexp.union( | ||
/^#{heading_text}\s*\r?\n[=-]+\s*?(\r?\n\r?\n?|$)/, | ||
/^h#{heading_level}\. #{heading_text}\s*?(\r?\n\r?\n?|$)/ | ||
) | ||
end | ||
|
||
end | ||
|
Oops, something went wrong.