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:
Academic Integrity: In educational settings, to ensure students write their code from scratch during exams or practice sessions.
Prevent Plagiarism: To discourage copying code from other sources without understanding it.
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
Include it in your project:
import { Editor } from "@monaco-editor/react";
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",
};
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);
}
});
};
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>
);
}
Here's full code:
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;
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.
Subscribe to my newsletter
Read articles from Ritish Shelke directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by