├── Plugin.php
├── README.md
├── ShortCode.php
└── TOC.php
/Plugin.php:
--------------------------------------------------------------------------------
1 | begin = [__Class__, 'init'];
22 | Typecho_Plugin::factory('Widget_Archive')->handleInit = [__Class__, 'init'];
23 | }
24 |
25 | /**
26 | * 禁用插件方法,如果禁用失败,直接抛出异常
27 | *
28 | * @static
29 | * @access public
30 | * @return void
31 | * @throws Typecho_Plugin_Exception
32 | */
33 | public static function deactivate(){}
34 |
35 | /**
36 | * 获取插件配置面板
37 | *
38 | * @access public
39 | * @param Typecho_Widget_Helper_Form $form 配置面板
40 | * @return void
41 | */
42 | public static function config(Typecho_Widget_Helper_Form $form){}
43 |
44 | /**
45 | * 个人用户的配置面板
46 | *
47 | * @access public
48 | * @param Typecho_Widget_Helper_Form $form
49 | * @return void
50 | */
51 | public static function personalConfig(Typecho_Widget_Helper_Form $form){}
52 |
53 | /**
54 | * 插件初始化
55 | *
56 | * @access public
57 | * @return void
58 | */
59 | public static function init(){
60 | require_once 'ShortCode.php';
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Typecho ShortCode 短代码插件
2 | Typecho ShortCode 是一款用于自定义短代码的Typecho插件
3 |
4 | [GitHub 地址](https://github.com/moeshin/Typecho-Plugins-ShortCode) | [GitHub 下载](https://codeload.github.com/moeshin/Typecho-Plugins-ShortCode/zip/master)
5 |
6 | 由于Typecho目前自带的MarkDown解析不支持许多HTML标签,可能影响你使用ShortCode短代码
7 | 可以使用其他的MarkDown解析,例如:[Parsedown](https://github.com/erusev/parsedown)([插件](https://github.com/kokororin/typecho-plugin-Parsedown))等等
8 | ## 函数说明
9 | 使用以下函数来自定义短代码,均为公开静态
10 | ### ShortCode::set
11 | 注册短代码,返回一个`ShortCode`实例
12 |
13 | 参数名|类型|说明
14 | :-|:-|:-
15 | names|mixed|短代码名称,可以一个字符串或字符串数组
16 | callbacks|mixed|短代码对应回调函数,可以一个回调函数或回调函数数组
17 | overried|bool|覆盖已存在的短代码设置
可选,默认`false`
18 | ### ShortCode::get
19 | 获取已注册短代码列表,返回数组,格式例如:
20 | ```php
21 | array{
22 | [短代码名称] => 回调函数或回调函数名
23 | ...
24 | }
25 | ```
26 | ### ShortCode::remove
27 | 移除已注册的短代码,返回一个`ShortCode`实例
28 |
29 | 参数名|类型|说明
30 | :-|:-|:-
31 | names|string|短代码名称
32 | callbacks|callback|只有回调函数相同,短代码才会被移除
可选,默认`null`
33 | ### ShortCode::removeAll
34 | 移除所有已注册短的代码,返回一个`ShortCode`实例
35 | ### ShortCode::isForce
36 | 是否强制处理内容,返回布尔值,当前设置
37 | 使用此插件后Markdown或AutoP失效,使用此函数,并传入`true`值
38 |
39 | 参数名|类型|说明
40 | :-|:-|:-
41 | bool|bool|可选,默认`null`
42 | ### ShortCode::handle
43 | 字符串处理,返回字符串
44 |
45 | 参数名|类型|说明
46 | :-|:-|:-
47 | content|string|要处理的字符串
48 | ## 短代码回调函数参数说明
49 | 参数名|类型|说明
50 | :-|:-|:-
51 | name|string|短代码名称
52 | attr|string|短代码属性
53 | text|string|短代码内容
54 | code|string|整条短代码内容
55 | ## 注册短代码栗子
56 | ### \#1 一个对一个
57 | ```php
58 | ShortCode::set('video',function ShorCode($name,$attr,$text,$code){
59 | return '';
60 | });
61 | ```
62 | ### \#2 多个对一个
63 | ```php
64 | ShortCode::set(['video','audio'],'ShorCode');
65 | function ShorCode($name,$attr,$text,$code){
66 | switch($name){
67 | case 'video':
68 | return '';
69 | case 'audio':
70 | return '';
71 | }
72 | return $code;
73 | }
74 | ```
75 | ## [TOC]自动生成目录说明
76 | 上下不要有文本,自己占一行,与``写法一样
77 | 在文章列表里不显示也不生成目录
78 |
79 | ### 举个栗子
80 | MarkDown:
81 | ```markdown
82 | [TOC]
83 | # 文章大标题
84 | ## 文章中标题
85 | ### 文章小标题
86 | ...
87 | ```
88 | HTML:
89 | ```html
90 |
...
112 | ``` 113 | 114 | ## 更新 115 | **2018.03.24** 116 | - 添加[TOC]自动生成目录功能 117 | - 支持短代码转义(在短代码前加上反斜杠) -------------------------------------------------------------------------------- /ShortCode.php: -------------------------------------------------------------------------------- 1 | content = ['ShortCode', 'content']; 4 | Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx = ['ShortCode', 'contentEx']; 5 | require_once 'TOC.php'; 6 | 7 | /** 8 | * Short Code 9 | * 10 | * @package ShortCode 11 | * @author 小さな手は 12 | * @version 1.0.1 13 | * @link https://www.littlehands.site/ 14 | */ 15 | class ShortCode{ 16 | 17 | /** 18 | * 已注册的短代码列表 19 | * 20 | * @access private 21 | * @var array 22 | */ 23 | private static $ShortCodes = []; 24 | 25 | /** 26 | * 实例 27 | * 28 | * @access private 29 | * @var array 30 | */ 31 | private static $instance = null; 32 | 33 | /** 34 | * 是否强制处理文本 35 | * 36 | * @access public 37 | * @var bool 38 | */ 39 | public static $isForce = false; 40 | 41 | /** 42 | * 注册短代码 43 | * 44 | * @access public 45 | * @param mixed $names 短代码名称,可以一个字符串或字符串数组 46 | * @param mixed $callbacks 短代码对应回调函数,可以一个回调函数或回调函数数组 47 | * @param bool $overried 覆盖已注册的短代码false
48 | * @return ShortCode
49 | */
50 | public static function set($names,$callbacks,$overried = false){
51 | if(!is_array($names)) $names = [$names];
52 | if(!is_array($callbacks)) $callbacks = [$callbacks];
53 | $i = count($callbacks)-1;
54 | foreach($names as $j => $name){
55 | $k = $j;
56 | if($i<$j) $k = $i;
57 | $callback = $callbacks[$k];
58 | if(!array_key_exists($name,self::$ShortCodes)||$overried)
59 | self::$ShortCodes[$name] = $callback;
60 | }
61 | return self::instance();
62 | }
63 |
64 | /**
65 | * 移除短代码
66 | *
67 | * @access public
68 | * @param string $name 短代码名称
69 | * @param callback $callback 只有回调函数相同,短代码才会被移除Null
70 | * @return ShortCode
71 | */
72 | public static function remove($name,$callback = null){
73 | if(isset(self::$ShortCodes[$name]))
74 | if(self::$ShortCodes[$name] === $callback||empty($callback))
75 | unset(self::$ShortCodes[$name]);
76 | return self::instance();
77 | }
78 |
79 | /**
80 | * 移除所有短代码
81 | *
82 | * @access public
83 | * @return ShortCode
84 | */
85 | public static function removeAll(){
86 | self::$ShortCodes[] = [];
87 | return self::instance();
88 | }
89 |
90 | /**
91 | * 获取短代码列表
92 | *
93 | * @access public
94 | * @return array
95 | */
96 | public static function get(){
97 | return self::$ShortCodes;
98 | }
99 |
100 | /**
101 | * 强制处理文本
102 | * 使用此插件后Markdown或AutoP失效,使用此函数,并传入true
值
103 | * @access public
104 | * @param bool
105 | * @return bool
106 | */
107 | public static function isForce($bool = null){
108 | if(is_bool($bool)) self::$isForce = $bool;
109 | return self::$isForce;
110 | }
111 |
112 | /**
113 | * 文本处理
114 | *
115 | * @access public
116 | * @param string
117 | * @retur string
118 | */
119 | public static function handle($content){
120 | $pattern = [];
121 | $RegExp = '((?:"[^"]*"|'."'[^']*'|[^'".'"\]])*)';
122 | foreach(array_keys(self::$ShortCodes) as $name)
123 | array_push($pattern,
124 | "#\\\\\[|\[($name)$RegExp\]([\s\S]*?)\[/$name\]#i",
125 | "#\\\\\[|\[($name)$RegExp\]()#i"
126 | );
127 | return preg_replace_callback($pattern,function($a){
128 | if(count($a) == 1)
129 | return $a[0];
130 | $name = strtolower($a[1]);
131 | $ShortCodes = self::$ShortCodes;
132 | $callback = $ShortCodes[$name];
133 | if(array_key_exists($name,$ShortCodes)&&is_callable($callback))
134 | return call_user_func($callback, $name, $a[2], trim($a[3]), $a[0]);
135 | else
136 | return $a[0];
137 | },$content);
138 | }
139 |
140 | /**
141 | * 插件处理 content
142 | *
143 | * @access public
144 | * @param string
145 | * @param Widget_Abstract_Contents
146 | * @param string
147 | * @return string
148 | */
149 | public static function content($content,$archive,$last){
150 | if($last) $content = $last;
151 | $content = self::handle($content);
152 | if(Typecho_Plugin::export()['handles']['Widget_Abstract_Contents:content'] === [[__Class__,__Function__]]||self::$isForce)
153 | return $archive->isMarkdown?$archive->markdown($content):$archive->autoP($content);
154 | return $content;
155 | }
156 |
157 | /**
158 | * 插件处理 contentEx
159 | *
160 | * @access public
161 | * @param string
162 | * @param Widget_Abstract_Contents
163 | * @param string
164 | * @return string
165 | */
166 | public static function contentEx($content,$archive,$last){
167 | if($last) $content = $last;
168 | return TOC::build($content,$archive->is('single'));
169 | }
170 |
171 | /**
172 | * 获取实例
173 | *
174 | * @access private
175 | * @return ShortCode
176 | */
177 | private static function instance(){
178 | return self::$instance?self::$instance:new ShortCode();
179 | }
180 |
181 | /**
182 | * 构造函数
183 | *
184 | * @access public
185 | */
186 | public function __construct(){
187 | self::$instance = $this;
188 | }
189 |
190 | }
191 |
--------------------------------------------------------------------------------
/TOC.php:
--------------------------------------------------------------------------------
1 | loadHTML(''.$content.'');
41 | libxml_use_internal_errors(false);
42 |
43 | if(self::$xpath){
44 | self::$xpath->__construct($dom);
45 | $xpath = self::$xpath;
46 | }else
47 | self::$xpath = $xpath = new DOMXPath($dom);
48 | $objs = $xpath->query('//h1|//h2|//h3|//h4|//h5|//h6');
49 | if (!$objs->length)
50 | return $content;
51 | $arr = [];
52 | $html = '\[toc\]
#i',$html,$content); 63 | } 64 | 65 | /** 66 | * 处理目录 67 | * 68 | * @param DOMElement $obj 69 | * @param int $n 70 | * @param array &$arr 71 | * @param string &$html 72 | * @return void 73 | */ 74 | public static function handle($obj,$n,&$arr,&$html){ 75 | $i = str_replace('h','',$obj->tagName); 76 | $j = end($arr); 77 | if($i > $j){ 78 | $arr[] = $i; 79 | $html .= '