Files
plotzilla/frontend/src/translate.ts
T

45 lines
1.8 KiB
TypeScript

// Applying a French → English translation computed in Go: which elements
// the selection covers, and the transaction that puts the translated
// elements in place.
import type { EditorState, Transaction } from 'prosemirror-state'
import type { Revision, TranslatedElement } from './backend'
import { flatElements, fromElement, schema } from './schema'
import { ownLocks, type CurrentRevision } from './revisions'
/** Flat indexes of the elements the selection touches; null for the whole script. */
export function selectedElements(state: EditorState): number[] | null {
const { from, to, empty } = state.selection
if (empty) return null
const out: number[] = []
flatElements(state.doc).forEach(({ node, pos }, i) => {
if (pos + node.nodeSize > from && pos < to) out.push(i)
})
return out
}
/**
* Replaces each translated element, in one undoable step. Go has already
* placed the element's locked pages in the translated text, so the lock
* plugin is told to leave them; translated text is marked with the current
* revision set when revisions are being marked.
*/
export function applyTranslation(
state: EditorState,
changes: TranslatedElement[],
revisions: Revision[],
current: CurrentRevision | null,
): Transaction {
const flat = flatElements(state.doc)
const tr = state.tr
const mark = current && schema.marks.revision.create(current)
// From the end, so the positions of the elements before stay valid.
for (const change of [...changes].sort((a, b) => b.index - a.index)) {
const at = flat[change.index]
if (!at) continue
const node = fromElement(change.element, revisions)
tr.replaceWith(at.pos, at.pos + at.node.nodeSize, node)
if (mark && node.content.size) tr.addMark(at.pos + 1, at.pos + 1 + node.content.size, mark)
}
return ownLocks(tr)
}