You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于QuillJS的Primeng Editor自定义标记替换问题求助

解决QuillJS(PrimeNG Editor)中自定义占位符Blot的替换问题

嘿,我一眼就看出问题出在哪了——你用了BlockEmbed这种块级嵌入类型的Blot,但你的占位符是在行内文本里的啊!BlockEmbed会把整个内容当成一个独立块来处理,这就是为什么整段字符串都被塞进自定义Blot里的原因。咱们得把Blot改成行内类型,再配合精准的替换逻辑,就能搞定这个问题。

第一步:修正自定义Blot的继承关系

把BlockEmbed换成InlineEmbed(Quill内置的行内嵌入Blot),这样你的自定义变量Blot就是行内元素,不会把整段文本都包裹进去。

declare var Quill: any;
const InlineEmbed = Quill.import('blots/inline/embed');

export class Variable extends InlineEmbed {
  static blotName = 'variable';
  static tagName = 'span';
  static className = 'custom-variable';

  static create(value: { key: string }) {
    const node = super.create(value) as HTMLElement;
    // 给占位符加样式和标识属性
    node.textContent = `{{${value.key}}}`;
    node.setAttribute('data-variable', value.key);
    node.style.color = '#1890ff';
    node.style.fontWeight = 'bold';
    return node;
  }

  static value(node: HTMLElement) {
    return {
      key: node.getAttribute('data-variable') || ''
    };
  }
}

// 注册自定义Blot到Quill
Quill.register('formats/variable', Variable);

第二步:实现精准的占位符替换逻辑

接下来要写一个函数,逐个识别文本中的{{xxx}}占位符,把它们替换成自定义的variable Blot,而不是一次性处理整个字符串。

假设你已经通过PrimeNG Editor拿到了Quill实例:

import { Component, ViewChild } from '@angular/core';
import { Editor } from 'primeng/editor';

@Component({
  // 你的组件元数据
})
export class YourComponent {
  @ViewChild(Editor) editor!: Editor;
  originalText = 'User data {{userName}} - {{lastName}}. Topic {{title}} and date: {{occurredDate}}';

  ngAfterViewInit() {
    this.replacePlaceholdersWithBlots();
  }

  replacePlaceholdersWithBlots() {
    const quill = this.editor.quillInstance;
    // 先清空编辑器内容
    quill.setText('');
    
    // 用正则拆分文本,区分普通文本和占位符片段
    const placeholderRegex = /(\{{2}[\w]+\}{2})/g;
    const textParts = this.originalText.split(placeholderRegex);
    
    let currentIndex = 0;
    textParts.forEach(part => {
      if (placeholderRegex.test(part)) {
        // 处理占位符:提取key并插入自定义Blot
        const variableKey = part.replace(/[{}]/g, '');
        quill.insertEmbed(currentIndex, 'variable', { key: variableKey }, 'user');
        currentIndex += 1; // Blot在Quill中占一个长度单位
      } else {
        // 处理普通文本:直接插入编辑器
        quill.insertText(currentIndex, part, 'user');
        currentIndex += part.length;
      }
    });
  }
}

关键说明

  • 为什么用InlineEmbed:你的占位符是嵌在句子中间的行内元素,BlockEmbed会强制占一整行,还会把周围文本都包裹进去,完全不符合需求;而InlineEmbed能和普通文本共存于同一行。
  • 拆分替换逻辑:用正则把原始文本拆成普通文本和占位符片段,逐个插入编辑器,这样Quill就能准确区分哪些是普通文本,哪些是自定义Blot。
  • PrimeNG Editor实例获取:通过ViewChild拿到Editor组件后,访问quillInstance就能操作底层的Quill核心实例。

这样处理后,每个{{xxx}}都会被替换成独立的行内自定义Blot,再也不会把整个字符串都包裹进去啦!

内容的提问来源于stack exchange,提问作者antonyboom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:14:30