yjs / y-codemirror.next Goto Github PK
View Code? Open in Web Editor NEWCollaborative extensions for CodeMirror6
License: Other
Collaborative extensions for CodeMirror6
License: Other
The demo link in the README is for the previous version of CodeMirror.
https://github.com/yjs/yjs-demos/blob/main/codemirror/package.json
Checklist
Describe the bug
When the CodeMirror 6 instance is not mounted
in Vue3(Nuxt, in my case), there are problems with synchronisations. When an instance is running with some text and a new instance is created in another browser tab, there is no synchronisation and there are errors in the console. Errors in the console:
To Reproduce
Steps to reproduce the behavior:
<template>
<div class="main" ref="main"></div>
</template>
<script lang="ts">
import Vue from 'vue'
import { EditorState } from '@codemirror/basic-setup'
import { EditorView } from '@codemirror/view'
import * as Y from 'yjs'
// @ts-ignore
import {
yCollab,
yUndoManagerKeymap,
} from '~/y-codemirror.next'
import { WebrtcProvider } from 'y-webrtc'
import * as random from 'lib0/random'
const usercolors = [
{ color: '#30bced', light: '#30bced33' },
{ color: '#6eeb83', light: '#6eeb8333' },
{ color: '#ffbc42', light: '#ffbc4233' },
{ color: '#ecd444', light: '#ecd44433' },
{ color: '#ee6352', light: '#ee635233' },
{ color: '#9ac2c9', light: '#9ac2c933' },
{ color: '#8acb88', light: '#8acb8833' },
{ color: '#1be7ff', light: '#1be7ff33' },
]
const userColor = usercolors[random.uint32() % usercolors.length]
const ydoc = new Y.Doc()
const provider = new WebrtcProvider('codemirror6-demo-room-2', ydoc)
const ytext = ydoc.getText('codemirror')
provider.awareness.setLocalStateField('user', {
name: 'Anonymous ' + Math.floor(Math.random() * 100),
color: userColor.color,
colorLight: userColor.light,
})
// This doesn't work as intended:
let state = EditorState.create({
doc: ytext.toString(),
extensions: [
EditorView.lineWrapping,
yCollab(ytext, provider.awareness),
],
})
export default Vue.extend({
name: 'IndexPage',
mounted() {
// This Works as intended:
// let state = EditorState.create({
// doc: ytext.toString(),
// extensions: [
// EditorView.lineWrapping,
// yCollab(ytext, provider.awareness),
// ],
// })
/* eslint-env browser */
new EditorView({
state,
// parent: document.body,
parent: this.$refs.main as Element,
})
},
})
</script>
Expected behavior
state
should be able to be created without being inside mounted
. I have never needed to create state
inside mounted
before, and there is nothing in the documentation that indicates this should be the case, therefore I believe this is an issue.
Screenshots
Given above.
Environment Information
Is your feature request related to a problem? Please describe.
Hi, I am working on this PR jupyterlab/jupyterlab#13093 . There is a need to dynamically update YSyncConfig
after the initialization of EditorView. I think ySyncFacet
is a nice place to do this. However YSyncPluginValue
reads this facet during construction, and caches its value. So changing ySyncFacet
after the initialization of EditorView has no effect on YSyncPluginValue
.
I am changing ySyncFacet
by using CodeMirror compartment.
packages/codemirror/src/editor.ts
...
const ySyncFacetCompartment = new Compartment();
...
this._editor = Private.createEditor(
host,
fullConfig,
this._yeditorBinding,
this._editorConfig,
[
this._markField,
Prec.high(domEventHandlers),
updateListener,
translation,
// might need some precedence setup here.
ySyncFacetCompartment.of(
ySyncFacet.of(
new YSyncConfig(
this._yeditorBinding?.text,
this._yeditorBinding?.awareness
)
)
),
]
);
...
// every time the model is switched, we need to re-initialize the editor binding
this.model.sharedModelSwitched.connect(() => {
this._initializeEditorBinding();
// it does change ySyncFacet. However YSyncPluginValue already cached old value.
this._editor.dispatch({
effects: ySyncFacetCompartment.reconfigure(
ySyncFacet.of(
new YSyncConfig(
this._yeditorBinding?.text,
this._yeditorBinding?.awareness
)
)
)
});
}, this);
...
Describe the solution you'd like
I think just not caching the facet value can solve the problem.
Describe alternatives you've considered
No
Additional context
Is your feature request related to a problem? Please describe.
The current version of @codemirror/state
is 0.19.2 and @codemirror/view
is 0.19.9. y-codemirror.next
specifies ^0.18.0
and this excludes 0.19.*, as far as I understand, because 0.x.y versions are considered to break on every x increment.
As far as I can tell (which is, admittedly, not very far), y-codemirror.next
continues to function if @codemirror/*
packages are upgraded to 0.19.*, except that npm reports a broken peer dependency.
Describe the solution you’d like
It would be nice if someone knowledgeable about both Yjs and CodeMirror 6 were to review the changes listed as breaking in @codemirror/state
0.19.0 and in @codemirror/view
0.19.1, and either support them in y-codemirror.next
or declare that no changes are needed and bump the peer dependency versions to maybe ^0.18.0 || ^0.19.0
or >= 0.18.0 <0.20
.
Describe alternatives you’ve considered
For the application I’m trying to develop, staying on CodeMirror 6 0.18 is suboptimal because 0.19 seems to fix some user-visible bugs.
I don’t want to build with CodeMirror 5 now and have to migrate to 6 later, as that would incur twice the integration effort.
When trying to import { yCollab } from "y-codemirror.next;
in a TypeScript file compiled with Webpack 5, I receive the following error:
Module not found: Error: Can't resolve 'y-codemirror.next' in '{absolute-path-to-directory-containing-file-where-imported}'
resolve 'y-codemirror.next' in '{absolute-path-to-directory-containing-file-where-imported}'
...
Field 'browser' doesn't contain a valid alias configuration
...
Steps to reproduce the behavior:
The import would succeed without incident.
[email protected]
tsconfig.json
options—
"compilerOptions": {
"module": "ES6",
"moduleResolution": "node",
},
Thank you for Yjs!!
Is your feature request related to a problem? Please describe.
I am creating a collab script editor. It can fetch script from backend, then store is in memfs.
While Open the editor, I don't know how to give a initila value to yCollab.
If give initContent to EditorState.create
, some strange things happen
export const createEditor = (params: {
el: HTMLElement;
provider: WebrtcProvider;
onSave?: () => boolean;
initContent?: string;
}) => {
const { el, provider, onSave, initContent } = params;
const ydoc = provider.doc;
const ytext = ydoc.getText("codemirror");
const undoManager = new Y.UndoManager(ytext);
provider.awareness.setLocalStateField("user", {
name: "Anonymous " + Math.floor(Math.random() * 100),
color: userColor.color,
colorLight: userColor.light,
});
const collabExt = yCollab(ytext, provider.awareness, { undoManager });
// if (ytext.toJSON().length === 0 && initContent) ytext.insert(0, initContent);
const state = EditorState.create({
doc: initContent,
extensions: [
basicSetup,
javascript(),
collabExt,
keymap.of([
{
key: "Ctrl-s",
run: onSave,
},
]),
],
});
const view = new EditorView({
state,
parent: el,
});
return {
view,
};
};
Describe the solution you'd like
I haven't figured out how y-codemirror.next works.
If adding a parameter, will it make the user more clear how to use the default data
const collabExt = yCollab(ytext, provider.awareness, { undoManager, initContent });
The selection ribbon doesn't fill to the right on the first line of multiple selections, for the remote user.
To Reproduce
Steps to reproduce the behavior:
const i = 10;
const j = i+1;
;
on the first line, through to the last ;
on the second lineExpected behavior
Ribbon for the remainder of the top line in a remote user's multi-line selection should match what the remote user sees. See rounded rectangle on the right of the above screenshot
Environment Information
The Y.UndoManager now has a method that allows adding to scope. This is required for compatibility with the Y.MultiDocUndoManager from y-utility
.
Describe the bug
The y-codemirror.next
package contains invalid JS that causes esbuild
to break.
Several files in the package import types from @codemirror/X
packages that are not exported by that package.
As it turns out, all those types are used in type annotation comments (which makes sense as they can't be used in code as they're not exported).
As these types are not actually exported, esbuild
(correctly) produces an error like: No matching export in "node_modules/@codemirror/X/dist/index.js" for import "Y"
Here are some links to the source:
DecorationSet
type: https://github.com/yjs/y-codemirror.next/blob/main/src/y-remote-selections.js#L2DecorationSet
type: https://github.com/yjs/y-codemirror.next/blob/main/src/y-remote-selections.js#L129DecorationSet
exported)d.ts
looks like this: https://unpkg.com/@codemirror/[email protected]/dist/index.d.ts (scroll down to the last line to see the exports: the DecorationSet
is exported)To Reproduce
Go to https://stackblitz.com/edit/node-jla3pz?file=package.json
In the console, do:
> npm install
Then do:
> npm run build
You should then see the following errors:
❯ npm run build
$ esbuild index.js --bundle --outfile=out.js --external:vue --format=esm
✘ [ERROR] No matching export in "node_modules/@codemirror/view/dist/index.js" for import "DecorationSet"
node_modules/y-codemirror.next/src/y-remote-selections.js:2:57:
2 │ ..., EditorView, Decoration, DecorationSet, WidgetType } from '@cod...
╵ ~~~~~~~~~~~~~
✘ [ERROR] No matching export in "node_modules/@codemirror/state/dist/index.js" for import "StateCommand"
node_modules/y-codemirror.next/src/y-undomanager.js:3:15:
3 │ EditorState, StateCommand, Facet, Annotation, AnnotationType // e...
╵ ~~~~~~~~~~~~
✘ [ERROR] No matching export in "node_modules/@codemirror/view/dist/index.js" for import "KeyBinding"
node_modules/y-codemirror.next/src/y-undomanager.js:6:33:
6 │ ... { ViewPlugin, ViewUpdate, KeyBinding, EditorView } from '@codem...
╵ ~~~~~~~~~~
✘ [ERROR] No matching export in "node_modules/@codemirror/state/dist/index.js" for import "Extension"
node_modules/y-codemirror.next/src/index.js:4:9:
4 │ import { Extension } from '@codemirror/state' // eslint-disable-line
╵ ~~~~~~~~~
4 errors
Expected behavior
The package should by default (without any modifications) also build using esbuild
.
Environment Information
Additional context
The demo project in the yjs-demos
project does work, but that is very likely due to it using webpack
and webpack doing some transformations on the source code.
Also see evanw/esbuild#2029 for the original discussion on esbuild
's repo.
I do not understand the purpose of the following line:
y-codemirror.next/src/y-undomanager.js
Line 76 in 6cf3bd9
What is/was the idea?
I do not see any usage of the field. Search shows only the definition above -
https://github.com/yjs/y-codemirror.next/search?q=_mux
Please save me some time and use the following template. In 90% of all issues I can't reproduce the problem because I don't know what exactly you are doing, in which environment, or which y-* version is responsible. Just use the following template even if you think the problem is obvious.
Checklist
Describe the bug
During collaborative editing, if the user's cursor is on the top, bottom, left, and right borders of the editor, the user name will be overflowed and hidden.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
It is expected that the user name can be displayed normally
Environment Information
Yjs Demo
Additional context
Add any other context about the problem here.
Is your feature request related to a problem? Please describe.
Could not find a declaration file for module 'y-codemirror.next'.
There are types at /dist/src/index.d.ts', but this result could not be resolved when respecting package.json "exports". The 'y-codemirror.next' library may need to update its package.json or typings.
Describe the solution you'd like
Add types field
Describe alternatives you've considered
Additional context
Checklist
Describe the bug
Ctrl + z / ctrl + y does not scroll to the place where a change was applied
To Reproduce
Expected behavior
The changes made by undo manager should result in scrolling the editor to relevant place
Screenshots
y.js bindings for CM6 (does not scroll):
Environment Information
Please save me some time and use the following template. In 90% of all issues I can't reproduce the problem because I don't know what exactly you are doing, in which environment, or which y-* version is responsible. Just use the following template even if you think the problem is obvious.
Checklist
I am not sure but it is happening to me when I try to use CodeMirror EditorView in nextjs React with y-codemirror.next, I recreated the demo.
Describe the bug
The error happens when as awarness of yColab triggers as a new client tries to make a transformation
Unhandled Runtime Error
TypeError: this.widget.destroy is not a function
Call Stack
WidgetView.destroy
node_modules/@codemirror/view/dist/index.js (830:0)
LineView.replaceChildren
node_modules/@codemirror/view/dist/index.js (444:0)
replaceRange
node_modules/@codemirror/view/dist/index.js (580:0)
mergeChildrenInto
node_modules/@codemirror/view/dist/index.js (590:0)
LineView.merge
node_modules/@codemirror/view/dist/index.js (1246:0)
replaceRange
node_modules/@codemirror/view/dist/index.js (511:0)
DocView.updateChildren
node_modules/@codemirror/view/dist/index.js (2447:0)
DocView.updateInner
node_modules/@codemirror/view/dist/index.js (2410:0)
DocView.update
node_modules/@codemirror/view/dist/index.js (2390:0)
EditorView.update
node_modules/@codemirror/view/dist/index.js (5821:0)
EditorView._dispatch
node_modules/@codemirror/view/dist/index.js (5713:0)
EditorView.dispatch
node_modules/@codemirror/view/dist/index.js (5769:0)
eval
node_modules/y-codemirror.next/src/y-remote-selections.js (124:0)
eval
node_modules/lib0/observable.js (73:62)
Array.forEach
<anonymous>
Awareness.emit
node_modules/lib0/observable.js (73:62)
Module.applyAwarenessUpdate
node_modules/y-protocols/awareness.js (286:0)
readMessage
node_modules/y-webrtc/src/y-webrtc.js (91:6)
eval
node_modules/y-webrtc/src/y-webrtc.js (330:0)
Room.eval [as mux]
node_modules/lib0/mutex.js (35:0)
eval
node_modules/y-webrtc/src/y-webrtc.js (329:0)
To Reproduce
Steps to reproduce the behavior:
Create this component in React, I am using Nextjs
import * as Y from 'yjs';
import { yCollab, yUndoManagerKeymap } from 'y-codemirror.next';
import { WebrtcProvider } from 'y-webrtc';
import { EditorState, EditorView, basicSetup } from '@codemirror/basic-setup';
import { markdown } from '@codemirror/lang-markdown';
import { defaultHighlightStyle } from '@codemirror/highlight';
import { keymap } from '@codemirror/view';
import { useEffect } from 'react';
import * as random from 'lib0/random';
export const usercolors = [
{ color: '#30bced', light: '#30bced33' },
{ color: '#6eeb83', light: '#6eeb8333' },
{ color: '#ffbc42', light: '#ffbc4233' },
{ color: '#ecd444', light: '#ecd44433' },
{ color: '#ee6352', light: '#ee635233' },
{ color: '#9ac2c9', light: '#9ac2c933' },
{ color: '#8acb88', light: '#8acb8833' },
{ color: '#1be7ff', light: '#1be7ff33' }
];
export const userColor = usercolors[random.uint32() % usercolors.length];
let editor, provider;
let state;
function loadCodemirror2(doc, onDocChange) {
const ydoc = new Y.Doc();
provider = new WebrtcProvider('codemirror-demo', ydoc);
const ytext = ydoc.getText('codemirror');
provider.awareness.setLocalStateField('user', {
name: 'Anonymous ' + Math.floor(Math.random() * 100),
color: userColor.color,
colorLight: userColor.light,
destroy(){
alert('lol')
}
});
state = EditorState.create({
doc: ytext.toString(),
extensions: [
keymap.of([...yUndoManagerKeymap]),
basicSetup,
markdown(),
yCollab(ytext, provider.awareness),
]
});
editor = new EditorView({
state,
parent: document.querySelector('#CMeditor')
});
}
const CodeMirror = ({ }) => {
useEffect(() => {
loadCodemirror2('', ()=>{});
return () => {
editor.destroy();
};
}, []);
return (
<div id="CMeditor">
</div>
);
};
export default CodeMirror;
Environment Information
Browser: Chrome / Node.js v17.1.0
React 17 / Nextjs
npm ls yjs
to find out the exact version you are using.├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └── [email protected] deduped
└─┬ [email protected]
├─┬ [email protected]
│ └── [email protected] deduped
└── [email protected] deduped
"@codemirror/basic-setup": "^0.19.0",
"@codemirror/lang-markdown": "^0.19.2",
"@codemirror/state": "^0.19.2",
"@codemirror/view": "^0.19.29",
"y-codemirror.next": "^0.1.0",
"y-webrtc": "^10.2.2",
"y-websocket": "^1.3.18"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.