复合组件

富文本编辑器 AsamEditor

使用结构化文档的富文本编辑、只读展示与资源插入。

富文本编辑器 ​

AsamEditor 使用结构化文档作为 v-model,提供编辑工具栏、只读显示和有限的实例方法。不要将 HTML 字符串传给模型。

编辑与实例方法 ​

下载示例将初始文档内联为完整单文件,并使用可编辑的公开 HTTPS 图片地址。编辑后可观察 change 次数;按钮分别调用聚焦、失焦、清空、插入图片和读取 HTML,页面同时展示当前结构化模型。

编辑与实例方法

展开源码

modelValue 的根节点为 { type: 'doc', content: [...] },内容数组非空;空文档可使用一个空 paragraph。 完整说明。

只读与禁用 ​

editable 默认开启,disabled 默认关闭。任一条件使编辑不可用时隐藏工具栏,clear 不修改内容,insertImage 返回 false;getHTML 仍可读取展示内容。示例在只读与禁用之间切换,并展示拒绝插图的返回值。

只读与禁用

展开源码

placeholder 默认是“请输入内容”,在空文档中显示提示。工具栏支持段落、1–3 级标题、引用、列表、代码块、分隔线、常用行内标记、撤销重做和链接。

占位提示响应后续 placeholder 变化,不需要重新聚焦;该更新不改写文档、不触发模型或 change 回声,也不清除撤销历史。

安全链接、资源插入与外部替换 ​

下面同时展示 HTTP(S)/mailto 链接、非法资源被拒绝、只读/禁用切换和外部 JSON 替换。链接工具栏支持选区添加和移除,不把任意字符串作为 HTML 注入。外部替换不发 change 回声,并重建历史;新文档不能通过 undo 恢复旧文档。所有编辑操作仍受 editable/disabled 限制。

链接、图片安全与外部 JSON 替换

展开源码

初始化与外部替换会验证结构化文档。非法根、字段、节点、标记、嵌套、heading level 或资源地址被拒绝;这不是只检查 JSON 是否可解析。粘贴内容的图片会剥离;Tiptap 序列化输出会去除内部默认属性后再验证。服务器持久化结构化模型,getHTML 用于当前显示的序列化,不扩大为任意 HTML 编辑接口。

文档与资源边界 ​

支持文本、标题、引用、列表、代码块与图片等节点,以及常用文本标记。 完整说明。

图片资源由调用方提供 src 和可选 alt、title;允许 HTTP(S) 或以单个 / 开头的站内绝对路径,拒绝 data、blob、协议相对地址、凭据和控制字符。insertImage 在资源非法或不可编辑时返回 false。粘贴 HTML 中的图片被移除,不负责上传、文件选择或后端存储。

链接只接受 HTTP(S) 或有效 mailto 地址。getHTML 返回当前序列化内容,持久化建议保留结构化模型;宿主对其他来源 HTML 的处理仍由宿主负责。公开方法仅为 focus、blur、clear、insertImage、getHTML,不暴露底层编辑器实例,也没有公开内容插槽。

可调用的公开辅助出口 ​

EMPTY_EDITOR_DOCUMENT 是共享的 AsamEditorDocument 对象,形状为 { type: 'doc', content: [{ type: 'paragraph' }] }。类型字段只读;创建独立模型时可用 structuredClone,不直接改写共享常量。

isSafeImageUrl(value: string): boolean 判定 HTTP(S) 无凭据地址或单个 / 开头的站内路径。 完整说明。

validateEditorDocument(value: unknown): asserts value is AsamEditorDocument 验证上述完整文档语法。 完整说明。

公开辅助函数与动态占位提示

展开源码

示例按需导入全部辅助出口,展示地址判定、未知 JSON 的验证和加载、独立空文档,以及动态占位提示与事件计数。

下载示例的图片来源 ​

编辑器的图片模型只接收可访问的 HTTP(S) 或站内根路径,不接受内联 data/blob。 完整说明。

API

属性 AsamEditorProps

属性名说明类型默认值
modelValue—AsamEditorDocument—
editable—boolean | undefinedtrue
disabled—boolean | undefinedfalse
placeholder—string | undefined'请输入内容'

事件 AsamEditorEmits

属性名说明类型默认值
update:modelValue—[document: AsamEditorDocument]—
change—[document: AsamEditorDocument]—

实例方法与状态 AsamEditorExpose

属性名说明类型默认值
focus—() => void—
blur—() => void—
clear—() => void—
insertImage—(resource: AsamEditorImageResource) => boolean—
getHTML—() => string—

类型 AsamEditorAttribute

类型 AsamEditorMark

属性名说明类型默认值
type—string—
attrs—Readonly<Record<string, AsamEditorAttribute>> | undefined—

类型 AsamEditorNode

属性名说明类型默认值
type—string—
attrs—Readonly<Record<string, AsamEditorAttribute>> | undefined—
content—readonly AsamEditorNode[] | undefined—
marks—readonly AsamEditorMark[] | undefined—
text—string | undefined—

类型 AsamEditorDocument

属性名说明类型默认值
type—enum"doc"完整类型:"doc"—
content—readonly AsamEditorNode[]—

类型 AsamEditorImageResource

属性名说明类型默认值
src—string—
alt—string | undefined—
title—string | undefined—

类型 EMPTY_EDITOR_DOCUMENT

属性名说明类型默认值
type—enum"doc"完整类型:"doc"—
content—readonly AsamEditorNode[]—

服务 isSafeImageUrl

ts
(value: string): boolean

服务 isSafeLinkUrl

ts
(value: string): boolean

服务 validateEditorDocument

ts
(value: unknown): asserts value is AsamEditorDocument

用法与契约补充说明 ​

编辑与实例方法 ​

modelValue 的根节点为 { type: 'doc', content: [...] },内容数组非空;空文档可使用一个空 paragraph。编辑产生 update:modelValue 和 change,两者传入结构化文档。外部替换模型时组件更新内容并重建撤销历史,不应依赖旧文档的 undo 恢复已替换数据。

可调用的公开辅助出口 ​

isSafeImageUrl(value: string): boolean 判定 HTTP(S) 无凭据地址或单个 / 开头的站内路径。isSafeLinkUrl(value: string): boolean 判定 HTTP(S) 无凭据地址或 mailto 路径包含 @ 的地址;它不保证邮箱有效或可送达。两者拒绝首尾空白、控制字符、反斜杠及不允许的协议,返回布尔值,不创建资源、不发送请求、不替调用方改写地址。

可调用的公开辅助出口 ​

validateEditorDocument(value: unknown): asserts value is AsamEditorDocument 验证上述完整文档语法。合法输入正常返回,并使 TypeScript 在后续代码中收窄类型;非法输入抛 TypeError,消息以 AsamEditor 开头。它只验证,不改写输入,不返回修复后的文档。JSON.parse 的语法错误应另行处理。

下载示例的图片来源 ​

编辑器的图片模型只接收可访问的 HTTP(S) 或站内根路径,不接受内联 data/blob。两个插图示例默认使用公开的 HTTPS 图片,按钮明确标为“插入示例图片”,地址可改为消费项目已托管的资源。默认图片需要网络;单个 Demo.vue 不提供文件上传、资源托管或新的根路径接口。其他允许 data URL 的图片显示组件仍可使用内联 SVG。此说明不改变编辑器的公开安全规则。

更多参数与事件说明 ​

文档与资源边界 ​

节点支持 paragraph、heading、blockquote、bulletList、orderedList、listItem、codeBlock、horizontalRule、image,以及文本块中的 text、hardBreak。heading 的 level 为 1、2 或 3;列表包含以 paragraph 开始的 listItem;引用和列表不能为空。标记支持 bold、italic、strike、code、underline、link,link 的 attrs 只包含 href。运行时会拒绝未知字段、非法嵌套或资源地址;类型中的通用字符串字段不代表任意节点名都受支持。

参数与事件补充说明

参数与事件说明

modelValue

必填:是;声明来源:ASAM 声明。

modelValue 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

  • modelValue.type: "doc" — ASAM 声明

    枚举:"doc"

  • modelValue.content: readonly AsamEditorNode[] — ASAM 声明

    嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

editable

必填:否;声明来源:ASAM 声明。

editable 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
true(源码表达式;ASAM 声明)
disabled

必填:否;声明来源:ASAM 声明。

disabled 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:false / true

默认值与来源
false(源码表达式;ASAM 声明)
placeholder

必填:否;声明来源:ASAM 声明。

默认值与来源
'请输入内容'(源码表达式;ASAM 声明)
AsamEditorProps 公开类型视图
ts
import type { AsamEditorProps, AsamEditorDocument, AsamEditorNode, AsamEditorImageResource } from '@asam-ui/ui';

// AsamEditorProps
type PublicContract = {
	readonly "modelValue": AsamEditorDocument;
	readonly "editable"?: boolean | undefined;
	readonly "disabled"?: boolean | undefined;
	readonly "placeholder"?: string | undefined;
};

参数与事件说明

update:modelValue

必填:是;声明来源:ASAM 声明。

change

必填:是;声明来源:ASAM 声明。

AsamEditorEmits 公开类型视图
ts
import type { AsamEditorEmits, AsamEditorDocument } from '@asam-ui/ui';

// AsamEditorEmits
type PublicContract = {
	"update:modelValue": [document: AsamEditorDocument];
	"change": [document: AsamEditorDocument];
};

参数与事件说明

focus

必填:是;声明来源:ASAM 声明。

focus 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): void

blur

必填:是;声明来源:ASAM 声明。

blur 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): void

clear

必填:是;声明来源:ASAM 声明。

clear 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): void

insertImage

必填:是;声明来源:ASAM 声明。

insertImage 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(resource: AsamEditorImageResource): boolean

getHTML

必填:是;声明来源:ASAM 声明。

getHTML 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

事件参数:(): string

AsamEditorExpose 公开类型视图
ts
import type { AsamEditorExpose, AsamEditorImageResource } from '@asam-ui/ui';

// AsamEditorExpose
type PublicContract = {
	"focus": () => void;
	"blur": () => void;
	"clear": () => void;
	"insertImage": (resource: AsamEditorImageResource) => boolean;
	"getHTML": () => string;
};

组合契约按分支生效;请同时查看公开类型。

AsamEditorAttribute 公开类型视图
ts
import type { AsamEditorAttribute } from '@asam-ui/ui';

// AsamEditorAttribute
type PublicContract = AsamEditorAttribute;

参数与事件说明

type

必填:是;声明来源:ASAM 声明。

attrs

必填:否;声明来源:ASAM 声明。

AsamEditorMark 公开类型视图
ts
import type { AsamEditorMark, AsamEditorImageResource, AsamEditorAttribute } from '@asam-ui/ui';

// AsamEditorMark
type PublicContract = {
	readonly "type": string;
	readonly "attrs"?: Readonly<Record<string, AsamEditorAttribute>> | undefined;
};

参数与事件说明

type

必填:是;声明来源:ASAM 声明。

attrs

必填:否;声明来源:ASAM 声明。

content

必填:否;声明来源:ASAM 声明。

marks

必填:否;声明来源:ASAM 声明。

text

必填:否;声明来源:ASAM 声明。

AsamEditorNode 公开类型视图
ts
import type { AsamEditorNode, AsamEditorImageResource, AsamEditorAttribute, AsamEditorMark } from '@asam-ui/ui';

// AsamEditorNode
type PublicContract = {
	readonly "type": string;
	readonly "attrs"?: Readonly<Record<string, AsamEditorAttribute>> | undefined;
	readonly "content"?: readonly AsamEditorNode[] | undefined;
	readonly "marks"?: readonly AsamEditorMark[] | undefined;
	readonly "text"?: string | undefined;
};

参数与事件说明

type

必填:是;声明来源:ASAM 声明。

type 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"doc"

content

必填:是;声明来源:ASAM 声明。

content 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

AsamEditorDocument 公开类型视图
ts
import type { AsamEditorDocument, AsamEditorNode } from '@asam-ui/ui';

// AsamEditorDocument
type PublicContract = {
	readonly "type": "doc";
	readonly "content": readonly AsamEditorNode[];
};

参数与事件说明

src

必填:是;声明来源:ASAM 声明。

alt

必填:否;声明来源:ASAM 声明。

title

必填:否;声明来源:ASAM 声明。

AsamEditorImageResource 公开类型视图
ts
import type { AsamEditorImageResource } from '@asam-ui/ui';

// AsamEditorImageResource
type PublicContract = {
	readonly "src": string;
	readonly "alt"?: string | undefined;
	readonly "title"?: string | undefined;
};

参数与事件说明

type

必填:是;声明来源:ASAM 声明。

type 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

枚举:"doc"

content

必填:是;声明来源:ASAM 声明。

content 参数与事件数据

下列为声明可读视图;可导入类型以公开类型视图为准。分支条件与父属性一致。

嵌套展开边界:框架 / 平台类型;完整类型见公开类型视图。

EMPTY_EDITOR_DOCUMENT 公开类型视图
ts
export type EMPTY_EDITOR_DOCUMENT = AsamEditorDocument;
isSafeImageUrl 公开类型视图
ts
import type { AsamEditorImageResource } from '@asam-ui/ui';

export declare function isSafeImageUrl(value: string): boolean;
isSafeLinkUrl 公开类型视图
ts
import type { AsamEditorImageResource } from '@asam-ui/ui';

export declare function isSafeLinkUrl(value: string): boolean;
validateEditorDocument 公开类型视图
ts
import type { AsamEditorProps, AsamEditorDocument } from '@asam-ui/ui';

export declare function validateEditorDocument(value: unknown): asserts value is AsamEditorDocument;

搜索文档

Tab 选择结果 Enter 打开 Esc 关闭