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
This commit is contained in:
zhengyi 2024-05-10 12:56:57 +08:00
commit 1b482b5d9b
10 changed files with 117 additions and 12 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

View File

@ -1,5 +1,11 @@
# 更新记录
### v1.7.0
- ⬆️ 调整 Halo 最低兼容版本为 `2.14.0`
- ✨ 添加`使用第一个h1作为标题`的功能 #33
- 🐛 修复代码块颜色异常的问题 #38
### v1.6.2
- ⬆️ 升级Vditor版本至3.10.2

View File

@ -41,7 +41,7 @@ build {
}
halo {
version = '2.12'
version = '2.14'
superAdminUsername = 'admin'
superAdminPassword = 'admin'
externalUrl = 'http://localhost:8090'

View File

@ -2,8 +2,9 @@
<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" />
<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
@ -36,6 +37,11 @@ const props = defineProps<{
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));

View File

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

View File

@ -7,6 +7,7 @@ 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;
@ -233,11 +234,13 @@ function getCustomRenders(options: Options):
*
* TODO: 该部分建议加入Vditor
* @param vditor vditor
* @param config Editor Config
* @returns html
*/
export function renderHTML(vditor: Vditor): string {
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>`,
@ -245,5 +248,10 @@ export function renderHTML(vditor: Vditor): string {
);
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;
}

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import Vditor from "vditor";
import { onMounted, onUnmounted, ref } from "vue";
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";
@ -18,11 +18,13 @@ 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,
@ -45,17 +47,56 @@ 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 = () => {
emit("update:raw", vditor.value.getValue());
emit("update:content", renderHTML(vditor.value) || "");
emit("update", vditor.value.getValue());
//
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);
};
//
@ -124,7 +165,15 @@ onMounted(async () => {
defaultRenderMode: editorConfig.value.basic.defaultRenderMode,
typeWriterMode: editorConfig.value.basic.typeWriterMode,
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;
},
input: debounceOnUpdate,
@ -196,7 +245,10 @@ const update = (val: string | null) => {
</script>
<template>
<div id="plugin-vditor-mde">
<div
id="plugin-vditor-mde"
:class="{ h1AsTitle: editorConfig?.basic.firstH1AsTitle }"
>
<VLoading v-if="!vditorLoaded" style="height: 100%" />
<DebugPanel
v-if="debugMode"
@ -271,4 +323,30 @@ const update = (val: string | null) => {
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

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

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:

View File

@ -6,7 +6,7 @@ metadata:
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/halo-plugin-vditor