将语法高亮添加到 svelte 中的输入

Adding syntax highlight to an input in 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}&nbsp;{/if}{part}</span
      >
    {/each}
  {/if}
</div>

虽然它并不完美,但它可以正常工作,除了在编辑时光标会不时重置,我认为这是因为编辑器内容在更新时被替换了。

所以基本上有什么方法可以绑定文本值,同时仍然能够动态地 add/remove html 标签?

我还注意到绑定 textContent 似乎确实有效,因为它在安装时删除了所有突出显示......或者我可能只是在绑定

上做错了什么

这会使用 use:action、on:blur 和替代品解决您的问题吗?

使用模糊,您必须离开(失去焦点)div 以标记 div 文本,但光标会在每次击键时跳转。

代码和回复:Highlight matched text in a contenteditable div with 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>