# EasyShortCode
**Repository Path**: ymz316/easy-short-code
## Basic Information
- **Project Name**: EasyShortCode
- **Description**: 基于typecho的短代码插件
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-14
- **Last Updated**: 2026-07-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# EasyShortCode 短代码插件
Typecho 短代码插件,在文章/页面中解析 `[tag]...[/tag]` 语法,共 **20 个内置短代码**,附带后台编辑器工具栏和弹窗配置。
## 目录
- [实现原理](#实现原理)
- [安装与配置](#安装与配置)
- [编辑器工具栏](#编辑器工具栏)
- [短代码列表](#短代码列表)
- [内容排版](#内容排版)
- [媒体](#媒体)
- [相册](#相册)
- [引用](#引用)
- [其他](#其他)
- [扩展开发](#扩展开发)
- [样式自定义](#样式自定义)
- [安全说明](#安全说明)
- [文件结构](#文件结构)
- [许可](#许可)
## 实现原理
### 解析流程
```
文章 Markdown 源码
│
▼
Typecho Markdown 解析
│
▼
contentEx 钩子 → EasyShortCode::parse()
│
├─ 按注册顺序遍历 20 个短代码的正则模式
├─ 成对标签:[tag attr="val"]content[/tag]
├─ 自闭合标签:[tag attr="val"]
├─ [raw] 最先匹配,防止内嵌短代码被二次解析
└─ 块级元素前后
自动清理
│
▼
最终 HTML 输出
```
### 核心机制
**钩子系统**
| 钩子 | 用途 |
|------|------|
| `Widget_Abstract_Contents::contentEx` | 文章内容短代码解析 |
| `Widget_Archive::handleInit` | 加载 Parser.php |
| `Widget_Archive::footer` | 注入 CSS + 前端 JS |
| `admin/header.php::header` | 注入编辑器 CSS |
| `admin/write-post.php::bottom` | 注入编辑器工具栏 JS |
| `admin/write-page.php::bottom` | 同上(页面编辑) |
**正则引擎**
- 每个短代码生成两个模式:成对 + 自闭合
- `\[` 转义支持:写 `\[tag]` 不被解析
- 属性用 `key="val"` 格式,大小写不敏感
- 解析失败静默回退,不破坏页面
- 模式按标签名缓存,避免重复编译
**XSS 防护**
- 属性值:`htmlspecialchars($val, ENT_QUOTES, 'UTF-8')`
- 枚举值:白名单校验,不在白名单则回退默认值
- body 内容:视为受信 HTML,不转义保留 `
`、`` 等
## 安装与配置
. 将 `EasyShortCode` 放入 `usr/plugins/`
. 后台 → 控制台 → 插件 → 启用 **EasyShortCode**
. 点击 **设置** 进行配置
| 配置 | 默认值 | 说明 |
|------|--------|------|
| 隐藏块样式 | 折叠(details/summary) | `[hide]` 的展示方式 |
| 按钮 CSS 类名 | `esc-btn` | 便于主题覆盖 |
## 编辑器工具栏
启用后,文章/页面编辑区上方自动注入短代码按钮。有弹窗配置的按钮(标 `…`)点击弹出表单,其余直接插入模板。
```
[按钮…] [提示框…] [备注] [隐藏块…] | [图片…] [视频…] [聊天…] [文件…] [音频…] |
[进度条…] [标签页] [时间线] [自适应相册] [瀑布流相册] [横向滚动] [网格相册…] [网格跨度] |
[站内文章…] [站外文章…] | [原样输出]
```
## 短代码列表
### 内容排版
#### 按钮 `[button]` / `[btn]`
```
[button url="https://x.com" type="primary" blank="true"]文字[/button]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `url` | `#` | 链接 |
| `type` | `primary` | primary / success / warning / danger / secondary |
| `blank` | `false` | 新窗口打开(含 `rel="noopener noreferrer"`) |
#### 提示框 `[alert]`
```
[alert type="info"]内容(支持 HTML)[/alert]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `type` | `info` | info / success / warning / error |
#### 备注 `[tip]` / `[notice]`
```
[tip]备注内容[/tip]
[notice type="warning"]警告[/notice]
```
属性同 `[alert]`。
#### 隐藏块 `[hide]`
```
[hide title="点击展开"]隐藏内容[/hide]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `title` | 点击展开 | 折叠模式标题 |
两种样式(插件设置中切换):折叠展开 / 模糊遮挡(hover 显示)。
#### 进度条 `[progress]`
```
[progress value="85" color="green" sub="熟练掌握"]Python[/progress]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| body | - | 名称(header 左侧) |
| `value` | 50 | 百分比 0–100 |
| `color` | blue | blue / green / red / yellow / purple / orange |
| `sub` | - | 底部描述 |
| `striped` | true | 条纹动画 |
| `animate` | false | 脉冲呼吸效果 |
#### 标签页 `[tabs]`
```
[tabs]
[tab title="标签1"]内容1[/tab]
[tab title="标签2"]内容2[/tab]
[/tabs]
```
纯 CSS radio 实现,第一个默认选中,内容支持 HTML。
#### 时间线 `[timeline]`
```
[timeline]
[item date="2024-01"]事件[/item]
[item date="2024-06"]事件[/item]
[/timeline]
```
竖线 + 圆点标记样式,`[item]` 无数量限制。
---
### 媒体
#### 单图片 `[img]`
```
[img src="https://x.com/photo.jpg"]标题[/img]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `src` | **必填** | 图片 URL |
| body | - | 标题(显示在图片底部渐变遮罩上) |
#### 视频 `[video]`
```
[video type="video/mp4"]https://x.com/v.mp4[/video]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `type` | video/mp4 | MIME 类型 |
| `preload` | auto | auto / metadata / none |
#### 音频 `[audio]`
```
[audio src="https://x.com/song.mp3" title="歌名"][/audio]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `src` | **必填** | 音频 URL |
| `title` | - | 标题 |
#### 聊天气泡 `[chat]`
```
[chat author="我" type="sent" email="xx@qq.com"]
消息内容(支持 HTML)
[/chat]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `author` | 我 | 名称 |
| `type` | sent | sent(右蓝)/ received(左灰) |
| `email` | - | QQ→QQ头像,其他→Cravatar |
| `imageurl` | - | 自定义头像,优先于 email |
| `todate` | 当前 | 时间戳 |
#### 文件下载 `[file]`
```
[file url="https://x.com/doc.pdf"]文档.pdf[/file]
```
---
### 相册
#### 自适应相册 `[album-auto]`
```
[album-auto]
[img src="1.jpg"]图1[/img]
[img src="2.jpg"]图2[/img]
[/album-auto]
```
CSS Grid `auto-fit`,列数自动适配容器宽度。Hover 图片放大。
#### 网格相册 `[album-grid]`
```
[album-grid set="2,sm-2,md-3,lg-4"]
[img src="1.jpg"]图1[/img]
[img src="2.jpg"]图2[/img]
[/album-grid]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `set` | - | 列数:N, sm-N, md-N, lg-N |
Hover 图片放大,支持 `[grid-span]` 跨行跨列。
#### 网格跨度 `[grid-span]`
```
[grid-span set="row-2,col-2"]
[img src="hero.jpg"]主图[/img]
[/grid-span]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `set` | - | row-N 跨行,col-N 跨列 |
#### 瀑布流相册 `[album-masonry]`
```
[album-masonry cols="3"]
[img src="1.jpg"]图1[/img]
...
[/album-masonry]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `cols` | 3 | 列数 2–5,响应式自动降级 |
CSS `column-count` 实现,图片按高度错落排列。Hover 图片放大。
#### 横向滚动相册 `[album-hscroll]`
```
[album-hscroll cols="4" speed="60"]
[img src="1.jpg"]图1[/img]...
[/album-hscroll]
```
| 属性 | 默认值 | 说明 |
|------|--------|------|
| `cols` | 4 | 每行图片数 |
| `speed` | 60 | 像素/秒 |
奇数行左→右,偶数行右→左,自动循环。hover 暂停。JS 像素级动画,无缝衔接。
---
### 引用
#### 站内文章 `[post]`
```
[post cid="60"][/post]
```
自动提取标题、摘要、缩略图(自定义字段 `thumb` → 附件 → 正文 → 随机图)。
#### 站外文章 `[fpost]`
```
[fpost href="https://x.com" src="https://x.com/thumb.jpg" description="摘要"]
标题
[/fpost]
```
---
### 其他
#### 原样输出 `[raw]`
```
[raw language="php"]
` 包装,主题可自定义样式
## 扩展开发
```php
// 在主题 functions.php 或插件中注册
Typecho_Plugin::factory('Widget_Archive')->handleInit = function () {
EasyShortCode_Parser::register('mytag', function ($atts, $content, $tag) {
$name = htmlspecialchars($atts['name'] ?? 'default', ENT_QUOTES, 'UTF-8');
return '' . $content . '
';
});
};
```
`register(name, callback, override)` — 支持别名数组,override 控制是否覆盖已有。
## 样式自定义
所有 CSS 类以 `esc-` 前缀,主题可覆盖。完整暗色模式支持(`.dark` 后代选择器)。
### CSS 类名速查
| 短代码 | 主要类 |
|--------|--------|
| button | `.esc-btn` `.esc-btn-{type}` |
| alert/tip | `.esc-alert` `.esc-tip` `.esc-alert-{type}` |
| hide | `.esc-hide` `.esc-hide-spoiler` `.esc-hide-blur` |
| progress | `.esc-progress` `.esc-progress-{color}` `.esc-progress-striped` `.esc-progress-animate` |
| tabs | `.esc-tabs` `.esc-tab-label` `.esc-tab-content` |
| timeline | `.esc-timeline` `.esc-timeline-marker` `.esc-timeline-date` `.esc-timeline-content` |
| img | `.imgdiv` `.imgtitle` |
| album-auto/grid/masonry/hscroll | `.album-auto` `.album-grid` `.album-masonry` `.album-hscroll` |
| chat | `.chat-container` `.message` `.sent`/`.received` `.message-content` `.timestamp` `.avatar` |
| file | `.file` `.fileimg` `.filetext` `.filedown` |
| post/fpost | `.post_inner` `.post_img_inner` `.post_info_inner` |
| grid-span | `.grid-span` `.grid-span-row-{n}` `.grid-span-col-{n}` |
## 安全说明
- `target="_blank"` 均含 `rel="noopener noreferrer"`
- body 内容为作者受信 HTML,不转义
- 属性值全部 `htmlspecialchars()` 转义
- 枚举值白名单校验
## 文件结构
```
EasyShortCode/
├── Plugin.php # 插件入口,钩子注册
├── Parser.php # 解析引擎 + 20 个短代码实现
├── README.md
└── assets/
├── style.css # 前端短代码样式(暗色模式)
├── frontend.js # 横向滚动相册动画
├── editor.css # 后台工具栏 + 弹窗样式
└── editor.js # 后台工具栏 + 弹窗逻辑
```
## 许可
按 Typecho 惯例使用与修改。