1

My problem consists of two parts actually. I am getting the editor content by using getValue(). This returns the raw text from the Monaco editor. Suppose I want to append new code after a specific code block. Then how do I achieve this.

I can get currentPosition() and it returns the current cursor location just fine. But how do I get the location specifically for a code block and insert new code after that. For example I can get code from the editor like this.

<body>
    <div>Big brown fox jumps at lazy dog.</div>

    <!-- I WANT TO ADD CODE HERE PROGRAMMATICALLY -->

    <p>we have all the details for singleton methods.</p>
    <div>new data comes here.</div>
</body>

How can I add code between two code blocks. The only solution that comes to my mind is if I could get positions/line locations along with the code by getValue. And later on use those pointers to add new blocks in the code. But I could not find any helpful solution yet.

Imjaad
  • 588
  • 3
  • 12

1 Answers1

1

I created two functions below that will insert HTML content inside the editor:

  • computeInsertRange – Compute the editor range to replace the placeholder
  • insertContent – Insert content within the editor at a specified line (pattern)

In the example below, after 1 second, the HTML inside the editor will update.

require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs' }});
window.MonacoEnvironment = { getWorkerUrl: () => proxy };

let proxy = URL.createObjectURL(new Blob([`
    self.MonacoEnvironment = {
        baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min'
    };
    importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/base/worker/workerMain.min.js');
`], { type: 'text/javascript' }));

const
  container = document.querySelector('#container'),
  htmlContent = `
<body>
  <div>Big brown fox jumps at lazy dog.</div>

  <!-- I WANT TO ADD CODE HERE PROGRAMMATICALLY -->

  <p>we have all the details for singleton methods.</p>
  <div>new data comes here.</div>
</body>
`.trim(),
  additionalHtmlContent = `
  <div>
    <strong>Hello World!</strong>
  </div>
`.trim();

const computeInsertRange = (editor, pattern) => {
  const lines = editor.getValue().split('\n');
  for (let index = 0; index < lines.length; index++) {
    if (lines[index].match(pattern)) {
      const indent = /^\s*/.exec(lines[index])?.[0].length ?? 0;
      return new monaco.Range(index + 1, indent + 1, index + 1, lines[index].length + 1);
    }
  }
  return null;
};

// Adapted from: https://stackoverflow.com/a/48764277/1762224
const insertContent = (editor, pattern, content) => {
  editor.executeEdits('my-source', [{
    identifier: { major: 1, minor: 1 },
    range: computeInsertRange(editor, pattern),
    text: content,
    forceMoveMarkers: true
  }]);
};

require(['vs/editor/editor.main'], function () {
  const editor = monaco.editor.create(container, {
    value: htmlContent,
    language: 'html',
    theme: 'vs-dark'
  });

  setTimeout(() => {
    insertContent(editor, /<!-- .+ -->/, additionalHtmlContent);
  }, 1000);
});
html, body, #container {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
<script src="https://unpkg.com/monaco-editor@0.8.3/min/vs/loader.js"></script>
<div id="container"></div>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132