@terrible-lexical/file
Version:
This package provides the file import/export feature for Lexical.
107 lines (94 loc) • 2.94 kB
text/typescript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type {EditorState, LexicalEditor} from 'terrible-lexical';
import {CLEAR_HISTORY_COMMAND} from 'terrible-lexical';
import {version} from '../package.json';
/**
* Takes a file and inputs its content into the editor state as an input field.
* @param editor - The lexical editor.
*/
export function importFile(editor: LexicalEditor) {
readTextFileFromSystem((text) => {
const json = JSON.parse(text);
const editorState = editor.parseEditorState(
JSON.stringify(json.editorState),
);
editor.setEditorState(editorState);
editor.dispatchCommand(CLEAR_HISTORY_COMMAND, undefined);
});
}
function readTextFileFromSystem(callback: (text: string) => void) {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.lexical';
input.addEventListener('change', (event: Event) => {
const target = event.target as HTMLInputElement;
if (target.files) {
const file = target.files[0];
const reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = (readerEvent) => {
if (readerEvent.target) {
const content = readerEvent.target.result;
callback(content as string);
}
};
}
});
input.click();
}
type DocumentJSON = {
editorState: EditorState;
lastSaved: number;
source: string | 'terrible-lexical';
version: typeof version;
};
/**
* Generates a .lexical file to be downloaded by the browser containing the current editor state.
* @param editor - The lexical editor.
* @param config - An object that optionally contains fileName and source. fileName defaults to
* the current date (as a string) and source defaults to lexical.
*/
export function exportFile(
editor: LexicalEditor,
config: Readonly<{
fileName?: string;
source?: string;
}> = Object.freeze({}),
) {
const now = new Date();
const editorState = editor.getEditorState();
const documentJSON: DocumentJSON = {
editorState: editorState,
lastSaved: now.getTime(),
source: config.source || 'terrible-lexical',
version,
};
const fileName = config.fileName || now.toISOString();
exportBlob(documentJSON, `${fileName}.lexical`);
}
// Adapted from https:/stackoverflow.com/a/19328891/2013580
function exportBlob(data: DocumentJSON, fileName: string) {
const a = document.createElement('a');
const body = document.body;
if (body === null) {
return;
}
body.appendChild(a);
a.style.display = 'none';
const json = JSON.stringify(data);
const blob = new Blob([json], {
type: 'octet/stream',
});
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}