UNPKG

@gdquest/gd-exercise

Version:

Core package that handles logic for the GDExercise project.

272 lines (270 loc) 8.42 kB
import "./chunk-MJPHVYKR.mjs"; // ../codemirror-freeze/dist/index.mjs import { Facet } from "@codemirror/state"; import { EditorView } from "@codemirror/view"; import { EditorSelection as EditorSelection2, EditorState } from "@codemirror/state"; import { syntaxTree } from "@codemirror/language"; import { EditorSelection } from "@codemirror/state"; import { RangeSetBuilder } from "@codemirror/state"; import { Decoration, ViewPlugin } from "@codemirror/view"; var startFreezeComment = Facet.define({ combine: (values) => { if (values.length > 0) { return values[values.length - 1]; } return "start-freeze"; } }); var endFreezeComment = Facet.define({ combine: (values) => { if (values.length > 0) { return values[values.length - 1]; } return "end-freeze"; } }); var freezeTheme = EditorView.theme({ ".cm-frozen": { opacity: 0.75, fontStyle: "italic" } }); function getFreezeRanges(state, startFreezeComment2, endFreezeComment2) { const tree = syntaxTree(state); const cursor = tree.cursor(); const commentTokens = state.languageDataAt("commentTokens", 0); const freezeRanges = []; let currentRangeFrom = 0; do { if (cursor.name !== "Comment") { continue; } let fromOffset = 0; let toOffset = 0; const text = state.sliceDoc(cursor.from, cursor.to); let comment = ""; for (const commentToken of commentTokens) { if (commentToken.line != null) { if (!text.startsWith(commentToken.line)) { continue; } fromOffset = commentToken.line.length; } else if (commentToken.block != null) { if (!(text.startsWith(commentToken.block.open) && text.endsWith(commentToken.block.close))) { continue; } fromOffset = commentToken.block.open.length; toOffset = -commentToken.block.close.length; } } comment = text.slice(fromOffset, text.length + toOffset).trim(); if (comment === startFreezeComment2) { currentRangeFrom = cursor.from; } else if (comment === endFreezeComment2) { freezeRanges.push(EditorSelection.range(currentRangeFrom, cursor.to)); currentRangeFrom = 0; } } while (cursor.next()); if (currentRangeFrom > 0) { freezeRanges.push( EditorSelection.range(currentRangeFrom, state.doc.toString().length) ); } return freezeRanges; } function createSetRangeFromSelectionRange(range) { const setRange = /* @__PURE__ */ new Set(); for (let i = range.from; i <= range.to; i++) { setRange.add(i); } return setRange; } function removeFromSetRange(rangeToRemove, setRange) { const numbersToRemove = Array.from( createSetRangeFromSelectionRange(rangeToRemove) ); for (const numberToRemove of numbersToRemove) { setRange.delete(numberToRemove); } } function createSelectionRangesFromSetRange(range) { const elements = Array.from(range).sort((a, b) => a - b); const min = elements.reduce((previousValue, currentValue, currentIndex) => { if (currentIndex === 0) { return currentValue; } return Math.min(previousValue, currentValue); }, 0); const max = elements.reduce((previousValue, currentValue, currentIndex) => { if (currentIndex === 0) { return currentValue; } return Math.max(previousValue, currentValue); }, 0); const selectionRanges = []; let selectionRange = null; for (let i = min; i < max; i++) { const element = elements.find((element2) => element2 === i); if (element == null && selectionRange != null) { selectionRanges.push(selectionRange); selectionRange = null; continue; } if (selectionRange == null) { selectionRange = EditorSelection.range(i, i); } else { selectionRange = EditorSelection.range(selectionRange.from, i); } } if (selectionRange != null) { selectionRanges.push(selectionRange); selectionRange = null; } return selectionRanges; } function getFreezeTransactionFilter() { return EditorState.transactionFilter.of((transaction) => { if (!(transaction.selection != null || transaction.docChanged)) { return transaction; } const freezeRanges = getFreezeRanges( transaction.startState, transaction.startState.facet(startFreezeComment), transaction.startState.facet(endFreezeComment) ); let ignoreChanges = false; if (transaction.docChanged) { transaction.changes.iterChanges((fromA, toA, fromB, toB, inserted) => { const diff = Math.max(toA - fromA, toB - fromB); for (let i = 0; i < freezeRanges.length; i++) { let range = freezeRanges[i]; if (diff > 0) { if (fromB < range.from) { range = EditorSelection2.range(range.from + diff, range.to + diff); freezeRanges[i] = range; } } } }); for (const freezeRange of freezeRanges) { const touchesRange = transaction.changes.desc.touchesRange( freezeRange.from, freezeRange.to ); switch (touchesRange) { case "cover": case true: ignoreChanges = true; break; case false: default: } if (ignoreChanges) { break; } } } let ranges = []; if (transaction.selection != null) { let selection = transaction.newSelection; if (ignoreChanges) { selection = transaction.startState.selection; } for (const selectionRange of selection.ranges) { const selectionRangeSet = createSetRangeFromSelectionRange(selectionRange); for (const freezeRange of freezeRanges) { removeFromSetRange(freezeRange, selectionRangeSet); } ranges.push(...createSelectionRangesFromSetRange(selectionRangeSet)); } const findHasFromZero = (selectionRange) => { return selectionRange.from === 0; }; const fromZeroFreezeRange = freezeRanges.find(findHasFromZero); if (fromZeroFreezeRange != null) { const fromZeroRange = ranges.find(findHasFromZero); if (fromZeroRange != null) { ranges = ranges.filter((range) => range !== fromZeroRange); } } } const returnedTransaction = { ...transaction, ...ranges.length > 0 ? { selection: EditorSelection2.create(ranges) } : {}, ...ignoreChanges ? { changes: [], selection: transaction.startState.selection } : {} }; return returnedTransaction; }); } var frozenDecoration = Decoration.line({ attributes: { class: "cm-frozen" } }); function freezeDecoration(view) { const builder = new RangeSetBuilder(); const freezeRanges = getFreezeRanges( view.state, view.state.facet(startFreezeComment), view.state.facet(endFreezeComment) ); for (const { from, to } of view.visibleRanges) { for (let pos = from; pos <= to; ) { const line = view.state.doc.lineAt(pos); for (const freezeRange of freezeRanges) { if (freezeRange.from < line.from && line.from < freezeRange.to || freezeRange.from < line.to && line.to < freezeRange.to) { builder.add(line.from, line.from, frozenDecoration); } } pos = line.to + 1; } } return builder.finish(); } var FreezeViewPlugin = class { constructor(view) { this.decorations = freezeDecoration(view); } update(update) { if (!(update.docChanged || update.viewportChanged)) { return; } this.decorations = freezeDecoration(update.view); } }; function getFreezeViewPlugin() { const plugin = ViewPlugin.fromClass(FreezeViewPlugin, { decorations: (value) => value.decorations }); return plugin; } var _startFreezeComment = startFreezeComment; var _endFreezeComment = endFreezeComment; function freeze(startFreezeComment2 = "start-freeze", endFreezeComment2 = "end-freeze") { const startFreezeCommentOf = _startFreezeComment.of(startFreezeComment2); const endFreezeCommentOf = _endFreezeComment.of(endFreezeComment2); const freezeTransactionFilter = getFreezeTransactionFilter(); const freezeViewPlugin = getFreezeViewPlugin(); return [ freezeTransactionFilter, freezeViewPlugin, startFreezeCommentOf, endFreezeCommentOf, freezeTheme ]; } export { endFreezeComment, freeze, startFreezeComment }; //# sourceMappingURL=dist-SFRFRGE3.mjs.map