mirror of
https://github.com/heyman/heynote.git
synced 2025-01-11 16:38:47 +01:00
Add metadata to the beginning of the serialized buffer.
Store the cursors' positions in the buffer metadata and restore the cursors when loading the buffer content.
This commit is contained in:
parent
ca38f9f932
commit
ec360f5456
@ -1,4 +1,4 @@
|
||||
import { Annotation, EditorState, Compartment, Facet } from "@codemirror/state"
|
||||
import { Annotation, EditorState, Compartment, Facet, EditorSelection } from "@codemirror/state"
|
||||
import { EditorView, keymap, drawSelection, ViewPlugin, lineNumbers } from "@codemirror/view"
|
||||
import { indentUnit, forceParsing, foldGutter, ensureSyntaxTree } from "@codemirror/language"
|
||||
import { markdown } from "@codemirror/lang-markdown"
|
||||
@ -21,6 +21,7 @@ import { languageDetection } from "./language-detection/autodetect.js"
|
||||
import { autoSaveContent } from "./save.js"
|
||||
import { todoCheckboxPlugin} from "./todo-checkbox.ts"
|
||||
import { links } from "./links.js"
|
||||
import { NoteFormat } from "./note-format.js"
|
||||
|
||||
export const LANGUAGE_SELECTOR_EVENT = "openLanguageSelector"
|
||||
|
||||
@ -61,9 +62,10 @@ export class HeynoteEditor {
|
||||
this.fontTheme = new Compartment
|
||||
this.defaultBlockToken = "text"
|
||||
this.defaultBlockAutoDetect = true
|
||||
this.saveFunction = saveFunction
|
||||
|
||||
const state = EditorState.create({
|
||||
doc: content || "",
|
||||
doc: "",
|
||||
extensions: [
|
||||
this.keymapCompartment.of(getKeymapExtensions(this, keymap)),
|
||||
heynoteCopyCut(this),
|
||||
@ -96,7 +98,7 @@ export class HeynoteEditor {
|
||||
return {class: view.state.facet(EditorView.darkTheme) ? "dark-theme" : "light-theme"}
|
||||
}),
|
||||
|
||||
saveFunction ? autoSaveContent(saveFunction, 2000) : [],
|
||||
this.saveFunction ? autoSaveContent(this, 2000) : [],
|
||||
|
||||
todoCheckboxPlugin,
|
||||
markdown(),
|
||||
@ -107,7 +109,7 @@ export class HeynoteEditor {
|
||||
// make sure saveFunction is called when page is unloaded
|
||||
if (saveFunction) {
|
||||
window.addEventListener("beforeunload", () => {
|
||||
saveFunction(this.getContent())
|
||||
this.save()
|
||||
})
|
||||
}
|
||||
|
||||
@ -116,36 +118,53 @@ export class HeynoteEditor {
|
||||
parent: element,
|
||||
})
|
||||
|
||||
// Ensure we have a parsed syntax tree when buffer is loaded. This prevents errors for large buffers
|
||||
// when moving the cursor to the end of the buffer when the program starts
|
||||
ensureSyntaxTree(state, state.doc.length, 5000)
|
||||
this.setContent(content)
|
||||
|
||||
if (focus) {
|
||||
this.view.dispatch({
|
||||
selection: {anchor: this.view.state.doc.length, head: this.view.state.doc.length},
|
||||
scrollIntoView: true,
|
||||
})
|
||||
this.view.focus()
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
this.saveFunction(this.getContent())
|
||||
}
|
||||
|
||||
getContent() {
|
||||
return this.view.state.sliceDoc()
|
||||
this.note.content = this.view.state.sliceDoc()
|
||||
this.note.cursors = this.view.state.selection.toJSON()
|
||||
return this.note.serialize()
|
||||
}
|
||||
|
||||
setContent(content) {
|
||||
this.note = NoteFormat.load(content)
|
||||
|
||||
// set buffer content
|
||||
this.view.dispatch({
|
||||
changes: {
|
||||
from: 0,
|
||||
to: this.view.state.doc.length,
|
||||
insert: content,
|
||||
insert: this.note.content,
|
||||
},
|
||||
annotations: [heynoteEvent.of(SET_CONTENT)],
|
||||
})
|
||||
this.view.dispatch({
|
||||
selection: {anchor: this.view.state.doc.length, head: this.view.state.doc.length},
|
||||
scrollIntoView: true,
|
||||
})
|
||||
|
||||
// Ensure we have a parsed syntax tree when buffer is loaded. This prevents errors for large buffers
|
||||
// when moving the cursor to the end of the buffer when the program starts
|
||||
ensureSyntaxTree(this.view.state, this.view.state.doc.length, 5000)
|
||||
|
||||
// set cursor positions
|
||||
if (this.note.cursors) {
|
||||
this.view.dispatch({
|
||||
selection: EditorSelection.fromJSON(this.note.cursors),
|
||||
scrollIntoView: true,
|
||||
})
|
||||
} else {
|
||||
// if metadata doesn't contain cursor position, we set the cursor to the end of the buffer
|
||||
this.view.dispatch({
|
||||
selection: {anchor: this.view.state.doc.length, head: this.view.state.doc.length},
|
||||
scrollIntoView: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getBlocks() {
|
||||
|
35
src/editor/note-format.js
Normal file
35
src/editor/note-format.js
Normal file
@ -0,0 +1,35 @@
|
||||
export class NoteFormat {
|
||||
constructor() {
|
||||
this.content = '';
|
||||
this.metadata = {};
|
||||
}
|
||||
|
||||
static load(data) {
|
||||
const note = new NoteFormat();
|
||||
|
||||
note.content = data
|
||||
const firstSeparator = data.indexOf("\n∞∞∞")
|
||||
if (firstSeparator !== -1) {
|
||||
const metadataContent = data.slice(0, firstSeparator).trim()
|
||||
if (metadataContent !== "") {
|
||||
note.metadata = JSON.parse(metadataContent)
|
||||
}
|
||||
note.content = data.slice(firstSeparator)
|
||||
}
|
||||
|
||||
return note
|
||||
}
|
||||
|
||||
serialize() {
|
||||
this.metadata.formatVersion = "1.0"
|
||||
return JSON.stringify(this.metadata) + this.content
|
||||
}
|
||||
|
||||
set cursors(cursors) {
|
||||
this.metadata.cursors = cursors
|
||||
}
|
||||
|
||||
get cursors() {
|
||||
return this.metadata.cursors
|
||||
}
|
||||
}
|
@ -2,17 +2,17 @@ import { ViewPlugin } from "@codemirror/view"
|
||||
import { debounce } from "debounce"
|
||||
|
||||
|
||||
export const autoSaveContent = (saveFunction, interval) => {
|
||||
const save = debounce((view) => {
|
||||
export const autoSaveContent = (editor, interval) => {
|
||||
const save = debounce(() => {
|
||||
//console.log("saving buffer")
|
||||
saveFunction(view.state.sliceDoc())
|
||||
editor.save()
|
||||
}, interval);
|
||||
|
||||
return ViewPlugin.fromClass(
|
||||
class {
|
||||
update(update) {
|
||||
if (update.docChanged) {
|
||||
save(update.view)
|
||||
save()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user