通过使用Typescript匹配Char开头和结尾来放置文本叠加

时间:2018-06-05 19:06:12

标签: css typescript overlay

我使用this简单库来创建文本叠加层,如下所示

enter image description here

匹配文字,将css叠加在上面:

new Textoverlay(document.getElementById("textarea"), [
  {
    match: /\B@\w+/g,
    css: { "background-color": "#d8dfea" }
  },
  {
    match: /e\w{8}d/g,
    css: { "background-color": "#cc9393" }
  }
]);

这是使用基于Regex的方法:

export interface Matcher {
  lastIndex: number;
  exec: (input: string) => null | [string] | RegExpExecArray;
}

作为匹配策略:

export interface Strategy {
  match: Matcher;
  css: CssStyle;
}

这没关系,但我需要不同的东西,我无法摆脱。在我的情况下,我需要匹配文本中的标记列表,我已经在输入文档中使用char begin和end offset,如:

[
{
   "text": "hello",
   "charBegin": 0,
   "charEnd": 4
},
{
   "text": "how",
   "charBegin": 6,
   "charEnd": 8
} ,
{
   "text": "are",
   "charBegin": 9,
   "charEnd": 11
}
]

所以我的情况是这种方法就像

一样
new Textoverlay(textarea, [
        {
            match: [0,4],
            css: { 'background-color': '#d8dfea' },
        },
        {
            match: [6,8],
            css: { 'background-color': '#cc9393' },
        },
        {
            match: [9,11],
            css: { 'background-color': '#ddd' },
        }
    ]);

所以喜欢使用基于范围的匹配器,因为有些用户建议我喜欢

export class RangeMatcher {
  public start: number;
  public end: number;
  public lastIndex: number;

  constructor(start: number, end: number) {
    this.start = start;
    this.end = end;
    this.lastIndex = -1;
  }

  public exec(text: string) {
    if (this.lastIndex !== -1) {
      this.lastIndex = -1;
      return null;
    }
    this.lastIndex = this.start;
    return [text.slice(this.start, this.end)];
  }
}

问题是我无法摆脱文本节点解析here

private computeOverlayNodes(): Node[] {
    return this.strategies.reduce((ns: Node[], strategy) => {
      const highlight = document.createElement('span');
      setStyle(highlight, strategy.css);
      return Array.prototype.concat.apply([], ns.map((node) => {
        if (node.nodeType !== Node.TEXT_NODE) {
          return node;
        }
        const text = node.textContent || '';
        const resp = [];
        while (true) {
          const prevIndex = strategy.match.lastIndex;
          const match = strategy.match.exec(text);
          if (!match) {
            resp.push(document.createTextNode(text.slice(prevIndex)));
            break;
          }
          const str = match[0];
          resp.push(document.createTextNode(
              text.slice(prevIndex, strategy.match.lastIndex - str.length)));
          const span = highlight.cloneNode();
          span.textContent = str;
          resp.push(span);
        }
        return resp;
      }));
    }, [document.createTextNode(this.textarea.value)]);
  }

因为在这个方法中我没有文档中文本节点的绝对位置,节点本身会累积前面的文本。

0 个答案:

没有答案