From: Chuck Hagenbuch Date: Sat, 15 Nov 2008 14:54:59 +0000 (-0500) Subject: move Horde_Text_Textile to git X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=91adb7a3b93c6d7c4311b528167f6834263b3864;p=horde.git move Horde_Text_Textile to git --- diff --git a/framework/Text_Textile/CVS/Entries b/framework/Text_Textile/CVS/Entries new file mode 100644 index 000000000..a92996860 --- /dev/null +++ b/framework/Text_Textile/CVS/Entries @@ -0,0 +1,3 @@ +/package.xml/1.5/Thu May 29 22:28:36 2008// +D/lib//// +D/test//// diff --git a/framework/Text_Textile/CVS/Repository b/framework/Text_Textile/CVS/Repository new file mode 100644 index 000000000..58462a6e9 --- /dev/null +++ b/framework/Text_Textile/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile diff --git a/framework/Text_Textile/CVS/Root b/framework/Text_Textile/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/CVS/Template b/framework/Text_Textile/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/lib/CVS/Entries b/framework/Text_Textile/lib/CVS/Entries new file mode 100644 index 000000000..ae2779e30 --- /dev/null +++ b/framework/Text_Textile/lib/CVS/Entries @@ -0,0 +1 @@ +D/Horde//// diff --git a/framework/Text_Textile/lib/CVS/Repository b/framework/Text_Textile/lib/CVS/Repository new file mode 100644 index 000000000..244940970 --- /dev/null +++ b/framework/Text_Textile/lib/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/lib diff --git a/framework/Text_Textile/lib/CVS/Root b/framework/Text_Textile/lib/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/lib/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/lib/CVS/Template b/framework/Text_Textile/lib/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/lib/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/lib/Horde/CVS/Entries b/framework/Text_Textile/lib/Horde/CVS/Entries new file mode 100644 index 000000000..66e2d7190 --- /dev/null +++ b/framework/Text_Textile/lib/Horde/CVS/Entries @@ -0,0 +1 @@ +D/Text//// diff --git a/framework/Text_Textile/lib/Horde/CVS/Repository b/framework/Text_Textile/lib/Horde/CVS/Repository new file mode 100644 index 000000000..43b6924cb --- /dev/null +++ b/framework/Text_Textile/lib/Horde/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/lib/Horde diff --git a/framework/Text_Textile/lib/Horde/CVS/Root b/framework/Text_Textile/lib/Horde/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/lib/Horde/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/lib/Horde/CVS/Template b/framework/Text_Textile/lib/Horde/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/lib/Horde/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/lib/Horde/Text/CVS/Entries b/framework/Text_Textile/lib/Horde/Text/CVS/Entries new file mode 100644 index 000000000..a82c12825 --- /dev/null +++ b/framework/Text_Textile/lib/Horde/Text/CVS/Entries @@ -0,0 +1,2 @@ +/Textile.php/1.2/Thu May 29 22:28:36 2008// +D diff --git a/framework/Text_Textile/lib/Horde/Text/CVS/Repository b/framework/Text_Textile/lib/Horde/Text/CVS/Repository new file mode 100644 index 000000000..2baaf83a3 --- /dev/null +++ b/framework/Text_Textile/lib/Horde/Text/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/lib/Horde/Text diff --git a/framework/Text_Textile/lib/Horde/Text/CVS/Root b/framework/Text_Textile/lib/Horde/Text/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/lib/Horde/Text/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/lib/Horde/Text/CVS/Template b/framework/Text_Textile/lib/Horde/Text/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/lib/Horde/Text/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/lib/Horde/Text/Textile.php b/framework/Text_Textile/lib/Horde/Text/Textile.php new file mode 100755 index 000000000..df7072eef --- /dev/null +++ b/framework/Text_Textile/lib/Horde/Text/Textile.php @@ -0,0 +1,839 @@ +toHtml($string); + * + * @category Horde + * @package Horde_Text_Textile + */ +class Horde_Text_Textile { + + /** + * A_HLGN + */ + const REGEX_A_HLGN = '(?:\<(?!>)|(?|\<\>|\=|[()]+(?! ))'; + + /** + * A_VLGN + */ + const REGEX_A_VLGN = '[\-^~]'; + + /** + * '(?:' . A_HLGN . '|' . A_VLGN . ')*' + */ + const REGEX_A = '(?:(?:\<(?!>)|(?|\<\>|\=|[()]+(?! ))|[\-^~])*'; + + /** + * '(?:' . S_CSPN . '|' . S_RSPN . ')*' + */ + const REGEX_S = '(?:(?:\\\\\d+)|(?:\/\d+))*'; + + /** + * '(?:' . C_CLAS . '|' . C_STYL . '|' . C_LNGE . '|' . A_HLGN . ')*' + */ + const REGEX_C = '(?:(?:\([^)]+\))|(?:\{[^}]+\})|(?:\[[^]]+\])|(?:\<(?!>)|(?|\<\>|\=|[()]+(?! )))*'; + + /** + * PUNCT + */ + const REGEX_PUNCT = '\!"#\$%&\'\*\+,-\.\/\:;\=\?@\\\^_`\|~'; + + /** + * LINK_RE + */ + const REGEX_URL = '[\w"$\-_.+!*\'(),";\/?:@=&%#{}|\\^~\[\]`]'; + + /** + * Block tags + */ + const REGEX_BLOCK_TAGS = 'bq|bc|notextile|pre|h[1-6]|fn\d+|p'; + + /** + * Glyphs. Can be overridden if you want to substitute different + * entities. + */ + public static $GLYPH_QUOTE_SINGLE_OPEN = '‘'; + public static $GLYPH_QUOTE_SINGLE_CLOSE = '’'; + public static $GLYPH_QUOTE_DOUBLE_OPEN = '“'; + public static $GLYPH_QUOTE_DOUBLE_CLOSE = '”'; + public static $GLYPH_APOSTROPHE = '’'; + public static $GLYPH_PRIME = '′'; + public static $GLYPH_PRIME_DOUBLE = '″'; + public static $GLYPH_ELLIPSIS = '…'; + public static $GLYPH_EMDASH = '—'; + public static $GLYPH_ENDASH = '–'; + public static $GLYPH_DIMENSION = '×'; + public static $GLYPH_TRADEMARK = '™'; + public static $GLYPH_REGISTERED = '®'; + public static $GLYPH_COPYRIGHT = '©'; + public static $GLYPH_RETURN_ARROW = '↩'; + + /** + * Show images? On by default. + * + * @var boolean + */ + public $images = true; + + /** + * Rel attribute for links (ex: nofollow). + * + * @var string + */ + public $rel = ''; + + /** + * Shelf of values being processed. + * + * @var array + */ + protected $_shelf = array(); + + public function transform($text, $rel = '') + { + if ($rel) { + $this->rel = ' rel="' . $rel . '" '; + } + + $text = $this->cleanWhiteSpace($text); + $text = $this->getRefs($text); + $text = $this->block($text); + + return $this->retrieve($text); + } + + /** + * parse block attributes + * @ignore + */ + public function parseBlockAttributes($in, $element = '') + { + $style = ''; + $class = ''; + $lang = ''; + $colspan = ''; + $rowspan = ''; + $id = ''; + $atts = ''; + + if (!empty($in)) { + $matched = $in; + if ($element == 'td') { + if (preg_match("/\\\\(\d+)/", $matched, $csp)) $colspan = $csp[1]; + if (preg_match("/\/(\d+)/", $matched, $rsp)) $rowspan = $rsp[1]; + } + + if ($element == 'td' || $element == 'tr') { + if (preg_match('/(' . self::REGEX_A_VLGN . ')/', $matched, $vert)) + $style[] = 'vertical-align:' . $this->vAlign($vert[1]) . ';'; + } + + if (preg_match('/\{([^}]*)\}/', $matched, $sty)) { + $style[] = rtrim($sty[1], ';') . ';'; + $matched = str_replace($sty[0], '', $matched); + } + + if (preg_match('/\[([^]]+)\]/U', $matched, $lng)) { + $lang = $lng[1]; + $matched = str_replace($lng[0], '', $matched); + } + + if (preg_match('/\(([^()]+)\)/U', $matched, $cls)) { + $class = $cls[1]; + $matched = str_replace($cls[0], '', $matched); + } + + if (preg_match('/([(]+)/', $matched, $pl)) { + $style[] = 'padding-left:' . strlen($pl[1]) . 'em;'; + $matched = str_replace($pl[0], '', $matched); + } + + if (preg_match('/([)]+)/', $matched, $pr)) { + $style[] = 'padding-right:' . strlen($pr[1]) . 'em;'; + $matched = str_replace($pr[0], '', $matched); + } + + if (preg_match('/(' . self::REGEX_A_HLGN . ')/', $matched, $horiz)) { + $style[] = 'text-align:' . $this->hAlign($horiz[1]) . ';'; + } + + if (preg_match('/^(.*)#(.*)$/', $class, $ids)) { + $id = $ids[2]; + $class = $ids[1]; + } + + return + ($style ? ' style="' . implode('', $style) . '"' : '') + . ($class ? ' class="' . $class . '"' : '') + . ($lang ? ' lang="' . $lang . '"' : '') + . ($id ? ' id="' . $id . '"' : '') + . ($colspan ? ' colspan="' . $colspan . '"' : '') + . ($rowspan ? ' rowspan="' . $rowspan . '"' : ''); + } + + return ''; + } + + /** + * @ignore + */ + public function hasRawText($text) + { + // Checks whether the text has text not already enclosed by a + // block tag. + $r = trim(preg_replace('@<(p|blockquote|div|form|table|ul|ol|pre|h\d)[^>]*?>.*@s', '', trim($text))); + $r = trim(preg_replace('@<\/?(p|blockquote|div|form|table|ul|ol|pre|h\d)[^>]*?\/?>@s', '', $r)); + $r = trim(preg_replace('@<(hr|br)[^>]*?/>@', '', $r)); + return '' != $r; + } + + /** + * @ignore + */ + public function table($text) + { + $text = $text . "\n\n"; + return preg_replace_callback("/^(?:table(_?" . self::REGEX_S . self::REGEX_A . self::REGEX_C . ")\. ?\n)?^(" . self::REGEX_A . self::REGEX_C . "\.? ?\|.*\|)\n\n/smU", + array($this, 'fTable'), $text); + } + + /** + * @ignore + */ + public function fTable($matches) + { + $tatts = $this->parseBlockAttributes($matches[1], 'table'); + + foreach (preg_split("/\|$/m", $matches[2], -1, PREG_SPLIT_NO_EMPTY) as $row) { + if (preg_match("/^(" . self::REGEX_A . self::REGEX_C . "\. )(.*)/m", ltrim($row), $rmtch)) { + $ratts = $this->parseBlockAttributes($rmtch[1], 'tr'); + $row = $rmtch[2]; + } else { + $ratts = ''; + } + $cells = array(); + foreach (explode('|', $row) as $cell) { + $ctyp = 'd'; + if (preg_match("/^_/", $cell)) { + $ctyp = 'h'; + } + if (preg_match("/^(_?" . self::REGEX_S . self::REGEX_A . self::REGEX_C . "\. )(.*)/", $cell, $cmtch)) { + $catts = $this->parseBlockAttributes($cmtch[1], 'td'); + $cell = $cmtch[2]; + } else { + $catts = ''; + } + + $cell = $this->paragraph($this->span($cell)); + if (trim($cell) != '') { + $cells[] = "\t\t\t$cell"; + } + } + $rows[] = "\t\t\n" . implode("\n", $cells) . ($cells ? "\n" : '') . "\t\t"; + unset($cells, $catts); + } + return "\t\n" . implode("\n", $rows) . "\n\t\n\n"; + } + + /** + * @ignore + */ + public function lists($text) + { + return preg_replace_callback("/^([#*]+" . self::REGEX_C . ".*)$(?![^#*])/smU", array($this, 'fList'), $text); + } + + /** + * @ignore + */ + public function fList($m) + { + $out = array(); + $lines = explode("\n", $m[0]); + for ($i = 0, $i_max = count($lines); $i < $i_max; $i++) { + $line = $lines[$i]; + $nextline = isset($lines[$i + 1]) ? $lines[$i + 1] : false; + + if (preg_match("/^([#*]+)(" . self::REGEX_A . self::REGEX_C . ") (.*)$/s", $line, $m)) { + list(, $tl, $atts, $content) = $m; + $nl = ''; + if (preg_match("/^([#*]+)\s.*/", $nextline, $nm)) { + $nl = $nm[1]; + } + $level = strlen($tl); + if (!isset($lists[$tl])) { + $lists[$tl] = true; + $atts = $this->parseBlockAttributes($atts); + $line = str_repeat("\t", $level) . '<' . $this->lT($tl) . "l$atts>\n" . str_repeat("\t", $level + 1) . '
  • ' . $this->paragraph($content); + } else { + $line = str_repeat("\t", $level + 1) . '
  • ' . $this->paragraph($content); + } + + if (strlen($nl) <= strlen($tl)) { + $line .= '
  • '; + } + foreach (array_reverse($lists) as $k => $v) { + if (strlen($k) > strlen($nl)) { + $line .= "\n" . str_repeat("\t", $level--) . 'lT($k) . 'l>'; + if (strlen($k) > 1) { + $line .= ''; + } + unset($lists[$k]); + } + } + } + + $out[] = $line; + } + + return implode("\n", $out); + } + + /** + * @ignore + */ + public function lT($in) + { + return substr($in, 0, 1) == '#' ? 'o' : 'u'; + } + + /** + * @ignore + */ + public function doPBr($in) + { + return preg_replace_callback('@<(p)([^>]*?)>(.*)()@s', array($this, 'doBr'), $in); + } + + /** + * @ignore + */ + public function doBr($m) + { + $content = preg_replace("@(.+)(?|
    )\n(?![#*\s|])@", "\$1
    \n", $m[3]); + return '<' . $m[1] . $m[2] . '>' . $content . $m[4]; + } + + /** + * @ignore + */ + public function block($text) + { + $tag = 'p'; + $atts = $cite = $graf = $ext = ''; + + $text = explode("\n\n", $text); + foreach ($text as $line) { + $anon = 0; + if (preg_match('/^(' . self::REGEX_BLOCK_TAGS . ')(' . self::REGEX_A . self::REGEX_C . ')\.(\.?)(?::(\S+))? (.*)$/s', $line, $m)) { + if ($ext) { + // last block was extended, so close it + $out[count($out) - 1] .= $c1; + } + // new block + list(, $tag, $atts, $ext, $cite, $graf) = $m; + list($o1, $o2, $content, $c2, $c1) = $this->fBlock(array(0, $tag, $atts, $ext, $cite, $graf)); + + // leave off c1 if this block is extended, we'll close + // it at the start of the next block + if ($ext) { + $line = $o1 . $o2 . $content . $c2; + } else { + $line = $o1 . $o2 . $content . $c2 . $c1; + } + } else { + // anonymous block + $anon = 1; + if ($ext || !preg_match('/^ /', $line)) { + list($o1, $o2, $content, $c2, $c1) = $this->fBlock(array(0, $tag, $atts, $ext, $cite, $line)); + // skip $o1/$c1 because this is part of a + // continuing extended block + if ($tag == 'p' && !$this->hasRawText($content)) { + $line = $content; + } else { + $line = $o2 . $content . $c2; + } + } else { + $line = $this->paragraph($line); + } + } + + $line = preg_replace('/
    /', '
    ', $this->doPBr($line)); + + if ($ext && $anon) { + $out[count($out) - 1] .= "\n" . $line; + } else { + $out[] = $line; + } + + if (!$ext) { + $tag = 'p'; + $atts = ''; + $cite = ''; + $graf = ''; + } + } + if ($ext) { + $out[count($out) - 1] .= $c1; + } + return implode("\n\n", $out); + } + + /** + * @ignore + */ + public function fBlock($m) + { + list(, $tag, $atts, $ext, $cite, $content) = $m; + $atts = $this->parseBlockAttributes($atts); + + $o1 = $o2 = $c2 = $c1 = ''; + + if (preg_match('/fn(\d+)/', $tag, $fns)) { + $tag = 'p'; + $fnid = $fns[1]; + $atts .= ' id="fn' . $fnid . '"'; + $content = '' . $fns[1] . ' ' . $content . ' ' . self::$GLYPH_RETURN_ARROW . ''; + } + + if ($tag == 'bq') { + $cite = $this->checkRefs($cite); + $cite = ($cite != '') ? ' cite="' . $cite . '"' : ''; + $o1 = '\n"; + $o2 = ""; + $c2 = '

    '; + $c1 = "\n"; + } elseif ($tag == 'bc') { + $o1 = ""; + $o2 = ""; + $c2 = ''; + $c1 = ''; + $content = $this->shelve($this->encodeHtml(rtrim($content, "\n") . "\n")); + } elseif ($tag == 'notextile') { + $content = $this->shelve($content); + $o1 = $o2 = ''; + $c1 = $c2 = ''; + } elseif ($tag == 'pre') { + $content = $this->shelve($this->encodeHtml(rtrim($content, "\n") . "\n")); + $o1 = ""; + $o2 = $c2 = ''; + $c1 = ''; + } else { + $o2 = "<$tag$atts>"; + $c2 = ""; + } + + return array($o1, $o2, $this->paragraph($content), $c2, $c1); + } + + /** + * Handle normal paragraph text. + * @ignore + */ + public function paragraph($text) + { + $text = $this->code($this->noTextile($text)); + $text = $this->links($text); + if ($this->images) { + $text = $this->image($text); + } + + $text = $this->table($this->lists($text)); + $text = $this->glyphs($this->footnoteRef($this->span($text))); + return rtrim($text, "\n"); + } + + /** + * @ignore + */ + public function span($text) + { + $qtags = array('\*\*', '\*', '\?\?', '-', '__', '_', '%', '\+', '~', '\^'); + $pnct = ".,\"'?!;:"; + + foreach ($qtags as $f) { + $text = preg_replace_callback("/ + (?:^|(?<=[\s>$pnct])|([{[])) + ($f)(?!$f) + (" . self::REGEX_C . ") + (?::(\S+))? + ([^\s$f]+|\S[^$f\n]*[^\s$f\n]) + ([$pnct]*) + $f + (?:$|([\]}])|(?=[[:punct:]]{1,2}|\s)) + /x", array($this, 'fSpan'), $text); + } + return $text; + } + + /** + * @ignore + */ + public function fSpan($m) + { + $qtags = array( + '*' => 'strong', + '**' => 'b', + '??' => 'cite', + '_' => 'em', + '__' => 'i', + '-' => 'del', + '%' => 'span', + '+' => 'ins', + '~' => 'sub', + '^' => 'sup', + ); + + list(, , $tag, $atts, $cite, $content, $end) = $m; + $tag = $qtags[$tag]; + $atts = $this->parseBlockAttributes($atts) + . ($cite ? 'cite="' . $cite . '"' : ''); + + return "<$tag$atts>$content$end"; + } + + /** + * @ignore + */ + public function links($text) + { + $punct = preg_quote('!"#$%&\'*+,-./:;=?@\\^_`|~', '/'); + return preg_replace_callback('/ + (^|(?<=[\s>.' . self::REGEX_PUNCT . '\(])|([{[])) # $pre + " # $start + (' . self::REGEX_C . ') # $atts + ([^"]+) # $text + \s? + (?:\(([^)]+)\)(?="))? # $title + ": + (' . self::REGEX_URL . '+) # $url + (\/)? # $slash + ([^\w\/;]*) # $post + (?:([\]}])|(?=\s|$|\))) + /Ux', array($this, 'fLink'), $text); + } + + /** + * @ignore + */ + public function fLink($m) + { + list(, $pre, $start, $atts, $text, $title, $url, $slash, $post) = $m; + + $atts = $this->parseBlockAttributes($atts) + . ($title != '') ? ' title="' . $this->encodeHtml($title) . '"' : ''; + + if ($this->images) { + $text = $this->image($text); + } + $text = $this->glyphs($this->span($text)); + + $url = $this->checkRefs($url); + + return $this->shelve('rel ? ' rel="' . $this->rel . '" ' : '') . '>' + . $text . '' . $post); + } + + /** + * @ignore + */ + public function getRefs($text) + { + return preg_replace_callback("/(?<=^|\s)\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/U", + array($this, 'refs'), $text); + } + + /** + * @ignore + */ + public function refs($m) + { + list(, $flag, $url) = $m; + $this->urlrefs[$flag] = $url; + return ''; + } + + /** + * @ignore + */ + public function checkRefs($text) + { + return isset($this->urlrefs[$text]) ? $this->urlrefs[$text] : $text; + } + + /** + * @ignore + */ + public function image($text) + { + return preg_replace_callback("/ + (?:[[{])? # pre + \! # opening ! + (\<|\=|\>)?? # optional alignment attributes + (" . self::REGEX_C . ") # optional style, class attributes + (?:\. )? # optional dot-space + ([^\s(!]+) # presume this is the src + \s? # optional space + (?:\(([^\)]+)\))? # optional title + \! # closing + (?::(\S+))? # optional href + (?:[\]}]|(?=\s|$)) # lookahead: space or end of string + /Ux", array($this, 'fImage'), $text); + } + + /** + * @ignore + */ + public function fImage($m) + { + list(, $algn, $atts, $url) = $m; + $title = isset($m[4]) ? $m[4] : ''; + $atts = $this->parseBlockAttributes($atts) + . ($algn != '' ? ' align="' . $this->iAlign($algn) . '"' : '') + . ($title ? ' title="' . $title . '"' : '') + . ' alt="' . $title . '"'; + + $href = isset($m[5]) ? $this->checkRefs($m[5]) : ''; + $url = $this->checkRefs($url); + + return ($href ? '' : '') + . '' + . ($href ? '' : ''); + } + + /** + * @ignore + */ + public function code($text) + { + $text = $this->doSpecial($text, '', '', 'fCode'); + $text = $this->doSpecial($text, '@', '@', 'fCode'); + $text = $this->doSpecial($text, '
    ', '
    ', 'fPre'); + return $text; + } + + /** + * @ignore + */ + public function fCode($m) + { + @list(, $before, $text, $after) = $m; + return $before . $this->shelve('' . $this->encodeHtml($text, false) . '') . $after; + } + + /** + * @ignore + */ + public function fPre($m) + { + @list(, $before, $text, $after) = $m; + return $before . '
    ' . $this->shelve($this->encodeHtml($text, false)) . '
    ' . $after; + } + + /** + * @ignore + */ + public function shelve($val) + { + $i = uniqid(mt_rand()); + $this->_shelf[$i] = $val; + return $i; + } + + /** + * @ignore + */ + public function retrieve($text) + { + if (is_array($this->_shelf)) { + do { + $old = $text; + $text = strtr($text, $this->_shelf); + } while ($text != $old); + } + return $text; + } + + /** + * @ignore + */ + public function cleanWhiteSpace($text) + { + return preg_replace(array("/\r\n/", "/\n{3,}/", "/\n *\n/"), + array("\n", "\n\n", "\n\n"), + $text); + } + + /** + * @ignore + */ + public function doSpecial($text, $start, $end, $method = 'fSpecial') + { + return preg_replace_callback('/(^|\s|[[({>])' . preg_quote($start, '/') . '(.*?)' . preg_quote($end, '/') . '(\s|$|[\])}])?/ms', + array($this, $method), $text); + } + + /** + * @ignore + */ + public function fSpecial($m) + { + // A special block like notextile or code + @list(, $before, $text, $after) = $m; + return $before . $this->shelve($this->encodeHtml($text)) . $after; + } + + /** + * @ignore + */ + public function noTextile($text) + { + $text = $this->doSpecial($text, '', '', 'fTextile'); + return $this->doSpecial($text, '==', '==', 'fTextile'); + } + + /** + * @ignore + */ + public function fTextile($m) + { + @list(, $before, $notextile, $after) = $m; + return $before . $this->shelve($notextile) . $after; + } + + /** + * @ignore + */ + public function footnoteRef($text) + { + return preg_replace('/\b\[([0-9]+)\](\s)?/U', + '$1$2', + $text); + } + + /** + * @ignore + */ + public function glyphs($text) + { + $glyph_search = array( + '/(\w)\'(\w)/', // apostrophe's + '/(\s)\'(\d+\w?)\b(?!\')/', // back in '88 + '/(\S)\'(?=\s|[[:punct:]]|<|$)/', // single closing + '/\'/', // single opening + '/(\S)\"(?=\s|[[:punct:]]|<|$)/', // double closing + '/"/', // double opening + '/\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/', // 3+ uppercase acronym + '/\b([A-Z][A-Z\'\-]+[A-Z])(?=[\s.,\)>])/', // 3+ uppercase + '/\b( )?\.{3}/', // ellipsis + '/(\s?)--(\s?)/', // em dash + '/\s-(?:\s|$)/', // en dash + '/(\d+)( ?)x( ?)(?=\d+)/', // dimension sign + '/\b ?[([]TM[])]/i', // trademark + '/\b ?[([]R[])]/i', // registered + '/\b ?[([]C[])]/i', // copyright + ); + + $glyph_replace = array( + '$1' . self::$GLYPH_APOSTROPHE . '$2', // apostrophes + '$1' . self::$GLYPH_APOSTROPHE . '$2', // back in '88 + '$1' . self::$GLYPH_QUOTE_SINGLE_CLOSE, // single closing + self::$GLYPH_QUOTE_SINGLE_OPEN, // single opening + '$1' . self::$GLYPH_QUOTE_DOUBLE_CLOSE, // double closing + self::$GLYPH_QUOTE_DOUBLE_OPEN, // double opening + '$1', // 3+ uppercase acronym + '$1', // 3+ uppercase + '$1' . self::$GLYPH_ELLIPSIS, // ellipsis + self::$GLYPH_EMDASH, // em dash + ' ' . self::$GLYPH_ENDASH . ' ', // en dash + '$1' . self::$GLYPH_DIMENSION, // dimension sign + self::$GLYPH_TRADEMARK, // trademark + self::$GLYPH_REGISTERED, // registered + self::$GLYPH_COPYRIGHT, // copyright + ); + + $text = preg_split('/(<.*>)/U', $text, -1, PREG_SPLIT_DELIM_CAPTURE); + foreach ($text as $line) { + if (!preg_match('/<.*>/', $line)) { + $line = preg_replace($glyph_search, $glyph_replace, $line); + } + $glyph_out[] = $line; + } + + return implode('', $glyph_out); + } + + /** + * @ignore + */ + public function iAlign($in) + { + $vals = array( + '<' => 'left', + '=' => 'center', + '>' => 'right'); + return isset($vals[$in]) ? $vals[$in] : ''; + } + + /** + * @ignore + */ + public function hAlign($in) + { + $vals = array( + '<' => 'left', + '=' => 'center', + '>' => 'right', + '<>' => 'justify'); + return isset($vals[$in]) ? $vals[$in] : ''; + } + + /** + * @ignore + */ + public function vAlign($in) + { + $vals = array( + '^' => 'top', + '-' => 'middle', + '~' => 'bottom'); + return isset($vals[$in]) ? $vals[$in] : ''; + } + + /** + * @ignore + */ + public function encodeHtml($str, $quotes = true) + { + $a = array( + '&' => '&', + '<' => '<', + '>' => '>', + ); + if ($quotes) { + $a = $a + array( + "'" => ''', + '"' => '"', + ); + } + + return strtr($str, $a); + } + +} diff --git a/framework/Text_Textile/package.xml b/framework/Text_Textile/package.xml new file mode 100644 index 000000000..c158ebff2 --- /dev/null +++ b/framework/Text_Textile/package.xml @@ -0,0 +1,100 @@ + + + Horde_Text_Textile + pear.horde.org + Textile formatting library + +_____________ +T E X T I L E + +A Humane Web Text Generator + +Version 2.0 + +Copyright (c) 2003-2004, Dean Allen <dean@textism.com> +All rights reserved. + +Thanks to Carlo Zottmann <carlo@g-blog.net> for refactoring +Textile's procedural code into a class framework + +Additions and fixes Copyright (c) 2006 Alex Shiels http://thresholdstate.com/ + +_____________ +L I C E N S E + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name Textile nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + + Chuck Hagenbuch + chuck + chuck@horde.org + yes + + 2007-05-12 + + 0.1.0 + 0.1.0 + + + beta + beta + + BSD + +* Initial release. +* Add return links to footnotes + + + + + + + + + + + + + + + + 5.1.0 + + + 1.5.0 + + + + + + + + + diff --git a/framework/Text_Textile/test/CVS/Entries b/framework/Text_Textile/test/CVS/Entries new file mode 100644 index 000000000..ae2779e30 --- /dev/null +++ b/framework/Text_Textile/test/CVS/Entries @@ -0,0 +1 @@ +D/Horde//// diff --git a/framework/Text_Textile/test/CVS/Repository b/framework/Text_Textile/test/CVS/Repository new file mode 100644 index 000000000..ba8a059f0 --- /dev/null +++ b/framework/Text_Textile/test/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/test diff --git a/framework/Text_Textile/test/CVS/Root b/framework/Text_Textile/test/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/test/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/test/CVS/Template b/framework/Text_Textile/test/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/test/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/test/Horde/CVS/Entries b/framework/Text_Textile/test/Horde/CVS/Entries new file mode 100644 index 000000000..66e2d7190 --- /dev/null +++ b/framework/Text_Textile/test/Horde/CVS/Entries @@ -0,0 +1 @@ +D/Text//// diff --git a/framework/Text_Textile/test/Horde/CVS/Repository b/framework/Text_Textile/test/Horde/CVS/Repository new file mode 100644 index 000000000..b68d0fa86 --- /dev/null +++ b/framework/Text_Textile/test/Horde/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/test/Horde diff --git a/framework/Text_Textile/test/Horde/CVS/Root b/framework/Text_Textile/test/Horde/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/test/Horde/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/test/Horde/CVS/Template b/framework/Text_Textile/test/Horde/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/test/Horde/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/test/Horde/Text/CVS/Entries b/framework/Text_Textile/test/Horde/Text/CVS/Entries new file mode 100644 index 000000000..0113b0cab --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/CVS/Entries @@ -0,0 +1 @@ +D/Textile//// diff --git a/framework/Text_Textile/test/Horde/Text/CVS/Repository b/framework/Text_Textile/test/Horde/Text/CVS/Repository new file mode 100644 index 000000000..3e4e8271d --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/test/Horde/Text diff --git a/framework/Text_Textile/test/Horde/Text/CVS/Root b/framework/Text_Textile/test/Horde/Text/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/test/Horde/Text/CVS/Template b/framework/Text_Textile/test/Horde/Text/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/test/Horde/Text/Textile/AllTests.php b/framework/Text_Textile/test/Horde/Text/Textile/AllTests.php new file mode 100755 index 000000000..9e41caf79 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/AllTests.php @@ -0,0 +1,52 @@ +isFile() && preg_match('/Test.php$/', $file->getFilename())) { + $pathname = $file->getPathname(); + require $pathname; + + $class = str_replace(DIRECTORY_SEPARATOR, '_', + preg_replace("/^$baseregexp(.*)\.php/", '\\1', $pathname)); + $suite->addTestSuite('Horde_Text_Textile_' . $class); + } + } + + return $suite; + } + +} + +if (PHPUnit_MAIN_METHOD == 'Horde_Text_Textile_AllTests::main') { + Horde_Text_Textile_AllTests::main(); +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/AttributesTest.php b/framework/Text_Textile/test/Horde/Text/Textile/AttributesTest.php new file mode 100644 index 000000000..58e277073 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/AttributesTest.php @@ -0,0 +1,113 @@ +assertTransforms('p(example1). An example', + '

    An example

    '); + + $this->assertTransforms('p(#big-red). Red here', + '

    Red here

    '); + + $this->assertTransforms('p(example1#big-red2). Red here', + '

    Red here

    '); + + $this->assertTransforms('p{color:blue;margin:30px}. Spacey blue', + '

    Spacey blue

    '); + + $this->assertTransforms('p[fr]. rouge', + '

    rouge

    '); + } + + public function testPhraseAttributes() + { + $this->assertTransforms('I seriously *{color:red}blushed* when I _(big)sprouted_ that corn stalk from my %[es]cabeza%.', + '

    I seriously blushed when I sprouted that corn stalk from my cabeza.

    '); + } + + public function testBlockAlignments() + { + $this->assertTransforms('p<. align left', + '

    align left

    '); + + $this->assertTransforms('p>. align right', + '

    align right

    '); + + $this->assertTransforms('p=. centered', + '

    centered

    '); + + $this->assertTransforms('p<>. justified', + '

    justified

    '); + + $this->assertTransforms('p(. left ident 1em', + '

    left ident 1em

    '); + + $this->assertTransforms('p((. left ident 2em', + '

    left ident 2em

    '); + + $this->assertTransforms('p))). right ident 3em', + '

    right ident 3em

    '); + } + + public function testCombinedAlignments() + { + $this->assertTransforms('h2()>. Bingo.', + '

    Bingo.

    '); + + $this->assertTransforms('h3()>[no]{color:red}. Bingo', + '

    Bingo

    '); + } + + public function testHtml() + { + $this->assertTransforms('
    +
    +a.gsub!( /
    +
    ', + '
    +
    +a.gsub!( /</, \'\' )
    +
    +
    '); + + $text = '
    + +h3. Sidebar + +"Hobix":http://hobix.com/ "Ruby":http://ruby-lang.org/ + +
    + +The main text of the page goes here and will stay to the left of the sidebar.'; + + $html = '
    + +

    Sidebar

    + +

    Hobix Ruby

    + +
    + +

    The main text of the page goes here and will stay to the left of the sidebar.

    '; + + $this->assertTransforms($text, $html); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/BlockModifiersTest.php b/framework/Text_Textile/test/Horde/Text/Textile/BlockModifiersTest.php new file mode 100644 index 000000000..514bea1a8 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/BlockModifiersTest.php @@ -0,0 +1,56 @@ +assertTransforms('h1. Header 1', '

    Header 1

    ', 'H1'); + $this->assertTransforms('h2. Header 2', '

    Header 2

    ', 'H2'); + $this->assertTransforms('h3. Header 3', '

    Header 3

    ', 'H3'); + } + + public function testBlockQuotes() + { + $text = "An old text + +bq. A block quotation. + +Any old text"; + $html = "

    An old text

    + +
    +

    A block quotation.

    +
    + +

    Any old text

    "; + + $this->assertTransforms($text, $html); + } + + public function testFootnotes() + { + $text = 'This is covered elsewhere[1].'; + $html = '

    This is covered elsewhere1.

    '; + $this->assertTransforms($text, $html); + + $text = 'fn1. Down here, in fact.'; + $html = '

    1 Down here, in fact.

    '; + $this->assertTransforms($text, $html); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/CVS/Entries b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Entries new file mode 100644 index 000000000..b03e78af3 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Entries @@ -0,0 +1,10 @@ +/AllTests.php/1.1/Wed Mar 5 20:37:52 2008// +/AttributesTest.php/1.1/Wed Mar 5 20:37:52 2008// +/BlockModifiersTest.php/1.2/Thu May 29 22:28:36 2008// +/ExternalReferencesTest.php/1.1/Wed Mar 5 20:37:52 2008// +/ListsTest.php/1.1/Wed Mar 5 20:37:52 2008// +/PhraseModifiersTest.php/1.1/Wed Mar 5 20:37:52 2008// +/TablesTest.php/1.1/Wed Mar 5 20:37:52 2008// +/TestCase.php/1.1/Wed Mar 5 20:37:52 2008// +/WritingTest.php/1.1/Wed Mar 5 20:37:52 2008// +D diff --git a/framework/Text_Textile/test/Horde/Text/Textile/CVS/Repository b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Repository new file mode 100644 index 000000000..787ce38f8 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Repository @@ -0,0 +1 @@ +framework/Text_Textile/test/Horde/Text/Textile diff --git a/framework/Text_Textile/test/Horde/Text/Textile/CVS/Root b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Root new file mode 100644 index 000000000..5d636129a --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Root @@ -0,0 +1 @@ +chuck@cvs.horde.org:/repository diff --git a/framework/Text_Textile/test/Horde/Text/Textile/CVS/Template b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Template new file mode 100644 index 000000000..3971591f9 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/CVS/Template @@ -0,0 +1,8 @@ + +Bug: +Submitted by: +Merge after: +CVS: ---------------------------------------------------------------------- +CVS: Bug: Fill this in if a listed bug is affected by the change. +CVS: Submitted by: Fill this in if someone else sent in the change. +CVS: Merge after: N [day[s]|week[s]|month[s]] (days assumed by default) diff --git a/framework/Text_Textile/test/Horde/Text/Textile/ExternalReferencesTest.php b/framework/Text_Textile/test/Horde/Text/Textile/ExternalReferencesTest.php new file mode 100644 index 000000000..d34fc13ab --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/ExternalReferencesTest.php @@ -0,0 +1,64 @@ +assertTransforms('I searched "Google":http://google.com.', + '

    I searched Google.

    '); + } + + public function testLinkAliases() + { + $this->assertTransforms('I am crazy about "Hobix":hobix and "it\'s":hobix "all":hobix I ever "link to":hobix! + +[hobix]http://hobix.com', + '

    I am crazy about Hobix and it’s all I ever link to!

    + +'); + } + + public function testEmbeddedImages() + { + $this->assertTransforms('!http://hobix.com/sample.jpg!', + '

    '); + + $this->assertTransforms('!openwindow1.gif(Bunny.)!', + '

    Bunny.

    '); + + $this->assertTransforms('!openwindow1.gif!:http://hobix.com/', + '

    '); + } + + public function testImageAlignments() + { + $this->assertTransforms('!>obake.gif! + +And others sat all round the small machine and paid it to sing to them.', + '

    + +

    And others sat all round the small machine and paid it to sing to them.

    '); + } + + public function testAcronyms() + { + $this->assertTransforms('We use CSS(Cascading Style Sheets).', + '

    We use CSS.

    '); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/ListsTest.php b/framework/Text_Textile/test/Horde/Text/Textile/ListsTest.php new file mode 100644 index 000000000..1c2e15366 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/ListsTest.php @@ -0,0 +1,86 @@ +assertTransforms('# A first item +# A second item +# A third', + "\t
      +\t\t
    1. A first item
    2. +\t\t
    3. A second item
    4. +\t\t
    5. A third
    6. +\t
    "); + + $this->assertTransforms('# Fuel could be: +## Coal +## Gasoline +## Electricity +# Humans need only: +## Water +## Protein', + "\t
      +\t\t
    1. Fuel could be: +\t\t
        +\t\t\t
      1. Coal
      2. +\t\t\t
      3. Gasoline
      4. +\t\t\t
      5. Electricity
      6. +\t\t
    2. +\t\t
    3. Humans need only: +\t\t
        +\t\t\t
      1. Water
      2. +\t\t\t
      3. Protein
      4. +\t\t
    4. +\t
    "); + } + + public function testBulletedLists() + { + $this->assertTransforms('* A first item +* A second item +* A third', + "\t
      +\t\t
    • A first item
    • +\t\t
    • A second item
    • +\t\t
    • A third
    • +\t
    "); + + $this->assertTransforms('* Fuel could be: +** Coal +** Gasoline +** Electricity +* Humans need only: +** Water +** Protein', + "\t
      +\t\t
    • Fuel could be: +\t\t
        +\t\t\t
      • Coal
      • +\t\t\t
      • Gasoline
      • +\t\t\t
      • Electricity
      • +\t\t
    • +\t\t
    • Humans need only: +\t\t
        +\t\t\t
      • Water
      • +\t\t\t
      • Protein
      • +\t\t
    • +\t
    "); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/PhraseModifiersTest.php b/framework/Text_Textile/test/Horde/Text/Textile/PhraseModifiersTest.php new file mode 100644 index 000000000..82e5db0fc --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/PhraseModifiersTest.php @@ -0,0 +1,67 @@ +assertTransforms('I _believe_ every word.', + '

    I believe every word.

    '); + + $this->assertTransforms('And then? She *fell*!', + '

    And then? She fell!

    '); + + $this->assertTransforms("I __know__. +I **really** __know__.", + "

    I know.
    +I really know.

    "); + + $this->assertTransforms('??Cat\'s Cradle?? by Vonnegut', + '

    Cat’s Cradle by Vonnegut

    ', + 'Citation'); + + $this->assertTransforms('Convert with @r.to_html@', + '

    Convert with r.to_html

    ', + 'Code'); + + $this->assertTransforms('I\'m -sure- not sure.', + '

    I’m sure not sure.

    ', + 'Deleted Text'); + + $this->assertTransforms('You are a +pleasant+ child.', + '

    You are a pleasant child.

    ', + 'Inserted Text'); + + $this->assertTransforms('a ^2^ + b ^2^ = c ^2^', + '

    a 2 + b 2 = c 2

    ', + 'Superscript'); + + $this->assertTransforms('log ~2~ x', + '

    log 2 x

    ', + 'Subscript'); + } + + public function testHtmlAttributes() + { + $this->assertTransforms('I\'m %unaware% of most soft drinks.', + '

    I’m unaware of most soft drinks.

    '); + + $this->assertTransforms('I\'m %{color:red}unaware% of most soft drinks.', + '

    I’m unaware of most soft drinks.

    '); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/TablesTest.php b/framework/Text_Textile/test/Horde/Text/Textile/TablesTest.php new file mode 100644 index 000000000..3bc16039c --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/TablesTest.php @@ -0,0 +1,195 @@ + +\t\t +\t\t\t name +\t\t\t age +\t\t\t sex +\t\t +\t\t +\t\t\t joan +\t\t\t 24 +\t\t\t f +\t\t +\t\t +\t\t\t archie +\t\t\t 29 +\t\t\t m +\t\t +\t\t +\t\t\t bella +\t\t\t 45 +\t\t\t f +\t\t +\t"; + $this->assertTransforms($text, $html); + } + + public function testSimpleTableHeaders() + { + $text = '|_. name |_. age |_. sex | +| joan | 24 | f | +| archie | 29 | m | +| bella | 45 | f |'; + $html = "\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t
    name age sex
    joan 24 f
    archie 29 m
    bella 45 f
    "; + $this->assertTransforms($text, $html); + } + + public function testCellAttributes() + { + $text = '|_. attribute list | +|<. align left | +|>. align right| +|=. center | +|<>. justify | +|^. valign top | +|~. bottom |'; + $html = "\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t
    attribute list
    align left
    align right
    center
    justify
    valign top
    bottom
    "; + $this->assertTransforms($text, $html, 'Cell alignment'); + + $text = '|\2. spans two cols | +| col 1 | col 2 |'; + $html = "\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t\t +\t\t +\t
    spans two cols
    col 1 col 2
    "; + $this->assertTransforms($text, $html, 'Colspan'); + + $text = '|/3. spans 3 rows | a | +| b | +| c |'; + $html = "\t +\t\t +\t\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t +\t
    spans 3 rows a
    b
    c
    "; + $this->assertTransforms($text, $html, 'Rowspan'); + + $text = '|{background:#ddd}. Grey cell|'; + $html = "\t +\t\t +\t\t\t +\t\t +\t
    Grey cell
    "; + $this->assertTransforms($text, $html, 'Block attributes on cells'); + } + + public function testTableRowAttributes() + { + $text = 'table{border:1px solid black}. +|This|is|a|row| +|This|is|a|row|'; + $html = "\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t
    Thisisarow
    Thisisarow
    "; + $this->assertTransforms($text, $html, 'Table-wide attributes'); + + $text = '|This|is|a|row| +{background:#ddd}. |This|is|grey|row|'; + $html = "\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t\t +\t\t +\t
    Thisisarow
    Thisisgreyrow
    "; + $this->assertTransforms($text, $html, 'Row attributes'); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/TestCase.php b/framework/Text_Textile/test/Horde/Text/Textile/TestCase.php new file mode 100644 index 000000000..15775b3f5 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/TestCase.php @@ -0,0 +1,29 @@ +textilizer = new Horde_Text_Textile; + } + + + public function assertTransforms($text, $html, $msg = '') + { + $this->assertEquals($html, $this->textilizer->transform($text), $msg); + } + +} diff --git a/framework/Text_Textile/test/Horde/Text/Textile/WritingTest.php b/framework/Text_Textile/test/Horde/Text/Textile/WritingTest.php new file mode 100755 index 000000000..029bb0c21 --- /dev/null +++ b/framework/Text_Textile/test/Horde/Text/Textile/WritingTest.php @@ -0,0 +1,68 @@ +A single paragraph.

    + +

    Followed by another.

    "; + + $this->assertTransforms($text, $html); + } + + public function testHtml() + { + $text = "I am very serious. + +
    +I am very serious.
    +
    "; + $html = "

    I am very serious.

    + +
    +I am <b>very</b> serious.
    +
    "; + + $this->assertTransforms($text, $html); + } + + public function testLinebreaks() + { + $text = "I spoke. +And none replied."; + $html = "

    I spoke.
    +And none replied.

    "; + + $this->assertTransforms($text, $html); + } + + public function testEntities() + { + $this->assertTransforms('"Observe!"', '

    “Observe!”

    ', 'Curly Quotes'); + $this->assertTransforms('Observe -- very nice!', '

    Observe—very nice!

    ', 'Em Dash'); + $this->assertTransforms('Observe - tiny and brief.', '

    Observe – tiny and brief.

    ', 'En Dash'); + $this->assertTransforms('Observe...', '

    Observe…

    ', 'Ellipsis'); + $this->assertTransforms('Observe: 2 x 2.', '

    Observe: 2×2.

    ', 'Dimension'); + $this->assertTransforms('one(TM), two(R), three(C).', '

    one™, two®, three©.

    ', 'Trademark, Registered, Copyright'); + } + +}