123 lines
4.0 KiB
HTML
123 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Yjs Prosemirror Example</title>
|
|
<link rel=stylesheet href="./prosemirror.css">
|
|
<style>
|
|
placeholder {
|
|
display: inline;
|
|
border: 1px solid #ccc;
|
|
color: #ccc;
|
|
}
|
|
placeholder:after {
|
|
content: "☁";
|
|
font-size: 200%;
|
|
line-height: 0.1;
|
|
font-weight: bold;
|
|
}
|
|
.ProseMirror img { max-width: 100px }
|
|
/* this is a rough fix for the first cursor position when the first paragraph is empty */
|
|
.ProseMirror > .ProseMirror-yjs-cursor:first-child {
|
|
margin-top: 16px;
|
|
}
|
|
.ProseMirror p:first-child, .ProseMirror h1:first-child, .ProseMirror h2:first-child, .ProseMirror h3:first-child, .ProseMirror h4:first-child, .ProseMirror h5:first-child, .ProseMirror h6:first-child {
|
|
margin-top: 16px
|
|
}
|
|
.ProseMirror-yjs-cursor {
|
|
position: absolute;
|
|
border-left: black;
|
|
border-left-style: solid;
|
|
border-left-width: 2px;
|
|
border-color: orange;
|
|
height: 1em;
|
|
word-break: normal;
|
|
}
|
|
.ProseMirror-yjs-cursor > div {
|
|
position: relative;
|
|
top: -1.05em;
|
|
font-size: 13px;
|
|
background-color: rgb(250, 129, 0);
|
|
font-family: serif;
|
|
font-style: normal;
|
|
font-weight: normal;
|
|
line-height: normal;
|
|
user-select: none;
|
|
color: white;
|
|
padding-left: 2px;
|
|
padding-right: 2px;
|
|
}
|
|
[ychange_state] {
|
|
position: relative;
|
|
}
|
|
[ychange_state]:hover::before {
|
|
content: attr(ychange_user);
|
|
background-color: #fa8100;
|
|
position: absolute;
|
|
top: -14px;
|
|
right: 0;
|
|
font-size: 12px;
|
|
padding: 0 2px;
|
|
border-radius: 3px 3px 0 0;
|
|
color: #fdfdfe;
|
|
user-select: none;
|
|
word-break: normal;
|
|
}
|
|
*[ychange_state='added'] {
|
|
background-color: #fa810069;
|
|
}
|
|
ychange[ychange_state='removed'] {
|
|
color: rgb(250, 129, 0);
|
|
text-decoration: line-through;
|
|
}
|
|
*:not(ychange)[ychange_state='removed'] {
|
|
background-color: #ff9494c9;
|
|
text-decoration: line-through;
|
|
}
|
|
img[ychange_state='removed'] {
|
|
padding: 2px;
|
|
}
|
|
.y-connect-btn {
|
|
position: absolute;
|
|
top: 20px;
|
|
right: 20px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<button type="button" class="y-connect-btn">Disconnect</button>
|
|
<p>This example shows how to bind a YXmlFragment to a <a href="http://prosemirror.net">Prosemirror</a> editor using <a href="https://github.com/y-js/y-prosemirror">y-prosemirror</a>.</p>
|
|
<p>The content of this editor is shared with every client that visits this domain.</p>
|
|
<div class="code-html">
|
|
|
|
<div id="editor" style="margin-bottom: 23px"></div>
|
|
<div style="display: none" id="content"></div>
|
|
</div>
|
|
<!-- The actual source file for the following code is found in ./prosemirror.js. Run `npm run watch` to compile the files -->
|
|
<script class="code-js" src="./build/prosemirror.js" type="module">
|
|
import * as Y from 'yjs'
|
|
import { WebsocketProvider } from 'yjs/provider/websocket.js'
|
|
import { prosemirrorPlugin, cursorPlugin } from 'yjs/bindings/prosemirror'
|
|
|
|
import * as conf from './exampleConfig.js'
|
|
|
|
import { EditorState } from 'prosemirror-state'
|
|
import { EditorView } from 'prosemirror-view'
|
|
import { DOMParser } from 'prosemirror-model'
|
|
import { schema } from 'prosemirror-schema-basic'
|
|
import { exampleSetup } from 'prosemirror-example-setup'
|
|
|
|
const provider = new WebsocketProvider(conf.serverAddress)
|
|
const ydocument = provider.get('prosemirror')
|
|
const type = ydocument.define('prosemirror', Y.XmlFragment)
|
|
|
|
const prosemirrorView = new EditorView(document.querySelector('#editor'), {
|
|
state: EditorState.create({
|
|
doc: DOMParser.fromSchema(schema).parse(document.querySelector('#content')),
|
|
plugins: exampleSetup({schema}).concat([prosemirrorPlugin(type), cursorPlugin])
|
|
})
|
|
})
|
|
|
|
window.example = { provider, ydocument, type, prosemirrorView }
|
|
</script>
|
|
</body>
|
|
</html> |