diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..acc5026
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,15 @@
+# Set default behaviour, in case users don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files we want to always be normalized and converted
+# to native line endings on checkout.
+*.php text eol=lf
+*.js text eol=lf
+*.css text eol=lf
+*.html text eol=lf
+*.xml text eol=lf
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cd0f9ed
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+.*.swp
+.*.swo
+._*
+.DS_Store
+/Debug/
+/ImgCache/
+/Backup_rar/
+/Debug/
+/debug/
+/upload/
+/avatar/
+/.idea/
+.svn/
+*.orig
+*.aps
+*.APS
+*.chm
+*.exp
+*.pdb
+*.rar
+.smbdelete*
+*.sublime*
+.sass-cache
+config.rb
+/config.inc.php
+/usr/uploads/
diff --git a/Akismet/Plugin.php b/Akismet/Plugin.php
new file mode 100644
index 0000000..3b6adf9
--- /dev/null
+++ b/Akismet/Plugin.php
@@ -0,0 +1,213 @@
+comment = array('Akismet_Plugin', 'filter');
+ Typecho_Plugin::factory('Widget_Feedback')->trackback = array('Akismet_Plugin', 'filter');
+ Typecho_Plugin::factory('Widget_XmlRpc')->pingback = array('Akismet_Plugin', 'filter');
+ Typecho_Plugin::factory('Widget_Comments_Edit')->mark = array('Akismet_Plugin', 'mark');
+
+ return _t('请配置此插件的API KEY, 以使您的反垃圾策略生效');
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate(){}
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+ $key = new Typecho_Widget_Helper_Form_Element_Textarea('key', NULL, NULL, _t('服务密钥'), _t('此密钥需要向服务提供商注册
+ 它是一个用于表明您合法用户身份的字符串'));
+ $form->addInput($key->addRule('required', _t('您必须填写一个服务密钥'))
+ ->addRule(array('Akismet_Plugin', 'validate'), _t('您使用的服务密钥错误')));
+
+ $url = new Typecho_Widget_Helper_Form_Element_Text('url', NULL, 'http://rest.akismet.com',
+ _t('服务地址'), _t('这是反垃圾评论服务提供商的服务器地址
+ 我们推荐您使用 Akismet 或者 Typepad 的反垃圾服务'));
+ $form->addInput($url->addRule('url', _t('您使用的地址格式错误')));
+ }
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form){}
+
+ /**
+ * 验证api的key值
+ *
+ * @access public
+ * @param string $key 服务密钥
+ * @return boolean
+ */
+ public static function validate($key)
+ {
+ $options = Typecho_Widget::widget('Widget_Options');
+ $url = Typecho_Request::getInstance()->url;
+
+ $data = array(
+ 'key' => $key,
+ 'blog' => $options->siteUrl
+ );
+
+ $client = Typecho_Http_Client::get('Curl', 'Socket');
+ if (false != $client) {
+ $client->setData($data)
+ ->setHeader('User-Agent', $options->generator . ' | Akismet/1.1')
+ ->send(Typecho_Common::url('/1.1/verify-key', $url));
+
+ if ('valid' == $client->getResponseBody()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 标记评论状态时的插件接口
+ *
+ * @access public
+ * @param array $comment 评论数据的结构体
+ * @param Typecho_Widget $commentWidget 评论组件
+ * @param string $status 评论状态
+ * @return void
+ */
+ public static function mark($comment, $commentWidget, $status)
+ {
+ if ('spam' == $comment['status'] && $status != 'spam') {
+ self::filter($comment, $commentWidget, NULL, 'submit-ham');
+ } else if ('spam' != $comment['status'] && $status == 'spam') {
+ self::filter($comment, $commentWidget, NULL, 'submit-spam');
+ }
+ }
+
+ /**
+ * 评论过滤器
+ *
+ * @access public
+ * @param array $comment 评论结构
+ * @param Typecho_Widget $post 被评论的文章
+ * @param array $result 返回的结果上下文
+ * @param string $api api地址
+ * @return void
+ */
+ public static function filter($comment, $post, $result, $api = 'comment-check')
+ {
+ $comment = empty($result) ? $comment : $result;
+
+ $options = Typecho_Widget::widget('Widget_Options');
+ $url = $options->plugin('Akismet')->url;
+ $key = $options->plugin('Akismet')->key;
+
+ $allowedServerVars = 'comment-check' == $api ? array(
+ 'SCRIPT_URI',
+ 'HTTP_HOST',
+ 'HTTP_USER_AGENT',
+ 'HTTP_ACCEPT',
+ 'HTTP_ACCEPT_LANGUAGE',
+ 'HTTP_ACCEPT_ENCODING',
+ 'HTTP_ACCEPT_CHARSET',
+ 'HTTP_KEEP_ALIVE',
+ 'HTTP_CONNECTION',
+ 'HTTP_CACHE_CONTROL',
+ 'HTTP_PRAGMA',
+ 'HTTP_DATE',
+ 'HTTP_EXPECT',
+ 'HTTP_MAX_FORWARDS',
+ 'HTTP_RANGE',
+ 'CONTENT_TYPE',
+ 'CONTENT_LENGTH',
+ 'SERVER_SIGNATURE',
+ 'SERVER_SOFTWARE',
+ 'SERVER_NAME',
+ 'SERVER_ADDR',
+ 'SERVER_PORT',
+ 'REMOTE_PORT',
+ 'GATEWAY_INTERFACE',
+ 'SERVER_PROTOCOL',
+ 'REQUEST_METHOD',
+ 'QUERY_STRING',
+ 'REQUEST_URI',
+ 'SCRIPT_NAME',
+ 'REQUEST_TIME'
+ ) : array();
+
+ $data = array(
+ 'blog' => $options->siteUrl,
+ 'user_ip' => $comment['ip'],
+ 'user_agent' => $comment['agent'],
+ 'referrer' => Typecho_Request::getInstance()->getReferer(),
+ 'permalink' => $post->permalink,
+ 'comment_type' => $comment['type'],
+ 'comment_author' => $comment['author'],
+ 'comment_author_email' => $comment['mail'],
+ 'comment_author_url' => $comment['url'],
+ 'comment_content' => $comment['text']
+ );
+
+ foreach ($allowedServerVars as $val) {
+ if (array_key_exists($val, $_SERVER)) {
+ $data[$val] = $_SERVER[$val];
+ }
+ }
+
+ try {
+ $client = Typecho_Http_Client::get();
+ if (false != $client && $key) {
+ $params = parse_url($url);
+ $url = $params['scheme'] . '://' . $key . '.' . $params['host'] . (isset($params['path']) ? $params['path'] : NULL);
+
+ $client->setHeader('User-Agent', $options->generator . ' | Akismet/1.1')
+ ->setTimeout(5)
+ ->setData($data)
+ ->send(Typecho_Common::url('/1.1/' . $api, $url));
+
+ if ('true' == $client->getResponseBody()) {
+ $comment['status'] = 'spam';
+ }
+ }
+ } catch (Typecho_Http_Client_Exception $e) {
+ //do nothing
+ error_log($e->getMessage());
+ }
+
+ return $comment;
+ }
+}
diff --git a/BlockComment/Plugin.php b/BlockComment/Plugin.php
new file mode 100644
index 0000000..b80ecd8
--- /dev/null
+++ b/BlockComment/Plugin.php
@@ -0,0 +1,124 @@
+comment = array('BlockComment_Plugin', 'filter');
+ Typecho_Plugin::factory('Widget_Feedback')->trackback = array('BlockComment_Plugin', 'filter');
+ Typecho_Plugin::factory('Widget_XmlRpc')->pingback = array('BlockComment_Plugin', 'filter');
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate(){}
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+ $hosts = new Typecho_Widget_Helper_Form_Element_Textarea('hosts', NULL, NULL,
+ _t('地址列表'), _t('每行单个地址,请仔细匹配以免误封杀'));
+
+ $form->addInput($hosts);
+ }
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form){}
+
+
+ /**
+ * 标记评论状态时的插件接口
+ *
+ * @access public
+ * @param array $comment 评论数据的结构体
+ * @param Typecho_Widget $commentWidget 评论组件
+ * @param string $status 评论状态
+ * @return void
+ */
+ public static function mark($comment, $commentWidget, $status)
+ {
+ if ('spam' == $comment['status'] && $status != 'spam') {
+ self::filter($comment, $commentWidget, NULL, 'submit-ham');
+ } else if ('spam' != $comment['status'] && $status == 'spam') {
+ self::filter($comment, $commentWidget, NULL, 'submit-spam');
+ }
+ }
+
+ /**
+ * 评论过滤器
+ *
+ * @access public
+ * @param array $comment 评论结构
+ * @param Typecho_Widget $post 被评论的文章
+ * @param array $result 返回的结果上下文
+ * @param string $api api地址
+ * @return void
+ */
+ public static function filter($comment, $post, $result, $api = 'comment-check')
+ {
+ $comment = empty($result) ? $comment : $result;
+
+ $options = Typecho_Widget::widget('Widget_Options');
+ $hosts = $options->plugin('BlockComment')->hosts;
+
+ $data = array(
+ 'blog' => $options->siteUrl,
+ 'user_ip' => $comment['ip'],
+ 'user_agent' => $comment['agent'],
+ 'referrer' => Typecho_Request::getInstance()->getReferer(),
+ 'permalink' => $post->permalink,
+ 'comment_type' => $comment['type'],
+ 'comment_author' => $comment['author'],
+ 'comment_author_email' => $comment['mail'],
+ 'comment_author_url' => $comment['url'],
+ 'comment_content' => $comment['text']
+ );
+
+ foreach(split("\n", $hosts) as $key => $value){
+ $value = trim($value);
+ if (strlen($value)) {
+ $regex = sprintf("/^%s/i", preg_quote($value));
+
+ // 如果提交者符合指定的 IP,则扔进垃圾评论中
+ if (preg_match($regex, $data['user_ip'])) {
+ $comment['status'] = 'spam';
+ break;
+ }
+ }
+ }
+
+ return $comment;
+ }
+}
diff --git a/ConnectToTwitter/OAuth.php b/ConnectToTwitter/OAuth.php
new file mode 100644
index 0000000..b36520e
--- /dev/null
+++ b/ConnectToTwitter/OAuth.php
@@ -0,0 +1,768 @@
+key = $key;
+ $this->secret = $secret;
+ $this->callback_url = $callback_url;
+ }/*}}}*/
+
+ function __toString() {/*{{{*/
+ return "OAuthConsumer[key=$this->key,secret=$this->secret]";
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthToken {/*{{{*/
+ // access tokens and request tokens
+ public $key;
+ public $secret;
+
+ /**
+ * key = the token
+ * secret = the token secret
+ */
+ function __construct($key, $secret) {/*{{{*/
+ $this->key = $key;
+ $this->secret = $secret;
+ }/*}}}*/
+
+ /**
+ * generates the basic string serialization of a token that a server
+ * would respond to request_token and access_token calls with
+ */
+ function to_string() {/*{{{*/
+ return "oauth_token=" . OAuthUtil::urlencode_rfc3986($this->key) .
+ "&oauth_token_secret=" . OAuthUtil::urlencode_rfc3986($this->secret);
+ }/*}}}*/
+
+ function __toString() {/*{{{*/
+ return $this->to_string();
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod {/*{{{*/
+ public function check_signature(&$request, $consumer, $token, $signature) {
+ $built = $this->build_signature($request, $consumer, $token);
+ return $built == $signature;
+ }
+}/*}}}*/
+
+class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ function get_name() {/*{{{*/
+ return "HMAC-SHA1";
+ }/*}}}*/
+
+ public function build_signature($request, $consumer, $token) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ $key_parts = array(
+ $consumer->secret,
+ ($token) ? $token->secret : ""
+ );
+
+ $key_parts = OAuthUtil::urlencode_rfc3986($key_parts);
+ $key = implode('&', $key_parts);
+
+ return base64_encode( hash_hmac('sha1', $base_string, $key, true));
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod {/*{{{*/
+ public function get_name() {/*{{{*/
+ return "PLAINTEXT";
+ }/*}}}*/
+
+ public function build_signature($request, $consumer, $token) {/*{{{*/
+ $sig = array(
+ OAuthUtil::urlencode_rfc3986($consumer->secret)
+ );
+
+ if ($token) {
+ array_push($sig, OAuthUtil::urlencode_rfc3986($token->secret));
+ } else {
+ array_push($sig, '');
+ }
+
+ $raw = implode("&", $sig);
+ // for debug purposes
+ $request->base_string = $raw;
+
+ return OAuthUtil::urlencode_rfc3986($raw);
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod {/*{{{*/
+ public function get_name() {/*{{{*/
+ return "RSA-SHA1";
+ }/*}}}*/
+
+ protected function fetch_public_cert(&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ // (2) fetch via http using a url provided by the requester
+ // (3) some sort of specific discovery code based on request
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_public_cert not implemented");
+ }/*}}}*/
+
+ protected function fetch_private_cert(&$request) {/*{{{*/
+ // not implemented yet, ideas are:
+ // (1) do a lookup in a table of trusted certs keyed off of consumer
+ //
+ // either way should return a string representation of the certificate
+ throw Exception("fetch_private_cert not implemented");
+ }/*}}}*/
+
+ public function build_signature(&$request, $consumer, $token) {/*{{{*/
+ $base_string = $request->get_signature_base_string();
+ $request->base_string = $base_string;
+
+ // Fetch the private key cert based on the request
+ $cert = $this->fetch_private_cert($request);
+
+ // Pull the private key ID from the certificate
+ $privatekeyid = openssl_get_privatekey($cert);
+
+ // Sign using the key
+ $ok = openssl_sign($base_string, $signature, $privatekeyid);
+
+ // Release the key resource
+ openssl_free_key($privatekeyid);
+
+ return base64_encode($signature);
+ } /*}}}*/
+
+ public function check_signature(&$request, $consumer, $token, $signature) {/*{{{*/
+ $decoded_sig = base64_decode($signature);
+
+ $base_string = $request->get_signature_base_string();
+
+ // Fetch the public key cert based on the request
+ $cert = $this->fetch_public_cert($request);
+
+ // Pull the public key ID from the certificate
+ $publickeyid = openssl_get_publickey($cert);
+
+ // Check the computed signature against the one passed in the query
+ $ok = openssl_verify($base_string, $decoded_sig, $publickeyid);
+
+ // Release the key resource
+ openssl_free_key($publickeyid);
+
+ return $ok == 1;
+ } /*}}}*/
+}/*}}}*/
+
+class OAuthRequest {/*{{{*/
+ private $parameters;
+ private $http_method;
+ private $http_url;
+ // for debug purposes
+ public $base_string;
+ public static $version = '1.0';
+
+ function __construct($http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $this->parameters = $parameters;
+ $this->http_method = $http_method;
+ $this->http_url = $http_url;
+ }/*}}}*/
+
+
+ /**
+ * attempt to build up a request from what was passed to the server
+ */
+ public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) {/*{{{*/
+ $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https';
+ @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
+ @$http_method or $http_method = $_SERVER['REQUEST_METHOD'];
+
+ $request_headers = OAuthRequest::get_headers();
+
+ // let the library user override things however they'd like, if they know
+ // which parameters to use then go for it, for example XMLRPC might want to
+ // do this
+ if ($parameters) {
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ } else {
+ // collect request parameters from query string (GET) and post-data (POST) if appropriate (note: POST vars have priority)
+ $req_parameters = $_GET;
+ if ($http_method == "POST" && @strstr($request_headers["Content-Type"], "application/x-www-form-urlencoded") ) {
+ $req_parameters = array_merge($req_parameters, $_POST);
+ }
+
+ // next check for the auth header, we need to do some extra stuff
+ // if that is the case, namely suck in the parameters from GET or POST
+ // so that we can include them in the signature
+ if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
+ $header_parameters = OAuthRequest::split_header($request_headers['Authorization']);
+ $parameters = array_merge($req_parameters, $header_parameters);
+ $req = new OAuthRequest($http_method, $http_url, $parameters);
+ } else $req = new OAuthRequest($http_method, $http_url, $req_parameters);
+ }
+
+ return $req;
+ }/*}}}*/
+
+ /**
+ * pretty much a helper function to set up the request
+ */
+ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) {/*{{{*/
+ @$parameters or $parameters = array();
+ $defaults = array("oauth_version" => OAuthRequest::$version,
+ "oauth_nonce" => OAuthRequest::generate_nonce(),
+ "oauth_timestamp" => OAuthRequest::generate_timestamp(),
+ "oauth_consumer_key" => $consumer->key);
+ $parameters = array_merge($defaults, $parameters);
+
+ if ($token) {
+ $parameters['oauth_token'] = $token->key;
+ }
+ return new OAuthRequest($http_method, $http_url, $parameters);
+ }/*}}}*/
+
+ public function set_parameter($name, $value) {/*{{{*/
+ $this->parameters[$name] = $value;
+ }/*}}}*/
+
+ public function get_parameter($name) {/*{{{*/
+ return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
+ }/*}}}*/
+
+ public function get_parameters() {/*{{{*/
+ return $this->parameters;
+ }/*}}}*/
+
+ /**
+ * Returns the normalized parameters of the request
+ *
+ * This will be all (except oauth_signature) parameters,
+ * sorted first by key, and if duplicate keys, then by
+ * value.
+ *
+ * The returned string will be all the key=value pairs
+ * concated by &.
+ *
+ * @return string
+ */
+ public function get_signable_parameters() {/*{{{*/
+ // Grab all parameters
+ $params = $this->parameters;
+
+ // Remove oauth_signature if present
+ if (isset($params['oauth_signature'])) {
+ unset($params['oauth_signature']);
+ }
+
+ // Urlencode both keys and values
+ $keys = OAuthUtil::urlencode_rfc3986(array_keys($params));
+ $values = OAuthUtil::urlencode_rfc3986(array_values($params));
+ $params = array_combine($keys, $values);
+
+ // Sort by keys (natsort)
+ uksort($params, 'strcmp');
+
+ // Generate key=value pairs
+ $pairs = array();
+ foreach ($params as $key=>$value ) {
+ if (is_array($value)) {
+ // If the value is an array, it's because there are multiple
+ // with the same key, sort them, then add all the pairs
+ natsort($value);
+ foreach ($value as $v2) {
+ $pairs[] = $key . '=' . $v2;
+ }
+ } else {
+ $pairs[] = $key . '=' . $value;
+ }
+ }
+
+ // Return the pairs, concated with &
+ return implode('&', $pairs);
+ }/*}}}*/
+
+ /**
+ * Returns the base string of this request
+ *
+ * The base string defined as the method, the url
+ * and the parameters (normalized), each urlencoded
+ * and the concated with &.
+ */
+ public function get_signature_base_string() {/*{{{*/
+ $parts = array(
+ $this->get_normalized_http_method(),
+ $this->get_normalized_http_url(),
+ $this->get_signable_parameters()
+ );
+
+ $parts = OAuthUtil::urlencode_rfc3986($parts);
+
+ return implode('&', $parts);
+ }/*}}}*/
+
+ /**
+ * just uppercases the http method
+ */
+ public function get_normalized_http_method() {/*{{{*/
+ return strtoupper($this->http_method);
+ }/*}}}*/
+
+ /**
+ * parses the url and rebuilds it to be
+ * scheme://host/path
+ */
+ public function get_normalized_http_url() {/*{{{*/
+ $parts = parse_url($this->http_url);
+
+ $port = @$parts['port'];
+ $scheme = $parts['scheme'];
+ $host = $parts['host'];
+ $path = @$parts['path'];
+
+ $port or $port = ($scheme == 'https') ? '443' : '80';
+
+ if (($scheme == 'https' && $port != '443')
+ || ($scheme == 'http' && $port != '80')) {
+ $host = "$host:$port";
+ }
+ return "$scheme://$host$path";
+ }/*}}}*/
+
+ /**
+ * builds a url usable for a GET request
+ */
+ public function to_url() {/*{{{*/
+ $out = $this->get_normalized_http_url() . "?";
+ $out .= $this->to_postdata();
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the data one would send in a POST request
+ *
+ * TODO(morten.fangel):
+ * this function might be easily replaced with http_build_query()
+ * and corrections for rfc3986 compatibility.. but not sure
+ */
+ public function to_postdata() {/*{{{*/
+ $total = array();
+ foreach ($this->parameters as $k => $v) {
+ if (is_array($v)) {
+ foreach ($v as $va) {
+ $total[] = OAuthUtil::urlencode_rfc3986($k) . "[]=" . OAuthUtil::urlencode_rfc3986($va);
+ }
+ } else {
+ $total[] = OAuthUtil::urlencode_rfc3986($k) . "=" . OAuthUtil::urlencode_rfc3986($v);
+ }
+ }
+ $out = implode("&", $total);
+ return $out;
+ }/*}}}*/
+
+ /**
+ * builds the Authorization: header
+ */
+ public function to_header() {/*{{{*/
+ $out ='Authorization: OAuth realm=""';
+ $total = array();
+ foreach ($this->parameters as $k => $v) {
+ if (substr($k, 0, 5) != "oauth") continue;
+ if (is_array($v)) throw new OAuthException('Arrays not supported in headers');
+ $out .= ',' . OAuthUtil::urlencode_rfc3986($k) . '="' . OAuthUtil::urlencode_rfc3986($v) . '"';
+ }
+ return $out;
+ }/*}}}*/
+
+ public function __toString() {/*{{{*/
+ return $this->to_url();
+ }/*}}}*/
+
+
+ public function sign_request($signature_method, $consumer, $token) {/*{{{*/
+ $this->set_parameter("oauth_signature_method", $signature_method->get_name());
+ $signature = $this->build_signature($signature_method, $consumer, $token);
+ $this->set_parameter("oauth_signature", $signature);
+ }/*}}}*/
+
+ public function build_signature($signature_method, $consumer, $token) {/*{{{*/
+ $signature = $signature_method->build_signature($this, $consumer, $token);
+ return $signature;
+ }/*}}}*/
+
+ /**
+ * util function: current timestamp
+ */
+ private static function generate_timestamp() {/*{{{*/
+ return time();
+ }/*}}}*/
+
+ /**
+ * util function: current nonce
+ */
+ private static function generate_nonce() {/*{{{*/
+ $mt = microtime();
+ $rand = mt_rand();
+
+ return md5($mt . $rand); // md5s look nicer than numbers
+ }/*}}}*/
+
+ /**
+ * util function for turning the Authorization: header into
+ * parameters, has to do some unescaping
+ */
+ private static function split_header($header) {/*{{{*/
+ $pattern = '/(([-_a-z]*)=("([^"]*)"|([^,]*)),?)/';
+ $offset = 0;
+ $params = array();
+ while (preg_match($pattern, $header, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) {
+ $match = $matches[0];
+ $header_name = $matches[2][0];
+ $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0];
+ $params[$header_name] = OAuthUtil::urldecode_rfc3986( $header_content );
+ $offset = $match[1] + strlen($match[0]);
+ }
+
+ if (isset($params['realm'])) {
+ unset($params['realm']);
+ }
+
+ return $params;
+ }/*}}}*/
+
+ /**
+ * helper to try to sort out headers for people who aren't running apache
+ */
+ private static function get_headers() {/*{{{*/
+ if (function_exists('apache_request_headers')) {
+ // we need this to get the actual Authorization: header
+ // because apache tends to tell us it doesn't exist
+ return apache_request_headers();
+ }
+ // otherwise we don't have apache and are just going to have to hope
+ // that $_SERVER actually contains what we need
+ $out = array();
+ foreach ($_SERVER as $key => $value) {
+ if (substr($key, 0, 5) == "HTTP_") {
+ // this is chaos, basically it is just there to capitalize the first
+ // letter of every word that is not an initial HTTP and strip HTTP
+ // code from przemek
+ $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
+ $out[$key] = $value;
+ }
+ }
+ return $out;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthServer {/*{{{*/
+ protected $timestamp_threshold = 300; // in seconds, five minutes
+ protected $version = 1.0; // hi blaine
+ protected $signature_methods = array();
+
+ protected $data_store;
+
+ function __construct($data_store) {/*{{{*/
+ $this->data_store = $data_store;
+ }/*}}}*/
+
+ public function add_signature_method($signature_method) {/*{{{*/
+ $this->signature_methods[$signature_method->get_name()] =
+ $signature_method;
+ }/*}}}*/
+
+ // high level functions
+
+ /**
+ * process a request_token request
+ * returns the request token on success
+ */
+ public function fetch_request_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // no token required for the initial token request
+ $token = NULL;
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_request_token($consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * process an access_token request
+ * returns the access token on success
+ */
+ public function fetch_access_token(&$request) {/*{{{*/
+ $this->get_version($request);
+
+ $consumer = $this->get_consumer($request);
+
+ // requires authorized request token
+ $token = $this->get_token($request, $consumer, "request");
+
+
+ $this->check_signature($request, $consumer, $token);
+
+ $new_token = $this->data_store->new_access_token($token, $consumer);
+
+ return $new_token;
+ }/*}}}*/
+
+ /**
+ * verify an api call, checks all the parameters
+ */
+ public function verify_request(&$request) {/*{{{*/
+ $this->get_version($request);
+ $consumer = $this->get_consumer($request);
+ $token = $this->get_token($request, $consumer, "access");
+ $this->check_signature($request, $consumer, $token);
+ return array($consumer, $token);
+ }/*}}}*/
+
+ // Internals from here
+ /**
+ * version 1
+ */
+ private function get_version(&$request) {/*{{{*/
+ $version = $request->get_parameter("oauth_version");
+ if (!$version) {
+ $version = 1.0;
+ }
+ if ($version && $version != $this->version) {
+ throw new OAuthException("OAuth version '$version' not supported");
+ }
+ return $version;
+ }/*}}}*/
+
+ /**
+ * figure out the signature with some defaults
+ */
+ private function get_signature_method(&$request) {/*{{{*/
+ $signature_method =
+ @$request->get_parameter("oauth_signature_method");
+ if (!$signature_method) {
+ $signature_method = "PLAINTEXT";
+ }
+ if (!in_array($signature_method,
+ array_keys($this->signature_methods))) {
+ throw new OAuthException(
+ "Signature method '$signature_method' not supported try one of the following: " . implode(", ", array_keys($this->signature_methods))
+ );
+ }
+ return $this->signature_methods[$signature_method];
+ }/*}}}*/
+
+ /**
+ * try to find the consumer for the provided request's consumer key
+ */
+ private function get_consumer(&$request) {/*{{{*/
+ $consumer_key = @$request->get_parameter("oauth_consumer_key");
+ if (!$consumer_key) {
+ throw new OAuthException("Invalid consumer key");
+ }
+
+ $consumer = $this->data_store->lookup_consumer($consumer_key);
+ if (!$consumer) {
+ throw new OAuthException("Invalid consumer");
+ }
+
+ return $consumer;
+ }/*}}}*/
+
+ /**
+ * try to find the token for the provided request's token key
+ */
+ private function get_token(&$request, $consumer, $token_type="access") {/*{{{*/
+ $token_field = @$request->get_parameter('oauth_token');
+ $token = $this->data_store->lookup_token(
+ $consumer, $token_type, $token_field
+ );
+ if (!$token) {
+ throw new OAuthException("Invalid $token_type token: $token_field");
+ }
+ return $token;
+ }/*}}}*/
+
+ /**
+ * all-in-one function to check the signature on a request
+ * should guess the signature method appropriately
+ */
+ private function check_signature(&$request, $consumer, $token) {/*{{{*/
+ // this should probably be in a different method
+ $timestamp = @$request->get_parameter('oauth_timestamp');
+ $nonce = @$request->get_parameter('oauth_nonce');
+
+ $this->check_timestamp($timestamp);
+ $this->check_nonce($consumer, $token, $nonce, $timestamp);
+
+ $signature_method = $this->get_signature_method($request);
+
+ $signature = $request->get_parameter('oauth_signature');
+ $valid_sig = $signature_method->check_signature(
+ $request,
+ $consumer,
+ $token,
+ $signature
+ );
+
+ if (!$valid_sig) {
+ throw new OAuthException("Invalid signature");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the timestamp is new enough
+ */
+ private function check_timestamp($timestamp) {/*{{{*/
+ // verify that timestamp is recentish
+ $now = time();
+ if ($now - $timestamp > $this->timestamp_threshold) {
+ throw new OAuthException("Expired timestamp, yours $timestamp, ours $now");
+ }
+ }/*}}}*/
+
+ /**
+ * check that the nonce is not repeated
+ */
+ private function check_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // verify that the nonce is uniqueish
+ $found = $this->data_store->lookup_nonce($consumer, $token, $nonce, $timestamp);
+ if ($found) {
+ throw new OAuthException("Nonce already used: $nonce");
+ }
+ }/*}}}*/
+
+
+
+}/*}}}*/
+
+class OAuthDataStore {/*{{{*/
+ function lookup_consumer($consumer_key) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ // implement me
+ }/*}}}*/
+
+ function new_request_token($consumer) {/*{{{*/
+ // return a new token attached to this consumer
+ }/*}}}*/
+
+ function new_access_token($token, $consumer) {/*{{{*/
+ // return a new access token attached to this consumer
+ // for the user associated with this token if the request token
+ // is authorized
+ // should also invalidate the request token
+ }/*}}}*/
+
+}/*}}}*/
+
+
+/* A very naive dbm-based oauth storage
+ */
+class SimpleOAuthDataStore extends OAuthDataStore {/*{{{*/
+ private $dbh;
+
+ function __construct($path = "oauth.gdbm") {/*{{{*/
+ $this->dbh = dba_popen($path, 'c', 'gdbm');
+ }/*}}}*/
+
+ function __destruct() {/*{{{*/
+ dba_close($this->dbh);
+ }/*}}}*/
+
+ function lookup_consumer($consumer_key) {/*{{{*/
+ $rv = dba_fetch("consumer_$consumer_key", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthConsumer)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_token($consumer, $token_type, $token) {/*{{{*/
+ $rv = dba_fetch("${token_type}_${token}", $this->dbh);
+ if ($rv === FALSE) {
+ return NULL;
+ }
+ $obj = unserialize($rv);
+ if (!($obj instanceof OAuthToken)) {
+ return NULL;
+ }
+ return $obj;
+ }/*}}}*/
+
+ function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/
+ if (dba_exists("nonce_$nonce", $this->dbh)) {
+ return TRUE;
+ } else {
+ dba_insert("nonce_$nonce", "1", $this->dbh);
+ return FALSE;
+ }
+ }/*}}}*/
+
+ function new_token($consumer, $type="request") {/*{{{*/
+ $key = md5(time());
+ $secret = time() + time();
+ $token = new OAuthToken($key, md5(md5($secret)));
+ if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) {
+ throw new OAuthException("doooom!");
+ }
+ return $token;
+ }/*}}}*/
+
+ function new_request_token($consumer) {/*{{{*/
+ return $this->new_token($consumer, "request");
+ }/*}}}*/
+
+ function new_access_token($token, $consumer) {/*{{{*/
+
+ $token = $this->new_token($consumer, 'access');
+ dba_delete("request_" . $token->key, $this->dbh);
+ return $token;
+ }/*}}}*/
+}/*}}}*/
+
+class OAuthUtil {/*{{{*/
+ public static function urlencode_rfc3986($input) {/*{{{*/
+ if (is_array($input)) {
+ return array_map(array('OAuthUtil','urlencode_rfc3986'), $input);
+ } else if (is_scalar($input)) {
+ return str_replace('+', ' ',
+ str_replace('%7E', '~', rawurlencode($input)));
+ } else {
+ return '';
+ }
+ }/*}}}*/
+
+
+ // This decode function isn't taking into consideration the above
+ // modifications to the encoding process. However, this method doesn't
+ // seem to be used anywhere so leaving it as is.
+ public static function urldecode_rfc3986($string) {/*{{{*/
+ return rawurldecode($string);
+ }/*}}}*/
+}/*}}}*/
\ No newline at end of file
diff --git a/ConnectToTwitter/Plugin.php b/ConnectToTwitter/Plugin.php
new file mode 100644
index 0000000..9f29058
--- /dev/null
+++ b/ConnectToTwitter/Plugin.php
@@ -0,0 +1,144 @@
+finishComment = array('ConnectToTwitter_Plugin', 'postToTwitter');
+ Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('ConnectToTwitter_Plugin', 'initComment');
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate() {
+
+ }
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+ $consumerKey = new Typecho_Widget_Helper_Form_Element_Text('consumerKey', NULL, '',
+ _t('Consumer Key'), _t('Your application consumer key from Twitter.com. '));
+ $form->addInput($consumerKey->addRule('required', _t('You must give the Consumer Key from Twitter.com')));
+
+ $consumerSecret = new Typecho_Widget_Helper_Form_Element_Text('consumerSecret', NULL, '',
+ _t('Consumer Secret'), _t('Your application consumer secret from Twitter.com. '));
+ $form->addInput($consumerSecret->addRule('required', _t('You must give the Consumer Key from Twitter.com')));
+ }
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form){}
+
+ public static function initComment($api)
+ {
+ session_start();
+ $options = Typecho_Widget::widget('Widget_Options');
+ $config = $options->plugin('ConnectToTwitter');
+
+ //发送请求到twitter
+ if(isset($api->request->connect_to_twitter))
+ {
+ $to = new TwitterOAuth($config->consumerKey, $config->consumerSecret);
+
+ $tok = $to->getRequestToken();
+
+ Typecho_Cookie::set('oauth_request_token', $tok['oauth_token']);
+ Typecho_Cookie::set('oauth_request_token_secret', $tok['oauth_token_secret']);
+
+ /* Build the authorization URL */
+ $request_link = $to->getAuthorizeURL($tok['oauth_token']);
+ header('Location:'.$request_link);
+ }
+
+ //从twitter返回
+ if(isset($api->request->oauth_token)) {
+ if(Typecho_Cookie::get('oauth_request_token') && Typecho_Cookie::get('oauth_request_token_secret'))
+ {
+ $to = new TwitterOAuth($config->consumerKey, $config->consumerSecret, Typecho_Cookie::get('oauth_request_token'), Typecho_Cookie::get('oauth_request_token_secret'));
+
+ $tok = $to->getAccessToken();
+
+ Typecho_Cookie::set('oauth_access_token', $tok['oauth_token'], time()+60*60*24*30);
+ Typecho_Cookie::set('oauth_access_token_secret', $tok['oauth_token_secret'], time()+60*60*24*30);
+
+ $info_json = $to->OAuthRequest('https://twitter.com/account/verify_credentials.json', array(), 'GET');
+ $info = Typecho_Json::decode($info_json, true);
+
+ self::twitterLogin($info, $api);
+ }
+ }
+ }
+
+ //登录,暂时做为setcookie,以后要和用户帐号相关联
+ public static function twitterLogin($info, $api)
+ {
+ if (!empty($info['screen_name'])) {
+ Typecho_Cookie::set('__typecho_remember_author', $info['screen_name'], time()+60*60*24*30);
+ }
+
+ if (!empty($info['url'])) {
+ Typecho_Cookie::set('__typecho_remember_url', $info['url'], time()+60*60*24*30);
+ }
+ }
+
+ //发送信息到twitter
+ public static function postToTwitter($api)
+ {
+ if(Typecho_Cookie::get('oauth_access_token') && Typecho_Cookie::get('oauth_access_token_secret') && $api->request->post_to_twitter) {
+ $options = Typecho_Widget::widget('Widget_Options');
+ $config = $options->plugin('ConnectToTwitter');
+ $to = new TwitterOAuth($config->consumerKey, $config->consumerSecret, Typecho_Cookie::get('oauth_access_token'), Typecho_Cookie::get('oauth_access_token_secret'));
+
+ $url_array = array();
+ $url_array = explode('?', $api->request->getReferer());
+ $url = $url_array[0] . '#comment-' . $api->coid;
+ $post = $api->text . ' ( from ' . $url . ' ) ';
+ $twitter = $to->OAuthRequest('https://twitter.com/statuses/update.xml', array('status' => $post), 'POST');
+ }
+ return $comment;
+ }
+
+ function showButton()
+ {
+ if(Typecho_Cookie::get('oauth_access_token') && Typecho_Cookie::get('oauth_access_token_secret')) {
+ echo '
+ * $parseConf = array(
+ * 'Include' => array(
+ * 'base' => '/path/to/scripts/'
+ * )
+ * );
+ *
+ *
+ * Note that most default rules do not need any parsing configuration.
+ *
+ * @access public
+ *
+ * @var array
+ *
+ */
+ public $parseConf = array();
+
+
+ /**
+ *
+ * Custom configuration for rules at the rendering stage.
+ *
+ * Because rendering may be different for each target format, the
+ * first-level element in this array is always a format name (e.g.,
+ * 'Xhtml').
+ *
+ * Within that first level element, the subsequent elements match the
+ * $parseConf format. That is, the sub-key is the rendering rule name,
+ * and the sub-value is an array of key-value configuration pairs
+ * corresponding to the $conf property in the target rendering rule.
+ *
+ * @access public
+ *
+ * @var array
+ *
+ */
+ public $renderConf = array(
+ 'Docbook' => array(),
+ 'Latex' => array(),
+ 'Pdf' => array(),
+ 'Plain' => array(),
+ 'Rtf' => array(),
+ 'Xhtml' => array()
+ );
+
+
+ /**
+ *
+ * Custom configuration for the output format itself.
+ *
+ * Even though Text_Wiki will render the tokens from parsed text,
+ * the format itself may require some configuration. For example,
+ * RTF needs to know font names and sizes, PDF requires page layout
+ * information, and DocBook needs a section hierarchy. This array
+ * matches the $conf property of the the format-level renderer
+ * (e.g., Text_Wiki_Render_Xhtml).
+ *
+ * In this array, the key is the rendering format name, and the value is
+ * an array of key-value configuration pairs corresponding to the $conf
+ * property in the rendering format rule.
+ *
+ * @access public
+ *
+ * @var array
+ *
+ */
+ public $formatConf = array(
+ 'Docbook' => array(),
+ 'Latex' => array(),
+ 'Pdf' => array(),
+ 'Plain' => array(),
+ 'Rtf' => array(),
+ 'Xhtml' => array()
+ );
+
+
+ /**
+ *
+ * The delimiter for token numbers of parsed elements in source text.
+ *
+ * @access public
+ *
+ * @var string
+ *
+ */
+ public $delim = "\xFF";
+
+
+ /**
+ *
+ * The tokens generated by rules as the source text is parsed.
+ *
+ * As Text_Wiki applies rule classes to the source text, it will
+ * replace portions of the text with a delimited token number. This
+ * is the array of those tokens, representing the replaced text and
+ * any options set by the parser for that replaced text.
+ *
+ * The tokens array is sequential; each element is itself a sequential
+ * array where element 0 is the name of the rule that generated the
+ * token, and element 1 is an associative array where the key is an
+ * option name and the value is an option value.
+ *
+ * @access private
+ *
+ * @var array
+ *
+ */
+ public $tokens = array();
+
+ /**
+ * How many tokens generated pro rules.
+ *
+ * Intended to load only necessary render objects
+ *
+ * @access private
+ * @var array
+ */
+ private $_countRulesTokens = array();
+
+
+ /**
+ *
+ * The source text to which rules will be applied.
+ *
+ * This text will be transformed in-place, which means that it will
+ * change as the rules are applied.
+ *
+ * @access public
+ *
+ * @var string
+ *
+ */
+ public $source = '';
+
+ /**
+ * The output text
+ *
+ * @var string
+ */
+ protected $output = '';
+
+
+ /**
+ *
+ * Array of rule parsers.
+ *
+ * Text_Wiki creates one instance of every rule that is applied to
+ * the source text; this array holds those instances. The array key
+ * is the rule name, and the array value is an instance of the rule
+ * class.
+ *
+ * @access private
+ *
+ * @var array
+ *
+ */
+
+ protected $parseObj = array();
+
+
+ /**
+ *
+ * Array of rule renderers.
+ *
+ * Text_Wiki creates one instance of every rule that is applied to
+ * the source text; this array holds those instances. The array key
+ * is the rule name, and the array value is an instance of the rule
+ * class.
+ *
+ * @access private
+ *
+ * @var array
+ *
+ */
+ protected $renderObj = array();
+
+
+ /**
+ *
+ * Array of format renderers.
+ *
+ * @access private
+ *
+ * @var array
+ *
+ */
+ protected $formatObj = array();
+
+
+ /**
+ *
+ * Array of paths to search, in order, for parsing and rendering rules.
+ *
+ * @access private
+ *
+ * @var array
+ *
+ */
+ protected $path = array(
+ 'parse' => array(),
+ 'render' => array()
+ );
+
+
+
+ /**
+ *
+ * The directory separator character.
+ *
+ * @access private
+ *
+ * @var string
+ *
+ */
+ private $_dirSep = DIRECTORY_SEPARATOR;
+
+ /**
+ * Temporary configuration variable
+ *
+ * @var string
+ */
+ protected $renderingType = 'preg';
+
+ /**
+ * Stack of rendering callbacks
+ *
+ * @var Array
+ */
+ private $_renderCallbacks = array();
+
+ /**
+ * Current output block
+ *
+ * @var string
+ */
+ private $_block;
+
+ /**
+ * A stack of blocks
+ *
+ * @param Array
+ */
+ private $_blocks;
+
+ /**
+ *
+ * Constructor.
+ *
+ * **DEPRECATED**
+ * Please use the singleton() or factory() methods.
+ *
+ * @access public
+ *
+ * @param array $rules The set of rules to load for this object. Defaults
+ * to null, which will load the default ruleset for this parser.
+ */
+
+ function __construct($rules = null)
+ {
+ if (is_array($rules)) {
+ $this->rules = array();
+ foreach ($rules as $rule) {
+ $this->rules[] = ucfirst($rule);
+ }
+ }
+
+ /*
+ $this->addPath(
+ 'parse',
+ $this->fixPath(dirname(__FILE__)) . 'Wiki/Parse/Default/'
+ );
+ */
+
+ $this->addPath(
+ 'parse', $this->fixPath(dirname(__FILE__) . '/Parse/')
+ );
+
+ $this->addPath(
+ 'render',
+ $this->fixPath(dirname(__FILE__) . '/Render/' )
+ );
+
+ $this->renderingType = 'char';
+ $this->setRenderConf('xhtml', 'center', 'css', 'center');
+ $this->setRenderConf('xhtml', 'url', 'target', null);
+ }
+
+
+ /**
+ * Singleton.
+ *
+ * This avoids instantiating multiple Text_Wiki instances where a number
+ * of objects are required in one call, e.g. to save memory in a
+ * CMS invironment where several parsers are required in a single page.
+ *
+ * $single = & singleton();
+ *
+ * or
+ *
+ * $single = & singleton('Parser', array('Prefilter', 'Delimiter', 'Code', 'Function',
+ * 'Html', 'Raw', 'Include', 'Embed', 'Anchor', 'Heading', 'Toc', 'Horiz',
+ * 'Break', 'Blockquote', 'List', 'Deflist', 'Table', 'Image', 'Phplookup',
+ * 'Center', 'Newline', 'Paragraph', 'Url', 'Freelink', 'Interwiki', 'Wikilink',
+ * 'Colortext', 'Strong', 'Bold', 'Emphasis', 'Italic', 'Underline', 'Tt',
+ * 'Superscript', 'Subscript', 'Revise', 'Tighten'));
+ *
+ * Call using a subset of this list. The order of passing rulesets in the
+ * $rules array is important!
+ *
+ * After calling this, call $single->setParseConf(), setRenderConf() or setFormatConf()
+ * as usual for a constructed object of this class.
+ *
+ * The internal static array of singleton objects has no index on the parser
+ * rules, the only index is on the parser name. So if you call this multiple
+ * times with different rules but the same parser name, you will get the same
+ * static parser object each time.
+ *
+ * @access public
+ * @static
+ * @since Method available since Release 1.1.0
+ * @param string $parser The parser to be used (defaults to 'Default').
+ * @param array $rules The set of rules to instantiate the object. This
+ * will only be used when the first call to singleton is made, if included
+ * in further calls it will be effectively ignored.
+ * @return &object a reference to the Text_Wiki unique instantiation.
+ */
+ /*
+ public function &singleton($parser = 'Default', $rules = null)
+ {
+ static $only = array();
+ if (!isset($only[$parser])) {
+ $ret = & Text_Wiki::factory($parser, $rules);
+ if (Text_Wiki::isError($ret)) {
+ return $ret;
+ }
+ $only[$parser] =& $ret;
+ }
+ return $only[$parser];
+ }
+ */
+
+ /**
+ * Returns a Text_Wiki Parser class for the specified parser.
+ *
+ * @access public
+ * @static
+ * @param string $parser The name of the parse to instantiate
+ * you need to have Text_Wiki_XXX installed to use $parser = 'XXX', it's E_FATAL
+ * @param array $rules The rules to pass into the constructor
+ * {@see Text_Wiki::singleton} for a list of rules
+ * @return Text_Wiki a Parser object extended from Text_Wiki
+ */
+ /*
+ public function &factory($parser = 'Default', $rules = null)
+ {
+ $class = 'Text_Wiki_' . ucfirst(strtolower($parser));
+ $file = str_replace('_', '/', $class).'.php';
+ if (!class_exists($class)) {
+ require_once $file;
+ if (!class_exists($class)) {
+ return Text_Wiki::error(
+ 'Class ' . $class . ' does not exist after requiring '. $file .
+ ', install package ' . $class . "\n");
+ }
+ }
+
+ $obj =& new $class($rules);
+ return $obj;
+ }
+ */
+
+ /**
+ *
+ * Set parser configuration for a specific rule and key.
+ *
+ * @access public
+ *
+ * @param string $rule The parse rule to set config for.
+ *
+ * @param array|string $arg1 The full config array to use for the
+ * parse rule, or a conf key in that array.
+ *
+ * @param string $arg2 The config value for the key.
+ *
+ * @return void
+ *
+ */
+ public function setParseConf($rule, $arg1, $arg2 = null)
+ {
+ $rule = ucwords(strtolower($rule));
+
+ if (! isset($this->parseConf[$rule])) {
+ $this->parseConf[$rule] = array();
+ }
+
+ // if first arg is an array, use it as the entire
+ // conf array for the rule. otherwise, treat arg1
+ // as a key and arg2 as a value for the rule conf.
+ if (is_array($arg1)) {
+ $this->parseConf[$rule] = $arg1;
+ } else {
+ $this->parseConf[$rule][$arg1] = $arg2;
+ }
+ }
+
+
+ /**
+ *
+ * Get parser configuration for a specific rule and key.
+ *
+ * @access public
+ *
+ * @param string $rule The parse rule to get config for.
+ *
+ * @param string $key A key in the conf array; if null,
+ * returns the entire conf array.
+ *
+ * @return mixed The whole conf array if no key is specified,
+ * or the specific conf key value.
+ *
+ */
+ public function getParseConf($rule, $key = null)
+ {
+ $rule = ucwords(strtolower($rule));
+
+ // the rule does not exist
+ if (! isset($this->parseConf[$rule])) {
+ return null;
+ }
+
+ // no key requested, return the whole array
+ if (is_null($key)) {
+ return $this->parseConf[$rule];
+ }
+
+ // does the requested key exist?
+ if (isset($this->parseConf[$rule][$key])) {
+ // yes, return that value
+ return $this->parseConf[$rule][$key];
+ } else {
+ // no
+ return null;
+ }
+ }
+
+
+ /**
+ *
+ * Set renderer configuration for a specific format, rule, and key.
+ *
+ * @access public
+ *
+ * @param string $format The render format to set config for.
+ *
+ * @param string $rule The render rule to set config for in the format.
+ *
+ * @param array|string $arg1 The config array, or the config key
+ * within the render rule.
+ *
+ * @param string $arg2 The config value for the key.
+ *
+ * @return void
+ *
+ */
+
+ function setRenderConf($format, $rule, $arg1, $arg2 = null)
+ {
+ $format = ucwords(strtolower($format));
+ $rule = ucwords(strtolower($rule));
+
+ if (! isset($this->renderConf[$format])) {
+ $this->renderConf[$format] = array();
+ }
+
+ if (! isset($this->renderConf[$format][$rule])) {
+ $this->renderConf[$format][$rule] = array();
+ }
+
+ // if first arg is an array, use it as the entire
+ // conf array for the render rule. otherwise, treat arg1
+ // as a key and arg2 as a value for the render rule conf.
+ if (is_array($arg1)) {
+ $this->renderConf[$format][$rule] = $arg1;
+ } else {
+ $this->renderConf[$format][$rule][$arg1] = $arg2;
+ }
+ }
+
+
+ /**
+ *
+ * Get renderer configuration for a specific format, rule, and key.
+ *
+ * @access public
+ *
+ * @param string $format The render format to get config for.
+ *
+ * @param string $rule The render format rule to get config for.
+ *
+ * @param string $key A key in the conf array; if null,
+ * returns the entire conf array.
+ *
+ * @return mixed The whole conf array if no key is specified,
+ * or the specific conf key value.
+ *
+ */
+
+ function getRenderConf($format, $rule, $key = null)
+ {
+ $format = ucwords(strtolower($format));
+ $rule = ucwords(strtolower($rule));
+
+ if (! isset($this->renderConf[$format]) ||
+ ! isset($this->renderConf[$format][$rule])) {
+ return null;
+ }
+
+ // no key requested, return the whole array
+ if (is_null($key)) {
+ return $this->renderConf[$format][$rule];
+ }
+
+ // does the requested key exist?
+ if (isset($this->renderConf[$format][$rule][$key])) {
+ // yes, return that value
+ return $this->renderConf[$format][$rule][$key];
+ } else {
+ // no
+ return null;
+ }
+
+ }
+
+ /**
+ *
+ * Set format configuration for a specific rule and key.
+ *
+ * @access public
+ *
+ * @param string $format The format to set config for.
+ *
+ * @param string $key The config key within the format.
+ *
+ * @param string $val The config value for the key.
+ *
+ * @return void
+ *
+ */
+
+ function setFormatConf($format, $arg1, $arg2 = null)
+ {
+ if (! is_array($this->formatConf[$format])) {
+ $this->formatConf[$format] = array();
+ }
+
+ // if first arg is an array, use it as the entire
+ // conf array for the format. otherwise, treat arg1
+ // as a key and arg2 as a value for the format conf.
+ if (is_array($arg1)) {
+ $this->formatConf[$format] = $arg1;
+ } else {
+ $this->formatConf[$format][$arg1] = $arg2;
+ }
+ }
+
+
+
+ /**
+ *
+ * Get configuration for a specific format and key.
+ *
+ * @access public
+ *
+ * @param string $format The format to get config for.
+ *
+ * @param mixed $key A key in the conf array; if null,
+ * returns the entire conf array.
+ *
+ * @return mixed The whole conf array if no key is specified,
+ * or the specific conf key value.
+ *
+ */
+
+ function getFormatConf($format, $key = null)
+ {
+ // the format does not exist
+ if (! isset($this->formatConf[$format])) {
+ return null;
+ }
+
+ // no key requested, return the whole array
+ if (is_null($key)) {
+ return $this->formatConf[$format];
+ }
+
+ // does the requested key exist?
+ if (isset($this->formatConf[$format][$key])) {
+ // yes, return that value
+ return $this->formatConf[$format][$key];
+ } else {
+ // no
+ return null;
+ }
+ }
+
+
+ /**
+ *
+ * Inserts a rule into to the rule set.
+ *
+ * @access public
+ *
+ * @param string $name The name of the rule. Should be different from
+ * all other keys in the rule set.
+ *
+ * @param string $tgt The rule after which to insert this new rule. By
+ * default (null) the rule is inserted at the end; if set to '', inserts
+ * at the beginning.
+ *
+ * @return void
+ *
+ */
+
+ function insertRule($name, $tgt = null)
+ {
+ $name = ucwords(strtolower($name));
+ if (! is_null($tgt)) {
+ $tgt = ucwords(strtolower($tgt));
+ }
+
+ // does the rule name to be inserted already exist?
+ if (in_array($name, $this->rules)) {
+ // yes, return
+ return null;
+ }
+
+ // the target name is not null, and not '', but does not exist
+ // in the list of rules. this means we're trying to insert after
+ // a target key, but the target key isn't there.
+ if (! is_null($tgt) && $tgt != '' &&
+ ! in_array($tgt, $this->rules)) {
+ return false;
+ }
+
+ // if $tgt is null, insert at the end. We know this is at the
+ // end (instead of resetting an existing rule) becuase we exited
+ // at the top of this method if the rule was already in place.
+ if (is_null($tgt)) {
+ $this->rules[] = $name;
+ return true;
+ }
+
+ // save a copy of the current rules, then reset the rule set
+ // so we can insert in the proper place later.
+ // where to insert the rule?
+ if ($tgt == '') {
+ // insert at the beginning
+ array_unshift($this->rules, $name);
+ return true;
+ }
+
+ // insert after the named rule
+ $tmp = $this->rules;
+ $this->rules = array();
+
+ foreach ($tmp as $val) {
+ $this->rules[] = $val;
+ if ($val == $tgt) {
+ $this->rules[] = $name;
+ }
+ }
+
+ return true;
+
+ }
+
+
+ /**
+ *
+ * Delete (remove or unset) a rule from the $rules property.
+ *
+ * @access public
+ *
+ * @param string $rule The name of the rule to remove.
+ *
+ * @return void
+ *
+ */
+
+ function deleteRule($name)
+ {
+ $name = ucwords(strtolower($name));
+ $key = array_search($name, $this->rules);
+ if ($key !== false) {
+ unset($this->rules[$key]);
+ }
+ }
+
+
+ /**
+ *
+ * Change from one rule to another in-place.
+ *
+ * @access public
+ *
+ * @param string $old The name of the rule to change from.
+ *
+ * @param string $new The name of the rule to change to.
+ *
+ * @return void
+ *
+ */
+
+ function changeRule($old, $new)
+ {
+ $old = ucwords(strtolower($old));
+ $new = ucwords(strtolower($new));
+ $key = array_search($old, $this->rules);
+ if ($key !== false) {
+ // delete the new name , case it was already there
+ $this->deleteRule($new);
+ $this->rules[$key] = $new;
+ }
+ }
+
+
+ /**
+ *
+ * Enables a rule so that it is applied when parsing.
+ *
+ * @access public
+ *
+ * @param string $rule The name of the rule to enable.
+ *
+ * @return void
+ *
+ */
+
+ function enableRule($name)
+ {
+ $name = ucwords(strtolower($name));
+ $key = array_search($name, $this->disable);
+ if ($key !== false) {
+ unset($this->disable[$key]);
+ }
+ }
+
+
+ /**
+ *
+ * Disables a rule so that it is not applied when parsing.
+ *
+ * @access public
+ *
+ * @param string $rule The name of the rule to disable.
+ *
+ * @return void
+ *
+ */
+
+ function disableRule($name)
+ {
+ $name = ucwords(strtolower($name));
+ $key = array_search($name, $this->disable);
+ if ($key === false) {
+ $this->disable[] = $name;
+ }
+ }
+
+
+ /**
+ *
+ * Parses and renders the text passed to it, and returns the results.
+ *
+ * First, the method parses the source text, applying rules to the
+ * text as it goes. These rules will modify the source text
+ * in-place, replacing some text with delimited tokens (and
+ * populating the $this->tokens array as it goes).
+ *
+ * Next, the method renders the in-place tokens into the requested
+ * output format.
+ *
+ * Finally, the method returns the transformed text. Note that the
+ * source text is transformed in place; once it is transformed, it is
+ * no longer the same as the original source text.
+ *
+ * @access public
+ *
+ * @param string $text The source text to which wiki rules should be
+ * applied, both for parsing and for rendering.
+ *
+ * @param string $format The target output format, typically 'xhtml'.
+ * If a rule does not support a given format, the output from that
+ * rule is rule-specific.
+ *
+ * @return string The transformed wiki text.
+ *
+ */
+ function transform($text, $format = 'Xhtml')
+ {
+ $this->parse($text);
+ return $this->render($format);
+ }
+
+
+ /**
+ *
+ * Sets the $_source text property, then parses it in place and
+ * retains tokens in the $_tokens array property.
+ *
+ * @access public
+ *
+ * @param string $text The source text to which wiki rules should be
+ * applied, both for parsing and for rendering.
+ *
+ * @return void
+ *
+ */
+
+ function parse($text)
+ {
+ // set the object property for the source text
+ $this->source = $text;
+
+ // reset the tokens.
+ $this->tokens = array();
+ $this->_countRulesTokens = array();
+
+ // apply the parse() method of each requested rule to the source
+ // text.
+ foreach ($this->rules as $name) {
+ // do not parse the rules listed in $disable
+ if (! in_array($name, $this->disable)) {
+
+ // load the parsing object
+ $this->loadParseObj($name);
+
+ // load may have failed; only parse if
+ // an object is in the array now
+ if (is_object($this->parseObj[$name])) {
+ $this->parseObj[$name]->parse();
+ }
+ }
+ }
+ }
+
+
+ /**
+ *
+ * Renders tokens back into the source text, based on the requested format.
+ *
+ * @access public
+ *
+ * @param string $format The target output format, typically 'xhtml'.
+ * If a rule does not support a given format, the output from that
+ * rule is rule-specific.
+ *
+ * @return string The transformed wiki text.
+ *
+ */
+
+ function render($format = 'Xhtml')
+ {
+ // the rendering method we're going to use from each rule
+ $format = ucwords(strtolower($format));
+
+ // the eventual output text
+ $this->output = '';
+
+ // when passing through the parsed source text, keep track of when
+ // we are in a delimited section
+ $in_delim = false;
+
+ // when in a delimited section, capture the token key number
+ $key = '';
+
+ // load the format object, or crap out if we can't find it
+ $result = $this->loadFormatObj($format);
+ if ($this->isError($result)) {
+ return $result;
+ }
+
+ /*
+ * hunked by feelinglucky..
+ // pre-rendering activity
+ if (is_object($this->formatObj[$format])) {
+ $this->output .= $this->formatObj[$format]->pre();
+ }
+ */
+ // load the render objects
+ foreach (array_keys($this->_countRulesTokens) as $rule) {
+ $this->loadRenderObj($format, $rule);
+ }
+
+
+ if ($this->renderingType == 'preg') {
+ $this->output = preg_replace_callback('/'.$this->delim.'(\d+)'.$this->delim.'/',
+ array(&$this, '_renderToken'),
+ $this->source);
+
+ /*
+ //Damn strtok()! Why does it "skip" empty parts of the string. It's useless now!
+ } elseif ($this->renderingType == 'strtok') {
+ echo ''.htmlentities($this->source).''; + $t = strtok($this->source, $this->delim); + $inToken = true; + $i = 0; + while ($t !== false) { + echo 'Token: '.$i.'
"'.htmlentities($t).'"
"; + } + + // ending + if ($type == 'end') { + return $pad . "\n"; + } + } +} +?> diff --git a/Creole/Render/Xhtml/Bold.php b/Creole/Render/Xhtml/Bold.php new file mode 100644 index 0000000..8bc59e8 --- /dev/null +++ b/Creole/Render/Xhtml/Bold.php @@ -0,0 +1,57 @@ + + * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 + * @version CVS: $Id: Bold.php 182 2008-09-14 15:56:00Z i.feelinglucky $ + * @link http://pear.php.net/package/Text_Wiki + */ + +/** + * This class renders bold text in XHTML. + * + * @category Text + * @package Text_Wiki + * @author Paul M. Jones
+ 'css_code' => null, // class for generic
+ 'css_php' => null, // class for PHP
+ 'css_html' => null, // class for HTML
+ 'css_filename' => null // class for optional filename
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $text = $options['text'];
+ $attr = $options['attr'];
+ $type = strtolower($attr['type']);
+
+ $css = $this->formatConf(' class="%s"', 'css');
+ $css_code = $this->formatConf(' class="%s"', 'css_code');
+ $css_php = $this->formatConf(' class="%s"', 'css_php');
+ $css_html = $this->formatConf(' class="%s"', 'css_html');
+ $css_filename = $this->formatConf(' class="%s"', 'css_filename');
+
+ if ($type == 'php') {
+ if (substr($options['text'], 0, 5) != '"; // ... tags)
+ ob_start();
+ highlight_string($text);
+ $text = ob_get_contents();
+ ob_end_clean();
+
+ // replace
tags with simple newlines.
+ // replace non-breaking space with simple spaces.
+ // translate HTML and color to XHTML and style.
+ // courtesy of research by A. Kalin :-).
+ $map = array(
+ '
' => "\n",
+ ' ' => ' ',
+ ' '' => '',
+ 'color="' => 'style="color:'
+ );
+ $text = strtr($text, $map);
+
+ // get rid of the last newline inside the code block
+ // (becuase higlight_string puts one there)
+ if (substr($text, -8) == "\n") {
+ $text = substr($text, 0, -8) . "";
+ }
+
+ // replace all tags with classed tags
+ if ($css_php) {
+ $text = str_replace('', "", $text);
+ }
+
+ // done
+ $text = "$text
";
+
+ } elseif ($type == 'html' || $type == 'xhtml') {
+
+ // HTML code example:
+ // add opening and closing tags,
+ // convert tabs to four spaces,
+ // convert entities.
+ $text = str_replace("\t", " ", $text);
+ $text = "\n$text\n";
+ $text = $this->textEncode($text);
+ $text = "$text
";
+
+ } else {
+ // generic code example:
+ // convert tabs to four spaces,
+ // convert entities.
+ $text = str_replace("\t", " ", $text);
+ $text = $this->textEncode($text);
+ $text = "$text
";
+ }
+
+ if ($css_filename && isset($attr['filename'])) {
+ $text = "" .
+ $attr['filename'] . '' . $text;
+ }
+
+ return "\n$text\n\n";
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Colortext.php b/Creole/Render/Xhtml/Colortext.php
new file mode 100644
index 0000000..8b6d534
--- /dev/null
+++ b/Creole/Render/Xhtml/Colortext.php
@@ -0,0 +1,79 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Colortext.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders colored text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Colortext extends Text_Wiki_Render {
+
+ var $colors = array(
+ 'aqua',
+ 'black',
+ 'blue',
+ 'fuchsia',
+ 'gray',
+ 'green',
+ 'lime',
+ 'maroon',
+ 'navy',
+ 'olive',
+ 'purple',
+ 'red',
+ 'silver',
+ 'teal',
+ 'white',
+ 'yellow'
+ );
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $type = $options['type'];
+ $color = $options['color'];
+
+ if (! in_array($color, $this->colors) && $color{0} != '#') {
+ $color = '#' . $color;
+ }
+
+ if ($type == 'start') {
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Deflist.php b/Creole/Render/Xhtml/Deflist.php
new file mode 100644
index 0000000..0a80c9c
--- /dev/null
+++ b/Creole/Render/Xhtml/Deflist.php
@@ -0,0 +1,87 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Deflist.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders definition lists in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Deflist extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css_dl' => null,
+ 'css_dt' => null,
+ 'css_dd' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $type = $options['type'];
+ $pad = " ";
+
+ switch ($type) {
+
+ case 'list_start':
+ $css = $this->formatConf(' class="%s"', 'css_dl');
+ return "\n";
+ break;
+
+ case 'list_end':
+ return "
\n\n";
+ break;
+
+ case 'term_start':
+ $css = $this->formatConf(' class="%s"', 'css_dt');
+ return $pad . "";
+ break;
+
+ case 'term_end':
+ return " \n";
+ break;
+
+ case 'narr_start':
+ $css = $this->formatConf(' class="%s"', 'css_dd');
+ return $pad . $pad . "";
+ break;
+
+ case 'narr_end':
+ return " \n";
+ break;
+
+ default:
+ return '';
+
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Delete.php b/Creole/Render/Xhtml/Delete.php
new file mode 100644
index 0000000..ae55423
--- /dev/null
+++ b/Creole/Render/Xhtml/Delete.php
@@ -0,0 +1,58 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Delete.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders underlined text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Delete extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ //$css = $this->formatConf(' class="%s"', 'css');
+ //return "";
+ //return "";
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Delimiter.php b/Creole/Render/Xhtml/Delimiter.php
new file mode 100644
index 0000000..c9543ba
--- /dev/null
+++ b/Creole/Render/Xhtml/Delimiter.php
@@ -0,0 +1,46 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Delimiter.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class set back the replaced delimiters in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Delimiter extends Text_Wiki_Render {
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ return $options['text'];
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Embed.php b/Creole/Render/Xhtml/Embed.php
new file mode 100644
index 0000000..cf5517a
--- /dev/null
+++ b/Creole/Render/Xhtml/Embed.php
@@ -0,0 +1,46 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Embed.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class replaces the embedded php output in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Embed extends Text_Wiki_Render {
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ return $options['text'];
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Emphasis.php b/Creole/Render/Xhtml/Emphasis.php
new file mode 100644
index 0000000..be06c37
--- /dev/null
+++ b/Creole/Render/Xhtml/Emphasis.php
@@ -0,0 +1,58 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Emphasis.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders emphasized text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Emphasis extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Font.php b/Creole/Render/Xhtml/Font.php
new file mode 100644
index 0000000..1127f15
--- /dev/null
+++ b/Creole/Render/Xhtml/Font.php
@@ -0,0 +1,83 @@
+
+ * @copyright 2005 bertrand Gugger
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Font.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * Font rule render class (used for BBCode)
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Bertrand Gugger
+ * @copyright 2005 bertrand Gugger
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ * @see Text_Wiki::Text_Wiki_Render()
+ */
+class Text_Wiki_Render_Xhtml_Font extends Text_Wiki_Render {
+
+/* var $size = array(
+ 'xx-small',
+ 'x-small',
+ 'small',
+ 'medium',
+ 'large',
+ 'x-large',
+ 'xx-large',
+ 'larger',
+ 'smaller'
+ );
+ var $units = array(
+ 'em',
+ 'ex',
+ 'px',
+ 'in',
+ 'cm',
+ 'mm',
+ 'pt',
+ 'pc'
+ );
+*/
+
+ /**
+ * Renders a token into text matching the requested format.
+ * process the font size option
+ *
+ * @access public
+ * @param array $options The "options" portion of the token (second element).
+ * @return string The text rendered from the token options.
+ */
+ function token($options)
+ {
+ if ($options['type'] == 'end') {
+ return ' ';
+ }
+ if ($options['type'] != 'start') {
+ return '';
+ }
+
+ $ret = '';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Freelink.php b/Creole/Render/Xhtml/Freelink.php
new file mode 100644
index 0000000..0fade11
--- /dev/null
+++ b/Creole/Render/Xhtml/Freelink.php
@@ -0,0 +1,35 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Freelink.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * The wikilink render class.
+ */
+require_once 'Text/Wiki/Render/Xhtml/Wikilink.php';
+
+/**
+ * This class renders free links in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Freelink extends Text_Wiki_Render_Xhtml_Wikilink {
+ // renders identically to wikilinks, only the parsing is different :-)
+}
+
+?>
diff --git a/Creole/Render/Xhtml/Function.php b/Creole/Render/Xhtml/Function.php
new file mode 100644
index 0000000..a4e7e82
--- /dev/null
+++ b/Creole/Render/Xhtml/Function.php
@@ -0,0 +1,108 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Function.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders a function description in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Function extends Text_Wiki_Render {
+
+ var $conf = array(
+ // list separator for params and throws
+ 'list_sep' => ', ',
+
+ // the "main" format string
+ 'format_main' => '%access %return %name ( %params ) %throws',
+
+ // the looped format string for required params
+ 'format_param' => '%type %descr',
+
+ // the looped format string for params with default values
+ 'format_paramd' => '[%type %descr default %default]',
+
+ // the looped format string for throws
+ 'format_throws' => 'throws %type %descr'
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ extract($options); // name, access, return, params, throws
+
+ // build the baseline output
+ $output = $this->conf['format_main'];
+ $output = str_replace('%access', $this->textEncode($access), $output);
+ $output = str_replace('%return', $this->textEncode($return), $output);
+ $output = str_replace('%name', $this->textEncode($name), $output);
+
+ // build the set of params
+ $list = array();
+ foreach ($params as $key => $val) {
+
+ // is there a default value?
+ if ($val['default']) {
+ $tmp = $this->conf['format_paramd'];
+ } else {
+ $tmp = $this->conf['format_param'];
+ }
+
+ // add the param elements
+ $tmp = str_replace('%type', $this->textEncode($val['type']), $tmp);
+ $tmp = str_replace('%descr', $this->textEncode($val['descr']), $tmp);
+ $tmp = str_replace('%default', $this->textEncode($val['default']), $tmp);
+ $list[] = $tmp;
+ }
+
+ // insert params into output
+ $tmp = implode($this->conf['list_sep'], $list);
+ $output = str_replace('%params', $tmp, $output);
+
+ // build the set of throws
+ $list = array();
+ foreach ($throws as $key => $val) {
+ $tmp = $this->conf['format_throws'];
+ $tmp = str_replace('%type', $this->textEncode($val['type']), $tmp);
+ $tmp = str_replace('%descr', $this->textEncode($val['descr']), $tmp);
+ $list[] = $tmp;
+ }
+
+ // insert throws into output
+ $tmp = implode($this->conf['list_sep'], $list);
+ $output = str_replace('%throws', $tmp, $output);
+
+ // close the div and return the output
+ $output .= '
';
+ return "\n$output\n\n";
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Heading.php b/Creole/Render/Xhtml/Heading.php
new file mode 100644
index 0000000..ce3c50d
--- /dev/null
+++ b/Creole/Render/Xhtml/Heading.php
@@ -0,0 +1,54 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Heading.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders headings in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Heading extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css_h1' => null,
+ 'css_h2' => null,
+ 'css_h3' => null,
+ 'css_h4' => null,
+ 'css_h5' => null,
+ 'css_h6' => null
+ );
+
+ function token($options)
+ {
+ $collapse = null;
+ static $jsOutput = false;
+ // get nice variable names (id, type, level)
+ extract($options);
+
+ switch($type) {
+ case 'start':
+ //$css = $this->formatConf(' class="%s"', "css_h$level");
+ return '';
+ //return '';
+ case 'end':
+ return ' ';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Horiz.php b/Creole/Render/Xhtml/Horiz.php
new file mode 100644
index 0000000..f8738e7
--- /dev/null
+++ b/Creole/Render/Xhtml/Horiz.php
@@ -0,0 +1,51 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Horiz.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders an horizontal bar in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Horiz extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "
\n";
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Html.php b/Creole/Render/Xhtml/Html.php
new file mode 100644
index 0000000..bce7f87
--- /dev/null
+++ b/Creole/Render/Xhtml/Html.php
@@ -0,0 +1,47 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Html.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders preformated html in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Html extends Text_Wiki_Render {
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ return $options['text'];
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Image.php b/Creole/Render/Xhtml/Image.php
new file mode 100644
index 0000000..58edba6
--- /dev/null
+++ b/Creole/Render/Xhtml/Image.php
@@ -0,0 +1,183 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Image.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class inserts an image in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Image extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'base' => null,
+ 'url_base' => null,
+ 'css' => null,
+ 'css_link' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ // note the image source
+ $src = $options['src'];
+
+ // is the source a local file or URL?
+ if (strpos($src, '://') === false) {
+ // the source refers to a local file.
+ // add the URL base to it.
+ $src = $this->getConf('base', '/') . $src;
+ }
+
+ // stephane@metacites.net
+ // is the image clickable?
+ if (isset($options['attr']['link'])) {
+ // yes, the image is clickable.
+ // are we linked to a URL or a wiki page?
+ if (strpos($options['attr']['link'], '://')) {
+ // it's a URL, prefix the URL base
+ $href = $this->getConf('url_base') . $options['attr']['link'];
+ } else {
+ // it's a WikiPage; assume it exists.
+ /** @todo This needs to honor sprintf wikilinks (pmjones) */
+ /** @todo This needs to honor interwiki (pmjones) */
+ /** @todo This needs to honor freelinks (pmjones) */
+ $href = $this->wiki->getRenderConf('xhtml', 'wikilink', 'view_url') .
+ $options['attr']['link'];
+ }
+ } else {
+ // image is not clickable.
+ $href = null;
+ }
+ // unset so it won't show up as an attribute
+ unset($options['attr']['link']);
+
+ // stephane@metacites.net -- 25/07/2004
+ // use CSS for all alignment
+ if (isset($options['attr']['align'])) {
+ // make sure we have a style attribute
+ if (!isset($options['attr']['style'])) {
+ // no style, set up a blank one
+ $options['attr']['style'] = '';
+ } else {
+ // style exists, add a space
+ $options['attr']['style'] .= ' ';
+ }
+
+ if ($options['attr']['align'] == 'center') {
+ // add a "center" style to the existing style.
+ $options['attr']['style'] .=
+ 'display: block; margin-left: auto; margin-right: auto;';
+ } else {
+ // add a float style to the existing style
+ $options['attr']['style'] .=
+ 'float: '.$options['attr']['align'];
+ }
+
+ // unset so it won't show up as an attribute
+ unset($options['attr']['align']);
+ }
+
+ // stephane@metacites.net -- 25/07/2004
+ // try to guess width and height
+ if (! isset($options['attr']['width']) &&
+ ! isset($options['attr']['height'])) {
+
+ // does the source refer to a local file or a URL?
+ if (strpos($src,'://')) {
+ // is a URL link
+ $imageFile = $src;
+ } elseif ($src[0] == '.') {
+ // reg at dav-muz dot net -- 2005-03-07
+ // is a local file on relative path.
+ $imageFile = $src; # ...don't do anything because it's perfect!
+ } else {
+ // is a local file on absolute path.
+ $imageFile = $_SERVER['DOCUMENT_ROOT'] . $src;
+ }
+
+ // attempt to get the image size
+ $imageSize = @getimagesize($imageFile);
+
+ if (is_array($imageSize)) {
+ $options['attr']['width'] = $imageSize[0];
+ $options['attr']['height'] = $imageSize[1];
+ }
+
+ }
+
+ // start the HTML output
+ $output = 'formatConf(' class="%s"', 'css');
+
+ // add the attributes to the output, and be sure to
+ // track whether or not we find an "alt" attribute
+ $alt = false;
+ foreach ($options['attr'] as $key => $val) {
+
+ // track the 'alt' attribute
+ if (strtolower($key) == 'alt') {
+ $alt = true;
+ }
+
+ // the 'class' attribute overrides the CSS class conf
+ if (strtolower($key) == 'class') {
+ $css = null;
+ }
+
+ $key = $this->textEncode($key);
+ $val = $this->textEncode($val);
+ $output .= " $key=\"$val\"";
+ }
+
+ // always add an "alt" attribute per Stephane Solliec
+ if (! $alt) {
+ $alt = $this->textEncode(basename($options['src']));
+ $output .= " alt=\"$alt\"";
+ }
+
+ // end the image tag with the automatic CSS class (if any)
+ $output .= "$css />";
+
+ // was the image clickable?
+ if ($href) {
+ // yes, add the href and return
+ $href = $this->textEncode($href);
+ $css = $this->formatConf(' class="%s"', 'css_link');
+ $output = "$output";
+ }
+
+ return $output;
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Include.php b/Creole/Render/Xhtml/Include.php
new file mode 100644
index 0000000..3072770
--- /dev/null
+++ b/Creole/Render/Xhtml/Include.php
@@ -0,0 +1,32 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Include.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders included maekup in XHTML. (empty)
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Include extends Text_Wiki_Render {
+ function token()
+ {
+ return '';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Interwiki.php b/Creole/Render/Xhtml/Interwiki.php
new file mode 100644
index 0000000..a71268c
--- /dev/null
+++ b/Creole/Render/Xhtml/Interwiki.php
@@ -0,0 +1,103 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Interwiki.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders inter wikis links in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Interwiki extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'sites' => array(
+ 'MeatBall' => 'http://www.usemod.com/cgi-bin/mb.pl?%s',
+ 'Advogato' => 'http://advogato.org/%s',
+ 'Wiki' => 'http://c2.com/cgi/wiki?%s'
+ ),
+ 'target' => '_blank',
+ 'css' => null
+ );
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $text = $options['text'];
+ if (isset($options['url'])) {
+ // calculated by the parser (e.g. Mediawiki)
+ $href = $options['url'];
+ } else {
+ $site = $options['site'];
+ // toggg 2006/02/05 page name must be url encoded (e.g. may contain spaces)
+ $page = $this->urlEncode($options['page']);
+
+ if (isset($this->conf['sites'][$site])) {
+ $href = $this->conf['sites'][$site];
+ } else {
+ return $text;
+ }
+
+ // old form where page is at end,
+ // or new form with %s placeholder for sprintf()?
+ if (strpos($href, '%s') === false) {
+ // use the old form
+ $href = $href . $page;
+ } else {
+ // use the new form
+ $href = sprintf($href, $page);
+ }
+ }
+
+ // allow for alternative targets
+ $target = $this->getConf('target');
+
+ // build base link
+ $css = $this->formatConf(' class="%s"', 'css');
+ $text = $this->textEncode($text);
+ $output = "textEncode($target);
+ $output .= " onclick=\"window.open(this.href, '$target');";
+ $output .= " return false;\"";
+ }
+
+ $output .= ">$text";
+
+ return $output;
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Italic.php b/Creole/Render/Xhtml/Italic.php
new file mode 100644
index 0000000..fbee3d8
--- /dev/null
+++ b/Creole/Render/Xhtml/Italic.php
@@ -0,0 +1,57 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Italic.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders italic text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Italic extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/List.php b/Creole/Render/Xhtml/List.php
new file mode 100644
index 0000000..cee17b7
--- /dev/null
+++ b/Creole/Render/Xhtml/List.php
@@ -0,0 +1,172 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: List.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders bullet and ordered lists in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_List extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css_ol' => null,
+ 'css_ol_li' => null,
+ 'css_ul' => null,
+ 'css_ul_li' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * This rendering method is syntactically and semantically compliant
+ * with XHTML 1.1 in that sub-lists are part of the previous list item.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ // make nice variables (type, level, count)
+ extract($options);
+
+ // set up indenting so that the results look nice; we do this
+ // in two steps to avoid str_pad mathematics. ;-)
+ $pad = str_pad('', $level, "\t");
+ $pad = str_replace("\t", ' ', $pad);
+
+ switch ($type) {
+
+ case 'bullet_list_start':
+
+ // build the base HTML
+ $css = $this->formatConf(' class="%s"', 'css_ul');
+ $html = "";
+
+ /*
+ // if this is the opening block for the list,
+ // put an extra newline in front of it so the
+ // output looks nice.
+ if ($level == 0) {
+ $html = "\n$html";
+ }
+ */
+
+ // done!
+ return $html;
+ break;
+
+ case 'bullet_list_end':
+
+ // build the base HTML
+ $html = "\n$pad
";
+
+ // if this is the closing block for the list,
+ // put extra newlines after it so the output
+ // looks nice.
+ if ($level == 0) {
+ $html .= "\n\n";
+ }
+
+ // done!
+ return $html;
+ break;
+
+ case 'number_list_start':
+ if (isset($format)) {
+ $format = ' type="' . $format . '"';
+ } else {
+ $format = '';
+ }
+ // build the base HTML
+ $css = $this->formatConf(' class="%s"', 'css_ol');
+ $html = "";
+
+ /*
+ // if this is the opening block for the list,
+ // put an extra newline in front of it so the
+ // output looks nice.
+ if ($level == 0) {
+ $html = "\n$html";
+ }
+ */
+
+ // done!
+ return $html;
+ break;
+
+ case 'number_list_end':
+
+ // build the base HTML
+ $html = "\n$pad
";
+
+ // if this is the closing block for the list,
+ // put extra newlines after it so the output
+ // looks nice.
+ if ($level == 0) {
+ $html .= "\n\n";
+ }
+
+ // done!
+ return $html;
+ break;
+
+ case 'bullet_item_start':
+ case 'number_item_start':
+
+ // pick the proper CSS class
+ if ($type == 'bullet_item_start') {
+ $css = $this->formatConf(' class="%s"', 'css_ul_li');
+ } else {
+ $css = $this->formatConf(' class="%s"', 'css_ol_li');
+ }
+
+ // build the base HTML
+ $html = "\n$pad";
+
+ // for the very first item in the list, do nothing.
+ // but for additional items, be sure to close the
+ // previous item.
+ if ($count > 0) {
+ $html = " $html";
+ }
+
+ // done!
+ return $html;
+ break;
+
+ case 'bullet_item_end':
+ case 'number_item_end':
+ default:
+ // ignore item endings and all other types.
+ // item endings are taken care of by the other types
+ // depending on their place in the list.
+ return '';
+ break;
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Newline.php b/Creole/Render/Xhtml/Newline.php
new file mode 100644
index 0000000..c08b7ad
--- /dev/null
+++ b/Creole/Render/Xhtml/Newline.php
@@ -0,0 +1,35 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Newline.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders new lines in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Newline extends Text_Wiki_Render {
+
+
+ function token($options)
+ {
+ return "
\n";
+ }
+}
+
+?>
diff --git a/Creole/Render/Xhtml/Page.php b/Creole/Render/Xhtml/Page.php
new file mode 100644
index 0000000..912f360
--- /dev/null
+++ b/Creole/Render/Xhtml/Page.php
@@ -0,0 +1,46 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Page.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders page markers in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Page extends Text_Wiki_Render {
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ return 'PAGE MARKER HERE*&^%$#^$%*PAGEMARKERHERE';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Paragraph.php b/Creole/Render/Xhtml/Paragraph.php
new file mode 100644
index 0000000..07b2250
--- /dev/null
+++ b/Creole/Render/Xhtml/Paragraph.php
@@ -0,0 +1,59 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Paragraph.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders paragraphs in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Paragraph extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ extract($options); //type
+
+ if ($type == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($type == 'end') {
+ return "
\n\n";
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Phplookup.php b/Creole/Render/Xhtml/Phplookup.php
new file mode 100644
index 0000000..2e598a8
--- /dev/null
+++ b/Creole/Render/Xhtml/Phplookup.php
@@ -0,0 +1,81 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Phplookup.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders a link to php functions description in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Phplookup extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'target' => '_blank',
+ 'css' => null
+ );
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $text = trim($options['text']);
+ $css = $this->formatConf(' class="%s"', 'css');
+
+ // start the html
+ $output = "getConf('target', '');
+ if ($target && $target != '_self') {
+ // use a "popup" window. this is XHTML compliant, suggested by
+ // Aaron Kalin. uses the $target as the new window name.
+ $target = $this->textEncode($target);
+ $output .= " onclick=\"window.open(this.href, '$target');";
+ $output .= " return false;\"";
+ }
+
+ // take off the final parens for functions
+ if (substr($text, -2) == '()') {
+ $q = substr($text, 0, -2);
+ } else {
+ $q = $text;
+ }
+
+ // toggg 2006/02/05 page name must be url encoded (e.g. may contain spaces)
+ $q = $this->urlEncode($q);
+ $text = $this->textEncode($text);
+
+ // finish and return
+ $output .= " href=\"http://php.net/$q\">$text";
+ return $output;
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Plugin.php b/Creole/Render/Xhtml/Plugin.php
new file mode 100644
index 0000000..3419c1e
--- /dev/null
+++ b/Creole/Render/Xhtml/Plugin.php
@@ -0,0 +1,47 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Plugin.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders wiki plugins in XHTML. (empty)
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Plugin extends Text_Wiki_Render {
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ * Plugins produce wiki markup so are processed by parsing, no tokens produced
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ return '';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Prefilter.php b/Creole/Render/Xhtml/Prefilter.php
new file mode 100644
index 0000000..64d87dc
--- /dev/null
+++ b/Creole/Render/Xhtml/Prefilter.php
@@ -0,0 +1,34 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Prefilter.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class implements a Text_Wiki_Render_Xhtml to "pre-filter" source text so
+ * that line endings are consistently \n, lines ending in a backslash \
+ * are concatenated with the next line, and tabs are converted to spaces.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Prefilter extends Text_Wiki_Render {
+ function token()
+ {
+ return '';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Preformatted.php b/Creole/Render/Xhtml/Preformatted.php
new file mode 100644
index 0000000..ea079fb
--- /dev/null
+++ b/Creole/Render/Xhtml/Preformatted.php
@@ -0,0 +1,47 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Preformatted.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders preformated text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Preformatted extends Text_Wiki_Render {
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ $text = $this->textEncode($options['text']);
+ return ''.$text.'
';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Raw.php b/Creole/Render/Xhtml/Raw.php
new file mode 100644
index 0000000..dbbdc19
--- /dev/null
+++ b/Creole/Render/Xhtml/Raw.php
@@ -0,0 +1,46 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Raw.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders not processed blocks in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Raw extends Text_Wiki_Render {
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ return $this->textEncode($options['text']);
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Revise.php b/Creole/Render/Xhtml/Revise.php
new file mode 100644
index 0000000..bad6f02
--- /dev/null
+++ b/Creole/Render/Xhtml/Revise.php
@@ -0,0 +1,68 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Revise.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders revision marks in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Revise extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css_ins' => null,
+ 'css_del' => null
+ );
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'del_start') {
+ $css = $this->formatConf(' class="%s"', 'css_del');
+ return "";
+ }
+
+ if ($options['type'] == 'del_end') {
+ return "";
+ }
+
+ if ($options['type'] == 'ins_start') {
+ $css = $this->formatConf(' class="%s"', 'css_ins');
+ return "";
+ }
+
+ if ($options['type'] == 'ins_end') {
+ return "";
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Smiley.php b/Creole/Render/Xhtml/Smiley.php
new file mode 100644
index 0000000..0e9a0ad
--- /dev/null
+++ b/Creole/Render/Xhtml/Smiley.php
@@ -0,0 +1,74 @@
+
+ * @copyright 2005 bertrand Gugger
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Smiley.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * Smiley rule Xhtml render class
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Bertrand Gugger
+ * @copyright 2005 bertrand Gugger
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ * @see Text_Wiki::Text_Wiki_Render()
+ */
+class Text_Wiki_Render_Xhtml_Smiley extends Text_Wiki_Render {
+
+ /**
+ * Configuration keys for this rule
+ * 'prefix' => the path to smileys images inclusive file name prefix,
+ * starts with '/' ==> abolute reference
+ * if no file names prefix but some folder, terminates with '/'
+ * 'extension' => the file extension (inclusive '.'), e.g. :
+ * if prefix 'smileys/icon_' and extension '.gif'
+ * ':)' whose name is 'smile' will give relative file 'smileys/icon_smile.gif'
+ * if prefix '/image/smileys/' and extension '.png': absolute '/image/smileys/smile.gif'
+ * 'css' => optional style applied to smileys
+ *
+ * @access public
+ * @var array 'config-key' => mixed config-value
+ */
+ var $conf = array(
+ 'prefix' => 'images/smiles/icon_',
+ 'extension' => '.gif',
+ 'css' => null
+ );
+
+ /**
+ * Renders a token into text matching the requested format.
+ * process the Smileys
+ *
+ * @access public
+ * @param array $options The "options" portion of the token (second element).
+ * @return string The text rendered from the token options.
+ */
+ function token($options)
+ {
+ $imageFile = $this->getConf('prefix') . $options['name'] . $this->getConf('extension');
+
+ // attempt to get the image size
+ $imageSize = @getimagesize($imageFile);
+
+ // return the HTML output
+ return 'formatConf(' class="%s"', 'css') . ' />';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Specialchar.php b/Creole/Render/Xhtml/Specialchar.php
new file mode 100644
index 0000000..36221b4
--- /dev/null
+++ b/Creole/Render/Xhtml/Specialchar.php
@@ -0,0 +1,52 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Specialchar.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders special characters in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_SpecialChar extends Text_Wiki_Render {
+
+ var $types = array('~bs~' => '\',
+ '~hs~' => ' ',
+ '~amp~' => '&',
+ '~ldq~' => '“',
+ '~rdq~' => '”',
+ '~lsq~' => '‘',
+ '~rsq~' => '’',
+ '~c~' => '©',
+ '~--~' => '—',
+ '" -- "' => '—',
+ '" -- "' => '—',
+ '~lt~' => '<',
+ '~gt~' => '>');
+
+ function token($options)
+ {
+ if (isset($this->types[$options['char']])) {
+ return $this->types[$options['char']];
+ } else {
+ return ''.substr($options['char'], 1, -1).';';
+ }
+ }
+}
+
+?>
diff --git a/Creole/Render/Xhtml/Strong.php b/Creole/Render/Xhtml/Strong.php
new file mode 100644
index 0000000..9bc0b95
--- /dev/null
+++ b/Creole/Render/Xhtml/Strong.php
@@ -0,0 +1,58 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Strong.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders text marked as strong in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Strong extends Text_Wiki_Render {
+
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Subscript.php b/Creole/Render/Xhtml/Subscript.php
new file mode 100644
index 0000000..efe6192
--- /dev/null
+++ b/Creole/Render/Xhtml/Subscript.php
@@ -0,0 +1,57 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Subscript.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders subscript text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Subscript extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Superscript.php b/Creole/Render/Xhtml/Superscript.php
new file mode 100644
index 0000000..a6c2b95
--- /dev/null
+++ b/Creole/Render/Xhtml/Superscript.php
@@ -0,0 +1,57 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Superscript.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders superscript text in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Superscript extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => null
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Table.php b/Creole/Render/Xhtml/Table.php
new file mode 100644
index 0000000..66fd867
--- /dev/null
+++ b/Creole/Render/Xhtml/Table.php
@@ -0,0 +1,140 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Table.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders tables in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Table extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css_table' => null,
+ 'css_caption' => null,
+ 'css_tr' => null,
+ 'css_th' => null,
+ 'css_td' => null
+ );
+
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ // make nice variable names (type, attr, span)
+ $span = $rowspan = 1;
+ extract($options);
+
+ // free format
+ $format = isset($format) ? ' '. $format : '';
+
+ $pad = ' ';
+
+ switch ($type) {
+
+ case 'table_start':
+ $css = $this->formatConf(' class="%s"', 'css_table');
+ return "\n\n\n";
+ break;
+
+ case 'table_end':
+ return "
\n\n";
+ break;
+
+ case 'caption_start':
+ $css = $this->formatConf(' class="%s"', 'css_caption');
+ return "\n";
+ break;
+
+ case 'caption_end':
+ return " \n";
+ break;
+
+ case 'row_start':
+ $css = $this->formatConf(' class="%s"', 'css_tr');
+ return "$pad\n";
+ break;
+
+ case 'row_end':
+ return "$pad \n";
+ break;
+
+ case 'cell_start':
+
+ // base html
+ $html = $pad . $pad;
+
+ // is this a TH or TD cell?
+ if ($attr == 'header') {
+ // start a header cell
+ $css = $this->formatConf(' class="%s"', 'css_th');
+ $html .= "formatConf(' class="%s"', 'css_td');
+ $html .= " 1) {
+ $html .= " colspan=\"$span\"";
+ }
+
+ // add the row span
+ if ($rowspan > 1) {
+ $html .= " rowspan=\"$rowspan\"";
+ }
+
+ // add alignment
+ if ($attr != 'header' && $attr != '') {
+ $html .= " style=\"text-align: $attr;\"";
+ }
+
+ // done!
+ $html .= "$format>";
+ return $html;
+ break;
+
+ case 'cell_end':
+ if ($attr == 'header') {
+ return "\n";
+ } else {
+ return " \n";
+ }
+ break;
+
+ default:
+ return '';
+
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Tighten.php b/Creole/Render/Xhtml/Tighten.php
new file mode 100644
index 0000000..128764f
--- /dev/null
+++ b/Creole/Render/Xhtml/Tighten.php
@@ -0,0 +1,34 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Tighten.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class makes the tightening in XHTML. (empty)
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Tighten extends Text_Wiki_Render {
+
+
+ function token()
+ {
+ return '';
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Titlebar.php b/Creole/Render/Xhtml/Titlebar.php
new file mode 100644
index 0000000..7a1be0a
--- /dev/null
+++ b/Creole/Render/Xhtml/Titlebar.php
@@ -0,0 +1,57 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Titlebar.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class renders a title bar in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Titlebar extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css' => 'titlebar'
+ );
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ if ($options['type'] == 'start') {
+ $css = $this->formatConf(' class="%s"', 'css');
+ return "";
+ }
+
+ if ($options['type'] == 'end') {
+ return '';
+ }
+ }
+}
+?>
diff --git a/Creole/Render/Xhtml/Toc.php b/Creole/Render/Xhtml/Toc.php
new file mode 100644
index 0000000..c4a52cf
--- /dev/null
+++ b/Creole/Render/Xhtml/Toc.php
@@ -0,0 +1,115 @@
+
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version CVS: $Id: Toc.php 182 2008-09-14 15:56:00Z i.feelinglucky $
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+
+/**
+ * This class inserts a table of content in XHTML.
+ *
+ * @category Text
+ * @package Text_Wiki
+ * @author Paul M. Jones
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Wiki
+ */
+class Text_Wiki_Render_Xhtml_Toc extends Text_Wiki_Render {
+
+ var $conf = array(
+ 'css_list' => null,
+ 'css_item' => null,
+ 'title' => 'Table of Contents',
+ 'div_id' => 'toc',
+ 'collapse' => true
+ );
+
+ var $min = 2;
+
+ /**
+ *
+ * Renders a token into text matching the requested format.
+ *
+ * @access public
+ *
+ * @param array $options The "options" portion of the token (second
+ * element).
+ *
+ * @return string The text rendered from the token options.
+ *
+ */
+
+ function token($options)
+ {
+ // type, id, level, count, attr
+ extract($options);
+
+ switch ($type) {
+
+ case 'list_start':
+
+ $css = $this->getConf('css_list');
+ $html = '';
+
+ // collapse div within a table?
+ if ($this->getConf('collapse')) {
+ $html .= '';
+ $html .= "\n";
+ }
+
+ // add the div, class, and id
+ $html .= 'getConf('div_id');
+ if ($div_id) {
+ $html .= " id=\"$div_id\"";
+ }
+
+ // add the title, and done
+ $html .= '>';
+ $html .= $this->getConf('title');
+ return $html;
+ break;
+
+ case 'list_end':
+ if ($this->getConf('collapse')) {
+ return "\n\n
\n\n";
+ } else {
+ return "\n
| ';
+
+ return $source . $numberItem . $sourceItem . '
+ * This file could be used by goodle code to allow syntax highlight for + * Virtual AGC SVN repository or if you don't want to commonize + * the header for the agc/aea html assembly listing. + * + * @author ohommes@alumni.cmu.edu + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // A line comment that starts with ; + [PR.PR_COMMENT, /^#[^\r\n]*/, null, '#'], + // Whitespace + [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], + // A double quoted, possibly multi-line, string. + [PR.PR_STRING, /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] + ], + [ + [PR.PR_KEYWORD, /^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,null], + [PR.PR_TYPE, /^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null], + // A single quote possibly followed by a word that optionally ends with + // = ! or ?. + [PR.PR_LITERAL, + /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/], + // Any word including labels that optionally ends with = ! or ?. + [PR.PR_PLAIN, + /^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i], + // A printable non-space non-special character + [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0()\"\\\';]+/] + ]), + ['apollo', 'agc', 'aea']); diff --git a/GoogleCodePrettify/src/lang-css.js b/GoogleCodePrettify/src/lang-css.js new file mode 100644 index 0000000..44013d2 --- /dev/null +++ b/GoogleCodePrettify/src/lang-css.js @@ -0,0 +1,78 @@ +// Copyright (C) 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + + +/** + * @fileoverview + * Registers a language handler for CSS. + * + * + * To use, include prettify.js and this file in your HTML page. + * Then put your code in an HTML tag like + *
+ * + * + * http://www.w3.org/TR/CSS21/grammar.html Section G2 defines the lexical + * grammar. This scheme does not recognize keywords containing escapes. + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // The space production(my lisp code)+ * The lang-cl class identifies the language as common lisp. + * This file supports the following language extensions: + * lang-cl - Common Lisp + * lang-el - Emacs Lisp + * lang-lisp - Lisp + * lang-scm - Scheme + * + * + * I used http://www.informatik.uni-freiburg.de/~thiemann/haskell/haskell98-report-html/syntax-iso.html + * as the basis, but ignore the way the ncomment production nests since this + * makes the lexical grammar irregular. It might be possible to support + * ncomments using the lookbehind filter. + * + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace + // whitechar -> newline | vertab | space | tab | uniWhite + // newline -> return linefeed | return | linefeed | formfeed + [PR.PR_PLAIN, /^[\t\n\x0B\x0C\r ]+/, null, '\t\n\x0B\x0C\r '], + // Single line double and single-quoted strings. + // char -> ' (graphic<' | \> | space | escape<\&>) ' + // string -> " {graphic<" | \> | space | escape | gap}" + // escape -> \ ( charesc | ascii | decimal | o octal + // | x hexadecimal ) + // charesc -> a | b | f | n | r | t | v | \ | " | ' | & + [PR.PR_STRING, /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/, + null, '"'], + [PR.PR_STRING, /^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/, + null, "'"], + // decimal -> digit{digit} + // octal -> octit{octit} + // hexadecimal -> hexit{hexit} + // integer -> decimal + // | 0o octal | 0O octal + // | 0x hexadecimal | 0X hexadecimal + // float -> decimal . decimal [exponent] + // | decimal exponent + // exponent -> (e | E) [+ | -] decimal + [PR.PR_LITERAL, + /^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i, + null, '0123456789'] + ], + [ + // Haskell does not have a regular lexical grammar due to the nested + // ncomment. + // comment -> dashes [ any
(my lisp code)+ * The lang-cl class identifies the language as common lisp. + * This file supports the following language extensions: + * lang-cl - Common Lisp + * lang-el - Emacs Lisp + * lang-lisp - Lisp + * lang-scm - Scheme + * + * + * I used http://www.devincook.com/goldparser/doc/meta-language/grammar-LISP.htm + * as the basis, but added line comments that start with ; and changed the atom + * production to disallow unquoted semicolons. + * + * "Name" = 'LISP' + * "Author" = 'John McCarthy' + * "Version" = 'Minimal' + * "About" = 'LISP is an abstract language that organizes ALL' + * | 'data around "lists".' + * + * "Start Symbol" = [s-Expression] + * + * {Atom Char} = {Printable} - {Whitespace} - [()"\''] + * + * Atom = ( {Atom Char} | '\'{Printable} )+ + * + * [s-Expression] ::= [Quote] Atom + * | [Quote] '(' [Series] ')' + * | [Quote] '(' [s-Expression] '.' [s-Expression] ')' + * + * [Series] ::= [s-Expression] [Series] + * | + * + * [Quote] ::= '' !Quote = do not evaluate + * | + * + * + * I used Practical Common Lisp as + * the basis for the reserved word list. + * + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + ['opn', /^\(/, null, '('], + ['clo', /^\)/, null, ')'], + // A line comment that starts with ; + [PR.PR_COMMENT, /^;[^\r\n]*/, null, ';'], + // Whitespace + [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], + // A double quoted, possibly multi-line, string. + [PR.PR_STRING, /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] + ], + [ + [PR.PR_KEYWORD, /^(?:block|c[ad]+r|catch|cons|defun|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/, null], + [PR.PR_LITERAL, + /^[+\-]?(?:0x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i], + // A single quote possibly followed by a word that optionally ends with + // = ! or ?. + [PR.PR_LITERAL, + /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/], + // A word that optionally ends with = ! or ?. + [PR.PR_PLAIN, + /^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i], + // A printable non-space non-special character + [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0()\"\\\';]+/] + ]), + ['cl', 'el', 'lisp', 'scm']); diff --git a/GoogleCodePrettify/src/lang-lua.js b/GoogleCodePrettify/src/lang-lua.js new file mode 100644 index 0000000..68bb30b --- /dev/null +++ b/GoogleCodePrettify/src/lang-lua.js @@ -0,0 +1,59 @@ +// Copyright (C) 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + + +/** + * @fileoverview + * Registers a language handler for Lua. + * + * + * To use, include prettify.js and this file in your HTML page. + * Then put your code in an HTML tag like + *
(my Lua code)+ * + * + * I used http://www.lua.org/manual/5.1/manual.html#2.1 + * Because of the long-bracket concept used in strings and comments, Lua does + * not have a regular lexical grammar, but luckily it fits within the space + * of irregular grammars supported by javascript regular expressions. + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace + [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], + // A double or single quoted, possibly multi-line, string. + [PR.PR_STRING, /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\''] + ], + [ + // A comment is either a line comment that starts with two dashes, or + // two dashes preceding a long bracketed block. + [PR.PR_COMMENT, /^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/], + // A long bracketed block not preceded by -- is a string. + [PR.PR_STRING, /^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/], + [PR.PR_KEYWORD, /^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/, null], + // A number is a hex integer literal, a decimal real literal, or in + // scientific notation. + [PR.PR_LITERAL, + /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], + // An identifier + [PR.PR_PLAIN, /^[a-z_]\w*/i], + // A run of punctuation + [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/] + ]), + ['lua']); diff --git a/GoogleCodePrettify/src/lang-ml.js b/GoogleCodePrettify/src/lang-ml.js new file mode 100644 index 0000000..c5a3db7 --- /dev/null +++ b/GoogleCodePrettify/src/lang-ml.js @@ -0,0 +1,56 @@ +// Copyright (C) 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + + +/** + * @fileoverview + * Registers a language handler for OCaml, SML, F# and similar languages. + * + * Based on the lexical grammar at + * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715 + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace is made up of spaces, tabs and newline characters. + [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], + // #if ident/#else/#endif directives delimit conditional compilation + // sections + [PR.PR_COMMENT, + /^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i, + null, '#'], + // A double or single quoted, possibly multi-line, string. + // F# allows escaped newlines in strings. + [PR.PR_STRING, /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\''] + ], + [ + // Block comments are delimited by (* and *) and may be + // nested. Single-line comments begin with // and extend to + // the end of a line. + // TODO: (*...*) comments can be nested. This does not handle that. + [PR.PR_COMMENT, /^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/], + [PR.PR_KEYWORD, /^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], + // A number is a hex integer literal, a decimal real literal, or in + // scientific notation. + [PR.PR_LITERAL, + /^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], + [PR.PR_PLAIN, /^(?:[a-z_]\w*[!?#]?|``[^\r\n\t`]*(?:``|$))/i], + // A printable non-space non-special character + [PR.PR_PUNCTUATION, /^[^\t\n\r \xA0\"\'\w]+/] + ]), + ['fs', 'ml']); diff --git a/GoogleCodePrettify/src/lang-proto.js b/GoogleCodePrettify/src/lang-proto.js new file mode 100644 index 0000000..d6531fd --- /dev/null +++ b/GoogleCodePrettify/src/lang-proto.js @@ -0,0 +1,35 @@ +// Copyright (C) 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * Registers a language handler for Protocol Buffers as described at + * http://code.google.com/p/protobuf/. + * + * Based on the lexical grammar at + * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715 + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler(PR.sourceDecorator({ + keywords: ( + 'bool bytes default double enum extend extensions false fixed32 ' + + 'fixed64 float group import int32 int64 max message option ' + + 'optional package repeated required returns rpc service ' + + 'sfixed32 sfixed64 sint32 sint64 string syntax to true uint32 ' + + 'uint64'), + cStyleComments: true + }), ['proto']); diff --git a/GoogleCodePrettify/src/lang-sql.js b/GoogleCodePrettify/src/lang-sql.js new file mode 100644 index 0000000..7a58097 --- /dev/null +++ b/GoogleCodePrettify/src/lang-sql.js @@ -0,0 +1,57 @@ +// Copyright (C) 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + + +/** + * @fileoverview + * Registers a language handler for SQL. + * + * + * To use, include prettify.js and this file in your HTML page. + * Then put your code in an HTML tag like + *
(my SQL code)+ * + * + * http://savage.net.au/SQL/sql-99.bnf.html is the basis for the grammar, and + * http://msdn.microsoft.com/en-us/library/aa238507(SQL.80).aspx as the basis + * for the keyword list. + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace + [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], + // A double or single quoted, possibly multi-line, string. + [PR.PR_STRING, /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null, + '"\''] + ], + [ + // A comment is either a line comment that starts with two dashes, or + // two dashes preceding a long bracketed block. + [PR.PR_COMMENT, /^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/], + [PR.PR_KEYWORD, /^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i, null], + // A number is a hex integer literal, a decimal real literal, or in + // scientific notation. + [PR.PR_LITERAL, + /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], + // An identifier + [PR.PR_PLAIN, /^[a-z_][\w-]*/i], + // A run of punctuation + [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/] + ]), + ['sql']); diff --git a/GoogleCodePrettify/src/lang-vb.js b/GoogleCodePrettify/src/lang-vb.js new file mode 100644 index 0000000..a38db45 --- /dev/null +++ b/GoogleCodePrettify/src/lang-vb.js @@ -0,0 +1,61 @@ +// Copyright (C) 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + + +/** + * @fileoverview + * Registers a language handler for various flavors of basic. + * + * + * To use, include prettify.js and this file in your HTML page. + * Then put your code in an HTML tag like + * + * + * + * http://msdn.microsoft.com/en-us/library/aa711638(VS.71).aspx defines the + * visual basic grammar lexical grammar. + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace + [PR.PR_PLAIN, /^[\t\n\r \xA0\u2028\u2029]+/, null, '\t\n\r \xA0\u2028\u2029'], + // A double quoted string with quotes escaped by doubling them. + // A single character can be suffixed with C. + [PR.PR_STRING, /^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i, null, + '"\u201C\u201D'], + // A comment starts with a single quote and runs until the end of the + // line. + [PR.PR_COMMENT, /^[\'\u2018\u2019][^\r\n\u2028\u2029]*/, null, '\'\u2018\u2019'] + ], + [ + [PR.PR_KEYWORD, /^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i, null], + // A second comment form + [PR.PR_COMMENT, /^REM[^\r\n\u2028\u2029]*/i], + // A boolean, numeric, or date literal. + [PR.PR_LITERAL, + /^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i], + // An identifier? + [PR.PR_PLAIN, /^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*\])/i], + // A run of punctuation + [PR.PR_PUNCTUATION, + /^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/], + // Square brackets + [PR.PR_PUNCTUATION, /^(?:\[|\])/] + ]), + ['vb', 'vbs']); diff --git a/GoogleCodePrettify/src/lang-wiki.js b/GoogleCodePrettify/src/lang-wiki.js new file mode 100644 index 0000000..d4aa350 --- /dev/null +++ b/GoogleCodePrettify/src/lang-wiki.js @@ -0,0 +1,53 @@ +// Copyright (C) 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * Registers a language handler for Wiki pages. + * + * Based on WikiSyntax at http://code.google.com/p/support/wiki/WikiSyntax + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace + [PR.PR_PLAIN, /^[\t \xA0a-gi-z0-9]+/, null, + '\t \xA0abcdefgijklmnopqrstuvwxyz0123456789'], + // Wiki formatting + [PR.PR_PUNCTUATION, /^[=*~\^\[\]]+/, null, '=*~^[]'] + ], + [ + // Meta-info like #summary, #labels, etc. + ['lang-wiki.meta', /(?:^^|\r\n?|\n)(#[a-z]+)\b/], + // A WikiWord + [PR.PR_LITERAL, /^(?:[A-Z][a-z][a-z0-9]+[A-Z][a-z][a-zA-Z0-9]+)\b/ + ], + // A preformatted block in an unknown language + ['lang-', /^\{\{\{([\s\S]+?)\}\}\}/], + // A block of source code in an unknown language + ['lang-', /^`([^\r\n`]+)`/], + // An inline URL. + [PR.PR_STRING, + /^https?:\/\/[^\/?#\s]*(?:\/[^?#\s]*)?(?:\?[^#\s]*)?(?:#\S*)?/i], + [PR.PR_PLAIN, /^(?:\r\n|[\s\S])[^#=*~^A-Zh\{`\[\r\n]*/] + ]), + ['wiki']); + +PR.registerLangHandler( + PR.createSimpleLexer([[PR.PR_KEYWORD, /^#[a-z]+/i, null, '#']], []), + ['wiki.meta']); diff --git a/GoogleCodePrettify/src/prettify.css b/GoogleCodePrettify/src/prettify.css new file mode 100644 index 0000000..990d48c --- /dev/null +++ b/GoogleCodePrettify/src/prettify.css @@ -0,0 +1,32 @@ +/* Pretty printing styles. Used with prettify.js. */ + +.str { color: #B1D631; font-style: italic; } +.kwd { color: #527AA2; } +.com { color: #666; font-style: italic; } +.typ { color: #FAF4C6; } +.lit { color: #527AA2; } +.pun { color: #FF8613; } +.pln { color: #FAF4C6; } +.tag { color: #527AA2; } +.atn { color: #FAF4C6; } +.atv { color: #B1D631; } +.dec { color: #FAF4C6; } +table.prettyprint-table { padding: 2px; border: 1px solid #000; background: #222; color: #eee; font-size: 13px; margin: 0; font: 12px/1.5 'andale mono','lucida console',monospace; } +table.prettyprint-table pre, table.prettyprint-table table {margin: 0; background: #222; border: none; font-size: 13px;} +pre.prettyprint tr:hover td {background: #333} +table.prettyprint-table td.number {color: #666; font-family: "Courier New",Courier,monospace } +.prettyprint-box {width: 100%; display: block; overflow-x: auto} +table.prettyprint-table td {padding: 2px 4px} + +@media print { + .str { color: #060; } + .kwd { color: #006; font-weight: bold; } + .com { color: #600; font-style: italic; } + .typ { color: #404; font-weight: bold; } + .lit { color: #044; } + .pun { color: #440; } + .pln { color: #000; } + .tag { color: #006; font-weight: bold; } + .atn { color: #404; } + .atv { color: #060; } +} diff --git a/GoogleCodePrettify/src/prettify.js b/GoogleCodePrettify/src/prettify.js new file mode 100644 index 0000000..09d6394 --- /dev/null +++ b/GoogleCodePrettify/src/prettify.js @@ -0,0 +1,1478 @@ +// Copyright (C) 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * some functions for browser-side pretty printing of code contained in html. + *
+ * + * For a fairly comprehensive set of languages see the + * README + * file that came with this source. At a minimum, the lexer should work on a + * number of languages including C and friends, Java, Python, Bash, SQL, HTML, + * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk + * and a subset of Perl, but, because of commenting conventions, doesn't work on + * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. + *
+ * Usage:
} and {@code } tags in your source with
+ * {@code class=prettyprint.}
+ * You can also use the (html deprecated) {@code } tag, but the pretty
+ * printer needs to do more substantial DOM manipulations to support that, so
+ * some css styles may not be preserved.
+ *
} or {@code } element to specify the
+ * language, as in {@code }. Any class that
+ * starts with "lang-" followed by a file extension, specifies the file type.
+ * See the "lang-*.js" files in this directory for code that implements
+ * per-language file handlers.
+ *
+ * Change log:
+ * cbeust, 2006/08/22
+ *
+ * Java annotations (start with "@") are now captured as literals ("lit")
+ *
+ * @requires console
+ * @overrides window
+ */
+
+// JSLint declarations
+/*global console, document, navigator, setTimeout, window */
+
+/**
+ * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
+ * UI events.
+ * If set to {@code false}, {@code prettyPrint()} is synchronous.
+ */
+window['PR_SHOULD_USE_CONTINUATION'] = true;
+
+/** the number of characters between tab columns */
+window['PR_TAB_WIDTH'] = 8;
+
+/** Walks the DOM returning a properly escaped version of innerHTML.
+ * @param {Node} node
+ * @param {Array.} out output buffer that receives chunks of HTML.
+ */
+window['PR_normalizedHtml']
+
+/** Contains functions for creating and registering new language handlers.
+ * @type {Object}
+ */
+ = window['PR']
+
+/** Pretty print a chunk of code.
+ *
+ * @param {string} sourceCodeHtml code as html
+ * @return {string} code as html, but prettier
+ */
+ = window['prettyPrintOne']
+/** Find all the {@code } and {@code } tags in the DOM with
+ * {@code class=prettyprint} and prettify them.
+ * @param {Function?} opt_whenDone if specified, called when the last entry
+ * has been finished.
+ */
+ = window['prettyPrint'] = void 0;
+
+/** browser detection. @extern @returns false if not IE, otherwise the major version. */
+window['_pr_isIE6'] = function () {
+ var ieVersion = navigator && navigator.userAgent &&
+ navigator.userAgent.match(/\bMSIE ([678])\./);
+ ieVersion = ieVersion ? +ieVersion[1] : false;
+ window['_pr_isIE6'] = function () { return ieVersion; };
+ return ieVersion;
+};
+
+
+(function () {
+ // Keyword lists for various languages.
+ var FLOW_CONTROL_KEYWORDS =
+ "break continue do else for if return while ";
+ var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " +
+ "double enum extern float goto int long register short signed sizeof " +
+ "static struct switch typedef union unsigned void volatile ";
+ var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " +
+ "new operator private protected public this throw true try typeof ";
+ var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " +
+ "concept concept_map const_cast constexpr decltype " +
+ "dynamic_cast explicit export friend inline late_check " +
+ "mutable namespace nullptr reinterpret_cast static_assert static_cast " +
+ "template typeid typename using virtual wchar_t where ";
+ var JAVA_KEYWORDS = COMMON_KEYWORDS +
+ "abstract boolean byte extends final finally implements import " +
+ "instanceof null native package strictfp super synchronized throws " +
+ "transient ";
+ var CSHARP_KEYWORDS = JAVA_KEYWORDS +
+ "as base by checked decimal delegate descending event " +
+ "fixed foreach from group implicit in interface internal into is lock " +
+ "object out override orderby params partial readonly ref sbyte sealed " +
+ "stackalloc string select uint ulong unchecked unsafe ushort var ";
+ var JSCRIPT_KEYWORDS = COMMON_KEYWORDS +
+ "debugger eval export function get null set undefined var with " +
+ "Infinity NaN ";
+ var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " +
+ "goto if import last local my next no our print package redo require " +
+ "sub undef unless until use wantarray while BEGIN END ";
+ var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " +
+ "elif except exec finally from global import in is lambda " +
+ "nonlocal not or pass print raise try with yield " +
+ "False True None ";
+ var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" +
+ " defined elsif end ensure false in module next nil not or redo rescue " +
+ "retry self super then true undef unless until when yield BEGIN END ";
+ var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " +
+ "function in local set then until ";
+ var ALL_KEYWORDS = (
+ CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS +
+ PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS);
+
+ // token style names. correspond to css classes
+ /** token style for a string literal */
+ var PR_STRING = 'str';
+ /** token style for a keyword */
+ var PR_KEYWORD = 'kwd';
+ /** token style for a comment */
+ var PR_COMMENT = 'com';
+ /** token style for a type */
+ var PR_TYPE = 'typ';
+ /** token style for a literal value. e.g. 1, null, true. */
+ var PR_LITERAL = 'lit';
+ /** token style for a punctuation string. */
+ var PR_PUNCTUATION = 'pun';
+ /** token style for a punctuation string. */
+ var PR_PLAIN = 'pln';
+
+ /** token style for an sgml tag. */
+ var PR_TAG = 'tag';
+ /** token style for a markup declaration such as a DOCTYPE. */
+ var PR_DECLARATION = 'dec';
+ /** token style for embedded source. */
+ var PR_SOURCE = 'src';
+ /** token style for an sgml attribute name. */
+ var PR_ATTRIB_NAME = 'atn';
+ /** token style for an sgml attribute value. */
+ var PR_ATTRIB_VALUE = 'atv';
+
+ /**
+ * A class that indicates a section of markup that is not code, e.g. to allow
+ * embedding of line numbers within code listings.
+ */
+ var PR_NOCODE = 'nocode';
+
+ /** A set of tokens that can precede a regular expression literal in
+ * javascript.
+ * http://www.mozilla.org/js/language/js20/rationale/syntax.html has the full
+ * list, but I've removed ones that might be problematic when seen in
+ * languages that don't support regular expression literals.
+ *
+ * Specifically, I've removed any keywords that can't precede a regexp
+ * literal in a syntactically legal javascript program, and I've removed the
+ * "in" keyword since it's not a keyword in many languages, and might be used
+ * as a count of inches.
+ *
+ *
The link a above does not accurately describe EcmaScript rules since
+ * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
+ * very well in practice.
+ *
+ * @private
+ */
+ var REGEXP_PRECEDER_PATTERN = function () {
+ var preceders = [
+ "!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=",
+ "&=", "(", "*", "*=", /* "+", */ "+=", ",", /* "-", */ "-=",
+ "->", /*".", "..", "...", handled below */ "/", "/=", ":", "::", ";",
+ "<", "<<", "<<=", "<=", "=", "==", "===", ">",
+ ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[",
+ "^", "^=", "^^", "^^=", "{", "|", "|=", "||",
+ "||=", "~" /* handles =~ and !~ */,
+ "break", "case", "continue", "delete",
+ "do", "else", "finally", "instanceof",
+ "return", "throw", "try", "typeof"
+ ];
+ var pattern = '(?:^^|[+-]';
+ for (var i = 0; i < preceders.length; ++i) {
+ pattern += '|' + preceders[i].replace(/([^=<>:&a-z])/g, '\\$1');
+ }
+ pattern += ')\\s*'; // matches at end, and matches empty string
+ return pattern;
+ // CAVEAT: this does not properly handle the case where a regular
+ // expression immediately follows another since a regular expression may
+ // have flags for case-sensitivity and the like. Having regexp tokens
+ // adjacent is not valid in any language I'm aware of, so I'm punting.
+ // TODO: maybe style special characters inside a regexp as punctuation.
+ }();
+
+ // Define regexps here so that the interpreter doesn't have to create an
+ // object each time the function containing them is called.
+ // The language spec requires a new object created even if you don't access
+ // the $1 members.
+ var pr_amp = /&/g;
+ var pr_lt = //g;
+ var pr_quot = /\"/g;
+ /** like textToHtml but escapes double quotes to be attribute safe. */
+ function attribToHtml(str) {
+ return str.replace(pr_amp, '&')
+ .replace(pr_lt, '<')
+ .replace(pr_gt, '>')
+ .replace(pr_quot, '"');
+ }
+
+ /** escapest html special characters to html. */
+ function textToHtml(str) {
+ return str.replace(pr_amp, '&')
+ .replace(pr_lt, '<')
+ .replace(pr_gt, '>');
+ }
+
+
+ var pr_ltEnt = /</g;
+ var pr_gtEnt = />/g;
+ var pr_aposEnt = /'/g;
+ var pr_quotEnt = /"/g;
+ var pr_ampEnt = /&/g;
+ var pr_nbspEnt = / /g;
+ /** unescapes html to plain text. */
+ function htmlToText(html) {
+ var pos = html.indexOf('&');
+ if (pos < 0) { return html; }
+ // Handle numeric entities specially. We can't use functional substitution
+ // since that doesn't work in older versions of Safari.
+ // These should be rare since most browsers convert them to normal chars.
+ for (--pos; (pos = html.indexOf('', pos + 1)) >= 0;) {
+ var end = html.indexOf(';', pos);
+ if (end >= 0) {
+ var num = html.substring(pos + 3, end);
+ var radix = 10;
+ if (num && num.charAt(0) === 'x') {
+ num = num.substring(1);
+ radix = 16;
+ }
+ var codePoint = parseInt(num, radix);
+ if (!isNaN(codePoint)) {
+ html = (html.substring(0, pos) + String.fromCharCode(codePoint) +
+ html.substring(end + 1));
+ }
+ }
+ }
+
+ return html.replace(pr_ltEnt, '<')
+ .replace(pr_gtEnt, '>')
+ .replace(pr_aposEnt, "'")
+ .replace(pr_quotEnt, '"')
+ .replace(pr_nbspEnt, ' ')
+ .replace(pr_ampEnt, '&');
+ }
+
+ /** is the given node's innerHTML normally unescaped? */
+ function isRawContent(node) {
+ return 'XMP' === node.tagName;
+ }
+
+ var newlineRe = /[\r\n]/g;
+ /**
+ * Are newlines and adjacent spaces significant in the given node's innerHTML?
+ */
+ function isPreformatted(node, content) {
+ // PRE means preformatted, and is a very common case, so don't create
+ // unnecessary computed style objects.
+ if ('PRE' === node.tagName) { return true; }
+ if (!newlineRe.test(content)) { return true; } // Don't care
+ var whitespace = '';
+ // For disconnected nodes, IE has no currentStyle.
+ if (node.currentStyle) {
+ whitespace = node.currentStyle.whiteSpace;
+ } else if (window.getComputedStyle) {
+ // Firefox makes a best guess if node is disconnected whereas Safari
+ // returns the empty string.
+ whitespace = window.getComputedStyle(node, null).whiteSpace;
+ }
+ return !whitespace || whitespace === 'pre';
+ }
+
+ function normalizedHtml(node, out) {
+ switch (node.nodeType) {
+ case 1: // an element
+ var name = node.tagName.toLowerCase();
+ out.push('<', name);
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes[i];
+ if (!attr.specified) { continue; }
+ out.push(' ');
+ normalizedHtml(attr, out);
+ }
+ out.push('>');
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ normalizedHtml(child, out);
+ }
+ if (node.firstChild || !/^(?:br|link|img)$/.test(name)) {
+ out.push('<\/', name, '>');
+ }
+ break;
+ case 2: // an attribute
+ out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"');
+ break;
+ case 3: case 4: // text
+ out.push(textToHtml(node.nodeValue));
+ break;
+ }
+ }
+
+ /**
+ * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
+ * matches the union o the sets o strings matched d by the input RegExp.
+ * Since it matches globally, if the input strings have a start-of-input
+ * anchor (/^.../), it is ignored for the purposes of unioning.
+ * @param {Array.} regexs non multiline, non-global regexs.
+ * @return {RegExp} a global regex.
+ */
+ function combinePrefixPatterns(regexs) {
+ var capturedGroupIndex = 0;
+
+ var needToFoldCase = false;
+ var ignoreCase = false;
+ for (var i = 0, n = regexs.length; i < n; ++i) {
+ var regex = regexs[i];
+ if (regex.ignoreCase) {
+ ignoreCase = true;
+ } else if (/[a-z]/i.test(regex.source.replace(
+ /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
+ needToFoldCase = true;
+ ignoreCase = false;
+ break;
+ }
+ }
+
+ function decodeEscape(charsetPart) {
+ if (charsetPart.charAt(0) !== '\\') { return charsetPart.charCodeAt(0); }
+ switch (charsetPart.charAt(1)) {
+ case 'b': return 8;
+ case 't': return 9;
+ case 'n': return 0xa;
+ case 'v': return 0xb;
+ case 'f': return 0xc;
+ case 'r': return 0xd;
+ case 'u': case 'x':
+ return parseInt(charsetPart.substring(2), 16)
+ || charsetPart.charCodeAt(1);
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7':
+ return parseInt(charsetPart.substring(1), 8);
+ default: return charsetPart.charCodeAt(1);
+ }
+ }
+
+ function encodeEscape(charCode) {
+ if (charCode < 0x20) {
+ return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
+ }
+ var ch = String.fromCharCode(charCode);
+ if (ch === '\\' || ch === '-' || ch === '[' || ch === ']') {
+ ch = '\\' + ch;
+ }
+ return ch;
+ }
+
+ function caseFoldCharset(charSet) {
+ var charsetParts = charSet.substring(1, charSet.length - 1).match(
+ new RegExp(
+ '\\\\u[0-9A-Fa-f]{4}'
+ + '|\\\\x[0-9A-Fa-f]{2}'
+ + '|\\\\[0-3][0-7]{0,2}'
+ + '|\\\\[0-7]{1,2}'
+ + '|\\\\[\\s\\S]'
+ + '|-'
+ + '|[^-\\\\]',
+ 'g'));
+ var groups = [];
+ var ranges = [];
+ var inverse = charsetParts[0] === '^';
+ for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
+ var p = charsetParts[i];
+ switch (p) {
+ case '\\B': case '\\b':
+ case '\\D': case '\\d':
+ case '\\S': case '\\s':
+ case '\\W': case '\\w':
+ groups.push(p);
+ continue;
+ }
+ var start = decodeEscape(p);
+ var end;
+ if (i + 2 < n && '-' === charsetParts[i + 1]) {
+ end = decodeEscape(charsetParts[i + 2]);
+ i += 2;
+ } else {
+ end = start;
+ }
+ ranges.push([start, end]);
+ // If the range might intersect letters, then expand it.
+ if (!(end < 65 || start > 122)) {
+ if (!(end < 65 || start > 90)) {
+ ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
+ }
+ if (!(end < 97 || start > 122)) {
+ ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
+ }
+ }
+ }
+
+ // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
+ // -> [[1, 12], [14, 14], [16, 17]]
+ ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1] - a[1]); });
+ var consolidatedRanges = [];
+ var lastRange = [NaN, NaN];
+ for (var i = 0; i < ranges.length; ++i) {
+ var range = ranges[i];
+ if (range[0] <= lastRange[1] + 1) {
+ lastRange[1] = Math.max(lastRange[1], range[1]);
+ } else {
+ consolidatedRanges.push(lastRange = range);
+ }
+ }
+
+ var out = ['['];
+ if (inverse) { out.push('^'); }
+ out.push.apply(out, groups);
+ for (var i = 0; i < consolidatedRanges.length; ++i) {
+ var range = consolidatedRanges[i];
+ out.push(encodeEscape(range[0]));
+ if (range[1] > range[0]) {
+ if (range[1] + 1 > range[0]) { out.push('-'); }
+ out.push(encodeEscape(range[1]));
+ }
+ }
+ out.push(']');
+ return out.join('');
+ }
+
+ function allowAnywhereFoldCaseAndRenumberGroups(regex) {
+ // Split into character sets, escape sequences, punctuation strings
+ // like ('(', '(?:', ')', '^'), and runs of characters that do not
+ // include any of the above.
+ var parts = regex.source.match(
+ new RegExp(
+ '(?:'
+ + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]' // a character set
+ + '|\\\\u[A-Fa-f0-9]{4}' // a unicode escape
+ + '|\\\\x[A-Fa-f0-9]{2}' // a hex escape
+ + '|\\\\[0-9]+' // a back-reference or octal escape
+ + '|\\\\[^ux0-9]' // other escape sequence
+ + '|\\(\\?[:!=]' // start of a non-capturing group
+ + '|[\\(\\)\\^]' // start/emd of a group, or line start
+ + '|[^\\x5B\\x5C\\(\\)\\^]+' // run of other characters
+ + ')',
+ 'g'));
+ var n = parts.length;
+
+ // Maps captured group numbers to the number they will occupy in
+ // the output or to -1 if that has not been determined, or to
+ // undefined if they need not be capturing in the output.
+ var capturedGroups = [];
+
+ // Walk over and identify back references to build the capturedGroups
+ // mapping.
+ for (var i = 0, groupIndex = 0; i < n; ++i) {
+ var p = parts[i];
+ if (p === '(') {
+ // groups are 1-indexed, so max group index is count of '('
+ ++groupIndex;
+ } else if ('\\' === p.charAt(0)) {
+ var decimalValue = +p.substring(1);
+ if (decimalValue && decimalValue <= groupIndex) {
+ capturedGroups[decimalValue] = -1;
+ }
+ }
+ }
+
+ // Renumber groups and reduce capturing groups to non-capturing groups
+ // where possible.
+ for (var i = 1; i < capturedGroups.length; ++i) {
+ if (-1 === capturedGroups[i]) {
+ capturedGroups[i] = ++capturedGroupIndex;
+ }
+ }
+ for (var i = 0, groupIndex = 0; i < n; ++i) {
+ var p = parts[i];
+ if (p === '(') {
+ ++groupIndex;
+ if (capturedGroups[groupIndex] === undefined) {
+ parts[i] = '(?:';
+ }
+ } else if ('\\' === p.charAt(0)) {
+ var decimalValue = +p.substring(1);
+ if (decimalValue && decimalValue <= groupIndex) {
+ parts[i] = '\\' + capturedGroups[groupIndex];
+ }
+ }
+ }
+
+ // Remove any prefix anchors so that the output will match anywhere.
+ // ^^ really does mean an anchored match though.
+ for (var i = 0, groupIndex = 0; i < n; ++i) {
+ if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
+ }
+
+ // Expand letters to groupts to handle mixing of case-sensitive and
+ // case-insensitive patterns if necessary.
+ if (regex.ignoreCase && needToFoldCase) {
+ for (var i = 0; i < n; ++i) {
+ var p = parts[i];
+ var ch0 = p.charAt(0);
+ if (p.length >= 2 && ch0 === '[') {
+ parts[i] = caseFoldCharset(p);
+ } else if (ch0 !== '\\') {
+ // TODO: handle letters in numeric escapes.
+ parts[i] = p.replace(
+ /[a-zA-Z]/g,
+ function (ch) {
+ var cc = ch.charCodeAt(0);
+ return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
+ });
+ }
+ }
+ }
+
+ return parts.join('');
+ }
+
+ var rewritten = [];
+ for (var i = 0, n = regexs.length; i < n; ++i) {
+ var regex = regexs[i];
+ if (regex.global || regex.multiline) { throw new Error('' + regex); }
+ rewritten.push(
+ '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
+ }
+
+ return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
+ }
+
+ var PR_innerHtmlWorks = null;
+ function getInnerHtml(node) {
+ // inner html is hopelessly broken in Safari 2.0.4 when the content is
+ // an html description of well formed XML and the containing tag is a PRE
+ // tag, so we detect that case and emulate innerHTML.
+ if (null === PR_innerHtmlWorks) {
+ var testNode = document.createElement('PRE');
+ testNode.appendChild(
+ document.createTextNode('\n '));
+ PR_innerHtmlWorks = !/)[\r\n]+/g, '$1')
+ .replace(/(?:[\r\n]+[ \t]*)+/g, ' ');
+ }
+ return content;
+ }
+
+ var out = [];
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ normalizedHtml(child, out);
+ }
+ return out.join('');
+ }
+
+ /** returns a function that expand tabs to spaces. This function can be fed
+ * successive chunks of text, and will maintain its own internal state to
+ * keep track of how tabs are expanded.
+ * @return {function (string) : string} a function that takes
+ * plain text and return the text with tabs expanded.
+ * @private
+ */
+ function makeTabExpander(tabWidth) {
+ var SPACES = ' ';
+ var charInLine = 0;
+
+ return function (plainText) {
+ // walk over each character looking for tabs and newlines.
+ // On tabs, expand them. On newlines, reset charInLine.
+ // Otherwise increment charInLine
+ var out = null;
+ var pos = 0;
+ for (var i = 0, n = plainText.length; i < n; ++i) {
+ var ch = plainText.charAt(i);
+
+ switch (ch) {
+ case '\t':
+ if (!out) { out = []; }
+ out.push(plainText.substring(pos, i));
+ // calculate how much space we need in front of this part
+ // nSpaces is the amount of padding -- the number of spaces needed
+ // to move us to the next column, where columns occur at factors of
+ // tabWidth.
+ var nSpaces = tabWidth - (charInLine % tabWidth);
+ charInLine += nSpaces;
+ for (; nSpaces >= 0; nSpaces -= SPACES.length) {
+ out.push(SPACES.substring(0, nSpaces));
+ }
+ pos = i + 1;
+ break;
+ case '\n':
+ charInLine = 0;
+ break;
+ default:
+ ++charInLine;
+ }
+ }
+ if (!out) { return plainText; }
+ out.push(plainText.substring(pos));
+ return out.join('');
+ };
+ }
+
+ var pr_chunkPattern = new RegExp(
+ '[^<]+' // A run of characters other than '<'
+ + '|<\!--[\\s\\S]*?--\>' // an HTML comment
+ + '|' // a CDATA section
+ // a probable tag that should not be highlighted
+ + '|<\/?[a-zA-Z](?:[^>\"\']|\'[^\']*\'|\"[^\"]*\")*>'
+ + '|<', // A '<' that does not begin a larger chunk
+ 'g');
+ var pr_commentPrefix = /^<\!--/;
+ var pr_cdataPrefix = /^) into their textual equivalent.
+ *
+ * @param {string} s html where whitespace is considered significant.
+ * @return {Object} source code and extracted tags.
+ * @private
+ */
+ function extractTags(s) {
+ // since the pattern has the 'g' modifier and defines no capturing groups,
+ // this will return a list of all chunks which we then classify and wrap as
+ // PR_Tokens
+ var matches = s.match(pr_chunkPattern);
+ var sourceBuf = [];
+ var sourceBufLen = 0;
+ var extractedTags = [];
+ if (matches) {
+ for (var i = 0, n = matches.length; i < n; ++i) {
+ var match = matches[i];
+ if (match.length > 1 && match.charAt(0) === '<') {
+ if (pr_commentPrefix.test(match)) { continue; }
+ if (pr_cdataPrefix.test(match)) {
+ // strip CDATA prefix and suffix. Don't unescape since it's CDATA
+ sourceBuf.push(match.substring(9, match.length - 3));
+ sourceBufLen += match.length - 12;
+ } else if (pr_brPrefix.test(match)) {
+ //
tags are lexically significant so convert them to text.
+ // This is undone later.
+ sourceBuf.push('\n');
+ ++sourceBufLen;
+ } else {
+ if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) {
+ // A will start a section that should be
+ // ignored. Continue walking the list until we see a matching end
+ // tag.
+ var name = match.match(pr_tagNameRe)[2];
+ var depth = 1;
+ var j;
+ end_tag_loop:
+ for (j = i + 1; j < n; ++j) {
+ var name2 = matches[j].match(pr_tagNameRe);
+ if (name2 && name2[2] === name) {
+ if (name2[1] === '/') {
+ if (--depth === 0) { break end_tag_loop; }
+ } else {
+ ++depth;
+ }
+ }
+ }
+ if (j < n) {
+ extractedTags.push(
+ sourceBufLen, matches.slice(i, j + 1).join(''));
+ i = j;
+ } else { // Ignore unclosed sections.
+ extractedTags.push(sourceBufLen, match);
+ }
+ } else {
+ extractedTags.push(sourceBufLen, match);
+ }
+ }
+ } else {
+ var literalText = htmlToText(match);
+ sourceBuf.push(literalText);
+ sourceBufLen += literalText.length;
+ }
+ }
+ }
+ return { source: sourceBuf.join(''), tags: extractedTags };
+ }
+
+ /** True if the given tag contains a class attribute with the nocode class. */
+ function isNoCodeTag(tag) {
+ return !!tag
+ // First canonicalize the representation of attributes
+ .replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,
+ ' $1="$2$3$4"')
+ // Then look for the attribute we want.
+ .match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/);
+ }
+
+ /**
+ * Apply the given language handler to sourceCode and add the resulting
+ * decorations to out.
+ * @param {number} basePos the index of sourceCode within the chunk of source
+ * whose decorations are already present on out.
+ */
+ function appendDecorations(basePos, sourceCode, langHandler, out) {
+ if (!sourceCode) { return; }
+ var job = {
+ source: sourceCode,
+ basePos: basePos
+ };
+ langHandler(job);
+ out.push.apply(out, job.decorations);
+ }
+
+ /** Given triples of [style, pattern, context] returns a lexing function,
+ * The lexing function interprets the patterns to find token boundaries and
+ * returns a decoration list of the form
+ * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
+ * where index_n is an index into the sourceCode, and style_n is a style
+ * constant like PR_PLAIN. index_n-1 <= index_n, and style_n-1 applies to
+ * all characters in sourceCode[index_n-1:index_n].
+ *
+ * The stylePatterns is a list whose elements have the form
+ * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
+ *
+ * Style is a style constant like PR_PLAIN, or can be a string of the
+ * form 'lang-FOO', where FOO is a language extension describing the
+ * language of the portion of the token in $1 after pattern executes.
+ * E.g., if style is 'lang-lisp', and group 1 contains the text
+ * '(hello (world))', then that portion of the token will be passed to the
+ * registered lisp handler for formatting.
+ * The text before and after group 1 will be restyled using this decorator
+ * so decorators should take care that this doesn't result in infinite
+ * recursion. For example, the HTML lexer rule for SCRIPT elements looks
+ * something like ['lang-js', /<[s]cript>(.+?)<\/script>/]. This may match
+ * '';
+
+ $value = str_replace($matches[0][$i], $url, $value);
+ }
+
+ return $value;
+ }
+}
\ No newline at end of file
diff --git a/SimpleCode.php b/SimpleCode.php
new file mode 100644
index 0000000..3b67481
--- /dev/null
+++ b/SimpleCode.php
@@ -0,0 +1,83 @@
+contentEx = array('SimpleCode', 'parse');
+ Typecho_Plugin::factory('Widget_Abstract_Contents')->excerptEx = array('SimpleCode', 'parse');
+ Typecho_Plugin::factory('Widget_Abstract_Comments')->contentEx = array('SimpleCode', 'parse');
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate(){}
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form){}
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form){}
+
+ /**
+ * 解析
+ *
+ * @access public
+ * @param array $matches 解析值
+ * @return string
+ */
+ public static function parseCallback($matches)
+ {
+ return highlight_string(trim($matches[2]), true);
+ }
+
+ /**
+ * 插件实现方法
+ *
+ * @access public
+ * @return void
+ */
+ public static function parse($text, $widget, $lastResult)
+ {
+ $text = empty($lastResult) ? $text : $lastResult;
+
+ if ($widget instanceof Widget_Archive || $widget instanceof Widget_Abstract_Comments) {
+ return preg_replace_callback("/]*)>(.*?)<\/code>/is", array('SimpleCode', 'parseCallback'), $text);
+ } else {
+ return $text;
+ }
+ }
+}
diff --git a/Textile2/Plugin.php b/Textile2/Plugin.php
new file mode 100644
index 0000000..2e7dae7
--- /dev/null
+++ b/Textile2/Plugin.php
@@ -0,0 +1,121 @@
+PHP implementation of Brad Choate's Textile 2. It is feature compatible with the MovableType plugin. Does not play well with the Markdown, Textile, or Textile 2 plugins that ship with WordPress. Packaged by Adam Gessaman.
+ *
+ * @package Textile 2 (Improved)
+ * @author Jim Riggs
+ * @version 2.1.1
+ * @dependence 9.9.2-*
+ * @link http://jimandlissa.com/project/textilephp
+ */
+
+require('Textile2/Textile.php');
+
+class Textile2_Plugin implements Typecho_Plugin_Interface
+{
+ /**
+ * 激活插件方法,如果激活失败,直接抛出异常
+ *
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function activate()
+ {
+ Typecho_Plugin::factory('Widget_Abstract_Contents')->excerpt = array('Textile2_Plugin', 'parse');
+ Typecho_Plugin::factory('Widget_Abstract_Contents')->content = array('Textile2_Plugin', 'parse');
+ Typecho_Plugin::factory('Widget_Abstract_Comments')->content = array('Textile2_Plugin', 'parse');
+ }
+
+ /**
+ * 禁用插件方法,如果禁用失败,直接抛出异常
+ *
+ * @static
+ * @access public
+ * @return void
+ * @throws Typecho_Plugin_Exception
+ */
+ public static function deactivate(){}
+
+ /**
+ * 获取插件配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form 配置面板
+ * @return void
+ */
+ public static function config(Typecho_Widget_Helper_Form $form)
+ {
+ $version = new Typecho_Widget_Helper_Form_Element_Radio('version',
+ array('MTTextile' => 'MTTextile - includes Brad Choates\' extensions.',
+ 'Textile' => 'Textile for the Textile purist.'), 'MTTextile',
+ 'Textile Flavor');
+ $form->addInput($version->multiMode());
+
+ $filters = new Typecho_Widget_Helper_Form_Element_Checkbox('filters',
+ array('SmartyPants' => 'Apply SmartyPants (provides em and en dashes, and other typographic niceities)',
+ 'EducateQuotes' => 'Apply Texturize (applies curly quotes)'),
+ array('SmartyPants', 'EducateQuotes'), 'Text Filters');
+ $form->addInput($filters->multiMode());
+
+ $headerOffset = new Typecho_Widget_Helper_Form_Element_Select('headerOffset',
+ array('0 (.h1 = .h1)', '1 (.h1 = .h2)', '2 (.h1 = .h3)', '3 (.h1 = .h4)', '4 (.h1 = .h5)', '5 (.h1 = .h6)'),
+ 0, 'Header Offset');
+ $form->addInput($headerOffset);
+
+ $parsing = new Typecho_Widget_Helper_Form_Element_Checkbox('parsing',
+ array('ClearLines' => 'Strip extra spaces from the end of each line.',
+ 'PreserveSpaces' => 'Change double-spaces to the HTML entity for an em-space (&8195;).'),
+ NULL, 'Parsing Options');
+ $form->addInput($parsing->multiMode());
+
+ $inputEncoding = new Typecho_Widget_Helper_Form_Element_Text('inputEncoding', NULL, Helper::options()->charset,
+ _t('Input Character Encoding'));
+ $inputEncoding->input->setAttribute('class', 'mini');
+ $form->addInput($inputEncoding);
+
+ $encoding = new Typecho_Widget_Helper_Form_Element_Text('encoding', NULL, Helper::options()->charset,
+ _t('Output Character Encoding'));
+ $encoding->input->setAttribute('class', 'mini');
+ $form->addInput($encoding);
+ }
+
+ /**
+ * 个人用户的配置面板
+ *
+ * @access public
+ * @param Typecho_Widget_Helper_Form $form
+ * @return void
+ */
+ public static function personalConfig(Typecho_Widget_Helper_Form $form){}
+
+ /**
+ * 插件实现方法
+ *
+ * @access public
+ * @return void
+ */
+ public static function parse($text, $widget, $lastResult)
+ {
+ $text = empty($lastResult) ? $text : $lastResult;
+
+ $settings = Helper::options()->plugin('Textile2');
+
+ if ($settings->version == 'Textile') {
+ $textile = new Textile;
+ } else {
+ $textile = new MTLikeTextile;
+ }
+
+ $textile->options['head_offset'] = $settings->headerOffset;
+ $textile->options['char_encoding'] = $settings->encoding;
+ $textile->options['input_encoding'] = $settings->inputEncoding;
+
+ $textile->options['do_quotes'] = $settings->filters && in_array('EducateQuotes', $settings->filters);
+ $textile->options['smarty_mode'] = $settings->filters && in_array('SmartyPants', $settings->filters);
+ $textile->options['trim_spaces'] = $settings->parsing && in_array('ClearLines', $settings->parsing);
+ $textile->options['preserve_spaces'] = $settings->parsing && in_array('PreserveSpaces', $settings->parsing);
+
+ return $textile->process($text);
+ }
+}
diff --git a/Textile2/Textile.php b/Textile2/Textile.php
new file mode 100644
index 0000000..a99141e
--- /dev/null
+++ b/Textile2/Textile.php
@@ -0,0 +1,4080 @@
+array
s 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 string
s 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'] : 'iso-8859-1');
+ $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
+ * \  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 \
+
+";
+ }
+}
diff --git a/TinyMCE/tiny_mce/langs.php b/TinyMCE/tiny_mce/langs.php
new file mode 100644
index 0000000..3608524
--- /dev/null
+++ b/TinyMCE/tiny_mce/langs.php
@@ -0,0 +1,391 @@
+setContentType('text/javascript');
+?>
+
+tinyMCE.addI18n({typecho:{
+common:{
+edit_confirm:"",
+apply:"",
+insert:"",
+update:"",
+cancel:"",
+close:"",
+browse:"",
+class_name:"",
+not_set:"",
+clipboard_msg:"",
+clipboard_no_support:"",
+popup_blocked:"",
+invalid_data:"",
+more_colors:""
+},
+contextmenu:{
+align:"",
+left:"",
+center:"",
+right:"",
+full:""
+},
+insertdatetime:{
+date_fmt:"",
+time_fmt:"",
+insertdate_desc:"",
+inserttime_desc:"",
+months_long:"",
+months_short:"",
+day_long:"",
+day_short:""
+},
+print:{
+print_desc:""
+},
+preview:{
+preview_desc:""
+},
+directionality:{
+ltr_desc:"",
+rtl_desc:""
+},
+layer:{
+insertlayer_desc:"",
+forward_desc:"",
+backward_desc:"",
+absolute_desc:"",
+content:""
+},
+save:{
+save_desc:"",
+cancel_desc:""
+},
+nonbreaking:{
+nonbreaking_desc:""
+},
+iespell:{
+iespell_desc:"",
+download:""
+},
+advhr:{
+advhr_desc:""
+},
+emotions:{
+emotions_desc:""
+},
+searchreplace:{
+search_desc:"",
+replace_desc:""
+},
+advimage:{
+image_desc:""
+},
+advlink:{
+link_desc:""
+},
+xhtmlxtras:{
+cite_desc:"",
+abbr_desc:"",
+acronym_desc:"",
+del_desc:"",
+ins_desc:"",
+attribs_desc:""
+},
+style:{
+desc:""
+},
+paste:{
+paste_text_desc:"",
+paste_word_desc:"",
+selectall_desc:""
+},
+paste_dlg:{
+text_title:"",
+text_linebreaks:"",
+word_title:""
+},
+table:{
+desc:"",
+row_before_desc:"",
+row_after_desc:"",
+delete_row_desc:"",
+col_before_desc:"",
+col_after_desc:"",
+delete_col_desc:"",
+split_cells_desc:"",
+merge_cells_desc:"",
+row_desc:"",
+cell_desc:"",
+props_desc:"",
+paste_row_before_desc:"",
+paste_row_after_desc:"",
+cut_row_desc:"",
+copy_row_desc:"",
+del:"",
+row:"",
+col:"",
+cell:""
+},
+autosave:{
+unload_msg:""
+},
+fullscreen:{
+desc:""
+},
+media:{
+desc:"",
+edit:""
+},
+fullpage:{
+desc:""
+},
+template:{
+desc:""
+},
+visualchars:{
+desc:""
+},
+spellchecker:{
+desc:"",
+menu:"",
+ignore_word:"",
+ignore_words:"",
+langs:"",
+wait:"",
+sug:"",
+no_sug:"",
+no_mpell:""
+},
+morebreak:{
+desc:""
+}}});
+
+tinyMCE.addI18n('typecho.advanced',{
+style_select:"",
+font_size:"",
+fontdefault:"",
+block:"",
+paragraph:"",
+div:"",
+address:"",
+pre:"",
+h1:"",
+h2:"",
+h3:"",
+h4:"",
+h5:"",
+h6:"",
+blockquote:"",
+code:"",
+samp:"",
+dt:"",
+dd:"",
+bold_desc:"",
+italic_desc:"",
+underline_desc:"",
+striketrough_desc:"",
+justifyleft_desc:"",
+justifycenter_desc:"",
+justifyright_desc:"",
+justifyfull_desc:"",
+bullist_desc:"",
+numlist_desc:"",
+outdent_desc:"",
+indent_desc:"",
+undo_desc:"",
+redo_desc:"",
+link_desc:"",
+unlink_desc:"",
+image_desc:"",
+cleanup_desc:"",
+code_desc:"",
+sub_desc:"",
+sup_desc:"",
+hr_desc:"",
+removeformat_desc:"",
+custom1_desc:"",
+forecolor_desc:"",
+backcolor_desc:"",
+charmap_desc:"",
+visualaid_desc:"",
+anchor_desc:"",
+cut_desc:"",
+copy_desc:"",
+paste_desc:"",
+image_props_desc:"",
+newdocument_desc:"",
+help_desc:"",
+blockquote_desc:"",
+clipboard_msg:"",
+path:"",
+newdocument:"",
+toolbar_focus:"",
+more_colors:"",
+
+colorpicker_delta_height: 30,
+image_delta_height: 30,
+link_delta_height: -20,
+link_delta_width: 10
+});
+
+tinyMCE.addI18n('typecho.advanced_dlg',{
+about_title:"",
+about_general:"",
+about_help:"",
+about_license:"",
+about_plugins:"",
+about_plugin:"",
+about_author:"",
+about_version:"",
+about_loaded:"",
+anchor_title:"",
+anchor_name:"",
+code_title:"",
+code_wordwrap:"",
+colorpicker_title:"",
+colorpicker_picker_tab:"",
+colorpicker_picker_title:"",
+colorpicker_palette_tab:"",
+colorpicker_palette_title:"",
+colorpicker_named_tab:"",
+colorpicker_named_title:"",
+colorpicker_color:"",
+colorpicker_name:"",
+charmap_title:"",
+image_title:"",
+image_src:"",
+image_alt:"",
+image_list:"",
+image_border:"",
+image_dimensions:"",
+image_vspace:"",
+image_hspace:"",
+image_align:"",
+image_align_baseline:"",
+image_align_top:"",
+image_align_middle:"",
+image_align_bottom:"",
+image_align_texttop:"",
+image_align_textbottom:"",
+image_align_left:"",
+image_align_right:"",
+link_title:"",
+link_url:"",
+link_target:"",
+link_target_same:"",
+link_target_blank:"",
+link_titlefield:"",
+link_is_email:"",
+link_is_external:"",
+link_list:""
+});
+
+tinyMCE.addI18n('typecho.media_dlg',{
+title:"",
+general:"",
+advanced:"",
+file:"",
+list:"",
+size:"",
+preview:"",
+constrain_proportions:"",
+type:"",
+id:"",
+name:"",
+class_name:"",
+vspace:"",
+hspace:"",
+play:"",
+loop:"",
+menu:"",
+quality:"",
+scale:"",
+align:"",
+salign:"",
+wmode:"",
+bgcolor:"",
+base:"",
+flashvars:"",
+liveconnect:"",
+autohref:"",
+cache:"",
+hidden:"",
+controller:"",
+kioskmode:"",
+playeveryframe:"",
+targetcache:"",
+correction:"",
+enablejavascript:"",
+starttime:"",
+endtime:"",
+href:"",
+qtsrcchokespeed:"",
+target:"",
+volume:"",
+autostart:"",
+enabled:"",
+fullscreen:"",
+invokeurls:"",
+mute:"",
+stretchtofit:"",
+windowlessvideo:"",
+balance:"",
+baseurl:"",
+captioningid:"",
+currentmarker:"",
+currentposition:"",
+defaultframe:"",
+playcount:"",
+rate:"",
+uimode:"",
+flash_options:"",
+qt_options:"",
+wmp_options:"",
+rmp_options:"",
+shockwave_options:"",
+autogotourl:"",
+center:"",
+imagestatus:"",
+maintainaspect:"",
+nojava:"",
+prefetch:"",
+shuffle:"",
+console:"",
+numloop:"",
+controls:"",
+scriptcallbacks:"",
+swstretchstyle:"",
+swstretchhalign:"",
+swstretchvalign:"",
+sound:"",
+progress:"",
+qtsrc:"",
+qt_stream_warn:"",
+align_top:"",
+align_right:"",
+align_bottom:"",
+align_left:"",
+align_center:"",
+align_top_left:"",
+align_top_right:"",
+align_bottom_left:"",
+align_bottom_right:"",
+flv_options:"",
+flv_scalemode:"",
+flv_buffer:"",
+flv_startimage:"",
+flv_starttime:"",
+flv_defaultvolume:"",
+flv_hiddengui:"",
+flv_autostart:"",
+flv_loop:"",
+flv_showscalemodes:"",
+flv_smoothvideo:"",
+flv_jscallback:""
+});
+
+/** offset */
+tinyMCE.addI18n('typecho.media',{
+ delta_height:40
+});
diff --git a/TinyMCE/tiny_mce/langs/typecho.js b/TinyMCE/tiny_mce/langs/typecho.js
new file mode 100644
index 0000000..ad52ac3
--- /dev/null
+++ b/TinyMCE/tiny_mce/langs/typecho.js
@@ -0,0 +1 @@
+/** nothing to do, just sleep...Zzz... */
diff --git a/TinyMCE/tiny_mce/plugins/coder/editor_plugin.js b/TinyMCE/tiny_mce/plugins/coder/editor_plugin.js
new file mode 100644
index 0000000..7abe85d
--- /dev/null
+++ b/TinyMCE/tiny_mce/plugins/coder/editor_plugin.js
@@ -0,0 +1,79 @@
+/**
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+ tinymce.create('tinymce.plugins.CoderPlugin', {
+ init : function(ed, url) {
+
+ ed.onClick.add(function(ed, e) {
+ e = e.target;
+
+ if (e.nodeName === 'CODE' || e.nodeName === 'PRE' || e.className.indexOf("typecho-plugin") >= 0)
+ ed.selection.select(e);
+ });
+
+
+ ed.onBeforeSetContent.add(function(ed, o) {
+
+ var _replace = function (g, a, b, c) {
+
+ c = c.trim().replace(/( |<|>|\r\n|\r|\n)/g, function (e) {
+
+ switch (e) {
+
+ case "<":
+ return "<";
+
+ case ">":
+ return ">";
+
+ case "\r\n":
+ case "\r":
+ case "\n":
+ return '
';
+
+ case " ":
+ return ' ';
+
+ default:
+ return;
+
+ }
+
+ });
+
+ return '<' + a + b + '>' + c + '' + a + '>';
+ };
+
+ o.content = o.content.replace(/<(code)([^>]*)>([\s\S]*?)<\/(code)>/ig, _replace);
+ o.content = o.content.replace(/<(pre)([^>]*)>([\s\S]*?)<\/(pre)>/ig, _replace);
+ });
+
+ /*
+ ed.onPostProcess.add(function(ed, o) {
+ if (o.get) {
+ o.content = o.content.replace(/