Как вставить ссылку для хэштегов и упоминаний в react quill?

#reactjs #react-quill

Вопрос:

Я использую react quill в качестве текстового редактора, и я использовал quill mention для добавления хэштегов и упоминаний людей в редакторе. Я просмотрел документы quill mention, но нет примера добавления ссылок на вставленный «хэштег» или «упоминание».

Для добавления ссылки есть prop, «linkTarget», но нет примера добавления ссылки к хэштегу и упоминанию.

Хэш-значения и atvalues из базы данных:

 hashvalues:[{
id:1,
value:"newHashtag"
}]

atvalues:[{
id:1,
value:"Jhon"
}]
 

Итак, мой ожидаемый результат:
для хэштега:

 <a href:`/#/hashtags/${id}`>#{value}</a>
 

для упоминания людей:

 <a href:`/#/people/${id}`>@{value}</a>
 

Вот мой код для текстового редактора и модуля упоминания:

 import React, { useEffect, useState } from "react";
import ReactQuill, { Quill } from "react-quill";
import * as Emoji from "quill-emoji";
import "react-quill/dist/quill.snow.css";
import "quill-emoji/dist/quill-emoji.css";
import "quill-mention/dist/quill.mention.css";
import "quill-mention";

//Add https to link if https is not present
const Link = Quill.import("formats/link");
Link.sanitize = function (url) {
  // quill by default creates relative links if scheme is missing.
  if (!url.startsWith("http://") amp;amp; !url.startsWith("https://")) {
    return `http://${url}`;
  }
  return url;
};
Quill.register(Link, true);
Quill.register("modules/emoji", Emoji);

// Add sizes to whitelist and register them
const Size = Quill.import("formats/size");
Size.whitelist = ["extra-small", "small", "medium", "large"];
Quill.register(Size, true);

// Add fonts to whitelist and register them
const Font = Quill.import("formats/font");
Font.whitelist = [
  "arial",
  "comic-sans",
  "courier-new",
  "georgia",
  "helvetica",
  "lucida",
];
Quill.register(Font, true);

let atValues = [];
let hashValues = [];


const mention = {
  allowedChars: /^[A-Za-zsÅÄÖåäö]*$/,
  mentionDenotationChars: ["@", "#"],
  linkTarget:"https://www.google.com",
  source: function (searchTerm, renderList, mentionChar, ) {
    let values;

    if (mentionChar === "@") {
      values = atValues;
    } else {
      values = hashValues;
    }

    if (searchTerm.length === 0) {
      renderList(values, searchTerm);
    } else {
      const matches = [];
      for (let i = 0; i < values.length; i  )
        if (~values[i].value.toLowerCase().indexOf(searchTerm.toLowerCase()))
          matches.push(values[i]);
      renderList(matches, searchTerm);
    }
  },
};

function Editor(props) {
  const [editorHtml, setEditorHtml] = useState("");

  const handleChange = (html) => {
    setEditorHtml(html);
    props.changeHandler(html);
  };

  useEffect(() => {
    if (props.value) {
      setEditorHtml(props.value);
    } else {
      setEditorHtml("");
    }
    if(props.values){
      let hash=props.values
      hash.map((v) => {
        v["value"] = v["display"]
      })
      hashValues=hash
    }
    if(props.people){
      let peoples = props.people
      peoples.map((v) => {
        v["value"] = v["display"]
      })
      atValues=peoples
    }
  }, [props.value]);

  return (
    <div>
      <ReactQuill
        onChange={handleChange}
        value={editorHtml}
        modules={modules}
        formats={formats}
        bounds={".app"}
        placeholder={props.placeholder}
      />
    </div>
  );
}

const modules = {
  toolbar: [
    [{ header: [1, 2, 3, 4, 5, 6, false] }],

    [{ list: "ordered" }, { list: "bullet" }],
    ["bold", "italic", "underline"],
    [{ color: [] }, { background: [] }],
    // [{ script: 'sub' }, { script: 'super' }],
    [{ align: [] }],
    ["link", "blockquote", "emoji"],
    ["clean"],
  ],
  clipboard: {
    // toggle to add extra line breaks when pasting HTML:
    matchVisual: false,
  },
  mention,
  "emoji-toolbar": true,
  "emoji-textarea": false,
  "emoji-shortname": true,
};

const formats = [
  "header",
  "font",
  "size",
  "bold",
  "italic",
  "underline",
  "strike",
  "blockquote",
  "list",
  "bullet",
  "indent",
  "link",
  "mention",
  "emoji",
];

export default function EMTextArea({
  placeHolder,
  name,
  value,
  changeHandler,
  hash,
  peopleMention
}) {
  return (
    <div className="custom-toolbar-example">
      <Editor
        placeholder={placeHolder}
        name={name}
        value={value}
        changeHandler={changeHandler}
        values={hash}
        people={peopleMention}
      />
    </div>
  );
}
 

Как я могу этого добиться?
Спасибо!

Ответ №1:

Я решил это, мне пришлось добавить ключ «link» в массив объектов atvalues и hashvalues.

Новые хэш-значения:

 hashvalues:[{
id:1,
value:"hashtag",
link:"/#/users/hashtags/1"}]
 

И в модуле упоминания:

 const mention = {
  allowedChars: /^[A-Za-zsÅÄÖåäö]*$/,
  mentionDenotationChars: ["@", "#"],
  linkTarget: '_self',
  source: function (searchTerm, renderList, mentionChar, ) {
    let values;

    if (mentionChar === "@") {
      values = atValues;
    } else {
      values = hashValues;
    }

    if (searchTerm.length === 0) {
      renderList(values, searchTerm);
    } else {
      const matches = [];
      for (let i = 0; i < values.length; i  )
        if (~values[i].value.toLowerCase().indexOf(searchTerm.toLowerCase()))
          matches.push(values[i]);
      renderList(matches, searchTerm);
    }
  },
};
 

В любом случае, спасибо.

Комментарии:

1. Как вы думаете, вы можете помочь мне с этой функцией? Я пытаюсь реализовать это в своем приложении, но это вызывает проблемы. Я также использую NextJS….