From 73513b8f821301b7e9758254aa88c30f6180f81d Mon Sep 17 00:00:00 2001 From: pecesama Date: Tue, 24 Jul 2007 20:52:33 +0000 Subject: [PATCH] Comment feature (started) and bug fix for the textile problem. --- admin/index.php | 6 +- admin/options.php | 136 +- classes/comments.class.php | 89 + classes/configuration.class.php | 7 +- classes/gelato.class.php | 2 +- classes/textile.class.php | 5216 +++++------------------ comments.php | 115 + index.php | 24 +- notice.txt | 4 +- themes/tumblr/style.css | 31 + themes/tumblr/template_comment_post.htm | 37 + themes/tumblr/template_comments.htm | 18 + 12 files changed, 1527 insertions(+), 4158 deletions(-) create mode 100644 classes/comments.class.php create mode 100644 comments.php create mode 100644 themes/tumblr/template_comment_post.htm create mode 100644 themes/tumblr/template_comments.htm diff --git a/admin/index.php b/admin/index.php index faf5544..fbe20f3 100644 --- a/admin/index.php +++ b/admin/index.php @@ -344,10 +344,10 @@ if ($user->isAdmin()) { if ($tumble->contarRegistros()>0) { while($register = mysql_fetch_array($rs)) { $formatedDate = date("M d", strtotime($register["date"])); - $permalink = $conf->urlGelato."/index.php/post/".$register["id_post"]."/"; + $permalink = $conf->urlGelato."/index.php/post/".$register["id_post"]."/"; - $textile = new Textile; - $register["description"] = $textile->process($register["description"]); + $textile = new Textile(); + $register["description"] = $textile->TextileThis($register["description"]); $register["title"] = stripslashes($register["title"]); $register["description"] = stripslashes($register["description"]); diff --git a/admin/options.php b/admin/options.php index f2c47f8..170bc09 100644 --- a/admin/options.php +++ b/admin/options.php @@ -45,6 +45,12 @@ if ($user->isAdmin()) { header("Location: ".$conf->urlGelato."/admin/options.php?error=1&des=".$conf->merror); die(); } + + if (!$tumble->saveOption($_POST["allow_comments"], "allow_comments")) { + header("Location: ".$conf->urlGelato."/admin/options.php?error=1&des=".$conf->merror); + die(); + } + header("Location: ".$conf->urlGelato."/admin/options.php?modified=true"); die(); } else { @@ -117,75 +123,81 @@ if ($user->isAdmin()) { -
  • +
  • +
  • + +
  • diff --git a/classes/comments.class.php b/classes/comments.class.php new file mode 100644 index 0000000..1aaf9d6 --- /dev/null +++ b/classes/comments.class.php @@ -0,0 +1,89 @@ + + + =========================== */ +?> +conf = new configuration(); + } + + function addComment($fieldsArray) { + if ($this->insertarDeFormulario($this->conf->tablePrefix."data", $fieldsArray)) { + return true; + } else { + return false; + } + } + + function generateCookie($fieldsArray) { + setcookie("cookie_gel_user", $fieldsArray["username"], time() + 30000000); + setcookie("cookie_gel_email", $fieldsArray["email"], time() + 30000000); + setcookie("cookie_gel_web", $fieldsArray["web"], time() + 30000000); + } + + function isSpam($fieldsArray) { + if (preg_match( "/^\d+$/", $fieldsArray["username"])) { return true; } + elseif (trim($fieldsArray["content"]) == "") { return true; } + elseif (preg_match( "/^\d+$/", $fieldsArray["content"])) { return true; } + elseif (strtolower($fieldsArray["content"]) == strtolower($fieldsArray["username"])) { return true; } + elseif (preg_match("#^[^.]+\.\.\.#", $fieldsArray["content"])) { return true; } + elseif (3 <= preg_match_all("/a href=/", strtolower($fieldsArray["content"]), $matches)) { return true; } + elseif ($this->isBadWord($fieldsArray["content"])) { return true; } + else { return false; } + } + + function isBadWord($str="") { + $bads = array ("puto", "viagra", "ringtones", "casino", "buy", "cheap", "order", "poker", "discount", "fuck", "cool", "site", "online", "very", "cholesterol", "milf", "sex", "sexo", "arredamento", "reddit", "sesso", "lesbico", "vzge", "angelcities", "porno", "holdem", "blackjack", "black-jack", "mortgage", "pharmacy", "loan", "refinance", "credit", "alberghi", "scarica", "hotel", "cellulare", "giochi", "gratis", "gif", "animata", "fantasy", "albergo", "blowjob", "delicio", "cosco", "dealerships"); + for($i=0;$i

    "; + $msg .= "Autor : ".$usuario." (IP: ".$ip_usuario.")

    "; + $msg .= "E-mail : ".$email."

    "; + $msg .= "URL    : ".$pagina_web."

    "; + $msg .= "Whois  : http://ws.arin.net/cgi-bin/whois.pl?queryinput=".$ip_usuario."

    "; + $msg .= "Comentario:

    ".$comentario; + $msg .= "

    ".$url_blog."/index.php?id=".$id_post."

    "; + + enviaMail($email_autor_post, "[".$desc_blog."] Nuevo mensaje en: ".$titulo_post."", $msg, EMAIL_ADMIN); + } + + function obtenerComentarios($idArticulo="") { + $this->ejecutarConsulta("select * from ".tabla_prefijo."comentarios WHERE id_post=".$idArticulo." AND spam=0 order by fecha ASC"); + return $this->mid_consulta; + } + + function contarComentarios($idArticulo="") { + $this->ejecutarConsulta("select * from ".tabla_prefijo."comentarios WHERE id_post=".$idArticulo." AND spam=0"); + return $this->contarRegistros(); + } + + function mostrarGravatar($email="") { + $emailg = $email; + $default = URL_CODICE."/images/noGravatar.jpg"; + $size = 30; + $grav_url = "http://www.gravatar.com/avatar.php?gravatar_id=".md5($emailg)."&default=".urlencode($default)."&size=".$size; + return "\"Gravatar\""; + } + +} +?> \ No newline at end of file diff --git a/classes/configuration.class.php b/classes/configuration.class.php index 32b48ec..b73e807 100644 --- a/classes/configuration.class.php +++ b/classes/configuration.class.php @@ -45,9 +45,10 @@ class configuration extends Conexion_Mysql { initLang($this->lang); $this->urlFriendly = $this->get_option("url_friendly"); - $this->richText = $this->get_option("rich_text"); - $this->offset_city = $this->get_option("offset_city"); - $this->offset_time = $this->get_option("offset_time"); + $this->richText = $this->get_option("rich_text"); + $this->offsetCity = $this->get_option("offset_city"); + $this->offsetTime = $this->get_option("offset_time"); + $this->allowComments = $this->get_option("allow_comments"); } else { if($isFeed) { header("HTTP/1.0 503 Service Unavailable"); diff --git a/classes/gelato.class.php b/classes/gelato.class.php index 2ea15a4..2b152cb 100644 --- a/classes/gelato.class.php +++ b/classes/gelato.class.php @@ -19,7 +19,7 @@ class gelato extends Conexion_Mysql { function gelato() { parent::Conexion_Mysql(DB_name, DB_Server, DB_User, DB_Password); - $this->conf = new configuration(); + $this->conf = new configuration(); } function saveSettings($fieldsArray) { diff --git a/classes/textile.class.php b/classes/textile.class.php index f6c5607..4c6d30d 100644 --- a/classes/textile.class.php +++ b/classes/textile.class.php @@ -1,4081 +1,1135 @@ -arrays of replacement blocks - * of text that are temporary removed from the input text to avoid - * processing. Different functions use this replacement - * functionality, and each shifts its own replacement array into - * position 0 and removes it when finished. This avoids having - * several replacement variables and/or functions clobbering - * eachothers' replacement blocks. - * - * @private - */ - var $repl = array(); - - /** - * The @c array containing temporary strings used in - * replacement callbacks. *JHR* - * - * @private - */ - var $tmp = array(); - - /** - * Instantiates a new Textile object. Optional options - * can be passed to initialize the object. Attributes for the - * options key are the same as the get/set method names - * documented here. - * - * @param $options The @c array specifying the options to use for - * this object. - * - * @public - */ - function Textile($options = array()) { - $this->options = $options; - $this->options['filters'] = ($this->options['filters'] ? $this->options['filters'] : array()); - $this->options['charset'] = ($this->options['charset'] ? $this->options['charset'] : 'utf-8'); - $this->options['char_encoding'] = (isset($this->options['char_encoding']) ? $this->options['char_encoding'] : 1); - $this->options['do_quotes'] = (isset($this->options['do_quotes']) ? $this->options['do_quotes'] : 1); - $this->options['trim_spaces'] = (isset($this->options['trim_spaces']) ? $this->options['trim_spaces'] : 0); - $this->options['smarty_mode'] = (isset($this->options['smarty_mode']) ? $this->options['smarty_mode'] : 1); - $this->options['preserve_spaces'] = (isset($this->options['preserve_spaces']) ? $this->options['preserve_spaaces'] : 0); - $this->options['head_offset'] = (isset($this->options['head_offset']) ? $this->options['head_offset'] : 0); - - if (is_array($this->options['css'])) { - $this->css($this->options['css']); - } - $this->options['macros'] = ($this->options['macros'] ? $this->options['macros'] : $this->default_macros()); - if (isset($this->options['flavor'])) { - $this->flavor($this->options['flavor']); - } else { - $this->flavor('xhtml1/css'); - } - $this->_create_re(); - } // function Textile - - // getter/setter methods... - - /** - * Used to set Textile attributes. Attribute names are the same - * as the get/set method names documented here. - * - * @param $opt A @c string specifying the name of the option to - * change or an @c array specifying options and values. - * @param $value The value for the provided option name. - * - * @public - */ - function set($opt, $value = NULL) { - if (is_array($opt)) { - foreach ($opt as $opt => $value) { - $this->set($opt, $value); - } - } else { - // the following options have special set methods - // that activate upon setting: - if ($opt == 'charset') { - $this->charset($value); - } elseif ($opt == 'css') { - $this->css($value); - } elseif ($opt == 'flavor') { - $this->flavor($value); - } else { - $this->options[$opt] = $value; - } - } - } // function set - - /** - * Used to get Textile attributes. Attribute names are the same - * as the get/set method names documented here. - * - * @param $opt A @c string specifying the name of the option to get. - * - * @return The value for the provided option. - * - * @public - */ - function get($opt) { - return $this->options[$opt]; - } // function get - - /** - * Gets or sets the "disable html" control, which allows you to - * prevent HTML tags from being used within the text processed. - * Any HTML tags encountered will be removed if disable html is - * enabled. Default behavior is to allow HTML. - * - * @param $disable_html If provided, a @c bool indicating whether or - * not this object should disable HTML. - * - * @return A true value if this object disables HTML; a false value - * otherwise. - * - * @public - */ - function disable_html($disable_html = NULL) { - if ($disable_html != NULL) { - $this->options['disable_html'] = $disable_html; - } - return ($this->options['disable_html'] ? $this->options['disable_html'] : 0); - } // function disable_html - - /** - * Gets or sets the relative heading offset, which allows you to - * change the heading level used within the text processed. For - * example, if the heading offset is '2' and the text contains an - * 'h1' block, an \ block will be output. - * - * @param $head_offset If provided, an @c integer specifying the - * heading offset for this object. - * - * @return An @c integer containing the heading offset for this - * object. - * - * @public - */ - function head_offset($head_offset = NULL) { - if ($head_offset != NULL) { - $this->options['head_offset'] = $head_offset; - } - return ($this->options['head_offset'] ? $this->options['head_offset'] : 0); - } // function head_offset - - /** - * Assigns the HTML flavor of output from Textile. Currently - * these are the valid choices: html, xhtml (behaves like "xhtml1"), - * xhtml1, xhtml2. Default flavor is "xhtml1". - * - * Note that the xhtml2 flavor support is experimental and incomplete - * (and will remain that way until the XHTML 2.0 draft becomes a - * proper recommendation). - * - * @param $flavor If provided, a @c string specifying the flavor to - * be used for this object. - * - * @return A @c string containing the flavor for this object. - * - * @public - */ - function flavor($flavor = NULL) { - if ($flavor != NULL) { - $this->options['flavor'] = $flavor; - if (preg_match('/^xhtml(\d)?(\D|$)/', $flavor, $matches)) { - if ($matches[1] == '2') { - $this->options['_line_open'] = ''; - $this->options['_line_close'] = ''; - $this->options['_blockcode_open'] = ''; - $this->options['_blockcode_close'] = ''; - $this->options['css_mode'] = 1; - } else { - // xhtml 1.x - $this->options['_line_open'] = ''; - $this->options['_line_close'] = '
    '; - $this->options['_blockcode_open'] = '
    ';
    -          $this->options['_blockcode_close'] = '
    '; - $this->options['css_mode'] = 1; - } - } elseif (preg_match('/^html/', $flavor)) { - $this->options['_line_open'] = ''; - $this->options['_line_close'] = '
    '; - $this->options['_blockcode_open'] = '
    ';
    -        $this->options['_blockcode_close'] = '
    '; - $this->options['css_mode'] = preg_match('/\/css/', $flavor); - } - if ($this->options['css_mode'] && !isset($this->options['css'])) { $this->_css_defaults(); } - } - return $this->options['flavor']; - } // function flavor - - /** - * Gets or sets the css support for Textile. If css is enabled, - * Textile will emit CSS rules. You may pass a 1 or 0 to enable - * or disable CSS behavior altogether. If you pass an associative array, - * you may assign the CSS class names that are used by - * Textile. The following key names for such an array are - * recognized: - * - *
      - *
    • class_align_right - * - * defaults to 'right'
    • - * - *
    • class_align_left - * - * defaults to 'left'
    • - * - *
    • class_align_center - * - * defaults to 'center'
    • - * - *
    • class_align_top - * - * defaults to 'top'
    • - * - *
    • class_align_bottom - * - * defaults to 'bottom'
    • - * - *
    • class_align_middle - * - * defaults to 'middle'
    • - * - *
    • class_align_justify - * - * defaults to 'justify'
    • - * - *
    • class_caps - * - * defaults to 'caps'
    • - * - *
    • class_footnote - * - * defaults to 'footnote'
    • - * - *
    • id_footnote_prefix - * - * defaults to 'fn'
    • - * - *
    - * - * @param $css If provided, either a @c bool indicating whether or - * not this object should use css or an associative @c array - * specifying class names to use. - * - * @return Either an associative @c array containing class names - * used by this object, or a true or false value indicating - * whether or not this object uses css. - * - * @public - */ - function css($css = NULL) { - if ($css != NULL) { - if (is_array($css)) { - $this->options['css'] = $css; - $this->options['css_mode'] = 1; - } else { - $this->options['css_mode'] = $css; - if ($this->options['css_mode'] && !isset($this->options['css'])) { $this->_css_defaults(); } - } - } - return ($this->options['css_mode'] ? $this->options['css'] : 0); - } // function css - - /** - * Gets or sets the character set targetted for publication. - * At this time, Textile only changes its behavior - * if the 'utf-8' character set is assigned. - * - * Specifically, if utf-8 is requested, any special characters - * created by Textile will be output as native utf-8 characters - * rather than HTML entities. - * - * @param $charset If provided, a @c string specifying the - * characater set to be used for this object. - * - * @return A @c string containing the character set for this object. - * - * @public - */ - function charset($charset = NULL) { - if ($charset != NULL) { - $this->options['charset'] = $charset; - if (preg_match('/^utf-?8$/i', $this->options['charset'])) { - $this->char_encoding(0); - } else { - $this->char_encoding(1); - } - } - return $this->options['charset']; - } // function charset - - /** - * Gets or sets the physical file path to root of document files. - * This path is utilized when images are referenced and size - * calculations are needed (the getimagesize() function is used to read - * the image dimensions). - * - * @param $docroot If provided, a @c string specifying the document - * root to use for this object. - * - * @return A @c string containing the docroot for this object. - * - * @public - */ - function docroot($docroot = NULL) { - if ($docroot != NULL) { - $this->options['docroot'] = $docroot; - } - return $this->options['docroot']; - } // function docroot - - /** - * Gets or sets the 'trim spaces' control flag. If enabled, this - * will clear any lines that have only spaces on them (the newline - * itself will remain). - * - * @param $trim_spaces If provided, a @c bool indicating whether or - * not this object should trim spaces. - * - * @return A true value if this object trims spaces; a false value - * otherwise. - * - * @public - */ - function trim_spaces($trim_spaces = NULL) { - if ($trim_spaces != NULL) { - $this->options['trim_spaces'] = $trim_spaces; - } - return $this->options['trim_spaces']; - } // function trim_spaces - - /** - * Gets or sets a parameter that is passed to filters. - * - * @param $filter_param If provided, a parameter that this object - * should pass to filters. - * - * @return The parameter this object passes to filters. - * - * @public - */ - function filter_param($filter_param = NULL) { - if ($filter_param != NULL) { - $this->options['filter_param'] = $filter_param; - } - return $this->options['filter_param']; - } // function filter_param - - /** - * Gets or sets the 'preserve spaces' control flag. If enabled, this - * will replace any double spaces within the paragraph data with the - * \&#8195; HTML entity (wide space). The default is 0. Spaces will - * pass through to the browser unchanged and render as a single space. - * Note that this setting has no effect on spaces within \, - * \ blocks or \ sections. - * - * @param $preserve_spaces If provided, a @c bool indicating whether - * or not this object should preserve spaces. - * - * @return A true value if this object preserves spaces; a false - * value otherwise. - * - * @public - */ - function preserve_spaces($preserve_spaces = NULL) { - if ($preserve_spaces != NULL) { - $this->options['preserve_spaces'] = $preserve_spaces; - } - return $this->options['preserve_spaces']; - } // function preserve_spaces - - /** - * Gets or sets a list of filters to make available for - * Textile to use. Returns a hash reference of the currently - * assigned filters. - * - * @param $filters If provided, an @c array of filters to be used - * for this object. - * - * @return An @c array containing the filters for this object. - * - * @public - */ - function filters($filters = NULL) { - if ($filters != NULL) { - $this->options['filters'] = $filters; - } - return $this->options['filters']; - } // function filters - - /** - * Gets or sets the character encoding logical flag. If character - * encoding is enabled, the htmlentities function is used to - * encode special characters. If character encoding is disabled, - * only \<, \>, " and & are encoded to HTML entities. - * - * @param $char_encoding If provided, a @c bool indicating whether - * or not this object should encode special characters. - * - * @return A true value if this object encodes special characters; a - * false value otherwise. - * - * @public - */ - function char_encoding($char_encoding = NULL) { - if ($char_encoding !== NULL) { - $this->options['char_encoding'] = $char_encoding; - } - return $this->options['char_encoding']; - } // function char_encoding - - /** - * Gets or sets the "smart quoting" control flag. Returns the - * current setting. - * - * @param $do_quotes If provided, a @c bool indicating whether or - * not this object should use smart quoting. - * - * @return A true value if this object uses smart quoting; a false - * value otherwise. - * - * @public - */ - function handle_quotes($do_quotes = NULL) { - if ($do_quotes != NULL) { - $this->options['do_quotes'] = $do_quotes; - } - return $this->options['do_quotes']; - } // function handle_quotes - - // end of getter/setter methods - - /** - * Creates the class variable regular expression patterns used by - * Textile. They are not initialized in the declaration, because - * some rely on the others, requiring a @c $this reference. - * - * PHP does not have the Perl qr operator to quote or precompile - * patterns, so to avoid escaping and matching problems, all - * patterns must use the same delimiter; this implementation uses - * {}. Every use of these patterns within this class has been - * changed to use these delimiters. *JHR* - * - * @private - */ - function _create_re() { - // a URL discovery regex. This is from Mastering Regex from O'Reilly. - // Some modifications by Brad Choate - $this->urlre = '(?: - # Must start out right... - (?=[a-zA-Z0-9./#]) - # Match the leading part (proto://hostname, or just hostname) - (?: - # ftp://, http://, or https:// leading part - (?:ftp|https?|telnet|nntp)://(?:\w+(?::\w+)?@)?[-\w]+(?:\.\w[-\w]*)+ - | - (?:mailto:)?[-\+\w]+@[-\w]+(?:\.\w[-\w]*)+ - | - # or, try to find a hostname with our more specific sub-expression - (?i: [a-z0-9] (?:[-a-z0-9]*[a-z0-9])? \. )+ # sub domains - # Now ending .com, etc. For these, require lowercase - (?-i: com\b - | edu\b - | biz\b - | gov\b - | in(?:t|fo)\b # .int or .info - | mil\b - | net\b - | org\b - | museum\b - | aero\b - | coop\b - | name\b - | pro\b - | [a-z][a-z]\b # two-letter country codes - ) - )? - - # Allow an optional port number - (?: : \d+ )? - - # The rest of the URL is optional, and begins with / . . . - (?: - /? - # The rest are heuristics for what seems to work well - [^.!,?;:"\'<>()\[\]{}\s\x7F-\xFF]* - (?: - [.!,?;:]+ [^.!,?;:"\'<>()\[\]{}\s\x7F-\xFF]+ #\'" - )* - )? -)'; - - $this->punct = '[\!"\#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\\\]\^_`{\|}\~]'; - $this->valignre = '[\-^~]'; - $this->tblalignre = '[<>=]'; - $this->halignre = '(?:<>|[<>=])'; - $this->alignre = '(?:(?:' . $this->valignre . '|<>' . $this->valignre . '?|' . $this->valignre . '?<>|' . $this->valignre . '?' . $this->halignre . '?|' . $this->halignre . '?' . $this->valignre . '?)(?!\w))'; - $this->imgalignre = '(?:(?:[<>]|' . $this->valignre . '){1,2})'; - - $this->clstypadre = '(?: - (?:\([A-Za-z0-9_\- \#]+\)) - | - (?:{ - (?: \( [^)]+ \) | [^\}] )+ - }) - | - (?:\(+? (?![A-Za-z0-9_\-\#]) ) - | - (?:\)+?) - | - (?: \[ [a-zA-Z\-]+? \] ) -)'; - - $this->clstyre = '(?: - (?:\([A-Za-z0-9_\- \#]+\)) - | - (?:{ - [A-Za-z0-9_\-](?: \( [^)]+ \) | [^\}] )+ - }) - | - (?: \[ [a-zA-Z\-]+? \] ) -)'; - - $this->clstyfiltre = '(?: - (?:\([A-Za-z0-9_\- \#]+\)) - | - (?:{ - [A-Za-z0-9_\-](?: \( [^)]+ \) | [^\}] )+ - }) - | - (?:\|[^\|]+\|) - | - (?:\(+?(?![A-Za-z0-9_\-\#])) - | - (?:\)+) - | - (?: \[ [a-zA-Z]+? \] ) -)'; - - $this->codere = '(?: - (?: - [\[{] - @ # opening - (?:\[([A-Za-z0-9]+)\])? # $1: language id - (.+?) # $2: code - @ # closing - [\]}] - ) - | - (?: - (?:^|(?<=[\s\(])) - @ # opening - (?:\[([A-Za-z0-9]+)\])? # $3: language id - ([^\s].+?[^\s]) # $4: code itself - @ # closing - (?:$|(?=' . $this->punct . '{1,2}|\s)) - ) -)'; - - $this->blocktags = ' - < - (( /? ( h[1-6] - | p - | pre - | div - | table - | t[rdh] - | [ou]l - | li - | block(?:quote|code) - | form - | input - | select - | option - | textarea - ) - [ >] - ) - | !-- - ) -'; - } // function _create_re - - /** - * Transforms the provided text using Textile markup rules. - * - * @param $str The @c string specifying the text to process. - * - * @return A @c string containing the processed (X)HTML. - * - * @public - */ - function process($str) { - /* - * Function names in PHP are case insensitive, so function - * textile() cannot be redefined. Thus, this PHP implementation - * will only use process(). - * - * return $this->textile($str); - * } // function process - * - * function textile($str) { - */ - - $this->charset('utf8'); - // quick translator for abbreviated block names - // to their tag - $macros = array('bq' => 'blockquote'); - - // an array to hold any portions of the text to be preserved - // without further processing by Textile - array_unshift($this->repl, array()); - - // strip out extra newline characters. we're only matching for \n herein - //$str = preg_replace('!(?:\r?\n|\r)!', "\n", $str); - $str = preg_replace('!(?:\015?\012|\015)!', "\n", $str); - - // optionally remove trailing spaces - if ($this->options['trim_spaces']) { $str = preg_replace('/ +$/m', '', $str); } - - // preserve contents of the '==', 'pre', 'blockcode' sections - $str = preg_replace_callback('{(^|\n\n)==(.+?)==($|\n\n)}s', - $this->_cb('"$m[1]\n\n" . $me->_repl($me->repl[0], $me->format_block(array("text" => $m[2]))) . "\n\n$m[3]"'), $str); - - if (!$this->disable_html()) { - // preserve style, script tag contents - $str = preg_replace_callback('!(<(style|script)(?:>| .+?>).*?)!s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str); - - // preserve HTML comments - $str = preg_replace_callback('|()|s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str); - - // preserve pre block contents, encode contents by default - $pre_start = count($this->repl[0]); - $str = preg_replace_callback('{(]*)?>)(.+?)()}s', - $this->_cb('"\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n"'), $str); - // fix code tags within pre blocks we just saved. - for ($i = $pre_start; $i < count($this->repl[0]); $i++) { - $this->repl[0][$i] = preg_replace('|<(/?)code(.*?)>|s', '<$1code$2>', $this->repl[0][$i]); - } - - // preserve code blocks by default, encode contents - $str = preg_replace_callback('{(]+)?>)(.+?)()}s', - $this->_cb('$me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3])'), $str); - - // encode blockcode tag (an XHTML 2 tag) and encode it's - // content by default - $str = preg_replace_callback('{(]+)?>)(.+?)()}s', - $this->_cb('"\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n"'), $str); - - // preserve PHPish, ASPish code - $str = preg_replace_callback('!(<([\?%]).*?(\2)>)!s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str); - } - - // pass through and remove links that follow this format - // [id_without_spaces (optional title text)]url - // lines like this are stripped from the content, and can be - // referred to using the "link text":id_without_spaces syntax - //$links = array(); - $str = preg_replace_callback('{(?:\n|^) [ ]* \[ ([^ ]+?) [ ]*? (?:\( (.+?) \) )? \] ((?:(?:ftp|https?|telnet|nntp)://|/)[^ ]+?) [ ]* (\n|$)}mx', - $this->_cb('($me->links[$m[1]] = array("url" => $m[3], "title" => $m[2])) ? $m[4] : $m[4]'), $str); - //$this->links = $links; - - // eliminate starting/ending blank lines - $str = preg_replace('/^\n+/s', '', $str, 1); - $str = preg_replace('/\n+$/s', '', $str, 1); - - // split up text into paragraph blocks, capturing newlines too - $para = preg_split('/(\n{2,})/', $str, -1, PREG_SPLIT_DELIM_CAPTURE); - unset($block, $bqlang, $filter, $class, $sticky, $lines, - $style, $stickybuff, $lang, $clear); - - $out = ''; - - foreach ($para as $para) { - if (preg_match('/^\n+$/s', $para)) { - if ($sticky && $stickybuff) { - $stickybuff .= $para; - } else { - $out .= $para; - } - continue; - } - - if ($sticky) { - $sticky++; - } else { - unset($block); - unset($class); - $style = ''; - unset($lang); - } - - unset($id, $cite, $align, $padleft, $padright, $lines, $buffer); - if (preg_match('{^(h[1-6]|p|bq|bc|fn\d+) - ((?:' . $this->clstyfiltre . '*|' . $this->halignre . ')*) - (\.\.?) - (?::(\d+|' . $this->urlre . '))?\ (.*)$}sx', $para, $matches)) { - if ($sticky) { - if ($block == 'bc') { - // close our blockcode section - $out = preg_replace('/\n\n$/', '', $out, 1); - $out .= $this->options['_blockcode_close'] . "\n\n"; - } elseif ($block == 'bq') { - $out = preg_replace('/\n\n$/', '', $out, 1); - $out .= '' . "\n\n"; - } elseif ($block == 'table') { - $table_out = $this->format_table(array('text' => $stickybuff)); - if (!$table_out) { $table_out = ''; } - $out .= $table_out; - unset($stickybuff); - } elseif ($block == 'dl') { - $dl_out = $this->format_deflist(array('text' => $stickybuff)); - if (!$dl_out) { $dl_out = ''; } - $out .= $dl_out; - unset($stickybuff); - } - $sticky = 0; - } - // block macros: h[1-6](class)., bq(class)., bc(class)., p(class). - //warn "paragraph: [[$para]]\n\tblock: $1\n\tparams: $2\n\tcite: $4"; - $block = $matches[1]; - $params = $matches[2]; - $cite = $matches[4]; - if ($matches[3] == '..') { - $sticky = 1; - } else { - $sticky = 0; - unset($class); - unset($bqlang); - unset($lang); - $style = ''; - unset($filter); - } - if (preg_match('/^h([1-6])$/', $block, $matches2)) { - if ($this->options['head_offset']) { - $block = 'h' . ($matches2[1] + $this->options['head_offset']); - } - } - if (preg_match('{(' . $this->halignre . '+)}', $params, $matches2)) { - $align = $matches2[1]; - $params = preg_replace('{' . $this->halignre . '+}', '', $params, 1); - } - if ($params) { - if (preg_match('/\|(.+)\|/', $params, $matches2)) { - $filter = $matches2[1]; - $params = preg_replace('/\|.+?\|/', '', $params, 1); - } - if (preg_match('/{([^}]+)}/', $params, $matches2)) { - $style = $matches2[1]; - $style = preg_replace('/\n/', ' ', $style); - $params = preg_replace('/{[^}]+}/', '', $params); - } - if (preg_match('/\(([A-Za-z0-9_\-\ ]+?)(?:\#(.+?))?\)/', $params, $matches2) || - preg_match('/\(([A-Za-z0-9_\-\ ]+?)?(?:\#(.+?))\)/', $params, $matches2)) { - if ($matches2[1] || $matches2[2]) { - $class = $matches2[1]; - $id = $matches2[2]; - if ($class) { - $params = preg_replace('/\([A-Za-z0-9_\-\ ]+?(#.*?)?\)/', '', $params); - } elseif ($id) { - $params = preg_replace('/\(#.+?\)/', '', $params); - } - } - } - if (preg_match('/(\(+)/', $params, $matches2)) { - $padleft = strlen($matches2[1]); - $params = preg_replace('/\(+/', '', $params, 1); - } - if (preg_match('/(\)+)/', $params, $matches2)) { - $padright = strlen($matches2[1]); - $params = preg_replace('/\)+/', '', $params, 1); - } - if (preg_match('/\[(.+?)\]/', $params, $matches2)) { - $lang = $matches2[1]; - if ($block == 'bc') { - $bqlang = $lang; - unset($lang); - } - $params = preg_replace('/\[.+?\]/', '', $params, 1); - } - } - // warn "settings:\n\tblock: $block\n\tpadleft: $padleft\n\tpadright: $padright\n\tclass: $class\n\tstyle: $style\n\tid: $id\n\tfilter: $filter\n\talign: $align\n\tlang: $lang\n\tsticky: $sticky"; - $para = $matches[5]; - } elseif (preg_match('|^$|', $para, $matches)) { - $buffer = $this->repl[0][$matches[1] - 1]; - } elseif (preg_match('/^clear([<>]+)?\.$/', $para, $matches)) { - if ($matches[1] == '<') { - $clear = 'left'; - } elseif ($matches[1] == '>') { - $clear = 'right'; - } else { - $clear = 'both'; - } - continue; - } elseif ($sticky && $stickybuff && - ($block == 'table' || $block == 'dl')) { - $stickybuff .= $para; - continue; - } elseif (preg_match('{^(?:' . $this->halignre . '|' . $this->clstypadre . '*)* - [\*\#] - (?:' . $this->halignre . '|' . $this->clstypadre . '*)* - \ }x', $para)) { - // '*', '#' prefix means a list - $buffer = $this->format_list(array('text' => $para)); - } elseif (preg_match('{^(?:table(?:' . $this->tblalignre . '|' . $this->clstypadre . '*)* - (\.\.?)\s+)? - (?:_|' . $this->alignre . '|' . $this->clstypadre . '*)*\|}x', $para, $matches)) { - // handle wiki-style tables - if ($matches[1] && ($matches[1] == '..')) { - $block = 'table'; - $stickybuff = $para; - $sticky = 1; - continue; - } else { - $buffer = $this->format_table(array('text' => $para)); - } - } elseif (preg_match('{^(?:dl(?:' . $this->clstyre . ')*(\.\.?)\s+)}x', $para, $matches)) { - // handle definition lists - if ($matches[1] && ($matches[1] == '..')) { - $block = 'dl'; - $stickybuff = $para; - $sticky = 1; - continue; - } else { - $buffer = $this->format_deflist(array('text' => $para)); - } - } - if ($buffer) { - $out .= $buffer; - continue; - } - $lines = preg_split('/\n/', $para); - if ((count($lines) == 1) && ($lines[0] == '')) { - continue; - } - - $block = ($block ? $block : 'p'); - - $buffer = ''; - $pre = ''; - $post = ''; - - if ($block == 'bc') { - if ($sticky <= 1) { - $pre .= $this->options['_blockcode_open']; - $pre = preg_replace('/>$/s', '', $pre, 1); - if ($bqlang) { $pre .= " language=\"$bqlang\""; } - if ($align) { - $alignment = $this->_halign($align); - if ($this->options['css_mode']) { - if (($padleft || $padright) && - (($alignment == 'left') || ($alignment == 'right'))) { - $style .= ';float:' . $alignment; - } else { - $style .= ';text-align:' . $alignment; - } - $class .= ' ' . ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment); - } else { - if ($alignment) { $pre .= " align=\"$alignment\""; } - } - } - if ($padleft) { $style .= ";padding-left:${padleft}em"; } - if ($padright) { $style .= ";padding-right:${padright}em"; } - if ($clear) { $style .= ";clear:${clear}"; } - if ($class) { $class = preg_replace('/^ /', '', $class, 1); } - if ($class) { $pre .= " class=\"$class\""; } - if ($id) { $pre .= " id=\"$id\""; } - if ($style) { $style = preg_replace('/^;/', '', $style, 1); } - if ($style) { $pre .= " style=\"$style\""; } - if ($lang) { $pre .= " lang=\"$lang\""; } - $pre .= '>'; - unset($lang); - unset($bqlang); - unset($clear); - } - $para = preg_replace_callback('{(?:^|(?<=[\s>])|([{[])) - ==(.+?)== - (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s))}sx', - $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])))'), $para); - $buffer .= $this->encode_html_basic($para, 1); - $buffer = preg_replace('/<textile#(\d+)>/', '', $buffer); - if ($sticky == 0) { - $post .= $this->options['_blockcode_close']; - } - $out .= $pre . $buffer . $post; - continue; - } elseif ($block == 'bq') { - if ($sticky <= 1) { - $pre .= '_halign($align); - if ($this->options['css_mode']) { - if (($padleft || $padright) && - (($alignment == 'left') || ($alignment == 'right'))) { - $style .= ';float:' . $alignment; - } else { - $style .= ';text-align:' . $alignment; - } - $class .= ' ' . ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment); - } else { - if ($alignment) { $pre .= " align=\"$alignment\""; } - } - } - if ($padleft) { $style .= ";padding-left:${padleft}em"; } - if ($padright) { $style .= ";padding-right:${padright}em"; } - if ($clear) { $style .= ";clear:${clear}"; } - if ($class) { $class = preg_replace('/^ /', '', $class, 1); } - if ($class) { $pre .= " class=\"$class\""; } - if ($id) { $pre .= " id=\"$id\""; } - if ($style) { $style = preg_replace('/^;/', '', $style, 1); } - if ($style) { $pre .= " style=\"$style\""; } - if ($lang) { $pre .= " lang=\"$lang\""; } - if ($cite) { $pre .= ' cite="' . $this->format_url(array('url' => $cite)) . '"'; } - $pre .= '>'; - unset($clear); - } - $pre .= '

    '; - } elseif (preg_match('/fn(\d+)/', $block, $matches)) { - $fnum = $matches[1]; - $pre .= 'options['css']['class_footnote']) { $class .= ' ' . $this->options['css']['class_footnote']; } - if ($align) { - $alignment = $this->_halign($align); - if ($this->options['css_mode']) { - if (($padleft || $padright) && - (($alignment == 'left') || ($alignment == 'right'))) { - $style .= ';float:' . $alignment; - } else { - $style .= ';text-align:' . $alignment; - } - $class .= ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment); - } else { - $pre .= " align=\"$alignment\""; - } - } - if ($padleft) { $style .= ";padding-left:${padleft}em"; } - if ($padright) { $style .= ";padding-right:${padright}em"; } - if ($clear) { $style .= ";clear:${clear}"; } - if ($class) { $class = preg_replace('/^ /', '', $class, 1); } - if ($class) { $pre .= " class=\"$class\""; } - $pre .= ' id="' . ($this->options['css']['id_footnote_prefix'] ? $this->options['css']['id_footnote_prefix'] : 'fn') . $fnum . '"'; - if ($style) { $style = preg_replace('/^;/', '', $style, 1); } - if ($style) { $pre .= " style=\"$style\""; } - if ($lang) { $pre .= " lang=\"$lang\""; } - $pre .= '>'; - $pre .= '' . $fnum . ' '; - // we can close like a regular paragraph tag now - $block = 'p'; - unset($clear); - } else { - $pre .= '<' . ($macros[$block] ? $macros[$block] : $block); - if ($align) { - $alignment = $this->_halign($align); - if ($this->options['css_mode']) { - if (($padleft || $padright) && - (($alignment == 'left') || ($alignment == 'right'))) { - $style .= ';float:' . $alignment; - } else { - $style .= ';text-align:' . $alignment; - } - $class .= ' ' . ($this->options['css']["class_align_$alignment"] ? $this->options['css']["class_align_$alignment"] : $alignment); - } else { - $pre .= " align=\"$alignment\""; - } - } - if ($padleft) { $style .= ";padding-left:${padleft}em"; } - if ($padright) { $style .= ";padding-right:${padright}em"; } - if ($clear) { $style .= ";clear:${clear}"; } - if ($class) { $class = preg_replace('/^ /', '', $class, 1); } - if ($class) { $pre .= " class=\"$class\""; } - if ($id) { $pre .= " id=\"$id\""; } - if ($style) { $style = preg_replace('/^;/', '', $style, 1); } - if ($style) { $pre .= " style=\"$style\""; } - if ($lang) { $pre .= " lang=\"$lang\""; } - if ($cite && ($block == 'bq')) { $pre .= ' cite="' . $this->format_url(array('url' => $cite)) . '"'; } - $pre .= '>'; - unset($clear); - } - - $buffer = $this->format_paragraph(array('text' => $para)); - - if ($block == 'bq') { - if (!preg_match('/]/', $buffer)) { $post .= '

    '; } - if ($sticky == 0) { - $post .= ''; - } - } else { - $post .= ''; - } - - if (preg_match('{' . $this->blocktags . '}x', $buffer)) { - $buffer = preg_replace('/^\n\n/s', '', $buffer, 1); - $out .= $buffer; - } else { - if ($filter) { $buffer = $this->format_block(array('text' => "|$filter|" . $buffer, 'inline' => 1)); } - $out .= $pre . $buffer . $post; - } - } - - if ($sticky) { - if ($block == 'bc') { - // close our blockcode section - $out .= $this->options['_blockcode_close']; // . "\n\n"; - } elseif ($block == 'bq') { - $out .= ''; // . "\n\n"; - } elseif (($block == 'table') && $stickybuff) { - $table_out = $this->format_table(array('text' => $stickybuff)); - if ($table_out) { $out .= $table_out; } - } elseif (($block == 'dl') && $stickybuff) { - $dl_out = $this->format_deflist(array('text' => $stickybuff)); - if ($dl_out) { $out .= $dl_out; } - } - } - - // cleanup-- restore preserved blocks - for ($i = count($this->repl[0]); $i > 0; $i--) { - $out = preg_replace('!(?:<|<)textile#' . $i . '(?:>|>)!', str_replace('$', '\\$', $this->repl[0][$i - 1]), $out, 1); - } - array_shift($this->repl); - - // scan for br, hr tags that are not closed and close them - // only for xhtml! just the common ones -- don't fret over input - // and the like. - if (preg_match('/^xhtml/i', $this->flavor())) { - $out = preg_replace('/(<(?:img|br|hr)[^>]*?(?/', '$1 />', $out); - } - - return $out; - } // function process - - /** - * Processes a single paragraph. The following attributes are - * allowed: - * - *
      - * - *
    • text - * - * The text to be processed.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the paragraph. - * - * @return A @c string containing the formatted paragraph. - * - * @private - */ - function format_paragraph($args) { - $buffer = (isset($args['text']) ? $args['text'] : ''); - - array_unshift($this->repl, array()); - $buffer = preg_replace_callback('{(?:^|(?<=[\s>])|([{[])) - ==(.+?)== - (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s))}sx', - $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])))'), $buffer); - - unset($tokens); - if (preg_match('/disable_html())) { // optimization -- no point in tokenizing if we - // have no tags to tokenize - $tokens = $this->_tokenize($buffer); - } else { - $tokens = array(array('text', $buffer)); - } - $result = ''; - foreach ($tokens as $token) { - $text = $token[1]; - if ($token[0] == 'tag') { - $text = preg_replace('/&(?!amp;)/', '&', $text); - $result .= $text; - } else { - $text = $this->format_inline(array('text' => $text)); - $result .= $text; - } - } - - // now, add line breaks for lines that contain plaintext - $lines = preg_split('/\n/', $result); - $result = ''; - $needs_closing = 0; - foreach ($lines as $line) { - if (!preg_match('{(' . $this->blocktags . ')}x', $line) - && ((preg_match('/^[^<]/', $line) || preg_match('/>[^<]/', $line)) - || !preg_match('/options['_line_open']) { - if ($result != '') { $result .= "\n"; } - $result .= $this->options['_line_open'] . $line . $this->options['_line_close']; - } else { - if ($needs_closing) { - $result .= $this->options['_line_close'] . "\n"; - } else { - $needs_closing = 1; - if ($result != '') { $result .= "\n"; } - } - $result .= $line; - } - } else { - if ($needs_closing) { - $result .= $this->options['_line_close'] . "\n"; - } else { - if ($result != '') { $result .= "\n"; } - } - $result .= $line; - $needs_closing = 0; - } - } - - // at this point, we will restore the \001's to \n's (reversing - // the step taken in _tokenize). - //$result = preg_replace('/\r/', "\n", $result); - $result = preg_replace('/\001/', "\n", $result); - - for ($i = count($this->repl[0]); $i > 0; $i--) { - $result = preg_replace("||", str_replace('$', '\\$', $this->repl[0][$i - 1]), $result, 1); - } - array_shift($this->repl); - - // quotalize - if ($this->options['do_quotes']) { - $result = $this->process_quotes($result); - } - - return $result; - } // function format_paragraph - - /** - * Processes an inline string (plaintext) for Textile syntax. - * The following attributes are allowed: - * - *
      - * - *
    • text - * - * The text to be processed.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the inline string. - * - * @return A @c string containing the formatted inline string. - * - * @private - */ - function format_inline($args) { - $qtags = array(array('**', 'b', '(?repl, array()); - - $text = preg_replace_callback('{' . $this->codere . '}mx', $this->_cb('$me->_repl($me->repl[0], $me->format_code(array("text" => $m[2] . $m[4], "lang" => $m[1] . $m[3])))'), $text); - - // images must be processed before encoding the text since they might - // have the <, > alignment specifiers... - - // !blah (alt)! -> image - $text = preg_replace_callback('{(?:^|(?<=[\s>])|([{[])) # $1: open brace/bracket - ! # opening - (' . $this->imgalignre . '?) # $2: optional alignment - (' . $this->clstypadre . '*) # $3: optional CSS class/id - (' . $this->imgalignre . '?) # $4: optional alignment - (?:\s*) # space between alignment/css stuff - ([^\s\(!]+) # $5: filename - (\s*[^\(!]*(?:\([^\)]+\))?[^!]*) # $6: extras (alt text) - ! # closing - (?::(\d+|' . $this->urlre . '))? # $7: optional URL - (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $8: closing brace/bracket - }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_image(array("pre" => $m[1], "src" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "extra" => $m[6], "url" => $m[7], "clsty" => $m[3], "post" => $m[8])))'), $text); - - $text = preg_replace_callback('{(?:^|(?<=[\s>])|([{[])) # $1: open brace/bracket - % # opening - (' . $this->halignre . '?) # $2: optional alignment - (' . $this->clstyre . '*) # $3: optional CSS class/id - (' . $this->halignre . '?) # $4: optional alignment - (?:\s*) # spacing - ([^%]+?) # $5: text - % # closing - (?::(\d+|' . $this->urlre . '))? # $6: optional URL - (?:$|([]}])|(?=' . $this->punct . '{1,2}|\s)) # $7: closing brace/bracket - }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_span(array("pre" => $m[1], "text" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "cite" => $m[6], "clsty" => $m[3], "post" => $m[7])))'), $text); - - $text = $this->encode_html($text); - $text = preg_replace('!<textile#(\d+)>!', '', $text); - $text = preg_replace('!&quot;!', '"', $text); - $text = preg_replace('!&(([a-z]+|#\d+);)!', '&$1', $text); - $text = preg_replace('!"!', '"', $text); - - // These create markup with entities. Do first and 'save' result for later: - // "text":url -> hyperlink - // links with brackets surrounding - $parenre = '\( (?: [^()] )* \)'; - $text = preg_replace_callback('{( - [{[] - (?: - (?:" # quote character - (' . $this->clstyre . '*)? # $2: optional CSS class/id - ([^"]+?) # $3: link text - (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $4: optional link title - " # closing quote - ) - | - (?:\' # open single quote - (' . $this->clstyre . '*)? # $5: optional CSS class/id - ([^\']+?) # $6: link text - (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $7: optional link title - \' # closing quote - ) - ) - :(.+?) # $8: URL suffix - [\]}] - ) - }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])))'), $text); - - $text = preg_replace_callback('{((?:^|(?<=[\s>\(])) # $1: open brace/bracket - (?: (?:" # quote character " - (' . $this->clstyre . '*)? # $2: optional CSS class/id - ([^"]+?) # $3: link text " - (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $4: optional link title - " # closing quote # " - ) - | - (?:\' # open single quote \' - (' . $this->clstyre . '*)? # $5: optional CSS class/id - ([^\']+?) # $6: link text \' - (?:\( ( (?:[^()]|' . $parenre . ')*) \))? # $7: optional link title - \' # closing quote \' - ) - ) - :(\d+|' . $this->urlre . ') # $8: URL suffix - (?:$|(?=' . $this->punct . '{1,2}|\s))) # $9: closing brace/bracket - }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])))'), $text); - - if (preg_match('/^xhtml2/', $this->flavor())) { - // citation with cite link - $text = preg_replace_callback('{(?:^|(?<=[\s>\'"\(])|([{[])) # $1: open brace/bracket \' - \?\? # opening \'??\' - ([^\?]+?) # $2: characters (can\'t contain \'?\') - \?\? # closing \'??\' - :(\d+|' . $this->urlre . ') # $3: optional citation URL - (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $4: closing brace/bracket - }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_cite(array("pre" => $m[1], "text" => $m[2], "cite" => $m[3], "post" => $m[4])))'), $text); - } - - // footnotes - if (preg_match('/[^ ]\[\d+\]/', $text)) { - $fntag = 'options['css']['class_footnote']) { $fntag .= ' class="' . $this->options['css']['class_footnote'] . '"'; } - $fntag .= '>$2', $text); - } - - // translate macros: - $text = preg_replace_callback('{(\{)(.+?)(\})}x', - $this->_cb('$me->format_macro(array("pre" => $m[1], "post" => $m[3], "macro" => $m[2]))'), $text); - - // these were present with textile 1 and are common enough - // to not require macro braces... - // (tm) -> ™ - $text = preg_replace('|[\(\[]TM[\)\]]|i', '™', $text); - // (c) -> © - $text = preg_replace('|[\(\[]C[\)\]]|i', '©', $text); - // (r) -> ® - $text = preg_replace('|[\(\[]R[\)\]]|i', '®', $text); - - if ($this->preserve_spaces()) { - // replace two spaces with an em space - $text = preg_replace('/(?tmp['f'][], $this->tmp['r'][], $qf, $cls) = $tag; - if ($last != ($text = preg_replace_callback('{(?:^|(?<=[\s>\'"])|([{[])) # "\' $1 - pre - ' . $qf . ' # - (?:(' . $this->clstyre . '*))? # $2 - attributes - ([^' . $cls . '\s].*?) # $3 - content - (?<=\S)' . $qf . ' # - (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $4 - post - }mx', $this->_cb('$me->format_tag(array("tag" => end($me->tmp["r"]), "marker" => end($me->tmp["f"]), "pre" => $m[1], "text" => $m[3], "clsty" => $m[2], "post" => $m[4]))'), $text))) { - $redo = ($redo || ($last != $text)); - $last = $text; - } - array_pop($this->tmp['f']); array_pop($this->tmp['r']); - } - } - - // superscript is an even simpler replacement... - $text = preg_replace('/(?$1', $text); - - // ABC(Aye Bee Cee) -> acronym - $text = preg_replace_callback('{\b([A-Z][A-Za-z0-9]*?[A-Z0-9]+?)\b(?:[(]([^)]*)[)])}', - $this->_cb('$me->_repl($me->repl[0],"encode_html_basic($m[2]) . "\">$m[1]")'), $text); - - // ABC -> 'capped' span - if ($this->tmp['caps'][] = $this->options['css']['class_caps']) { - $text = preg_replace_callback('/(^|[^"][>\s]) # " - ((?:[A-Z](?:[A-Z0-9\.,\']|\&){2,}\ *)+?) # \' - (?=[^A-Z\.0-9]|$) - /mx', $this->_cb('$m[1] . $me->_repl($me->repl[0], "tmp["caps"]) . "\">$m[2]")'), $text); - } - array_pop($this->tmp['caps']); - - // nxn -> n×n - $text = preg_replace('!((?:[0-9\.]0|[1-9]|\d[\'"])\ ?)x(\ ?\d)!', '$1×$2', $text); - - // translate these entities to the Unicode equivalents: - $text = preg_replace('/…/', '…', $text); - $text = preg_replace('/‘/', '‘', $text); - $text = preg_replace('/’/', '’', $text); - $text = preg_replace('/“/', '“', $text); - $text = preg_replace('/”/', '”', $text); - $text = preg_replace('/–/', '–', $text); - $text = preg_replace('/—/', '—', $text); - - // Restore replacements done earlier: - for ($i = count($this->repl[0]); $i > 0; $i--) { - $text = preg_replace("||", str_replace('$', '\\$', $this->repl[0][$i - 1]), $text); - } - array_shift($this->repl); - - // translate entities to characters for highbit stuff since - // we're using utf8 - // removed for backward compatability with older versions of Perl - //if (preg_match('/^utf-?8$/i', $this->options['charset'])) { - // // translate any unicode entities to native UTF-8 - // $text = preg_replace('/\&\#(\d+);/e', '($1 > 127) ? pack('U', $1) : chr($1)', $text); - //} - - return $text; - } // function format_inline - - /** - * Responsible for processing a particular macro. Arguments passed - * include: - * - *
      - * - *
    • pre - * - * open brace character
    • - * - *
    • post - * - * close brace character
    • - * - *
    • macro - * - * the macro to be executed
    • - * - *
    - * - * The return value from this method would be the replacement - * text for the macro given. If the macro is not defined, it will - * return pre + macro + post, thereby preserving the original - * macro string. - * - * @param $attrs An @c array containing the attributes for - * formatting the macro. - * - * @return A @c string containing the formatted macro. - * - * @private - */ - function format_macro($attrs) { - $macro = $attrs['macro']; - if ($this->options['macros'][$macro]) { - return $this->options['macros'][$macro]; - } - - return $attrs['pre'] . $macro . $attrs['post']; - } // function format_macro - - /** - * Processes text for a citation tag. The following attributes - * are allowed: - * - *
      - * - *
    • pre - * - * Any text that comes before the citation.
    • - * - *
    • text - * - * The text that is being cited.
    • - * - *
    • cite - * - * The URL of the citation.
    • - * - *
    • post - * - * Any text that follows the citation.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the citation. - * - * @return A @c string containing the formatted citation. - * - * @private - */ - function format_cite($args) { - $pre = (isset($args['pre']) ? $args['pre'] : ''); - $text = (isset($args['text']) ? $args['text'] : ''); - $cite = $args['cite']; - $post = (isset($args['post']) ? $args['post'] : ''); - $this->_strip_borders($pre, $post); - $tag = $pre . 'flavor()) && $cite) { - $cite = $this->format_url(array('url' => $cite)); - $tag .= " cite=\"$cite\""; - } else { - $post .= ':'; - } - $tag .= '>'; - return $tag . $this->format_inline(array('text' => $text)) . '' . $post; - } // function format_cite - - /** - * Processes '@...@' type blocks (code snippets). The following - * attributes are allowed: - * - *
      - * - *
    • text - * - * The text of the code itself.
    • - * - *
    • lang - * - * The language (programming language) for the code.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the code. - * - * @return A @c string containing the formatted code. - * - * @private - */ - function format_code($args) { - $code = (isset($args['text']) ? $args['text'] : ''); - $lang = $args['lang']; - $code = $this->encode_html($code, 1); - $code = preg_replace('/<textile#(\d+)>/', '', $code); - $tag = '' . $code . ''; - } // function format_code - - /** - * Returns a string of tag attributes to accomodate the class, - * style and symbols present in @c $clsty. - * - * @c $clsty is checked for: - * - *
      - * - *
    • {...} - * - * style rules. If present, they are appended to $style.
    • - * - *
    • (...#...) - * - * class and/or ID name declaration
    • - * - *
    • ( (one or more) - * - * pad left characters
    • - * - *
    • ) (one or more) - * - * pad right characters
    • - * - *
    • [ll] - * - * language declaration
    • - * - *
    - * - * The attribute string returned will contain any combination - * of class, id, style and/or lang attributes. - * - * @param $clsty A @c string specifying the class/style to process. - * @param $class A @c string specifying the predetermined class. - * @param $style A @c string specifying the predetermined style. - * - * @return A @c string containing the formatted class, ID, style, - * and/or language. - * - * @private - */ - function format_classstyle($clsty = NULL, $class = NULL, $style = NULL) { - $class = preg_replace('/^ /', '', $class, 1); - - unset($lang, $padleft, $padright, $id); - if ($clsty && preg_match('/{([^}]+)}/', $clsty, $matches)) { - $_style = $matches[1]; - $_style = preg_replace('/\n/', ' ', $_style); - $style .= ';' . $_style; - $clsty = preg_replace('/{[^}]+}/', '', $clsty); - } - if ($clsty && (preg_match('/\(([A-Za-z0-9_\- ]+?)(?:#(.+?))?\)/', $clsty, $matches) || - preg_match('/\(([A-Za-z0-9_\- ]+?)?(?:#(.+?))\)/', $clsty, $matches))) { - if ($matches[1] || $matches[2]) { - if ($class) { - $class = $matches[1] . ' ' . $class; - } else { - $class = $matches[1]; - } - $id = $matches[2]; - if ($class) { - $clsty = preg_replace('/\([A-Za-z0-9_\- ]+?(#.*?)?\)/', '', $clsty); - } - if ($id) { - $clsty = preg_replace('/\(#.+?\)/', '', $clsty); - } - } - } - if ($clsty && preg_match('/(\(+)/', $clsty, $matches)) { - $padleft = strlen($matches[1]); - $clsty = preg_replace('/\(+/', '', $clsty, 1); - } - if ($clsty && preg_match('/(\)+)/', $clsty, $matches)) { - $padright = strlen($matches[1]); - $clsty = preg_replace('/\)+/', '', $clsty, 1); - } - if ($clsty && preg_match('/\[(.+?)\]/', $clsty, $matches)) { - $lang = $matches[1]; - $clsty = preg_replace('/\[.+?\]/', '', $clsty); - } - $attrs = ''; - if ($padleft) { $style .= ";padding-left:${padleft}em"; } - if ($padright) { $style .= ";padding-right:${padright}em"; } - $style = preg_replace('/^;/', '', $style, 1); - $class = preg_replace('/^ /', '', $class, 1); - $class = preg_replace('/ $/', '', $class, 1); - if ($class) { $attrs .= " class=\"$class\""; } - if ($id) { $attrs .= " id=\"$id\""; } - if ($style) { $attrs .= " style=\"$style\""; } - if ($lang) { $attrs .= " lang=\"$lang\""; } - $attrs = preg_replace('/^ /', '', $attrs, 1); - return $attrs; - } // function format_classstyle - - /** - * Constructs an HTML tag. Accepted arguments: - * - *
      - * - *
    • tag - * - * the tag to produce
    • - * - *
    • text - * - * the text to output inside the tag
    • - * - *
    • pre - * - * text to produce before the tag
    • - * - *
    • post - * - * text to produce following the tag
    • - * - *
    • clsty - * - * class and/or style attributes that should be assigned to the tag.
    • - * - *
    - * - * @param $args @c array specifying the attributes for formatting - * the tag. - * - * @return A @c string containing the formatted tag. - * - * @private - */ - function format_tag($args) { - $tagname = $args['tag']; - $text = (isset($args['text']) ? $args['text'] : ''); - $pre = (isset($args['pre']) ? $args['pre'] : ''); - $post = (isset($args['post']) ? $args['post'] : ''); - $clsty = (isset($args['clsty']) ? $args['clsty'] : ''); - $this->_strip_borders($pre, $post); - $tag = "<$tagname"; - $attr = $this->format_classstyle($clsty); - if ($attr) { $tag .= " $attr"; } - $tag .= ">$text"; - return $pre . $tag . $post; - } // function format_tag - - /** - * Takes a Textile formatted definition list and - * returns the markup for it. Arguments accepted: - * - *
      - * - *
    • text - * - * The text to be processed.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the definition list. - * - * @return A @c string containing the formatted definition list. - * - * @private - */ - function format_deflist($args) { - $str = (isset($args['text']) ? $args['text'] : ''); - unset($clsty); - $lines = preg_split('/\n/', $str); - if (preg_match('{^(dl(' . $this->clstyre . '*?)\.\.?(?:\ +|$))}x', $lines[0], $matches)) { - $clsty = $matches[2]; - $lines[0] = substr($lines[0], strlen($matches[1])); - } - - unset($dt, $dd); - $out = ''; - foreach ($lines as $line) { - if (preg_match('{^((?:' . $this->clstyre . '*)(?:[^\ ].*?)(?add_term($dt, $dd); } - $dt = $matches[1]; - $dd = $matches[2]; - } else { - $dd .= "\n" . $line; - } - } - if ($dt && $dd) { $out .= $this->add_term($dt, $dd); } - - $tag = 'format_classstyle($clsty); } - if ($attr) { $tag .= " $attr"; } - $tag .= '>' . "\n"; - - return $tag . $out . "\n"; - } // function format_deflist - - /** - * Processes a single definition list item from the provided term - * and definition. - * - * @param $dt A @c string specifying the term to be defined. - * @param $dd A @c string specifying the definition for the term. - * - * @return A @c string containing the formatted definition list - * item. - * - * @private - */ - function add_term($dt, $dd) { - unset($dtattr, $ddattr); - unset($dtlang); - if (preg_match('{^(' . $this->clstyre . '*)}x', $dt, $matches)) { - $param = $matches[1]; - $dtattr = $this->format_classstyle($param); - if (preg_match('/\[([A-Za-z]+?)\]/', $param, $matches)) { - $dtlang = $matches[1]; - } - $dt = substr($dt, strlen($param)); - } - if (preg_match('{^(' . $this->clstyre . '*)}x', $dd, $matches)) { - $param = $matches[1]; - // if the language was specified for the term, - // then apply it to the definition as well (unless - // already specified of course) - if ($dtlang && preg_match('/\[([A-Za-z]+?)\]/', $param)) { - unset($dtlang); - } - $ddattr = $this->format_classstyle(($dtlang ? "[$dtlang]" : '') . $param); - $dd = substr($dd, strlen($param)); - } - $out = 'format_inline(array('text' => $dt)) . '' . "\n"; - if (preg_match('/\n\n/', $dd)) { - if (preg_match('/\n\n/', $dd)) { $dd = $this->process($dd); } - } else { - $dd = $this->format_paragraph(array('text' => $dd)); - } - $out .= '' . "\n"; - return $out; - } // function add_term - - /** - * Takes a Textile formatted list (numeric or bulleted) and - * returns the markup for it. Text that is passed in requires - * substantial parsing, so the @c format_list method is a little - * involved. But it should always produce a proper ordered - * or unordered list. If it cannot (due to misbalanced input), - * it will return the original text. Arguments accepted: - * - *
      - * - *
    • text - * - * The text to be processed.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the list. - * - * @return A @c string containing the formatted list. - * - * @private - */ - function format_list($args) { - $str = (isset($args['text']) ? $args['text'] : ''); - - $list_tags = array('*' => 'ul', '#' => 'ol'); - - $lines = preg_split('/\n/', $str); - - unset($stack); - $last_depth = 0; - $item = ''; - $out = ''; - foreach ($lines as $line) { - if (preg_match('{^((?:' . $this->clstypadre . '*|' . $this->halignre . ')*) - ([\#\*]+) - ((?:' . $this->halignre . '|' . $this->clstypadre . '*)*) - \ (.+)$}x', $line, $matches)) { - if ($item != '') { - if (preg_match('/\n/', $item)) { - if ($this->options['_line_open']) { - $item = preg_replace('/(]*>|^)/m', '$1' . $this->options['_line_open'], $item); - $item = preg_replace('/(\n|$)/s', $this->options['_line_close'] . '$1', $item); - } else { - $item = preg_replace('/(\n)/s', $this->options['_line_close'] . '$1', $item); - } - } - $out .= $item; - $item = ''; - } - $type = substr($matches[2], 0, 1); - $depth = strlen($matches[2]); - $blockparam = $matches[1]; - $itemparam = $matches[3]; - $line = $matches[4]; - unset ($blockclsty, $blockalign, $blockattr, $itemattr, $itemclsty, - $itemalign); - if (preg_match('{(' . $this->clstypadre . '+)}x', $blockparam, $matches)) { - $blockclsty = $matches[1]; - } - if (preg_match('{(' . $this->halignre . '+)}', $blockparam, $matches)) { - $blockalign = $matches[1]; - } - if (preg_match('{(' . $this->clstypadre . '+)}x', $itemparam, $matches)) { - $itemclsty = $matches[1]; - } - if (preg_match('{(' . $this->halignre . '+)}', $itemparam, $matches)) { - $itemalign = $matches[1]; - } - if ($itemclsty) { $itemattr = $this->format_classstyle($itemclsty); } - if ($depth > $last_depth) { - for ($j = $last_depth; $j < $depth; $j++) { - $out .= "\n<$list_tags[$type]"; - $stack[] = $type; - if ($blockclsty) { - $blockattr = $this->format_classstyle($blockclsty); - if ($blockattr) { $out .= ' ' . $blockattr; } - } - $out .= ">\nformat_paragraph(array('text' => $line)); - } - - if (preg_match('/\n/', $item, $matches)) { - if ($this->options['_line_open']) { - $item = preg_replace('/(]*>|^)/m', '$1' . $this->options['_line_open'], $item); - $item = preg_replace('/(\n|$)/s', $this->options['_line_close'] . '$1', $item); - } else { - $item = preg_replace('/(\n)/s', $this->options['_line_close'] . '$1', $item); - } - } - $out .= $item; - - for ($j = 1; $j <= $last_depth; $j++) { - if ($j == 1) { $out .= ''; } - $type = array_pop($stack); - $out .= "\n" . '' . "\n"; - if ($j != $last_depth) { $out .= ''; } - } - - return $out . "\n"; - } // function format_list - - /** - * Processes '==xxxxx==' type blocks for filters. A filter - * would follow the open '==' sequence and is specified within - * pipe characters, like so: - *
    -   *     ==|filter|text to be filtered==
    -   * 
    - * You may specify multiple filters in the filter portion of - * the string. Simply comma delimit the filters you desire - * to execute. Filters are defined using the filters method. - * - * @param $args An @c array specifying the attributes for formatting - * the block. - * - * @return A @c string containing the formatted block. - * - * @private - */ - function format_block($args) { - $str = (isset($args['text']) ? $args['text'] : ''); - $inline = $args['inline']; - $pre = (isset($args['pre']) ? $args['pre'] : ''); - $post = (isset($args['post']) ? $args['post'] : ''); - $this->_strip_borders($pre, $post); - $filters = (preg_match('/^(\|(?:(?:[a-z0-9_\-]+)\|)+)/', $str, $matches) ? $matches[1] : ''); - if ($filters) { - $filtreg = preg_replace('/[^A-Za-z0-9]/', '\\\\$1', $filters); - $str = preg_replace('/^' . $filtreg . '/', '', $str, 1); - $filters = preg_replace('/^\|/', '', $filters, 1); - $filters = preg_replace('/\|$/', '', $filter, 1); - $filters = preg_split('/\|/', $filters); - $str = $this->apply_filters(array('text' => $str, 'filters' => $filters)); - $count = count($filters); - if ($str = preg_replace('!(

    ){' . $count . '}!se', '(++$i ? "$1" : "$1")', $str) && $i) { - $str = preg_replace('!(

    ){' . $count . '}!s', '$1', $str); - $str = preg_replace('!(){' . $count . '}!s', '$1', $str); - } - } - if ($inline) { - // strip off opening para, closing para, since we're - // operating within an inline block - $str = preg_replace('/^\s*]*>/', '', $str, 1); - $str = preg_replace('/<\/p>\s*$/', '', $str, 1); - } - return $pre . $str . $post; - } // function format_block - - /** - * Takes the Textile link attributes and transforms them into - * a hyperlink. - * - * @param $args An @c array specifying the attributes for formatting - * the link. - * - * @return A @c string containing the formatted link. - * - * @private - */ - function format_link($args) { - $text = (isset($args['text']) ? $args['text'] : ''); - $linktext = (isset($args['linktext']) ? $args['linktext'] : ''); - $title = $args['title']; - $url = $args['url']; - $clsty = $args['clsty']; - - if (!$url || ($url == '')) { - return $text; - } - if (isset($this->links) && isset($this->links[$url])) { - $title = ($title ? $title : $this->links[$url]['title']); - $url = $this->links[$url]['url']; - } - $linktext = preg_replace('/ +$/', '', $linktext, 1); - $linktext = $this->format_paragraph(array('text' => $linktext)); - $url = $this->format_url(array('linktext' => $linktext, 'url' => $url)); - $tag = "format_classstyle($clsty); - if ($attr) { $tag .= " $attr"; } - if ($title) { - $title = preg_replace('/^\s+/', '', $title, 1); - if (strlen($title)) { $tag .= " title=\"$title\""; } - } - $tag .= ">$linktext"; - return $tag; - } // function format_link - - /** - * Takes the given @c $url and transforms it appropriately. - * - * @param $args An @c array specifying the attributes for formatting - * the url. - * - * @return A @c string containing the formatted url. - * - * @private - */ - function format_url($args) { - $url = ($args['url'] ? $args['url'] : ''); - if (preg_match('/^(mailto:)?([-\+\w]+@[-\w]+(\.\w[-\w]*)+)$/', $url, $matches)) { - $url = 'mailto:' . $this->mail_encode($matches[2]); - } - if (!preg_match('!^(/|\./|\.\./|#)!', $url)) { - if (!preg_match('!^(https?|ftp|mailto|nntp|telnet)!', $url)) { $url = "http://$url"; } - } - $url = preg_replace('/&(?!amp;)/', '&', $url); - $url = preg_replace('/\ /', '+', $url); - $url = preg_replace_callback('/^((?:.+?)\?)(.+)$/', $this->_cb('$m[1] . $me->encode_url($m[2])'), $url); - return $url; - } // function format_url - - /** - * Takes a Textile formatted span and returns the markup for it. - * - * @return A @c string containing the formatted span. - * - * @private - */ - function format_span($args) { - $text = (isset($args['text']) ? $args['text'] : ''); - $pre = (isset($args['pre']) ? $args['pre'] : ''); - $post = (isset($args['post']) ? $args['post'] : ''); - $align = $args['align']; - $cite = (isset($args['cite']) ? $args['cite'] : ''); - $clsty = $args['clsty']; - $this->_strip_borders($pre, $post); - unset($class, $style); - $tag = "options['css_mode']) { - $alignment = $this->_halign($align); - if ($alignment) { $style .= ";float:$alignment"; } - if ($alignment) { $class .= ' ' . $this->options['css']["class_align_$alignment"]; } - } else { - $alignment = ($this->_halign($align) ? $this->_halign($align) : $this->_valign($align)); - if ($alignment) { $tag .= " align=\"$alignment\""; } - } - } - $attr = $this->format_classstyle($clsty, $class, $style); - if ($attr) { $tag .= " $attr"; } - if ($cite) { - $cite = preg_replace('/^:/', '', $cite, 1); - $cite = $this->format_url(array('url' => $cite)); - $tag .= " cite=\"$cite\""; - } - return $pre . $tag . '>' . $this->format_paragraph(array('text' => $text)) . '' . $post; - } // function format_span - - /** - * Returns markup for the given image. @c $src is the location of - * the image, @c $extra contains the optional height/width and/or - * alt text. @c $url is an optional hyperlink for the image. @c $class - * holds the optional CSS class attribute. - * - * Arguments you may pass: - * - *
      - * - *
    • src - * - * The 'src' (URL) for the image. This may be a local path, - * ideally starting with a '/'. Images can be located within - * the file system if the docroot method is used to specify - * where the docroot resides. If the image can be found, the - * image_size method is used to determine the dimensions of - * the image.
    • - * - *
    • extra - * - * Additional parameters for the image. This would include - * alt text, height/width specification or scaling instructions.
    • - * - *
    • align - * - * Alignment attribute.
    • - * - *
    • pre - * - * Text to produce prior to the tag.
    • - * - *
    • post - * - * Text to produce following the tag.
    • - * - *
    • link - * - * Optional URL to connect with the image tag.
    • - * - *
    • clsty - * - * Class and/or style attributes.
    • - * - *
    - * - * @param $args An @c array specifying the attributes for formatting - * the image. - * - * @return A @c string containing the formatted image. - * - * @private - */ - function format_image($args) { - $src = (isset($args['src']) ? $args['src'] : ''); - $extra = $args['extra']; - $align = $args['align']; - $pre = (isset($args['pre']) ? $args['pre'] : ''); - $post = (isset($args['post']) ? $args['post'] : ''); - $link = $args['url']; - $clsty = $args['clsty']; - $this->_strip_borders($pre, $post); - if (strlen($src) == 0) { return $pre . '!!' . $post; } - unset($tag); - if (preg_match('/^xhtml2/', $this->options['flavor'])) { - unset($type); // poor man's mime typing. need to extend this externally - if (preg_match('/(?:\.jpeg|\.jpg)$/i', $src)) { - $type = 'image/jpeg'; - } elseif (preg_match('/\.gif$/i', $src)) { - $type = 'image/gif'; - } elseif (preg_match('/\.png$/i', $src)) { - $type = 'image/png'; - } elseif (preg_match('/\.tiff$/i', $src)) { - $type = 'image/tiff'; - } - $tag = "options['css_mode']) { - $alignment = $this->_halign($align); - if ($alignment) { $style .= ";float:$alignment"; } - if ($alignment) { $class .= ' ' . $alignment; } - $alignment = $this->_valign($align); - if ($alignment) { - $imgvalign = (preg_match('/(top|bottom)/', $alignment) ? 'text-' . $alignment : $alignment); - if ($imgvalign) { $style .= ";vertical-align:$imgvalign"; } - if ($alignment) { $class .= ' ' . $this->options['css']["class_align_$alignment"]; } - } - } else { - $alignment = ($this->_halign($align) ? $this->_halign($align) : $this->_valign($align)); - if ($alignment) { $tag .= " align=\"$alignment\""; } - } - } - unset($pctw, $pcth, $w, $h, $alt); - if ($extra) { - $alt = (preg_match('/\(([^\)]+)\)/', $extra, $matches) ? $matches[1] : ''); - $extra = preg_replace('/\([^\)]+\)/', '', $extra, 1); - $pct = (preg_match('/(^|\s)(\d+)%(\s|$)/', $extra, $matches) ? $matches[2] : ''); - if (!$pct) { - list($pctw, $pcth) = (preg_match('/(^|\s)(\d+)%x(\d+)%(\s|$)/', $extra, $matches) ? array($matches[2], $matches[3]) : NULL); - } else { - $pctw = $pcth = $pct; - } - if (!$pctw && !$pcth) { - list($w,$h) = (preg_match('/(^|\s)(\d+|\*)x(\d+|\*)(\s|$)/', $extra, $matches) ? array($matches[2], $matches[3]) : NULL); - if ($w == '*') { $w = ''; } - if ($h == '*') { $h = ''; } - if (!$w) { - $w = (preg_match('/(^|[,\s])(\d+)w([\s,]|$)/', $extra, $matches) ? $matches[2] : ''); - } - if (!$h) { - $h = (preg_match('/(^|[,\s])(\d+)h([\s,]|$)/', $extra, $matches) ? $matches[2] : ''); - } - } - } - $alt = ($alt ? $alt : ''); - if (!preg_match('/^xhtml2/', $this->options['flavor'])) { - $tag .= ' alt="' . $this->encode_html_basic($alt) . '"'; - } - if ($w && $h) { - if (!preg_match('/^xhtml2/', $this->options['flavor'])) { - $tag .= " height=\"$h\" width=\"$w\""; - } else { - $style .= ";height:${h}px;width:${w}px"; - } - } else { - list($image_w, $image_h) = $this->image_size($src); - if (($image_w && $image_h) && ($w || $h)) { - // image size determined, but only width or height specified - if ($w && !$h) { - // width defined, scale down height proportionately - $h = intval($image_h * ($w / $image_w)); - } elseif ($h && !$w) { - $w = intval($image_w * ($h / $image_h)); - } - } else { - $w = $image_w; - $h = $image_h; - } - if ($w && $h) { - if ($pctw || $pcth) { - $w = intval($w * $pctw / 100); - $h = intval($h * $pcth / 100); - } - if (!preg_match('/^xhtml2/', $this->options['flavor'])) { - $tag .= " height=\"$h\" width=\"$w\""; - } else { - $style .= ";height:{$h}px;width:{$w}px"; - } - } - } - $attr = $this->format_classstyle($clsty, $class, $style); - if ($attr) { $tag .= " $attr"; } - if (preg_match('/^xhtml2/', $this->options['flavor'])) { - $tag .= '>

    ' . $this->encode_html_basic($alt) . '

    '; - } elseif (preg_match('/^xhtml/', $this->options['flavor'])) { - $tag .= ' />'; - } else { - $tag .= '>'; - } - if ($link) { - $link = preg_replace('/^:/', '', $link, 1); - $link = $this->format_url(array('url' => $link)); - $tag = '' . $tag . ''; - } - return $pre . $tag . $post; - } // function format_image - - /** - * Takes a Wiki-ish string of data and transforms it into a full - * table. - * - * @param $args An @c array specifying the attributes for formatting - * the table. - * - * @return A @c string containing the formatted table. - * - * @private - */ - function format_table($args) { - $str = (isset($args['text']) ? $args['text'] : ''); - - $lines = preg_split('/\n/', $str); - unset($rows); - $line_count = count($lines); - for ($i = 0; $i < $line_count; $i++) { - if (!preg_match('/\|\s*$/', $lines[$i])) { - if ($i + 1 < $line_count) { - if ($i + 1 <= count($lines) - 1) { $lines[$i + 1] = $lines[$i] . "\n" . $lines[$i + 1]; } - } else { - $rows[] = $lines[$i]; - } - } else { - $rows[] = $lines[$i]; - } - } - unset($tid, $tpadl, $tpadr, $tlang); - $tclass = ''; - $tstyle = ''; - $talign = ''; - if (preg_match('/^table[^\.]/', $rows[0])) { - $row = $rows[0]; - $row = preg_replace('/^table/', '', $row, 1); - $params = 1; - // process row parameters until none are left - while ($params) { - if (preg_match('{^(' . $this->tblalignre . ')}', $row, $matches)) { - // found row alignment - $talign .= $matches[1]; - if ($matches[1]) { $row = substr($row, strlen($matches[1])); } - if ($matches[1]) { continue; } - } - if (preg_match('{^(' . $this->clstypadre . ')}x', $row, $matches)) { - // found a class/id/style/padding indicator - $clsty = $matches[1]; - if ($clsty) { $row = substr($row, strlen($clsty)); } - if (preg_match('/{([^}]+)}/', $clsty, $matches)) { - $tstyle = $matches[1]; - $clsty = preg_replace('/{([^}]+)}/', '', $clsty, 1); - if ($tstyle) { continue; } - } - if (preg_match('/\(([A-Za-z0-9_\- ]+?)(?:#(.+?))?\)/', $clsty, $matches) || - preg_match('/\(([A-Za-z0-9_\- ]+?)?(?:#(.+?))\)/', $clsty, $matches)) { - if ($matches[1] || $matches[2]) { - $tclass = $matches[1]; - $tid = $matches[2]; - continue; - } - } - if (preg_match('/(\(+)/', $clsty, $matches)) { $tpadl = strlen($matches[1]); } - if (preg_match('/(\)+)/', $clsty, $matches)) { $tpadr = strlen($matches[1]); } - if (preg_match('/\[(.+?)\]/', $clsty, $matches)) { $tlang = $matches[1]; } - if ($clsty) { continue; } - } - $params = 0; - } - $row = preg_replace('/\.\s+/', '', $row, 1); - $rows[0] = $row; - } - $out = ''; - $cols = preg_split('/\|/', $rows[0] . ' '); - unset($colaligns, $rowspans); - foreach ($rows as $row) { - $cols = preg_split('/\|/', $row . ' '); - $colcount = count($cols) - 1; - array_pop($cols); - $colspan = 0; - $row_out = ''; - unset($rowclass, $rowid, $rowalign, $rowstyle, $rowheader); - if (!$cols[0]) { $cols[0] = ''; } - if (preg_match('/_/', $cols[0])) { - $cols[0] = preg_replace('/_/', '', $cols[0]); - $rowheader = 1; - } - if (preg_match('/{([^}]+)}/', $cols[0], $matches)) { - $rowstyle = $matches[1]; - $cols[0] = preg_replace('/{[^}]+}/', '', $cols[0]); - } - if (preg_match('/\(([^\#]+?)?(#(.+))?\)/', $cols[0], $matches)) { - $rowclass = $matches[1]; - $rowid = $matches[3]; - $cols[0] = preg_replace('/\([^\)]+\)/', '', $cols[0]); - } - if (preg_match('{(' . $this->alignre . ')}', $cols[0], $matches)) { $rowalign = $matches[1]; } - for ($c = $colcount - 1; $c > 0; $c--) { - if ($rowspans[$c]) { - $rowspans[$c]--; - if ($rowspans[$c] > 1) { continue; } - } - unset($colclass, $colid, $header, $colparams, $colpadl, $colpadr, $collang); - $colstyle = ''; - $colalign = $colaligns[$c]; - $col = array_pop($cols); - $col = ($col ? $col : ''); - $attrs = ''; - if (preg_match('{^(((_|[/\\\\]\d+|' . $this->alignre . '|' . $this->clstypadre . ')+)\.\ )}x', $col, $matches)) { - $colparams = $matches[2]; - $col = substr($col, strlen($matches[1])); - $params = 1; - // keep processing column parameters until there - // are none left... - while ($params) { - if (preg_match('{^(_|' . $this->alignre . ')(.*)$}', $colparams, $matches)) { - // found alignment or heading indicator - $attrs .= $matches[1]; - if ($matches[1]) { $colparams = $matches[2]; } - if ($matches[1]) { continue; } - } - if (preg_match('{^(' . $this->clstypadre . ')(.*)$}x', $colparams, $matches)) { - // found a class/id/style/padding marker - $clsty = $matches[1]; - if ($clsty) { $colparams = $matches[2]; } - if (preg_match('/{([^}]+)}/', $clsty, $matches)) { - $colstyle = $matches[1]; - $clsty = preg_replace('/{([^}]+)}/', '', $clsty, 1); - } - if (preg_match('/\(([A-Za-z0-9_\- ]+?)(?:#(.+?))?\)/', $clsty, $matches) || - preg_match('/\(([A-Za-z0-9_\- ]+?)?(?:#(.+?))\)/', $clsty, $matches)) { - if ($matches[1] || $matches[2]) { - $colclass = $matches[1]; - $colid = $matches[2]; - if ($colclass) { - $clsty = preg_replace('/\([A-Za-z0-9_\- ]+?(#.*?)?\)/', '', $clsty); - } elseif ($colid) { - $clsty = preg_replace('/\(#.+?\)/', '', $clsty); - } - } - } - if (preg_match('/(\(+)/', $clsty, $matches)) { - $colpadl = strlen($matches[1]); - $clsty = preg_replace('/\(+/', '', $clsty, 1); - } - if (preg_match('/(\)+)/', $clsty, $matches)) { - $colpadr = strlen($matches[1]); - $clsty = preg_replace('/\)+/', '', $clsty, 1); - } - if (preg_match('/\[(.+?)\]/', $clsty, $matches)) { - $collang = $matches[1]; - $clsty = preg_replace('/\[.+?\]/', '', $clsty, 1); - } - if ($clsty) { continue; } - } - if (preg_match('/^\\\\(\d+)/', $colparams, $matches)) { - $colspan = $matches[1]; - $colparams = substr($colparams, strlen($matches[1]) + 1); - if ($matches[1]) { continue; } - } - if (preg_match('/\/(\d+)/', $colparams, $matches)) { - if ($matches[1]) { $rowspans[$c] = $matches[1]; } - $colparams = substr($colparams, strlen($matches[1]) + 1); - if ($matches[1]) { continue; } - } - $params = 0; - } - } - if (strlen($attrs)) { - if (preg_match('/_/', $attrs)) { $header = 1; } - if (preg_match('{(' . $this->alignre . ')}', $attrs, $matches) && strlen($matches[1])) { $colalign = ''; } - // determine column alignment - if (preg_match('/<>/', $attrs)) { - $colalign .= '<>'; - } elseif (preg_match('//', $attrs)) { - $colalign = '>'; - } - if (preg_match('/\^/', $attrs)) { - $colalign .= '^'; - } elseif (preg_match('/~/', $attrs)) { - $colalign .= '~'; - } elseif (preg_match('/-/', $attrs)) { - $colalign .= '-'; - } - } - if ($rowheader) { $header = 1; } - if ($header) { $colaligns[$c] = $colalign; } - $col = preg_replace('/^ +/', '', $col, 1); $col = preg_replace('/ +$/', '', $col, 1); - if (strlen($col)) { - // create one cell tag - $rowspan = ($rowspans[$c] ? $rowspans[$c] : 0); - $col_out = '<' . ($header ? 'th' : 'td'); - if ($colalign) { - // horizontal, vertical alignment - $halign = $this->_halign($colalign); - if ($halign) { $col_out .= " align=\"$halign\""; } - $valign = $this->_valign($colalign); - if ($valign) { $col_out .= " valign=\"$valign\""; } - } - // apply css attributes, row, column spans - if ($colpadl) { $colstyle .= ";padding-left:${colpadl}em"; } - if ($colpadr) { $colstyle .= ";padding-right:${colpadr}em"; } - if ($colclass) { $col_out .= " class=\"$colclass\""; } - if ($colid) { $col_out .= " id=\"$colid\""; } - if ($colstyle) { $colstyle = preg_replace('/^;/', '', $colstyle, 1); } - if ($colstyle) { $col_out .= " style=\"$colstyle\""; } - if ($collang) { $col_out .= " lang=\"$collang\""; } - if ($colspan > 1) { $col_out .= " colspan=\"$colspan\""; } - if ($rowspan > 1) { $col_out .= " rowspan=\"$rowspan\""; } - $col_out .= '>'; - // if the content of this cell has newlines OR matches - // our paragraph block signature, process it as a full-blown - // textile document - if (preg_match('/\n\n/', $col) || - preg_match('{^(?:' . $this->halignre . '|' . $this->clstypadre . '*)* - [\*\#] - (?:' . $this->clstypadre . '*|' . $this->halignre . ')*\ }x', $col)) { - $col_out .= $this->process($col); - } else { - $col_out .= $this->format_paragraph(array('text' => $col)); - } - $col_out .= ''; - $row_out = $col_out . $row_out; - if ($colspan) { $colspan = 0; } - } else { - if ($colspan == 0) { $colspan = 1; } - $colspan++; - } - } - if ($colspan > 1) { - // handle the spanned column if we came up short - $colspan--; - $row_out = " 1 ? " colspan=\"$colspan\"" : '') - . ">$row_out"; - } - - // build one table row - $out .= "_valign($rowalign); - if ($valign) { $out .= " valign=\"$valign\""; } - } - if ($rowclass) { $out .= " class=\"$rowclass\""; } - if ($rowid) { $out .= " id=\"$rowid\""; } - if ($rowstyle) { $out .= " style=\"$rowstyle\""; } - $out .= ">$row_out"; - } - - // now, form the table tag itself - $table = ''; - $table .= "options['css_mode']) { - // horizontal alignment - $alignment = $this->_halign($talign); - if ($talign == '=') { - $tstyle .= ';margin-left:auto;margin-right:auto'; - } else { - if ($alignment) { $tstyle .= ';float:' . $alignment; } - } - if ($alignment) { $tclass .= ' ' . $alignment; } - } else { - $alignment = $this->_halign($talign); - if ($alignment) { $table .= " align=\"$alignment\""; } - } - } - if ($tpadl) { $tstyle .= ";padding-left:${tpadl}em"; } - if ($tpadr) { $tstyle .= ";padding-right:${tpadr}em"; } - if ($tclass) { $tclass = preg_replace('/^ /', '', $tclass, 1); } - if ($tclass) { $table .= " class=\"$tclass\""; } - if ($tid) { $table .= " id=\"$tid\""; } - if ($tstyle) { $tstyle = preg_replace('/^;/', '', $tstyle, 1); } - if ($tstyle) { $table .= " style=\"$tstyle\""; } - if ($tlang) { $table .= " lang=\"$tlang\""; } - if ($tclass || $tid || $tstyle) { $table .= " cellspacing=\"0\""; } - $table .= ">$out"; - - if (preg_match('||', $table)) { - // exception -- something isn't right so return fail case - return NULL; - } - - return $table; - } // function format_table - - /** - * The following attributes are allowed: - * - *
      - * - *
    • text - * - * The text to be processed.
    • - * - *
    • filters - * - * An array reference of filter names to run for the given text.
    • - * - *
    - * - * @param $args An @c array specifying the text and filters to - * apply. - * - * @return A @c string containing the filtered text. - * - * @private - */ - function apply_filters($args) { - $text = $args['text']; - if (!$text) { return ''; } - $list = $args['filters']; - $filters = $this->options['filters']; - if (!is_array($filters)) { return $text; } - - $param = $this->filter_param(); - foreach ($list as $filter) { - if (!isset($filters[$filter])) { continue; } - if (is_string($filters[$filter])) { - $text = (($f = create_function('$text, $param', $filters[$filter])) ? $f($text, $param) : $text); - } - } - return $text; - } // function apply_filters - - // minor utility / formatting routines - - var $Have_Entities = 1; - - /** - * Encodes input @c $html string, escaping characters as needed - * to HTML entities. This relies on the @c htmlentities function - * for full effect. If unavailable, @c encode_html_basic is used - * as a fallback technique. If the "char_encoding" flag is - * set to false, @c encode_html_basic is used exclusively. - * - * @param $html A @c string specifying the HTML to be encoded. - * @param $can_double_encode If provided, a @c bool indicating - * whether or not ampersand characters should be - * unconditionally encoded. - * - * @return A @c string containing the encoded HTML. - * - * @private - */ - function encode_html($html, $can_double_encode = FALSE) { - if (!$html) { return ''; } - if ($this->Have_Entities && $this->options['char_encoding']) { - $html = htmlentities($html); - } else { - $html = $this->encode_html_basic($html, $can_double_encode); - } - return $html; - } // function encode_html - - /** - * Decodes HTML entities in @c $html to their natural character - * equivalents. - * - * @param $html A @c string specifying the HTML to be decoded. - * - * @return A @c string containing the decode HTML - * - * @private - */ - function decode_html($html) { - $html = preg_replace('!"!', '"', $html); - $html = preg_replace('!&!', '&', $html); - $html = preg_replace('!<!', '<', $html); - $html = preg_replace('!>!', '>', $html); - return $html; - } // function decode_html - - /** - * Encodes the input @c $html string for the following characters: - * \<, \>, & and ". If @c $can_double_encode is true, all - * ampersand characters are escaped even if they already were. - * If @c $can_double_encode is false, ampersands are only escaped - * when they aren't part of a HTML entity already. - * - * @param $html A @c string specifying the HTML to be encoded. - * @param $can_double_encode If provided, a @c bool indicating - * whether or not ampersand characters should be - * unconditionally encoded. - * - * @return A @c string containing the encoded HTML. - * - * @private - */ - function encode_html_basic($html, $can_double_encode = FALSE) { - if (!$html) { return ''; } - if (!preg_match('/[^\w\s]/', $html)) { return $html; } - if ($can_double_encode) { - $html = preg_replace('!&!', '&', $html); - } else { - // Encode any & not followed by something that looks like - // an entity, numeric or otherwise. - $html = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w{1,8});)/', '&', $html); - } - $html = preg_replace('!"!', '"', $html); - $html = preg_replace('!!', '>', $html); - return $html; - } // function encode_html_basic - - /** - * Returns the size for the image identified in @c $file. This - * method relies upon the @c getimagesize function. If unavailable, - * @c image_size will return @c NULL. Otherwise, the expected return - * value is an array of the width and height (in that order), in - * pixels. - * - * @param $file A @c string specifying the path or URL for the image - * file. - * - * @return An @c array containing the width and height - * (respectively) of the image. - * - * @private - */ - function image_size($file) { - $Have_ImageSize = function_exists('getimagesize'); - - if ($Have_ImageSize) { - if (file_exists($file)) { - return @getimagesize($file); - } else { - if ($docroot = ($this->docroot() ? $this->docroot() : $_SERVER['DOCUMENT_ROOT'])) { - $fullpath = $docroot . preg_replace('|^/*(.*)$|', '/$1', $file); - if (file_exists($fullpath)) { - return @getimagesize($fullpath); - } - } - } - } - return @getimagesize($file); - } // function image_size - - /** - * Encodes the query portion of a URL, escaping characters - * as necessary. - * - * @param $str A @c string specifying the URL to be encoded. - * - * @return A @c string containing the encoded URL. - * - * @private - */ - function encode_url($str) { - $str = preg_replace_callback('!([^A-Za-z0-9_\.\-\+\&=%;])!x', - $this->_cb('ord($m[1]) > 255 ? \'%u\' . sprintf("%04X", ord($m[1])) - : \'%\' . sprintf("%02X", ord($m[1]))'), $str); - return $str; - } // function encode_url - - /** - * Encodes the email address in @c $addr for 'mailto:' links. - * - * @param $addr A @c string specifying the email address to encode. - * - * @return A @c string containing the encoded email address. - * - * @private - */ - function mail_encode($addr) { - // granted, this is simple, but it gives off warm fuzzies - $addr = preg_replace_callback('!([^\$])!x', - $this->_cb('ord($m[1]) > 255 ? \'%u\' . sprintf("%04X", ord($m[1])) - : \'%\' . sprintf("%02X", ord($m[1]))'), $addr); - return $addr; - } // function mail_encode - - /** - * Processes string, formatting plain quotes into curly quotes. - * - * @param $str A @c string specifying the text to process. - * - * @return A @c string containing the processed text. - * - * @private - */ - function process_quotes($str) { - // stub routine for now. subclass and implement. - return $str; - } // function process_quotes - - // a default set of macros for the {...} macro syntax - // just a handy way to write a lot of the international characters - // and some commonly used symbols - - /** - * Returns an associative @c array of macros that are assigned to be processed by - * default within the @c format_inline method. - * - * @return An @c array containing the default macros. - * - * @private - */ - function default_macros() { - // <, >, " must be html entities in the macro text since - // those values are escaped by the time they are processed - // for macros. - return array( - 'c|' => '¢', // CENT SIGN - '|c' => '¢', // CENT SIGN - 'L-' => '£', // POUND SIGN - '-L' => '£', // POUND SIGN - 'Y=' => '¥', // YEN SIGN - '=Y' => '¥', // YEN SIGN - '(c)' => '©', // COPYRIGHT SIGN - '<<' => '«', // LEFT-POINTING DOUBLE ANGLE QUOTATION - '(r)' => '®', // REGISTERED SIGN - '+_' => '±', // PLUS-MINUS SIGN - '_+' => '±', // PLUS-MINUS SIGN - '>>' => '»', // RIGHT-POINTING DOUBLE ANGLE QUOTATION - '1/4' => '¼', // VULGAR FRACTION ONE QUARTER - '1/2' => '½', // VULGAR FRACTION ONE HALF - '3/4' => '¾', // VULGAR FRACTION THREE QUARTERS - 'A`' => 'À', // LATIN CAPITAL LETTER A WITH GRAVE - '`A' => 'À', // LATIN CAPITAL LETTER A WITH GRAVE - 'A\'' => 'Á', // LATIN CAPITAL LETTER A WITH ACUTE - '\'A' => 'Á', // LATIN CAPITAL LETTER A WITH ACUTE - 'A^' => 'Â', // LATIN CAPITAL LETTER A WITH CIRCUMFLEX - '^A' => 'Â', // LATIN CAPITAL LETTER A WITH CIRCUMFLEX - 'A~' => 'Ã', // LATIN CAPITAL LETTER A WITH TILDE - '~A' => 'Ã', // LATIN CAPITAL LETTER A WITH TILDE - 'A"' => 'Ä', // LATIN CAPITAL LETTER A WITH DIAERESIS - '"A' => 'Ä', // LATIN CAPITAL LETTER A WITH DIAERESIS - 'Ao' => 'Å', // LATIN CAPITAL LETTER A WITH RING ABOVE - 'oA' => 'Å', // LATIN CAPITAL LETTER A WITH RING ABOVE - 'AE' => 'Æ', // LATIN CAPITAL LETTER AE - 'C,' => 'Ç', // LATIN CAPITAL LETTER C WITH CEDILLA - ',C' => 'Ç', // LATIN CAPITAL LETTER C WITH CEDILLA - 'E`' => 'È', // LATIN CAPITAL LETTER E WITH GRAVE - '`E' => 'È', // LATIN CAPITAL LETTER E WITH GRAVE - 'E\'' => 'É', // LATIN CAPITAL LETTER E WITH ACUTE - '\'E' => 'É', // LATIN CAPITAL LETTER E WITH ACUTE - 'E^' => 'Ê', // LATIN CAPITAL LETTER E WITH CIRCUMFLEX - '^E' => 'Ê', // LATIN CAPITAL LETTER E WITH CIRCUMFLEX - 'E"' => 'Ë', // LATIN CAPITAL LETTER E WITH DIAERESIS - '"E' => 'Ë', // LATIN CAPITAL LETTER E WITH DIAERESIS - 'I`' => 'Ì', // LATIN CAPITAL LETTER I WITH GRAVE - '`I' => 'Ì', // LATIN CAPITAL LETTER I WITH GRAVE - 'I\'' => 'Í', // LATIN CAPITAL LETTER I WITH ACUTE - '\'I' => 'Í', // LATIN CAPITAL LETTER I WITH ACUTE - 'I^' => 'Î', // LATIN CAPITAL LETTER I WITH CIRCUMFLEX - '^I' => 'Î', // LATIN CAPITAL LETTER I WITH CIRCUMFLEX - 'I"' => 'Ï', // LATIN CAPITAL LETTER I WITH DIAERESIS - '"I' => 'Ï', // LATIN CAPITAL LETTER I WITH DIAERESIS - 'D-' => 'Ð', // LATIN CAPITAL LETTER ETH - '-D' => 'Ð', // LATIN CAPITAL LETTER ETH - 'N~' => 'Ñ', // LATIN CAPITAL LETTER N WITH TILDE - '~N' => 'Ñ', // LATIN CAPITAL LETTER N WITH TILDE - 'O`' => 'Ò', // LATIN CAPITAL LETTER O WITH GRAVE - '`O' => 'Ò', // LATIN CAPITAL LETTER O WITH GRAVE - 'O\'' => 'Ó', // LATIN CAPITAL LETTER O WITH ACUTE - '\'O' => 'Ó', // LATIN CAPITAL LETTER O WITH ACUTE - 'O^' => 'Ô', // LATIN CAPITAL LETTER O WITH CIRCUMFLEX - '^O' => 'Ô', // LATIN CAPITAL LETTER O WITH CIRCUMFLEX - 'O~' => 'Õ', // LATIN CAPITAL LETTER O WITH TILDE - '~O' => 'Õ', // LATIN CAPITAL LETTER O WITH TILDE - 'O"' => 'Ö', // LATIN CAPITAL LETTER O WITH DIAERESIS - '"O' => 'Ö', // LATIN CAPITAL LETTER O WITH DIAERESIS - 'O/' => 'Ø', // LATIN CAPITAL LETTER O WITH STROKE - '/O' => 'Ø', // LATIN CAPITAL LETTER O WITH STROKE - 'U`' => 'Ù', // LATIN CAPITAL LETTER U WITH GRAVE - '`U' => 'Ù', // LATIN CAPITAL LETTER U WITH GRAVE - 'U\'' => 'Ú', // LATIN CAPITAL LETTER U WITH ACUTE - '\'U' => 'Ú', // LATIN CAPITAL LETTER U WITH ACUTE - 'U^' => 'Û', // LATIN CAPITAL LETTER U WITH CIRCUMFLEX - '^U' => 'Û', // LATIN CAPITAL LETTER U WITH CIRCUMFLEX - 'U"' => 'Ü', // LATIN CAPITAL LETTER U WITH DIAERESIS - '"U' => 'Ü', // LATIN CAPITAL LETTER U WITH DIAERESIS - 'Y\'' => 'Ý', // LATIN CAPITAL LETTER Y WITH ACUTE - '\'Y' => 'Ý', // LATIN CAPITAL LETTER Y WITH ACUTE - 'a`' => 'à', // LATIN SMALL LETTER A WITH GRAVE - '`a' => 'à', // LATIN SMALL LETTER A WITH GRAVE - 'a\'' => 'á', // LATIN SMALL LETTER A WITH ACUTE - '\'a' => 'á', // LATIN SMALL LETTER A WITH ACUTE - 'a^' => 'â', // LATIN SMALL LETTER A WITH CIRCUMFLEX - '^a' => 'â', // LATIN SMALL LETTER A WITH CIRCUMFLEX - 'a~' => 'ã', // LATIN SMALL LETTER A WITH TILDE - '~a' => 'ã', // LATIN SMALL LETTER A WITH TILDE - 'a"' => 'ä', // LATIN SMALL LETTER A WITH DIAERESIS - '"a' => 'ä', // LATIN SMALL LETTER A WITH DIAERESIS - 'ao' => 'å', // LATIN SMALL LETTER A WITH RING ABOVE - 'oa' => 'å', // LATIN SMALL LETTER A WITH RING ABOVE - 'ae' => 'æ', // LATIN SMALL LETTER AE - 'c,' => 'ç', // LATIN SMALL LETTER C WITH CEDILLA - ',c' => 'ç', // LATIN SMALL LETTER C WITH CEDILLA - 'e`' => 'è', // LATIN SMALL LETTER E WITH GRAVE - '`e' => 'è', // LATIN SMALL LETTER E WITH GRAVE - 'e\'' => 'é', // LATIN SMALL LETTER E WITH ACUTE - '\'e' => 'é', // LATIN SMALL LETTER E WITH ACUTE - 'e^' => 'ê', // LATIN SMALL LETTER E WITH CIRCUMFLEX - '^e' => 'ê', // LATIN SMALL LETTER E WITH CIRCUMFLEX - 'e"' => 'ë', // LATIN SMALL LETTER E WITH DIAERESIS - '"e' => 'ë', // LATIN SMALL LETTER E WITH DIAERESIS - 'i`' => 'ì', // LATIN SMALL LETTER I WITH GRAVE - '`i' => 'ì', // LATIN SMALL LETTER I WITH GRAVE - 'i\'' => 'í', // LATIN SMALL LETTER I WITH ACUTE - '\'i' => 'í', // LATIN SMALL LETTER I WITH ACUTE - 'i^' => 'î', // LATIN SMALL LETTER I WITH CIRCUMFLEX - '^i' => 'î', // LATIN SMALL LETTER I WITH CIRCUMFLEX - 'i"' => 'ï', // LATIN SMALL LETTER I WITH DIAERESIS - '"i' => 'ï', // LATIN SMALL LETTER I WITH DIAERESIS - 'n~' => 'ñ', // LATIN SMALL LETTER N WITH TILDE - '~n' => 'ñ', // LATIN SMALL LETTER N WITH TILDE - 'o`' => 'ò', // LATIN SMALL LETTER O WITH GRAVE - '`o' => 'ò', // LATIN SMALL LETTER O WITH GRAVE - 'o\'' => 'ó', // LATIN SMALL LETTER O WITH ACUTE - '\'o' => 'ó', // LATIN SMALL LETTER O WITH ACUTE - 'o^' => 'ô', // LATIN SMALL LETTER O WITH CIRCUMFLEX - '^o' => 'ô', // LATIN SMALL LETTER O WITH CIRCUMFLEX - 'o~' => 'õ', // LATIN SMALL LETTER O WITH TILDE - '~o' => 'õ', // LATIN SMALL LETTER O WITH TILDE - 'o"' => 'ö', // LATIN SMALL LETTER O WITH DIAERESIS - '"o' => 'ö', // LATIN SMALL LETTER O WITH DIAERESIS - ':-' => '÷', // DIVISION SIGN - '-:' => '÷', // DIVISION SIGN - 'o/' => 'ø', // LATIN SMALL LETTER O WITH STROKE - '/o' => 'ø', // LATIN SMALL LETTER O WITH STROKE - 'u`' => 'ù', // LATIN SMALL LETTER U WITH GRAVE - '`u' => 'ù', // LATIN SMALL LETTER U WITH GRAVE - 'u\'' => 'ú', // LATIN SMALL LETTER U WITH ACUTE - '\'u' => 'ú', // LATIN SMALL LETTER U WITH ACUTE - 'u^' => 'û', // LATIN SMALL LETTER U WITH CIRCUMFLEX - '^u' => 'û', // LATIN SMALL LETTER U WITH CIRCUMFLEX - 'u"' => 'ü', // LATIN SMALL LETTER U WITH DIAERESIS - '"u' => 'ü', // LATIN SMALL LETTER U WITH DIAERESIS - 'y\'' => 'ý', // LATIN SMALL LETTER Y WITH ACUTE - '\'y' => 'ý', // LATIN SMALL LETTER Y WITH ACUTE - 'y"' => 'ÿ', // LATIN SMALL LETTER Y WITH DIAERESIS - '"y' => 'ÿ', // LATIN SMALL LETTER Y WITH DIAERESIS - 'OE' => 'Œ', // LATIN CAPITAL LIGATURE OE - 'oe' => 'œ', // LATIN SMALL LIGATURE OE - '*' => '•', // BULLET - 'Fr' => '₣', // FRENCH FRANC SIGN - 'L=' => '₤', // LIRA SIGN - '=L' => '₤', // LIRA SIGN - 'Rs' => '₨', // RUPEE SIGN - 'C=' => '€', // EURO SIGN - '=C' => '€', // EURO SIGN - 'tm' => '™', // TRADE MARK SIGN - '<-' => '←', // LEFTWARDS ARROW - '->' => '→', // RIGHTWARDS ARROW - '<=' => '⇐', // LEFTWARDS DOUBLE ARROW - '=>' => '⇒', // RIGHTWARDS DOUBLE ARROW - '=/' => '≠', // NOT EQUAL TO - '/=' => '≠', // NOT EQUAL TO - '<_' => '≤', // LESS-THAN OR EQUAL TO - '_<' => '≤', // LESS-THAN OR EQUAL TO - '>_' => '≥', // GREATER-THAN OR EQUAL TO - '_>' => '≥', // GREATER-THAN OR EQUAL TO - ':(' => '☹', // WHITE FROWNING FACE - ':)' => '☺', // WHITE SMILING FACE - 'spade' => '♠', // BLACK SPADE SUIT - 'club' => '♣', // BLACK CLUB SUIT - 'heart' => '♥', // BLACK HEART SUIT - 'diamond' => '♦', // BLACK DIAMOND SUIT - ); - } // function default_macros - - // "private", internal routines - - /** - * Sets the default CSS names for CSS controlled markup. This - * is an internal function that should not be called directly. - * - * @private - */ - function _css_defaults() { - $css_defaults = array( - 'class_align_right' => 'right', - 'class_align_left' => 'left', - 'class_align_center' => 'center', - 'class_align_top' => 'top', - 'class_align_bottom' => 'bottom', - 'class_align_middle' => 'middle', - 'class_align_justify' => 'justify', - 'class_caps' => 'caps', - 'class_footnote' => 'footnote', - 'id_footnote_prefix' => 'fn', - ); - $this->css($css_defaults); - } // function _css_defaults - - /** - * Returns the alignment keyword depending on the symbol passed. - * - *
      - * - *
    • \<\> - * - * becomes 'justify'
    • - * - *
    • \< - * - * becomes 'left'
    • - * - *
    • \> - * - * becomes 'right'
    • - * - *
    • = - * - * becomes 'center'
    • - * - *
    - * - * @param $align A @c string specifying the alignment code. - * - * @return A @c string containing the alignment text. - * - * @private - */ - function _halign($align) { - if (preg_match('/<>/', $align)) { - return 'justify'; - } elseif (preg_match('//', $align)) { - return 'right'; - } elseif (preg_match('/=/', $align)) { - return 'center'; - } - return ''; - } // function _halign - - /** - * Returns the alignment keyword depending on the symbol passed. - * - *
      - * - *
    • ^ - * - * becomes 'top'
    • - * - *
    • ~ - * - * becomes 'bottom'
    • - * - *
    • - - * - * becomes 'middle'
    • - * - *
    - * - * @param $align A @c string specifying the alignment code. - * - * @return A @c string containing the alignment text. - * - * @private - */ - function _valign($align) { - if (preg_match('/\^/', $align)) { - return 'top'; - } elseif (preg_match('/~/', $align)) { - return 'bottom'; - } elseif (preg_match('/-/', $align)) { - return 'middle'; - } - return ''; - } // function _valign - - /** - * Returns the alignment keyword depending on the symbol passed. - * The following alignment symbols are recognized, and given - * preference in the order listed: - * - *
      - * - *
    • ^ - * - * becomes 'top'
    • - * - *
    • ~ - * - * becomes 'bottom'
    • - * - *
    • - - * - * becomes 'middle'
    • - * - *
    • \< - * - * becomes 'left'
    • - * - *
    • \> - * - * becomes 'right'
    • - * - *
    - * - * @param $align A @c string containing the alignment code. - * - * @return A @c string containing the alignment text. - * - * @private - */ - function _imgalign($align) { - $align = preg_replace('/(<>|=)/', '', $align); - return ($this->_valign($align) ? $this->_valign($align) : $this->_halign($align)); - } // function _imgalign - - /** - * This utility routine will take 'border' characters off of - * the given @c $pre and @c $post strings if they match one of these - * conditions: - *
    -   *     $pre starts with '[', $post ends with ']'
    -   *     $pre starts with '{', $post ends with '}'
    -   * 
    - * If neither condition is met, then the @c $pre and @c $post - * values are left untouched. - * - * @param $pre A @c string specifying the prefix. - * @param $post A @c string specifying the postfix. - * - * @private - */ - function _strip_borders(&$pre, &$post) { - if ($post && $pre && preg_match('/[{[]/', ($open = substr($pre, 0, 1)))) { - $close = substr($post, 0, 1); - if ((($open == '{') && ($close == '}')) || - (($open == '[') && ($close == ']'))) { - $pre = substr($pre, 1); - $post = substr($post, 1); - } else { - if (!preg_match('/[}\]]/', $close)) { $close = substr($post, -1, 1); } - if ((($open == '{') && ($close == '}')) || - (($open == '[') && ($close == ']'))) { - $pre = substr($pre, 1); - $post = substr($post, 0, strlen($post) - 1); - } - } - } - } // function _strip_borders - - /** - * An internal routine that takes a string and appends it to an array. - * It returns a marker that is used later to restore the preserved - * string. - * - * @param $array The @c array in which to store the replacement - * text. - * @param $str A @c string specifying the replacement text. - * - * @return A @c string containing a temporary marker for the - * replacement. - * - * @private - */ - function _repl(&$array, $str) { - $array[] = $str; - return ''; - } // function _repl - - /** - * An internal routine responsible for breaking up a string into - * individual tag and plaintext elements. - * - * @param $str A @c string specifying the text to tokenize. - * - * @return An @c array containing the tag and text tokens. - * - * @private - */ - function _tokenize($str) { - $pos = 0; - $len = strlen($str); - unset($tokens); - - $depth = 6; - $nested_tags = substr(str_repeat('(?:]|', $depth), 0, -1) - . str_repeat(')*>)', $depth); - $match = '(?s: )| # comment - (?s: <\? .*? \?> )| # processing instruction - (?s: <% .*? %> )| # ASP-like - (?:' . $nested_tags . ')| - (?:' . $this->codere . ')'; // nested tags - - while (preg_match('{(' . $match . ')}x', substr($str, $pos), $matches, PREG_OFFSET_CAPTURE)) { - $whole_tag = $matches[1][0]; - $sec_start = $pos + $matches[1][1] + strlen($whole_tag); - $tag_start = $sec_start - strlen($whole_tag); - if ($pos < $tag_start) { - $tokens[] = array('text', substr($str, $pos, $tag_start - $pos)); - } - if (preg_match('/^[[{]?@/', $whole_tag)) { - $tokens[] = array('text', $whole_tag); - } else { - // this clever hack allows us to preserve \n within tags. - // this is restored at the end of the format_paragraph method - //$whole_tag = preg_replace('/\n/', "\r", $whole_tag); - $whole_tag = preg_replace('/\n/', "\001", $whole_tag); - $tokens[] = array('tag', $whole_tag); - } - $pos = $sec_start; - } - if ($pos < $len) { $tokens[] = array('text', substr($str, $pos, $len - $pos)); } - return $tokens; - } // function _tokenize - - /** - * Returns the version of this release of Textile.php. *JHR* - * - * @return An @c array with keys 'text' and 'build' containing the - * text version and build ID of this release, respectively. - * - * @static - */ - function version() { - /* Why text and an ID? Well, the text is easier for the user to - * read and understand while the build ID, being a number (a date - * with a serial, specifically), is easier for the developer to - * use to determine newer/older versions for upgrade and - * installation purposes. - */ - return array("text" => "2.0.8", "build" => 2005032100); - } // function version - -/** - * Creates a custom callback function from the provided PHP - * code. The result is used as the callback in - * @c preg_replace_callback calls. *JHR* - * - * @param $function A @c string specifying the PHP code for the - * function body. - * - * @return A @c function to be used for the callback. - * - * @private - */ - function _cb($function) { - $current =& Textile::_current_store($this); - return create_function('$m', '$me =& Textile::_current(); return ' . $function . ';'); - } // function _cb - - /** - * Stores a static variable for the Textile class. This helper - * function is used by @c _current to simulate a static - * class variable in PHP. *JHR* - * - * @param $new If a non-@c NULL object reference, the Textile object - * to be set as the current object. - * - * @return The @c array containing a reference to the current - * Textile object at index 0. An array is used because PHP - * does not allow static variables to be references. - * - * @static - * @private - */ - /* static */ function &_current_store(&$new) { - static $current = array(); - - if ($new != NULL) { - $current = array(&$new); - } - - return $current; - } // function _current_store - - /** - * Returns the "current" Textile object. This is used within - * anonymous callback functions which cannot have the scope of a - * specific object. *JHR* - * - * @return An @c object reference to the current Textile object. - * - * @static - * @private - */ - /* static */ function &_current() { - $current =& Textile::_current_store($null = NULL); - return $current[0]; - } // function _current -} // class Textile - -/** - * Brad Choate's mttextile Movable Type plugin adds some additional - * functionality to the Textile.pm Perl module. This includes optional - * "SmartyPants" processing of text to produce smart quotes, dashes, - * etc., code colorizing using Beautifier, and some special lookup - * links (imdb, google, dict, and amazon). The @c MTLikeTextile class - * is a subclass of @c Textile that provides an MT-like implementation - * of Textile to produce results similar to that of the mttextile - * plugin. Currently only the SmartyPants and special lookup links are - * implemented. - * - * Using the @c MTLikeTextile class is exactly the same as using @c - * Textile. Simply use $textile = new MTLikeTextile; - * instead of $textile = new Textile; to create a Textile - * object. This will enable the special lookup links. To enable - * SmartyPants processing, you must install the SmartyPants-PHP - * implementation available at - * http://monauraljerk.org/smartypants-php/ - * and include the - * SmartyPants-PHP.inc file. - * - *
    
    - * include_once("Textile.php");
    - * include_once("SmartyPants-PHP.inc");
    - * $text = \<\<\process($text);
    - * print $html;
    - * 
    - * - * @brief A Textile implementation providing additional - * Movable-Type-like formatting to produce results similar to - * the mttextile plugin. - * - * @author Jim Riggs \ - */ -class MTLikeTextile extends Textile { - /** - * Instantiates a new MTLikeTextile object. Optional options - * can be passed to initialize the object. Attributes for the - * options key are the same as the get/set method names - * documented here. - * - * @param $options The @c array specifying the options to use for - * this object. - * - * @public - */ - function MTLikeTextile($options = array()) { - parent::Textile($options); - } // function MTLikeTextile - - /** - * @private - */ - function process_quotes($str) { - if (!$this->options['do_quotes'] || !function_exists('SmartyPants')) { - return $str; - } - - return SmartyPants($str, $this->options['smarty_mode']); - } // function process_quotes - - /** - * @private - */ - function format_url($args) { - $url = ($args['url'] ? $args['url'] : ''); - - if (preg_match('/^(imdb|google|dict|amazon)(:(.+))?$/x', $url, $matches)) { - $term = $matches[3]; - $term = ($term ? $term : strip_tags($args['linktext'])); - - switch ($matches[1]) { - case 'imdb': - $args['url'] = 'http://www.imdb.com/Find?for=' . $term; - break; - - case 'google': - $args['url'] = 'http://www.google.com/search?q=' . $term; - break; - - case 'dict': - $args['url'] = 'http://www.dictionary.com/search?q=' . $term; - break; - - case 'amazon': - $args['url'] = 'http://www.amazon.com/exec/obidos/external-search?index=blended&keyword=' . $term; - break; - } - } - - return parent::format_url($args); - } // function format_url -} // class MTLikeTextile - -/** - * @mainpage - * Textile - A Humane Web Text Generator. - * - * @section synopsis SYNOPSIS - * - *
    
    - * include_once("Textile.php");
    - * $text = \<\<\process($text);
    - * print $html;
    - * 
    - * - * @section abstract ABSTRACT - * - * Textile.php is a PHP-based implementation of Dean Allen's Textile - * syntax. Textile is shorthand for doing common formatting tasks. - * - * @section syntax SYNTAX - * - * Textile processes text in units of blocks and lines. - * A block might also be considered a paragraph, since blocks - * are separated from one another by a blank line. Blocks - * can begin with a signature that helps identify the rest - * of the block content. Block signatures include: - * - *
      - * - *
    • p - * - * A paragraph block. This is the default signature if no - * signature is explicitly given. Paragraphs are formatted - * with all the inline rules (see inline formatting) and - * each line receives the appropriate markup rules for - * the flavor of HTML in use. For example, newlines for XHTML - * content receive a \
      tag at the end of the line - * (with the exception of the last line in the paragraph). - * Paragraph blocks are enclosed in a \ tag.
    • - * - *
    • pre - * - * A pre-formatted block of text. Textile will not add any - * HTML tags for individual lines. Whitespace is also preserved. - * - * Note that within a "pre" block, \< and \> are - * translated into HTML entities automatically.
    • - * - *
    • bc - * - * A "bc" signature is short for "block code", which implies - * a preformatted section like the 'pre' block, but it also - * gets a \ tag (or for XHTML 2, a \ - * tag is used instead). - * - * Note that within a "bc" block, \< and \> are - * translated into HTML entities automatically.
    • - * - *
    • table - * - * For composing HTML tables. See the "TABLES" section for more - * information.
    • - * - *
    • bq - * - * A "bq" signature is short for "block quote". Paragraph text - * formatting is applied to these blocks and they are enclosed - * in a \ tag as well as \ tags - * within.
    • - * - *
    • h1, h2, h3, h4, h5, h6 - * - * Headline signatures that produce \, etc. tags. - * You can adjust the relative output of these using the - * head_offset attribute.
    • - * - *
    • clear - * - * A 'clear' signature is simply used to indicate that the next - * block should emit a CSS style attribute that clears any - * floating elements. The default behavior is to clear "both", - * but you can use the left (\< or right \>) alignment - * characters to indicate which side to clear.
    • - * - *
    • dl - * - * A "dl" signature is short for "definition list". See the - * "LISTS" section for more information.
    • - * - *
    • fn - * - * A "fn" signature is short for "footnote". You add a number - * following the "fn" keyword to number the footnote. Footnotes - * are output as paragraph tags but are given a special CSS - * class name which can be used to style them as you see fit.
    • - * - *
    - * - * All signatures should end with a period and be followed - * with a space. Inbetween the signature and the period, you - * may use several parameters to further customize the block. - * These include: - * - *
      - * - *
    • {style rule} - * - * A CSS style rule. Style rules can span multiple lines.
    • - * - *
    • [ll] - * - * A language identifier (for a "lang" attribute).
    • - * - *
    • (class) or (#id) or (class#id) - * - * For CSS class and id attributes.
    • - * - *
    • \>, \<, =, \<\> - * - * Modifier characters for alignment. Right-justification, left-justification, - * centered, and full-justification.
    • - * - *
    • ( (one or more) - * - * Adds padding on the left. 1em per "(" character is applied. - * When combined with the align-left or align-right modifier, - * it makes the block float.
    • - * - *
    • ) (one or more) - * - * Adds padding on the right. 1em per ")" character is applied. - * When combined with the align-left or align-right modifier, - * it makes the block float.
    • - * - *
    • |filter| or |filter|filter|filter| - * - * A filter may be invoked to further format the text for this - * signature. If one or more filters are identified, the text - * will be processed first using the filters and then by - * Textile's own block formatting rules.
    • - * - *
    - * - * @subsection extendedblocks Extended Blocks - * - * Normally, a block ends with the first blank line encountered. - * However, there are situations where you may want a block to continue - * for multiple paragraphs of text. To cause a given block signature - * to stay active, use two periods in your signature instead of one. - * This will tell Textile to keep processing using that signature - * until it hits the next signature is found. - * - * For example: - *
    - *     bq.. This is paragraph one of a block quote.
    - *
    - *     This is paragraph two of a block quote.
    - *
    - *     p. Now we're back to a regular paragraph.
    - * 
    - * You can apply this technique to any signature (although for - * some it doesn't make sense, like "h1" for example). This is - * especially useful for "bc" blocks where your code may - * have many blank lines scattered through it. - * - * @subsection escaping Escaping - * - * Sometimes you want Textile to just get out of the way and - * let you put some regular HTML markup in your document. You - * can disable Textile formatting for a given block using the '==' - * escape mechanism: - *
    - *     p. Regular paragraph
    - *
    - *     ==
    - *     Escaped portion -- will not be formatted
    - *     by Textile at all
    - *     ==
    - *
    - *     p. Back to normal.
    - * 
    - * You can also use this technique within a Textile block, - * temporarily disabling the inline formatting functions: - *
    - *     p. This is ==*a test*== of escaping.
    - * 
    - * @subsection inlineformatting Inline Formatting - * - * Formatting within a block of text is covered by the "inline" - * formatting rules. These operators must be placed up against - * text/punctuation to be recognized. These include: - * - *
      - * - *
    • *strong* - * - * Translates into \strong\.
    • - * - *
    • _emphasis_ - * - * Translates into \emphasis\.
    • - * - *
    • **bold** - * - * Translates into \bold\.
    • - * - *
    • __italics__ - * - * Translates into \italics\.
    • - * - *
    • ++bigger++ - * - * Translates into \bigger\.
    • - * - *
    • --smaller-- - * - * Translates into: \smaller\.
    • - * - *
    • -deleted text- - * - * Translates into \deleted text\.
    • - * - *
    • +inserted text+ - * - * Translates into \inserted text\.
    • - * - *
    • ^superscript^ - * - * Translates into \superscript\.
    • - * - *
    • ~subscript~ - * - * Translates into \subscript\.
    • - * - *
    • \%span\% - * - * Translates into \span\.
    • - * - *
    • \@code\@ - * - * Translates into \code\. Note - * that within a '\@...\@' section, \< and \> are - * translated into HTML entities automatically.
    • - * - *
    - * - * Inline formatting operators accept the following modifiers: - * - *
      - * - *
    • {style rule} - * - * A CSS style rule.
    • - * - *
    • [ll] - * - * A language identifier (for a "lang" attribute).
    • - * - *
    • (class) or (#id) or (class#id) - * - * For CSS class and id attributes.
    • - * - *
    - * - * @subsubsection examples Examples - *
    - *     Textile is *way* cool.
    - *
    - *     Textile is *_way_* cool.
    - * 
    - * Now this won't work, because the formatting - * characters need whitespace before and after - * to be properly recognized. - *
    - *     Textile is way c*oo*l.
    - * 
    - * However, you can supply braces or brackets to - * further clarify that you want to format, so - * this would work: - *
    - *     Textile is way c[*oo*]l.
    - * 
    - * @subsection footnotes Footnotes - * - * You can create footnotes like this: - *
    - *     And then he went on a long trip[1].
    - * 
    - * By specifying the brackets with a number inside, Textile will - * recognize that as a footnote marker. It will replace that with - * a construct like this: - *
    - *     And then he went on a long
    - *     trip1
    - * 
    - * To supply the content of the footnote, place it at the end of your - * document using a "fn" block signature: - *
    - *     fn1. And there was much rejoicing.
    - * 
    - * Which creates a paragraph that looks like this: - *
    - *     

    1 And there was - * much rejoicing.

    - *
    - * @subsection links Links - * - * Textile defines a shorthand for formatting hyperlinks. - * The format looks like this: - *
    - *     "Text to display":http://example.com
    - * 
    - * In addition to this, you can add 'title' text to your link: - *
    - *     "Text to display (Title text)":http://example.com
    - * 
    - * The URL portion of the link supports relative paths as well - * as other protocols like ftp, mailto, news, telnet, etc. - *
    - *     "E-mail me please":mailto:someone\@example.com
    - * 
    - * You can also use single quotes instead of double-quotes if - * you prefer. As with the inline formatting rules, a hyperlink - * must be surrounded by whitespace to be recognized (an - * exception to this is common punctuation which can reside - * at the end of the URL). If you have to place a URL next to - * some other text, use the bracket or brace trick to do that: - *
    - *     You["gotta":http://example.com]seethis!
    - * 
    - * Textile supports an alternate way to compose links. You can - * optionally create a lookup list of links and refer to them - * separately. To do this, place one or more links in a block - * of it's own (it can be anywhere within your document): - *
    - *     [excom]http://example.com
    - *     [exorg]http://example.org
    - * 
    - * For a list like this, the text in the square brackets is - * used to uniquely identify the link given. To refer to that - * link, you would specify it like this: - *
    - *     "Text to display":excom
    - * 
    - * Once you've defined your link lookup table, you can use - * the identifiers any number of times. - * - * @subsection images Images - * - * Images are identified by the following pattern: - *
    - *     !/path/to/image!
    - * 
    - * Image attributes may also be specified: - *
    - *     !/path/to/image 10x20!
    - * 
    - * Which will render an image 10 pixels wide and 20 pixels high. - * Another way to indicate width and height: - *
    - *     !/path/to/image 10w 20h!
    - * 
    - * You may also redimension the image using a percentage. - *
    - *     !/path/to/image 20%x40%!
    - * 
    - * Which will render the image at 20% of it's regular width - * and 40% of it's regular height. - * - * Or specify one percentage to resize proprotionately: - *
    - *     !/path/to/image 20%!
    - * 
    - * Alt text can be given as well: - *
    - *     !/path/to/image (Alt text)!
    - * 
    - * The path of the image may refer to a locally hosted image or - * can be a full URL. - * - * You can also use the following modifiers after the opening '!' - * character: - * - *
      - * - *
    • \< - * - * Align the image to the left (causes the image to float if - * CSS options are enabled).
    • - * - *
    • \> - * - * Align the image to the right (causes the image to float if - * CSS options are enabled).
    • - * - *
    • - (dash) - * - * Aligns the image to the middle.
    • - * - *
    • ^ - * - * Aligns the image to the top.
    • - * - *
    • ~ (tilde) - * - * Aligns the image to the bottom.
    • - * - *
    • {style rule} - * - * Applies a CSS style rule to the image.
    • - * - *
    • (class) or (#id) or (class#id) - * - * Applies a CSS class and/or id to the image.
    • - * - *
    • ( (one or more) - * - * Pads 1em on the left for each '(' character.
    • - * - *
    • ) (one or more) - * - * Pads 1em on the right for each ')' character.
    • - * - *
    - * - * @subsection characterreplacements Character Replacements - * - * A few simple, common symbols are automatically replaced: - *
    - *     (c)
    - *     (r)
    - *     (tm)
    - * 
    - * In addition to these, there are a whole set of character - * macros that are defined by default. All macros are enclosed - * in curly braces. These include: - *
    - *     {c|} or {|c} cent sign
    - *     {L-} or {-L} pound sign
    - *     {Y=} or {=Y} yen sign
    - * 
    - * Many of these macros can be guessed. For example: - *
    - *     {A'} or {'A}
    - *     {a"} or {"a}
    - *     {1/4}
    - *     {*}
    - *     {:)}
    - *     {:(}
    - * 
    - * @subsection lists Lists - * - * Textile also supports ordered and unordered lists. - * You simply place an asterisk or pound sign, followed - * with a space at the start of your lines. - * - * Simple lists: - *
    - *     * one
    - *     * two
    - *     * three
    - * 
    - * Multi-level lists: - *
    - *     * one
    - *     ** one A
    - *     ** one B
    - *     *** one B1
    - *     * two
    - *     ** two A
    - *     ** two B
    - *     * three
    - * 
    - * Ordered lists: - *
    - *     # one
    - *     # two
    - *     # three
    - * 
    - * Styling lists: - *
    - *     (class#id)* one
    - *     * two
    - *     * three
    - * 
    - * The above sets the class and id attributes for the \ - * tag. - *
    - *     *(class#id) one
    - *     * two
    - *     * three
    - * 
    - * The above sets the class and id attributes for the first \ - * tag. - * - * Definition lists: - *
    - *     dl. textile:a cloth, especially one manufactured by weaving
    - *     or knitting; a fabric
    - *     format:the arrangement of data for storage or display.
    - * 
    - * Note that there is no space between the term and definition. The - * term must be at the start of the line (or following the "dl" - * signature as shown above). - * - * @subsection tables Tables - * - * Textile supports tables. Tables must be in their own block and - * must have pipe characters delimiting the columns. An optional - * block signature of "table" may be used, usually for applying - * style, class, id or other options to the table element itself. - * - * From the simple: - *
    - *     |a|b|c|
    - *     |1|2|3|
    - * 
    - * To the complex: - *
    - *     table(fig). {color:red}_|Top|Row|
    - *     {color:blue}|/2. Second|Row|
    - *     |_{color:green}. Last|
    - * 
    - * Modifiers can be specified for the table signature itself, - * for a table row (prior to the first '|' character) and - * for any cell (following the '|' for that cell). Note that for - * cells, a period followed with a space must be placed after - * any modifiers to distinguish the modifier from the cell content. - * - * Modifiers allowed are: - * - *
      - * - *
    • {style rule} - * - * A CSS style rule.
    • - * - *
    • (class) or (#id) or (class#id) - * - * A CSS class and/or id attribute.
    • - * - *
    • ( (one or more) - * - * Adds 1em of padding to the left for each '(' character.
    • - * - *
    • ) (one or more) - * - * Adds 1em of padding to the right for each ')' character.
    • - * - *
    • \< - * - * Aligns to the left (floats to left for tables if combined with the - * ')' modifier).
    • - * - *
    • \> - * - * Aligns to the right (floats to right for tables if combined with - * the '(' modifier).
    • - * - *
    • = - * - * Aligns to center (sets left, right margins to 'auto' for tables).
    • - * - *
    • \<\> - * - * For cells only. Justifies text.
    • - * - *
    • ^ - * - * For rows and cells only. Aligns to the top.
    • - * - *
    • ~ (tilde) - * - * For rows and cells only. Aligns to the bottom.
    • - * - *
    • _ (underscore) - * - * Can be applied to a table row or cell to indicate a header - * row or cell.
    • - * - *
    • \\2 or \\3 or \\4, etc. - * - * Used within cells to indicate a colspan of 2, 3, 4, etc. columns. - * When you see "\\", think "push forward".
    • - * - *
    • /2 or /3 or /4, etc. - * - * Used within cells to indicate a rowspan of 2, 3, 4, etc. rows. - * When you see "/", think "push downward".
    • - * - *
    - * - * When a cell is identified as a header cell and an alignment - * is specified, that becomes the default alignment for - * cells below it. You can always override this behavior by - * specifying an alignment for one of the lower cells. - * - * @subsection cssnotes CSS Notes - * - * When CSS is enabled (and it is by default), CSS class names - * are automatically applied in certain situations. - * - *
      - * - *
    • Aligning a block or span or other element to - * left, right, etc. - * - * "left" for left justified, "right" for right justified, - * "center" for centered text, "justify" for full-justified - * text.
    • - * - *
    • Aligning an image to the top or bottom - * - * "top" for top alignment, "bottom" for bottom alignment, - * "middle" for middle alignment.
    • - * - *
    • Footnotes - * - * "footnote" is applied to the paragraph tag for the - * footnote text itself. An id of "fn" plus the footnote - * number is placed on the paragraph for the footnote as - * well. For the footnote superscript tag, a class of - * "footnote" is used.
    • - * - *
    • Capped text - * - * For a series of characters that are uppercased, a - * span is placed around them with a class of "caps".
    • - * - *
    - * - * @subsection miscellaneous Miscellaneous - * - * Textile tries to do it's very best to ensure proper XHTML - * syntax. It will even attempt to fix errors you may introduce - * writing in HTML yourself. Unescaped '&' characters within - * URLs will be properly escaped. Singlet tags such as br, img - * and hr are checked for the '/' terminator (and it's added - * if necessary). The best way to make sure you produce valid - * XHTML with Textile is to not use any HTML markup at all-- - * use the Textile syntax and let it produce the markup for you. - * - * @section license LICENSE - * - * Text::Textile is licensed under the same terms as Perl - * itself. Textile.php is licensed under the terms of the GNU General - * Public License. - * - * @section authorandcopyright AUTHOR & COPYRIGHT - * - * Text::Textile was written by Brad Choate, \. - * It is an adaptation of Textile, developed by Dean Allen of Textism.com. - * - * Textile.php is a PHP port of Brad Choate's Text::Textile - * (Textile.pm) Perl module. - * - * Textile.php was ported by Jim Riggs \. Great care has been taken to leave the Perl code in much the - * same form as Textile.pm. While changes were required due to - * syntactical differences between Perl and PHP, much of the code was - * left intact (even if alternative syntax or code optimizations could - * have been made in PHP), even to the point where one can compare - * functions/subroutines side by side between the two implementations. - * This has been done to ensure compatibility, reduce the possibility - * of introducing errors, and simplify maintainance as one version or - * the other is updated. - * - * @author Jim Riggs \ - * @author Brad Choate \ - * @copyright Copyright © 2004 Jim Riggs and Brad Choate - * @version @(#) $Id: Textile.php,v 1.13 2005/03/21 15:26:55 jhriggs Exp $ - */ -?> +TextileThis($string); + * + */ + +/* +$Id: classTextile.php 216 2006-10-17 22:31:53Z zem $ +$LastChangedRevision: 216 $ +*/ + +/* + +_____________ +T E X T I L E + +A Humane Web Text Generator + +Version 2.0 + +Copyright (c) 2003-2004, Dean Allen +All rights reserved. + +Thanks to Carlo Zottmann 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. + +_________ +U S A G E + +Block modifier syntax: + + Header: h(1-6). + Paragraphs beginning with 'hn. ' (where n is 1-6) are wrapped in header tags. + Example: h1. Header... ->

    Header...

    + + Paragraph: p. (also applied by default) + Example: p. Text ->

    Text

    + + Blockquote: bq. + Example: bq. Block quotation... ->
    Block quotation...
    + + Blockquote with citation: bq.:http://citation.url + Example: bq.:http://textism.com/ Text... + ->
    Text...
    + + Footnote: fn(1-100). + Example: fn1. Footnote... ->

    Footnote...

    + + Numeric list: #, ## + Consecutive paragraphs beginning with # are wrapped in ordered list tags. + Example:
    1. ordered list
    + + Bulleted list: *, ** + Consecutive paragraphs beginning with * are wrapped in unordered list tags. + Example:
    • unordered list
    + +Phrase modifier syntax: + + _emphasis_ -> emphasis + __italic__ -> italic + *strong* -> strong + **bold** -> bold + ??citation?? -> citation + -deleted text- -> deleted + +inserted text+ -> inserted + ^superscript^ -> superscript + ~subscript~ -> subscript + @code@ -> computer code + %(bob)span% -> span + + ==notextile== -> leave text alone (do not format) + + "linktext":url -> linktext + "linktext(title)":url -> linktext + + !imageurl! -> + !imageurl(alt text)! -> alt text + !imageurl!:linkurl -> + +ABC(Always Be Closing) -> ABC + + +Table syntax: + + Simple tables: + + |a|simple|table|row| + |And|Another|table|row| + + |_. A|_. table|_. header|_.row| + |A|simple|table|row| + + Tables with attributes: + + table{border:1px solid black}. + {background:#ddd;color:red}. |{}| | | | + + +Applying Attributes: + + Most anywhere Textile code is used, attributes such as arbitrary css style, + css classes, and ids can be applied. The syntax is fairly consistent. + + The following characters quickly alter the alignment of block elements: + + < -> left align ex. p<. left-aligned para + > -> right align h3>. right-aligned header 3 + = -> centred h4=. centred header 4 + <> -> justified p<>. justified paragraph + + These will change vertical alignment in table cells: + + ^ -> top ex. |^. top-aligned table cell| + - -> middle |-. middle aligned| + ~ -> bottom |~. bottom aligned cell| + + Plain (parentheses) inserted between block syntax and the closing dot-space + indicate classes and ids: + + p(hector). paragraph ->

    paragraph

    + + p(#fluid). paragraph ->

    paragraph

    + + (classes and ids can be combined) + p(hector#fluid). paragraph ->

    paragraph

    + + Curly {brackets} insert arbitrary css style + + p{line-height:18px}. paragraph ->

    paragraph

    + + h3{color:red}. header 3 ->

    header 3

    + + Square [brackets] insert language attributes + + p[no]. paragraph ->

    paragraph

    + + %[fr]phrase% -> phrase + + Usually Textile block element syntax requires a dot and space before the block + begins, but since lists don't, they can be styled just using braces + + #{color:blue} one ->
      + # big
    1. one
    2. + # list
    3. big
    4. +
    5. list
    6. +
    + + Using the span tag to style a phrase + + It goes like this, %{color:red}the fourth the fifth% + -> It goes like this, the fourth the fifth + +*/ + +// define these before including this file to override the standard glyphs +@define('txt_quote_single_open', '‘'); +@define('txt_quote_single_close', '’'); +@define('txt_quote_double_open', '“'); +@define('txt_quote_double_close', '”'); +@define('txt_apostrophe', '’'); +@define('txt_prime', '′'); +@define('txt_prime_double', '″'); +@define('txt_ellipsis', '…'); +@define('txt_emdash', '—'); +@define('txt_endash', '–'); +@define('txt_dimension', '×'); +@define('txt_trademark', '™'); +@define('txt_registered', '®'); +@define('txt_copyright', '©'); + +class Textile +{ + var $hlgn; + var $vlgn; + var $clas; + var $lnge; + var $styl; + var $cspn; + var $rspn; + var $a; + var $s; + var $c; + var $pnct; + var $rel; + var $fn; + + var $shelf = array(); + var $restricted = false; + var $noimage = false; + var $lite = false; + var $url_schemes = array(); + var $glyph = array(); + var $hu = ''; + + var $ver = '2.0.0'; + var $rev = '$Rev: 216 $'; + +// ------------------------------------------------------------- + function Textile() + { + $this->hlgn = "(?:\<(?!>)|(?|\<\>|\=|[()]+(?! ))"; + $this->vlgn = "[\-^~]"; + $this->clas = "(?:\([^)]+\))"; + $this->lnge = "(?:\[[^]]+\])"; + $this->styl = "(?:\{[^}]+\})"; + $this->cspn = "(?:\\\\\d+)"; + $this->rspn = "(?:\/\d+)"; + $this->a = "(?:{$this->hlgn}|{$this->vlgn})*"; + $this->s = "(?:{$this->cspn}|{$this->rspn})*"; + $this->c = "(?:{$this->clas}|{$this->styl}|{$this->lnge}|{$this->hlgn})*"; + + $this->pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]'; + $this->urlch = '[\w"$\-_.+!*\'(),";\/?:@=&%#{}|\\^~\[\]`]'; + + $this->url_schemes = array('http','https','ftp','mailto'); + + $this->btag = array('bq', 'bc', 'notextile', 'pre', 'h[1-6]', 'fn\d+', 'p'); + + $this->glyph = array( + 'quote_single_open' => txt_quote_single_open, + 'quote_single_close' => txt_quote_single_close, + 'quote_double_open' => txt_quote_double_open, + 'quote_double_close' => txt_quote_double_close, + 'apostrophe' => txt_apostrophe, + 'prime' => txt_prime, + 'prime_double' => txt_prime_double, + 'ellipsis' => txt_ellipsis, + 'emdash' => txt_emdash, + 'endash' => txt_endash, + 'dimension' => txt_dimension, + 'trademark' => txt_trademark, + 'registered' => txt_registered, + 'copyright' => txt_copyright, + ); + + if (defined('hu')) + $this->hu = hu; + + } + +// ------------------------------------------------------------- + function TextileThis($text, $lite='', $encode='', $noimage='', $strict='', $rel='') + { + if ($rel) + $this->rel = ' rel="'.$rel.'" '; + $this->lite = $lite; + $this->noimage = $noimage; + + if ($encode) { + $text = $this->incomingEntities($text); + $text = str_replace("x%x%", "&", $text); + return $text; + } else { + + if(!$strict) { + $text = $this->cleanWhiteSpace($text); + } + + $text = $this->getRefs($text); + + if (!$lite) { + $text = $this->block($text); + } + + $text = $this->retrieve($text); + + // just to be tidy + $text = str_replace("
    ", "
    \n", $text); + + return $text; + } + } + +// ------------------------------------------------------------- + function TextileRestricted($text, $lite=1, $noimage=1, $rel='nofollow') + { + $this->restricted = true; + $this->lite = $lite; + $this->noimage = $noimage; + if ($rel) + $this->rel = ' rel="'.$rel.'" '; + + // escape any raw html + $text = $this->encode_html($text, 0); + + $text = $this->cleanWhiteSpace($text); + $text = $this->getRefs($text); + + if ($lite) { + $text = $this->blockLite($text); + } + else { + $text = $this->block($text); + } + + $text = $this->retrieve($text); + + // just to be tidy + $text = str_replace("
    ", "
    \n", $text); + + return $text; + } + +// ------------------------------------------------------------- + function pba($in, $element = "") // "parse block attributes" + { + $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' or $element == 'tr') { + if (preg_match("/($this->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)) { + // $this->dump($pr); + $style[] = "padding-right:" . strlen($pr[1]) . "em;"; + $matched = str_replace($pr[0], '', $matched); + } + + if (preg_match("/($this->hlgn)/", $matched, $horiz)) + $style[] = "text-align:" . $this->hAlign($horiz[1]) . ";"; + + if (preg_match("/^(.*)#(.*)$/", $class, $ids)) { + $id = $ids[2]; + $class = $ids[1]; + } + + if ($this->restricted) + return ($lang) ? ' lang="' . $lang .'"':''; + + return join('',array( + ($style) ? ' style="' . join("", $style) .'"':'', + ($class) ? ' class="' . $class .'"':'', + ($lang) ? ' lang="' . $lang .'"':'', + ($id) ? ' id="' . $id .'"':'', + ($colspan) ? ' colspan="' . $colspan .'"':'', + ($rowspan) ? ' rowspan="' . $rowspan .'"':'' + )); + } + return ''; + } + +// ------------------------------------------------------------- + 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('@<(hr|br)[^>]*?/>@', '', $r)); + return '' != $r; + } + +// ------------------------------------------------------------- + function table($text) + { + $text = $text . "\n\n"; + return preg_replace_callback("/^(?:table(_?{$this->s}{$this->a}{$this->c})\. ?\n)?^({$this->a}{$this->c}\.? ?\|.*\|)\n\n/smU", + array(&$this, "fTable"), $text); + } + +// ------------------------------------------------------------- + function fTable($matches) + { + $tatts = $this->pba($matches[1], 'table'); + + foreach(preg_split("/\|$/m", $matches[2], -1, PREG_SPLIT_NO_EMPTY) as $row) { + if (preg_match("/^($this->a$this->c\. )(.*)/m", ltrim($row), $rmtch)) { + $ratts = $this->pba($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("/^(_?$this->s$this->a$this->c\. )(.*)/", $cell, $cmtch)) { + $catts = $this->pba($cmtch[1], 'td'); + $cell = $cmtch[2]; + } else $catts = ''; + + $cell = $this->graf($this->span($cell)); + + if (trim($cell) != '') + $cells[] = "\t\t\t$cell"; + } + $rows[] = "\t\t\n" . join("\n", $cells) . ($cells ? "\n" : "") . "\t\t"; + unset($cells, $catts); + } + return "\t\n" . join("\n", $rows) . "\n\t\n\n"; + } + +// ------------------------------------------------------------- + function lists($text) + { + return preg_replace_callback("/^([#*]+$this->c .*)$(?![^#*])/smU", array(&$this, "fList"), $text); + } + +// ------------------------------------------------------------- + function fList($m) + { + $text = explode("\n", $m[0]); + foreach($text as $line) { + $nextline = next($text); + if (preg_match("/^([#*]+)($this->a$this->c) (.*)$/s", $line, $m)) { + list(, $tl, $atts, $content) = $m; + $nl = ''; + if (preg_match("/^([#*]+)\s.*/", $nextline, $nm)) + $nl = $nm[1]; + if (!isset($lists[$tl])) { + $lists[$tl] = true; + $atts = $this->pba($atts); + $line = "\t<" . $this->lT($tl) . "l$atts>\n\t\t
  • " . $this->graf($content); + } else { + $line = "\t\t
  • " . $this->graf($content); + } + + if(strlen($nl) <= strlen($tl)) $line .= "
  • "; + foreach(array_reverse($lists) as $k => $v) { + if(strlen($k) > strlen($nl)) { + $line .= "\n\tlT($k) . "l>"; + if(strlen($k) > 1) + $line .= ""; + unset($lists[$k]); + } + } + } + $out[] = $line; + } + return join("\n", $out); + } + +// ------------------------------------------------------------- + function lT($in) + { + return preg_match("/^#+/", $in) ? 'o' : 'u'; + } + +// ------------------------------------------------------------- + function doPBr($in) + { + return preg_replace_callback('@<(p)([^>]*?)>(.*)()@s', array(&$this, 'doBr'), $in); + } + +// ------------------------------------------------------------- + function doBr($m) + { + $content = preg_replace("@(.+)(?|
    )\n(?![#*\s|])@", '$1
    ', $m[3]); + return '<'.$m[1].$m[2].'>'.$content.$m[4]; + } + +// ------------------------------------------------------------- + function block($text) + { + $find = $this->btag; + $tre = join('|', $find); + + $text = explode("\n\n", $text); + + $tag = 'p'; + $atts = $cite = $graf = $ext = ''; + + foreach($text as $line) { + $anon = 0; + if (preg_match("/^($tre)($this->a$this->c)\.(\.?)(?::(\S+))? (.*)$/s", $line, $m)) { + // last block was extended, so close it + if ($ext) + $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 or !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' and !$this->hasRawText($content)) { + $line = $content; + } + else { + $line = $o2.$content.$c2; + } + } + else { + $line = $this->graf($line); + } + } + + $line = $this->doPBr($line); + $line = preg_replace('/
    /', '
    ', $line); + + if ($ext and $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 join("\n\n", $out); + } + + + +// ------------------------------------------------------------- + function fBlock($m) + { + // $this->dump($m); + list(, $tag, $atts, $ext, $cite, $content) = $m; + $atts = $this->pba($atts); + + $o1 = $o2 = $c2 = $c1 = ''; + + if (preg_match("/fn(\d+)/", $tag, $fns)) { + $tag = 'p'; + $fnid = empty($this->fn[$fns[1]]) ? $fns[1] : $this->fn[$fns[1]]; + $atts .= ' id="fn' . $fnid . '"'; + if (strpos($atts, 'class=') === false) + $atts .= ' class="footnote"'; + $content = '' . $fns[1] . ' ' . $content; + } + + if ($tag == "bq") { + $cite = $this->checkRefs($cite); + $cite = ($cite != '') ? ' cite="' . $cite . '"' : ''; + $o1 = "\t\n"; + $o2 = "\t\t"; + $c2 = "

    "; + $c1 = "\n\t"; + } + elseif ($tag == 'bc') { + $o1 = ""; + $o2 = ""; + $c2 = ""; + $c1 = ""; + $content = $this->shelve($this->encode_html(rtrim($content, "\n")."\n")); + } + elseif ($tag == 'notextile') { + $content = $this->shelve($content); + $o1 = $o2 = ''; + $c1 = $c2 = ''; + } + elseif ($tag == 'pre') { + $content = $this->shelve($this->encode_html(rtrim($content, "\n")."\n")); + $o1 = ""; + $o2 = $c2 = ''; + $c1 = ""; + } + else { + $o2 = "\t<$tag$atts>"; + $c2 = ""; + } + + $content = $this->graf($content); + + return array($o1, $o2, $content, $c2, $c1); + } + +// ------------------------------------------------------------- + function graf($text) + { + // handle normal paragraph text + if (!$this->lite) { + $text = $this->noTextile($text); + $text = $this->code($text); + } + + $text = $this->links($text); + if (!$this->noimage) + $text = $this->image($text); + + if (!$this->lite) { + $text = $this->lists($text); + $text = $this->table($text); + } + + $text = $this->span($text); + $text = $this->footnoteRef($text); + $text = $this->glyphs($text); + return rtrim($text, "\n"); + } + +// ------------------------------------------------------------- + function span($text) + { + $qtags = array('\*\*','\*','\?\?','-','__','_','%','\+','~','\^'); + $pnct = ".,\"'?!;:"; + + foreach($qtags as $f) { + $text = preg_replace_callback("/ + (?:^|(?<=[\s>$pnct])|([{[])) + ($f)(?!$f) + ({$this->c}) + (?::(\S+))? + ([^\s$f]+|\S[^$f\n]*[^\s$f\n]) + ([$pnct]*) + $f + (?:$|([\]}])|(?=[[:punct:]]{1,2}|\s)) + /x", array(&$this, "fSpan"), $text); + } + return $text; + } + +// ------------------------------------------------------------- + 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->pba($atts); + $atts .= ($cite != '') ? 'cite="' . $cite . '"' : ''; + + $out = "<$tag$atts>$content$end"; + +// $this->dump($out); + + return $out; + + } + +// ------------------------------------------------------------- + function links($text) + { + return preg_replace_callback('/ + (?:^|(?<=[\s>.$pnct\(])|([{[])) # $pre + " # start + (' . $this->c . ') # $atts + ([^"]+) # $text + \s? + (?:\(([^)]+)\)(?="))? # $title + ": + ('.$this->urlch.'+) # $url + (\/)? # $slash + ([^\w\/;]*) # $post + (?:([\]}])|(?=\s|$|\))) + /Ux', array(&$this, "fLink"), $text); + } + +// ------------------------------------------------------------- + function fLink($m) + { + list(, $pre, $atts, $text, $title, $url, $slash, $post) = $m; + + $url = $this->checkRefs($url); + + $atts = $this->pba($atts); + $atts .= ($title != '') ? ' title="' . $this->encode_html($title) . '"' : ''; + + if (!$this->noimage) + $text = $this->image($text); + + $text = $this->span($text); + $text = $this->glyphs($text); + + $url = $this->relURL($url); + + $out = 'rel . '>' . $text . '' . $post; + + // $this->dump($out); + return $this->shelve($out); + + } + +// ------------------------------------------------------------- + function getRefs($text) + { + return preg_replace_callback("/(?<=^|\s)\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/U", + array(&$this, "refs"), $text); + } + +// ------------------------------------------------------------- + function refs($m) + { + list(, $flag, $url) = $m; + $this->urlrefs[$flag] = $url; + return ''; + } + +// ------------------------------------------------------------- + function checkRefs($text) + { + return (isset($this->urlrefs[$text])) ? $this->urlrefs[$text] : $text; + } + +// ------------------------------------------------------------- + function relURL($url) + { + $parts = parse_url($url); + if ((empty($parts['scheme']) or @$parts['scheme'] == 'http') and + empty($parts['host']) and + preg_match('/^\w/', @$parts['path'])) + $url = $this->hu.$url; + if ($this->restricted and !empty($parts['scheme']) and + !in_array($parts['scheme'], $this->url_schemes)) + return '#'; + return $url; + } + +// ------------------------------------------------------------- + function image($text) + { + return preg_replace_callback("/ + (?:[[{])? # pre + \! # opening ! + (\<|\=|\>)?? # optional alignment atts + ($this->c) # optional style,class atts + (?:\. )? # 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); + } + +// ------------------------------------------------------------- + function fImage($m) + { + list(, $algn, $atts, $url) = $m; + $atts = $this->pba($atts); + $atts .= ($algn != '') ? ' align="' . $this->iAlign($algn) . '"' : ''; + $atts .= (isset($m[4])) ? ' title="' . $m[4] . '"' : ''; + $atts .= (isset($m[4])) ? ' alt="' . $m[4] . '"' : ' alt=""'; + $size = @getimagesize($url); + if ($size) $atts .= " $size[3]"; + + $href = (isset($m[5])) ? $this->checkRefs($m[5]) : ''; + $url = $this->checkRefs($url); + + $url = $this->relURL($url); + + $out = array( + ($href) ? '' : '', + '', + ($href) ? '' : '' + ); + + return join('',$out); + } + +// ------------------------------------------------------------- + function code($text) + { + $text = $this->doSpecial($text, '', '', 'fCode'); + $text = $this->doSpecial($text, '@', '@', 'fCode'); + $text = $this->doSpecial($text, '
    ', '
    ', 'fPre'); + return $text; + } + +// ------------------------------------------------------------- + function fCode($m) + { + @list(, $before, $text, $after) = $m; + if ($this->restricted) + // $text is already escaped + return $before.$this->shelve(''.$text.'').$after; + else + return $before.$this->shelve(''.$this->encode_html($text).'').$after; + } + +// ------------------------------------------------------------- + function fPre($m) + { + @list(, $before, $text, $after) = $m; + if ($this->restricted) + // $text is already escaped + return $before.'
    '.$this->shelve($text).'
    '.$after; + else + return $before.'
    '.$this->shelve($this->encode_html($text)).'
    '.$after; + } +// ------------------------------------------------------------- + function shelve($val) + { + $i = uniqid(rand()); + $this->shelf[$i] = $val; + return $i; + } + +// ------------------------------------------------------------- + function retrieve($text) + { + if (is_array($this->shelf)) + do { + $old = $text; + $text = strtr($text, $this->shelf); + } while ($text != $old); + + return $text; + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function incomingEntities($text) + { + return preg_replace("/&(?![#a-z0-9]+;)/i", "x%x%", $text); + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function encodeEntities($text) + { + return (function_exists('mb_encode_numericentity')) + ? $this->encode_high($text) + : htmlentities($text, ENT_NOQUOTES, "utf-8"); + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function fixEntities($text) + { + /* de-entify any remaining angle brackets or ampersands */ + return str_replace(array(">", "<", "&"), + array(">", "<", "&"), $text); + } + +// ------------------------------------------------------------- + function cleanWhiteSpace($text) + { + $out = str_replace("\r\n", "\n", $text); + $out = preg_replace("/\n{3,}/", "\n\n", $out); + $out = preg_replace("/\n *\n/", "\n\n", $out); + $out = preg_replace('/"$/', "\" ", $out); + return $out; + } + +// ------------------------------------------------------------- + function doSpecial($text, $start, $end, $method='fSpecial') + { + return preg_replace_callback('/(^|\s|[[({>])'.preg_quote($start, '/').'(.*?)'.preg_quote($end, '/').'(\s|$|[\])}])?/ms', + array(&$this, $method), $text); + } + +// ------------------------------------------------------------- + function fSpecial($m) + { + // A special block like notextile or code + @list(, $before, $text, $after) = $m; + return $before.$this->shelve($this->encode_html($text)).$after; + } + +// ------------------------------------------------------------- + function noTextile($text) + { + $text = $this->doSpecial($text, '', '', 'fTextile'); + return $this->doSpecial($text, '==', '==', 'fTextile'); + + } + +// ------------------------------------------------------------- + function fTextile($m) + { + @list(, $before, $notextile, $after) = $m; + #$notextile = str_replace(array_keys($modifiers), array_values($modifiers), $notextile); + return $before.$this->shelve($notextile).$after; + } + +// ------------------------------------------------------------- + function footnoteRef($text) + { + return preg_replace('/\b\[([0-9]+)\](\s)?/Ue', + '$this->footnoteID(\'\1\',\'\2\')', $text); + } + +// ------------------------------------------------------------- + function footnoteID($id, $t) + { + if (empty($this->fn[$id])) + $this->fn[$id] = uniqid(rand()); + $fnid = $this->fn[$id]; + return ''.$id.''.$t; + } + +// ------------------------------------------------------------- + function glyphs($text) + { + // fix: hackish + $text = preg_replace('/"\z/', "\" ", $text); + $pnc = '[[:punct:]]'; + + $glyph_search = array( + '/(\w)\'(\w)/', // apostrophe's + '/(\s)\'(\d+\w?)\b(?!\')/', // back in '88 + '/(\S)\'(?=\s|'.$pnc.'|<|$)/', // single closing + '/\'/', // single opening + '/(\S)\"(?=\s|'.$pnc.'|<|$)/', // 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 + ); + + extract($this->glyph, EXTR_PREFIX_ALL, 'txt'); + + $glyph_replace = array( + '$1'.$txt_apostrophe.'$2', // apostrophe's + '$1'.$txt_apostrophe.'$2', // back in '88 + '$1'.$txt_quote_single_close, // single closing + $txt_quote_single_open, // single opening + '$1'.$txt_quote_double_close, // double closing + $txt_quote_double_open, // double opening + '$1', // 3+ uppercase acronym + '$1', // 3+ uppercase + '$1'.$txt_ellipsis, // ellipsis + '$1'.$txt_emdash.'$2', // em dash + ' '.$txt_endash.' ', // en dash + '$1$2'.$txt_dimension.'$3', // dimension sign + $txt_trademark, // trademark + $txt_registered, // registered + $txt_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 join('', $glyph_out); + } + +// ------------------------------------------------------------- + function iAlign($in) + { + $vals = array( + '<' => 'left', + '=' => 'center', + '>' => 'right'); + return (isset($vals[$in])) ? $vals[$in] : ''; + } + +// ------------------------------------------------------------- + function hAlign($in) + { + $vals = array( + '<' => 'left', + '=' => 'center', + '>' => 'right', + '<>' => 'justify'); + return (isset($vals[$in])) ? $vals[$in] : ''; + } + +// ------------------------------------------------------------- + function vAlign($in) + { + $vals = array( + '^' => 'top', + '-' => 'middle', + '~' => 'bottom'); + return (isset($vals[$in])) ? $vals[$in] : ''; + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function encode_high($text, $charset = "UTF-8") + { + return mb_encode_numericentity($text, $this->cmap(), $charset); + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function decode_high($text, $charset = "UTF-8") + { + return mb_decode_numericentity($text, $this->cmap(), $charset); + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function cmap() + { + $f = 0xffff; + $cmap = array( + 0x0080, 0xffff, 0, $f); + return $cmap; + } + +// ------------------------------------------------------------- + function encode_html($str, $quotes=1) + { + $a = array( + '&' => '&', + '<' => '<', + '>' => '>', + ); + if ($quotes) $a = $a + array( + "'" => ''', + '"' => '"', + ); + + return strtr($str, $a); + } + +// ------------------------------------------------------------- + function textile_popup_help($name, $helpvar, $windowW, $windowH) + { + return ' ' . $name . '
    '; + + return $out; + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function txtgps($thing) + { + if (isset($_POST[$thing])) { + if (get_magic_quotes_gpc()) { + return stripslashes($_POST[$thing]); + } + else { + return $_POST[$thing]; + } + } + else { + return ''; + } + } + +// ------------------------------------------------------------- +// NOTE: deprecated + function dump() + { + foreach (func_get_args() as $a) + echo "\n
    ",(is_array($a)) ? print_r($a) : $a, "
    \n"; + } + +// ------------------------------------------------------------- + + function blockLite($text) + { + $this->btag = array('bq', 'p'); + return $this->block($text."\n\n"); + } + + +} // end class + +?> diff --git a/comments.php b/comments.php new file mode 100644 index 0000000..f75acee --- /dev/null +++ b/comments.php @@ -0,0 +1,115 @@ + + + =========================== */ +?> +deleteComment($_GET['delete']); + header("Location: comments.php?delete=true"); + die(); +} + +if(isset($_POST["btnAdd"])) { + unset($_POST["btnAdd"]); + $_POST["username"] = strip_tags($_POST["username"]); + $_POST["email"] = strip_tags($_POST["email"]); + $_POST["web"] = strip_tags($_POST["web"]); + + if (isset($_POST["id_comment"])) { + $comment->modifyComment($_POST, $_POST["id_comment"]); + } else { + $comment->generateCookie($_POST); + $_POST["spam"] = ($comment->isSpam($_POST)) ? "1" : "0"; + $_POST["ip_user"] = $_SERVER["REMOTE_ADDR"]; + + if ($comment->addComment($_POST)) { + header("Location: comments.php?added=true"); + die(); + } else { + header("Location: comments.php?added=false"); + die(); + } + } +} else { + if ($isEdition) { + $row = $comment->getCommentByID($userId); + } +?> + + + + gelato :: <?php echo __("add user")?> + + + + + + + + + + +
    + +
    + +
    + + +
    + + + + + + + +
    + + +
    +
    + +
    + + + \ No newline at end of file diff --git a/index.php b/index.php index 37b1a94..4cb5a5a 100644 --- a/index.php +++ b/index.php @@ -97,12 +97,12 @@ if ($tumble->contarRegistros()>0) { $dateTmp = null; while($register = mysql_fetch_array($rs)) { - $formatedDate = date("M d", strtotime($register["date"])+transform_offset($conf->offset_time)); + $formatedDate = date("M d", strtotime($register["date"])+transform_offset($conf->offsetTime)); if ( $dateTmp != null && $formatedDate == $dateTmp ) { $formatedDate = ""; } else { $dateTmp = $formatedDate; } $permalink = $conf->urlGelato."/index.php/post/".$register["id_post"]."/"; - $textile = new Textile; - $register["description"] = $textile->process($register["description"]); + $textile = new Textile(); + $register["description"] = $textile->TextileThis($register["description"]); $register["title"] = stripslashes($register["title"]); $register["description"] = stripslashes($register["description"]); @@ -188,11 +188,11 @@ } else { $register = $tumble->getPost($id_post); - $formatedDate = date("M d", strtotime($register["date"])); + $formatedDate = date("M d", strtotime($register["date"])+transform_offset($conf->offsetTime)); $permalink = $conf->urlGelato."/index.php/post/".$register["id_post"]."/"; - $textile = new Textile; - $register["description"] = $textile->process($register["description"]); + $textile = new Textile(); + $register["description"] = $textile->TextileThis($register["description"]); $register["title"] = stripslashes($register["title"]); $register["description"] = stripslashes($register["description"]); @@ -259,6 +259,18 @@ $template->mostrarPlantilla(); break; } + + if ($conf->allowComments) { + + // before the comments form must be the comments on the DB + + $input = array("{User_Cookie}", "{Email_Cookie}", "{Web_Cookie}", "{Id_Post}", "{Form_Action}", "{Date_Added}"); + $output = array($_COOKIE['cookie_gel_user'], $_COOKIE['cookie_gel_email'], $_COOKIE['cookie_gel_web'], $register["id_post"], $conf->urlGelato."/comments.php", gmmktime()); + + $template->cargarPlantilla($input, $output, "template_comment_post"); + $template->mostrarPlantilla(); + + } } $input = array("{URL_Tumble}"); diff --git a/notice.txt b/notice.txt index 37f2a53..75643a2 100644 --- a/notice.txt +++ b/notice.txt @@ -1,4 +1,4 @@ -== CREDITS= = +== CREDITS== Gelato developers and designers (in chronological order): Pedro Santana [ http://www.pecesama.net/weblog/ ] @@ -42,7 +42,7 @@ Copyright (c) Pedro Santana, http://www.pecesama.net/weblog/ Clase plantillas available under MIT license. = Textile class = -Copyright (c) Jim Riggs, http://jimandlissa.com/project/textilephp +Copyright (c) 2003-2004, Dean Allen, http://textile.thresholdstate.com/ Textile class available under GNU General Public License. = PHP-gettext = diff --git a/themes/tumblr/style.css b/themes/tumblr/style.css index fe978db..6dd5ef1 100644 --- a/themes/tumblr/style.css +++ b/themes/tumblr/style.css @@ -261,4 +261,35 @@ padding: 2px 5px 2px 5px; margin-right: 2px; border: 1px solid #f3f3f3; color: #ccc; +} + +.containerFormComments { + margin: 25px 65px 0px 0px; + font-family: Verdana; + font-size: 0.75em; +} + +#commentForm input, #commentForm textarea { + font: 0.9em 'Lucida Grande', Verdana, Arial, Sans-Serif; +} + +#commentForm p { + font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; + margin: 5px 0; +} + +#commentForm input { + width: 170px; + padding: 2px; + margin: 5px 5px 1px 0; +} + +#commentForm textarea { + width: 100%; + padding: 2px; +} + +#commentForm #btnAdd { + margin: 0; + float: right; } \ No newline at end of file diff --git a/themes/tumblr/template_comment_post.htm b/themes/tumblr/template_comment_post.htm new file mode 100644 index 0000000..3f5dddc --- /dev/null +++ b/themes/tumblr/template_comment_post.htm @@ -0,0 +1,37 @@ + +
    +

    Add your comment

    + +
    +

    + + +

    +

    + + +

    +

    + + +

    +

    + +

    +

    + Textile syntax is supported. +

    + +

    +

    + + +

    +
    +
    diff --git a/themes/tumblr/template_comments.htm b/themes/tumblr/template_comments.htm new file mode 100644 index 0000000..9fd4b65 --- /dev/null +++ b/themes/tumblr/template_comments.htm @@ -0,0 +1,18 @@ +
    +

    <*NumeroDeComentarios*> Respuestas a “<*TituloPost*>”

    +
      + [bloque: comentarios] +
    1. + + #   + <*ImagenAvatar*>   + <*AutorComentario*> dijo: + +
      + el <*Fecha*>

      + <*TextoComentario*> +

      +
    2. + [/bloque: comentarios] +
    +