GhostText
GhostText copied to clipboard
Add support for Monaco Editor (Freecodecamp, Repl.it, Google Colab)
Setup
Browser: Chrome [Latest version] Editor: Sublime Text 3 [restarted after installation]
Description
It doesn't work on Freecodecamp. When I click on the button, it successfully copies the content of the Textarea to the editor and says it is connected... which is great, but it is not able to edit the code contained therein when I try to edit it through the editor.
The editor used by Freecodecamp: Monaco Editor by Microsoft Here's the demo page: https://microsoft.github.io/monaco-editor/
Beside freecodecamp', there are other sites that use
monaco`
Support for monaco
would be a great one to have.
There seem to be getter/setter (refering to #4) for monaco
.
https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.itextmodel.html#getvalue https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.itextmodel.html#setvalue
Too bad that I don't know enough javascript to be able to make a PR :(
I work on an addon similar to GhostText and came here to ~~steal code~~ understand how GhostText implemented Monaco support. I was disappointed to discover that GhostText didn't work with Monaco and that I would actually have to figure out how Monaco worked!
In order to avoid wasting effort, here's what I found out:
- Monaco uses textareas
- When a textarea is focused, you can find out if it belongs to a monaco instance by looking at its parents and seeing if any of them has both a monaco-editor class and a data-uri attribute.
- If they do, you can retrieve the editor's instance by passing the data-uri to
monaco.editor.getModel()
. - Once you have the model, just use getValue to retrieve its content and setValue to set it.
I won't open a PR because I don't use GhostText but hopefully this will help whoever wants to add Monaco support to GhostText :).
The new version is on master
now so PR welcome to add support for it. Supporting new textarea editors is much easier now, as long as the editor allows it.
@fregante off-topic question: does GhostText support Draft-js? Firenvim doesn't, I tried to add support for it and while I got retrieving the element's content to work I never managed to reliably write data.
@glacambre off topic, Does reddit.com use Monaco editor? If no, then what does it use?
@subnut Reddit's fancy editor uses Draft.js and its "simple" editor is a regular textarea :).
PR welcome to add support for Monaco. It's in 2 parts:
- Detect it in this function https://github.com/GhostText/GhostText/blob/261c838a8205e8fbb8cf0f5c2d3520796596431c/browser/scripts/content.js#L63-L81
- Add listeners like this: https://github.com/GhostText/GhostText/blob/261c838a8205e8fbb8cf0f5c2d3520796596431c/browser/scripts/unsafe-messenger.js#L35-L51
This mess of a code (unsafe-messenger) is necessary because extensions don't have access to the variables on the page (like CodeMirror’s constructor) so that code needs to be injected "unsafely"
Here's the base API to wrap:
-
monaco.editor.getEditors()
returns an array with all the instances on the page -
instance.getValue()
to get the value -
instance.setValue(string)
to set the value
Example to help how they're connected:
const container = document.querySelector('.monaco-editor').parentElement;
const instance = monaco.editor.getEditors().find(editor => editor._domElement);
const currentText = instance.getValue();
instance.setValue(`GhostText was here \n ${currentText}`)
You can run this code on https://microsoft.github.io/monaco-editor/index.html
@fregante I'm trying to add support for the Monaco editor when I do import * as monaco from 'monaco-editor';
I'm getting this error:
Error: Bundles must have unique names
AssertionError [ERR_ASSERTION]: Bundles must have unique names
at BundlerRunner.nameBundles (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:343:23)
at async BundlerRunner.bundle (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/requests/BundleGraphRequest.js:286:5)
at async RequestTracker.runRequest (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/RequestTracker.js:725:20)
at async Object.run (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/requests/ParcelBuildRequest.js:62:7)
at async RequestTracker.runRequest (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/RequestTracker.js:725:20)
at async Parcel._build (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/Parcel.js:399:11)
at async Parcel._startNextBuild (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/core/lib/Parcel.js:298:24)
at async $b0fd219fea43bcac$export$2e2bcd8739ae039._runFn (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/utils/lib/index.js:32339:13)
at async $b0fd219fea43bcac$export$2e2bcd8739ae039._next (/Users/ryanefendy/Documents/chrome-extensions/GhostText/node_modules/@parcel/utils/lib/index.js:32332:9)
I'm not sure where the name conflict is coming from with when importing monaco
.
I tried a few more things, but still getting the same error - Error: Bundles must have unique names
-
I tried resolving this issue by importing the specific parts of the monaco-editor, rather than the entire package:
import monaco from 'monaco-editor/esm/vs/editor/editor.api';
-
naming it to something unique/different -
import * as monaco_editor from 'monaco-editor';
It's also possible monaco-editor
is already being used by another library in this project, causing the naming conflict. What do you think you could recommend here?
Thank you for trying!
You don't need to install Monaco, refer to the other implementations. GhostText detects and accesses the local editor implementation by looking for its root element.
The error is an annoying Parcel bug, I'll look into updating Parcel at some point but again no further dependencies are required.
Refer to the existing implementations for CodeMirror. No external library needs to be imported because we must use what's already on the page.
Thanks for the pointer @fregante. When you get a chance can you take a look at Add support for Monaco Editor #239 .