当 contenteditible=true 并使用 highlight.js 时,将光标放在 <pre> 的末尾

Place cursor at the end of <pre> when contenteditible=true and using highlight.js

我正在使用 highlight.js 自动突出显示 <pre> 元素中的代码。我正在尝试在键入时启用实时语法突出显示。我现在的代码可以按预期工作,并且突出显示确实可以在回车 return 上工作,但光标会移动到 <pre> 元素的开头。我想在 keyup 事件检测到回车 return 后将光标移动到末尾,然后重新处理该元素以添加语法突出显示。我怎样才能做到这一点?

示例位于此处:https://tools.peer.ooo/snippity

但是我在相关部分使用的代码是这样的:

document.addEventListener("keyup", function(e){
    if(e.keyCode == 13){
        document.querySelectorAll('pre').forEach((block) => {
            hljs.highlightBlock(block);

        })
    }
})

如何将光标放在现有输入的末尾?

代码片段

  document.addEventListener('DOMContentLoaded', async () => {
    document.querySelectorAll('pre').forEach((block) => {
      hljs.highlightBlock(block);
      block.classList.add("container")
    })
  })
  var db = new Dexie("snippits");
  db.version(1).stores({
    snippits: "++id, identifier, name, data, *tags"
  });

  document.getElementById("save").addEventListener("click", function() {

    let name = document.getElementById("snipname").value
    let data = document.getElementById("rendered").textContent
    db.snippits.add({
      identifier: "some id",
      name: name,
      data: data
    })
    document.querySelectorAll('pre').forEach((block) => {
      hljs.highlightBlock(block);
    })

  })

  document.getElementById("rendered").addEventListener("blur", function(e) {
    console.log("tabbed out")
    document.querySelectorAll('pre').forEach((block) => {
      hljs.highlightBlock(block);
    })
  })

  document.addEventListener('DOMContentLoaded', async () => {
    const data = await db.snippits.orderBy('id').last()

    console.log(JSON.stringify(data))
    document.getElementById("snipname").value = data.name
    document.getElementById("rendered").textContent = data.data
    document.querySelectorAll('pre').forEach((block) => {
      hljs.highlightBlock(block);
    })
  })

  function onPaste(e) {
    e.preventDefault(); // stop the paste
    const t = e.clipboardData.getData("text"); // grab the pasted content as plain text
    e.target.textContent = t; // set the element's innerHTML to the plain text
    document.querySelectorAll('pre').forEach((block) => {
      hljs.highlightBlock(block);
    })
  }

  document.addEventListener("keyup", function(e) {
    if (e.keyCode == 13) {
      document.querySelectorAll('pre').forEach((block) => {
        hljs.highlightBlock(block);
      })
    }
  })

  const paste = document.getElementById('rendered');
  paste.addEventListener('paste', onPaste);
 html {
    background: rgb(58, 58, 63)
  }

  pre {
    outline: none;
    min-height: 100px;
  }

  input {
    outline: none;
  }

  textarea {
    outline: none;
  }

  /* Comment */
  .hljs-comment,
  .hljs-quote {
    color: #989498;
  }

  /* Red */
  .hljs-variable,
  .hljs-template-variable,
  .hljs-attribute,
  .hljs-tag,
  .hljs-name,
  .hljs-selector-id,
  .hljs-selector-class,
  .hljs-regexp,
  .hljs-link,
  .hljs-deletion {
    color: #dd464c;
  }

  /* Orange */
  .hljs-number,
  .hljs-built_in,
  .hljs-builtin-name,
  .hljs-literal,
  .hljs-type,
  .hljs-params {
    color: #fd8b19;
  }

  /* Yellow */
  .hljs-class .hljs-title {
    color: #fdcc59;
  }

  /* Green */
  .hljs-string,
  .hljs-symbol,
  .hljs-bullet,
  .hljs-addition {
    color: #8fc13e;
  }

  /* Aqua */
  .hljs-meta {
    color: #149b93;
  }

  /* Blue */
  .hljs-function,
  .hljs-section,
  .hljs-title {
    color: #1290bf;
  }

  /* Purple */
  .hljs-keyword,
  .hljs-selector-tag {
    color: #c85e7c;
  }

  .hljs {
    display: block;
    overflow-x: auto;
    background: #322931;
    color: #b9b5b8;
    padding: 0.5em;
  }

  .hljs-emphasis {
    font-style: italic;
  }

  .hljs-strong {
    font-weight: bold;
  }
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.0/css/bulma.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.1.2/build/styles/default.min.css">
  <script src="https://cdn.jsdelivr.net/npm/dexie@3.0.2/dist/dexie.min.js"></script>
  <script src="https://chr15m.github.io/bugout/bugout.min.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.1.2/build/highlight.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>

<section class="section container">
    <input class="input" id="name" placeholder="Search . . ."></input>
    <div id="results" class="container"></div>
    <pre class="containe" id="rendered" contenteditable="true" spellcheck="false"></pre>
    <div class="field is-grouped">
      <input class="input" id="snipname" placeholder="Snippit name . . ."></input>
      <button class="button" id="save">Save</button>
      <button class="button" id="delete">Delete</button>
      <button class="button" id="share">Share</button>
    </div>
    <textarea class="textarea" id="notes" placeholder="Notes . . ."></textarea>
  </section>

这个怎么样?

document.addEventListener('DOMContentLoaded', async() => {
  document.querySelectorAll('pre').forEach((block) => {
    hljs.highlightBlock(block);
    block.classList.add("container")
  })
})
var db = new Dexie("snippits");
db.version(1).stores({
  snippits: "++id, identifier, name, data, *tags"
});

document.getElementById("save").addEventListener("click", function() {

  let name = document.getElementById("snipname").value
  let data = document.getElementById("rendered").textContent
  db.snippits.add({
    identifier: "some id",
    name: name,
    data: data
  })
  document.querySelectorAll('pre').forEach((block) => {
    hljs.highlightBlock(block);
  })

})

document.getElementById("rendered").addEventListener("blur", function(e) {
  console.log("tabbed out")
  document.querySelectorAll('pre').forEach((block) => {
    hljs.highlightBlock(block);
  })
})

document.addEventListener('DOMContentLoaded', async() => {
  const data = await db.snippits.orderBy('id').last()

  console.log(JSON.stringify(data))
  document.getElementById("snipname").value = data.name
  document.getElementById("rendered").textContent = data.data
  document.querySelectorAll('pre').forEach((block) => {

    hljs.highlightBlock(block);
  })
})

function onPaste(e) {
  e.preventDefault(); // stop the paste
  const t = e.clipboardData.getData("text"); // grab the pasted content as plain text
  e.target.textContent = t; // set the element's innerHTML to the plain text
  document.querySelectorAll('pre').forEach((block) => {
    hljs.highlightBlock(block);
  })
}

const editerElem = document.querySelector('#code-snippet')
editerElem.addEventListener('keyup', (evt) => {
   const val = evt.target.value;
   const outputPre = document.querySelector('#output')
   const output =  hljs.highlightAuto(val);
   outputPre.innerHTML = output.value;
})
/*
document.addEventListener("keyup", function(e) {
  if (e.keyCode == 13) {
    document.querySelector('pre')
      .forEach((block) => {
      const output = hljs.highlightBlock(block);
      block.focus();
    })
  }
})
*/
const paste = document.getElementById('rendered');
paste.addEventListener('paste', onPaste);
html {
  background: rgb(58, 58, 63)
}

#the-code-editor {
  display: flex;
  flex-direction: row;
}
#the-code-editor textarea, #the-code-editor pre {
  display: block;
  width: 50%;
}
pre {
  outline: none;
  min-height: 100px;
}

input {
  outline: none;
}

textarea {
  outline: none;
}


/* Comment */

.hljs-comment,
.hljs-quote {
  color: #989498;
}


/* Red */

.hljs-variable,
.hljs-template-variable,
.hljs-attribute,
.hljs-tag,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-regexp,
.hljs-link,
.hljs-deletion {
  color: #dd464c;
}


/* Orange */

.hljs-number,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params {
  color: #fd8b19;
}


/* Yellow */

.hljs-class .hljs-title {
  color: #fdcc59;
}


/* Green */

.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition {
  color: #8fc13e;
}


/* Aqua */

.hljs-meta {
  color: #149b93;
}


/* Blue */

.hljs-function,
.hljs-section,
.hljs-title {
  color: #1290bf;
}


/* Purple */

.hljs-keyword,
.hljs-selector-tag {
  color: #c85e7c;
}

.hljs {
  display: block;
  overflow-x: auto;
  background: #322931;
  color: #b9b5b8;
  padding: 0.5em;
}

.hljs-emphasis {
  font-style: italic;
}

.hljs-strong {
  font-weight: bold;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.0/css/bulma.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.1.2/build/styles/default.min.css">
<script src="https://cdn.jsdelivr.net/npm/dexie@3.0.2/dist/dexie.min.js"></script>
<script src="https://chr15m.github.io/bugout/bugout.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@10.1.2/build/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>

<section class="section container">
  <input class="input" id="name" placeholder="Search . . ."></input>
  <div id="results" class="container"></div>
  <label>The Next Gen Code Editor :</label>
  <br/ >
  <div id="the-code-editor">
      <textarea rows="5" id="code-snippet"></textarea>
      <pre id="output"></pre>
  </div>
  <br />
  <pre class="containe" id="rendered" contenteditable="true" spellcheck="false"></pre>
  <div class="field is-grouped">
    <input class="input" id="snipname" placeholder="Snippit name . . ."></input>
    <button class="button" id="save">Save</button>
    <button class="button" id="delete">Delete</button>
    <button class="button" id="share">Share</button>
  </div>
  <textarea class="textarea" id="notes" placeholder="Notes . . ."></textarea>
</section>

祝你好运...