@fresh-editor/fresh-editor 0.1.88 → 0.1.90

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Release Notes
2
2
 
3
+ ## 0.1.90
4
+
5
+ ### Features
6
+
7
+ * **Package Manager**: Browse, install, and uninstall plugins, themes, and language packs from the [official registry](https://github.com/sinelaw/fresh-plugins-registry). Features search, package validation, background registry sync with local caching, and automatic theme reloading after install.
8
+ - **Language packs** bundle syntax highlighting (`.sublime-syntax`), language settings, and LSP server configuration
9
+ - Filter by package type: Plugins, Themes, Languages
10
+ - See [fresh-plugins](https://github.com/sinelaw/fresh-plugins) for example packages
11
+
12
+ * **Command Palette** (Ctrl+P): Unified prompt for navigating files, commands, buffers, and lines. Use prefix characters to switch modes:
13
+ - No prefix: fuzzy file finder
14
+ - `>` prefix: commands
15
+ - `#` prefix: switch open buffers by name
16
+ - `:` prefix: go to line number
17
+
18
+ Includes hints line showing available prefixes and Tab completion.
19
+
20
+ * **Status Message Log**: Click status bar messages to view full message history.
21
+
22
+ * **Package Scaffolding (`--init`)**: Create new plugin, theme, or language pack projects with `fresh --init`. Interactive wizard generates package.json, entry files, and proper directory structure.
23
+
24
+ * **Theme Schema**: JSON Schema for theme validation. Use `scripts/validate-theme.sh` or any JSON Schema validator.
25
+
26
+ ### Bug Fixes
27
+
28
+ * **Bracket Expansion**: Pressing Enter between matching brackets expands them with proper indentation (#629).
29
+ * **Ctrl+D Word Selection**: Ctrl+D selects the entire word when no selection exists.
30
+ * **Ctrl+Right Word Jump**: Ctrl+Right jumps to word end, matching Ctrl+Shift+Right behavior.
31
+ * **Alt+N/P Search**: Search invalidates when cursor moves manually, preventing stale matches.
32
+ * **Theme Fallback**: Falls back to default theme when configured theme is not found.
33
+ * **Cross-Platform Theme Paths**: Theme path handling works correctly on Windows.
34
+
35
+ ### Internal
36
+
37
+ * Moved calculator, color-highlighter, todo-highlighter plugins to external repository (installable via package manager).
38
+ * Moved catppuccin and xscriptor themes to external repository (installable via package manager).
39
+ * Added WASM feature flag for shared editor core modules.
40
+ * Italian translation update (#839).
41
+
42
+ ---
43
+
3
44
  ## 0.1.88
4
45
 
5
46
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fresh-editor/fresh-editor",
3
- "version": "0.1.88",
3
+ "version": "0.1.90",
4
4
  "description": "A modern terminal-based text editor with plugin support",
5
5
  "repository": {
6
6
  "type": "git",
@@ -557,19 +557,12 @@ async function updateReviewUI() {
557
557
 
558
558
  editor.clearNamespace(state.reviewBufferId, "review-diff");
559
559
  highlights.forEach((h) => {
560
- const bg = h.bg || [-1, -1, -1];
561
- // addOverlay signature: bufferId, namespace, start, end, r, g, b, underline, bold, italic, bg_r, bg_g, bg_b
562
- editor.addOverlay(
563
- state.reviewBufferId!,
564
- "review-diff",
565
- h.range[0],
566
- h.range[1],
567
- h.fg[0], h.fg[1], h.fg[2], // foreground color
568
- false, // underline
569
- h.bold || false, // bold
570
- h.italic || false, // italic
571
- bg[0], bg[1], bg[2] // background color
572
- );
560
+ editor.addOverlay(state.reviewBufferId!, "review-diff", h.range[0], h.range[1], {
561
+ fg: h.fg,
562
+ bg: h.bg,
563
+ bold: h.bold || false,
564
+ italic: h.italic || false,
565
+ });
573
566
  });
574
567
  }
575
568
  }
@@ -144,6 +144,15 @@
144
144
  "x-standalone-category": true,
145
145
  "x-no-add": true,
146
146
  "default": {}
147
+ },
148
+ "packages": {
149
+ "description": "Package manager settings for plugin/theme installation",
150
+ "$ref": "#/$defs/PackagesConfig",
151
+ "default": {
152
+ "sources": [
153
+ "https://github.com/sinelaw/fresh-plugins-registry"
154
+ ]
155
+ }
147
156
  }
148
157
  },
149
158
  "$defs": {
@@ -905,6 +914,22 @@
905
914
  }
906
915
  },
907
916
  "x-display-field": "/enabled"
917
+ },
918
+ "PackagesConfig": {
919
+ "description": "Package manager configuration for plugins and themes",
920
+ "type": "object",
921
+ "properties": {
922
+ "sources": {
923
+ "description": "Registry sources (git repository URLs containing plugin/theme indices)\nDefault: [\"https://github.com/sinelaw/fresh-plugins-registry\"]",
924
+ "type": "array",
925
+ "items": {
926
+ "type": "string"
927
+ },
928
+ "default": [
929
+ "https://github.com/sinelaw/fresh-plugins-registry"
930
+ ]
931
+ }
932
+ }
908
933
  }
909
934
  }
910
935
  }
@@ -98,16 +98,10 @@ globalThis.bookmark_add = function (): void {
98
98
 
99
99
  // Add visual indicator with bookmark namespace
100
100
  const bufferId = editor.getActiveBufferId();
101
- editor.addOverlay(
102
- bufferId,
103
- "bookmark", // namespace for all bookmarks
104
- position,
105
- position + 1,
106
- 0, // Red
107
- 128, // Green (teal color)
108
- 255, // Blue
109
- true // Underline
110
- );
101
+ editor.addOverlay(bufferId, "bookmark", position, position + 1, {
102
+ fg: [0, 128, 255], // Teal color
103
+ underline: true,
104
+ });
111
105
 
112
106
  editor.setStatus(`Added ${name} at ${path}:${line}:${column}`);
113
107
  editor.debug(`Bookmark ${id} created: ${JSON.stringify(bookmark)}`);
@@ -49,16 +49,9 @@ globalThis.highlight_region = function (): void {
49
49
  const end = cursorPos + 5;
50
50
 
51
51
  // Use namespace "demo" for batch operations
52
- const success = editor.addOverlay(
53
- bufferId,
54
- "demo", // namespace
55
- start,
56
- end,
57
- 255, // Red
58
- 255, // Green
59
- 0, // Blue (yellow highlight)
60
- false // No underline
61
- );
52
+ const success = editor.addOverlay(bufferId, "demo", start, end, {
53
+ fg: [255, 255, 0], // Yellow highlight
54
+ });
62
55
 
63
56
  if (success) {
64
57
  editor.setStatus(`Highlighted region ${start}-${end}`);
@@ -336,18 +336,11 @@ function applyGitLogHighlighting(): void {
336
336
 
337
337
  // Highlight section header
338
338
  if (line === editor.t("panel.commits_header")) {
339
- editor.addOverlay(
340
- bufferId,
341
- "gitlog",
342
- lineStart,
343
- lineEnd,
344
- colors.header[0],
345
- colors.header[1],
346
- colors.header[2],
347
- true, // underline
348
- true, // bold
349
- false // italic
350
- );
339
+ editor.addOverlay(bufferId, "gitlog", lineStart, lineEnd, {
340
+ fg: colors.header,
341
+ underline: true,
342
+ bold: true,
343
+ });
351
344
  byteOffset += line.length + 1;
352
345
  continue;
353
346
  }
@@ -364,35 +357,19 @@ function applyGitLogHighlighting(): void {
364
357
 
365
358
  // Highlight entire line if cursor is on it (using selected color with underline)
366
359
  if (isCurrentLine) {
367
- editor.addOverlay(
368
- bufferId,
369
- "gitlog",
370
- lineStart,
371
- lineEnd,
372
- colors.selected[0],
373
- colors.selected[1],
374
- colors.selected[2],
375
- true, // underline to make it visible
376
- true, // bold
377
- false // italic
378
- );
360
+ editor.addOverlay(bufferId, "gitlog", lineStart, lineEnd, {
361
+ fg: colors.selected,
362
+ underline: true,
363
+ bold: true,
364
+ });
379
365
  }
380
366
 
381
367
  // Parse the line format: "shortHash (author, relativeDate) subject [refs]"
382
368
  // Highlight hash (first 7+ chars until space)
383
369
  const hashEnd = commit.shortHash.length;
384
- editor.addOverlay(
385
- bufferId,
386
- "gitlog",
387
- lineStart,
388
- lineStart + hashEnd,
389
- colors.hash[0],
390
- colors.hash[1],
391
- colors.hash[2],
392
- false, // underline
393
- false, // bold
394
- false // italic
395
- );
370
+ editor.addOverlay(bufferId, "gitlog", lineStart, lineStart + hashEnd, {
371
+ fg: colors.hash,
372
+ });
396
373
 
397
374
  // Highlight author name (inside parentheses)
398
375
  const authorPattern = "(" + commit.author + ",";
@@ -400,18 +377,9 @@ function applyGitLogHighlighting(): void {
400
377
  if (authorStartInLine >= 0) {
401
378
  const authorStart = lineStart + authorStartInLine + 1; // skip "("
402
379
  const authorEnd = authorStart + commit.author.length;
403
- editor.addOverlay(
404
- bufferId,
405
- "gitlog",
406
- authorStart,
407
- authorEnd,
408
- colors.author[0],
409
- colors.author[1],
410
- colors.author[2],
411
- false, // underline
412
- false, // bold
413
- false // italic
414
- );
380
+ editor.addOverlay(bufferId, "gitlog", authorStart, authorEnd, {
381
+ fg: colors.author,
382
+ });
415
383
  }
416
384
 
417
385
  // Highlight relative date
@@ -420,18 +388,9 @@ function applyGitLogHighlighting(): void {
420
388
  if (dateStartInLine >= 0) {
421
389
  const dateStart = lineStart + dateStartInLine + 2; // skip ", "
422
390
  const dateEnd = dateStart + commit.relativeDate.length;
423
- editor.addOverlay(
424
- bufferId,
425
- "gitlog",
426
- dateStart,
427
- dateEnd,
428
- colors.date[0],
429
- colors.date[1],
430
- colors.date[2],
431
- false, // underline
432
- false, // bold
433
- false // italic
434
- );
391
+ editor.addOverlay(bufferId, "gitlog", dateStart, dateEnd, {
392
+ fg: colors.date,
393
+ });
435
394
  }
436
395
 
437
396
  // Highlight refs (branches/tags) at end of line if present
@@ -449,18 +408,10 @@ function applyGitLogHighlighting(): void {
449
408
  refColor = colors.remote;
450
409
  }
451
410
 
452
- editor.addOverlay(
453
- bufferId,
454
- "gitlog",
455
- refsStart,
456
- refsEnd,
457
- refColor[0],
458
- refColor[1],
459
- refColor[2],
460
- false, // underline
461
- true, // bold (make refs stand out)
462
- false // italic
463
- );
411
+ editor.addOverlay(bufferId, "gitlog", refsStart, refsEnd, {
412
+ fg: refColor,
413
+ bold: true,
414
+ });
464
415
  }
465
416
  }
466
417
 
@@ -621,112 +572,52 @@ function applyCommitDetailHighlighting(): void {
621
572
 
622
573
  // Highlight diff additions (green)
623
574
  if (line.startsWith("+") && !line.startsWith("+++")) {
624
- editor.addOverlay(
625
- bufferId,
626
- "gitdetail",
627
- lineStart,
628
- lineEnd,
629
- colors.diffAdd[0],
630
- colors.diffAdd[1],
631
- colors.diffAdd[2],
632
- false, // underline
633
- false, // bold
634
- false // italic
635
- );
575
+ editor.addOverlay(bufferId, "gitdetail", lineStart, lineEnd, {
576
+ fg: colors.diffAdd,
577
+ });
636
578
  }
637
579
  // Highlight diff deletions (red)
638
580
  else if (line.startsWith("-") && !line.startsWith("---")) {
639
- editor.addOverlay(
640
- bufferId,
641
- "gitdetail",
642
- lineStart,
643
- lineEnd,
644
- colors.diffDel[0],
645
- colors.diffDel[1],
646
- colors.diffDel[2],
647
- false, // underline
648
- false, // bold
649
- false // italic
650
- );
581
+ editor.addOverlay(bufferId, "gitdetail", lineStart, lineEnd, {
582
+ fg: colors.diffDel,
583
+ });
651
584
  }
652
585
  // Highlight hunk headers (cyan/blue)
653
586
  else if (line.startsWith("@@")) {
654
- editor.addOverlay(
655
- bufferId,
656
- "gitdetail",
657
- lineStart,
658
- lineEnd,
659
- colors.diffHunk[0],
660
- colors.diffHunk[1],
661
- colors.diffHunk[2],
662
- false, // underline
663
- true, // bold
664
- false // italic
665
- );
587
+ editor.addOverlay(bufferId, "gitdetail", lineStart, lineEnd, {
588
+ fg: colors.diffHunk,
589
+ bold: true,
590
+ });
666
591
  }
667
592
  // Highlight commit hash in "commit <hash>" line (git show format)
668
593
  else if (line.startsWith("commit ")) {
669
594
  const hashMatch = line.match(/^commit ([a-f0-9]+)/);
670
595
  if (hashMatch) {
671
596
  const hashStart = lineStart + 7; // "commit " is 7 chars
672
- editor.addOverlay(
673
- bufferId,
674
- "gitdetail",
675
- hashStart,
676
- hashStart + hashMatch[1].length,
677
- colors.hash[0],
678
- colors.hash[1],
679
- colors.hash[2],
680
- false, // underline
681
- true, // bold
682
- false // italic
683
- );
597
+ editor.addOverlay(bufferId, "gitdetail", hashStart, hashStart + hashMatch[1].length, {
598
+ fg: colors.hash,
599
+ bold: true,
600
+ });
684
601
  }
685
602
  }
686
603
  // Highlight author line
687
604
  else if (line.startsWith("Author:")) {
688
- editor.addOverlay(
689
- bufferId,
690
- "gitdetail",
691
- lineStart + 8, // "Author: " is 8 chars
692
- lineEnd,
693
- colors.author[0],
694
- colors.author[1],
695
- colors.author[2],
696
- false, // underline
697
- false, // bold
698
- false // italic
699
- );
605
+ editor.addOverlay(bufferId, "gitdetail", lineStart + 8, lineEnd, {
606
+ fg: colors.author,
607
+ });
700
608
  }
701
609
  // Highlight date line
702
610
  else if (line.startsWith("Date:")) {
703
- editor.addOverlay(
704
- bufferId,
705
- "gitdetail",
706
- lineStart + 6, // "Date: " is 6 chars (with trailing spaces it's 8)
707
- lineEnd,
708
- colors.date[0],
709
- colors.date[1],
710
- colors.date[2],
711
- false, // underline
712
- false, // bold
713
- false // italic
714
- );
611
+ editor.addOverlay(bufferId, "gitdetail", lineStart + 6, lineEnd, {
612
+ fg: colors.date,
613
+ });
715
614
  }
716
615
  // Highlight diff file headers
717
616
  else if (line.startsWith("diff --git")) {
718
- editor.addOverlay(
719
- bufferId,
720
- "gitdetail",
721
- lineStart,
722
- lineEnd,
723
- colors.header[0],
724
- colors.header[1],
725
- colors.header[2],
726
- false, // underline
727
- true, // bold
728
- false // italic
729
- );
617
+ editor.addOverlay(bufferId, "gitdetail", lineStart, lineEnd, {
618
+ fg: colors.header,
619
+ bold: true,
620
+ });
730
621
  }
731
622
 
732
623
  byteOffset += line.length + 1;
@@ -1080,7 +971,10 @@ function applyFileViewHighlighting(bufferId: number, content: string, filePath:
1080
971
  inMultilineComment = true;
1081
972
  }
1082
973
  if (inMultilineComment) {
1083
- editor.addOverlay(bufferId, "syntax", lineStart, lineStart + line.length, colors.syntaxComment[0], colors.syntaxComment[1], colors.syntaxComment[2], false, false, true);
974
+ editor.addOverlay(bufferId, "syntax", lineStart, lineStart + line.length, {
975
+ fg: colors.syntaxComment,
976
+ italic: true,
977
+ });
1084
978
  if (line.includes("*/")) {
1085
979
  inMultilineComment = false;
1086
980
  }
@@ -1099,7 +993,9 @@ function applyFileViewHighlighting(bufferId: number, content: string, filePath:
1099
993
  }
1100
994
  }
1101
995
  if (inMultilineString) {
1102
- editor.addOverlay(bufferId, "syntax", lineStart, lineStart + line.length, colors.syntaxString[0], colors.syntaxString[1], colors.syntaxString[2], false, false, false);
996
+ editor.addOverlay(bufferId, "syntax", lineStart, lineStart + line.length, {
997
+ fg: colors.syntaxString,
998
+ });
1103
999
  byteOffset += line.length + 1;
1104
1000
  continue;
1105
1001
  }
@@ -1113,12 +1009,14 @@ function applyFileViewHighlighting(bufferId: number, content: string, filePath:
1113
1009
  }
1114
1010
 
1115
1011
  if (commentStart >= 0) {
1116
- editor.addOverlay(bufferId, "syntax", lineStart + commentStart, lineStart + line.length, colors.syntaxComment[0], colors.syntaxComment[1], colors.syntaxComment[2], false, false, true);
1012
+ editor.addOverlay(bufferId, "syntax", lineStart + commentStart, lineStart + line.length, {
1013
+ fg: colors.syntaxComment,
1014
+ italic: true,
1015
+ });
1117
1016
  }
1118
1017
 
1119
1018
  // String highlighting (simple: find "..." and '...')
1120
1019
  let i = 0;
1121
- let stringCount = 0;
1122
1020
  while (i < line.length) {
1123
1021
  const ch = line[i];
1124
1022
  if (ch === '"' || ch === "'") {
@@ -1132,7 +1030,9 @@ function applyFileViewHighlighting(bufferId: number, content: string, filePath:
1132
1030
  if (i < line.length) i++; // Include closing quote
1133
1031
  const end = i;
1134
1032
  if (commentStart < 0 || start < commentStart) {
1135
- editor.addOverlay(bufferId, "syntax", lineStart + start, lineStart + end, colors.syntaxString[0], colors.syntaxString[1], colors.syntaxString[2], false, false, false);
1033
+ editor.addOverlay(bufferId, "syntax", lineStart + start, lineStart + end, {
1034
+ fg: colors.syntaxString,
1035
+ });
1136
1036
  }
1137
1037
  } else {
1138
1038
  i++;
@@ -1142,25 +1042,30 @@ function applyFileViewHighlighting(bufferId: number, content: string, filePath:
1142
1042
  // Keyword highlighting
1143
1043
  for (const keyword of keywords) {
1144
1044
  const regex = new RegExp(`\\b${keyword}\\b`, "g");
1145
- let match;
1045
+ let match: RegExpExecArray | null;
1146
1046
  while ((match = regex.exec(line)) !== null) {
1147
1047
  const kwStart = match.index;
1148
1048
  const kwEnd = kwStart + keyword.length;
1149
1049
  // Don't highlight if inside comment
1150
1050
  if (commentStart < 0 || kwStart < commentStart) {
1151
- editor.addOverlay(bufferId, "syntax", lineStart + kwStart, lineStart + kwEnd, colors.syntaxKeyword[0], colors.syntaxKeyword[1], colors.syntaxKeyword[2], false, true, false);
1051
+ editor.addOverlay(bufferId, "syntax", lineStart + kwStart, lineStart + kwEnd, {
1052
+ fg: colors.syntaxKeyword,
1053
+ bold: true,
1054
+ });
1152
1055
  }
1153
1056
  }
1154
1057
  }
1155
1058
 
1156
1059
  // Number highlighting
1157
1060
  const numberRegex = /\b\d+(\.\d+)?\b/g;
1158
- let numMatch;
1061
+ let numMatch: RegExpExecArray | null;
1159
1062
  while ((numMatch = numberRegex.exec(line)) !== null) {
1160
1063
  const numStart = numMatch.index;
1161
1064
  const numEnd = numStart + numMatch[0].length;
1162
1065
  if (commentStart < 0 || numStart < commentStart) {
1163
- editor.addOverlay(bufferId, "syntax", lineStart + numStart, lineStart + numEnd, colors.syntaxNumber[0], colors.syntaxNumber[1], colors.syntaxNumber[2], false, false, false);
1066
+ editor.addOverlay(bufferId, "syntax", lineStart + numStart, lineStart + numEnd, {
1067
+ fg: colors.syntaxNumber,
1068
+ });
1164
1069
  }
1165
1070
  }
1166
1071
 
@@ -1335,62 +1335,26 @@ export class Finder<T> {
1335
1335
 
1336
1336
  // Highlight current line if it's an item line
1337
1337
  if (isCurrentLine && isItemLine && line.trim() !== "") {
1338
- this.editor.addOverlay(
1339
- bufferId,
1340
- namespace,
1341
- lineStart,
1342
- lineEnd,
1343
- colors.selected[0],
1344
- colors.selected[1],
1345
- colors.selected[2],
1346
- false,
1347
- false,
1348
- false,
1349
- undefined,
1350
- undefined,
1351
- undefined,
1352
- true
1353
- );
1338
+ this.editor.addOverlay(bufferId, namespace, lineStart, lineEnd, {
1339
+ fg: colors.selected,
1340
+ extendToLineEnd: true,
1341
+ });
1354
1342
  }
1355
1343
 
1356
1344
  // Title line
1357
1345
  if (lineNumber === 1) {
1358
- this.editor.addOverlay(
1359
- bufferId,
1360
- namespace,
1361
- lineStart,
1362
- lineEnd,
1363
- colors.title[0],
1364
- colors.title[1],
1365
- colors.title[2],
1366
- false,
1367
- true,
1368
- false,
1369
- undefined,
1370
- undefined,
1371
- undefined,
1372
- false
1373
- );
1346
+ this.editor.addOverlay(bufferId, namespace, lineStart, lineEnd, {
1347
+ fg: colors.title,
1348
+ bold: true,
1349
+ });
1374
1350
  }
1375
1351
 
1376
1352
  // File header (ends with : but isn't title)
1377
1353
  if (line.endsWith(":") && lineNumber > 1 && !line.startsWith(" ")) {
1378
- this.editor.addOverlay(
1379
- bufferId,
1380
- namespace,
1381
- lineStart,
1382
- lineEnd,
1383
- colors.fileHeader[0],
1384
- colors.fileHeader[1],
1385
- colors.fileHeader[2],
1386
- false,
1387
- true,
1388
- false,
1389
- undefined,
1390
- undefined,
1391
- undefined,
1392
- false
1393
- );
1354
+ this.editor.addOverlay(bufferId, namespace, lineStart, lineEnd, {
1355
+ fg: colors.fileHeader,
1356
+ bold: true,
1357
+ });
1394
1358
  }
1395
1359
 
1396
1360
  // Severity icon highlighting
@@ -1415,42 +1379,17 @@ export class Finder<T> {
1415
1379
  color = colors.hint;
1416
1380
  }
1417
1381
 
1418
- this.editor.addOverlay(
1419
- bufferId,
1420
- namespace,
1421
- lineStart,
1422
- iconEnd,
1423
- color[0],
1424
- color[1],
1425
- color[2],
1426
- false,
1427
- true,
1428
- false,
1429
- undefined,
1430
- undefined,
1431
- undefined,
1432
- false
1433
- );
1382
+ this.editor.addOverlay(bufferId, namespace, lineStart, iconEnd, {
1383
+ fg: color,
1384
+ bold: true,
1385
+ });
1434
1386
  }
1435
1387
 
1436
1388
  // Help line (dimmed)
1437
1389
  if (line.startsWith("Enter:") || line.includes("|")) {
1438
- this.editor.addOverlay(
1439
- bufferId,
1440
- namespace,
1441
- lineStart,
1442
- lineEnd,
1443
- colors.help[0],
1444
- colors.help[1],
1445
- colors.help[2],
1446
- false,
1447
- false,
1448
- false,
1449
- undefined,
1450
- undefined,
1451
- undefined,
1452
- false
1453
- );
1390
+ this.editor.addOverlay(bufferId, namespace, lineStart, lineEnd, {
1391
+ fg: colors.help,
1392
+ });
1454
1393
  }
1455
1394
 
1456
1395
  byteOffset += line.length + 1;