Добавление подсветки синтаксиса к входным данным в svelte

#svelte

Вопрос:

Я пытаюсь добавить чрезвычайно простую «подсветку синтаксиса» для ввода текста в svelte.

В принципе, я хочу выделить все во входных данных, которые соответствуют регулярному /{.*?}/ выражению, другим цветом, но я не могу понять, как это сделать.

мой последний эксперимент выглядит так

 <script>
  export let value;
  let editor;

  function update() {
    value = editor.textContent
  }
</script>

<div contenteditable="true"
bind:this={editor} on:input={update}>
  {#if value}
    {#each value.split(" ") as part, i}
      <span class={part.match(/{.*?}/gm) ? "text-nord-12" : "text-nord-4"}
        >{#if i !== 0}amp;nbsp;{/if}{part}</span
      >
    {/each}
  {/if}
</div>
 

и хотя это не идеально, это вроде как работает, за исключением того, что курсор время от времени сбрасывается при редактировании, что, я полагаю, связано с тем, что содержимое редактора заменяется при обновлении.

Итак, в принципе, есть ли какой-либо способ привязать текстовое значение, сохраняя при этом возможность динамического добавления/удаления html-тегов?

Я также могу отметить, что привязка textContent , похоже, работает либо потому, что она удаляет все выделения при монтировании… либо я просто делаю что-то не так с привязкой

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

1. Вы можете использовать html.replace(rex, replacerFunc) для замены совпадений rex с помощью функции замены. Эта функция замены может изменить ваше соответствие в чем-то вроде <mark class=»highlicht»>{сопоставленный текст}<mark class=»highlicht»></mark> Подробнее здесь: </mark> developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Ответ №1:

Решит ли это вашу проблему с помощью use:action, on:blur и заменителя?

При размытии вам нужно оставить (потерять фокус) div, чтобы отметить текст div, но курсор не будет прыгать при каждом нажатии клавиши.

Код и повторение: Выделите соответствующий текст в удобном для просмотра div с помощью svelte

 <script>
  let match = "svelte|input";  // pseudo rex
  let content = "Adding syntax highlight to an input in svelte using a svelte action";
  let editor;

  function updateContent() {
    if (editor) content = editor.textContent;
  }

  function marker(txt, rex) {
    function markTerm(term) {
      let cls = "red";
      return ` <mark class="no-clicks ${cls}">${term}</mark> `;
    }
    return txt.replace(rex, (term) => markTerm(term));
  }

  export function highlight(node, [val, text]) {
    function action() {
      console.log(text);
      if (text) node.innerHTML = marker(text, new RegExp(val, "g"));
    }
    action();
    return {
      update(obj) {
        [val, text] = obj;
        action();
      }
    };
  }
</script>

<div>
  <div contenteditable="true" use:highlight={[match, content]} 
    bind:this={editor} on:blur={updateContent} />
</div>

<style>
  :global(.red) {
    color: red;
  }
</style>