DEV Community

Pranom Vignesh
Pranom Vignesh

Posted on

5 2

Restrict Editable Area in Monaco Editor - Part 2

Table of contents

Intro

This post is continuation of the previous post, which you can see here

What's new?

This time granular editing is made possible by giving set of instructions to the script, which then creates a regex in runtime to validate the output

Process is simple; if regex is matched , output will be left as such, if not then content will be set to its previous state (undo operation)

Demo - click here

Demo of Playground

Instructions

There are 2 types of instructions that can provided to the script

  • editableArea - space defined to edit a portion of single line
  • multiLineEditableArea - space defined to edit multiple lines

Fallback Content

This content can be given as so that when the output is rendered default content will be present in place of the editable area comment

eg : /* editableArea=fallbackContent */

ID

This id can be used to reference the output and whenever the editor content changes, a mapping object is generated

eg : /* editableArea#id */

This fallback content and id is applicable for both single line and multiline editable

Thus, places other than the editable area are not allowed to be edited by the user

Under the hood

function restrictEditArea (value) {
    const editable = (() => {
        const regexObjects = {};
        const labels = [];
        const generateRegexUsing = (label, consumeSpace = false) => new RegExp((consumeSpace?"\\^\\s*":"")+"\\/\\*\\s*(" + label + ")(#([^#]+?))?\\s*(=\\s*(.+?))?\\s*\\*\\/"+(consumeSpace?"\\s*\\$"+"\\"+"\\n":""), "g")
        return {
            add: (name, label, regexReplacer, { consumeSpace } = {}) => {
                regexObjects[name] = {
                    valueRegex : generateRegexUsing(label),
                    regex: generateRegexUsing(label, consumeSpace),
                    idIndex: 3,
                    fallbackContentIndex: 5,
                    regexReplacer: regexReplacer
                }
                labels.indexOf(label) === -1 && labels.push(label);
                return regexObjects[name];
            },
            getAll: () => regexObjects,
            getIdReplacerRegex: () => generateRegexUsing(labels.join('|'))
        }
    })();
    editable.add('singleLine', 'editableArea', '(.*?)')
    editable.add('multiLine', 'multiLineEditableArea', '(^.*?$\\n)*', { consumeSpace: true })
    const generateRegexFromValue = (string, {
        singleLine,
        multiLine
    }, idReplacer) => {
        let valueToSet = string;
        let regexString = string;
        let map = {};
        let matchCount = 0;
        const regexFor = {
            brackets: /(\(|\)|\{|\}|\[|\])/g,
            newLine: /\n/g,
            blankSpace: /\s/g
        }
        valueToSet = valueToSet.replace(singleLine.valueRegex, "$" + singleLine.fallbackContentIndex)
        valueToSet = valueToSet.replace(multiLine.valueRegex, "$" + multiLine.fallbackContentIndex)
        regexString = regexString.replace(regexFor.brackets, '\\$1'); //! This order matters
        regexString = '^'+regexString.split(regexFor.newLine).join('$\\n^')+'$';
        regexString = regexString.replace(singleLine.regex, singleLine.regexReplacer)
        regexString = regexString.replace(multiLine.regex, multiLine.regexReplacer)
        string.replace(idReplacer, function (...matches) {
            map[matchCount++] = matches[3];
        })
        return {
            valueToSet: valueToSet,
            regexForValidation: new RegExp(regexString, 'm'),
            map: map
        }
    }
    return generateRegexFromValue(value, editable.getAll(), editable.getIdReplacerRegex())
}
Enter fullscreen mode Exit fullscreen mode

This can be a workaround to solve this issue

Provide ability to block editing specific lines #953

sinaa avatar
sinaa posted on

Monaco is a great editor for providing programmatic interfaces for users to an application.

One feature that'd significantly help with the user experience is to make specific lines read-only, such that user can enter their code within a specific block (e.g., between a function block).

Would it be possible to include this as a core features/API of the editor?

Future ideas

Will try to publish this as an npm package so that it will be accessible for everyone

Actual Code available in

GitHub logo Pranomvignesh / constrained-editor-plugin

This project is to restrict the editable area in the monaco-editor

Top comments (0)

Image of AssemblyAI

Automatic Speech Recognition with AssemblyAI

Experience near-human accuracy, low-latency performance, and advanced Speech AI capabilities with AssemblyAI's Speech-to-Text API. Sign up today and get $50 in API credit. No credit card required.

Try the API

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay