Compare commits

...

53 Commits
v1.5.0 ... main

Author SHA1 Message Date
zhengyi 2600445d15 Merge pull request '📝Update README' (PR#82) from docs into main
Build Plugin JAR File / build (push) Successful in 8m8s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Reviewed-on: #82
2024-06-10 00:20:35 +08:00
zhengyi59 868aec124c 📝Update README 2024-06-10 00:19:04 +08:00
zhengyi 1b482b5d9b Merge pull request 'v1.7.0 Releases' (PR#81) from dev into main
Build Plugin JAR File / build (push) Successful in 2m11s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Reviewed-on: #81
2024-05-10 12:56:57 +08:00
zhengyi 8cab82fa52 Merge branch 'refs/heads/main' into dev
Build Plugin JAR File / build (push) Successful in 7m58s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-05-05 17:25:04 +08:00
zhengyi b8000377ac 🐛Fix compatible issue with docsme
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Build Plugin JAR File / build (push) Has been cancelled Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/38
2024-05-05 17:24:43 +08:00
justice2001 ffaf19cf76
Merge pull request #39 from ruibaby/patch-1
Build Plugin JAR File / build (push) Successful in 3m7s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
chore: update plugin.yaml
2024-05-02 18:34:58 +08:00
Ryan Wang fe1ba30230
Update plugin.yaml 2024-05-02 10:43:09 +08:00
Ryan Wang eb58dc8028
chore: update plugin.yaml 2024-05-02 10:40:38 +08:00
zhengyi 7757091b80 🐛 Change font size and style of title
Build Plugin JAR File / build (push) Successful in 2m3s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
#74
https://github.com/justice2001/halo-plugin-vditor/issues/33
2024-04-26 22:59:56 +08:00
zhengyi d830c03d8b 🐛 Fix issue with incorrect cursor position in title input.
Build Plugin JAR File / build (push) Failing after 1m29s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
#79
2024-04-26 22:39:53 +08:00
zhengyi 8c6cfc73d4 👷Change artifact retention days to 90
Build Plugin JAR File / build (push) Successful in 1m18s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-04-19 21:39:32 +08:00
zhengyi c60381920c 🐛Fix https://github.com/justice2001/halo-plugin-vditor/issues/33
Build Plugin JAR File / build (push) Successful in 2m9s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix #74
2024-04-16 13:42:02 +08:00
zhengyi f927bfb3d5 Improve title gen performance
Build Plugin JAR File / build (push) Successful in 1m59s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/33
Fix #74
2024-04-14 10:51:23 +08:00
zhengyi 6bcf8f89f0 Add feature "use first h1 as title"
Build Plugin JAR File / build (push) Failing after 1m15s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/33
Fix #74
2024-04-14 10:43:02 +08:00
zhengyi f08ec8074f Merge pull request 'v1.6.2 Releases' (PR#71) from dev into main
Build Plugin JAR File / build (push) Successful in 1m11s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Reviewed-on: #71
2024-03-25 22:20:09 +08:00
zhengyi bab4075109 ⬆️Update vditor to 3.10.2
Build Plugin JAR File / build (push) Successful in 2m23s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
🔥Remove zstatic cdn
Add npmmirror

Fix #69
2024-03-25 22:03:55 +08:00
zhengyi 7581ccb6fc Add cdn settings for post render
Build Plugin JAR File / build (push) Has been cancelled Details
Build Plugin JAR File / github-release (push) Has been cancelled Details
Fix #57
Fix https://github.com/justice2001/halo-plugin-vditor/issues/30
2024-03-23 14:05:05 +08:00
zhengyi 6fd0974199 Merge pull request 'v1.6.1 Releases' (PR#67) from dev into main
Build Plugin JAR File / build (push) Successful in 1m24s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Reviewed-on: #67
2024-03-01 11:46:30 +08:00
zhengyi dfe7a274e9 🐛 Fix several issues in media render.
Build Plugin JAR File / build (push) Successful in 2m31s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-03-01 11:13:44 +08:00
zhengyi 0287ce2b33 📝 Update CHANGELOG 2024-03-01 10:39:19 +08:00
zhengyi 8ae973f2c4 🐛 Add plantumlRender to post render
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/28
Fix #66
2024-02-29 13:32:12 +08:00
zhengyi c76808258a 📝 Add test case doc
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
2024-02-29 13:30:48 +08:00
zhengyi59 30ce08e2c8 🐛 Fix version not replace in single page
Build Plugin JAR File / build (push) Successful in 2m3s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/27
Fix #65
2024-02-22 17:37:05 +08:00
zhengyi f8611f1a0c Merge pull request 'v1.6.0 Releases' (PR#63) from dev into main
Build Plugin JAR File / build (push) Successful in 1m42s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Reviewed-on: #63
2024-02-11 00:39:03 +08:00
zhengyi 14ca6bf173 🐛 Fix insert image fail use attachment selector.
Build Plugin JAR File / build (push) Successful in 1m11s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix #62
2024-02-09 00:10:20 +08:00
zhengyi 56143952c4 🐛 Fix insert image failed use attachment selector in hotkey.
Build Plugin JAR File / build (push) Successful in 1m7s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
#62
2024-02-08 23:38:00 +08:00
zhengyi 6d1b9eab6c Update debug panel
Build Plugin JAR File / build (push) Successful in 1m5s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-02-08 22:49:34 +08:00
zhengyi 464ca2769c 🐛 Fix rending error in sv mode
Build Plugin JAR File / build (push) Successful in 1m53s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix #61
2024-02-08 22:03:44 +08:00
zhengyi 285ae2c28a 📝 Update Changelog
Build Plugin JAR File / build (push) Successful in 1m15s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-02-07 00:20:13 +08:00
zhengyi 5760e1a9d4 🐛 Fix custom renders inconsistent with previous version in html render
Build Plugin JAR File / build (push) Successful in 1m24s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Add vditor debug panel
2024-02-07 00:18:00 +08:00
zhengyi 4eea179a24 🐛 Compatible old version render
Build Plugin JAR File / build (push) Successful in 1m9s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-02-06 23:09:42 +08:00
zhengyi 16442b7068 ⬆️ Update halo-render to 1.1.1
Build Plugin JAR File / build (push) Successful in 1m13s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-02-06 22:25:17 +08:00
zhengyi 7cbdbd70ac ⬆️ Update halo-render to v1.1.1
Build Plugin JAR File / build (push) Successful in 1m4s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/23
Fix #58
Fix #52
2024-02-06 22:11:15 +08:00
zhengyi aa28599a75 🍱 Use local assets
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Build Plugin JAR File / build (push) Has been cancelled Details
2024-02-06 17:09:50 +08:00
zhengyi b416739947 Merge branch 'main' into dev
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
2024-02-06 16:40:40 +08:00
justice2001 f9007864b6
Merge pull request #25 from ruibaby/chore/simplify-bundler-config
Build Plugin JAR File / build (push) Successful in 2m10s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
chore: simplify bundler config
2024-02-06 16:32:57 +08:00
zhengyi 968b7d0a7f 🎨 Rename render script
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
2024-02-06 16:32:04 +08:00
zhengyi 527ce8ceab 🗑️ Clean code
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
2024-02-06 16:21:54 +08:00
Ryan Wang 7eb9546241 chore: simplify bundler config
Signed-off-by: Ryan Wang <i@ryanc.cc>
2024-02-05 11:23:11 +08:00
zhengyi59 ed5f59cb5c 🐛 Fix https://github.com/justice2001/halo-plugin-vditor/issues/24
Build Plugin JAR File / build (push) Has been cancelled Details
Build Plugin JAR File / github-release (push) Has been cancelled Details
Fix #59
Wait test
2024-02-03 01:42:40 +08:00
zhengyi d48f8aa144 ⬆️ Update vditor 3.9.9 (official)
Build Plugin JAR File / build (push) Has been cancelled Details
Build Plugin JAR File / github-release (push) Has been cancelled Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/20
Fix #51
2024-01-30 18:41:57 +08:00
zhengyi b074329dc5 📝 Update CHANGELOG
Build Plugin JAR File / build (push) Has been cancelled Details
Build Plugin JAR File / github-release (push) Has been cancelled Details
2024-01-27 17:42:06 +08:00
zhengyi 8cf103932e Add settings for vditor debugger
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Fix: #56
2024-01-27 17:39:06 +08:00
zhengyi d9f364ad49 🐛 Fix https://github.com/justice2001/halo-plugin-vditor/issues/22
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Fix #55
2024-01-27 17:09:43 +08:00
zhengyi abf2a73d70 🐛 Fix https://github.com/justice2001/halo-plugin-vditor/issues/22
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Fix #55
2024-01-27 17:07:29 +08:00
zhengyi c41bfea624 🔧 Update docker config in build.gradle
Build Plugin JAR File / build (push) Has been cancelled Details
Build Plugin JAR File / github-release (push) Has been cancelled Details
2024-01-25 11:49:39 +08:00
zhengyi 23cdb944a6 Merge pull request 'v1.5.1 Releases' (PR#53) from dev into main
Build Plugin JAR File / build (push) Successful in 1m44s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Reviewed-on: #53
2024-01-21 18:38:29 +08:00
zhengyi 8fc93ab574 📝 Update CHANGELOG
Build Plugin JAR File / build (push) Successful in 1m9s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
2024-01-21 13:46:49 +08:00
zhengyi dcc0758313 ♻️ Refactor script builder
Build Plugin JAR File / build (push) Failing after 2m55s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix #50 (comment)
2024-01-16 22:28:52 +08:00
zhengyi 00eb633cf2 🐛 Fix font color covered by render when use dark mode
Build Plugin JAR File / build (push) Successful in 1m15s Details
Build Plugin JAR File / github-release (push) Has been skipped Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/18
Fix #48
2024-01-16 21:07:25 +08:00
zhengyi cb6b6cc224 🐛 Add version param in render script
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Fix https://github.com/justice2001/halo-plugin-vditor/issues/19
Fix #49
2024-01-16 21:00:22 +08:00
zhengyi 4724bc04e9 Add quick insert for gallery
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
https://github.com/justice2001/halo-plugin-vditor/issues/15
#45
2024-01-16 20:43:53 +08:00
zhengyi 49ab197ffb 🐛 Clear all css style in render
Build Plugin JAR File / build (push) Waiting to run Details
Build Plugin JAR File / github-release (push) Blocked by required conditions Details
Fix: https://github.com/justice2001/halo-plugin-vditor/issues/17
Fix: #47
2024-01-15 20:45:08 +08:00
54 changed files with 2065 additions and 226 deletions

View File

@ -64,7 +64,7 @@ jobs:
name: plugin-starter
path: |
build/libs/*.jar
retention-days: 1
retention-days: 90
github-release:
runs-on: debian-12

126
CHANGELOG.md Normal file
View File

@ -0,0 +1,126 @@
# 更新记录
### v1.7.0
- ⬆️ 调整 Halo 最低兼容版本为 `2.14.0`
- ✨ 添加`使用第一个h1作为标题`的功能 #33
- 🐛 修复代码块颜色异常的问题 #38
### v1.6.2
- ⬆️ 升级Vditor版本至3.10.2
- ✨ 添加页面加载CDN设置添加自定义CDN支持 `#30`
#### 关于CDN配置
由于Vditor本体加载CDN的方式无法支持类似`cdnjs`的url格式。当前内置4种CDN: `内置`,`jsDelivr`, `unpkg`, `zstatic`
**如何确认cdn是否可用:**
您可以访问`<你的cdn>/dist/index.min.js`能加载出来则说明可用同时注意cdn是否包含该版本资源版本升级信息会在更新日志中体现。
### v1.6.1
- 🐛 修复单页文章加载Vditor资源时 version 未成功替换问题 `#27`
- 🐛 添加遗漏的 plantuml 渲染器 `#28`
- 🐛 修复多媒体链接无法渲染的问题
- 🐛 修复多媒体渲染的大小问题
### v1.6.0
- ⬆️ 修改Vditor为官方版本(Vditor 3.9.9)
- ✨ 添加 Vditor Debugger 设置
- 🐛 修复行内公式渲染的问题 #22
- 🐛 修复操作栏修改属性不生效的问题 #20 \[vditor]
- 🐛 修复在 PJAX 主题下渲染器无法正常处理的问题 #24
- 🐛 修复 render 样式与其他样式冲突的问题
- 🐛 修复`插入图片`在 Safari 中不可用的问题
### v1.5.1
- ✨ 添加图集的快捷插入按钮
- 🐛 修复脑图、图标、echart暗色模式渲染错误的问题
- 🐛 解决更新插件前台资源缓存的问题
- 🐛 解决暗色模式渲染异常的问题
- 🐛 解决主题代码块等样式覆盖的问题
### v1.5.0
- ✨ 使用新的快速插入表单,界面更美观
- ✨ 支持渲染其他插件/主题的自定义组件(需要开发者支持)
- ✨ 支持加入快速插入链接(需要开发者支持)
- ✨ 允许用户禁用HTML代码块隐藏的特性
- ✨ 支持用户自定义上传图片的格式
- ✨ vditor-halo-render添加组图组件(gallery)
- 🐛 修复图片拖拽插入错位的问题
- 🐛 修复echartsmindmap无法渲染的问题
- 🐛 修复所见即所得模式下超链接颜色丢失的问题
- 🚀 优化前端渲染逻辑去除无用的dom查询
### v1.4.0
- ✨ 支持编辑器加载状态展示
- ✨ 支持拖拽上传图片
- ✨ 添加快速插入自定义块的按钮
- ✨ 添加仅在Markdown文章注入解析器的选项
- ⬆️ 更新halo-vditor至3.9.9版本对应vditor 3.9.8
- ⬆️ 更新vditor-halo-render到1.1.0版本
- ✨ 重新设计tip、git模块
- ✨ 添加资源下载模块
- ✨ 为git添加fork、topic信息
- ✨ 为git添加缓存
- ✨ 添加对Gitee的支持
- 🐛 修复invalid type界面边框与其他模块不对齐的问题
### v1.3.2
- 🐛 编辑器编写代码块出现闪屏问题
### v1.3.1
- 🐛 修复Vditor编辑器切换到其他编辑器导致的样式冲突问题
- 🐛 修复编辑器在Halo中出现页面滚动条的问题
- 🐛 修复前台数学公式无法渲染的问题
### v1.3.0
- ✨ 支持更多tips渲染
- ✨ 支持github仓库信息渲染
- ✨ 升级vditor为分支halo-vditor版本 https://github.com/justice2001/halo-vditor
- ⬆️ 升级halo-vditor到3.9.8版本(对应vditor3.9.7)
- 🐛 修复页面偶尔出现加载shi问题使用本地资源
### v1.2.0
- 🚸 将设置拆分为编辑器和渲染两个部分
- ✨ 为编辑器添加多国语言支持(简中、繁中、英语)
- ✨ 添加启用编辑器代码块的选项
- ✨ 添加跟随Joe 3.0主题切换暗色模式的选项
- 🐛 修复单页未对内容进行渲染的问题
- 🐛 修复所见即所得模式下部分内容被小工具栏遮挡的问题
### v1.1.0
- ⬆️ 更新 Halo 最低兼容版本至 2.8.0
- ✨ 添加默认编辑模式设置
- ✨ 添加打字机模式设置
- ✨ 添加插入图片功能(快捷键:⇧⌘P)
- ✨ 添加自动暗色模式的支持
- 🐛 修复了编辑器中有序列表左侧序号消失的问题
- 🐛 修复全屏编辑器左侧被Halo导航栏遮挡的问题
- 🧪 实验性特性: 支持多媒体渲染
### v1.0.1
- ⚡ 修改为仅在文章中加入vditor render优化部分页面加载速度
- ⚡ 修改vditor库从本地加载优化页面加载速度
- 🐛 修复由于id重复可能存在的冲突问题
- ⚰️ 删除了部分无用代码
### v1.0.0
- ✨ 集成强大的Markdown编辑器Vditor进Halo中
- ✨ 提供所见即所得(wysiwyg)、即时渲染(ir)、分屏渲染(sv)三种渲染模式
- ✨ 支持大纲、数学公式、脑图、图表、流程图、甘特图、时序图、五线谱、多媒体、语音阅读、标题锚点、代码高亮及复制、graphviz 渲染、plantumlUML图
- ✨ 支持字符计数
- ✨ 支持在前台注入渲染脚本(需在设置中开启)

View File

@ -1,14 +1,9 @@
# halo-plugin-vditor
---
## NEXT VERSION
- ✨ 使用新的快速插入表单,界面更美观
- ✨ 支持渲染其他插件/主题的自定义组件(需要开发者支持)
- ✨ 允许用户禁用HTML代码块隐藏的特性
---
![](https://img.shields.io/badge/状态-稳定-red.svg)
![](https://img.shields.io/badge/启动时间-2023/11/23-green.svg)
![](https://img.shields.io/badge/优先级-HIGH-blue.svg)
![GitHub Release](https://img.shields.io/github/v/release/justice2001/halo-plugin-vditor?color=yellow&label=版本)
本插件将Vditor整合进Halo支持所见即所得编辑模式。 Support English (*Only Editor)!
@ -68,7 +63,9 @@
## 🙏 鸣谢
>特别感谢[Vditor](https://github.com/Vanessa219/vditor),本插件大部分内容均为此编辑器提供
> 特别感谢来自 [Halo](https://github.com/halo-dev) 的投喂
> 特别感谢[Vditor](https://github.com/Vanessa219/vditor),本插件大部分内容均为此编辑器提供
* [Vditor](https://github.com/Vanessa219/vditor) 一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora和分屏预览模式。
* [Lute](https://github.com/88250/lute):🎼 一款结构化的 Markdown 引擎,支持 Go 和 JavaScript

View File

@ -41,13 +41,9 @@ build {
}
halo {
version = '2.11.3'
version = '2.14'
superAdminUsername = 'admin'
superAdminPassword = 'admin'
externalUrl = 'http://localhost:8090'
docker {
// windows npipe:////./pipe/docker_engine
url = 'npipe:////./pipe/docker_engine'
apiVersion = '1.42'
}
debug = true
}

View File

@ -15,11 +15,12 @@
"@halo-dev/api-client": "^2.11.0",
"@halo-dev/components": "^1.10.0",
"@halo-dev/console-shared": "^2.11.0",
"@zhengyi/vditor": "3.9.10",
"vditor": "3.10.2",
"canvas-confetti": "^1.6.0",
"vue": "^3.3.4"
},
"devDependencies": {
"@halo-dev/ui-plugin-bundler-kit": "^2.12.0",
"@iconify/json": "^2.2.76",
"@rushstack/eslint-patch": "^1.3.1",
"@types/canvas-confetti": "^1.6.0",
@ -42,5 +43,6 @@
"vite": "^3.2.7",
"vitest": "^0.24.5",
"vue-tsc": "^1.6.5"
}
},
"packageManager": "pnpm@8.0.0"
}

View File

@ -17,17 +17,20 @@ dependencies:
'@halo-dev/console-shared':
specifier: ^2.11.0
version: 2.11.0(vue-router@4.2.5)(vue@3.3.12)
'@zhengyi/vditor':
specifier: 3.9.10
version: 3.9.10
canvas-confetti:
specifier: ^1.6.0
version: 1.9.2
vditor:
specifier: 3.10.2
version: 3.10.2
vue:
specifier: ^3.3.4
version: 3.3.12(typescript@4.7.4)
devDependencies:
'@halo-dev/ui-plugin-bundler-kit':
specifier: ^2.12.0
version: 2.12.0(vite@3.2.7)
'@iconify/json':
specifier: ^2.2.76
version: 2.2.159
@ -595,6 +598,15 @@ packages:
vue-router: 4.2.5(vue@3.3.12)
dev: false
/@halo-dev/ui-plugin-bundler-kit@2.12.0(vite@3.2.7):
resolution: {integrity: sha512-3558qzH5RN9pB2j0ZonuIxX3cw8lh870cWpPPHjkDxTIjKt+aO5tjKhcqKlFL853jdx9nHIIS+nMDCeqjejpxw==}
engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
vite: ^4.0.0 || ^5.0.0
dependencies:
vite: 3.2.7(@types/node@16.18.68)(sass@1.69.5)
dev: true
/@humanwhocodes/config-array@0.11.13:
resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==}
engines: {node: '>=10.10.0'}
@ -1117,17 +1129,6 @@ packages:
'@types/node': 16.18.68
dev: true
/@zhengyi/halo-render@1.1.0:
resolution: {integrity: sha512-r+aD7wvdXVRyFcw/yI/PbdIqSsC+Bnql2WSKZa8CK+ntpTvc2tybn6Wxsfw96C71QS+Q/MPe8ufwZBjtRd+hhg==, tarball: https://git.mczhengyi.top/api/packages/zhengyi/npm/%40zhengyi%2Fhalo-render/-/1.1.0/halo-render-1.1.0.tgz}
dev: false
/@zhengyi/vditor@3.9.10:
resolution: {integrity: sha512-8bAUlH4bsuUNbkrxAuxTL0XMNoLre/mab5HF8cR9wND7e/Xj56l2qz7aEARklK6oRtOlCoTYK6JEkLdozUfTkg==, tarball: https://git.mczhengyi.top/api/packages/zhengyi/npm/%40zhengyi%2Fvditor/-/3.9.10/vditor-3.9.10.tgz}
dependencies:
'@zhengyi/halo-render': 1.1.0
diff-match-patch: 1.0.5
dev: false
/abab@2.0.6:
resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==}
deprecated: Use your platform's native atob() and btoa() methods instead
@ -3717,6 +3718,12 @@ packages:
spdx-expression-parse: 3.0.1
dev: true
/vditor@3.10.2:
resolution: {integrity: sha512-NtnsqKoU7cFUb7HPLct+fSjRnuhSlfSp0bpCDm0GcH2emngoZb6m1cEyg8yhu1WkHt8ugD9i1OMrA1tnMEW6fA==}
dependencies:
diff-match-patch: 1.0.5
dev: false
/vite@3.2.7(@types/node@16.18.68)(sass@1.69.5):
resolution: {integrity: sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==}
engines: {node: ^14.18.0 || >=16.0.0}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
style="fill: #ffffff;"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10 11C10 10.4477 10.4477 10 11 10H13C13.5523 10 14 10.4477 14 11C14 11.5523 13.5523 12 13 12H11C10.4477 12 10 11.5523 10 11Z"
/>
<path
d="M11 14C10.4477 14 10 14.4477 10 15C10 15.5523 10.4477 16 11 16H13C13.5523 16 14 15.5523 14 15C14 14.4477 13.5523 14 13 14H11Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M9.09447 4.74918C8.41606 4.03243 8 3.0648 8 2H10C10 3.10457 10.8954 4 12 4C13.1046 4 14 3.10457 14 2H16C16 3.0648 15.5839 4.03243 14.9055 4.74918C16.1782 5.45491 17.1673 6.6099 17.6586 8H19C19.5523 8 20 8.44772 20 9C20 9.55229 19.5523 10 19 10H18V12H19C19.5523 12 20 12.4477 20 13C20 13.5523 19.5523 14 19 14H18V16H19C19.5523 16 20 16.4477 20 17C20 17.5523 19.5523 18 19 18H17.6586C16.8349 20.3304 14.6124 22 12 22C9.38756 22 7.16508 20.3304 6.34141 18H5C4.44772 18 4 17.5523 4 17C4 16.4477 4.44772 16 5 16H6V14H5C4.44772 14 4 13.5523 4 13C4 12.4477 4.44772 12 5 12H6V10H5C4.44772 10 4 9.55229 4 9C4 8.44772 4.44772 8 5 8H6.34141C6.83274 6.6099 7.82181 5.45491 9.09447 4.74918ZM8 16V10C8 7.79086 9.79086 6 12 6C14.2091 6 16 7.79086 16 10V16C16 18.2091 14.2091 20 12 20C9.79086 20 8 18.2091 8 16Z"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -24,6 +24,13 @@ const lang: I18nLang = {
link: "Link",
password: "Password",
quick_insert: "Quick Insert",
insert_gallery: "Insert Gallery",
grid: "Grid",
linear: "Linear",
image_group: "Image Group",
image: "Image",
image_alt: "Alt",
image_alt_ph: "Use File Name If You Dont Place This",
};
export default lang;

View File

@ -24,6 +24,13 @@ const lang: I18nLang = {
link: "链接",
password: "密码",
quick_insert: "快速插入",
insert_gallery: "插入图集",
grid: "九宫格",
linear: "线性",
image_group: "图片组",
image: "图片",
image_alt: "图片介绍",
image_alt_ph: "不填写此项则默认使用图像文件名",
};
export default lang;

View File

@ -24,6 +24,13 @@ const lang: I18nLang = {
link: "鏈接",
password: "密碼",
quick_insert: "快速插入",
insert_gallery: "插入圖集",
grid: "九宮格",
linear: "線性",
image_group: "圖片組",
image: "圖片",
image_alt: "圖片介紹",
image_alt_ph: "不填寫此項則默認使用影像檔名",
};
export default lang;

View File

@ -1,7 +1,7 @@
import {definePlugin, type EditorProvider} from "@halo-dev/console-shared";
import Vditor from "./views/Vditor.vue";
import logo from "./assets/vditor.png"
import {markRaw} from "vue";
import { definePlugin, type EditorProvider } from "@halo-dev/console-shared";
import logo from "./assets/vditor.png";
import { markRaw } from "vue";
import VditorMde from "./views/VditorMde.vue";
export default definePlugin({
components: {},
@ -11,10 +11,9 @@ export default definePlugin({
{
name: "vditor-mde",
displayName: "Vditor Markdown",
// @ts-ignore
component: markRaw(Vditor),
component: markRaw(VditorMde),
rawType: "markdown",
logo: logo
logo: logo,
},
];
},

View File

@ -0,0 +1,122 @@
<template>
<div id="vditor-debug-panel">
<div id="vditor-debug-op" :class="{ active: debugOpOpen }">
<div id="vditor-debug-op-bar" @click="debugOpOpen = !debugOpOpen">
<img src="../assets/debug.svg" alt="DEBUG"/>
</div>
<VButton type="primary" size="sm" @click="getRaw">Get Raw</VButton>
<VButton type="primary" size="sm" @click="getHTML">Get HTML</VButton>
<VButton type="primary" size="sm" @click="getRenderList">
Get Vditor Options
</VButton>
<VButton type="primary" size="sm" @click="getPluginConfig">
Get Plugin Config
</VButton>
<VButton type="primary" size="sm" @click="getCursor">
Get Last Cursor
</VButton>
</div>
<div v-if="false" id="vditor-debug-data">
<div>Vditor DEBUG</div>
</div>
</div>
</template>
<script setup lang="ts">
import type { EditorConfig } from "@/utils/config-utils";
import { renderHTML } from "@/utils/vditor-utils";
import { VButton } from "@halo-dev/components";
import type Vditor from "vditor";
import { defineProps, ref } from "vue";
const debugOpOpen = ref<boolean>(false);
const props = defineProps<{
vditor: Vditor | null;
config: EditorConfig | undefined;
cursor: Range | undefined;
}>();
const getRaw = () => {
if (!props.vditor) return;
console.log("RAW: ", props.vditor?.getValue());
};
const getHTML = () => {
if (!props.vditor) return;
console.log("HTML", renderHTML(props.vditor));
};
const getRenderList = () => {
if (!props.vditor) return;
console.log("RENDER LIST", props.vditor.vditor.options);
};
const getPluginConfig = () => {
if (props.config) {
console.log("CONFIG: ", props.config);
}
};
const getCursor = () => {
if (props.cursor) {
console.log("LAST CURSOR", props.cursor);
}
};
</script>
<style scoped>
#vditor-debug-panel {
z-index: 9999;
}
#vditor-debug-op {
position: fixed;
padding: 10px;
z-index: 9999;
background-color: #999;
border-radius: 5px 0 0 5px;
right: 0;
top: 50%;
transform: translateY(-50%) translateX(100%);
transition: transform 0.3s;
display: flex;
flex-direction: column;
gap: 5px;
}
#vditor-debug-op-bar {
content: "";
position: absolute;
width: 26px;
height: 35px;
background-color: #999;
left: -26px;
border-radius: 5px 0 0 5px;
top: 50%;
transform: translateY(-50%);
text-align: center;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
#vditor-debug-op-bar img {
width: 16px;
}
#vditor-debug-op.active {
transform: translateY(-50%) translateX(0);
}
#vditor-debug-data {
position: fixed;
left: 10px;
top: 10px;
background-color: #000000cc;
color: #ffffff;
z-index: 9999;
padding: 10px;
}
</style>

View File

@ -31,8 +31,11 @@ const generateCode = () => {
emit("done", htmlEncode(code));
return;
}
props.schema.handler && props.schema.handler(data.value);
emit("done", null);
emit(
"done",
(props.schema.handler && props.schema.handler(data.value)) || null
);
};
// FormKit IDSchema

View File

@ -0,0 +1,83 @@
import type { Schema, SchemaData } from "@/type/editor";
import { t } from "@/utils/i18n-utils";
const schema: Schema = {
type: "template",
id: "gallery",
icon: "",
name: t("insert_gallery"),
formKit: [
{
$formkit: "select",
name: "type",
label: t("type"),
value: "grid",
options: {
grid: t("grid"),
linear: t("linear"),
},
},
{
$formkit: "text",
name: "title",
label: t("title"),
value: "",
},
{
$formkit: "repeater",
name: "attachments",
label: t("image_group"),
min: 1,
value: [{}],
children: [
{
$formkit: "attachment",
name: "attachment",
label: t("image"),
accepts: ["image/*"],
value: "",
},
{
$formkit: "text",
name: "attach_title",
label: t("image_alt"),
value: "",
placeholder: t("image_alt_ph"),
},
],
},
],
handler: (data: SchemaData) => {
// title type list[]
const galleryData = data as GallerySchemaData;
let html = `\`\`\`halo\ngallery:${galleryData.type}`;
if (galleryData.title) {
html += `[${galleryData.title}]`;
}
html += "\n";
galleryData.attachments?.forEach((att) => {
let title = "";
if (att.attach_title) {
title = att.attach_title;
} else {
const start = att.attachment.lastIndexOf("/");
const end = att.attachment.lastIndexOf(".");
title = att.attachment.slice(start, end);
}
html += `![${title}](${att.attachment})\n`;
});
html += "```";
return html;
},
};
export interface GallerySchemaData extends SchemaData {
title: string;
type: "grid" | "linear";
attachments: Array<{
attachment: string;
attach_title?: string;
}>;
}
export default schema;

View File

@ -1,5 +1,5 @@
import type { Schema } from "@/type/editor";
import {t} from "@/utils/i18n-utils";
import { t } from "@/utils/i18n-utils";
const schema: Schema = {
type: "template",

View File

@ -1,3 +1,5 @@
import type { EditorConfig } from "@/utils/config-utils";
export declare type Options = {
defaultRenderMode: "ir" | "wysiwyg" | "sv" | undefined;
typeWriterMode: boolean;
@ -10,6 +12,7 @@ export declare type Options = {
openModal: (schema: Schema) => void;
quickInsertList: QuickInsert[];
enableQuickInsert: boolean;
config: EditorConfig;
};
export interface Schema {
@ -22,7 +25,11 @@ export interface Schema {
// 解析后处理
afterHandle?: (data: { [key: string]: string }, code: string) => string;
// 覆盖解析
handler?: (data: { [key: string]: string }) => string;
handler?: (data: SchemaData) => string;
}
export interface SchemaData {
_id?: string;
}
export interface QuickInsert {

View File

@ -7,10 +7,14 @@ export declare type EditorConfig = {
enableQuickInsert: boolean;
quickInsertUrl: [];
disableHTMLBlockPreview: boolean;
firstH1AsTitle: boolean;
};
extension: {
allowImageType: string;
};
developer: {
debugger: boolean;
};
};
export const defaultEditorConfig: EditorConfig = {
@ -22,8 +26,12 @@ export const defaultEditorConfig: EditorConfig = {
enableQuickInsert: false,
quickInsertUrl: [],
disableHTMLBlockPreview: false,
firstH1AsTitle: false,
},
extension: {
allowImageType: "png,jpg,jpeg,bmp,gif,webp,svg",
}
}
},
developer: {
debugger: false,
},
};

View File

@ -1,5 +1,5 @@
export function getCursor() {
return window.getSelection()?.getRangeAt(0);
return window.getSelection()?.getRangeAt(0).cloneRange();
}
export function setCursor(range: Range | undefined) {

View File

@ -2,7 +2,7 @@ import zhCN from "@/i18n/zh-CN";
import type { I18nLang } from "@/type/i18n";
import zhTW from "@/i18n/zh-TW";
import enUS from "@/i18n/en-US";
import {getLanguage} from "@/utils/vditor-utils";
import { getLanguage } from "@/utils/vditor-utils";
const langDict: { [key: string]: I18nLang } = {
zh_CN: zhCN,

View File

@ -4,6 +4,14 @@ import { t } from "@/utils/i18n-utils";
import tips from "@/schema/tips";
import git from "@/schema/git";
import drive from "@/schema/drive";
import gallery from "@/schema/gallery";
import { addScript, addStyleSheet } from "@/utils/dom-utils";
import type Vditor from "vditor";
import type {EditorConfig} from "@/utils/config-utils";
declare const HaloJs: {
renderHalo: (content: string, cdn: string) => string;
};
export function getOptions(options: Options): IOptions {
const cdn =
@ -50,6 +58,9 @@ export function getOptions(options: Options): IOptions {
current: "light",
path: `${cdn}/dist/css/content-theme`,
},
math: {
inlineDigit: true,
},
},
outline: {
enable: true,
@ -61,6 +72,8 @@ export function getOptions(options: Options): IOptions {
upload: {
handler: options.uploadImage,
},
debugger: options.config.developer.debugger,
customRenders: getCustomRenders(options),
};
}
@ -141,6 +154,11 @@ function getToolbar(
icon: t("insert_drive"),
click: () => openModal(drive),
},
{
name: "insert_gallery",
icon: t("insert_gallery"),
click: () => openModal(gallery),
},
],
},
{
@ -170,3 +188,70 @@ function buildQuickInsertToolbar(
toolbar: children,
};
}
/**
*
* @param options
*/
function getCustomRenders(options: Options):
| {
language: string;
render: (element: HTMLElement, vditor: IVditor) => void;
}[]
| undefined {
if (options.config.developer.debugger) {
console.log("QUICK INSERT: ", options.quickInsertList);
}
const renders: {
language: string;
render: (element: HTMLElement, vditor: IVditor) => void;
}[] = [];
// 启用内置渲染器
addScript(
"/plugins/vditor-mde/assets/static/halo-renders/index.js",
"halo-render"
);
addStyleSheet(
"/plugins/vditor-mde/assets/static/halo-renders/index.css",
"halo-render-css"
);
renders.push({
language: "halo",
render: (element: HTMLElement) => {
element.querySelectorAll(".language-halo").forEach((el) => {
el.outerHTML = HaloJs.renderHalo(
el.textContent || "",
"/plugins/vditor-mde/assets/static/halo-renders"
);
});
},
});
console.log("Renders: ", renders);
return renders;
}
/**
*
* TODO: 该部分建议加入Vditor
* @param vditor vditor
* @param config Editor Config
* @returns html
*/
export function renderHTML(vditor: Vditor, config: EditorConfig): string {
let value = vditor.getHTML();
const customRenders = vditor.vditor.options.customRenders;
// FIXME 此部分逻辑有大问题!
customRenders?.forEach((render) => {
const reg = new RegExp(
`<pre><code class="language-${render.language}">(.*?)</code></pre>`,
"gs"
);
value = value.replace(reg, '<div class="language-halo">$1</div>');
});
// Remove H1 Title When start with "h1"
if (config.basic.firstH1AsTitle && value.startsWith("<h1")) {
value = value.replace(/<h1(?:\s+[^>]*)?>(.*?)<\/h1>/, "");
console.log(value);
}
return value;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,352 @@
<script setup lang="ts">
import Vditor from "vditor";
import { onMounted, onUnmounted, ref, watch } from "vue";
import "vditor/dist/index.css";
import type { Schema } from "@/type/editor";
import { getOptions, renderHTML } from "@/utils/vditor-utils";
import type { AttachmentLike } from "@halo-dev/console-shared";
import type { Attachment } from "@halo-dev/api-client";
import { VLoading } from "@halo-dev/components";
import TemplateModal from "@/model/TemplateModal.vue";
import joeProgress from "@/schema/joe-progress";
import { fetchAllQuickInsert } from "@/utils/fetch-utils";
import { quickInsertInject } from "@/utils/quick-insert-utils";
import { addStyle } from "@/utils/dom-utils";
import { getCursor, setCursor } from "@/utils/cursor-utils";
import { defaultEditorConfig, type EditorConfig } from "@/utils/config-utils";
import DebugPanel from "@/model/DebugPanel.vue";
const props = withDefaults(
defineProps<{
title?: string;
raw?: string;
content: string;
uploadImage?: (file: File) => Promise<Attachment>;
}>(),
{
title: "",
raw: "",
content: "",
uploadImage: undefined,
}
);
const vditor = ref();
const vditorRef = ref();
const vditorLoaded = ref(false);
const attachmentSelectorModalShow = ref(false);
const editorConfig = ref<EditorConfig>();
// none/tips/git
//
const customInsertOpen = ref(false);
const customInsertSchema = ref<Schema>(joeProgress);
let lastSelectionRange: Range | undefined = undefined;
// Image Upload
let imageUploadCursor: Range | undefined;
const imageUploadLock = false;
let allowImageUpload: string[] = [];
// Debug
const debugMode = ref<boolean>(false);
// updateContent
const internalTitle = ref<string>("");
const emit = defineEmits<{
(event: "update:raw", value: string): void;
(event: "update:content", value: string): void;
(event: "update", value: string): void;
(event: "update:title", value: string): void;
}>();
// Watch Title Change
watch(
() => props.title,
(val) => {
// When option disabled or nothing to update
if (
!editorConfig.value?.basic.firstH1AsTitle ||
internalTitle.value === val
) {
return;
}
// Get title
const vdiVal = vditor.value.getValue();
if (vdiVal.startsWith("# ")) {
internalTitle.value = val;
vditor.value.setValue(vdiVal.replace(/# .*?\n/, `# ${val}\n`));
}
}
);
// Update content
const debounceOnUpdate = () => {
//
let value = vditor.value.getValue();
if (editorConfig.value?.basic.firstH1AsTitle && value.startsWith("# ")) {
// First Line is Title
const firstLine = value.match(/^.*/)[0];
console.log(`title is ${firstLine.substring(2)}`);
internalTitle.value = firstLine.substring(2);
emit("update:title", internalTitle.value);
//
value = value.substring(firstLine.length + 2);
}
// update content
emit("update:raw", value);
emit(
"update:content",
renderHTML(vditor.value, editorConfig.value || defaultEditorConfig) || ""
);
emit("update", value);
};
//
const attachmentSelect = (attachments: AttachmentLike[]) => {
setCursor(lastSelectionRange);
// Reference https://github.com/guqing/willow-mde/blob/4b8e697132f8a8f4b08dd0f92cf10d070cb26793/console/src/components/toolbar/Toolbar.vue#L104
attachments.forEach((attachment) => {
if (typeof attachment === "string") {
vditor.value.insertValue(`![](${attachment})`);
} else if ("url" in attachment) {
vditor.value.insertValue(`![${attachment.type}](${attachment.url})`);
} else if ("spec" in attachment) {
const { displayName } = attachment.spec;
const { permalink } = attachment.status || {};
vditor.value.insertValue(`![${displayName}](${permalink})`);
}
});
};
onUnmounted(async () => {
document
.querySelectorAll("script[id^='vditor']")
.forEach((el) => el.remove());
document.querySelectorAll("link[id^='vditor']").forEach((el) => el.remove());
vditorLoaded.value = false;
});
onMounted(async () => {
// :
const lang = localStorage.getItem("locale") || "zh-CN";
try {
const response = await fetch(
"/apis/api.vditor.mczhengyi.top/editor-options"
);
editorConfig.value = await response.json();
} catch (e) {
// ignore this
editorConfig.value = defaultEditorConfig;
}
if (!editorConfig.value) return;
// Assign allowImage
allowImageUpload = allowImageUpload.concat(
editorConfig.value.extension.allowImageType.split(",").map((i) => i.trim())
);
console.log("ALLOW", allowImageUpload);
// HTML
if (editorConfig.value.basic.disableHTMLBlockPreview)
addStyle(
"[data-type=html-block] pre {display: block!important;}\n" +
".vditor-ir__node[data-type=html-block] .vditor-ir__marker {height: auto; width: auto; display: inline;}",
"vditor-mde-hide-html"
);
// Debug Mode
debugMode.value = editorConfig.value.developer.debugger;
// Quick Insert Process
const qil = await fetchAllQuickInsert(
editorConfig.value.basic.quickInsertUrl
);
qil.forEach((q) => {
quickInsertInject(q.inject || [], q.provider);
});
// Create Vditor
vditor.value = new Vditor(
vditorRef.value,
getOptions({
defaultRenderMode: editorConfig.value.basic.defaultRenderMode,
typeWriterMode: editorConfig.value.basic.typeWriterMode,
after: () => {
let content = "";
if (props.raw) {
content = props.raw;
}
if (editorConfig.value?.basic.firstH1AsTitle) {
internalTitle.value = props.title;
content = `# ${props.title}\n\n` + content;
}
vditor.value.setValue(content);
vditorLoaded.value = true;
},
input: debounceOnUpdate,
showAttachment: () => {
lastSelectionRange = getCursor();
attachmentSelectorModalShow.value = true;
},
language: lang,
codeBlockPreview: editorConfig.value.basic.codeBlockPreview,
uploadImage: (files: File[]) => {
console.log("UPLOAD IMAGE");
if (imageUploadLock) {
vditor.value.tip("当前已经存在正在上传的文件,请等待上传完成", 2000);
return;
}
// Save cursor
imageUploadCursor = getCursor();
// Check extension name
const extendName = files[0].name
.slice(files[0].name.lastIndexOf(".") + 1)
.toLowerCase();
if (allowImageUpload.indexOf(extendName) === -1) {
vditor.value.tip("不允许上传该类型图片!", 2000);
return null;
}
// Upload
if (props.uploadImage) {
vditor.value.tip("正在上传图片...", 2000);
props.uploadImage(files[0]).then((res: Attachment) => {
if (!res.status) return;
vditor.value.disabled();
// Move cursor
const tmpCursor = getCursor();
setCursor(imageUploadCursor);
imageUploadCursor = undefined;
// Insert
vditor.value.insertValue(
`\n\n![${res.spec.displayName}](${res.status.permalink})\n\n`
);
// Restore cursor
setCursor(tmpCursor);
vditor.value.enable();
});
}
return null;
},
openModal: (schema: Schema) => {
lastSelectionRange = getCursor();
customInsertSchema.value = schema;
customInsertOpen.value = true;
},
enableQuickInsert: editorConfig.value.basic.enableQuickInsert,
quickInsertList: qil,
config: editorConfig.value,
})
);
});
const update = (val: string | null) => {
setCursor(lastSelectionRange);
if (!val) {
vditor.value.tip("未知错误,插入失败", 3000);
} else {
vditor.value.focus();
vditor.value.insertValue(`\n\n${val}\n\n`);
}
customInsertOpen.value = false;
};
</script>
<template>
<div
id="plugin-vditor-mde"
:class="{ h1AsTitle: editorConfig?.basic.firstH1AsTitle }"
>
<VLoading v-if="!vditorLoaded" style="height: 100%" />
<DebugPanel
v-if="debugMode"
:config="editorConfig"
:vditor="vditor"
:cursor="lastSelectionRange"
/>
<div id="vditor" ref="vditorRef"></div>
<TemplateModal
:open="customInsertOpen"
:schema="customInsertSchema"
@close="customInsertOpen = false"
@done="update"
/>
<AttachmentSelectorModal
v-model:visible="attachmentSelectorModalShow"
:accepts="['image/*']"
:max="1"
@select="attachmentSelect"
/>
</div>
</template>
<style>
#plugin-vditor-mde ol {
list-style: decimal;
}
/** Fix Link color in wysiwyg mode */
#plugin-vditor-mde a {
color: #3478cd;
}
/** Fix content was covered by vditor panel in wysiwyg mode */
#plugin-vditor-mde button,
#plugin-vditor-mde input {
line-height: normal;
}
.insert-modals label {
width: 100%;
display: flex;
}
.insert-modals label span {
width: 60px;
text-align: right;
}
.insert-modals select {
border: 1px solid #cccccc;
border-radius: 3px;
padding-top: 8px;
padding-bottom: 8px;
margin-left: 10px;
flex: 1;
}
.insert-modals textarea {
border: 1px solid #cccccc;
border-radius: 3px;
margin-left: 10px;
flex: 1;
}
.insert-modals input[type="text"] {
border: 1px solid #cccccc;
border-radius: 3px;
margin-left: 10px;
flex: 1;
padding: 8px 10px;
}
/* title */
#plugin-vditor-mde.h1AsTitle .vditor-ir h1:first-child::before,
#plugin-vditor-mde.h1AsTitle .vditor-wysiwyg h1:first-child::before {
content: "T";
}
#plugin-vditor-mde.h1AsTitle .vditor-ir h1:first-child,
#plugin-vditor-mde.h1AsTitle .vditor-wysiwyg h1:first-child {
border-bottom: 2px solid #eaecef;
color: #333333;
text-align: left;
text-decoration: none;
font-size: 2rem;
background: none;
}
/**
Fix compatible issues with docsme.
https://github.com/justice2001/halo-plugin-vditor/issues/38
*/
#plugin-vditor-mde code[class*=language-],
#plugin-vditor-mde pre[class*=language-] {
color: #000000;
}
</style>

View File

@ -4,58 +4,19 @@ import { defineConfig } from "vite";
import Vue from "@vitejs/plugin-vue";
import VueJsx from "@vitejs/plugin-vue-jsx";
import Icons from "unplugin-icons/vite";
const pluginEntryName = "vditor-mde";
import { HaloUIPluginBundlerKit } from "@halo-dev/ui-plugin-bundler-kit";
// https://vitejs.dev/config/
export default ({ mode }: { mode: string }) => {
const isProduction = mode === "production";
const outDir = isProduction
? "../src/main/resources/console"
: "../build/resources/main/console";
return defineConfig({
plugins: [Vue(),VueJsx(), Icons({ compiler: "vue3" })],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
export default defineConfig({
plugins: [
Vue(),
VueJsx(),
Icons({ compiler: "vue3" }),
HaloUIPluginBundlerKit(),
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
define: {
"process.env": process.env,
},
build: {
outDir,
emptyOutDir: true,
lib: {
entry: "src/index.ts",
name: pluginEntryName,
formats: ["iife"],
fileName: () => "main.js",
},
rollupOptions: {
external: [
"vue",
"vue-router",
"@vueuse/core",
"@vueuse/components",
"@vueuse/router",
"@halo-dev/shared",
"@halo-dev/components",
],
output: {
globals: {
vue: "Vue",
"vue-router": "VueRouter",
"@vueuse/core": "VueUse",
"@vueuse/components": "VueUse",
"@vueuse/router": "VueUse",
"@halo-dev/console-shared": "HaloConsoleShared",
"@halo-dev/components": "HaloComponents",
},
extend: true,
},
},
},
});
};
},
});

47
doc/test/halo-render.md Normal file
View File

@ -0,0 +1,47 @@
```halo
tips:info
test1
```
```halo**
tips:warn
22222
```
```halo
tips:default
DEFAULT TIPS
```
```halo
tips:success
SUCCESS TIPS
```
```halo
tips:danger
DANGER TIPS
```
```halo
git:[@github/justice2001/halo-plugin-vditor]
```
```halo
gallery:grid[Grid]
![/截屏2024-01-17%2015.53.25](/upload/截屏2024-01-17%2015.53.25.png)
![123](/upload/截屏2024-01-17%2014.11.28.png)
```
```halo
gallery:linear
![/截屏2024-01-17%2015.53.25](/upload/截屏2024-01-17%2015.53.25.png)
![123](/upload/截屏2024-01-17%2014.11.28.png)
```
![截屏2024-01-17 15.53.25.png](/upload/截屏2024-01-17%2015.53.25.png)
![截屏2024-01-17 15.53.25.png](/upload/截屏2024-01-17%2015.53.25.png)
![截屏2024-01-17 14.11.28.png](/upload/截屏2024-01-17%2014.11.28.png)

1
doc/test/render.md Normal file
View File

@ -0,0 +1 @@
[WIP]

51
doc/test/test_case.md Normal file
View File

@ -0,0 +1,51 @@
# 测试文档[WIP]
为了保证插件更新过程的正常运行,需要进行下面的测试用例,测试包含下面几个大类:
1. 基础功能,包含插件的基础设置功能,运行状态
2. 插件配置,包含所有插件的配置功能
3. 拓展功能,包含插件的拓展项测试
4. 文档测试,检查插件在前台、编辑器中的显示状态
## 基础功能
- 编辑器是否正常加载
- 编辑器能否正常使用
- 前台是否能够正常渲染
## 插件配置
- 编辑器配置
- 默认渲染模式是否正常工作
- 打字机模式是否正常开启
- 编辑器代码块渲染是否能够正常关闭
- 启用快速插入功能是否正常启用(使用见下方用例)
- 是否能够禁用代码块隐藏
- 文件格式
- 能否正常限制上传的格式
- 渲染
- `内置渲染器` 能否正常禁用渲染器
- `暗色模式` 切换主题,检查能否正常适配主题暗色模式
- `渲染媒体标签` 检查渲染媒体标签是否正常运作
- `仅在Markdown模式下渲染` 是否能够禁用在其他编辑器下渲染
- 开发者配置
- `启用Debugger` Debugger能否正常工作
## 拓展功能
WIP
## 文档测试
借助文档测试,可以判断编辑器及渲染器能否正常渲染文章,这包含下列几种情况
- 编辑器能否正常工作
- 能否在文章页面进行渲染
- 能否在单页进行渲染
- 能否兼容PJAX
文章列表如下
- [Vditor 官方用例](vditor.md)
- [渲染器用例](render.md)
- [Halo Render测试](halo-render.md)

396
doc/test/vditor.md Normal file
View File

@ -0,0 +1,396 @@
Vditor 是一款**所见即所得**编辑器,支持 *Markdown*
* 不熟悉 Markdown 可使用工具栏或快捷键进行排版
* 熟悉 Markdown 可直接排版,也可切换为分屏预览
更多细节和用法请参考 [Vditor - 浏览器端的 Markdown 编辑器](https://ld246.com/article/1549638745630),同时也欢迎向我们提出建议或报告问题,谢谢 ❤️
## 教程
这是一篇讲解如何正确使用 **Markdown** 的排版示例,学会这个很有必要,能让你的文章有更佳清晰的排版。
> 引用文本Markdown is a text formatting syntax inspired
## 语法指导
### 普通内容
这段内容展示了在内容里面一些排版格式,比如:
- **加粗** - `**加粗**`
- *倾斜* - `*倾斜*`
- ~~删除线~~ - `~~删除线~~`
- `Code 标记` - `` `Code 标记` ``
- [超级链接](https://ld246.com) - `[超级链接](https://ld246.com)`
- [username@gmail.com](mailto:username@gmail.com) - `[username@gmail.com](mailto:username@gmail.com)`
### 提及用户
@Vanessa 通过 `@User` 可以在内容中提及用户,被提及的用户将会收到系统通知。
> NOTE:
>
> 1. @用户名之后需要有一个空格
> 2. 新手没有艾特的功能权限
### 表情符号 Emoji
支持大部分标准的表情符号,可使用输入法直接输入,也可手动输入字符格式。通过输入 `:` 触发自动完成,可在个人设置中[设置常用表情](https://ld246.com/settings/function)。
#### 一些表情例子
😄 😆 😵 😭 😰 😅 😢 😤 😍 😌
👍 👎 💯 👏 🔔 🎁 ❓ 💣 ❤️ ☕️ 🌀 🙇 💋 🙏 💢
### 大标题 - Heading 3
你可以选择使用 H1 至 H6使用 ##(N) 打头。建议帖子或回帖中的顶级标题使用 Heading 3不要使用 1 或 2因为 1 是系统站点级2 是帖子标题级。
> NOTE: 别忘了 # 后面需要有空格!
#### Heading 4
##### Heading 5
###### Heading 6
### 图片
```
![alt 文本](http://image-path.png)
![alt 文本](http://image-path.png "图片 Title 值")
```
支持复制粘贴直接上传。
### 代码块
#### 普通
```
*emphasize* **strong**
_emphasize_ __strong__
var a = 1
```
#### 语法高亮支持
如果在 ``` 后面跟随语言名称,可以有语法高亮的效果哦,比如:
##### 演示 Go 代码高亮
```go
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
```
##### 演示 Java 高亮
```java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
```
> Tip: 语言名称支持下面这些: `ruby`, `python`, `js`, `html`, `erb`, `css`, `coffee`, `bash`, `json`, `yml`, `xml` ...
### 有序、无序、任务列表
#### 无序列表
- Java
- Spring
- IoC
- AOP
- Go
- gofmt
- Wide
- Node.js
- Koa
- Express
#### 有序列表
1. Node.js
1. Express
2. Koa
3. Sails
2. Go
1. gofmt
2. Wide
3. Java
1. Latke
2. IDEA
#### 任务列表
- [x] 发布 Sym
- [x] 发布 Solo
- [ ] 预约牙医
### 表格
如果需要展示数据什么的,可以选择使用表格。
| header 1 | header 2 |
| -------- | -------- |
| cell 1 | cell 2 |
| cell 3 | cell 4 |
| cell 5 | cell 6 |
### 隐藏细节
<details>
<summary>这里是摘要部分。</summary>
这里是细节部分。
</details>
### 段落
空行可以将内容进行分段,便于阅读。(这是第一段)
使用空行在 Markdown 排版中相当重要。(这是第二段)
### 链接引用
[链接文本][链接标识]
[链接标识]: https://b3log.org
```
[链接文本][链接标识]
[链接标识]: https://b3log.org
```
### 数学公式
多行公式块:
$$
\frac{1}{
\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{
\frac25 \pi}} = 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {
1+\frac{e^{-6\pi}}
{1+\frac{e^{-8\pi}}{1+\cdots}}
}
}
$$
行内公式:
公式 $a^2 + b^2 = \color{red}c^2$ 是行内。
### 脑图
```mindmap
- 教程
- 语法指导
- 普通内容
- 提及用户
- 表情符号 Emoji
- 一些表情例子
- 大标题 - Heading 3
- Heading 4
- Heading 5
- Heading 6
- 图片
- 代码块
- 普通
- 语法高亮支持
- 演示 Go 代码高亮
- 演示 Java 高亮
- 有序、无序、任务列表
- 无序列表
- 有序列表
- 任务列表
- 表格
- 隐藏细节
- 段落
- 链接引用
- 数学公式
- 脑图
- 流程图
- 时序图
- 甘特图
- 图表
- 五线谱
- Graphviz
- 多媒体
- 脚注
- 快捷键
```
### 流程图
```mermaid
graph TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
```
### 时序图
```mermaid
sequenceDiagram
Alice->>John: Hello John, how are you?
loop Every minute
John-->>Alice: Great!
end
```
### 甘特图
```mermaid
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2019-01-01, 30d
Another task :after a1 , 20d
section Another
Task in sec :2019-01-12 , 12d
another task : 24d
```
### 图表
```echarts
{
"title": { "text": "最近 30 天" },
"tooltip": { "trigger": "axis", "axisPointer": { "lineStyle": { "width": 0 } } },
"legend": { "data": ["帖子", "用户", "回帖"] },
"xAxis": [{
"type": "category",
"boundaryGap": false,
"data": ["2019-05-08","2019-05-09","2019-05-10","2019-05-11","2019-05-12","2019-05-13","2019-05-14","2019-05-15","2019-05-16","2019-05-17","2019-05-18","2019-05-19","2019-05-20","2019-05-21","2019-05-22","2019-05-23","2019-05-24","2019-05-25","2019-05-26","2019-05-27","2019-05-28","2019-05-29","2019-05-30","2019-05-31","2019-06-01","2019-06-02","2019-06-03","2019-06-04","2019-06-05","2019-06-06","2019-06-07"],
"axisTick": { "show": false },
"axisLine": { "show": false }
}],
"yAxis": [{ "type": "value", "axisTick": { "show": false }, "axisLine": { "show": false }, "splitLine": { "lineStyle": { "color": "rgba(0, 0, 0, .38)", "type": "dashed" } } }],
"series": [
{
"name": "帖子", "type": "line", "smooth": true, "itemStyle": { "color": "#d23f31" }, "areaStyle": { "normal": {} }, "z": 3,
"data": ["18","14","22","9","7","18","10","12","13","16","6","9","15","15","12","15","8","14","9","10","29","22","14","22","9","10","15","9","9","15","0"]
},
{
"name": "用户", "type": "line", "smooth": true, "itemStyle": { "color": "#f1e05a" }, "areaStyle": { "normal": {} }, "z": 2,
"data": ["31","33","30","23","16","29","23","37","41","29","16","13","39","23","38","136","89","35","22","50","57","47","36","59","14","23","46","44","51","43","0"]
},
{
"name": "回帖", "type": "line", "smooth": true, "itemStyle": { "color": "#4285f4" }, "areaStyle": { "normal": {} }, "z": 1,
"data": ["35","42","73","15","43","58","55","35","46","87","36","15","44","76","130","73","50","20","21","54","48","73","60","89","26","27","70","63","55","37","0"]
}
]
}
```
### 五线谱
```abc
X: 24
T: Clouds Thicken
C: Paul Rosen
S: Copyright 2005, Paul Rosen
M: 6/8
L: 1/8
Q: 3/8=116
R: Creepy Jig
K: Em
|:"Em"EEE E2G|"C7"_B2A G2F|"Em"EEE E2G|\
"C7"_B2A "B7"=B3|"Em"EEE E2G|
"C7"_B2A G2F|"Em"GFE "D (Bm7)"F2D|\
1"Em"E3-E3:|2"Em"E3-E2B|:"Em"e2e gfe|
"G"g2ab3|"Em"gfeg2e|"D"fedB2A|"Em"e2e gfe|\
"G"g2ab3|"Em"gfe"D"f2d|"Em"e3-e3:|
```
### Graphviz
```graphviz
digraph finite_state_machine {
rankdir=LR;
size="8,5"
node [shape = doublecircle]; S;
node [shape = point ]; qi
node [shape = circle];
qi -> S;
S -> q1 [ label = "a" ];
S -> S [ label = "a" ];
q1 -> S [ label = "a" ];
q1 -> q2 [ label = "ddb" ];
q2 -> q1 [ label = "b" ];
q2 -> q2 [ label = "b" ];
}
```
### Flowchart
```flowchart
st=>start: Start
op=>operation: Your Operation
cond=>condition: Yes or No?
e=>end
st->op->cond
cond(yes)->e
cond(no)->op
```
### 多媒体
支持 v.qq.comyoutube.comyouku.comcoub.comfacebook.com/videodailymotion.com.mp4.m4v.ogg.ogv.webm.mp3.wav 链接解析
https://v.qq.com/x/cover/zf2z0xpqcculhcz/y0016tj0qvh.html
### 脚注
这里是一个脚注引用[^1],这里是另一个脚注引用[^bignote]。
[^1]: 第一个脚注定义。
[^bignote]: 脚注定义可使用多段内容。
缩进对齐的段落包含在这个脚注定义内。
```
可以使用代码块。
```
还有其他行级排版语法,比如**加粗**和[链接](https://b3log.org)。
```
这里是一个脚注引用[^1],这里是另一个脚注引用[^bignote]。
[^1]: 第一个脚注定义。
[^bignote]: 脚注定义可使用多段内容。
缩进对齐的段落包含在这个脚注定义内。
```
可以使用代码块。
```
还有其他行级排版语法,比如**加粗**和[链接](https://b3log.org)。
```
## 快捷键
我们的编辑器支持很多快捷键,具体请参考 [键盘快捷键](https://ld246.com/article/1474030007391)(或者按 "`?` "😼)

View File

@ -1,7 +1,7 @@
cd src/main/resources/static
if exist dist rmdir /s /q dist
echo %cd%
bitsadmin /transfer vditorDownloadJob https://git.mczhengyi.top/zhengyi/-/packages/npm/@zhengyi%%2Fvditor/3.9.10/files/262 %cd%\vditor.tgz
bitsadmin /transfer vditorDownloadJob https://registry.npmjs.org/vditor/-/vditor-3.10.2.tgz %cd%\vditor.tgz
7z x vditor.tgz
7z x vditor.tar
move /y %cd%\package\dist %cd%

View File

@ -4,7 +4,7 @@ cd src/main/resources/static
rm -rf dist
pwd
curl -o vditor.tgz \
https://git.mczhengyi.top/zhengyi/-/packages/npm/@zhengyi%2Fvditor/3.9.10/files/262
https://registry.npmjs.org/vditor/-/vditor-3.10.2.tgz
tar -xzvf vditor.tgz
mv package/dist .
rm -rf package

View File

@ -1 +1 @@
version=1.5.0-SNAPSHOT
version=1.6.3-SNAPSHOT

View File

@ -1,8 +1,8 @@
package top.mczhengyi.vditor;
import org.pf4j.PluginWrapper;
import org.springframework.stereotype.Component;
import run.halo.app.plugin.BasePlugin;
import run.halo.app.plugin.PluginContext;
/**
* <p>Plugin main class to manage the lifecycle of the plugin.</p>
@ -15,8 +15,8 @@ import run.halo.app.plugin.BasePlugin;
@Component
public class VditorMdePlugin extends BasePlugin {
public VditorMdePlugin(PluginWrapper wrapper) {
super(wrapper);
public VditorMdePlugin(PluginContext pluginContext) {
super(pluginContext);
}
@Override

View File

@ -4,8 +4,19 @@ import lombok.Data;
@Data
public class RenderConfig {
private final String VDITOR_VERSION = "3.10.2";
Boolean enableRender;
String darkMode;
Boolean mediaRender;
Boolean onlyMarkdown;
String cdn;
String cdnUrl;
public String getCdn() {
if ("self-hosted".equals(cdn)) {
return cdnUrl.replace("${v}", VDITOR_VERSION);
}
return cdn.replace("${v}", VDITOR_VERSION);
}
}

View File

@ -3,6 +3,7 @@ package top.mczhengyi.vditor.extension;
import com.google.common.base.Throwables;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginWrapper;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import run.halo.app.plugin.ReactiveSettingFetcher;
@ -17,18 +18,23 @@ public class VditorPostContentHandler implements ReactivePostContentHandler {
private final ReactiveSettingFetcher reactiveSettingFetcher;
private final PluginWrapper pluginWrapper;
@Override
public Mono<PostContentContext> handle(PostContentContext contentContext) {
return reactiveSettingFetcher.fetch("render", RenderConfig.class)
.map(renderConfig -> {
if (renderConfig.getEnableRender()&&
(!renderConfig.getOnlyMarkdown() || contentContext.getRawType().equals("markdown"))) {
contentContext.setContent(ScriptUtils.renderScript(renderConfig) + "\n" + contentContext.getContent());
var content = ScriptUtils.renderScript(renderConfig) + "\n" + contentContext.getContent();
contentContext.setContent(ScriptUtils.setContentProperty(content, pluginWrapper));
}
return contentContext;
})
.onErrorResume(e -> {
log.error("VditorHeadProcessor process failed", Throwables.getRootCause(e));
if (e instanceof Throwable) {
log.error("VditorHeadProcessor process failed", Throwables.getRootCause(e));
}
return Mono.just(contentContext);
});
}

View File

@ -1,8 +1,10 @@
package top.mczhengyi.vditor.extension;
import com.google.common.base.Throwables;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginWrapper;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import run.halo.app.plugin.ReactiveSettingFetcher;
@ -15,6 +17,8 @@ import top.mczhengyi.vditor.utils.ScriptUtils;
@Slf4j
public class VditorSinglePageContentHandler implements ReactiveSinglePageContentHandler {
private final ReactiveSettingFetcher reactiveSettingFetcher;
private final PluginWrapper pluginWrapper;
@Override
public Mono<SinglePageContentContext> handle(SinglePageContentContext contentContext) {
return reactiveSettingFetcher.fetch("render", RenderConfig.class)
@ -22,12 +26,15 @@ public class VditorSinglePageContentHandler implements ReactiveSinglePageContent
// 启用条件开启渲染器在启用仅Markdown渲染时当前页面为Markdown
if (renderConfig.getEnableRender() &&
(!renderConfig.getOnlyMarkdown() || contentContext.getRawType().equals("markdown"))) {
contentContext.setContent(ScriptUtils.renderScript(renderConfig) + "\n" + contentContext.getContent());
var content = ScriptUtils.renderScript(renderConfig) + "\n" + contentContext.getContent();
contentContext.setContent(ScriptUtils.setContentProperty(content, pluginWrapper));
}
return contentContext;
})
.onErrorResume(e -> {
log.error("VditorHeadProcessor process failed", Throwables.getRootCause(e));
if (e instanceof Throwable) {
log.error("VditorHeadProcessor process failed", Throwables.getRootCause(e));
}
return Mono.empty();
});
}

View File

@ -0,0 +1,54 @@
package top.mczhengyi.vditor.utils;
/**
* Script Builder
* 用于构造Script内嵌Script样式表
* @author zhengyi59
*/
public class ScriptBuilder {
private final StringBuilder script;
ScriptBuilder() {
this.script = new StringBuilder();
}
public ScriptBuilder script(String path, String id) {
this.script.append("<script src=\"%s?version=${version}\" id=\"vditor-%s\"></script>"
.formatted(getUrl(path), id));
return this;
}
public ScriptBuilder innerScript(String script) {
this.script.append("<script>%s</script>".formatted(script));
return this;
}
public ScriptBuilder stylesheet(String path, String id) {
this.script.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"%s?version=${version}\" id=\"vditor-%s\" />"
.formatted(getUrl(path), id));
return this;
}
public ScriptBuilder sign(String signId) {
this.script.append("<div data-type=\"sign\" id=\"vditor-%s\"></div>".formatted(signId));
return this;
}
public ScriptBuilder variable(String varId, String varValue) {
this.script.append("<div data-type=\"var\" id=\"vditor-var-%s\" value=\"%s\"></div>"
.formatted(varId, varValue));
return this;
}
public String getScript() {
return this.script.toString();
}
private String getUrl(String url) {
if (url.startsWith("http")) {
return url;
} else {
return "/plugins/vditor-mde/assets/static/%s".formatted(url);
}
}
}

View File

@ -1,44 +1,36 @@
package top.mczhengyi.vditor.utils;
import org.pf4j.PluginWrapper;
import org.springframework.util.PropertyPlaceholderHelper;
import top.mczhengyi.vditor.bean.RenderConfig;
import java.util.Properties;
public class ScriptUtils {
static final PropertyPlaceholderHelper
PROPERTY_PLACEHOLDER_HELPER = new PropertyPlaceholderHelper("${", "}");
public static String renderScript(RenderConfig renderConfig) {
StringBuilder script = new StringBuilder();
script.append(basicScript(renderConfig));
// 如果是跟随Joe 3.0则注入脚本
if ("joe".equals(renderConfig.getDarkMode()))
script.append(joeDarkMode());
return script.toString();
ScriptBuilder script = new ScriptBuilder();
script.sign("article-sign")
.variable("cdn", renderConfig.getCdn())
.stylesheet("vditor-render.css", "style")
.script("dist/method.min.js", "methods")
.script("render-utils.js", "render-utils"); // 标记文章位置
if (renderConfig.getMediaRender())
script.script("external/media-render.js", "media");
if (!renderConfig.getDarkMode().equals("disabled")) {
script.script("dark-mode/dark-%s.js".formatted(renderConfig.getDarkMode()), "dark-mode");
}
script.script("halo-renders/index.js", "halo-render-js")
.stylesheet("halo-renders/index.css", "halo-render-css")
.script("external/halo-renders.js", "halo-render")
.script("render.js", "render"); // 完成操作后渲染
return script.getScript();
}
public static String basicScript(RenderConfig renderConfig) {
return """
<link rel="stylesheet" type="text/css" href="/plugins/vditor-mde/assets/static/dist/index.css" id="vditor-style" />
<script src="/plugins/vditor-mde/assets/static/dist/method.min.js"></script>
<script src="/plugins/vditor-mde/assets/static/render.js" id="vditor-render"
data-dark="%s" data-mediaRender="%s"></script>
""".formatted(renderConfig.getDarkMode(), renderConfig.getMediaRender());
}
public static String joeDarkMode() {
return """
<script>
window.addEventListener("load", () => {
var html = document.getElementsByTagName("html")[0]
if (!html) return
setTheme(html.dataset.mode)
var callback = (mutation) => {
if (mutation[0].attributeName=="data-mode") {
console.log("CHANGED")
var mode = mutation[0].target.dataset.mode
setTheme(mode)
}
}
var observer = new MutationObserver(callback)
observer.observe(html, {attributes:true})
})
</script>
""";
public static String setContentProperty(String script, PluginWrapper pluginWrapper) {
final Properties properties = new Properties();
properties.setProperty("version", pluginWrapper.getDescriptor().getVersion());
return PROPERTY_PLACEHOLDER_HELPER.replacePlaceholders(script, properties);
}
}

View File

@ -51,6 +51,11 @@ spec:
label: 禁用HTML代码块隐藏
help: 开启此选项后HTML代码块将会一直显示
value: false
- $formkit: checkbox
name: firstH1AsTitle
label: 🧪自动将第一行作为标题
help: 开启此选项后第一行H1将会作为文章标题同时标题会用 T 标识
value: false
- group: extension
label: 文件格式
formSchema:
@ -88,4 +93,35 @@ spec:
name: onlyMarkdown
label: "仅在Markdown模式下渲染"
help: "启用该功能将仅在Markdown格式的文章下注入渲染脚本"
value: true
value: true
- $formkit: select
id: cdn
name: cdn
label: "Vditor CDN"
help: "前台渲染所使用的 CDN 配置"
value: "/plugins/vditor-mde/assets/static"
options:
- label: "内建"
value: "/plugins/vditor-mde/assets/static"
- label: "jsDelivr(国外)"
value: "https://cdn.jsdelivr.net/npm/vditor@${v}"
- label: "unpkg(国外)"
value: "https://unpkg.com/vditor@${v}"
- label: "npmmirror(国内)"
value: "https://registry.npmmirror.com/vditor/${v}/files"
- label: "自建"
value: "self-hosted"
- $formkit: text
if: "$cdn == 'self-hosted'"
name: cdnUrl
label: CDN URL
placeholder: "在此处填入您的自建cdn(不支持 cdnjs 格式,使用${v}代替版本号)"
value: ""
- group: developer
label: 开发者设置
formSchema:
- $formkit: checkbox
name: debugger
label: "启用Debugger"
help: "启动Vditor编辑器的Debugger模式一般用于开发者使用"
value: false

View File

@ -1,22 +1,23 @@
apiVersion: plugin.halo.run/v1alpha1
kind: Plugin
metadata:
# The name defines how the plugin is invoked,A unique name
name: vditor-mde
annotations:
store.halo.run/app-id: app-uBcYw
spec:
enabled: true
requires: ">=2.11.0"
requires: ">=2.14.0"
author:
name: zhengyi59
website: https://github.com/justice2001/veditor-plugin
website: https://github.com/justice2001/halo-plugin-vditor
logo: vditor.png
# 'homepage' usually links to the GitHub repository of the plugin
homepage: https://github.com/justice2001/veditor-plugin
# 'displayName' explains what the plugin does in only a few words
homepage: https://www.halo.run/store/apps/app-uBcYw
repo: https://github.com/justice2001/halo-plugin-vditor
issues: https://github.com/justice2001/halo-plugin-vditor/issues
settingName: vditor-mde-settings
configMapName: vditor-mde-configMap
displayName: "Vditor编辑器"
description: "适用于Halo的Vditor编辑器"
displayName: "Vditor 编辑器"
description: "适用于 Halo Vditor 编辑器"
license:
- name: "GPL-3.0"
url: "https://github.com/justice2001/veditor-plugin/blob/main/LICENSE"
url: "https://github.com/justice2001/halo-plugin-vditor/blob/main/LICENSE"

View File

@ -0,0 +1,7 @@
window.addEventListener("load", () => {
console.log("Use Joe Dark Mode")
let html = document.getElementsByTagName("html")[0]
if (!html) return
const mode = html.dataset.mode
setDarkMode(mode === "dark")
})

View File

@ -0,0 +1,5 @@
window.addEventListener("load", () => {
console.log("Use System Dark Mode")
let media = window.matchMedia('(prefers-color-scheme: dark)');
setDarkMode(media.matches)
})

View File

@ -0,0 +1,8 @@
vditorRender.addExternal((conf) => {
document.querySelectorAll(".language-halo").forEach(el => {
el.outerHTML = HaloJs.renderHalo(
el.textContent,
"/plugins/vditor-mde/assets/static/halo-renders"
);
})
})

View File

@ -0,0 +1,5 @@
vditorRender.addExternal((conf) => {
console.log("Run External Function: Media Render!")
let root = document.getElementById("vditor-article-sign").parentElement;
Vditor.mediaRender(root)
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1703730875005" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7787" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M157.520435 0h708.958984C953.08055-0.058514 1023.443968 69.822161 1023.999854 156.408663v711.182527C1023.443968 954.177692 953.065921 1024.058368 866.479419 1023.999854H157.520435C70.919304 1024.058368 0.555886 954.177692 0 867.59119V156.408663C0.555886 69.822161 70.933933-0.058514 157.520435 0z" fill="#FFFFFF" p-id="7788"></path><path d="M438.008623 167.146033a227.386482 227.386482 0 0 1 237.231509 86.147645 224.372997 224.372997 0 0 1 42.964108 115.858269c1.097143 15.828112 0.6144 31.743995-1.404342 47.469708l-0.906972 2.311314c-28.671996 0.146286-57.05142 6.026971-83.426731 17.261712a226.88911 226.88911 0 0 0-64.146276 42.569136c-5.412571 6.334171-11.746741 11.849141-17.568912 17.876112-20.085026 20.085026-40.857594 40.755194-61.14742 61.235191-5.909942 5.529599-11.029941 11.746741-17.466512 16.764341A211.924084 211.924084 0 0 0 317.147383 424.755139a171.563861 171.563861 0 0 0-41.545137-5.31017l-8.045713-0.512a192.248658 192.248658 0 0 1-1.901714-32.226739 217.951055 217.951055 0 0 1 24.590625-103.292328 227.181682 227.181682 0 0 1 147.777808-116.267869z m38.85348 103.906728a116.443412 116.443412 0 0 0-101.800214 112.552213 115.653469 115.653469 0 0 0 18.168683 65.53599 116.66284 116.66284 0 1 0 83.631531-178.088203z" fill="#2C61E4" p-id="7789"></path><path d="M715.892926 418.932969L716.799898 416.621655v2.311314a211.529113 211.529113 0 0 1 92.964558 401.568857 213.942827 213.942827 0 0 1-147.880208 14.453026 210.826941 210.826941 0 0 1-84.231302-44.470851 52.809135 52.809135 0 0 1-18.066283-40.755194 53.408907 53.408907 0 0 1 67.876562-50.190621 55.120449 55.120449 0 0 1 21.679539 11.746741 104.916099 104.916099 0 1 0 11.936913-169.574376 136.235866 136.235866 0 0 0-24.795425 20.479997L423.350797 774.436461a231.80431 231.80431 0 0 1-31.817139 28.11611 211.426713 211.426713 0 0 1-105.61827 38.85348 212.523855 212.523855 0 0 1-206.204314-112.054841 211.631513 211.631513 0 0 1 111.030842-295.935958 214.235398 214.235398 0 0 1 77.311989-14.467655l8.031084 0.512c12.317255 1.609143 23.639768 7.592227 31.919538 16.852112a53.511307 53.511307 0 0 1-7.738513 78.701703 54.506049 54.506049 0 0 1-29.213253 10.649599 106.013242 106.013242 0 0 0-60.22582 16.471769 104.813699 104.813699 0 0 0 94.661473 185.929116 108.426956 108.426956 0 0 0 42.071765-30.134853c41.954737-40.959994 83.017131-82.812331 124.781696-123.874725 6.436571-5.017599 11.55657-11.234741 17.466512-16.76434 20.085026-20.070397 40.769823-40.755194 61.14742-61.235192 5.822171-6.026971 12.141713-11.55657 17.554283-17.876111a226.88911 226.88911 0 0 1 63.956105-41.954737 215.537341 215.537341 0 0 1 83.426731-17.261712z" fill="#3377F9" p-id="7790"></path><path d="M275.572989 419.444969c14.028798 0.058514 27.984453 1.8432 41.559766 5.31017a211.924084 211.924084 0 0 1 155.20912 149.884322c-41.764565 41.062394-82.82696 82.92936-124.781696 123.889353a106.422842 106.422842 0 0 0 21.67954-41.354965 104.301699 104.301699 0 0 0-6.729142-71.592218 105.515871 105.515871 0 0 0-65.448219-55.617821 111.630613 111.630613 0 0 0-26.009597-4.315428 54.506049 54.506049 0 0 0 29.110853-10.63497 53.511307 53.511307 0 0 0 7.738513-78.701703 51.799764 51.799764 0 0 0-32.329138-16.86674z" fill="#D2402C" p-id="7791"></path></svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,309 @@
.halo-render {
margin: 5px;
}
.halo-render .btn {
background-color: #3478CD;
color: #ffffff;
padding: 5px 8px;
text-align: center;
border-radius: 3px;
font-size: 14px;
min-width: 80px;
text-decoration: none;
}
.halo-render .error {
text-align: center;
color: #C31919;
}
.halo-render .invalid-type {
color: red;
font-size: 20px;
text-align: center;
padding: 10px;
background-color: lightpink;
border-radius: 3px;
}
.halo-render .iconfont {
font-family: iconfont, sans-serif;
font-size: 16px;
}
.halo-render img,
.halo-render a {
width: initial;
height: initial;
min-width: initial;
min-height: initial;
max-width: initial;
max-height: initial;
border-radius: initial;
border: initial;
margin: initial;
padding: initial;
}
.halo-render-wrapper {
margin: 20px 15px;
}
.halo-render.tips {
position: relative;
padding: 15px 15px;
border-left-style: solid;
border-left-width: 6px;
border-radius: 3px;
color: #333333;
border-left-color: #818181;
background-color: #F4F4F4;
}
.halo-render.tips.halo-render.tips:after {
font-family: "iconfont", serif !important;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
font-size: 14px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border-radius: 50%;
color: #F4F4F4;
background-color: #818181;
display: block;
position: absolute;
left: calc(-10px - 6px / 2);
top: 4px;
content: "\e77e";
}
.halo-render.tips.halo-render.tips-warn {
background-color: #FFFAED;
color: #FF8C00;
border-left-color: #FF8C00;
}
.halo-render.tips.halo-render.tips-warn.halo-render.tips.halo-render.tips-warn:after {
color: #FFFAED;
background-color: #FF8C00;
content: "\e671";
}
.halo-render.tips.halo-render.tips-danger {
background-color: #FFEDED;
color: #C31919;
border-left-color: #C31919;
}
.halo-render.tips.halo-render.tips-danger.halo-render.tips.halo-render.tips-danger:after {
background-color: #C31919;
color: #FFEDED;
content: "\e671";
}
.halo-render.tips.halo-render.tips-success {
background-color: #F2FFED;
color: #05B800;
border-left-color: #05B800;
}
.halo-render.tips.halo-render.tips-success.halo-render.tips.halo-render.tips-success:after {
background-color: #05B800;
color: #F2FFED;
}
.halo-render.tips.halo-render.tips-info {
background-color: #F1F7FF;
color: #3478CD;
border-left-color: #3478CD;
}
.halo-render.tips.halo-render.tips-info.halo-render.tips.halo-render.tips-info:after {
color: #F1F7FF;
background-color: #3478CD;
}
.halo-render.git {
display: flex;
gap: 10px;
border: 1px solid #ececec;
padding: 10px;
border-radius: 3px;
}
.halo-render.git .information {
display: flex;
flex-direction: column;
gap: 10px;
}
.halo-render.git .information .info {
font-size: 14px;
display: flex;
align-items: center;
gap: 15px;
}
.halo-render.git .information .info .topics {
position: relative;
display: flex;
gap: 5px;
color: #ffffff;
font-size: 12px;
max-width: 30%;
overflow: hidden;
transition: max-width 0.2s;
cursor: pointer;
}
.halo-render.git .information .info .topics:after {
position: absolute;
display: block;
width: 20px;
height: 30px;
right: 0;
background: linear-gradient(to right, transparent, #ffffff);
content: '';
transition: width 0.2s;
}
.halo-render.git .information .info .topics:hover:after {
width: 0;
}
.halo-render.git .information .info .topics:hover {
max-width: 70%;
}
.halo-render.git .information .info .topics .topic {
background-color: #3478CD;
padding: 3px 5px;
border-radius: 3px;
white-space: nowrap;
}
.halo-render.git .information .info .language {
display: flex;
align-items: center;
gap: 5px;
}
.halo-render.git .information .info .language .dot {
width: 14px;
height: 14px;
border-radius: 50%;
}
.halo-render.git .information .info .count {
display: flex;
align-items: center;
gap: 10px;
}
.halo-render.git .information .info .count .count-item {
display: flex;
align-items: center;
gap: 5px;
}
.halo-render.git .information .info .count .icon {
font-size: 18px;
color: #818181;
}
.halo-render.git .information .description {
font-size: 14px;
}
.halo-render.git .information .info {
font-size: 14px;
color: #999999;
}
.halo-render.git .error {
color: darkred;
text-align: center;
}
.halo-render.git .repo-name a {
font-size: 18px;
color: #3478CD;
text-decoration: none;
}
.halo-render.git .icon {
font-family: "iconfont", serif;
font-size: 24px;
color: #333333;
}
.halo-render.drive {
border: 1px solid #F4F4F4;
border-radius: 3px;
padding: 10px;
display: flex;
align-items: center;
justify-content: space-between;
user-select: none;
}
.halo-render.drive .drive-info {
display: flex;
flex-direction: column;
gap: 10px;
}
.halo-render.drive .drive-info .platform {
display: flex;
align-items: center;
}
.halo-render.drive .drive-info .platform .drive-icon {
width: 25px;
}
.halo-render.drive .drive-info .platform span {
font-size: 16px;
margin-left: 3px;
color: #3478CD;
}
.halo-render.drive .download-info {
display: flex;
flex-direction: column;
align-items: center;
}
.halo-render.drive .download-info .drive-password {
color: #818181;
font-size: 12px;
margin-top: 5px;
}
.halo-render.gallery {
border: 1px solid #F4F4F4;
border-radius: 3px;
padding: 10px 15px;
}
.halo-render.gallery .title {
display: flex;
align-items: center;
font-size: 18px;
margin-bottom: 10px;
}
.halo-render.gallery .title .iconfont {
font-size: 30px;
margin-right: 5px;
}
.halo-render.gallery .image-list {
display: flex;
width: 100%;
}
.halo-render.gallery .image-list .vditor--gallery-container .img {
border-radius: 3px !important;
}
.halo-render.gallery.halo-render.gallery.grid .image-list {
flex-wrap: wrap;
column-gap: 2%;
row-gap: 10px;
}
.halo-render.gallery.halo-render.gallery.grid .image-list .vditor--gallery-container {
width: 32%;
height: 0;
position: relative;
padding-bottom: 32%;
}
.halo-render.gallery.halo-render.gallery.grid .image-list .vditor--gallery-container .img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
@media screen and (min-width: 1400px) {
.halo-render.gallery.halo-render.gallery.grid .image-list .container {
width: 23%;
padding-bottom: 23%;
}
}
.halo-render.gallery.halo-render.gallery.linear .image-list {
display: flex;
overflow-y: hidden;
overflow-x: auto;
width: 100%;
gap: 10px;
}
.halo-render.gallery.halo-render.gallery.linear .image-list .vditor--gallery-container {
height: 300px;
}
.halo-render.gallery.halo-render.gallery.linear .image-list .vditor--gallery-container .img {
height: 99%;
width: auto!important;
max-width: unset!important;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,78 @@
(function (win) {
if (win.vditorRender) return;
const THEME_PREFIX="/plugins/vditor-mde/assets/static/themes"
const CDN = "https://cdn.jsdelivr.net/npm/vditor@3.9.9"
/** 拓展处理 ({dark}) => void */
let functionList = []
let darkMode = false
/**
* 处理渲染
* @param func
*/
function addExternal(func) {
functionList.push(func)
}
/**
* 设置暗色模式
* @param {Boolean} dark
*/
function setDarkMode(dark = false) {
darkMode = dark
}
/**
* 设置CDN
* @param {string} cdn CDN
*/
function setCDN(cdn) {
this.CDN = cdn;
}
/**
* 渲染
* @param elId 搜寻位置
*/
function vditorRender(elId="vditor-article-sign") {
Vditor.setContentTheme(darkMode?"dark":"light", THEME_PREFIX)
let root = document.getElementById(elId)
if (!root) {
console.log("[Vditor Render] Can't Found Article Root Element!");
return
}
root = root.parentElement
root.classList.add("vditor-reset")
console.log(`Using CDN: ${this.CDN}`)
// Render
const renderTheme = darkMode?"dark":"classic"
Vditor.mathRender(root, {cdn: this.CDN})
Vditor.mindmapRender(root, this.CDN, renderTheme)
Vditor.mermaidRender(root, this.CDN, renderTheme)
Vditor.chartRender(root, this.CDN, renderTheme)
Vditor.abcRender(root, this.CDN)
Vditor.graphvizRender(root, this.CDN)
Vditor.flowchartRender(root, this.CDN)
Vditor.plantumlRender(root, this.CDN)
// Run External Plugin
functionList.forEach(func => {
func({
darkMode
})
})
}
win.vditorRender = {
THEME_PREFIX,
CDN,
functionList,
darkMode,
addExternal,
setDarkMode,
vditorRender,
render: vditorRender,
setCDN
}
})(window)

View File

@ -1,73 +1,23 @@
const THEME_PREFIX="/plugins/vditor-mde/assets/static/dist/css/content-theme"
const CDN = "/plugins/vditor-mde/assets/static"
window.addEventListener("load", () => {
// 暗色模式初始化
let dark = initDarkMode()
setTheme(dark?"dark":"light")
const root = document.getElementById("vditor-render").parentElement
root.classList.add("vditor-reset")
// Render
const renderTheme = dark?"dark":"classic"
Vditor.mathRender(root, {cdn: CDN})
Vditor.mindmapRender(root, CDN, renderTheme)
Vditor.mermaidRender(root, CDN, renderTheme)
Vditor.chartRender(root, CDN, renderTheme)
Vditor.abcRender(root, CDN)
Vditor.graphvizRender(root, CDN)
Vditor.flowchartRender(root, CDN)
Vditor.haloRender(root, CDN)
// Render Media
let mediaRenderOption = document.getElementById("vditor-render").dataset.mediarender
if (mediaRenderOption==="true") {
let article = document.getElementById("vditor-render").parentElement;
Vditor.mediaRender(article)
if (!window.vditorPjax) {
window.vditorPjax = true
let cdnVar = document.getElementById("vditor-var-cdn")
let cdn = cdnVar ? cdnVar.getAttribute("value") : ""
cdn && vditorRender.setCDN(cdn)
// 当网页已经准备就绪则直接执行渲染任务
if (document.readyState === "complete") {
vditorRender.render()
} else {
window.addEventListener('load', () => vditorRender.render())
}
})
/**
* 初始化暗色模式策略
* 创建所需监听器
* @returns {boolean} 初始暗黑模式状态
*/
function initDarkMode() {
let darkModeChange = document.getElementById("vditor-render").dataset.dark
let dark = false
// 检测暗黑模式策略
switch (darkModeChange) {
// 禁用暗黑模式
case "disabled": break
// 跟随系统
case "system":
dark = initSystemDarkMode()
}
return dark
// 兼容 PJAX
$(document).on('pjax:complete', function() {
vditorRender.render()
console.log("[Vditor Render] PJAX END")
})
// 兼容 Jquery-Pjax
$(document).on('pjax:end', function() {
vditorRender.render()
console.log("[Vditor Render] PJAX END")
})
console.log("[Vditor Render] PJAX Injected")
}
/**
* 系统模式暗黑模式策略
* @returns {boolean}
*/
function initSystemDarkMode() {
let media = window.matchMedia('(prefers-color-scheme: dark)');
let callback = (e) => {
let prefersDarkMode = e.matches;
setTheme(prefersDarkMode?"dark":"light")
};
if (typeof media.addEventListener === 'function') {
media.addEventListener('change', callback);
} else if (typeof media.addListener === 'function') {
media.addListener(callback);
}
return media.matches
}
/**
* 配置主题
* @param theme 主题
*/
function setTheme(theme) {
Vditor.setContentTheme(theme, THEME_PREFIX)
}

View File

@ -0,0 +1,27 @@
/**
This is a theme for halo-plugin-vditor
Modified from vditor content_theme
*/
.vditor-reset .language-abc svg,
.vditor-reset .language-abc path {
fill: currentColor;
color: #d1d5da;
}
.language-graphviz polygon {
fill: rgba(66, 133, 244, .36);
}
.vditor-reset .iframe__video {
display: block;
margin: 0 auto !important;
min-width: 80%;
min-height: 36vh;
border: none;
}
.vditor-reset video {
display: block;
margin: 0 auto !important;
min-width: 80%;
}

View File

@ -0,0 +1,18 @@
/**
This is a theme for halo-plugin-vditor
Modified from vditor content_theme
*/
.vditor-reset .iframe__video {
display: block;
margin: 0 auto !important;
min-width: 80%;
min-height: 36vh;
border: none;
}
.vditor-reset video {
display: block;
margin: 0 auto !important;
min-width: 80%;
}

View File

@ -0,0 +1,39 @@
.vditor-reset--anchor {
padding-left: 20px;
}
.vditor-reset--error {
color: #d23f31;
font-size: 12px;
display: block;
line-height: 16px;
}
.vditor-reset .language-math,
.vditor-reset .language-echarts,
.vditor-reset .language-mindmap,
.vditor-reset .language-plantuml,
.vditor-reset .language-mermaid,
.vditor-reset .language-markmap,
.vditor-reset .language-abc,
.vditor-reset .language-flowchart,
.vditor-reset .language-graphviz {
margin-bottom: 16px;
}
.vditor-reset .language-math mjx-container:focus {
outline: none;
cursor: context-menu;
}
.vditor-reset .language-echarts,
.vditor-reset .language-mindmap {
overflow: hidden;
height: 420px;
}
.vditor-reset .language-mermaid,
.vditor-reset .language-markmap,
.vditor-reset .language-flowchart,
.vditor-reset .language-graphviz {
text-align: center;
}
.vditor-reset .language-graphviz parsererror {
overflow: auto;
}