Merge pull request 'v1.7.0 Releases' (PR#81) from dev into main
Reviewed-on: #81
This commit is contained in:
commit
1b482b5d9b
|
@ -64,7 +64,7 @@ jobs:
|
||||||
name: plugin-starter
|
name: plugin-starter
|
||||||
path: |
|
path: |
|
||||||
build/libs/*.jar
|
build/libs/*.jar
|
||||||
retention-days: 1
|
retention-days: 90
|
||||||
|
|
||||||
github-release:
|
github-release:
|
||||||
runs-on: debian-12
|
runs-on: debian-12
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
# 更新记录
|
# 更新记录
|
||||||
|
|
||||||
|
### v1.7.0
|
||||||
|
|
||||||
|
- ⬆️ 调整 Halo 最低兼容版本为 `2.14.0`
|
||||||
|
- ✨ 添加`使用第一个h1作为标题`的功能 #33
|
||||||
|
- 🐛 修复代码块颜色异常的问题 #38
|
||||||
|
|
||||||
### v1.6.2
|
### v1.6.2
|
||||||
|
|
||||||
- ⬆️ 升级Vditor版本至3.10.2
|
- ⬆️ 升级Vditor版本至3.10.2
|
||||||
|
|
|
@ -41,7 +41,7 @@ build {
|
||||||
}
|
}
|
||||||
|
|
||||||
halo {
|
halo {
|
||||||
version = '2.12'
|
version = '2.14'
|
||||||
superAdminUsername = 'admin'
|
superAdminUsername = 'admin'
|
||||||
superAdminPassword = 'admin'
|
superAdminPassword = 'admin'
|
||||||
externalUrl = 'http://localhost:8090'
|
externalUrl = 'http://localhost:8090'
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
<div id="vditor-debug-panel">
|
<div id="vditor-debug-panel">
|
||||||
<div id="vditor-debug-op" :class="{ active: debugOpOpen }">
|
<div id="vditor-debug-op" :class="{ active: debugOpOpen }">
|
||||||
<div id="vditor-debug-op-bar" @click="debugOpOpen = !debugOpOpen">
|
<div id="vditor-debug-op-bar" @click="debugOpOpen = !debugOpOpen">
|
||||||
<img src="../assets/debug.svg" />
|
<img src="../assets/debug.svg" alt="DEBUG"/>
|
||||||
</div>
|
</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="getHTML">Get HTML</VButton>
|
||||||
<VButton type="primary" size="sm" @click="getRenderList">
|
<VButton type="primary" size="sm" @click="getRenderList">
|
||||||
Get Vditor Options
|
Get Vditor Options
|
||||||
|
@ -36,6 +37,11 @@ const props = defineProps<{
|
||||||
cursor: Range | undefined;
|
cursor: Range | undefined;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const getRaw = () => {
|
||||||
|
if (!props.vditor) return;
|
||||||
|
console.log("RAW: ", props.vditor?.getValue());
|
||||||
|
};
|
||||||
|
|
||||||
const getHTML = () => {
|
const getHTML = () => {
|
||||||
if (!props.vditor) return;
|
if (!props.vditor) return;
|
||||||
console.log("HTML", renderHTML(props.vditor));
|
console.log("HTML", renderHTML(props.vditor));
|
||||||
|
|
|
@ -7,6 +7,7 @@ export declare type EditorConfig = {
|
||||||
enableQuickInsert: boolean;
|
enableQuickInsert: boolean;
|
||||||
quickInsertUrl: [];
|
quickInsertUrl: [];
|
||||||
disableHTMLBlockPreview: boolean;
|
disableHTMLBlockPreview: boolean;
|
||||||
|
firstH1AsTitle: boolean;
|
||||||
};
|
};
|
||||||
extension: {
|
extension: {
|
||||||
allowImageType: string;
|
allowImageType: string;
|
||||||
|
@ -25,6 +26,7 @@ export const defaultEditorConfig: EditorConfig = {
|
||||||
enableQuickInsert: false,
|
enableQuickInsert: false,
|
||||||
quickInsertUrl: [],
|
quickInsertUrl: [],
|
||||||
disableHTMLBlockPreview: false,
|
disableHTMLBlockPreview: false,
|
||||||
|
firstH1AsTitle: false,
|
||||||
},
|
},
|
||||||
extension: {
|
extension: {
|
||||||
allowImageType: "png,jpg,jpeg,bmp,gif,webp,svg",
|
allowImageType: "png,jpg,jpeg,bmp,gif,webp,svg",
|
||||||
|
|
|
@ -7,6 +7,7 @@ import drive from "@/schema/drive";
|
||||||
import gallery from "@/schema/gallery";
|
import gallery from "@/schema/gallery";
|
||||||
import { addScript, addStyleSheet } from "@/utils/dom-utils";
|
import { addScript, addStyleSheet } from "@/utils/dom-utils";
|
||||||
import type Vditor from "vditor";
|
import type Vditor from "vditor";
|
||||||
|
import type {EditorConfig} from "@/utils/config-utils";
|
||||||
|
|
||||||
declare const HaloJs: {
|
declare const HaloJs: {
|
||||||
renderHalo: (content: string, cdn: string) => string;
|
renderHalo: (content: string, cdn: string) => string;
|
||||||
|
@ -233,11 +234,13 @@ function getCustomRenders(options: Options):
|
||||||
* 进行自定义渲染器的后处理
|
* 进行自定义渲染器的后处理
|
||||||
* TODO: 该部分建议加入Vditor
|
* TODO: 该部分建议加入Vditor
|
||||||
* @param vditor vditor
|
* @param vditor vditor
|
||||||
|
* @param config Editor Config
|
||||||
* @returns html
|
* @returns html
|
||||||
*/
|
*/
|
||||||
export function renderHTML(vditor: Vditor): string {
|
export function renderHTML(vditor: Vditor, config: EditorConfig): string {
|
||||||
let value = vditor.getHTML();
|
let value = vditor.getHTML();
|
||||||
const customRenders = vditor.vditor.options.customRenders;
|
const customRenders = vditor.vditor.options.customRenders;
|
||||||
|
// FIXME 此部分逻辑有大问题!
|
||||||
customRenders?.forEach((render) => {
|
customRenders?.forEach((render) => {
|
||||||
const reg = new RegExp(
|
const reg = new RegExp(
|
||||||
`<pre><code class="language-${render.language}">(.*?)</code></pre>`,
|
`<pre><code class="language-${render.language}">(.*?)</code></pre>`,
|
||||||
|
@ -245,5 +248,10 @@ export function renderHTML(vditor: Vditor): string {
|
||||||
);
|
);
|
||||||
value = value.replace(reg, '<div class="language-halo">$1</div>');
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Vditor from "vditor";
|
import Vditor from "vditor";
|
||||||
import { onMounted, onUnmounted, ref } from "vue";
|
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||||
import "vditor/dist/index.css";
|
import "vditor/dist/index.css";
|
||||||
import type { Schema } from "@/type/editor";
|
import type { Schema } from "@/type/editor";
|
||||||
import { getOptions, renderHTML } from "@/utils/vditor-utils";
|
import { getOptions, renderHTML } from "@/utils/vditor-utils";
|
||||||
|
@ -18,11 +18,13 @@ import DebugPanel from "@/model/DebugPanel.vue";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
title?: string;
|
||||||
raw?: string;
|
raw?: string;
|
||||||
content: string;
|
content: string;
|
||||||
uploadImage?: (file: File) => Promise<Attachment>;
|
uploadImage?: (file: File) => Promise<Attachment>;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
|
title: "",
|
||||||
raw: "",
|
raw: "",
|
||||||
content: "",
|
content: "",
|
||||||
uploadImage: undefined,
|
uploadImage: undefined,
|
||||||
|
@ -45,17 +47,56 @@ const imageUploadLock = false;
|
||||||
let allowImageUpload: string[] = [];
|
let allowImageUpload: string[] = [];
|
||||||
// Debug
|
// Debug
|
||||||
const debugMode = ref<boolean>(false);
|
const debugMode = ref<boolean>(false);
|
||||||
|
// 防止内部标题更新触发updateContent
|
||||||
|
const internalTitle = ref<string>("");
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: "update:raw", value: string): void;
|
(event: "update:raw", value: string): void;
|
||||||
(event: "update:content", value: string): void;
|
(event: "update:content", value: string): void;
|
||||||
(event: "update", 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 = () => {
|
const debounceOnUpdate = () => {
|
||||||
emit("update:raw", vditor.value.getValue());
|
// 解析标题
|
||||||
emit("update:content", renderHTML(vditor.value) || "");
|
let value = vditor.value.getValue();
|
||||||
emit("update", 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 选取附件后处理
|
// 选取附件后处理
|
||||||
|
@ -124,7 +165,15 @@ onMounted(async () => {
|
||||||
defaultRenderMode: editorConfig.value.basic.defaultRenderMode,
|
defaultRenderMode: editorConfig.value.basic.defaultRenderMode,
|
||||||
typeWriterMode: editorConfig.value.basic.typeWriterMode,
|
typeWriterMode: editorConfig.value.basic.typeWriterMode,
|
||||||
after: () => {
|
after: () => {
|
||||||
vditor.value.setValue(props.raw || "# Title Here");
|
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;
|
vditorLoaded.value = true;
|
||||||
},
|
},
|
||||||
input: debounceOnUpdate,
|
input: debounceOnUpdate,
|
||||||
|
@ -196,7 +245,10 @@ const update = (val: string | null) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="plugin-vditor-mde">
|
<div
|
||||||
|
id="plugin-vditor-mde"
|
||||||
|
:class="{ h1AsTitle: editorConfig?.basic.firstH1AsTitle }"
|
||||||
|
>
|
||||||
<VLoading v-if="!vditorLoaded" style="height: 100%" />
|
<VLoading v-if="!vditorLoaded" style="height: 100%" />
|
||||||
<DebugPanel
|
<DebugPanel
|
||||||
v-if="debugMode"
|
v-if="debugMode"
|
||||||
|
@ -271,4 +323,30 @@ const update = (val: string | null) => {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 8px 10px;
|
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>
|
</style>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
version=1.6.2-SNAPSHOT
|
version=1.6.3-SNAPSHOT
|
||||||
|
|
|
@ -51,6 +51,11 @@ spec:
|
||||||
label: 禁用HTML代码块隐藏
|
label: 禁用HTML代码块隐藏
|
||||||
help: 开启此选项后,HTML代码块将会一直显示
|
help: 开启此选项后,HTML代码块将会一直显示
|
||||||
value: false
|
value: false
|
||||||
|
- $formkit: checkbox
|
||||||
|
name: firstH1AsTitle
|
||||||
|
label: 🧪自动将第一行作为标题
|
||||||
|
help: 开启此选项后,第一行H1将会作为文章标题,同时标题会用 T 标识
|
||||||
|
value: false
|
||||||
- group: extension
|
- group: extension
|
||||||
label: 文件格式
|
label: 文件格式
|
||||||
formSchema:
|
formSchema:
|
||||||
|
|
|
@ -6,7 +6,7 @@ metadata:
|
||||||
store.halo.run/app-id: app-uBcYw
|
store.halo.run/app-id: app-uBcYw
|
||||||
spec:
|
spec:
|
||||||
enabled: true
|
enabled: true
|
||||||
requires: ">=2.11.0"
|
requires: ">=2.14.0"
|
||||||
author:
|
author:
|
||||||
name: zhengyi59
|
name: zhengyi59
|
||||||
website: https://github.com/justice2001/halo-plugin-vditor
|
website: https://github.com/justice2001/halo-plugin-vditor
|
||||||
|
|
Loading…
Reference in New Issue