This commit is contained in:
tonyrewin 2022-10-21 01:02:09 +03:00
parent df28889248
commit 92906931da
3 changed files with 86 additions and 82 deletions

View File

@ -1,59 +1,52 @@
import { keymap } from 'prosemirror-keymap'
import { ProseMirrorExtension } from './helpers'
import { Schema } from 'prosemirror-model'
import base from './extension/base'
import markdown from './extension/markdown'
import link from './extension/link'
// import scroll from './prosemirror/extension/scroll'
import todoList from './extension/todo-list'
import code from './extension/code'
import strikethrough from './extension/strikethrough'
import placeholder from './extension/placeholder'
// import menu from './extension/menu'
import image from './extension/image'
// import scroll from './prosemirror/extension/scroll'
import { keymap } from 'prosemirror-keymap'
import type { ProseMirrorExtension } from './helpers'
import { Schema } from 'prosemirror-model'
import { t } from '../../../utils/intl'
import base from './extension/base'
import code from './extension/code'
import dragHandle from './extension/drag-handle'
import image from './extension/image'
import link from './extension/link'
import markdown from './extension/markdown'
import pasteMarkdown from './extension/paste-markdown'
import table from './extension/table'
import collab from './extension/collab'
import { Config, YOptions } from '../store/context'
import type { Config, YOptions } from '../store/context'
import selectionMenu from './extension/selection'
import type { Command } from 'prosemirror-state'
import placeholder from './extension/placeholder'
import todoList from './extension/todo-list'
import strikethrough from './extension/strikethrough'
import scrollPlugin from './extension/scroll'
interface Props {
data?: unknown;
keymap?: any;
config: Config;
markdown: boolean;
path?: string;
y?: YOptions;
schema?: Schema;
interface ExtensionsProps {
data?: unknown
keymap?: { [key: string]: Command }
config: Config
markdown: boolean
path?: string
y?: YOptions
schema?: Schema
collab?: any
typewriterMode?: boolean
}
const customKeymap = (props: Props): ProseMirrorExtension => ({
const customKeymap = (props: ExtensionsProps): ProseMirrorExtension => ({
plugins: (prev) => (props.keymap ? [...prev, keymap(props.keymap)] : prev)
})
/*
const codeMirrorKeymap = (props: Props) => {
const keys = []
for (const key in props.keymap) {
keys.push({key: key, run: props.keymap[key]})
}
return cmKeymap.of(keys)
}
*/
export const createExtensions = (props: Props): ProseMirrorExtension[] =>
props.markdown
? [
placeholder('Просто начните...'),
customKeymap(props),
base(props.markdown),
collab(props.y),
selectionMenu()
]
: [
selectionMenu(),
customKeymap(props),
base(props.markdown),
export const createExtensions = (props: ExtensionsProps): ProseMirrorExtension[] => {
const eee = [
placeholder(t('Just start typing...')),
customKeymap(props),
base(props.markdown),
selectionMenu(),
scrollPlugin(props.config?.typewriterMode)
]
if (props.markdown) {
eee.push(
markdown(),
todoList(),
dragHandle(),
@ -62,19 +55,21 @@ export const createExtensions = (props: Props): ProseMirrorExtension[] =>
link(),
table(),
image(props.path),
pasteMarkdown(),
collab(props.y)
// scroll(props.config.typewriterMode),
pasteMarkdown()
/*
codeBlock({
theme: codeTheme(props.config),
typewriterMode: props.config.typewriterMode,
fontSize: props.config.fontSize,
prettier: props.config.prettier,
extensions: () => [codeMirrorKeymap(props)],
}),
*/
]
codeBlock({
theme: codeTheme(props.config),
typewriterMode: props.config.typewriterMode,
fontSize: props.config.fontSize,
prettier: props.config.prettier,
extensions: () => [codeMirrorKeymap(props)],
}),
*/
)
}
if (props.collab?.room) eee.push(collab(props.y))
return eee
}
export const createEmptyText = () => ({
doc: {
@ -88,7 +83,7 @@ export const createEmptyText = () => ({
}
})
export const createSchema = (props: Props) => {
export const createSchema = (props: ExtensionsProps) => {
const extensions = createExtensions({
config: props.config,
markdown: props.markdown,

View File

@ -1,12 +1,9 @@
import { Store, createStore, unwrap } from 'solid-js/store'
import { v4 as uuidv4 } from 'uuid'
import { EditorState } from 'prosemirror-state'
import type { EditorState } from 'prosemirror-state'
import { undo, redo } from 'prosemirror-history'
import { selectAll, deleteSelection } from 'prosemirror-commands'
import * as Y from 'yjs'
import { undo as yUndo, redo as yRedo } from 'y-prosemirror'
import { WebrtcProvider } from 'y-webrtc'
import { uniqueNamesGenerator, adjectives, animals } from 'unique-names-generator'
import { debounce } from 'lodash'
import { createSchema, createExtensions, createEmptyText } from '../prosemirror/setup'
import { State, File, Config, ServiceError, newState } from './context'
@ -14,11 +11,10 @@ import { mod } from '../env'
import { serialize, createMarkdownParser } from '../markdown'
import db from '../db'
import { isEmpty, isInitialized } from '../prosemirror/helpers'
import { Awareness } from 'y-protocols/awareness'
const isText = (x: any) => x && x.doc && x.selection
const isState = (x: any) => typeof x.lastModified !== 'string' && Array.isArray(x.files)
const isFile = (x: any): boolean => x && (x.text || x.path)
const isText = (x) => x && x.doc && x.selection
const isState = (x) => typeof x.lastModified !== 'string' && Array.isArray(x.files)
const isFile = (x): boolean => x && (x.text || x.path)
export const createCtrl = (initial: State): [Store<State>, any] => {
const [store, setState] = createStore(initial)
@ -131,13 +127,14 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
const fetchData = async (): Promise<State> => {
const state: State = unwrap(store)
const room = window.location.pathname?.slice(1).trim()
const args = { room: room ? room : undefined }
const args = { room: room ?? undefined }
const data = await db.get('state')
let parsed: any
if (data !== undefined) {
try {
parsed = JSON.parse(data)
} catch (err) {
} catch (error) {
console.error(error)
throw new ServiceError('invalid_state', data)
}
}
@ -162,7 +159,7 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
config: undefined
})
const newState = {
const newst = {
...parsed,
text,
extensions,
@ -170,8 +167,8 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
args
}
if (newState.lastModified) {
newState.lastModified = new Date(newState.lastModified)
if (newst.lastModified) {
newst.lastModified = new Date(newst.lastModified)
}
for (const file of parsed.files) {
@ -180,11 +177,11 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
}
}
if (!isState(newState)) {
if (!isState(newst)) {
throw new ServiceError('invalid_state', newState)
}
return newState
return newst
}
const getTheme = (state: State) => ({ theme: state.config.theme })
@ -222,7 +219,7 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
const extensions = createExtensions({
config: data.config ?? store.config,
markdown: data.markdown ?? store.markdown,
keymap: keymap
keymap
})
data = { ...data, text, extensions }
}
@ -284,14 +281,14 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
y: { type, provider }
})
let newState = state
let newst = state
if ((backup && !isEmpty(state.text)) || state.path) {
let files = state.files
if (!state.error) {
files = addToFiles(files, state)
}
newState = {
newst = {
...state,
files,
lastModified: undefined,
@ -301,7 +298,7 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
}
return {
...newState,
...newst,
extensions,
collab: { started: true, room, y: { type, provider } }
}
@ -356,7 +353,7 @@ export const createCtrl = (initial: State): [Store<State>, any] => {
config: state.config,
markdown,
path: state.path,
keymap: keymap,
keymap,
y: state.collab?.y
})

View File

@ -1,8 +1,10 @@
import { createContext, useContext } from 'solid-js'
import { Store } from 'solid-js/store'
import { XmlFragment } from 'yjs'
import { WebrtcProvider } from 'y-webrtc'
import { ProseMirrorExtension, ProseMirrorState } from '../prosemirror/helpers'
import type { Store } from 'solid-js/store'
import type { XmlFragment } from 'yjs'
import type { WebrtcProvider } from 'y-webrtc'
import type { ProseMirrorExtension, ProseMirrorState } from '../prosemirror/helpers'
import type { Command, EditorState } from 'prosemirror-state'
import type { EditorView } from 'prosemirror-view'
export interface Args {
cwd?: string;
@ -50,7 +52,7 @@ export type LoadingType = 'loading' | 'initialized'
export interface State {
text?: ProseMirrorState;
editorView?: any;
editorView?: EditorView;
extensions?: ProseMirrorExtension[];
markdown?: boolean;
lastModified?: Date;
@ -62,6 +64,16 @@ export interface State {
collab?: Collab;
path?: string;
args?: Args;
keymap?: { [key: string]: Command; }
}
export interface Draft {
body?: string
lastModified?: Date
text?: { doc: EditorState['doc']; selection: { type: string; anchor: number; head: number } }
path?: string
markdown?: boolean
extensions?: ProseMirrorExtension[]
}
export interface File {