@fresh-editor/fresh-editor 0.2.2 → 0.2.4
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 +67 -0
- package/README.md +32 -29
- package/package.json +1 -1
- package/plugins/config-schema.json +50 -0
- package/plugins/lib/fresh.d.ts +153 -62
- package/plugins/markdown_compose.i18n.json +42 -56
- package/plugins/markdown_compose.ts +1050 -79
- package/plugins/pkg.ts +135 -8
- package/plugins/schemas/package.schema.json +5 -0
- package/plugins/schemas/theme.schema.json +9 -0
- package/plugins/theme_editor.i18n.json +28 -0
package/plugins/pkg.ts
CHANGED
|
@@ -118,6 +118,7 @@ interface PackageManifest {
|
|
|
118
118
|
repository?: string;
|
|
119
119
|
fresh?: {
|
|
120
120
|
min_version?: string;
|
|
121
|
+
min_api_version?: number;
|
|
121
122
|
entry?: string;
|
|
122
123
|
themes?: Array<{
|
|
123
124
|
file: string;
|
|
@@ -191,6 +192,8 @@ interface InstalledPackage {
|
|
|
191
192
|
version: string;
|
|
192
193
|
commit?: string;
|
|
193
194
|
manifest?: PackageManifest;
|
|
195
|
+
/** Original local path if installed from a local directory */
|
|
196
|
+
localSource?: string;
|
|
194
197
|
}
|
|
195
198
|
|
|
196
199
|
interface LockfileEntry {
|
|
@@ -554,6 +557,7 @@ function getInstalledPackages(type: "plugin" | "theme" | "language" | "bundle"):
|
|
|
554
557
|
// Try to get git remote
|
|
555
558
|
const gitConfigPath = editor.pathJoin(pkgPath, ".git", "config");
|
|
556
559
|
let source = "";
|
|
560
|
+
let localSource: string | undefined;
|
|
557
561
|
if (editor.fileExists(gitConfigPath)) {
|
|
558
562
|
const gitConfig = editor.readFile(gitConfigPath);
|
|
559
563
|
if (gitConfig) {
|
|
@@ -564,13 +568,24 @@ function getInstalledPackages(type: "plugin" | "theme" | "language" | "bundle"):
|
|
|
564
568
|
}
|
|
565
569
|
}
|
|
566
570
|
|
|
571
|
+
// Check for .fresh-source.json (local path or monorepo installs)
|
|
572
|
+
if (!source) {
|
|
573
|
+
const freshSourcePath = editor.pathJoin(pkgPath, ".fresh-source.json");
|
|
574
|
+
const freshSource = readJsonFile<{ local_path?: string; original_url?: string }>(freshSourcePath);
|
|
575
|
+
if (freshSource?.local_path) {
|
|
576
|
+
localSource = freshSource.local_path;
|
|
577
|
+
source = freshSource.original_url || freshSource.local_path;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
567
581
|
packages.push({
|
|
568
582
|
name: entry.name,
|
|
569
583
|
path: pkgPath,
|
|
570
584
|
type,
|
|
571
585
|
source,
|
|
572
586
|
version: manifest?.version || "unknown",
|
|
573
|
-
manifest
|
|
587
|
+
manifest,
|
|
588
|
+
localSource,
|
|
574
589
|
});
|
|
575
590
|
}
|
|
576
591
|
}
|
|
@@ -641,6 +656,18 @@ function validatePackage(packageDir: string, packageName: string): ValidationRes
|
|
|
641
656
|
};
|
|
642
657
|
}
|
|
643
658
|
|
|
659
|
+
// Warn if package requires a newer plugin API version
|
|
660
|
+
if (manifest.fresh?.min_api_version) {
|
|
661
|
+
const currentApi = editor.apiVersion();
|
|
662
|
+
if (manifest.fresh.min_api_version > currentApi) {
|
|
663
|
+
editor.warn(
|
|
664
|
+
`[pkg] Package '${packageName}' requires plugin API version ${manifest.fresh.min_api_version}, ` +
|
|
665
|
+
`but this editor only supports version ${currentApi}. Some features may not work. ` +
|
|
666
|
+
`Update Fresh to get the latest plugin API.`
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
644
671
|
// For plugins, validate entry file exists
|
|
645
672
|
if (manifest.type === "plugin") {
|
|
646
673
|
const entryFile = manifest.fresh?.entry || `${manifest.name}.ts`;
|
|
@@ -1348,6 +1375,85 @@ async function updatePackage(pkg: InstalledPackage): Promise<boolean> {
|
|
|
1348
1375
|
}
|
|
1349
1376
|
}
|
|
1350
1377
|
|
|
1378
|
+
/**
|
|
1379
|
+
* Reinstall a package from its original local path.
|
|
1380
|
+
* Removes the installed copy and re-copies from the source directory.
|
|
1381
|
+
*/
|
|
1382
|
+
async function reinstallPackage(pkg: InstalledPackage): Promise<boolean> {
|
|
1383
|
+
if (!pkg.localSource) {
|
|
1384
|
+
editor.setStatus(`Cannot reinstall ${pkg.name}: no local source path`);
|
|
1385
|
+
return false;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
const sourcePath = pkg.localSource;
|
|
1389
|
+
|
|
1390
|
+
if (!editor.fileExists(sourcePath)) {
|
|
1391
|
+
editor.setStatus(`Source path no longer exists: ${sourcePath}`);
|
|
1392
|
+
return false;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
editor.setStatus(`Reinstalling ${pkg.name} from ${sourcePath}...`);
|
|
1396
|
+
|
|
1397
|
+
// Unload plugin first if applicable
|
|
1398
|
+
if (pkg.type === "plugin") {
|
|
1399
|
+
const loadedPlugins = await editor.listPlugins();
|
|
1400
|
+
const plugin = loadedPlugins.find((p: { path: string }) => p.path.startsWith(pkg.path));
|
|
1401
|
+
if (plugin) {
|
|
1402
|
+
await editor.unloadPlugin(plugin.name).catch(() => {});
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// Remove old copy
|
|
1407
|
+
const rmResult = await editor.spawnProcess("rm", ["-rf", pkg.path]);
|
|
1408
|
+
if (rmResult.exit_code !== 0) {
|
|
1409
|
+
editor.setStatus(`Failed to remove old copy: ${rmResult.stderr}`);
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
// Re-copy from source
|
|
1414
|
+
const copyResult = await editor.spawnProcess("cp", ["-r", sourcePath, pkg.path]);
|
|
1415
|
+
if (copyResult.exit_code !== 0) {
|
|
1416
|
+
editor.setStatus(`Failed to copy from source: ${copyResult.stderr}`);
|
|
1417
|
+
return false;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
// Re-write the .fresh-source.json marker
|
|
1421
|
+
const sourceInfo = {
|
|
1422
|
+
local_path: sourcePath,
|
|
1423
|
+
original_url: pkg.source,
|
|
1424
|
+
installed_at: new Date().toISOString()
|
|
1425
|
+
};
|
|
1426
|
+
await writeJsonFile(editor.pathJoin(pkg.path, ".fresh-source.json"), sourceInfo);
|
|
1427
|
+
|
|
1428
|
+
// Re-read manifest for validation and reload
|
|
1429
|
+
const validation = validatePackage(pkg.path, pkg.name);
|
|
1430
|
+
if (!validation.valid) {
|
|
1431
|
+
editor.setStatus(`Reinstalled ${pkg.name} but package is invalid: ${validation.error}`);
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
const manifest = validation.manifest;
|
|
1436
|
+
|
|
1437
|
+
// Reload
|
|
1438
|
+
if (manifest?.type === "plugin" && validation.entryPath) {
|
|
1439
|
+
await editor.loadPlugin(validation.entryPath);
|
|
1440
|
+
editor.setStatus(`Reinstalled and activated ${pkg.name}`);
|
|
1441
|
+
} else if (manifest?.type === "theme") {
|
|
1442
|
+
editor.reloadThemes();
|
|
1443
|
+
editor.setStatus(`Reinstalled theme ${pkg.name}`);
|
|
1444
|
+
} else if (manifest?.type === "language") {
|
|
1445
|
+
await loadLanguagePack(pkg.path, manifest);
|
|
1446
|
+
editor.setStatus(`Reinstalled language pack ${pkg.name}`);
|
|
1447
|
+
} else if (manifest?.type === "bundle") {
|
|
1448
|
+
await loadBundle(pkg.path, manifest);
|
|
1449
|
+
editor.setStatus(`Reinstalled bundle ${pkg.name}`);
|
|
1450
|
+
} else {
|
|
1451
|
+
editor.setStatus(`Reinstalled ${pkg.name}`);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
return true;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1351
1457
|
/**
|
|
1352
1458
|
* Remove a package
|
|
1353
1459
|
*/
|
|
@@ -1401,14 +1507,24 @@ async function updateAllPackages(): Promise<void> {
|
|
|
1401
1507
|
|
|
1402
1508
|
for (const pkg of all) {
|
|
1403
1509
|
editor.setStatus(`Updating ${pkg.name} (${updated + failed + 1}/${all.length})...`);
|
|
1404
|
-
const result = await gitCommand(["-C", `${pkg.path}`, "pull", "--ff-only"]);
|
|
1405
1510
|
|
|
1406
|
-
if (
|
|
1407
|
-
|
|
1511
|
+
if (pkg.localSource) {
|
|
1512
|
+
// Local packages: reinstall from source path
|
|
1513
|
+
const ok = await reinstallPackage(pkg);
|
|
1514
|
+
if (ok) {
|
|
1408
1515
|
updated++;
|
|
1516
|
+
} else {
|
|
1517
|
+
failed++;
|
|
1409
1518
|
}
|
|
1410
1519
|
} else {
|
|
1411
|
-
|
|
1520
|
+
const result = await gitCommand(["-C", `${pkg.path}`, "pull", "--ff-only"]);
|
|
1521
|
+
if (result.exit_code === 0) {
|
|
1522
|
+
if (!result.stdout.includes("Already up to date")) {
|
|
1523
|
+
updated++;
|
|
1524
|
+
}
|
|
1525
|
+
} else {
|
|
1526
|
+
failed++;
|
|
1527
|
+
}
|
|
1412
1528
|
}
|
|
1413
1529
|
}
|
|
1414
1530
|
|
|
@@ -1851,6 +1967,9 @@ function getActionButtons(): string[] {
|
|
|
1851
1967
|
const item = items[pkgState.selectedIndex];
|
|
1852
1968
|
|
|
1853
1969
|
if (item.installed) {
|
|
1970
|
+
if (item.installedPackage?.localSource) {
|
|
1971
|
+
return ["Reinstall", "Uninstall"];
|
|
1972
|
+
}
|
|
1854
1973
|
return item.updateAvailable ? ["Update", "Uninstall"] : ["Uninstall"];
|
|
1855
1974
|
} else {
|
|
1856
1975
|
return ["Install"];
|
|
@@ -2539,7 +2658,11 @@ globalThis.pkg_activate = async function(): Promise<void> {
|
|
|
2539
2658
|
const actions = getActionButtons();
|
|
2540
2659
|
const actionName = actions[focus.index];
|
|
2541
2660
|
|
|
2542
|
-
if (actionName === "
|
|
2661
|
+
if (actionName === "Reinstall" && item.installedPackage) {
|
|
2662
|
+
await reinstallPackage(item.installedPackage);
|
|
2663
|
+
pkgState.items = buildPackageList();
|
|
2664
|
+
updatePkgManagerView();
|
|
2665
|
+
} else if (actionName === "Update" && item.installedPackage) {
|
|
2543
2666
|
await updatePackage(item.installedPackage);
|
|
2544
2667
|
pkgState.items = buildPackageList();
|
|
2545
2668
|
updatePkgManagerView();
|
|
@@ -2752,12 +2875,16 @@ globalThis.pkg_update = function(): void {
|
|
|
2752
2875
|
id: "pkg-update",
|
|
2753
2876
|
format: (pkg) => ({
|
|
2754
2877
|
label: pkg.name,
|
|
2755
|
-
description: `${pkg.type} | ${pkg.version}`,
|
|
2878
|
+
description: `${pkg.type} | ${pkg.version}${pkg.localSource ? " (local)" : ""}`,
|
|
2756
2879
|
metadata: pkg
|
|
2757
2880
|
}),
|
|
2758
2881
|
preview: false,
|
|
2759
2882
|
onSelect: async (pkg) => {
|
|
2760
|
-
|
|
2883
|
+
if (pkg.localSource) {
|
|
2884
|
+
await reinstallPackage(pkg);
|
|
2885
|
+
} else {
|
|
2886
|
+
await updatePackage(pkg);
|
|
2887
|
+
}
|
|
2761
2888
|
}
|
|
2762
2889
|
});
|
|
2763
2890
|
|
|
@@ -52,6 +52,11 @@
|
|
|
52
52
|
"pattern": "^\\d+\\.\\d+\\.\\d+",
|
|
53
53
|
"description": "Minimum required Fresh version"
|
|
54
54
|
},
|
|
55
|
+
"min_api_version": {
|
|
56
|
+
"type": "integer",
|
|
57
|
+
"minimum": 1,
|
|
58
|
+
"description": "Minimum required plugin API version (integer, e.g. 2)"
|
|
59
|
+
},
|
|
55
60
|
"entry": {
|
|
56
61
|
"type": "string",
|
|
57
62
|
"description": "Plugin entry point file (for plugins)"
|
|
@@ -124,6 +124,8 @@
|
|
|
124
124
|
"field.line_number_fg_desc": "řádek číslo text barva",
|
|
125
125
|
"field.line_number_bg": "řádek číslo pozadí",
|
|
126
126
|
"field.line_number_bg_desc": "řádek číslo okraj pozadí",
|
|
127
|
+
"field.ruler_bg": "Pozadí pravítka",
|
|
128
|
+
"field.ruler_bg_desc": "Barva svislé čáry pravítka",
|
|
127
129
|
"field.diff_add_bg": "Diff Added pozadí",
|
|
128
130
|
"field.diff_add_bg_desc": "Diff added řádek pozadí",
|
|
129
131
|
"field.diff_remove_bg": "Diff Removed pozadí",
|
|
@@ -395,6 +397,8 @@
|
|
|
395
397
|
"field.line_number_fg_desc": "Textfarbe der Zeilennummern",
|
|
396
398
|
"field.line_number_bg": "Zeilennummer Hintergrund",
|
|
397
399
|
"field.line_number_bg_desc": "Hintergrund des Zeilennummern-Bereichs",
|
|
400
|
+
"field.ruler_bg": "Lineal Hintergrund",
|
|
401
|
+
"field.ruler_bg_desc": "Farbe der vertikalen Lineallinie",
|
|
398
402
|
"field.tab_active_fg": "Aktiver Tab Vordergrund",
|
|
399
403
|
"field.tab_active_fg_desc": "Textfarbe des aktiven Tabs",
|
|
400
404
|
"field.tab_active_bg": "Aktiver Tab Hintergrund",
|
|
@@ -712,6 +716,8 @@
|
|
|
712
716
|
"field.line_number_fg_desc": "Line number text color",
|
|
713
717
|
"field.line_number_bg": "Line Number Background",
|
|
714
718
|
"field.line_number_bg_desc": "Line number gutter background",
|
|
719
|
+
"field.ruler_bg": "Ruler Background",
|
|
720
|
+
"field.ruler_bg_desc": "Vertical ruler line color",
|
|
715
721
|
"field.diff_add_bg": "Diff Added Background",
|
|
716
722
|
"field.diff_add_bg_desc": "Diff added line background",
|
|
717
723
|
"field.diff_remove_bg": "Diff Removed Background",
|
|
@@ -983,6 +989,8 @@
|
|
|
983
989
|
"field.line_number_fg_desc": "Color de texto del numero de linea",
|
|
984
990
|
"field.line_number_bg": "Fondo de numero de linea",
|
|
985
991
|
"field.line_number_bg_desc": "Fondo del margen de numeros de linea",
|
|
992
|
+
"field.ruler_bg": "Fondo de regla",
|
|
993
|
+
"field.ruler_bg_desc": "Color de linea de regla vertical",
|
|
986
994
|
"field.tab_active_fg": "Primer plano de pestana activa",
|
|
987
995
|
"field.tab_active_fg_desc": "Color de texto de pestana activa",
|
|
988
996
|
"field.tab_active_bg": "Fondo de pestana activa",
|
|
@@ -1277,6 +1285,8 @@
|
|
|
1277
1285
|
"field.line_number_fg_desc": "Couleur du texte des numeros de ligne",
|
|
1278
1286
|
"field.line_number_bg": "Arriere-plan des numeros de ligne",
|
|
1279
1287
|
"field.line_number_bg_desc": "Arriere-plan de la gouttiere des numeros",
|
|
1288
|
+
"field.ruler_bg": "Arriere-plan de la regle",
|
|
1289
|
+
"field.ruler_bg_desc": "Couleur de la ligne de regle verticale",
|
|
1280
1290
|
"field.tab_active_fg": "Premier plan onglet actif",
|
|
1281
1291
|
"field.tab_active_fg_desc": "Couleur du texte de l'onglet actif",
|
|
1282
1292
|
"field.tab_active_bg": "Arriere-plan onglet actif",
|
|
@@ -1571,6 +1581,8 @@
|
|
|
1571
1581
|
"field.line_number_fg_desc": "行番号のテキスト色",
|
|
1572
1582
|
"field.line_number_bg": "行番号背景",
|
|
1573
1583
|
"field.line_number_bg_desc": "行番号ガターの背景",
|
|
1584
|
+
"field.ruler_bg": "ルーラー背景",
|
|
1585
|
+
"field.ruler_bg_desc": "垂直ルーラーの線の色",
|
|
1574
1586
|
"field.tab_active_fg": "アクティブタブ前景",
|
|
1575
1587
|
"field.tab_active_fg_desc": "アクティブタブのテキスト色",
|
|
1576
1588
|
"field.tab_active_bg": "アクティブタブ背景",
|
|
@@ -1888,6 +1900,8 @@
|
|
|
1888
1900
|
"field.line_number_fg_desc": "줄 숫자 텍스트 색상",
|
|
1889
1901
|
"field.line_number_bg": "줄 숫자 배경",
|
|
1890
1902
|
"field.line_number_bg_desc": "줄 숫자 여백 배경",
|
|
1903
|
+
"field.ruler_bg": "눈금자 배경",
|
|
1904
|
+
"field.ruler_bg_desc": "수직 눈금자 선 색상",
|
|
1891
1905
|
"field.diff_add_bg": "Diff Added 배경",
|
|
1892
1906
|
"field.diff_add_bg_desc": "Diff added 줄 배경",
|
|
1893
1907
|
"field.diff_remove_bg": "Diff Removed 배경",
|
|
@@ -2182,6 +2196,8 @@
|
|
|
2182
2196
|
"field.line_number_fg_desc": "linha número texto cor",
|
|
2183
2197
|
"field.line_number_bg": "linha número fundo",
|
|
2184
2198
|
"field.line_number_bg_desc": "linha número margem fundo",
|
|
2199
|
+
"field.ruler_bg": "Fundo da regua",
|
|
2200
|
+
"field.ruler_bg_desc": "Cor da linha da regua vertical",
|
|
2185
2201
|
"field.diff_add_bg": "Diff Added fundo",
|
|
2186
2202
|
"field.diff_add_bg_desc": "Diff added linha fundo",
|
|
2187
2203
|
"field.diff_remove_bg": "Diff Removed fundo",
|
|
@@ -2476,6 +2492,8 @@
|
|
|
2476
2492
|
"field.line_number_fg_desc": "строка число текст цвет",
|
|
2477
2493
|
"field.line_number_bg": "строка число фон",
|
|
2478
2494
|
"field.line_number_bg_desc": "строка число поле фон",
|
|
2495
|
+
"field.ruler_bg": "Фон линейки",
|
|
2496
|
+
"field.ruler_bg_desc": "Цвет вертикальной линии линейки",
|
|
2479
2497
|
"field.diff_add_bg": "Diff Added фон",
|
|
2480
2498
|
"field.diff_add_bg_desc": "Diff added строка фон",
|
|
2481
2499
|
"field.diff_remove_bg": "Diff Removed фон",
|
|
@@ -2770,6 +2788,8 @@
|
|
|
2770
2788
|
"field.line_number_fg_desc": "บรรทัด ตัวเลข ข้อความ สี",
|
|
2771
2789
|
"field.line_number_bg": "บรรทัด ตัวเลข พื้นหลัง",
|
|
2772
2790
|
"field.line_number_bg_desc": "บรรทัด ตัวเลข ขอบ พื้นหลัง",
|
|
2791
|
+
"field.ruler_bg": "พื้นหลังไม้บรรทัด",
|
|
2792
|
+
"field.ruler_bg_desc": "สีเส้นไม้บรรทัดแนวตั้ง",
|
|
2773
2793
|
"field.diff_add_bg": "Diff Added พื้นหลัง",
|
|
2774
2794
|
"field.diff_add_bg_desc": "Diff added บรรทัด พื้นหลัง",
|
|
2775
2795
|
"field.diff_remove_bg": "Diff Removed พื้นหลัง",
|
|
@@ -3064,6 +3084,8 @@
|
|
|
3064
3084
|
"field.line_number_fg_desc": "рядок число текст колір",
|
|
3065
3085
|
"field.line_number_bg": "рядок число фон",
|
|
3066
3086
|
"field.line_number_bg_desc": "рядок число поле фон",
|
|
3087
|
+
"field.ruler_bg": "Фон лінійки",
|
|
3088
|
+
"field.ruler_bg_desc": "Колір вертикальної лінії лінійки",
|
|
3067
3089
|
"field.diff_add_bg": "Diff Added фон",
|
|
3068
3090
|
"field.diff_add_bg_desc": "Diff added рядок фон",
|
|
3069
3091
|
"field.diff_remove_bg": "Diff Removed фон",
|
|
@@ -3358,6 +3380,8 @@
|
|
|
3358
3380
|
"field.line_number_fg_desc": "Màu văn bản số dòng",
|
|
3359
3381
|
"field.line_number_bg": "Nền số dòng",
|
|
3360
3382
|
"field.line_number_bg_desc": "Nền lề số dòng",
|
|
3383
|
+
"field.ruler_bg": "Nền thước kẻ",
|
|
3384
|
+
"field.ruler_bg_desc": "Màu đường thước kẻ dọc",
|
|
3361
3385
|
"field.diff_add_bg": "Nền diff thêm",
|
|
3362
3386
|
"field.diff_add_bg_desc": "Nền dòng diff được thêm",
|
|
3363
3387
|
"field.diff_remove_bg": "Nền diff xóa",
|
|
@@ -3629,6 +3653,8 @@
|
|
|
3629
3653
|
"field.line_number_fg_desc": "行号文本颜色",
|
|
3630
3654
|
"field.line_number_bg": "行号背景",
|
|
3631
3655
|
"field.line_number_bg_desc": "行号区域背景",
|
|
3656
|
+
"field.ruler_bg": "标尺背景",
|
|
3657
|
+
"field.ruler_bg_desc": "垂直标尺线颜色",
|
|
3632
3658
|
"field.tab_active_fg": "活动标签页前景",
|
|
3633
3659
|
"field.tab_active_fg_desc": "活动标签页文本颜色",
|
|
3634
3660
|
"field.tab_active_bg": "活动标签页背景",
|
|
@@ -3923,6 +3949,8 @@
|
|
|
3923
3949
|
"field.line_number_fg_desc": "Colore del testo del numero di riga",
|
|
3924
3950
|
"field.line_number_bg": "Sfondo numero riga",
|
|
3925
3951
|
"field.line_number_bg_desc": "Sfondo del margine dei numeri di riga",
|
|
3952
|
+
"field.ruler_bg": "Sfondo del righello",
|
|
3953
|
+
"field.ruler_bg_desc": "Colore della linea del righello verticale",
|
|
3926
3954
|
"field.diff_add_bg": "Sfondo Diff Aggiunta",
|
|
3927
3955
|
"field.diff_add_bg_desc": "Sfondo della riga aggiunta nel diff",
|
|
3928
3956
|
"field.diff_remove_bg": "Sfondo Diff Rimozione",
|