DEV Community

Ritish Shelke
Ritish Shelke

Posted on

Simple Method to Block Copy and Paste in Monaco Editor with React

Monaco Editor, the code editor that powers Visual Studio Code, is a powerful tool for developers, providing a rich set of features and customization options. However, there might be situations where you want to disable the copy-paste functionality, such as in coding assessments or educational tools to prevent cheating. In this blog, we will explore how to disable the copy-paste feature in Monaco Editor.

Why Disable Copy-Paste?
Before diving into the implementation, let’s discuss why you might want to disable copy-paste in a code editor:

  1. Academic Integrity: In educational settings, to ensure students write their code from scratch during exams or practice sessions.
  2. Prevent Plagiarism: To discourage copying code from other sources without understanding it.
  3. Skill Assessment: To accurately assess a developer’s coding skills during interviews or coding challenges.

Step by step solution

Step 1: Setting Up Monaco Editor
First, ensure you have Monaco Editor set up in your project. You can install it via npm:

npm install @monaco-editor/react
Enter fullscreen mode Exit fullscreen mode

Include it in your project:

import { Editor } from "@monaco-editor/react";
Enter fullscreen mode Exit fullscreen mode

Step 2: Configuring Editor Options
To disable certain functionalities and customize the editor's behavior, configure its options. For instance, you can disable the context menu and set other useful preferences:

Here's list of options for editor: https://microsoft.github.io/monaco-editor/typedoc/interfaces/editor.IStandaloneEditorConstructionOptions.html

const options = {
  selectOnLineNumbers: true,
  mouseWheelZoom: true,
  fontSize: 18,
  contextmenu: false, // Disables right-click context menu
  formatOnType: true,
  smoothScrolling: true,
  wordWrap: "on",
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Handling Key Down Events
To detect and prevent copy-paste actions, add an event listener for key down events. This allows you to intercept the key combinations for copy (Ctrl/Cmd + C) and paste (Ctrl/Cmd + V):

const onMount = (editor, monaco) => {
  editorRef.current = editor;
  editor.focus();

  editor.onKeyDown((event) => {
    const { keyCode, ctrlKey, metaKey } = event;
    if ((keyCode === 33 || keyCode === 52) && (metaKey || ctrlKey)) {
      event.preventDefault();
      setActivity("copypaste");
      setOpen(true);
    }
  });
};
Enter fullscreen mode Exit fullscreen mode

Step 4: Implementing the Modal Component
The Modal component provides visual feedback to the user about their activities. Here's how to implement it:

import React from "react";
import { IoIosCloseCircle } from "react-icons/io";
import { IoWarning } from "react-icons/io5";

export default function Modal({ activity, open, onClose }) {
  return (
    <div>
      <div
        className={`fixed inset-0 bg-gray-800 bg-opacity-80 z-50 transition-opacity ${
          open ? "opacity-100" : "opacity-0 pointer-events-none"
        }`}
      ></div>
      <div
        onClick={(e) => e.stopPropagation()}
        className={`fixed inset-0 flex justify-center items-center z-50 ${
          open ? "opacity-100" : "opacity-0 pointer-events-none"
        }`}
      >
        <div className="bg-white rounded-xl shadow p-6 relative">
          <button onClick={onClose} className="absolute top-2 right-2">
            <IoIosCloseCircle size={24} />
          </button>
          <div className="text-center w-full h-52 z-50 flex justify-center items-center flex-col gap-5">
            <div className="mx-auto my-4 w-full">
              <h3 className="text-lg font-black text-gray-800">
                {activity === "copypaste"
                  ? "Copy Paste Activity"
                  : "Handle any other activity here"}
              </h3>
              <p className="text-md text-gray-700 font-semibold">
                {activity === "copypaste"
                  ? "Copy paste activity has been notified to faculty"
                  : "Handle any other activity here"}
              </p>
              <p className="text-md text-gray-700 font-semibold">
                {activity === "copypaste"
                  ? "On Next copy paste your exam will be terminated"
                  : "Handle any other activity here"}
              </p>
            </div>
            <button
              className="text-white bg-red-500 p-3 rounded-lg w-full flex justify-center items-center gap-2"
              onClick={onClose}
            >
              {<IoWarning />} {activity === "copypaste" ? "Close Warning" : "Handle any other here"}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Full code for Editor Component:

import React, { useState, useRef } from "react";
import { Editor } from "@monaco-editor/react";
import Modal from "../../../../components/Modal/Modal.jsx";

const EditorWindow = () => {
  const [activity, setActivity] = useState("");
  const [open, setOpen] = useState(false);

  const editorRef = useRef(null);

  const options = {
    selectOnLineNumbers: true,
    mouseWheelZoom: true,
    fontSize: 18,
    contextmenu: false,
    formatOnType: true,
    smoothScrolling: true,
    wordWrap: "on",
  };

  const onMount = (editor, monaco) => {
    editorRef.current = editor;
    editor.focus();

    editor.onKeyDown((event) => {
      const { keyCode, ctrlKey, metaKey } = event;
      if ((keyCode === 33 || keyCode === 52) && (metaKey || ctrlKey)) {
        event.preventDefault();
        setActivity("copypaste");
        setOpen(true);
  };

  return (
    <>
      <div>
        <Modal activity={activity} open={open} onClose={() => setOpen(false)} />
        <div className="overlay overflow-hidden w-full h-full shadow-4xl">
          <Editor
            height="85vh"
            width="100vw"
            theme="vs-dark"
            language="java"
            options={options}
            defaultValue="some default value for editor"
            onMount={onMount}
          />
        </div>
      </div>
    </>
  );
};

export default EditorWindow;
Enter fullscreen mode Exit fullscreen mode

Conclusion
By following these steps, you can effectively disable copy-paste functionality in Monaco Editor and monitor user activities to ensure academic integrity. This approach is particularly useful in educational platforms and coding assessments where maintaining the originality of student work is crucial. By customizing and extending this implementation, you can adapt it to suit various educational and assessment platforms.

Top comments (0)