96 lines
2.2 KiB
Vue
96 lines
2.2 KiB
Vue
<template>
|
|
<t-popconfirm
|
|
v-model:visible="visible"
|
|
trigger="click"
|
|
:confirm-btn="{ content: '插入', theme: 'primary' }"
|
|
:cancel-btn="{ content: '取消', theme: 'default' }"
|
|
placement="bottom"
|
|
@visible-change="onVisibleChange"
|
|
@confirm="onConfirm"
|
|
>
|
|
<template #icon><span></span></template>
|
|
<template #content>
|
|
<div class="link-form">
|
|
<t-input v-model="linkForm.href" placeholder="请输入链接地址" />
|
|
<t-input v-model="linkForm.text" placeholder="请输入显示文本,可留空" />
|
|
<t-checkbox v-model="linkForm.syncToHref">显示文本同步为链接</t-checkbox>
|
|
</div>
|
|
</template>
|
|
<t-button v-popup="'插入链接'" variant="outline" :theme="active ? 'primary' : 'default'">
|
|
<t-icon name="link-1" />
|
|
</t-button>
|
|
</t-popconfirm>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import type { TiptapEditorInstance } from "timi-web/editor";
|
|
|
|
defineOptions({
|
|
name: "TiptapLinkButton"
|
|
});
|
|
|
|
const props = defineProps<{
|
|
editor?: TiptapEditorInstance;
|
|
active: boolean;
|
|
}>();
|
|
|
|
const visible = ref(false);
|
|
const linkForm = reactive({
|
|
href: "",
|
|
text: "",
|
|
syncToHref: false
|
|
});
|
|
|
|
function onVisibleChange(nextVisible: boolean) {
|
|
if (!nextVisible || !props.editor) {
|
|
return;
|
|
}
|
|
const previousUrl = (props.editor.getAttributes("link").href as string) || "";
|
|
const selectedText = props.editor.state.doc.textBetween(
|
|
props.editor.state.selection.from,
|
|
props.editor.state.selection.to,
|
|
""
|
|
);
|
|
linkForm.href = previousUrl || "https://";
|
|
linkForm.text = selectedText || "";
|
|
linkForm.syncToHref = false;
|
|
}
|
|
|
|
function onConfirm() {
|
|
if (!props.editor) {
|
|
return;
|
|
}
|
|
const href = linkForm.href.trim();
|
|
if (!href) {
|
|
props.editor.chain().focus().unsetLink().run();
|
|
visible.value = false;
|
|
return;
|
|
}
|
|
const text = linkForm.syncToHref ? href : linkForm.text.trim();
|
|
if (text) {
|
|
props.editor
|
|
.chain()
|
|
.focus()
|
|
.insertContent({
|
|
type: "text",
|
|
text,
|
|
marks: [{ type: "link", attrs: { href } }]
|
|
})
|
|
.run();
|
|
visible.value = false;
|
|
return;
|
|
}
|
|
props.editor.chain().focus().extendMarkRange("link").setLink({ href }).run();
|
|
visible.value = false;
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.link-form {
|
|
gap: .75rem;
|
|
width: 20rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
</style>
|