pref: add folding function to code blocks (#6177)

#### What type of PR is this?

/kind improvement
/area editor
/milestone 2.17.x

#### What this PR does / why we need it:

为默认编辑器代码块增加折叠功能。

<img width="892" alt="image" src="https://github.com/halo-dev/halo/assets/31335418/8325cba9-08ce-4bd7-98b6-6bc28fe52daf">

#### How to test it?

测试折叠功能是否可用。
测试重新打开文章之后代码块是否仍旧处于折叠状态。

#### Which issue(s) this PR fixes:

Fixes #6166

#### Does this PR introduce a user-facing change?
```release-note
为默认编辑器代码块增加折叠功能
```
pull/6185/head
Takagi 2024-06-27 17:42:54 +08:00 committed by GitHub
parent 556e65a618
commit ab14157def
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 5 deletions

View File

@ -6,6 +6,8 @@ import { NodeViewContent, NodeViewWrapper } from "@/tiptap/vue-3";
import { useTimeout } from "@vueuse/core";
import { computed } from "vue";
import BxBxsCopy from "~icons/bx/bxs-copy";
import RiArrowDownSFill from "~icons/ri/arrow-down-s-fill";
import RiArrowRightSFill from "~icons/ri/arrow-right-s-fill";
import IconCheckboxCircle from "~icons/ri/checkbox-circle-line";
import lowlight from "./lowlight";
@ -33,6 +35,15 @@ const selectedLanguage = computed({
},
});
const collapsed = computed<boolean>({
get: () => {
return props.node.attrs.collapsed || false;
},
set: (collapsed: boolean) => {
props.updateAttributes({ collapsed: collapsed });
},
});
const { ready, start } = useTimeout(2000, { controls: true, immediate: false });
const handleCopyCode = () => {
@ -44,14 +55,29 @@ const handleCopyCode = () => {
};
</script>
<template>
<node-view-wrapper as="div" class="code-node border-[1px] rounded mt-3">
<node-view-wrapper
as="div"
class="code-node border-[1px] rounded mt-3 overflow-hidden"
>
<div
class="bg-neutral-100 border-b-[1px] border-b-gray-100 py-1 flex items-center justify-between rounded-t"
contenteditable="false"
class="bg-neutral-100 border-b-[1px] border-b-gray-100 py-1 flex items-center justify-between"
>
<div class="flex-1 flex items-center pl-3">
<div
class="flex-1 flex items-center pl-3"
@click.self="collapsed ? (collapsed = false) : null"
>
<div class="pr-3 flex items-center">
<div
class="w-8 h-8 cursor-pointer rounded flex items-center justify-center hover:bg-zinc-200"
@click.stop="collapsed = !collapsed"
>
<RiArrowRightSFill v-if="collapsed" />
<RiArrowDownSFill v-else />
</div>
</div>
<select
v-model="selectedLanguage"
contenteditable="false"
class="block !leading-8 text-sm text-gray-900 border select-none border-transparent rounded-md bg-transparent focus:ring-blue-500 focus:border-blue-500 cursor-pointer hover:bg-zinc-200"
>
<option :value="null">auto</option>
@ -80,6 +106,6 @@ const handleCopyCode = () => {
</div>
</div>
</div>
<pre><node-view-content as="code" class="hljs" /></pre>
<pre v-show="!collapsed"><node-view-content as="code" class="hljs" /></pre>
</node-view-wrapper>
</template>

View File

@ -105,6 +105,25 @@ export default CodeBlockLowlight.extend<
// otherwise the Mod-a shortcut key will be overridden.
priority: 110,
fakeSelection: true,
addAttributes() {
return {
...this.parent?.(),
collapsed: {
default: false,
parseHTML: (element) => !!element.getAttribute("collapsed"),
renderHTML: (attributes) => {
if (attributes.collapsed) {
return {
collapsed: attributes.collapsed,
};
}
return {};
},
},
};
},
addCommands() {
return {
...this.parent?.(),