@lexical/dragon
Version:
This package contains compatibility with Dragon NaturallySpeaking accessibility tools.
108 lines (101 loc) • 3.95 kB
JavaScript
/**
* 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.
*
*/
;
var extension = require('@lexical/extension');
var lexical = require('lexical');
/**
* 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.
*
*/
function registerDragonSupport(editor) {
const origin = window.location.origin;
const handler = event => {
if (event.origin !== origin) {
return;
}
const rootElement = editor.getRootElement();
if (document.activeElement !== rootElement) {
return;
}
const data = event.data;
if (typeof data === 'string') {
let parsedData;
try {
parsedData = JSON.parse(data);
} catch (_e) {
return;
}
if (parsedData && parsedData.protocol === 'nuanria_messaging' && parsedData.type === 'request') {
const payload = parsedData.payload;
if (payload && payload.functionId === 'makeChanges') {
const args = payload.args;
if (args) {
const [elementStart, elementLength, text, selStart, selLength] = args;
// TODO: we should probably handle formatCommand somehow?
// formatCommand;
editor.update(() => {
const selection = lexical.$getSelection();
if (lexical.$isRangeSelection(selection)) {
const anchor = selection.anchor;
let anchorNode = anchor.getNode();
let setSelStart = 0;
let setSelEnd = 0;
if (lexical.$isTextNode(anchorNode)) {
// set initial selection
if (elementStart >= 0 && elementLength >= 0) {
setSelStart = elementStart;
setSelEnd = elementStart + elementLength;
// If the offset is more than the end, make it the end
selection.setTextNodeRange(anchorNode, setSelStart, anchorNode, setSelEnd);
}
}
if (setSelStart !== setSelEnd || text !== '') {
selection.insertRawText(text);
anchorNode = anchor.getNode();
}
if (lexical.$isTextNode(anchorNode)) {
// set final selection
setSelStart = selStart;
setSelEnd = selStart + selLength;
const anchorNodeTextLength = anchorNode.getTextContentSize();
// If the offset is more than the end, make it the end
setSelStart = setSelStart > anchorNodeTextLength ? anchorNodeTextLength : setSelStart;
setSelEnd = setSelEnd > anchorNodeTextLength ? anchorNodeTextLength : setSelEnd;
selection.setTextNodeRange(anchorNode, setSelStart, anchorNode, setSelEnd);
}
// block the chrome extension from handling this event
event.stopImmediatePropagation();
}
});
}
}
}
}
};
window.addEventListener('message', handler, true);
return () => {
window.removeEventListener('message', handler, true);
};
}
/**
* Add Dragon speech to text input support to the editor, via the
* \@lexical/dragon module.
*/
const DragonExtension = lexical.defineExtension({
build: (editor, config, state) => extension.namedSignals(config),
config: lexical.safeCast({
disabled: typeof window === 'undefined'
}),
name: '@lexical/dragon',
register: (editor, config, state) => extension.effect(() => state.getOutput().disabled.value ? undefined : registerDragonSupport(editor))
});
exports.DragonExtension = DragonExtension;
exports.registerDragonSupport = registerDragonSupport;