关于 umbraco-tiptap-statusbar-extension
用于构建 Umbraco Tiptap 状态栏扩展的技能,可在编辑器中显示信息。它指导开发者查阅最新文档、创建清单与元素,并说明测试方式。
主要功能
- 01状态栏扩展指导
- 02清单与元素示例
- 03访问编辑器上下文和事件
- 04优先查阅文档的工作流
适用场景
- 01显示字数或字符数
- 02呈现元素路径导航
- 03跟踪光标位置或编辑器状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ umbraco/ umbraco-cms-backoffice-skills --skill umbraco-tiptap-statusbar-extension安装后在 Claude Code 中输入/umbraco-tiptap-statusbar-extension确认已加载。
详细介绍
Umbraco Tiptap 状态栏扩展
这是什么?
Tiptap 状态栏扩展会在富文本编辑器底部的状态栏中添加组件。常见用途包括显示元素路径(面包屑导航)、字数、字符数或其他编辑器状态信息。与工具栏扩展不同,状态栏扩展纯粹用于显示信息。
文档
实现前请务必获取最新文档:
- 扩展类型:https://docs.umbraco.com/umbraco-cms/extend-your-project/backoffice-extensions/extending-overview/extension-types
- 富文本编辑器:https://docs.umbraco.com/umbraco-cms/model-your-content/property-editors/built-in-umbraco-property-editors/rich-text-editor
- Tiptap 文档:https://tiptap.dev/docs/editor/extensions/overview
- 基础:https://docs.umbraco.com/umbraco-cms/extend-your-project/backoffice-extensions/foundation
相关技能
-
Tiptap 扩展:用于添加编辑器功能
- 参考技能:
umbraco-tiptap-extension
- 参考技能:
-
Umbraco 元素:用于实现状态栏元素
- 参考技能:
umbraco-umbraco-element
- 参考技能:
-
上下文 API:用于访问 Tiptap RTE 上下文
- 参考技能:
umbraco-context-api
- 参考技能:
工作流
- 获取文档 - 对上述 URL 使用 WebFetch
- 提出问题 - 要显示哪些信息?是否需要实时更新?
- 生成文件 - 根据最新文档创建清单和元素
- 说明 - 展示已创建的内容以及如何测试
最简示例
清单(manifests.ts)
import type { ManifestTiptapStatusbarExtension } from '@umbraco-cms/backoffice/extension-registry';
const manifest: ManifestTiptapStatusbarExtension = {
type: 'tiptapStatusbarExtension',
alias: 'My.TiptapStatusbar.WordCount',
name: 'Word Count Statusbar',
element: () => import('./word-count.statusbar-element.js'),
forExtensions: [], // Optional: link to specific tiptap extensions
meta: {
alias: 'wordCount',
icon: 'icon-document',
label: 'Word Count',
},
};
export const manifests = [manifest];
状态栏元素(word-count.statusbar-element.ts)
import { html, css, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_TIPTAP_RTE_CONTEXT } from '@umbraco-cms/backoffice/tiptap';
@customElement('my-word-count-statusbar')
export class WordCountStatusbarElement extends UmbLitElement {
@state()
private _wordCount = 0;
@state()
private _charCount = 0;
constructor() {
super();
this.consumeContext(UMB_TIPTAP_RTE_CONTEXT, (context) => {
this.observe(context.editor, (editor) => {
if (editor) {
// Update counts when editor content changes
editor.on('update', () => this.#updateCounts(editor));
// Initial count
this.#updateCounts(editor);
}
});
});
}
#updateCounts(editor: any) {
const text = editor.getText();
this._charCount = text.length;
this._wordCount = text.trim() ? text.trim().split(/\s+/).length : 0;
}
render() {
return html`
<span class="count">Words: ${this._wordCount}</span>
<span class="count">Characters: ${this._charCount}</span>
`;
}
static styles = css`
:host {
display: flex;
gap: var(--uui-size-space-4);
font-size: var(--uui-type-small-size);
color: var(--uui-color-text-alt);
}
.count {
padding: 0 var(--uui-size-space-2);
}
`;
}
export default WordCountStatusbarElement;
declare global {
interface HTMLElementTagNameMap {
'my-word-count-statusbar': WordCountStatusbarElement;
}
}
元素路径状态栏(面包屑导航)
import { html, css, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_TIPTAP_RTE_CONTEXT } from '@umbraco-cms/backoffice/tiptap';
@customElement('my-element-path-statusbar')
export class ElementPathStatusbarElement extends UmbLitElement {
@state()
private _path: string[] = [];
constructor() {
super();
this.consumeContext(UMB_TIPTAP_RTE_CONTEXT, (context) => {
this.observe(context.editor, (editor) => {
if (editor) {
editor.on('selectionUpdate', () => this.#updatePath(editor));
this.#updatePath(editor);
}
});
});
}
#updatePath(editor: any) {
const { $from } = editor.state.selection;
const path: string[] = [];
for (let depth = $from.depth; depth > 0; depth--) {
const node = $from.node(depth);
path.unshift(node.type.name);
}
this._path = path;
}
#handleClick(index: number) {
// Could implement navigation to that element
console.log('Navigate to:', this._path[index]);
}
render() {
return html`
${this._path.map(
(name, index) => html`
${index > 0 ? html`<span class="separator">›</span>` : ''}
<button @click=${() => this.#handleClick(index)}>${name}</button>
`
)}
`;
}
static styles = css`
:host {
display: flex;
align-items: center;
font-size: var(--uui-type-small-size);
}
button {
background: none;
border: none;
padding: var(--uui-size-space-1) var(--uui-size-space-2);
cursor: pointer;
color: var(--uui-color-text-alt);
}
button:hover {
color: var(--uui-color-text);
text-decoration: underline;
}
.separator {
color: var(--uui-color-border);
margin: 0 var(--uui-size-space-1);
}
`;
}
export default ElementPathStatusbarElement;
光标位置状态栏
import { html, css, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_TIPTAP_RTE_CONTEXT } from '@umbraco-cms/backoffice/tiptap';
@customElement('my-cursor-position-statusbar')
export class CursorPositionStatusbarElement extends UmbLitElement {
@state()
private _line = 1;
@state()
private _column = 1;
constructor() {
super();
this.consumeContext(UMB_TIPTAP_RTE_CONTEXT, (context) => {
this.observe(context.editor, (editor) => {
if (editor) {
editor.on('selectionUpdate', () => this.#updatePosition(editor));
}
});
});
}
#updatePosition(editor: any) {
const { from } = editor.state.selection;
// Simplified line/column calculation
const doc = editor.state.doc;
let pos = 0;
let line = 1;
doc.descendants((node: any, nodePos: number) => {
if (nodePos >= from) return false;
if (node.isBlock) line++;
return true;
});
this._line = line;
this._column = from - pos;
}
render() {
return html`
<span>Ln ${this._line}, Col ${this._column}</span>
`;
}
static styles = css`
:host {
font-size: var(--uui-type-small-size);
color: var(--uui-color-text-alt);
}
`;
}
export default CursorPositionStatusbarElement;
元属性
| 属性 | 描述 |
|---|---|
alias | 状态栏项的唯一标识符 |
icon | 图标(用于配置界面) |
label | 显示名称 |
访问编辑器上下文
使用 UMB_TIPTAP_RTE_CONTEXT 访问 Tiptap 编辑器实例,并订阅以下事件:
update- 内容已更改selectionUpdate- 光标/选区已更改focus/blur- 焦点状态已更改
就是这样!请始终获取最新文档,保持示例精简,并生成完整可运行的代码。
评论
支持 Markdown