���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/parser.tar
���ѧ٧ѧ�
parser.php 0000644 00000021622 15151236357 0006564 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Library of functions and constants for module wiki * * It contains the great majority of functions defined by Moodle * that are mandatory to develop a module. * * @package mod_wiki * @copyright 2009 Marc Alier, Jordi Piguillem marc.alier@upc.edu * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu * * @author Jordi Piguillem * @author Marc Alier * @author David Jimenez * @author Josep Arus * @author Kenneth Riba * * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Generic parser implementation * * @author Josep Arús * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package mod_wiki */ class wiki_parser_proxy { private static $parsers = array(); private static $basepath = ""; public static function parse(&$string, $type, $options = array()) { if (empty(self::$basepath)) { global $CFG; self::$basepath = $CFG->dirroot . '/mod/wiki/parser/'; } $type = strtolower($type); self::$parsers[$type] = null; // Reset the current parser because it may have other options. if (self::create_parser_instance($type)) { return self::$parsers[$type]->parse($string, $options); } else { return false; } } public static function get_token($name, $type) { if (self::create_parser_instance($type)) { return self::$parsers[$type]->get_token($name); } else { return false; } } public static function get_section(&$string, $type, $section, $allcontent = false) { if (self::create_parser_instance($type)) { $content = self::$parsers[$type]->get_section($section, $string, true); if ($allcontent) { return $content; } else { return is_array($content) ? $content[1] : null; } } else { return false; } } private static function create_parser_instance($type) { if (empty(self::$parsers[$type])) { include_once(self::$basepath . "markups/$type.php"); $class = strtolower($type) . "_parser"; if (class_exists($class)) { self::$parsers[$type] = new $class; return true; } else { return false; } } else { return true; } } } require_once('utils.php'); abstract class generic_parser { protected $string; protected $blockrules = array(); protected $tagrules = array(); private $rulestack = array(); protected $parserstatus = 'Before'; /** * Dynamic return values */ protected $returnvalues = array(); private $nowikiindex = array(); protected $nowikitoken = "%!"; public function __construct() { } /** * Parse function */ public function parse(&$string, $options = array()) { if (!is_string($string)) { return false; } $this->string =& $string; $this->set_options(is_array($options) ? $options : array()); $this->initialize_nowiki_index(); if (method_exists($this, 'before_parsing')) { $this->before_parsing(); } $this->parserstatus = 'Parsing'; foreach ($this->blockrules as $name => $block) { $this->process_block_rule($name, $block); } $this->commit_nowiki_index(); $this->parserstatus = 'After'; if (method_exists($this, 'after_parsing')) { $this->after_parsing(); } return array('parsed_text' => $this->string) + $this->returnvalues; } /** * Initialize options */ protected function set_options($options) { } /** * Block processing function & callbacks */ protected function process_block_rule($name, $block) { $this->rulestack[] = array('callback' => method_exists($this, $name . "_block_rule") ? $name . "_block_rule" : null, 'rule' => $block); $this->string = preg_replace_callback($block['expression'], array($this, 'block_callback'), $this->string); array_pop($this->rulestack); } private function block_callback($match) { $rule = end($this->rulestack); if (!empty($rule['callback'])) { $stuff = $this->{$rule['callback']}($match); } else { $stuff = $match[1]; } if (is_array($stuff) && $rule['rule']['tag']) { $this->rules($stuff[0], $rule['rule']['tags']); $stuff = "\n" . parser_utils::h($rule['rule']['tag'], $stuff[0], $stuff[1]) . "\n"; } else { if (!isset($rule['rule']['tags'])) { $rule['rule']['tags'] = null; } $this->rules($stuff, $rule['rule']['tags']); if (isset($rule['rule']['tag']) && is_string($rule['rule']['tag'])) { $stuff = "\n" . parser_utils::h($rule['rule']['tag'], $stuff) . "\n"; } } return $stuff; } /** * Rules processing function & callback */ protected final function rules(&$text, $rules = null) { if ($rules === null) { $rules = array('except' => array()); } else if (is_array($rules) && count($rules) > 1) { $rules = array('only' => $rules); } if (isset($rules['only']) && is_array($rules['only'])) { $rules = $rules['only']; foreach ($rules as $r) { if (!empty($this->tagrules[$r])) { $this->process_tag_rule($r, $this->tagrules[$r], $text); } } } else if (isset($rules['except']) && is_array($rules['except'])) { $rules = $rules['except']; foreach ($this->tagrules as $r => $tr) { if (!in_array($r, $rules)) { $this->process_tag_rule($r, $tr, $text); } } } } private function process_tag_rule($name, $rule, &$text) { if (method_exists($this, $name . "_tag_rule")) { $this->rulestack[] = array('callback' => $name . "_tag_rule", 'rule' => $rule); $text = preg_replace_callback($rule['expression'], array($this, 'tag_callback'), $text); array_pop($this->rulestack); } else { if (isset($rule['simple'])) { $replace = "<{$rule['tag']} />"; } else { $replace = parser_utils::h($rule['tag'], "$1"); } $text = preg_replace($rule['expression'], $replace, $text); } } private function tag_callback($match) { $rule = end($this->rulestack); $stuff = $this->{$rule['callback']}($match); if (is_array($stuff)) { return parser_utils::h($rule['rule']['tag'], $stuff[0], $stuff[1]); } else { return $stuff; } } /** * Special nowiki parser index */ private function initialize_nowiki_index() { $token = "\Q" . $this->nowikitoken . "\E"; $this->string = preg_replace_callback("/" . $token . "\d+" . $token . "/", array($this, "initialize_nowiki_index_callback"), $this->string); } private function initialize_nowiki_index_callback($match) { return $this->protect($match[0]); } protected function protect($text) { $this->nowikiindex[] = $text; return $this->nowikitoken . (count($this->nowikiindex) - 1) . $this->nowikitoken; } private function commit_nowiki_index() { $token = "\Q" . $this->nowikitoken . "\E"; $this->string = preg_replace_callback("/" . $token . "(\d+)" . $token . "/", array($this, "commit_nowiki_index_callback"), $this->string); } private function commit_nowiki_index_callback($match) { return $this->nowikiindex[intval($match[1])]; } /** * Get token of the parsable element $name. */ public function get_token($name) { foreach (array_merge($this->blockrules, $this->tagrules) as $n => $v) { if ($name == $n && isset($v['token'])) { return $v['token'] ? $v['token'] : false; } } return false; } } utils.php 0000644 00000005377 15151236357 0006441 0 ustar 00 <?php /** * Parser utils and default callbacks. * * @author Josep Arús * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package mod_wiki */ require_once($CFG->dirroot . "/lib/outputcomponents.php"); class parser_utils { public static function h($tag, $text = null, $options = array(), $escape_text = false) { $tag = htmlentities($tag, ENT_COMPAT, 'UTF-8'); if(!empty($text) && $escape_text) { $text = htmlentities($text, ENT_COMPAT, 'UTF-8'); } return html_writer::tag($tag, $text, $options); } /** * Default link generator */ public static function wiki_parser_link_callback($link, $options) { $l = urlencode($link); if(!empty($options['anchor'])) { $l .= "#".urlencode($options['anchor']); } return array('content' => $link, 'url' => "http://".$l); } /** * Default table generator */ public static function wiki_parser_table_callback($table) { $html = ""; $headers = $table[0]; $columncount = count($headers); $headerhtml = ""; foreach($headers as $h) { $text = trim($h[1]); if($h[0] == 'header') { $headerhtml .= "\n".parser_utils::h('th', $text)."\n"; $hasheaders = true; } else if($h[0] == 'normal'){ $headerhtml .= "\n".parser_utils::h("td", $text)."\n"; } } $headerhtml = "\n".parser_utils::h('tr', $headerhtml)."\n"; $bodyhtml = ""; if(isset($hasheaders)) { $html = "\n".parser_utils::h('thead', $headerhtml)."\n"; } else { $bodyhtml .= $headerhtml; } array_shift($table); foreach($table as $row) { $htmlrow = ""; for($i = 0; $i < $columncount; $i++) { $text = ""; if(!isset($row[$i])) { $htmlrow .= "\n".parser_utils::h('td', $text)."\n"; } else { $text = trim($row[$i][1]); if($row[$i][0] == 'header') { $htmlrow .= "\n".parser_utils::h('th', $text)."\n"; } else if($row[$i][0] == 'normal'){ $htmlrow .= "\n".parser_utils::h('td', $text)."\n"; } } } $bodyhtml .= "\n".parser_utils::h('tr', $htmlrow)."\n"; } $html .= "\n".parser_utils::h('tbody', $bodyhtml)."\n"; return "\n".parser_utils::h('table', $html)."\n"; } /** * Default path converter */ public static function wiki_parser_real_path($url) { return $url; } } markups/wikimarkup.php 0000644 00000032520 15151236357 0011134 0 ustar 00 <?php /** * Generic & abstract parser functions & skeleton. It has some functions & generic stuff. * * @author Josep Arús * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package mod_wiki */ abstract class wiki_markup_parser extends generic_parser { protected $pretty_print = false; protected $printable = false; //page id protected $wiki_page_id; //sections protected $repeated_sections; protected $section_editing = true; //header & ToC protected $toc = array(); protected $maxheaderdepth = 3; /** * function wiki_parser_link_callback($link = "") * * Returns array('content' => "Inside the link", 'url' => "http://url.com/Wiki/Entry", 'new' => false). */ private $linkgeneratorcallback = array('parser_utils', 'wiki_parser_link_callback'); private $linkgeneratorcallbackargs = array(); /** * Table generator callback */ private $tablegeneratorcallback = array('parser_utils', 'wiki_parser_table_callback'); /** * Get real path from relative path */ private $realpathcallback = array('parser_utils', 'wiki_parser_real_path'); private $realpathcallbackargs = array(); /** * Before and after parsing... */ protected function before_parsing() { $this->toc = array(); $this->string = preg_replace('/\r\n/', "\n", $this->string); $this->string = preg_replace('/\r/', "\n", $this->string); $this->string .= "\n\n"; if (!$this->printable && $this->section_editing) { $this->returnvalues['unparsed_text'] = $this->string; $this->string = $this->get_repeated_sections($this->string); } } protected function after_parsing() { if (!$this->printable) { $this->returnvalues['repeated_sections'] = array_unique($this->returnvalues['repeated_sections']); } $this->process_toc(); $this->string = preg_replace("/\n\s/", "\n", $this->string); $this->string = preg_replace("/\n{2,}/", "\n", $this->string); $this->string = trim($this->string); $this->string .= "\n"; } /** * Set options */ protected function set_options($options) { parent::set_options($options); $this->returnvalues['link_count'] = array(); $this->returnvalues['repeated_sections'] = array(); $this->returnvalues['toc'] = ""; foreach ($options as $name => $o) { switch ($name) { case 'link_callback': $callback = explode(':', $o); global $CFG; require_once($CFG->dirroot . $callback[0]); if (function_exists($callback[1])) { $this->linkgeneratorcallback = $callback[1]; } break; case 'link_callback_args': if (is_array($o)) { $this->linkgeneratorcallbackargs = $o; } break; case 'real_path_callback': $callback = explode(':', $o); global $CFG; require_once($CFG->dirroot . $callback[0]); if (function_exists($callback[1])) { $this->realpathcallback = $callback[1]; } break; case 'real_path_callback_args': if (is_array($o)) { $this->realpathcallbackargs = $o; } break; case 'table_callback': $callback = explode(':', $o); global $CFG; require_once($CFG->dirroot . $callback[0]); if (function_exists($callback[1])) { $this->tablegeneratorcallback = $callback[1]; } break; case 'pretty_print': if ($o) { $this->pretty_print = true; } break; case 'pageid': $this->wiki_page_id = $o; break; case 'printable': if ($o) { $this->printable = true; } break; } } } /** * Generic block rules */ protected function line_break_block_rule($match) { return '<hr />'; } protected function list_block_rule($match) { preg_match_all("/^\ *([\*\#]{1,5})\ *((?:[^\n]|\n(?!(?:\ *[\*\#])|\n))+)/im", $match[1], $listitems, PREG_SET_ORDER); return $this->process_block_list($listitems) . $match[2]; } protected function nowiki_block_rule($match) { return parser_utils::h('pre', $this->protect($match[1])); } /** * Generic tag rules */ protected function nowiki_tag_rule($match) { return parser_utils::h('tt', $this->protect($match[1])); } /** * Header generation */ protected function generate_header($text, $level) { $toctext = $text = trim($text); if (!$this->pretty_print && $level == 1) { $editlink = '[' . get_string('editsection', 'wiki') . ']'; $url = array('href' => "edit.php?pageid={$this->wiki_page_id}§ion=" . urlencode($text), 'class' => 'wiki_edit_section'); $text .= ' ' . parser_utils::h('a', $this->protect($editlink), $url); $toctext .= ' ' . parser_utils::h('a', $editlink, $url); } if ($level <= $this->maxheaderdepth) { $this->toc[] = array($level, $toctext); $num = count($this->toc); $text = parser_utils::h('a', "", array('name' => "toc-$num")) . $text; } // Display headers as <h3> and lower for accessibility. return parser_utils::h('h' . min(6, $level + 2), $text) . "\n\n"; } /** * Table of contents processing after parsing */ protected function process_toc() { if (empty($this->toc)) { return; } $toc = ""; $currentsection = array(0, 0, 0); $i = 1; foreach ($this->toc as & $header) { switch ($header[0]) { case 1: $currentsection = array($currentsection[0] + 1, 0, 0); break; case 2: $currentsection[1]++; $currentsection[2] = 0; if ($currentsection[0] == 0) { $currentsection[0]++; } break; case 3: $currentsection[2]++; if ($currentsection[1] == 0) { $currentsection[1]++; } if ($currentsection[0] == 0) { $currentsection[0]++; } break; default: continue 2; } $number = "$currentsection[0]"; if (!empty($currentsection[1])) { $number .= ".$currentsection[1]"; if (!empty($currentsection[2])) { $number .= ".$currentsection[2]"; } } $toc .= parser_utils::h('p', $number . ". " . parser_utils::h('a', str_replace(array('[[', ']]'), '', $header[1]), array('href' => "#toc-$i")), array('class' => 'wiki-toc-section-' . $header[0] . " wiki-toc-section")); $i++; } $this->returnvalues['toc'] = "<div class=\"wiki-toc\"><p class=\"wiki-toc-title\">" . get_string('tableofcontents', 'wiki') . "</p>$toc</div>"; } /** * List helpers */ private function process_block_list($listitems) { $list = array(); foreach ($listitems as $li) { $text = str_replace("\n", "", $li[2]); $this->rules($text); if ($li[1][0] == '*') { $type = 'ul'; } else { $type = 'ol'; } $list[] = array(strlen($li[1]), $text, $type); } $type = $list[0][2]; return "<$type>" . "\n" . $this->generate_list($list) . "\n" . "</$type>" . "\n"; } /** * List generation function from an array of array(level, text) */ protected function generate_list($listitems) { $list = ""; $current_depth = 1; $next_depth = 1; $liststack = array(); for ($lc = 0; $lc < count($listitems) && $next_depth; $lc++) { $cli = $listitems[$lc]; $nli = isset($listitems[$lc + 1]) ? $listitems[$lc + 1] : null; $text = $cli[1]; $current_depth = $next_depth; $next_depth = $nli ? $nli[0] : null; if ($next_depth == $current_depth || $next_depth == null) { $list .= parser_utils::h('li', $text) . "\n"; } else if ($next_depth > $current_depth) { $next_depth = $current_depth + 1; $list .= "<li>" . $text . "\n"; $list .= "<" . $nli[2] . ">" . "\n"; $liststack[] = $nli[2]; } else { $list .= parser_utils::h('li', $text) . "\n"; for ($lv = $next_depth; $lv < $current_depth; $lv++) { $type = array_pop($liststack); $list .= "</$type>" . "\n" . "</li>" . "\n"; } } } for ($lv = 1; $lv < $current_depth; $lv++) { $type = array_pop($liststack); $list .= "</$type>" . "\n" . "</li>" . "\n"; } return $list; } /** * Table generation functions */ protected function generate_table($table) { $table_html = call_user_func_array($this->tablegeneratorcallback, array($table)); return $table_html; } protected function format_image($src, $alt, $caption = "", $align = 'left') { $src = $this->real_path($src); return parser_utils::h('div', parser_utils::h('p', $caption) . '<img src="' . $src . '" alt="' . $alt . '" />', array('class' => 'wiki_image_' . $align)); } protected function real_path($url) { $callbackargs = array_merge(array($url), $this->realpathcallbackargs); return call_user_func_array($this->realpathcallback, array_values($callbackargs)); } /** * Link internal callback */ protected function link($link, $anchor = "") { $link = trim($link); if (preg_match("/^(https?|s?ftp):\/\/.+$/i", $link)) { $link = trim($link, ",.?!"); return array('content' => $link, 'url' => $link); } else { $callbackargs = $this->linkgeneratorcallbackargs; $callbackargs['anchor'] = $anchor; $link = call_user_func_array($this->linkgeneratorcallback, array($link, $callbackargs)); if (isset($link['link_info'])) { $l = $link['link_info']['link']; unset($link['link_info']['link']); $this->returnvalues['link_count'][$l] = $link['link_info']; } return $link; } } /** * Format links */ protected function format_link($text) { $matches = array(); if (preg_match("/^([^\|]+)\|(.+)$/i", $text, $matches)) { $link = $matches[1]; $content = trim($matches[2]); if (preg_match("/(.+)#(.*)/is", $link, $matches)) { $link = $this->link($matches[1], $matches[2]); } else if ($link[0] == '#') { $link = array('url' => "#" . urlencode(substr($link, 1))); } else { $link = $this->link($link); } $link['content'] = $content; } else { $link = $this->link($text); } if (isset($link['new']) && $link['new']) { $options = array('class' => 'wiki_newentry'); } else { $options = array(); } $link['content'] = $this->protect($link['content']); $link['url'] = $this->protect($link['url']); $options['href'] = $link['url']; if ($this->printable) { $options['href'] = '#'; //no target for the link } return array($link['content'], $options); } /** * Section editing */ public function get_section($header, $text, $clean = false) { if ($clean) { $text = preg_replace('/\r\n/', "\n", $text); $text = preg_replace('/\r/', "\n", $text); $text .= "\n\n"; } $regex = "/(.*?)(=\ *".preg_quote($header, '/')."\ *=*\n.*?)((?:\n=[^=]+.*)|$)/is"; preg_match($regex, $text, $match); if (!empty($match)) { return array($match[1], $match[2], $match[3]); } else { return false; } } protected function get_repeated_sections(&$text, $repeated = array()) { $this->repeated_sections = $repeated; return preg_replace_callback($this->blockrules['header']['expression'], array($this, 'get_repeated_sections_callback'), $text); } protected function get_repeated_sections_callback($match) { $num = strlen($match[1]); $text = trim($match[2]); if ($num == 1) { if (in_array($text, $this->repeated_sections)) { $this->returnvalues['repeated_sections'][] = $text; return $text . "\n"; } else { $this->repeated_sections[] = $text; } } return $match[0]; } } markups/html.php 0000644 00000006777 15151236357 0007734 0 ustar 00 <?php /** * HTML parser implementation. It only implements links. * * @author Josep Arús * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package mod_wiki */ include_once("nwiki.php"); class html_parser extends nwiki_parser { protected $blockrules = array(); protected $section_editing = true; /** @var int Minimum level of the headers on the page (usually tinymce uses <h1> and atto <h3>) */ protected $minheaderlevel = null; public function __construct() { parent::__construct(); // The order is important, headers should be parsed before links. $this->tagrules = array( // Headers are considered tags here. 'header' => array( 'expression' => "/<\s*h([1-6])\s*>(.+?)<\/h[1-6]>/is" ), 'link' => $this->tagrules['link'], 'url' => $this->tagrules['url'] ); } /** * Find minimum header level used on the page (<h1>, <h3>, ...) * * @param string $text * @return int */ protected function find_min_header_level($text) { preg_match_all($this->tagrules['header']['expression'], $text, $matches); return !empty($matches[1]) ? min($matches[1]) : 1; } protected function before_parsing() { parent::before_parsing(); $this->minheaderlevel = $this->find_min_header_level($this->string); // Protect all explicit links from further wiki parsing. The link text may contain another URL which would get // converted into another link via {@see nwiki_parser::$tagrules} 'url' element. if (preg_match_all('/<a\s[^>]+?>(.*?)<\/a>/is', $this->string, $matches)) { foreach (array_unique($matches[0]) as $match) { $this->string = str_replace($match, $this->protect($match), $this->string); } } $this->rules($this->string); } /** * Header tag rule * @param array $match Header regex match * @return string */ protected function header_tag_rule($match) { return $this->generate_header($match[2], (int)$match[1] - $this->minheaderlevel + 1); } /** * Section editing: Special for HTML Parser (It parses <h1></h1>) */ public function get_section($header, $text, $clean = false) { if ($clean) { $text = preg_replace('/\r\n/', "\n", $text); $text = preg_replace('/\r/', "\n", $text); $text .= "\n\n"; } $minheaderlevel = $this->find_min_header_level($text); $h1 = array("<\s*h{$minheaderlevel}\s*>", "<\/h{$minheaderlevel}>"); $regex = "/(.*?)({$h1[0]}\s*".preg_quote($header, '/')."\s*{$h1[1]}.*?)((?:{$h1[0]}.*)|$)/is"; preg_match($regex, $text, $match); if (!empty($match)) { return array($match[1], $match[2], $match[3]); } else { return false; } } protected function get_repeated_sections(&$text, $repeated = array()) { $this->repeated_sections = $repeated; return preg_replace_callback($this->tagrules['header'], array($this, 'get_repeated_sections_callback'), $text); } protected function get_repeated_sections_callback($match) { $text = trim($match[2]); if (in_array($text, $this->repeated_sections)) { $this->returnvalues['repeated_sections'][] = $text; return parser_utils::h('p', $text); } else { $this->repeated_sections[] = $text; } return $match[0]; } } markups/creole.php 0000644 00000014125 15151236357 0010223 0 ustar 00 <?php /** * Creole parser implementation * * @author Josep Arús * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package mod_wiki */ include_once("wikimarkup.php"); class creole_parser extends wiki_markup_parser { protected $blockrules = array( 'nowiki' => array( 'expression' => "/^\{\{\{(.*?)\}\}\}/ims", 'tags' => array(), 'token' => array('{{{', '}}}') ), 'header' => array( 'expression' => "/^\ *(={1,6})\ *(.+?)=*\ *$/ims", 'tags' => array(), //none 'token' => '=' ), 'table' => array( 'expression' => "/^(?:\|.*?\|\ *\n)+/ims" ), 'line_break' => array( 'expression' => "/^----\s*$/im", 'token' => '----', 'tags' => array() ), 'list' => array( 'expression' => "/((?:^\ *[\*#][^\*#]\ *.+?)(?:^\ *[\*#]{1,5}\ *.+?)*)(\n\s*(?:\n|<(?:h\d|pre|table|tbody|thead|tr|th|td|ul|li|ol|hr)))/ims", 'tags' => array(), 'token' => array('*', '#') ), 'paragraph' => array( 'expression' => "/^\ *((?:<(?!\ *\/?(?:h\d|pre|table|tbody|thead|tr|th|td|ul|li|ol|hr)\ *\/?>)|[^<\s]).+?)\n\s*\n/ims", //not specified -> all tags (null or unset) 'tag' => 'p' ) ); protected $tagrules = array( 'nowiki' => array( 'expression' => "/\{\{\{(.*?)\}\}\}/is", 'token' => array('{{{', '}}}') ), 'image' => array( 'expression' => "/\~?\{\{(.+)\|(.+)\}\}/i", 'tags' => array(), 'token' => array('{{', '|Alt}}') ), 'link' => array( 'expression' => "/\~?\[\[(.+?)\]\]/is", 'tag' => 'a', 'token' => array('[[', ']]') ), 'url' => array( 'expression' => "/\~?(?<!=\")((?:https?|ftp):\/\/[^\s\n]+[^,\.\?!:;\"\'\n\ ])/is", 'tag' => 'a', 'token' => "http://" ), 'line_break' => array( 'expression' => "/\\\\\\\\/", 'tag' => 'br', 'simple' => true, 'token' => '----' ), 'bold' => array( 'expression' => "/\*\*(.*?)(?:\*\*|$)/is", 'tag' => 'strong', 'token' => array('**', '**') ), 'italic' => array( 'expression' => "#(?<!http:|https:|ftp:)//(.+?)(?<!http:|https:|ftp:)//#is", 'tag' => 'em', 'token' => array('//', '//') ) ); /** * Block hooks */ protected function before_parsing() { $this->string = htmlspecialchars($this->string, ENT_COMPAT); parent::before_parsing(); } public function get_section($header, $text, $clean = false) { // The requested header is likely to have been passed to htmlspecialchars in // self::before_parsing(), therefore we should decode it when looking for it. return parent::get_section(htmlspecialchars_decode($header, ENT_COMPAT), $text, $clean); } protected function header_block_rule($match) { $num = strlen($match[1]); $text = trim($match[2]); $text = preg_replace("/\s*={1,$num}$/im", "", $text); return $this->generate_header($text, $num); } /** * Table generation */ protected function table_block_rule($match) { $rows = explode("\n", $match[0]); $table = array(); foreach($rows as $r) { if(empty($r)) { continue; } $rawcells = explode("|", $r); $cells = array(); array_shift($rawcells); array_pop($rawcells); foreach($rawcells as $c) { if(!empty($c)) { if($c[0] == "=") { $type = 'header'; $c = substr($c, 1); } else { $type = 'normal'; } $this->rules($c); $cells[] = array($type, $c); } } $table[] = $cells; } return $this->generate_table($table); } protected function paragraph_block_rule($match) { $text = $match[1]; foreach($this->tagrules as $tr) { if(isset($tr['token'])) { if(is_array($tr['token'])) { $this->escape_token_string($text, $tr['token'][0]); $this->escape_token_string($text, $tr['token'][1]); } else { $this->escape_token_string($text, $tr['token']); } } } $this->escape_token_string($text, "~"); return $text; } /** * Escape token when it is "negated" */ private function escape_token_string(&$text, $token) { $text = str_replace("~".$token, $this->protect($token), $text); } /** * Tag functions */ protected function url_tag_rule($match) { if(strpos($match[0], "~") === 0) { return substr($match[0], 1); } else { $text = trim($match[0]); $options = array('href' => $text); return array($text, $options); } } protected function link_tag_rule($match) { $text = trim($match[1]); if(strpos($match[0], "~") === 0) { return substr($match[0], 1); } else { return $this->format_link($text); } } /** * Special treatment of // ** // ** // */ protected function bold_tag_rule($match) { $text = $match[1]; $this->rules($text, array('only' => array('italic'))); if(strpos($text, "//") !== false) { $text = str_replace("//", $this->protect("//"), $text); } return array($text, array()); } protected function image_tag_rule($match) { if(strpos($match[0], "~") === 0) { return substr($match[0], 1); } return $this->format_image($match[1], $match[2]); } } markups/nwiki.php 0000644 00000017555 15151236357 0010105 0 ustar 00 <?php /** * NWiki parser implementation * * @author Josep Arús * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package mod_wiki */ include_once("wikimarkup.php"); class nwiki_parser extends wiki_markup_parser { protected $blockrules = array( 'nowiki' => array( 'expression' => "/^<nowiki>(.*?)<\/nowiki>/ims", 'tags' => array(), 'token' => array('<nowiki>', '</nowiki>') ), 'header' => array( 'expression' => "/^\ *(={1,6})\ *(.+?)(={1,6})\ *$/ims", 'tags' => array(), //none 'token' => '=' ), 'line_break' => array( 'expression' => "/^-{3,4}\s*$/im", 'tags' => array(), 'token' => '---' ), 'desc_list' => array( 'expression' => "/(?:^.+?\:.+?\;\n)+/ims", 'tags' => array(), 'token' => array(':', ';'), 'tag' => 'dl' ), 'table' => array( 'expression' => "/\{\|(.+?)\|\}/ims" ), 'tab_paragraph' => array( 'expression' => "/^(\:+)(.+?)$/ims", 'tag' => 'p' ), 'list' => array( 'expression' => "/^((?:\ *[\*|#]{1,5}\ *.+?)+)(\n\s*(?:\n|<(?:h\d|pre|table|tbody|thead|tr|th|td|ul|li|ol|hr)\ *\/?>))/ims", 'tags' => array(), 'token' => array('*', '#') ), 'paragraph' => array( 'expression' => "/^\ *((?:<(?!\ *\/?(?:h\d|pre|table|tbody|thead|tr|th|td|ul|li|ol|hr)\ *\/?>)|[^<\s]).+?)\n\s*\n/ims", //not specified -> all tags (null or unset) 'tag' => 'p' ) ); protected $tagrules = array( 'nowiki' => array( 'expression' => "/<nowiki>(.*?)<\/nowiki>/is", 'token' => array('<nowiki>', '</nowiki>') ), 'image' => array( 'expression' => "/\[\[image:(.+?)\|(.+?)\]\]/is", 'token' => array("[[image:", "|alt]]") ), 'attach' => array( 'expression' => "/\[\[attach:(.+?)\]\]/is", 'token' => array("[[attach:", "|name]]") ), 'link' => array( 'expression' => "/\[\[(.+?)\]\]/is", 'tag' => 'a', 'token' => array("[[", "]]") ), 'url_tag' => array( 'expression' => "/\[(.+?)\]/is", 'tag' => 'a', 'token' => array("[", "]") ), 'url' => array( 'expression' => "/(?<!=\")((?:https?|ftp):\/\/[^\s\n]+[^,\.\?!:;\"\'\n\ ])/i", 'tag' => 'a', 'token' => 'http://' ), 'italic' => array( 'expression' => "/\'{3}(.+?)(\'{3}(?:\'{2})?)/is", 'tag' => 'em', 'token' => array("'''", "'''") ), 'bold' => array( 'expression' => "/\'{2}(.+?)\'{2}/is", 'tag' => 'strong', 'token' => array("''", "''") ) ); protected function after_parsing() { parent::after_parsing(); } /** * Block hooks */ protected function header_block_rule($match) { if($match[1] != $match[3]) { return $match[0]; } $num = strlen($match[1]); return $this->generate_header($match[2], $num); } protected function table_block_rule($match) { $rows = explode("\n|-", $match[1]); $table = array(); foreach($rows as $r) { $colsendline = explode("\n", $r); $cols = array(); foreach($colsendline as $ce) { $cols = array_merge($cols, $this->get_table_cells($ce)); } if(!empty($cols)) { $table[] = $cols; } } return $this->generate_table($table); } private function get_table_cells($string) { $string = ltrim($string); $type = (!empty($string) && $string[0] == "!") ? 'header' : 'normal'; $string = substr($string, 1); if(empty($string)) { $normalcells = array(); } else { $normalcells = explode("||", $string); } $cells = array(); foreach($normalcells as $nc) { $headercells = explode("!!", $nc); $countheadercells = count($headercells); for($i = 0; $i < $countheadercells; $i++) { $cells[] = array($type, $headercells[$i]); $type = 'header'; } $type = 'normal'; } return $cells; } protected function tab_paragraph_block_rule($match) { $num = strlen($match[1]); $text = $match[2]; $html = ""; for($i = 0; $i < $num - 1; $i++) { $html = parser_utils::h('p', $html, array('class' => 'wiki_tab_paragraph')); } return parser_utils::h('p', $text, array('class' => 'wiki_tab_paragraph')); } protected function desc_list_block_rule($match) { preg_match_all("/^(.+?)\:(.+?)\;$/ims", $match[0], $listitems, PREG_SET_ORDER); $list = ""; foreach($listitems as $li) { $term = $li[1]; $this->rules($term); $description = $li[2]; $this->rules($description); $list .= parser_utils::h('dt', $term).parser_utils::h('dd', $description); } return $list; } /** * Tag functions */ /** * Bold and italic similar to creole... */ protected function italic_tag_rule($match) { $text = $match[1]; if(strlen($match[2]) == 5) { $text .= "''"; } $this->rules($text, array('only' => array('bold'))); if(strpos($text, "''") !== false) { $text = str_replace("''", $this->protect("''"), $text); } return array($text, array()); } /** * Link tag functions */ protected function link_tag_rule($match) { return $this->format_link($match[1]); } protected function url_tag_tag_rule($match) { $text = trim($match[1]); if(preg_match("/(.+?)\|(.+)/is", $text, $matches)) { $link = $matches[1]; $text = $matches[2]; } else if(preg_match("/(.+?)\ (.+)/is", $text, $matches)) { $link = $matches[1]; $text = $matches[2]; } else { $link = $text; } return array($this->protect($text), array('href' => $this->protect($link))); } protected function url_tag_rule($match) { $url = $this->protect($match[1]); $options = array('href' => $url); return array($url, $options); } /** * Attachments & images */ protected function image_tag_rule($match) { return $this->format_image($match[1], $match[2]); } protected function attach_tag_rule($match) { $parts = explode("|", $match[1]); $url = array_shift($parts); if(count($parts) > 0) { $text = array_shift($parts); } $extension = substr($url, strrpos($url, ".")); $text = empty($text) ? $url : $text; $imageextensions = array('jpg', 'jpeg', 'png', 'bmp', 'gif', 'tif'); if(in_array($extension, $imageextensions)) { $align = 'left'; if(count($parts) > 0) { switch(strtolower($text)) { case 'right': $align = 'right'; break; case 'center': $align = 'center'; break; default: $align = 'left'; } $text = $parts[0]; } return $this->format_image($url, $text, $text, $align); } else { $url = $this->real_path($url); return parser_utils::h('a', $text, array('href' => $url, 'class' => 'wiki-attachment')); } } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0.01 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�