GhostText icon indicating copy to clipboard operation
GhostText copied to clipboard

Add support for Monaco Editor (Freecodecamp, Repl.it, Google Colab)

Open Clevious opened this issue 6 years ago • 8 comments

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/

Clevious avatar Aug 06 '18 13:08 Clevious

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 :(

wizzup avatar Oct 12 '19 09:10 wizzup

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 :).

glacambre avatar Nov 14 '19 05:11 glacambre

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 avatar Nov 27 '20 07:11 fregante

@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 avatar Nov 27 '20 07:11 glacambre

@glacambre off topic, Does reddit.com use Monaco editor? If no, then what does it use?

subnut avatar Dec 19 '20 16:12 subnut

@subnut Reddit's fancy editor uses Draft.js and its "simple" editor is a regular textarea :).

glacambre avatar Dec 19 '20 16:12 glacambre

PR welcome to add support for Monaco. It's in 2 parts:

  1. Detect it in this function https://github.com/GhostText/GhostText/blob/261c838a8205e8fbb8cf0f5c2d3520796596431c/browser/scripts/content.js#L63-L81
  2. 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"

fregante avatar Jan 29 '21 04:01 fregante

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 avatar Aug 21 '22 09:08 fregante

@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

  1. 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';

  2. 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?

ryan6416 avatar Jan 22 '23 20:01 ryan6416

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.

fregante avatar Jan 22 '23 23:01 fregante

Refer to the existing implementations for CodeMirror. No external library needs to be imported because we must use what's already on the page.

fregante avatar Jan 23 '23 17:01 fregante

Thanks for the pointer @fregante. When you get a chance can you take a look at Add support for Monaco Editor #239 .

ryan6416 avatar Jan 23 '23 22:01 ryan6416