Created
December 25, 2024 18:39
-
-
Save xarical/7c4b35c53db08efbc6b3d1949f18f862 to your computer and use it in GitHub Desktop.
Simple collaborative code editor using Monaco and Flask - https://xarical.medium.com/making-a-simple-collaborative-code-editor-using-monaco-and-flask-64977f1ac1cf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require.config({paths: {'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs'}}); | |
| require(['vs/editor/editor.main'], function() { | |
| const editor = monaco.editor.create(document.getElementById('editor'), { | |
| value: '', | |
| language: 'python', | |
| theme: 'vs-dark', | |
| automaticLayout: true | |
| }); | |
| const myself = Math.random(); | |
| let flag = false; | |
| function normalizeContent(content) { | |
| return content.replace(/\r\n/g, '\n').trim(); | |
| } | |
| function fetchContent() { | |
| fetch('/content', { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| } | |
| }) | |
| .then(response => { | |
| if (!response.ok) { | |
| throw new Error('Whoops, something went wrong'); | |
| } else { | |
| return response.json() | |
| } | |
| }) | |
| .then(data => { | |
| const currentContent = editor.getValue(); | |
| let hasChanged = normalizeContent(currentContent) !== normalizeContent(data.content) | |
| if (hasChanged && myself != data.lastEditor) { | |
| flag = true; | |
| const selection = editor.getSelection(); | |
| const model = editor.getModel(); | |
| model.pushEditOperations( | |
| [], | |
| [ | |
| { | |
| range: model.getFullModelRange(), | |
| text: data.content, | |
| } | |
| ] | |
| ); | |
| editor.setSelection(selection); | |
| } | |
| }) | |
| .catch((error) => { | |
| console.log(error); | |
| }); | |
| } | |
| const fetchDelay = 1000 | |
| function fetchContentLoop() { | |
| (function loop() { | |
| setTimeout(() => { | |
| fetchContent(); | |
| loop(); | |
| }, fetchDelay); | |
| })(); | |
| } | |
| fetchContentLoop(); | |
| editor.onDidChangeModelContent(function() { | |
| if (flag){ | |
| flag = false; | |
| return; | |
| } else { | |
| fetch('/update', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| code: editor.getValue(), | |
| iam: myself | |
| }) | |
| }) | |
| .then(response => { | |
| if (!response.ok) { | |
| throw new Error('Whoops, something went wrong'); | |
| } | |
| }) | |
| .catch((error) => { | |
| console.log(error); | |
| }); | |
| } | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>My Code Editor</title> | |
| <style> | |
| #editor { | |
| width: 100%; | |
| height: 600px; | |
| border: 1px solid #000; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="editor"></div> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs/loader.js"></script> | |
| <script src="editor.js"></script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from flask import Flask, abort, request, json, jsonify, send_file | |
| import os | |
| app = Flask(__name__) | |
| last_editor = "1" | |
| @app.route('/', methods=['GET']) | |
| def home(): | |
| return send_file('index.html') | |
| @app.route('/editor.js', methods=['GET']) | |
| def get_editor(): | |
| return send_file('editor.js') | |
| @app.route('/content', methods=['GET']) | |
| def get_content(): | |
| if os.path.exists('code.txt'): | |
| with open('code.txt', 'r') as file: | |
| content = file.read() | |
| return jsonify({'content': content, 'lastEditor': last_editor}) | |
| else: | |
| abort(404, description="Whoops! Document not found") | |
| @app.route('/update', methods=['POST']) | |
| def update_file(): | |
| data = json.loads(request.data) | |
| code = data["code"] | |
| global last_editor | |
| last_editor = data["iam"] | |
| with open('code.txt', 'w') as file: | |
| file.write(code) | |
| return "" | |
| if __name__ == "__main__": | |
| app.run(host="0.0.0.0", port=8080) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment