mirror of
https://github.com/imdap/ruoyi-plus-vben5.git
synced 2026-04-23 00:38:34 +08:00
feat(@vben/plugins): add tiptap rich text editor
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
export {
|
||||
TextAlignCenter as AlignCenter,
|
||||
TextAlignStart as AlignLeft,
|
||||
TextAlignEnd as AlignRight,
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
ArrowLeftToLine,
|
||||
@@ -7,6 +10,7 @@ export {
|
||||
ArrowUp,
|
||||
ArrowUpToLine,
|
||||
Bell,
|
||||
Bold,
|
||||
BookOpenText,
|
||||
Check,
|
||||
ChevronDown,
|
||||
@@ -22,6 +26,7 @@ export {
|
||||
Copy,
|
||||
CornerDownLeft,
|
||||
Ellipsis,
|
||||
Eraser,
|
||||
Expand,
|
||||
ExternalLink,
|
||||
Eye,
|
||||
@@ -32,12 +37,20 @@ export {
|
||||
Grid,
|
||||
Grip,
|
||||
GripVertical,
|
||||
Heading1,
|
||||
Heading2,
|
||||
Highlighter,
|
||||
Menu as IconDefault,
|
||||
ImagePlus,
|
||||
Inbox,
|
||||
Info,
|
||||
InspectionPanel,
|
||||
Italic,
|
||||
Languages,
|
||||
LayoutGrid,
|
||||
Link2,
|
||||
List,
|
||||
ListOrdered,
|
||||
LoaderCircle,
|
||||
LockKeyhole,
|
||||
LogOut,
|
||||
@@ -46,15 +59,19 @@ export {
|
||||
ArrowRightFromLine as MdiMenuClose,
|
||||
ArrowLeftFromLine as MdiMenuOpen,
|
||||
Menu,
|
||||
MessageSquareCode,
|
||||
Minimize,
|
||||
Minimize2,
|
||||
MoonStar,
|
||||
Paintbrush,
|
||||
Palette,
|
||||
PanelLeft,
|
||||
PanelRight,
|
||||
Pin,
|
||||
PinOff,
|
||||
Plus,
|
||||
Redo2,
|
||||
RemoveFormatting,
|
||||
RotateCw,
|
||||
Search,
|
||||
SearchX,
|
||||
@@ -62,10 +79,16 @@ export {
|
||||
Shrink,
|
||||
Square,
|
||||
SquareCheckBig,
|
||||
SquareCode,
|
||||
SquareMinus,
|
||||
Strikethrough,
|
||||
Sun,
|
||||
SunMoon,
|
||||
SwatchBook,
|
||||
TextQuote,
|
||||
Underline,
|
||||
Undo2,
|
||||
Unlink2,
|
||||
UserRoundPen,
|
||||
X,
|
||||
} from 'lucide-vue-next';
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
"types": "./src/echarts/index.ts",
|
||||
"default": "./src/echarts/index.ts"
|
||||
},
|
||||
"./tiptap": {
|
||||
"types": "./src/tiptap/index.ts",
|
||||
"default": "./src/tiptap/index.ts"
|
||||
},
|
||||
"./vxe-table": {
|
||||
"types": "./src/vxe-table/index.ts",
|
||||
"default": "./src/vxe-table/index.ts"
|
||||
@@ -32,8 +36,20 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@tiptap/core": "catalog:",
|
||||
"@tiptap/extension-doc": "catalog:",
|
||||
"@tiptap/extension-highlight": "catalog:",
|
||||
"@tiptap/extension-image": "catalog:",
|
||||
"@tiptap/extension-link": "catalog:",
|
||||
"@tiptap/extension-placeholder": "catalog:",
|
||||
"@tiptap/extension-text-align": "catalog:",
|
||||
"@tiptap/extension-text-style": "catalog:",
|
||||
"@tiptap/extension-underline": "catalog:",
|
||||
"@tiptap/starter-kit": "catalog:",
|
||||
"@tiptap/vue-3": "catalog:",
|
||||
"@vben-core/design": "workspace:*",
|
||||
"@vben-core/form-ui": "workspace:*",
|
||||
"@vben-core/popup-ui": "workspace:*",
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben-core/shared": "workspace:*",
|
||||
"@vben/hooks": "workspace:*",
|
||||
|
||||
55
packages/effects/plugins/src/tiptap/extensions.ts
Normal file
55
packages/effects/plugins/src/tiptap/extensions.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import type { Extensions } from '@tiptap/vue-3';
|
||||
|
||||
import type { VbenTiptapExtensionOptions } from './types';
|
||||
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import Document from '@tiptap/extension-doc';
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import Image from '@tiptap/extension-image';
|
||||
import Link from '@tiptap/extension-link';
|
||||
import Placeholder from '@tiptap/extension-placeholder';
|
||||
import TextAlign from '@tiptap/extension-text-align';
|
||||
import { Color, TextStyle } from '@tiptap/extension-text-style';
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
|
||||
export function createDefaultTiptapExtensions(
|
||||
options: VbenTiptapExtensionOptions = {},
|
||||
): Extensions {
|
||||
return [
|
||||
Document,
|
||||
StarterKit.configure({
|
||||
heading: {
|
||||
levels: [1, 2, 3, 4],
|
||||
},
|
||||
}),
|
||||
Underline,
|
||||
TextAlign.configure({
|
||||
types: ['heading', 'paragraph'],
|
||||
}),
|
||||
TextStyle,
|
||||
Color.configure({
|
||||
types: ['textStyle'],
|
||||
}),
|
||||
Highlight.configure({
|
||||
multicolor: true,
|
||||
}),
|
||||
Link.configure({
|
||||
autolink: true,
|
||||
defaultProtocol: 'https',
|
||||
enableClickSelection: true,
|
||||
openOnClick: false,
|
||||
protocols: ['mailto', { optionalSlashes: true, scheme: 'tel' }],
|
||||
}),
|
||||
Image.configure({
|
||||
allowBase64: true,
|
||||
HTMLAttributes: {
|
||||
class: 'vben-tiptap__image',
|
||||
},
|
||||
}),
|
||||
Placeholder.configure({
|
||||
placeholder: options.placeholder ?? $t('ui.tiptap.placeholder'),
|
||||
}),
|
||||
];
|
||||
}
|
||||
4
packages/effects/plugins/src/tiptap/index.ts
Normal file
4
packages/effects/plugins/src/tiptap/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { default as VbenTiptapPreview } from './preview.vue';
|
||||
export { default as VbenTiptap } from './tiptap.vue';
|
||||
|
||||
export * from './types';
|
||||
33
packages/effects/plugins/src/tiptap/preview.vue
Normal file
33
packages/effects/plugins/src/tiptap/preview.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import type { TipTapPreviewProps } from './types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import './style.css';
|
||||
const props = withDefaults(defineProps<TipTapPreviewProps>(), {
|
||||
content: '',
|
||||
minHeight: 160,
|
||||
});
|
||||
const contentMinHeight = computed(() =>
|
||||
typeof props.minHeight === 'number'
|
||||
? `${props.minHeight}px`
|
||||
: props.minHeight,
|
||||
);
|
||||
const previewClass = computed(() =>
|
||||
cn(
|
||||
'vben-tiptap-content bg-transparent p-0 leading-7 text-foreground',
|
||||
props.class,
|
||||
),
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div
|
||||
:class="previewClass"
|
||||
:style="{ minHeight: contentMinHeight }"
|
||||
v-html="content"
|
||||
></div>
|
||||
</template>
|
||||
56
packages/effects/plugins/src/tiptap/style.css
Normal file
56
packages/effects/plugins/src/tiptap/style.css
Normal file
@@ -0,0 +1,56 @@
|
||||
@reference "@vben/tailwind-config/theme";
|
||||
|
||||
.vben-tiptap-content > * + * {
|
||||
@apply mt-3;
|
||||
}
|
||||
|
||||
.vben-tiptap-content h1 {
|
||||
@apply text-2xl font-bold leading-[1.4];
|
||||
}
|
||||
|
||||
.vben-tiptap-content h2 {
|
||||
@apply text-xl font-bold leading-[1.45];
|
||||
}
|
||||
|
||||
.vben-tiptap-content h3 {
|
||||
@apply text-lg font-semibold leading-[1.5];
|
||||
}
|
||||
|
||||
.vben-tiptap-content h4 {
|
||||
@apply text-base font-semibold leading-[1.55];
|
||||
}
|
||||
|
||||
.vben-tiptap-content ul {
|
||||
@apply list-disc pl-6;
|
||||
}
|
||||
|
||||
.vben-tiptap-content ol {
|
||||
@apply list-decimal pl-6;
|
||||
}
|
||||
|
||||
.vben-tiptap-content blockquote {
|
||||
@apply border-l-4 border-primary pl-4 text-muted-foreground;
|
||||
}
|
||||
|
||||
.vben-tiptap-content a {
|
||||
@apply text-primary underline decoration-1 underline-offset-[3px];
|
||||
}
|
||||
|
||||
.vben-tiptap-content code {
|
||||
@apply rounded-[0.45rem] border border-border bg-secondary px-[0.35rem] py-[0.15rem] text-[0.9em] text-primary;
|
||||
}
|
||||
|
||||
.vben-tiptap-content pre {
|
||||
@apply overflow-x-auto rounded-[0.9rem] border border-border bg-popover p-4 text-popover-foreground;
|
||||
}
|
||||
|
||||
.vben-tiptap-content pre code {
|
||||
@apply border-none bg-transparent p-0 text-inherit;
|
||||
}
|
||||
|
||||
.vben-tiptap-content img,
|
||||
.vben-tiptap-content .vben-tiptap__image {
|
||||
@apply my-4 block h-auto rounded-2xl border border-border;
|
||||
|
||||
max-width: min(100%, 640px);
|
||||
}
|
||||
285
packages/effects/plugins/src/tiptap/tiptap.vue
Normal file
285
packages/effects/plugins/src/tiptap/tiptap.vue
Normal file
@@ -0,0 +1,285 @@
|
||||
<script setup lang="ts">
|
||||
import type {
|
||||
TipTapProps,
|
||||
ToolbarAction,
|
||||
VbenTiptapChangeEvent,
|
||||
} from './types';
|
||||
|
||||
import { computed, onBeforeUnmount, watch } from 'vue';
|
||||
|
||||
import { Check, ChevronDown, Eye } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { useVbenModal } from '@vben-core/popup-ui';
|
||||
import { VbenIconButton, VbenPopover } from '@vben-core/shadcn-ui';
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { EditorContent, useEditor } from '@tiptap/vue-3';
|
||||
|
||||
import { createDefaultTiptapExtensions } from './extensions';
|
||||
import Preview from './preview.vue';
|
||||
import { createToolbarGroups } from './toolbar';
|
||||
import { useTiptapToolbar } from './use-tiptap-toolbar';
|
||||
|
||||
import './style.css';
|
||||
const props = withDefaults(defineProps<TipTapProps>(), {
|
||||
editable: true,
|
||||
extensions: undefined,
|
||||
minHeight: 240,
|
||||
placeholder: $t('ui.tiptap.placeholder'),
|
||||
previewable: true,
|
||||
toolbar: true,
|
||||
});
|
||||
const emit = defineEmits<{
|
||||
change: [payload: VbenTiptapChangeEvent];
|
||||
}>();
|
||||
const modelValue = defineModel<string>({ default: '' });
|
||||
const contentMinHeight = computed(() =>
|
||||
typeof props.minHeight === 'number'
|
||||
? `${props.minHeight}px`
|
||||
: props.minHeight,
|
||||
);
|
||||
const tiptapContentClass = cn(
|
||||
'vben-tiptap-content vben-tiptap__content',
|
||||
'min-h-(--vben-tiptap-min-height) leading-7 text-foreground outline-none',
|
||||
);
|
||||
const editor = useEditor({
|
||||
content: modelValue.value,
|
||||
editable: props.editable,
|
||||
editorProps: {
|
||||
attributes: {
|
||||
class: tiptapContentClass,
|
||||
},
|
||||
},
|
||||
extensions:
|
||||
props.extensions ??
|
||||
createDefaultTiptapExtensions({
|
||||
placeholder: props.placeholder,
|
||||
}),
|
||||
onUpdate: ({ editor }) => {
|
||||
const html = editor.getHTML();
|
||||
if (html !== modelValue.value) {
|
||||
modelValue.value = html;
|
||||
}
|
||||
emit('change', {
|
||||
html,
|
||||
json: editor.getJSON(),
|
||||
text: editor.getText(),
|
||||
});
|
||||
},
|
||||
});
|
||||
const toolbarGroups = computed<ToolbarAction[][]>(() => {
|
||||
return createToolbarGroups();
|
||||
});
|
||||
const previewContent = computed(
|
||||
() => editor.value?.getHTML() ?? modelValue.value,
|
||||
);
|
||||
const [PreviewModal, previewModalApi] = useVbenModal({
|
||||
footer: false,
|
||||
fullscreenButton: false,
|
||||
});
|
||||
const {
|
||||
applyPaletteColor,
|
||||
canRunAction,
|
||||
canRunMenuItem,
|
||||
clearPaletteColor,
|
||||
getActionIndicatorColor,
|
||||
getMenuItemClass,
|
||||
getPaletteCurrentColor,
|
||||
getPaletteSwatchClass,
|
||||
getToolbarButtonClass,
|
||||
isMenuItemActive,
|
||||
runAction,
|
||||
runMenuItem,
|
||||
} = useTiptapToolbar({
|
||||
editable: () => props.editable,
|
||||
editor,
|
||||
});
|
||||
function openPreviewModal() {
|
||||
previewModalApi.open();
|
||||
}
|
||||
watch(
|
||||
() => props.editable,
|
||||
(editable) => {
|
||||
editor.value?.setEditable(editable);
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => modelValue.value,
|
||||
(nextValue = '') => {
|
||||
if (!editor.value) {
|
||||
return;
|
||||
}
|
||||
const currentValue = editor.value.getHTML();
|
||||
if (nextValue === currentValue) {
|
||||
return;
|
||||
}
|
||||
editor.value.commands.setContent(nextValue, {
|
||||
emitUpdate: false,
|
||||
});
|
||||
},
|
||||
);
|
||||
onBeforeUnmount(() => {
|
||||
editor.value?.destroy();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:style="{ '--vben-tiptap-min-height': contentMinHeight }"
|
||||
class="vben-tiptap overflow-hidden rounded-xl border border-border bg-card"
|
||||
>
|
||||
<div
|
||||
v-if="toolbar"
|
||||
class="sticky top-0 z-10 flex flex-wrap items-center gap-2 border-b border-border p-2 backdrop-blur-[14px]"
|
||||
>
|
||||
<div
|
||||
v-for="(group, groupIndex) in toolbarGroups"
|
||||
:key="groupIndex"
|
||||
class="flex items-center gap-1"
|
||||
>
|
||||
<template v-for="action in group" :key="action.label">
|
||||
<VbenPopover
|
||||
v-if="action.menu || action.palette"
|
||||
:content-props="{ align: 'start', side: 'bottom', sideOffset: 8 }"
|
||||
content-class="w-auto p-2"
|
||||
>
|
||||
<template #trigger>
|
||||
<VbenIconButton
|
||||
:aria-label="action.label"
|
||||
:class="getToolbarButtonClass(action)"
|
||||
:disabled="!canRunAction(action)"
|
||||
:tooltip="action.label"
|
||||
tooltip-side="top"
|
||||
variant="ghost"
|
||||
>
|
||||
<template v-if="action.triggerText">
|
||||
<span class="text-xs font-semibold tracking-wide">
|
||||
{{
|
||||
typeof action.triggerText === 'function'
|
||||
? action.triggerText(editor)
|
||||
: action.triggerText
|
||||
}}
|
||||
</span>
|
||||
<ChevronDown class="size-4 opacity-70" />
|
||||
</template>
|
||||
<component
|
||||
v-else-if="action.icon"
|
||||
:is="action.icon"
|
||||
class="size-4"
|
||||
/>
|
||||
<span
|
||||
v-if="getActionIndicatorColor(action)"
|
||||
:style="{ backgroundColor: getActionIndicatorColor(action) }"
|
||||
class="absolute bottom-1 left-1/2 h-1 w-4 -translate-x-1/2 rounded-full shadow-[0_0_0_1px_hsl(var(--card)/0.7)]"
|
||||
></span>
|
||||
</VbenIconButton>
|
||||
</template>
|
||||
<div
|
||||
v-if="action.palette"
|
||||
class="flex max-w-52 flex-wrap items-center gap-2"
|
||||
>
|
||||
<button
|
||||
v-for="color in action.palette.colors"
|
||||
:key="color"
|
||||
:aria-label="`${action.label}-${color}`"
|
||||
:class="getPaletteSwatchClass(action, color)"
|
||||
:style="{ backgroundColor: color }"
|
||||
type="button"
|
||||
@click="applyPaletteColor(action, color)"
|
||||
>
|
||||
<Check
|
||||
v-if="getPaletteCurrentColor(action) === color"
|
||||
class="size-4 text-white drop-shadow-sm"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
v-if="action.palette.clear"
|
||||
class="h-8 w-full rounded-xl border border-border bg-secondary text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
|
||||
type="button"
|
||||
@click="clearPaletteColor(action)"
|
||||
>
|
||||
{{ $t('ui.tiptap.toolbar.clear') }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else-if="action.menu" class="flex min-w-32 flex-col gap-1">
|
||||
<button
|
||||
v-for="item in action.menu.items"
|
||||
:key="item.shortLabel"
|
||||
:class="getMenuItemClass(item)"
|
||||
:disabled="!canRunMenuItem(item)"
|
||||
type="button"
|
||||
@click="runMenuItem(item)"
|
||||
>
|
||||
<span class="w-7 text-xs font-semibold tracking-wide">
|
||||
{{ item.shortLabel }}
|
||||
</span>
|
||||
<span class="flex-1">{{ item.label }}</span>
|
||||
<Check
|
||||
v-if="isMenuItemActive(item)"
|
||||
class="size-4 text-primary"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</VbenPopover>
|
||||
<VbenIconButton
|
||||
v-else
|
||||
:aria-label="action.label"
|
||||
:class="getToolbarButtonClass(action)"
|
||||
:disabled="!canRunAction(action)"
|
||||
:tooltip="action.label"
|
||||
tooltip-side="top"
|
||||
@click="runAction(action)"
|
||||
>
|
||||
<component :is="action.icon" class="size-4" />
|
||||
<span
|
||||
v-if="getActionIndicatorColor(action)"
|
||||
:style="{ backgroundColor: getActionIndicatorColor(action) }"
|
||||
class="absolute bottom-1 left-1/2 h-1 w-4 -translate-x-1/2 rounded-full shadow-[0_0_0_1px_hsl(var(--card)/0.7)]"
|
||||
></span>
|
||||
</VbenIconButton>
|
||||
</template>
|
||||
<div
|
||||
v-if="groupIndex < toolbarGroups.length - 1"
|
||||
class="ml-1 h-5 w-px bg-border"
|
||||
></div>
|
||||
</div>
|
||||
<div v-if="previewable" class="ml-auto flex items-center">
|
||||
<VbenIconButton
|
||||
:aria-label="$t('ui.tiptap.toolbar.preview')"
|
||||
:class="
|
||||
getToolbarButtonClass({
|
||||
action: () => {},
|
||||
label: $t('ui.tiptap.toolbar.preview'),
|
||||
})
|
||||
"
|
||||
:tooltip="$t('ui.tiptap.toolbar.preview')"
|
||||
tooltip-side="top"
|
||||
variant="ghost"
|
||||
@click="openPreviewModal"
|
||||
>
|
||||
<Eye class="size-4" />
|
||||
</VbenIconButton>
|
||||
</div>
|
||||
</div>
|
||||
<EditorContent v-if="editor" :editor="editor" class="p-4" />
|
||||
<PreviewModal
|
||||
v-if="previewable"
|
||||
:title="$t('ui.tiptap.toolbar.preview')"
|
||||
class="w-4/5"
|
||||
>
|
||||
<Preview :content="previewContent" :min-height="320" />
|
||||
</PreviewModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.vben-tiptap
|
||||
:deep(.vben-tiptap__content p.is-editor-empty:first-child::before) {
|
||||
float: left;
|
||||
height: 0;
|
||||
color: hsl(var(--input-placeholder));
|
||||
pointer-events: none;
|
||||
content: attr(data-placeholder);
|
||||
}
|
||||
</style>
|
||||
345
packages/effects/plugins/src/tiptap/toolbar.ts
Normal file
345
packages/effects/plugins/src/tiptap/toolbar.ts
Normal file
@@ -0,0 +1,345 @@
|
||||
import type { Editor } from '@tiptap/vue-3';
|
||||
|
||||
import type { ToolbarAction, ToolbarMenuItem } from './types';
|
||||
|
||||
import {
|
||||
AlignCenter,
|
||||
AlignLeft,
|
||||
AlignRight,
|
||||
Bold,
|
||||
Highlighter,
|
||||
ImagePlus,
|
||||
Italic,
|
||||
Link2,
|
||||
List,
|
||||
ListOrdered,
|
||||
MessageSquareCode,
|
||||
Paintbrush,
|
||||
Redo2,
|
||||
RemoveFormatting,
|
||||
SquareCode,
|
||||
Strikethrough,
|
||||
TextQuote,
|
||||
Underline,
|
||||
Undo2,
|
||||
Unlink2,
|
||||
} from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { COLOR_PRESETS } from '@vben/preferences';
|
||||
|
||||
import { prompt } from '@vben-core/popup-ui';
|
||||
|
||||
const headingLevels = [1, 2, 3, 4] as const;
|
||||
const editorColorPresets = [
|
||||
'hsl(var(--foreground))',
|
||||
'hsl(var(--warning))',
|
||||
'hsl(var(--success))',
|
||||
'hsl(var(--destructive))',
|
||||
...COLOR_PRESETS.map((item) => item.color),
|
||||
];
|
||||
const editorHighlightPresets = [
|
||||
withAlpha('hsl(var(--warning))', 0.45),
|
||||
withAlpha('hsl(var(--success))', 0.35),
|
||||
withAlpha('hsl(var(--primary))', 0.3),
|
||||
withAlpha('hsl(var(--destructive))', 0.3),
|
||||
...COLOR_PRESETS.map((item) => withAlpha(item.color, 0.4)),
|
||||
];
|
||||
|
||||
function createHeadingMenuItems(): ToolbarMenuItem[] {
|
||||
return [
|
||||
{
|
||||
action: (editor) => editor.chain().focus().setParagraph().run(),
|
||||
can: (editor) => editor.can().chain().focus().setParagraph().run(),
|
||||
isActive: (editor) => editor.isActive('paragraph'),
|
||||
label: $t('ui.tiptap.toolbar.paragraph'),
|
||||
shortLabel: 'P',
|
||||
},
|
||||
...headingLevels.map((level) => ({
|
||||
action: (editor: Editor) =>
|
||||
editor.chain().focus().toggleHeading({ level }).run(),
|
||||
can: (editor: Editor) =>
|
||||
editor.can().chain().focus().toggleHeading({ level }).run(),
|
||||
isActive: (editor: Editor) => editor.isActive('heading', { level }),
|
||||
label: $t(`ui.tiptap.toolbar.heading${level}`),
|
||||
shortLabel: `H${level}`,
|
||||
})),
|
||||
];
|
||||
}
|
||||
|
||||
function getHeadingTriggerText(editor?: Editor) {
|
||||
if (editor?.isActive('paragraph')) {
|
||||
return 'P';
|
||||
}
|
||||
|
||||
const level = headingLevels.find((headingLevel) =>
|
||||
editor?.isActive('heading', { level: headingLevel }),
|
||||
);
|
||||
|
||||
return level ? `H${level}` : 'H';
|
||||
}
|
||||
|
||||
function normalizeLinkUrl(url: string) {
|
||||
if (/^(https?:|mailto:|tel:)/i.test(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return `https://${url}`;
|
||||
}
|
||||
|
||||
function withAlpha(color: string, alpha: number) {
|
||||
const normalizedAlpha = Math.min(Math.max(alpha, 0), 1);
|
||||
const hslMatch = color.match(/^hsl\((.+)\)$/);
|
||||
|
||||
if (!hslMatch) {
|
||||
return color;
|
||||
}
|
||||
|
||||
return `hsl(${hslMatch[1]} / ${normalizedAlpha})`;
|
||||
}
|
||||
|
||||
async function handleLinkAction(editor: Editor) {
|
||||
const currentHref = editor.getAttributes('link').href as string | undefined;
|
||||
|
||||
let url: string | undefined;
|
||||
|
||||
try {
|
||||
url = await prompt<string>({
|
||||
componentProps: {
|
||||
placeholder: 'https://example.com',
|
||||
},
|
||||
content: $t('ui.tiptap.prompts.link'),
|
||||
defaultValue: currentHref ?? '',
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextUrl = (url ?? '').trim();
|
||||
|
||||
if (!nextUrl) {
|
||||
editor.chain().focus().extendMarkRange('link').unsetLink().run();
|
||||
return;
|
||||
}
|
||||
|
||||
editor
|
||||
.chain()
|
||||
.focus()
|
||||
.extendMarkRange('link')
|
||||
.setLink({
|
||||
href: normalizeLinkUrl(nextUrl),
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
async function handleImageAction(editor: Editor) {
|
||||
let url: string | undefined;
|
||||
|
||||
try {
|
||||
url = await prompt<string>({
|
||||
componentProps: {
|
||||
placeholder: 'https://example.com/image.png',
|
||||
},
|
||||
content: $t('ui.tiptap.prompts.image'),
|
||||
defaultValue: '',
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextUrl = (url ?? '').trim();
|
||||
|
||||
if (!nextUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.chain().focus().setImage({ src: nextUrl }).run();
|
||||
}
|
||||
|
||||
export function createToolbarGroups(): ToolbarAction[][] {
|
||||
const headingMenuItems = createHeadingMenuItems();
|
||||
|
||||
return [
|
||||
[
|
||||
{
|
||||
action: (editor) => editor.chain().focus().undo().run(),
|
||||
can: (editor) => editor.can().chain().focus().undo().run(),
|
||||
icon: Undo2,
|
||||
label: $t('ui.tiptap.toolbar.undo'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().redo().run(),
|
||||
can: (editor) => editor.can().chain().focus().redo().run(),
|
||||
icon: Redo2,
|
||||
label: $t('ui.tiptap.toolbar.redo'),
|
||||
},
|
||||
{
|
||||
action: (editor) =>
|
||||
editor.chain().focus().clearNodes().unsetAllMarks().run(),
|
||||
icon: RemoveFormatting,
|
||||
label: $t('ui.tiptap.toolbar.clear'),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleBold().run(),
|
||||
active: { name: 'bold' },
|
||||
can: (editor) => editor.can().chain().focus().toggleBold().run(),
|
||||
icon: Bold,
|
||||
label: $t('ui.tiptap.toolbar.bold'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleItalic().run(),
|
||||
active: { name: 'italic' },
|
||||
can: (editor) => editor.can().chain().focus().toggleItalic().run(),
|
||||
icon: Italic,
|
||||
label: $t('ui.tiptap.toolbar.italic'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleUnderline().run(),
|
||||
active: { name: 'underline' },
|
||||
can: (editor) => editor.can().chain().focus().toggleUnderline().run(),
|
||||
icon: Underline,
|
||||
label: $t('ui.tiptap.toolbar.underline'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleStrike().run(),
|
||||
active: { name: 'strike' },
|
||||
can: (editor) => editor.can().chain().focus().toggleStrike().run(),
|
||||
icon: Strikethrough,
|
||||
label: $t('ui.tiptap.toolbar.strike'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleCode().run(),
|
||||
active: { name: 'code' },
|
||||
can: (editor) => editor.can().chain().focus().toggleCode().run(),
|
||||
icon: SquareCode,
|
||||
label: $t('ui.tiptap.toolbar.code'),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
action: () => {},
|
||||
can: (editor) =>
|
||||
headingMenuItems.some((item) => (item.can ? item.can(editor) : true)),
|
||||
isActive: (editor) =>
|
||||
headingMenuItems.some((item) => item.isActive?.(editor)),
|
||||
label: $t('ui.tiptap.toolbar.heading'),
|
||||
menu: {
|
||||
items: headingMenuItems,
|
||||
},
|
||||
triggerText: (editor) => getHeadingTriggerText(editor),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleBulletList().run(),
|
||||
active: { name: 'bulletList' },
|
||||
can: (editor) => editor.can().chain().focus().toggleBulletList().run(),
|
||||
icon: List,
|
||||
label: $t('ui.tiptap.toolbar.bulletList'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleOrderedList().run(),
|
||||
active: { name: 'orderedList' },
|
||||
can: (editor) => editor.can().chain().focus().toggleOrderedList().run(),
|
||||
icon: ListOrdered,
|
||||
label: $t('ui.tiptap.toolbar.orderedList'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleBlockquote().run(),
|
||||
active: { name: 'blockquote' },
|
||||
can: (editor) => editor.can().chain().focus().toggleBlockquote().run(),
|
||||
icon: TextQuote,
|
||||
label: $t('ui.tiptap.toolbar.blockquote'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().toggleCodeBlock().run(),
|
||||
active: { name: 'codeBlock' },
|
||||
can: (editor) => editor.can().chain().focus().toggleCodeBlock().run(),
|
||||
icon: MessageSquareCode,
|
||||
label: $t('ui.tiptap.toolbar.codeBlock'),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
action: (editor) => handleLinkAction(editor),
|
||||
active: { name: 'link' },
|
||||
can: (editor) =>
|
||||
editor.can().chain().focus().extendMarkRange('link').run(),
|
||||
icon: Link2,
|
||||
label: $t('ui.tiptap.toolbar.link'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().unsetLink().run(),
|
||||
can: (editor) => editor.can().chain().focus().unsetLink().run(),
|
||||
icon: Unlink2,
|
||||
isActive: (editor) => editor.isActive('link'),
|
||||
label: $t('ui.tiptap.toolbar.unlink'),
|
||||
},
|
||||
{
|
||||
action: (editor) => handleImageAction(editor),
|
||||
icon: ImagePlus,
|
||||
label: $t('ui.tiptap.toolbar.image'),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
action: () => {},
|
||||
icon: Paintbrush,
|
||||
indicatorColor: (editor) =>
|
||||
editor.getAttributes('textStyle').color as string | undefined,
|
||||
isActive: (editor) => Boolean(editor.getAttributes('textStyle').color),
|
||||
label: $t('ui.tiptap.toolbar.textColor'),
|
||||
palette: {
|
||||
apply: (editor, color) =>
|
||||
editor.chain().focus().setColor(color).run(),
|
||||
clear: (editor) => editor.chain().focus().unsetColor().run(),
|
||||
colors: editorColorPresets,
|
||||
currentColor: (editor) =>
|
||||
editor.getAttributes('textStyle').color as string | undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
action: () => {},
|
||||
icon: Highlighter,
|
||||
indicatorColor: (editor) =>
|
||||
(editor.getAttributes('highlight').color as string | undefined) ??
|
||||
'#fef08a',
|
||||
isActive: (editor) => editor.isActive('highlight'),
|
||||
label: $t('ui.tiptap.toolbar.highlightColor'),
|
||||
palette: {
|
||||
apply: (editor, color) =>
|
||||
editor.chain().focus().setHighlight({ color }).run(),
|
||||
clear: (editor) => editor.chain().focus().unsetHighlight().run(),
|
||||
colors: editorHighlightPresets,
|
||||
currentColor: (editor) =>
|
||||
editor.getAttributes('highlight').color as string | undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
action: (editor) => editor.chain().focus().setTextAlign('left').run(),
|
||||
can: (editor) =>
|
||||
editor.can().chain().focus().setTextAlign('left').run(),
|
||||
icon: AlignLeft,
|
||||
isActive: (editor) => editor.isActive({ textAlign: 'left' }),
|
||||
label: $t('ui.tiptap.toolbar.alignLeft'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().setTextAlign('center').run(),
|
||||
can: (editor) =>
|
||||
editor.can().chain().focus().setTextAlign('center').run(),
|
||||
icon: AlignCenter,
|
||||
isActive: (editor) => editor.isActive({ textAlign: 'center' }),
|
||||
label: $t('ui.tiptap.toolbar.alignCenter'),
|
||||
},
|
||||
{
|
||||
action: (editor) => editor.chain().focus().setTextAlign('right').run(),
|
||||
can: (editor) =>
|
||||
editor.can().chain().focus().setTextAlign('right').run(),
|
||||
icon: AlignRight,
|
||||
isActive: (editor) => editor.isActive({ textAlign: 'right' }),
|
||||
label: $t('ui.tiptap.toolbar.alignRight'),
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
60
packages/effects/plugins/src/tiptap/types.ts
Normal file
60
packages/effects/plugins/src/tiptap/types.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { Extensions, JSONContent } from '@tiptap/core';
|
||||
import type { Editor } from '@tiptap/vue-3';
|
||||
|
||||
import type { Component } from 'vue';
|
||||
|
||||
export interface TipTapProps {
|
||||
editable?: boolean;
|
||||
extensions?: Extensions;
|
||||
minHeight?: number | string;
|
||||
placeholder?: string;
|
||||
previewable?: boolean;
|
||||
toolbar?: boolean;
|
||||
}
|
||||
|
||||
export interface TipTapPreviewProps {
|
||||
class?: any;
|
||||
content?: string;
|
||||
minHeight?: number | string;
|
||||
}
|
||||
|
||||
export interface VbenTiptapChangeEvent {
|
||||
html: string;
|
||||
json: JSONContent;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface VbenTiptapExtensionOptions {
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export interface ToolbarAction {
|
||||
action: (editor: Editor) => void;
|
||||
active?: {
|
||||
attrs?: Record<string, unknown>;
|
||||
name: string;
|
||||
};
|
||||
can?: (editor: Editor) => boolean;
|
||||
icon?: Component;
|
||||
indicatorColor?: (editor: Editor) => string | undefined;
|
||||
isActive?: (editor: Editor) => boolean;
|
||||
label: string;
|
||||
menu?: {
|
||||
items: ToolbarMenuItem[];
|
||||
};
|
||||
palette?: {
|
||||
apply: (editor: Editor, color: string) => void;
|
||||
clear?: (editor: Editor) => void;
|
||||
colors: string[];
|
||||
currentColor?: (editor: Editor) => string | undefined;
|
||||
};
|
||||
triggerText?: ((editor?: Editor) => string) | string;
|
||||
}
|
||||
|
||||
export interface ToolbarMenuItem {
|
||||
action: (editor: Editor) => void;
|
||||
can?: (editor: Editor) => boolean;
|
||||
isActive?: (editor: Editor) => boolean;
|
||||
label: string;
|
||||
shortLabel: string;
|
||||
}
|
||||
176
packages/effects/plugins/src/tiptap/use-tiptap-toolbar.ts
Normal file
176
packages/effects/plugins/src/tiptap/use-tiptap-toolbar.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import type { Editor } from '@tiptap/vue-3';
|
||||
|
||||
import type { ShallowRef } from 'vue';
|
||||
|
||||
import type { ToolbarAction, ToolbarMenuItem } from './types';
|
||||
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
interface UseTiptapToolbarOptions {
|
||||
editable: () => boolean;
|
||||
editor: Readonly<ShallowRef<Editor | undefined>>;
|
||||
}
|
||||
|
||||
export function useTiptapToolbar(options: UseTiptapToolbarOptions) {
|
||||
const getEditor = () => options.editor.value;
|
||||
|
||||
function getActionIndicatorColor(action: ToolbarAction) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !action.indicatorColor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return action.indicatorColor(currentEditor);
|
||||
}
|
||||
|
||||
function getPaletteCurrentColor(action: ToolbarAction) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !action.palette?.currentColor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return action.palette.currentColor(currentEditor);
|
||||
}
|
||||
|
||||
function canRunAction(action: ToolbarAction) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !options.editable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return action.can ? action.can(currentEditor) : true;
|
||||
}
|
||||
|
||||
function canRunMenuItem(item: ToolbarMenuItem) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !options.editable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return item.can ? item.can(currentEditor) : true;
|
||||
}
|
||||
|
||||
function isActionActive(action: ToolbarAction) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (action.isActive) {
|
||||
return action.isActive(currentEditor);
|
||||
}
|
||||
|
||||
if (!action.active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return currentEditor.isActive(action.active.name, action.active.attrs);
|
||||
}
|
||||
|
||||
function isMenuItemActive(item: ToolbarMenuItem, currentEditor?: Editor) {
|
||||
const targetEditor = currentEditor ?? getEditor();
|
||||
|
||||
if (!targetEditor || !item.isActive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return item.isActive(targetEditor);
|
||||
}
|
||||
|
||||
function runAction(action: ToolbarAction) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !options.editable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (action.menu || action.palette) {
|
||||
return;
|
||||
}
|
||||
|
||||
action.action(currentEditor);
|
||||
}
|
||||
|
||||
function runMenuItem(item: ToolbarMenuItem) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !options.editable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
item.action(currentEditor);
|
||||
}
|
||||
|
||||
function applyPaletteColor(action: ToolbarAction, color: string) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !action.palette) {
|
||||
return;
|
||||
}
|
||||
|
||||
action.palette.apply(currentEditor, color);
|
||||
}
|
||||
|
||||
function clearPaletteColor(action: ToolbarAction) {
|
||||
const currentEditor = getEditor();
|
||||
|
||||
if (!currentEditor || !action.palette?.clear) {
|
||||
return;
|
||||
}
|
||||
|
||||
action.palette.clear(currentEditor);
|
||||
}
|
||||
|
||||
function getToolbarButtonClass(action: ToolbarAction) {
|
||||
return cn(
|
||||
'relative rounded-[10px] border border-transparent bg-transparent text-muted-foreground shadow-none',
|
||||
'transition-[transform,color,background-color,border-color,box-shadow] duration-200 ease-out',
|
||||
'enabled:hover:-translate-y-px enabled:hover:border-border disabled:opacity-45',
|
||||
'enabled:hover:bg-accent enabled:hover:text-foreground',
|
||||
isActionActive(action) &&
|
||||
'border-primary/30 bg-accent text-primary shadow-primary',
|
||||
);
|
||||
}
|
||||
|
||||
function getPaletteSwatchClass(action: ToolbarAction, color: string) {
|
||||
return cn(
|
||||
'inline-flex size-8 items-center justify-center rounded-full border border-border',
|
||||
'shadow-accent',
|
||||
'transition-[transform,box-shadow,border-color] duration-200 ease-out',
|
||||
'hover:-translate-y-px hover:scale-[1.04]',
|
||||
getPaletteCurrentColor(action) === color &&
|
||||
'border-primary shadow-primary',
|
||||
);
|
||||
}
|
||||
|
||||
function getMenuItemClass(item: ToolbarMenuItem) {
|
||||
return cn(
|
||||
'flex items-center gap-2 rounded-lg p-2 text-left text-sm transition-colors',
|
||||
'disabled:cursor-not-allowed disabled:opacity-45',
|
||||
isMenuItemActive(item)
|
||||
? 'bg-accent text-foreground'
|
||||
: 'text-muted-foreground hover:bg-accent hover:text-foreground',
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
applyPaletteColor,
|
||||
canRunAction,
|
||||
canRunMenuItem,
|
||||
clearPaletteColor,
|
||||
getActionIndicatorColor,
|
||||
getMenuItemClass,
|
||||
getPaletteCurrentColor,
|
||||
getPaletteSwatchClass,
|
||||
getToolbarButtonClass,
|
||||
isActionActive,
|
||||
isMenuItemActive,
|
||||
runAction,
|
||||
runMenuItem,
|
||||
};
|
||||
}
|
||||
@@ -61,6 +61,42 @@
|
||||
"cancel": "Cancel cropping",
|
||||
"errorTip": "Cropping error"
|
||||
},
|
||||
"tiptap": {
|
||||
"placeholder": "Please enter content...",
|
||||
"prompts": {
|
||||
"image": "Enter image URL",
|
||||
"link": "Enter link URL"
|
||||
},
|
||||
"toolbar": {
|
||||
"bold": "Bold",
|
||||
"italic": "Italic",
|
||||
"underline": "Underline",
|
||||
"strike": "Strike",
|
||||
"code": "Code",
|
||||
"codeBlock": "Code Block",
|
||||
"heading": "Heading",
|
||||
"paragraph": "Paragraph",
|
||||
"heading1": "H1",
|
||||
"heading2": "H2",
|
||||
"heading3": "H3",
|
||||
"heading4": "H4",
|
||||
"bulletList": "Bullets",
|
||||
"orderedList": "Numbering",
|
||||
"blockquote": "Quote",
|
||||
"link": "Link",
|
||||
"unlink": "Unlink",
|
||||
"image": "Image",
|
||||
"textColor": "Text Color",
|
||||
"highlightColor": "Highlight Color",
|
||||
"alignLeft": "Left",
|
||||
"alignCenter": "Center",
|
||||
"alignRight": "Right",
|
||||
"preview": "Preview",
|
||||
"undo": "Undo",
|
||||
"redo": "Redo",
|
||||
"clear": "Clear"
|
||||
}
|
||||
},
|
||||
"fallback": {
|
||||
"pageNotFound": "Oops! Page Not Found",
|
||||
"pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for.",
|
||||
|
||||
@@ -61,6 +61,42 @@
|
||||
"cancel": "取消裁剪",
|
||||
"errorTip": "裁剪错误"
|
||||
},
|
||||
"tiptap": {
|
||||
"placeholder": "请输入内容...",
|
||||
"prompts": {
|
||||
"image": "请输入图片地址",
|
||||
"link": "请输入链接地址"
|
||||
},
|
||||
"toolbar": {
|
||||
"bold": "加粗",
|
||||
"italic": "斜体",
|
||||
"underline": "下划线",
|
||||
"strike": "删除线",
|
||||
"code": "行内代码",
|
||||
"codeBlock": "代码块",
|
||||
"heading": "标题",
|
||||
"paragraph": "正文",
|
||||
"heading1": "标题1",
|
||||
"heading2": "标题2",
|
||||
"heading3": "标题3",
|
||||
"heading4": "标题4",
|
||||
"bulletList": "无序列表",
|
||||
"orderedList": "有序列表",
|
||||
"blockquote": "引用",
|
||||
"link": "链接",
|
||||
"unlink": "移除链接",
|
||||
"image": "图片",
|
||||
"textColor": "文字颜色",
|
||||
"highlightColor": "高亮颜色",
|
||||
"alignLeft": "左对齐",
|
||||
"alignCenter": "居中",
|
||||
"alignRight": "右对齐",
|
||||
"preview": "预览",
|
||||
"undo": "撤销",
|
||||
"redo": "重做",
|
||||
"clear": "清除"
|
||||
}
|
||||
},
|
||||
"fallback": {
|
||||
"pageNotFound": "哎呀!未找到页面",
|
||||
"pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。",
|
||||
|
||||
@@ -40,6 +40,7 @@ import {
|
||||
import { useSortable } from '@vben/hooks';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { VbenTiptap } from '@vben/plugins/tiptap';
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { message, Modal, notification } from 'ant-design-vue';
|
||||
@@ -583,6 +584,7 @@ export type ComponentType =
|
||||
| 'RadioGroup'
|
||||
| 'RangePicker'
|
||||
| 'Rate'
|
||||
| 'RichEditor'
|
||||
| 'Select'
|
||||
| 'Space'
|
||||
| 'Switch'
|
||||
@@ -646,6 +648,7 @@ async function initComponentAdapter() {
|
||||
RadioGroup,
|
||||
RangePicker,
|
||||
Rate,
|
||||
RichEditor: withDefaultPlaceholder(VbenTiptap, 'input'),
|
||||
Select: withDefaultPlaceholder(Select, 'select'),
|
||||
Space,
|
||||
Switch,
|
||||
|
||||
@@ -79,5 +79,8 @@
|
||||
},
|
||||
"cropper": {
|
||||
"title": "Cropper"
|
||||
},
|
||||
"tiptap": {
|
||||
"title": "Rich Text Editor"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,5 +79,8 @@
|
||||
},
|
||||
"cropper": {
|
||||
"title": "图片裁剪"
|
||||
},
|
||||
"tiptap": {
|
||||
"title": "富文本编辑器"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +346,15 @@ const routes: RouteRecordRaw[] = [
|
||||
title: $t('examples.cropper.title'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'TiptapExample',
|
||||
path: '/examples/tiptap',
|
||||
component: () => import('#/views/examples/tiptap/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:square-pen',
|
||||
title: $t('examples.tiptap.title'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -409,6 +409,12 @@ const [BaseForm, baseFormApi] = useVbenForm({
|
||||
},
|
||||
rules: 'selectRequired',
|
||||
},
|
||||
{
|
||||
component: 'RichEditor',
|
||||
fieldName: 'richEditor',
|
||||
label: '富文本',
|
||||
formItemClass: 'col-span-3 items-baseline',
|
||||
},
|
||||
],
|
||||
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
|
||||
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
|
||||
@@ -485,6 +491,12 @@ function handleSetFormValue() {
|
||||
timePicker: dayjs('2022-01-01 12:00:00'),
|
||||
treeSelect: 'leaf1',
|
||||
username: '1',
|
||||
richEditor: `
|
||||
<h1>Vben Tiptap</h1>
|
||||
<p>这个编辑器已经被封装在 <code>packages/effects/plugins/src/tiptap</code> 中。</p>
|
||||
<p>你可以直接在各个 app 里通过 <code>@vben/plugins/tiptap</code> 引入。</p>
|
||||
<blockquote>默认内置 StarterKit、Underline、TextAlign、Placeholder。</blockquote>
|
||||
`,
|
||||
});
|
||||
|
||||
// 设置单个表单值
|
||||
|
||||
39
playground/src/views/examples/tiptap/index.vue
Normal file
39
playground/src/views/examples/tiptap/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { VbenTiptap, VbenTiptapPreview } from '@vben/plugins/tiptap';
|
||||
|
||||
import { Card } from 'ant-design-vue';
|
||||
const content = ref(`
|
||||
<h1>Vben Tiptap</h1>
|
||||
<p>这个编辑器已经被封装在 <code>packages/effects/plugins/src/tiptap</code> 中。</p>
|
||||
<p>你可以直接在各个 app 里通过 <code>@vben/plugins/tiptap</code> 引入。</p>
|
||||
<blockquote>默认内置 StarterKit、Underline、TextAlign、Placeholder。</blockquote>
|
||||
`);
|
||||
const previewContent = computed(() => content.value);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page title="Tiptap 富文本">
|
||||
<template #description>
|
||||
<div class="mt-2 text-foreground/80">
|
||||
统一封装后的富文本编辑器,适合在各个 app 中直接复用。
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Card class="mb-5" title="编辑器">
|
||||
<VbenTiptap v-model="content" />
|
||||
</Card>
|
||||
|
||||
<Card class="mb-5" title="富文本预览">
|
||||
<VbenTiptapPreview :content="previewContent" />
|
||||
</Card>
|
||||
|
||||
<Card title="HTML 输出">
|
||||
<pre class="overflow-auto rounded-xl border border-border bg-muted p-4">
|
||||
{{ previewContent }}
|
||||
</pre>
|
||||
</Card>
|
||||
</Page>
|
||||
</template>
|
||||
660
pnpm-lock.yaml
generated
660
pnpm-lock.yaml
generated
@@ -78,6 +78,36 @@ catalogs:
|
||||
'@tanstack/vue-store':
|
||||
specifier: ^0.9.3
|
||||
version: 0.9.3
|
||||
'@tiptap/core':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-highlight':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-image':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-link':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-placeholder':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-text-align':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-text-style':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/extension-underline':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/starter-kit':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tiptap/vue-3':
|
||||
specifier: ^3.21.0
|
||||
version: 3.21.0
|
||||
'@tsdown/css':
|
||||
specifier: ^0.21.7
|
||||
version: 0.21.7
|
||||
@@ -1758,12 +1788,45 @@ importers:
|
||||
|
||||
packages/effects/plugins:
|
||||
dependencies:
|
||||
'@tiptap/core':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-highlight':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-image':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-link':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-placeholder':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-text-align':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-text-style':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-underline':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/starter-kit':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0
|
||||
'@tiptap/vue-3':
|
||||
specifier: 'catalog:'
|
||||
version: 3.21.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)(vue@3.5.31(typescript@5.9.3))
|
||||
'@vben-core/design':
|
||||
specifier: workspace:*
|
||||
version: link:../../@core/base/design
|
||||
'@vben-core/form-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../@core/ui-kit/form-ui
|
||||
'@vben-core/popup-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../@core/ui-kit/popup-ui
|
||||
'@vben-core/shadcn-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../@core/ui-kit/shadcn-ui
|
||||
@@ -4474,6 +4537,9 @@ packages:
|
||||
'@quansync/fs@1.0.0':
|
||||
resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==}
|
||||
|
||||
'@remirror/core-constants@3.0.0':
|
||||
resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==}
|
||||
|
||||
'@rolldown/binding-android-arm64@1.0.0-rc.12':
|
||||
resolution: {integrity: sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -5035,6 +5101,178 @@ packages:
|
||||
peerDependencies:
|
||||
vue: ^3.5.31
|
||||
|
||||
'@tiptap/core@3.21.0':
|
||||
resolution: {integrity: sha512-IfnQiuEeabDSPr1C/zHFTbnvlTf5z0DE/d/xz4C6bkL4ZBDJ3rr99h2qsaV0l8F+kbNswZMlQdM8rxNlMy95fQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-blockquote@3.21.0':
|
||||
resolution: {integrity: sha512-JDM/RR6rM0dMCZ1UnEf7eqmN6pAdIa2llhN+E24HdTGNJCklMFhLAGE/OT8/1r7M0WWA9GVO7/PTe4EdGh6+lQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-bold@3.21.0':
|
||||
resolution: {integrity: sha512-iyEJRzG7XTCPlHwEDzUw3HnuYYCfL7lNpcCHmxcpYMrIUA8rv7EUxerIwApT6xY8hQ/07ljuJKgOyPvnJOOzuA==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-bubble-menu@3.21.0':
|
||||
resolution: {integrity: sha512-/fabRRhhf8i4LAx9e8xz9ppqN5KgdJk3TxMuxAD5vAWGsejvhSoPa8O8H/QwwyntXm1Vue8aQiMHsUk48b2hGQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-bullet-list@3.21.0':
|
||||
resolution: {integrity: sha512-PWNF+xwxgOeXYGD88sCQLKL0eBoQqjUnZNALxBjN3Y7x4llalh42rHOp2Nt2t6UbQgqTBtBzU/uFcussTpxreQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/extension-list': ^3.21.0
|
||||
|
||||
'@tiptap/extension-code-block@3.21.0':
|
||||
resolution: {integrity: sha512-zrVOcOzDCjHQ8NJcC+qHmZZKiwnP/NMSb3qVJlSMN8TzuHept1MZCDa2Mbo70O6I0txo456SGuXB9sqV1vHmGg==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-code@3.21.0':
|
||||
resolution: {integrity: sha512-D7wA9jp+4X2r1f3FIoga73s6Rn4rmZY57Jes6a4rK3HY+3yHk1r057pPIZSY8Drfs97jxHQVFdfUYUomLSFYBA==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-document@3.21.0':
|
||||
resolution: {integrity: sha512-7oCyzXI9ChvJQUlr23AURdfVar4OIsrYUvqdhEwo3bjcI/Q/j0KJiXfuh6ZzL5eVaINSailH53sZaGg4THQtUg==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-dropcursor@3.21.0':
|
||||
resolution: {integrity: sha512-6fsDSVAM2iz7eElvT6iivMrGBGjIP/oPigVZ/SPm6f31phaYhz6TIOEgV/Lr2jaPIOgyK4U0cU4Yd4KUBCmhzQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/extensions': ^3.21.0
|
||||
|
||||
'@tiptap/extension-floating-menu@3.21.0':
|
||||
resolution: {integrity: sha512-n2HzTB+I/5rAl8R/1sKMv92JiY1oDK1hroXizxEKYa6dskJcAMW0CfYyPcPOZWQQEe7qoeOvQISr2ooLAKW+Mw==}
|
||||
peerDependencies:
|
||||
'@floating-ui/dom': ^1.0.0
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-gapcursor@3.21.0':
|
||||
resolution: {integrity: sha512-wGjgAoYBTvPAe9QYMI5px355XcNeMkaUrMY9IHbMqgqdmHcDxqooxM4H6sYVX2CRcHwXy4I8NQAoOhSYrQJDMg==}
|
||||
peerDependencies:
|
||||
'@tiptap/extensions': ^3.21.0
|
||||
|
||||
'@tiptap/extension-hard-break@3.21.0':
|
||||
resolution: {integrity: sha512-6JFVSAOQ1qhQHi9mVcdn2/XO8YIMgYV8zjarzNUzP6Sf2waeE5BLXjlg6rIH/945sY1J+FndTojLru6gQ07a5A==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-heading@3.21.0':
|
||||
resolution: {integrity: sha512-ji6VJmoRnDzAHYflEYEZohMHRi77UGLW1o3ua7UhI32iJ9nuYssbPNuzEeE4SvENMQwZRszad5+a+dKAa+NC7g==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-highlight@3.21.0':
|
||||
resolution: {integrity: sha512-3f/bVgfm2dJZxalh07TThDxcTaeXJ+dpYyRY9trnFeHbhyYQXSy6yzkNhNcYB4Ua5jxpKQv4b9Q448QVh+KNzA==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-horizontal-rule@3.21.0':
|
||||
resolution: {integrity: sha512-vNBnOfFEY62CoJPGo4nonRM7RiOvhII1vhoO+WFr1GxDqCAfmEFjToflt7JT1UJdo6lMVcD+aaaAgOiuSz5p6g==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-image@3.21.0':
|
||||
resolution: {integrity: sha512-W9786a2K4LSZJMPeRLmoDulJeXOsM0ueRV2MHjTol7ikPRauROB7GUbAz9DyPAJHA2AGUfpswnGAYPO3tz5CLg==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-italic@3.21.0':
|
||||
resolution: {integrity: sha512-2I8oPvwyXhRn1k8lbDFIutzvhtLEjoO5mmQCNX4TnT4PdxxaSrK9+ihYg12VeqhUeO7dg1MKiFqws0HVBrwzWg==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-link@3.21.0':
|
||||
resolution: {integrity: sha512-oMU7Yve1sbgBsaFAUc2R0GPf4d3ZPVJeMUFC6b6X9rJIvx/IhEUEn9toQcSBGfp02uWK9NdQyIFYFdWlVXH++w==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-list-item@3.21.0':
|
||||
resolution: {integrity: sha512-1ZymZmlQVbAoC4q5x3cro0v5+3I6l+BHqbhIMQLjQFlAOJfcE0pvqRzAFW7PduxUj41tXEtsYqp2NREvO9F5Fg==}
|
||||
peerDependencies:
|
||||
'@tiptap/extension-list': ^3.21.0
|
||||
|
||||
'@tiptap/extension-list-keymap@3.21.0':
|
||||
resolution: {integrity: sha512-EzrfW3ASNFPWKhR8sNOq7Kqw4hvaTAOn4dlI7chB8HIANSrlyPOUn+eKAnO6HQgsUgsbjg2GbTUrGrxcoLykUg==}
|
||||
peerDependencies:
|
||||
'@tiptap/extension-list': ^3.21.0
|
||||
|
||||
'@tiptap/extension-list@3.21.0':
|
||||
resolution: {integrity: sha512-KeBlEtLrGce2d3dgL89hmwWEtREuzlW4XY5bYWpKNvCbFqvdSb3n7vkdkw32YclZmMWxAcABgW6ucCStkE0rsQ==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/extension-ordered-list@3.21.0':
|
||||
resolution: {integrity: sha512-+d+0orokMfqaBfvr9tUBgGvo2ZCV+fR3JzsJTmnLBWOkhBSJN7H4pnfXPTue0qwspUwRmkLJxdIlU+J7HkMrng==}
|
||||
peerDependencies:
|
||||
'@tiptap/extension-list': ^3.21.0
|
||||
|
||||
'@tiptap/extension-paragraph@3.21.0':
|
||||
resolution: {integrity: sha512-cMPG/jCoZ9NmLZ5ctFziILaxJGfDtMTb5OLBhifMFZeMVwF1pEJIygDEfnX/HSruv507weZSQG4pERO2tRszMg==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-placeholder@3.21.0':
|
||||
resolution: {integrity: sha512-fs+cQqMh1d1naV6OgOhP/0qbRJwtw8DpQMj3/oqGKbaRRKIeecEaZPXYRd7MYa4e9K0Cfk5Bm0MNs9lwu/BYsw==}
|
||||
peerDependencies:
|
||||
'@tiptap/extensions': ^3.21.0
|
||||
|
||||
'@tiptap/extension-strike@3.21.0':
|
||||
resolution: {integrity: sha512-easnVaN11Wl+5fOtfvzJ10J762S9TRXZaMj5rLBGavgf82DCYHqhGhBqpLQrJ41r4nPABGlYvTRoxfvBLB74Lg==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-text-align@3.21.0':
|
||||
resolution: {integrity: sha512-XaoUaq45nai9LLoUStumMItHhhCnmXirPR8mTjEDKZ2QD0Kg/YHEr6guJYc6qKB7YA+Wa1EgBIrZOv1+d2Pdag==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-text-style@3.21.0':
|
||||
resolution: {integrity: sha512-MI/3X75D45Wa/+0Fp8nYfNJq5makkjtG7B2/lIzNUe0kEKJ56RVQoV1GQSXxAiFNyAYRfKFq8dJslhesW3EkWA==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-text@3.21.0':
|
||||
resolution: {integrity: sha512-Zx8QdB8a5iBuE4uO21c3BjmpBfaJEr2Jd1QFnsdgx11fm6P7dGgZaGko1FaINhfOPRGTN6O/kiF02cDMdOHa/w==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extension-underline@3.21.0':
|
||||
resolution: {integrity: sha512-gGmBEymbWnr8AIS8bI/bPw5rcwo7wAFcBw/TsLd1nAanu1dDqSRNDBrit3m02Ru+D88u2SfNvmbOPI1pz+1f5w==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
|
||||
'@tiptap/extensions@3.21.0':
|
||||
resolution: {integrity: sha512-MN1uh5PmHT1F2BNsbc21MIS0AMFFA73oODlp/4ckpBR4o5AxRwV+8f43Cd52UL4MgMkKj/A+QfZ7iK9IDb0h5A==}
|
||||
peerDependencies:
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
|
||||
'@tiptap/pm@3.21.0':
|
||||
resolution: {integrity: sha512-I3sNo7oMMsR6FFz1ecvPb9uCF0VQuS2WV67j8Io2M7DJicRWCE/GM5DaiYjTeWBbnByk6BuG0txoJATAqPVliQ==}
|
||||
|
||||
'@tiptap/starter-kit@3.21.0':
|
||||
resolution: {integrity: sha512-w7fWxglDtqXFBgRYH+LforJyUboSAQllnWQbGVSTyX4rsICqZjkb3f6CTSUWpGoGKmlmbb2ZpEuoik7tur9d8Q==}
|
||||
|
||||
'@tiptap/vue-3@3.21.0':
|
||||
resolution: {integrity: sha512-dfjxBwxg9+GNvsgkCbxLnj/vmG+YZMdcD/qF7bKM710bANWfqzimRUhH5W2KZcxqlYzqpz0u/P0zi7dUMR5IZA==}
|
||||
peerDependencies:
|
||||
'@floating-ui/dom': ^1.0.0
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/pm': ^3.21.0
|
||||
vue: ^3.5.31
|
||||
|
||||
'@tsdown/css@0.21.7':
|
||||
resolution: {integrity: sha512-kydfZ109LIXwoBDrdIeEVi+PtM8375X9d/6UtYtjhj6TS94J25gJVUXw9AyJE6THEqB6OdGKM5MLqJPutO4kkA==}
|
||||
engines: {node: '>=20.19.0'}
|
||||
@@ -6045,8 +6283,8 @@ packages:
|
||||
bare-buffer:
|
||||
optional: true
|
||||
|
||||
bare-os@3.8.4:
|
||||
resolution: {integrity: sha512-4JboWUl7/2LhgU536tjUszzaVC8/WEWKtyX5crayvlN71ih8+O2SdvBhotQeDsuhhmPZmLCrPBJEcwVPhI/kkQ==}
|
||||
bare-os@3.8.6:
|
||||
resolution: {integrity: sha512-l8xaNWWb/bXuzgsrlF5jaa5QYDJ9S0ddd54cP6CH+081+5iPrbJiCfBWQqrWYzmUhCbsH+WR6qxo9MeHVCr0MQ==}
|
||||
engines: {bare: '>=1.14.0'}
|
||||
|
||||
bare-path@3.0.0:
|
||||
@@ -6502,6 +6740,9 @@ packages:
|
||||
resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
crelt@1.0.6:
|
||||
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||
|
||||
croner@10.0.1:
|
||||
resolution: {integrity: sha512-ixNtAJndqh173VQ4KodSdJEI6nuioBWI0V1ITNKhZZsO0pEMoDxz539T4FTTbSZ/xIOSuDnzxLVRqBVSvPNE2g==}
|
||||
engines: {node: '>=18.0'}
|
||||
@@ -8303,6 +8544,12 @@ packages:
|
||||
lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
|
||||
linkify-it@5.0.0:
|
||||
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
|
||||
|
||||
linkifyjs@4.3.2:
|
||||
resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==}
|
||||
|
||||
listhen@1.9.0:
|
||||
resolution: {integrity: sha512-I8oW2+QL5KJo8zXNWX046M134WchxsXC7SawLPvRQpogCbkyQIaFxPE89A2HiwR7vAK2Dm2ERBAmyjTYGYEpBg==}
|
||||
hasBin: true
|
||||
@@ -8457,6 +8704,10 @@ packages:
|
||||
mark.js@8.11.1:
|
||||
resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
|
||||
|
||||
markdown-it@14.1.1:
|
||||
resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==}
|
||||
hasBin: true
|
||||
|
||||
math-intrinsics@1.1.0:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -8476,6 +8727,9 @@ packages:
|
||||
mdn-data@2.27.1:
|
||||
resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
|
||||
|
||||
mdurl@2.0.0:
|
||||
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
|
||||
|
||||
medium-zoom@1.1.0:
|
||||
resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==}
|
||||
|
||||
@@ -8802,6 +9056,9 @@ packages:
|
||||
resolution: {integrity: sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
orderedmap@2.1.1:
|
||||
resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==}
|
||||
|
||||
outdent@0.5.0:
|
||||
resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
|
||||
|
||||
@@ -9159,6 +9416,64 @@ packages:
|
||||
property-information@7.1.0:
|
||||
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
|
||||
|
||||
prosemirror-changeset@2.4.0:
|
||||
resolution: {integrity: sha512-LvqH2v7Q2SF6yxatuPP2e8vSUKS/L+xAU7dPDC4RMyHMhZoGDfBC74mYuyYF4gLqOEG758wajtyhNnsTkuhvng==}
|
||||
|
||||
prosemirror-collab@1.3.1:
|
||||
resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==}
|
||||
|
||||
prosemirror-commands@1.7.1:
|
||||
resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==}
|
||||
|
||||
prosemirror-dropcursor@1.8.2:
|
||||
resolution: {integrity: sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==}
|
||||
|
||||
prosemirror-gapcursor@1.4.1:
|
||||
resolution: {integrity: sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==}
|
||||
|
||||
prosemirror-history@1.5.0:
|
||||
resolution: {integrity: sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==}
|
||||
|
||||
prosemirror-inputrules@1.5.1:
|
||||
resolution: {integrity: sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==}
|
||||
|
||||
prosemirror-keymap@1.2.3:
|
||||
resolution: {integrity: sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==}
|
||||
|
||||
prosemirror-markdown@1.13.4:
|
||||
resolution: {integrity: sha512-D98dm4cQ3Hs6EmjK500TdAOew4Z03EV71ajEFiWra3Upr7diytJsjF4mPV2dW+eK5uNectiRj0xFxYI9NLXDbw==}
|
||||
|
||||
prosemirror-menu@1.3.0:
|
||||
resolution: {integrity: sha512-TImyPXCHPcDsSka2/lwJ6WjTASr4re/qWq1yoTTuLOqfXucwF6VcRa2LWCkM/EyTD1UO3CUwiH8qURJoWJRxwg==}
|
||||
|
||||
prosemirror-model@1.25.4:
|
||||
resolution: {integrity: sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==}
|
||||
|
||||
prosemirror-schema-basic@1.2.4:
|
||||
resolution: {integrity: sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==}
|
||||
|
||||
prosemirror-schema-list@1.5.1:
|
||||
resolution: {integrity: sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==}
|
||||
|
||||
prosemirror-state@1.4.4:
|
||||
resolution: {integrity: sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==}
|
||||
|
||||
prosemirror-tables@1.8.5:
|
||||
resolution: {integrity: sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==}
|
||||
|
||||
prosemirror-trailing-node@3.0.0:
|
||||
resolution: {integrity: sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==}
|
||||
peerDependencies:
|
||||
prosemirror-model: ^1.22.1
|
||||
prosemirror-state: ^1.4.2
|
||||
prosemirror-view: ^1.33.8
|
||||
|
||||
prosemirror-transform@1.12.0:
|
||||
resolution: {integrity: sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==}
|
||||
|
||||
prosemirror-view@1.41.7:
|
||||
resolution: {integrity: sha512-jUwKNCEIGiqdvhlS91/2QAg21e4dfU5bH2iwmSDQeosXJgKF7smG0YSplOWK0cjSNgIqXe7VXqo7EIfUFJdt3w==}
|
||||
|
||||
proto-list@1.2.4:
|
||||
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
|
||||
|
||||
@@ -9174,6 +9489,10 @@ packages:
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
punycode.js@2.3.1:
|
||||
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -9429,6 +9748,9 @@ packages:
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
rope-sequence@1.3.4:
|
||||
resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==}
|
||||
|
||||
run-applescript@7.1.0:
|
||||
resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -10258,6 +10580,9 @@ packages:
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
uc.micro@2.1.0:
|
||||
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
|
||||
|
||||
ufo@1.6.3:
|
||||
resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
|
||||
|
||||
@@ -10812,6 +11137,9 @@ packages:
|
||||
vxe-table@4.18.10:
|
||||
resolution: {integrity: sha512-8V9WL83pB4PrvgBS6DoDU7dSRxOlJw9ZkVcxDnKBFQkTTnLVvC8HYOJ75uwfRNyo9cALNIpJnSkow2uqaMKbNQ==}
|
||||
|
||||
w3c-keyname@2.2.8:
|
||||
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||
|
||||
warning@4.0.3:
|
||||
resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
|
||||
|
||||
@@ -13573,6 +13901,8 @@ snapshots:
|
||||
dependencies:
|
||||
quansync: 1.0.0
|
||||
|
||||
'@remirror/core-constants@3.0.0': {}
|
||||
|
||||
'@rolldown/binding-android-arm64@1.0.0-rc.12':
|
||||
optional: true
|
||||
|
||||
@@ -14007,6 +14337,196 @@ snapshots:
|
||||
'@tanstack/virtual-core': 3.13.23
|
||||
vue: 3.5.31(typescript@5.9.3)
|
||||
|
||||
'@tiptap/core@3.21.0(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@tiptap/pm': 3.21.0
|
||||
|
||||
'@tiptap/extension-blockquote@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-bold@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-bubble-menu@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.7.6
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
optional: true
|
||||
|
||||
'@tiptap/extension-bullet-list@3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extension-list': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-code-block@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
|
||||
'@tiptap/extension-code@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-document@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-dropcursor@3.21.0(@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extensions': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-floating-menu@3.21.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.7.6
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
optional: true
|
||||
|
||||
'@tiptap/extension-gapcursor@3.21.0(@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extensions': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-hard-break@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-heading@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-highlight@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-horizontal-rule@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
|
||||
'@tiptap/extension-image@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-italic@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-link@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
linkifyjs: 4.3.2
|
||||
|
||||
'@tiptap/extension-list-item@3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extension-list': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-list-keymap@3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extension-list': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
|
||||
'@tiptap/extension-ordered-list@3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extension-list': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-paragraph@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-placeholder@3.21.0(@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/extensions': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-strike@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-text-align@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-text-style@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-text@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extension-underline@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
|
||||
'@tiptap/pm@3.21.0':
|
||||
dependencies:
|
||||
prosemirror-changeset: 2.4.0
|
||||
prosemirror-collab: 1.3.1
|
||||
prosemirror-commands: 1.7.1
|
||||
prosemirror-dropcursor: 1.8.2
|
||||
prosemirror-gapcursor: 1.4.1
|
||||
prosemirror-history: 1.5.0
|
||||
prosemirror-inputrules: 1.5.1
|
||||
prosemirror-keymap: 1.2.3
|
||||
prosemirror-markdown: 1.13.4
|
||||
prosemirror-menu: 1.3.0
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-schema-basic: 1.2.4
|
||||
prosemirror-schema-list: 1.5.1
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-tables: 1.8.5
|
||||
prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7)
|
||||
prosemirror-transform: 1.12.0
|
||||
prosemirror-view: 1.41.7
|
||||
|
||||
'@tiptap/starter-kit@3.21.0':
|
||||
dependencies:
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-blockquote': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-bold': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-bullet-list': 3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-code': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-code-block': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-document': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-dropcursor': 3.21.0(@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-gapcursor': 3.21.0(@tiptap/extensions@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-hard-break': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-heading': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-horizontal-rule': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-italic': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-link': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-list': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-list-item': 3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-list-keymap': 3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-ordered-list': 3.21.0(@tiptap/extension-list@3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-paragraph': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-strike': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-text': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extension-underline': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))
|
||||
'@tiptap/extensions': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
|
||||
'@tiptap/vue-3@3.21.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)(vue@3.5.31(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.7.6
|
||||
'@tiptap/core': 3.21.0(@tiptap/pm@3.21.0)
|
||||
'@tiptap/pm': 3.21.0
|
||||
vue: 3.5.31(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
'@tiptap/extension-bubble-menu': 3.21.0(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
'@tiptap/extension-floating-menu': 3.21.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.21.0(@tiptap/pm@3.21.0))(@tiptap/pm@3.21.0)
|
||||
|
||||
'@tsdown/css@0.21.7(jiti@2.6.1)(postcss@8.5.8)(sass-embedded@1.98.0)(sass@1.98.0)(tsdown@0.21.7)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
lightningcss: 1.32.0
|
||||
@@ -15217,11 +15737,11 @@ snapshots:
|
||||
- bare-abort-controller
|
||||
- react-native-b4a
|
||||
|
||||
bare-os@3.8.4: {}
|
||||
bare-os@3.8.6: {}
|
||||
|
||||
bare-path@3.0.0:
|
||||
dependencies:
|
||||
bare-os: 3.8.4
|
||||
bare-os: 3.8.6
|
||||
|
||||
bare-stream@2.11.0(bare-events@2.8.2):
|
||||
dependencies:
|
||||
@@ -15686,6 +16206,8 @@ snapshots:
|
||||
crc-32: 1.2.2
|
||||
readable-stream: 4.7.0
|
||||
|
||||
crelt@1.0.6: {}
|
||||
|
||||
croner@10.0.1: {}
|
||||
|
||||
cross-env@10.1.0:
|
||||
@@ -17672,6 +18194,12 @@ snapshots:
|
||||
|
||||
lines-and-columns@1.2.4: {}
|
||||
|
||||
linkify-it@5.0.0:
|
||||
dependencies:
|
||||
uc.micro: 2.1.0
|
||||
|
||||
linkifyjs@4.3.2: {}
|
||||
|
||||
listhen@1.9.0:
|
||||
dependencies:
|
||||
'@parcel/watcher': 2.5.6
|
||||
@@ -17833,6 +18361,15 @@ snapshots:
|
||||
|
||||
mark.js@8.11.1: {}
|
||||
|
||||
markdown-it@14.1.1:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
entities: 4.5.0
|
||||
linkify-it: 5.0.0
|
||||
mdurl: 2.0.0
|
||||
punycode.js: 2.3.1
|
||||
uc.micro: 2.1.0
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mathml-tag-names@4.0.0: {}
|
||||
@@ -17855,6 +18392,8 @@ snapshots:
|
||||
|
||||
mdn-data@2.27.1: {}
|
||||
|
||||
mdurl@2.0.0: {}
|
||||
|
||||
medium-zoom@1.1.0: {}
|
||||
|
||||
memoize-one@6.0.0: {}
|
||||
@@ -18275,6 +18814,8 @@ snapshots:
|
||||
stdin-discarder: 0.3.1
|
||||
string-width: 8.2.0
|
||||
|
||||
orderedmap@2.1.1: {}
|
||||
|
||||
outdent@0.5.0: {}
|
||||
|
||||
own-keys@1.0.1:
|
||||
@@ -18610,6 +19151,109 @@ snapshots:
|
||||
|
||||
property-information@7.1.0: {}
|
||||
|
||||
prosemirror-changeset@2.4.0:
|
||||
dependencies:
|
||||
prosemirror-transform: 1.12.0
|
||||
|
||||
prosemirror-collab@1.3.1:
|
||||
dependencies:
|
||||
prosemirror-state: 1.4.4
|
||||
|
||||
prosemirror-commands@1.7.1:
|
||||
dependencies:
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
|
||||
prosemirror-dropcursor@1.8.2:
|
||||
dependencies:
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
prosemirror-view: 1.41.7
|
||||
|
||||
prosemirror-gapcursor@1.4.1:
|
||||
dependencies:
|
||||
prosemirror-keymap: 1.2.3
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-view: 1.41.7
|
||||
|
||||
prosemirror-history@1.5.0:
|
||||
dependencies:
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
prosemirror-view: 1.41.7
|
||||
rope-sequence: 1.3.4
|
||||
|
||||
prosemirror-inputrules@1.5.1:
|
||||
dependencies:
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
|
||||
prosemirror-keymap@1.2.3:
|
||||
dependencies:
|
||||
prosemirror-state: 1.4.4
|
||||
w3c-keyname: 2.2.8
|
||||
|
||||
prosemirror-markdown@1.13.4:
|
||||
dependencies:
|
||||
'@types/markdown-it': 14.1.2
|
||||
markdown-it: 14.1.1
|
||||
prosemirror-model: 1.25.4
|
||||
|
||||
prosemirror-menu@1.3.0:
|
||||
dependencies:
|
||||
crelt: 1.0.6
|
||||
prosemirror-commands: 1.7.1
|
||||
prosemirror-history: 1.5.0
|
||||
prosemirror-state: 1.4.4
|
||||
|
||||
prosemirror-model@1.25.4:
|
||||
dependencies:
|
||||
orderedmap: 2.1.1
|
||||
|
||||
prosemirror-schema-basic@1.2.4:
|
||||
dependencies:
|
||||
prosemirror-model: 1.25.4
|
||||
|
||||
prosemirror-schema-list@1.5.1:
|
||||
dependencies:
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
|
||||
prosemirror-state@1.4.4:
|
||||
dependencies:
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-transform: 1.12.0
|
||||
prosemirror-view: 1.41.7
|
||||
|
||||
prosemirror-tables@1.8.5:
|
||||
dependencies:
|
||||
prosemirror-keymap: 1.2.3
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
prosemirror-view: 1.41.7
|
||||
|
||||
prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.4)(prosemirror-state@1.4.4)(prosemirror-view@1.41.7):
|
||||
dependencies:
|
||||
'@remirror/core-constants': 3.0.0
|
||||
escape-string-regexp: 4.0.0
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-view: 1.41.7
|
||||
|
||||
prosemirror-transform@1.12.0:
|
||||
dependencies:
|
||||
prosemirror-model: 1.25.4
|
||||
|
||||
prosemirror-view@1.41.7:
|
||||
dependencies:
|
||||
prosemirror-model: 1.25.4
|
||||
prosemirror-state: 1.4.4
|
||||
prosemirror-transform: 1.12.0
|
||||
|
||||
proto-list@1.2.4: {}
|
||||
|
||||
proxy-from-env@2.1.0: {}
|
||||
@@ -18624,6 +19268,8 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
sade: 1.8.1
|
||||
|
||||
punycode.js@2.3.1: {}
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
pupa@3.3.0:
|
||||
@@ -18939,6 +19585,8 @@ snapshots:
|
||||
'@rollup/rollup-win32-x64-msvc': 4.60.1
|
||||
fsevents: 2.3.3
|
||||
|
||||
rope-sequence@1.3.4: {}
|
||||
|
||||
run-applescript@7.1.0: {}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
@@ -19835,6 +20483,8 @@ snapshots:
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
uc.micro@2.1.0: {}
|
||||
|
||||
ufo@1.6.3: {}
|
||||
|
||||
ultrahtml@1.6.0: {}
|
||||
@@ -20439,6 +21089,8 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
w3c-keyname@2.2.8: {}
|
||||
|
||||
warning@4.0.3:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
@@ -47,6 +47,17 @@ catalog:
|
||||
'@tailwindcss/vite': ^4.2.2
|
||||
'@tanstack/vue-query': ^5.95.2
|
||||
'@tanstack/vue-store': ^0.9.3
|
||||
'@tiptap/core': ^3.21.0
|
||||
'@tiptap/extension-doc': ^3.21.0
|
||||
'@tiptap/extension-highlight': ^3.21.0
|
||||
'@tiptap/extension-image': ^3.21.0
|
||||
'@tiptap/extension-link': ^3.21.0
|
||||
'@tiptap/extension-placeholder': ^3.21.0
|
||||
'@tiptap/extension-text-align': ^3.21.0
|
||||
'@tiptap/extension-text-style': ^3.21.0
|
||||
'@tiptap/extension-underline': ^3.21.0
|
||||
'@tiptap/starter-kit': ^3.21.0
|
||||
'@tiptap/vue-3': ^3.21.0
|
||||
'@tsdown/css': ^0.21.7
|
||||
'@types/archiver': ^7.0.0
|
||||
'@types/html-minifier-terser': ^7.0.2
|
||||
|
||||
Reference in New Issue
Block a user