Utility

提取RichText

import React from "react";

const getRichTextPosition = (s: string, key: string) => {
  const values: { from: number; to: number; tag: string }[] = [];
  let searchStart = 0;
  const tagLeft = `<${key}>`;
  const tagRight = `</${key}>`;
  let tagStart = s.indexOf(tagLeft, searchStart);
  let tagEnd = s.indexOf(tagRight, searchStart);
  while (tagStart > -1 && tagEnd > -1) {
    searchStart = tagStart + tagLeft.length;
    values.push({
      from: searchStart,
      to: tagEnd,
      tag: key
    });
    searchStart = tagEnd + tagRight.length;
    tagStart = s.indexOf(tagLeft, searchStart);
    tagEnd = s.indexOf(tagRight, searchStart);
  }
  return values;
};

export default function App() {
  const t = (
    s: string,
    richOptions?: Record<string, (value: string) => React.ReactNode>
  ) => {
    if (richOptions) {
      let isNested = false;
      const results: React.ReactNode[] = [];
      let positions: { from: number; to: number; tag: string }[] = [];
      const optionKeys = Object.keys(richOptions);
      if (optionKeys.length > 1) {
        optionKeys.forEach((key: string) => {
          positions = positions.concat(getRichTextPosition(s, key));
        });
        positions.sort((a, b) => a.from - b.from);
      } else {
        positions = getRichTextPosition(s, optionKeys[0]);
      }
      let start = 0;
      positions.forEach((position) => {
        if (start > position.from) {
          isNested = true;
        }
        results.push(
          s.substring(start, position.from - (position.tag.length + 2))
        );
        results.push(
          richOptions[position.tag](s.substring(position.from, position.to))
        );
        start = position.to + (position.tag.length + 3);
      });
      results.push(s.substring(start));
      if (isNested && process.env.NODE_ENV !== "production") {
        throw new Error(`[Localization] - "${s}" includes nest tag`);
      }
      return results;
    }
    return s;
  };

  const str = "aaa<strong>你好张三</strong><t>,欢迎来到你好啊</t>ggggg<strong>这里武汉</strong>gggg";

  const node = t(str, {
    strong: (value: string) => (
      <strong style={{ color: "red" }}>{value}</strong>
    ),
    t: (value: string) => (
      <strong style={{ color: "green" }}>{value}</strong>
    )
  });

  return (
    <div className="App">
      {node}
    </div>
  );
}