Advertisement
Guest User

codemirrorsetup.ts

a guest
Mar 12th, 2021
2,923
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { drawSelection, highlightActiveLine, keymap } from '@codemirror/view';
  2. import { EditorState, Prec, StateCommand } from '@codemirror/state';
  3. import { history, historyKeymap } from '@codemirror/history';
  4. import { indentOnInput, indentUnit } from '@codemirror/language';
  5. import { lineNumbers } from '@codemirror/gutter';
  6. import { defaultKeymap, indentMore, indentLess } from '@codemirror/commands';
  7. import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
  8. import { rectangularSelection } from '@codemirror/rectangular-selection';
  9. import { defaultHighlightStyle } from '@codemirror/highlight';
  10. import { EditorView } from "@codemirror/view";
  11. import { Line } from "@codemirror/text";
  12. import { EditorSelection } from '@codemirror/state';
  13.  
  14. // Simple CodeMirror 6 setup for markdown editing and a modest js bundle size.
  15. // lang-markdown was not added as a bundle size cost/benefit consideration.
  16.  
  17. // Four spaces indentation, line wrapping, theme with min and max widget height.
  18. // Special function for toggling markdown checkboxes: "- [x]" bound to Ctrl-d.
  19. // Tab and shift-tab indents or indets-less.
  20.  
  21. const Theme = EditorView.theme({
  22.   $: {
  23.     fontSize: "11pt",
  24.     border: "1px solid #c0c0c0"
  25.   },
  26.   $content: {
  27.     minHeight: "200px"
  28.   },
  29.   $gutter: {
  30.     minHeight: "200px"
  31.   },
  32.   $scroller: {
  33.     overflow: "auto",
  34.     maxHeight: "600px"
  35.   }
  36. });
  37.  
  38. function changeBySelectedLine(state:EditorState, f:(line:Line, change:any[], range:any) => void ) {
  39.   let atLine = -1;
  40.   return state.changeByRange(range => {
  41.       let changes:any[] = [];
  42.       for (let pos = range.from; pos <= range.to;) {
  43.           let line = state.doc.lineAt(pos);
  44.           if (line.number > atLine && (range.empty || range.to > line.from)) {
  45.               f(line, changes, range);
  46.               atLine = line.number;
  47.           }
  48.           pos = line.to + 1;
  49.       }
  50.       let changeSet = state.changes(changes);
  51.       return { changes,
  52.           range: EditorSelection.range(changeSet.mapPos(range.anchor, 1), changeSet.mapPos(range.head, 1)) };
  53.   });
  54. }
  55.  
  56. const toggleCheckbox:StateCommand = ({ state, dispatch }) => {
  57.   // Create or toggle markdown style check boxes: "- [ ]" and "- [x]", respecting indentation,
  58.   // for all selected lines:
  59.   let changes = changeBySelectedLine(state, (line, changes, range) => {
  60.     let indent = line.text.search(/\S|$/);
  61.     // Detect markdown bullet
  62.     if ((line.text.substring(indent, indent + 2) == "- ") ||
  63.         (line.text.substring(indent, indent + 2) == "* ")) {
  64.       // Toggle an existing checkbox
  65.       if (line.text.substring(indent + 2, indent + 5) == "[ ]") {
  66.         changes.push({from: line.from + indent + 3, to: line.from + indent + 4, insert: "x"});
  67.       }
  68.       else if (line.text.substring(indent + 2, indent + 5) == "[x]") {
  69.         changes.push({from: line.from + indent + 3, to: line.from + indent + 4, insert: " "});
  70.       }
  71.       else {
  72.         // Add new checkbox
  73.         changes.push({from: line.from + indent + 2, to: line.from + indent + 2, insert: "[ ] "});
  74.       }
  75.     }
  76.     else {
  77.       // No bullet, add one with checkbox
  78.       changes.push({from: line.from + indent, to: line.from + indent, insert: "- [ ] "});
  79.     }
  80.   });
  81.   if (!changes.changes.empty) {
  82.     dispatch(state.update(changes));
  83.   }
  84.   return true;
  85. }
  86.  
  87. const CodeMirrorSetup = [
  88.     lineNumbers(),
  89.     history(),
  90.     drawSelection(),
  91.     EditorState.allowMultipleSelections.of(true),
  92.     indentOnInput(),
  93.     Prec.fallback(defaultHighlightStyle),
  94.     rectangularSelection(),
  95.     highlightActiveLine(),
  96.     highlightSelectionMatches(),
  97.     indentUnit.of("    "),
  98.     EditorView.lineWrapping,
  99.     Theme,
  100.     keymap.of([
  101.         ...defaultKeymap,
  102.         ...searchKeymap,
  103.         ...historyKeymap,
  104.         { key: "Tab", run: indentMore, shift: indentLess },
  105.         { key: "c-d", run: toggleCheckbox }
  106.     ])
  107. ];
  108.  
  109. export { CodeMirrorSetup };
  110.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement