mrmd-editor 0.7.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +7 -3
  2. package/src/commands.js +112 -4
  3. package/src/comment-syntax.js +364 -39
  4. package/src/config/handlers.js +1 -2
  5. package/src/config/schema.js +46 -4
  6. package/src/document-template.js +2236 -0
  7. package/src/frontmatter-updater.js +204 -74
  8. package/src/grammar.js +758 -0
  9. package/src/index.js +1074 -55
  10. package/src/keymap.js +11 -2
  11. package/src/markdown/block-decorations.js +108 -5
  12. package/src/markdown/facets.js +37 -0
  13. package/src/markdown/html-inline.js +9 -5
  14. package/src/markdown/index.js +13 -3
  15. package/src/markdown/inline-commands.js +256 -0
  16. package/src/markdown/inline-model.js +578 -0
  17. package/src/markdown/inline-state.js +103 -0
  18. package/src/markdown/renderer.js +219 -12
  19. package/src/markdown/styles.js +290 -3
  20. package/src/markdown/widgets/alert-title.js +10 -8
  21. package/src/markdown/widgets/frontmatter.js +0 -6
  22. package/src/markdown/widgets/index.js +1 -0
  23. package/src/markdown/widgets/list-marker.js +29 -0
  24. package/src/markdown/wysiwyg.js +1158 -0
  25. package/src/mrp-types.js +2 -0
  26. package/src/output-widget.js +567 -27
  27. package/src/page-view-pagination.js +127 -0
  28. package/src/runtime-lsp.js +1757 -150
  29. package/src/section-controls/commands.js +617 -0
  30. package/src/section-controls/index.js +63 -0
  31. package/src/section-controls/plugin.js +165 -0
  32. package/src/section-controls/widgets.js +936 -0
  33. package/src/shell/ai-menu.js +11 -0
  34. package/src/shell/components/context-panel.js +572 -0
  35. package/src/shell/components/status-bar.js +10 -2
  36. package/src/shell/layouts/studio.js +206 -14
  37. package/src/shell/orchestrator-client.js +69 -0
  38. package/src/spellcheck.js +166 -0
  39. package/src/tables/README.md +97 -0
  40. package/src/tables/commands/insert-linked-table.js +122 -0
  41. package/src/tables/commands/open-table-workspace.js +43 -0
  42. package/src/tables/index.js +24 -0
  43. package/src/tables/jobs/client.js +158 -0
  44. package/src/tables/parsing/anchors.js +82 -0
  45. package/src/tables/parsing/linked-table-blocks.js +61 -0
  46. package/src/tables/state/linked-table-state.js +68 -0
  47. package/src/tables/widgets/linked-table-source-banner.js +77 -0
  48. package/src/tables/widgets/linked-table-widget.js +256 -0
  49. package/src/tables/workspace/controller.js +616 -0
  50. package/src/term-pty-client.js +51 -2
  51. package/src/term-widget.js +43 -3
  52. package/src/widgets/theme-utils.js +24 -16
  53. package/src/widgets/theme.js +1015 -1
  54. package/src/runtime-codelens/detector.js +0 -279
  55. package/src/runtime-codelens/index.js +0 -76
  56. package/src/runtime-codelens/plugin.js +0 -142
  57. package/src/runtime-codelens/styles.js +0 -184
  58. package/src/runtime-codelens/widgets.js +0 -216
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mrmd-editor",
3
- "version": "0.7.1",
3
+ "version": "0.8.1",
4
4
  "description": "Markdown editor with realtime collaboration - the core editor package",
5
5
  "type": "module",
6
6
  "main": "dist/mrmd.cjs",
@@ -15,7 +15,8 @@
15
15
  "dev": "rollup -c --watch",
16
16
  "build": "rollup -c",
17
17
  "serve": "npx serve .",
18
- "test:node": "node -e \"const m = require('./dist/mrmd.cjs'); console.log('Loaded:', m.version, Object.keys(m))\""
18
+ "test:node": "node -e \"const m = require('./dist/mrmd.cjs'); console.log('Loaded:', m.version, Object.keys(m))\"",
19
+ "prepublishOnly": "npm run build"
19
20
  },
20
21
  "keywords": [
21
22
  "codemirror",
@@ -30,7 +31,8 @@
30
31
  "@rollup/plugin-node-resolve": "^15.2.3",
31
32
  "@rollup/plugin-terser": "^0.4.4",
32
33
  "puppeteer": "^24.34.0",
33
- "rollup": "^4.9.0"
34
+ "rollup": "^4.9.0",
35
+ "vite": "^8.0.0"
34
36
  },
35
37
  "dependencies": {
36
38
  "@codemirror/autocomplete": "^6.18.0",
@@ -50,6 +52,7 @@
50
52
  "@codemirror/lang-yaml": "^6.1.2",
51
53
  "@codemirror/language": "^6.10.2",
52
54
  "@codemirror/legacy-modes": "^6.5.2",
55
+ "@codemirror/lint": "^6.8.0",
53
56
  "@codemirror/search": "^6.5.6",
54
57
  "@codemirror/state": "^6.4.1",
55
58
  "@codemirror/theme-one-dark": "^6.1.3",
@@ -61,6 +64,7 @@
61
64
  "codemirror-lang-r": "^0.1.1",
62
65
  "katex": "^0.16.27",
63
66
  "mrmd-js": "^2.2.0",
67
+ "prettier": "^3.8.1",
64
68
  "y-codemirror.next": "^0.3.5",
65
69
  "y-websocket": "^2.0.0",
66
70
  "yaml": "^2.8.2",
package/src/commands.js CHANGED
@@ -10,11 +10,14 @@
10
10
 
11
11
  import { findCells, findCodeBlocks, getCellAtCursor, findCodeBlockAtPosition, findOutputBlock } from './cells.js';
12
12
  import { indentRange } from '@codemirror/language';
13
+ import { applyFrontmatterTemplate } from './frontmatter-updater.js';
13
14
  import { prettierFormat, prettierSupports } from './prettier.js';
15
+ import { applyFirstLanguageToolSuggestion } from './grammar.js';
16
+ import { insertPageBreak } from './section-controls/commands.js';
14
17
 
15
18
  /**
16
19
  * Run the current cell and stay in place.
17
- * Bound to Mod-Enter by default.
20
+ * Used by the default Mod-Enter shortcut when the cursor is in a code cell.
18
21
  *
19
22
  * @param {Object} editor - Editor API instance
20
23
  * @returns {(view: EditorView) => boolean}
@@ -42,6 +45,23 @@ export function runCell(editor) {
42
45
  };
43
46
  }
44
47
 
48
+ /**
49
+ * Run the current cell when the cursor is inside executable code.
50
+ * Otherwise insert a markdown page break token at the cursor.
51
+ * Bound to Mod-Enter by default.
52
+ *
53
+ * @param {Object} editor - Editor API instance
54
+ * @returns {(view: EditorView) => boolean}
55
+ */
56
+ export function runCellOrInsertPageBreak(editor) {
57
+ const runCellCommand = runCell(editor);
58
+
59
+ return (view) => {
60
+ if (runCellCommand(view)) return true;
61
+ return insertPageBreak(view);
62
+ };
63
+ }
64
+
45
65
  /**
46
66
  * Run the current cell and advance to the next cell.
47
67
  * If no next cell exists, create a new one with the same language.
@@ -286,7 +306,7 @@ export function insertCellBelow(editor) {
286
306
  const currentCell = getCellAtCursor(content, pos);
287
307
 
288
308
  // Determine language and insert position
289
- const lang = currentCell?.language || 'javascript';
309
+ const lang = currentCell?.language || editor?.defaultCellLanguage || 'python';
290
310
  const outputBlock = currentCell ? findOutputBlock(content, currentCell.end) : null;
291
311
  const insertPos = outputBlock ? outputBlock.end : (currentCell ? currentCell.end : content.length);
292
312
 
@@ -314,7 +334,7 @@ export function insertCellAbove(editor) {
314
334
  const pos = view.state.selection.main.head;
315
335
  const currentCell = getCellAtCursor(content, pos);
316
336
 
317
- const lang = currentCell?.language || 'javascript';
337
+ const lang = currentCell?.language || editor?.defaultCellLanguage || 'python';
318
338
  const insertPos = currentCell ? currentCell.start : 0;
319
339
 
320
340
  const newCell = `\`\`\`${lang}\n\n\`\`\`\n\n`;
@@ -348,7 +368,7 @@ function getMostCommonLanguage(content) {
348
368
 
349
369
  // Find most common
350
370
  let maxCount = 0;
351
- let mostCommon = 'javascript'; // default
371
+ let mostCommon = 'python'; // default (primary notebook runtime)
352
372
 
353
373
  for (const [lang, count] of Object.entries(langCounts)) {
354
374
  if (count > maxCount) {
@@ -791,12 +811,95 @@ export function viewSource(editor) {
791
811
  };
792
812
  }
793
813
 
814
+ /**
815
+ * Insert or augment scholarly frontmatter at the top of the document.
816
+ * Preserves existing frontmatter values and adds missing template fields.
817
+ *
818
+ * @param {Object} editor - Editor API instance
819
+ * @returns {(view: EditorView) => boolean}
820
+ */
821
+ export function insertFrontmatterTemplate(editor) {
822
+ return (view) => {
823
+ const result = applyFrontmatterTemplate(view.state.doc.toString());
824
+
825
+ if (!result) {
826
+ console.warn('[frontmatter] Cannot apply template to invalid frontmatter. Fix YAML first.');
827
+ return false;
828
+ }
829
+
830
+ const spec = {
831
+ changes: result.changes,
832
+ scrollIntoView: true,
833
+ };
834
+
835
+ if (result.selection) {
836
+ spec.selection = {
837
+ anchor: result.selection.from,
838
+ head: result.selection.to,
839
+ };
840
+ }
841
+
842
+ view.dispatch(spec);
843
+ return true;
844
+ };
845
+ }
846
+
847
+ /**
848
+ * Apply the first available grammar suggestion near the cursor.
849
+ *
850
+ * @param {Object} editor - Editor API instance
851
+ * @returns {(view: EditorView) => boolean}
852
+ */
853
+ export function applyFirstGrammarSuggestion(editor) {
854
+ return (view) => applyFirstLanguageToolSuggestion(view);
855
+ }
856
+
857
+ /**
858
+ * Toggle source mode (show all raw markdown syntax).
859
+ *
860
+ * @param {Object} editor - Editor API instance
861
+ * @returns {(view: EditorView) => boolean}
862
+ */
863
+ export function toggleSourceMode(editor) {
864
+ return (view) => {
865
+ editor.setSourceMode();
866
+ return true;
867
+ };
868
+ }
869
+
870
+ /**
871
+ * Toggle WYSIWYG mode.
872
+ *
873
+ * @param {Object} editor - Editor API instance
874
+ * @returns {(view: EditorView) => boolean}
875
+ */
876
+ export function toggleWysiwygMode(editor) {
877
+ return (view) => {
878
+ editor.setWysiwygMode();
879
+ return true;
880
+ };
881
+ }
882
+
883
+ /**
884
+ * Toggle invisible characters (spaces, tabs, newlines).
885
+ *
886
+ * @param {Object} editor - Editor API instance
887
+ * @returns {(view: EditorView) => boolean}
888
+ */
889
+ export function toggleInvisibles(editor) {
890
+ return (view) => {
891
+ editor.setShowInvisibles();
892
+ return true;
893
+ };
894
+ }
895
+
794
896
  /**
795
897
  * All available commands.
796
898
  * Maps command names to factory functions.
797
899
  */
798
900
  export const commandRegistry = {
799
901
  runCell,
902
+ runCellOrInsertPageBreak,
800
903
  runCellAndAdvance,
801
904
  runAllCells,
802
905
  runAllAbove,
@@ -811,4 +914,9 @@ export const commandRegistry = {
811
914
  indent,
812
915
  dedent,
813
916
  viewSource,
917
+ insertFrontmatterTemplate,
918
+ applyFirstGrammarSuggestion,
919
+ toggleSourceMode,
920
+ toggleWysiwygMode,
921
+ toggleInvisibles,
814
922
  };