dsh-ide-git 0.14.2 → 0.14.3
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/dsh.plugin.json +1 -1
- package/package.json +1 -1
- package/src/client.js +674 -82
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-ide-git",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"description": "IDE 级 Git 操作面板:分支树 + 提交图谱 + 变更/暂存/提交 + 提交详情。装了 dsh-better-sidebar 时挂成它的原生 tab(右侧栏 + 底部工作台);没装时直接挂 DSH 原生右侧栏,单独安装即可用。JetBrains 风格 Git 工具窗口 for DeepSeek Harness.",
|
|
6
6
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ide-git",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
4
4
|
"description": "DSH plugin: an IDE-grade Git tool window as a native dsh-better-sidebar tab — branch tree, commit graph, changes, commit details, JetBrains-style actions, in the right sidebar and the bottom panel. | DSH 插件:IDE 级 Git 工具窗口,以 dsh-better-sidebar 原生 Tab 挂载——分支树 / 提交图谱 / 变更与提交详情 / JetBrains 风格操作,右侧栏与底部面板双布局自适应。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/client.js
CHANGED
|
@@ -202,6 +202,16 @@ window.__ModuleLoader__.load({
|
|
|
202
202
|
'settings.placement.immersive': '沉浸模式(占满全高,隐藏输入框)',
|
|
203
203
|
'settings.placement.immersiveHint': '开启后 Git 标签页占满整个会话区高度,输入框自动收起;审批与提问仍会正常显示。',
|
|
204
204
|
'preview.openFile': '打开文件预览',
|
|
205
|
+
'lf.added': '+{count}',
|
|
206
|
+
'lf.deleted': '-{count}',
|
|
207
|
+
'lf.selectFile': '选择要查看的文件',
|
|
208
|
+
'lf.split': '切换为左右对比',
|
|
209
|
+
'lf.unified': '切换为单栏对比',
|
|
210
|
+
'lf.wrap': '开启自动换行',
|
|
211
|
+
'lf.nowrap': '关闭自动换行',
|
|
212
|
+
'lf.created': '新建的文件',
|
|
213
|
+
'lf.removedFile': '删除的文件',
|
|
214
|
+
'lf.truncated': '只显示前 {count} 行',
|
|
205
215
|
'preview.title': 'Git 预览',
|
|
206
216
|
'preview.hint': '点击文件或提交的「显示差异」,差异会在侧边栏这里打开。',
|
|
207
217
|
'settings.rail.title': '动作条按钮',
|
|
@@ -417,6 +427,16 @@ window.__ModuleLoader__.load({
|
|
|
417
427
|
'settings.placement.immersive': 'Immersive mode (full height, hidden composer)',
|
|
418
428
|
'settings.placement.immersiveHint': 'On, the Git tab fills the whole conversation area and the composer steps aside; approvals and questions still show.',
|
|
419
429
|
'preview.openFile': 'Open in the file preview',
|
|
430
|
+
'lf.added': '+{count}',
|
|
431
|
+
'lf.deleted': '-{count}',
|
|
432
|
+
'lf.selectFile': 'Choose the file to review',
|
|
433
|
+
'lf.split': 'Switch to split view',
|
|
434
|
+
'lf.unified': 'Switch to unified view',
|
|
435
|
+
'lf.wrap': 'Enable line wrap',
|
|
436
|
+
'lf.nowrap': 'Disable line wrap',
|
|
437
|
+
'lf.created': 'Created file',
|
|
438
|
+
'lf.removedFile': 'Deleted file',
|
|
439
|
+
'lf.truncated': 'Showing the first {count} lines',
|
|
420
440
|
'preview.title': 'Git Preview',
|
|
421
441
|
'preview.hint': 'Click “Show diff” on a file or commit — the diff opens here in the sidebar.',
|
|
422
442
|
'settings.rail.title': 'Action rail buttons',
|
|
@@ -640,6 +660,16 @@ window.__ModuleLoader__.load({
|
|
|
640
660
|
'settings.placement.immersive': '沉浸模式(佔滿全高,隱藏輸入框)',
|
|
641
661
|
'settings.placement.immersiveHint': '開啟之後 Git 分頁會佔滿整個會話區高度,輸入框自動收起;審批與提問仍會正常顯示。',
|
|
642
662
|
'preview.openFile': '開啟檔案預覽',
|
|
663
|
+
'lf.added': '+{count}',
|
|
664
|
+
'lf.deleted': '-{count}',
|
|
665
|
+
'lf.selectFile': '選擇要查看嘅檔案',
|
|
666
|
+
'lf.split': '切換為左右對比',
|
|
667
|
+
'lf.unified': '切換為單欄對比',
|
|
668
|
+
'lf.wrap': '開啟自動換行',
|
|
669
|
+
'lf.nowrap': '關閉自動換行',
|
|
670
|
+
'lf.created': '新建嘅檔案',
|
|
671
|
+
'lf.removedFile': '刪除嘅檔案',
|
|
672
|
+
'lf.truncated': '只顯示前 {count} 行',
|
|
643
673
|
'preview.title': 'Git 預覽',
|
|
644
674
|
'preview.hint': '喺檔案或提交撳「顯示差異」,差異就會喺側邊欄度開啟。',
|
|
645
675
|
'settings.rail.title': '動作列按鈕',
|
|
@@ -855,6 +885,16 @@ window.__ModuleLoader__.load({
|
|
|
855
885
|
'settings.placement.immersive': '沉浸模式(佔滿全高,隱藏輸入框)',
|
|
856
886
|
'settings.placement.immersiveHint': '開啟之後 Git 分頁會佔滿整個對話區高度,輸入框自動收起;審核與提問仍會正常顯示。',
|
|
857
887
|
'preview.openFile': '開啟檔案預覽',
|
|
888
|
+
'lf.added': '+{count}',
|
|
889
|
+
'lf.deleted': '-{count}',
|
|
890
|
+
'lf.selectFile': '選擇要查看的檔案',
|
|
891
|
+
'lf.split': '切換為左右對比',
|
|
892
|
+
'lf.unified': '切換為單欄對比',
|
|
893
|
+
'lf.wrap': '開啟自動換行',
|
|
894
|
+
'lf.nowrap': '關閉自動換行',
|
|
895
|
+
'lf.created': '新建的檔案',
|
|
896
|
+
'lf.removedFile': '刪除的檔案',
|
|
897
|
+
'lf.truncated': '只顯示前 {count} 行',
|
|
858
898
|
'preview.title': 'Git 預覽',
|
|
859
899
|
'preview.hint': '點選檔案或提交的「顯示差異」,差異就會在側邊欄開啟。',
|
|
860
900
|
'settings.rail.title': '動作列按鈕',
|
|
@@ -1070,6 +1110,16 @@ window.__ModuleLoader__.load({
|
|
|
1070
1110
|
'settings.placement.immersive': '沉浸模式(佔滿全高,隱藏輸入框)',
|
|
1071
1111
|
'settings.placement.immersiveHint': '開啟之後 Git 分頁會佔滿整個會話區高度,輸入框自動收起;審批與提問仍會正常顯示。',
|
|
1072
1112
|
'preview.openFile': '開啟檔案預覽',
|
|
1113
|
+
'lf.added': '+{count}',
|
|
1114
|
+
'lf.deleted': '-{count}',
|
|
1115
|
+
'lf.selectFile': '選擇要查看嘅檔案',
|
|
1116
|
+
'lf.split': '切換為左右對比',
|
|
1117
|
+
'lf.unified': '切換為單欄對比',
|
|
1118
|
+
'lf.wrap': '開啟自動換行',
|
|
1119
|
+
'lf.nowrap': '關閉自動換行',
|
|
1120
|
+
'lf.created': '新建嘅檔案',
|
|
1121
|
+
'lf.removedFile': '刪除嘅檔案',
|
|
1122
|
+
'lf.truncated': '只顯示前 {count} 行',
|
|
1073
1123
|
'preview.title': 'Git 預覽',
|
|
1074
1124
|
'preview.hint': '喺檔案或提交撳「顯示差異」,差異就會喺側邊欄度開啟。',
|
|
1075
1125
|
'settings.rail.title': '動作列按鈕',
|
|
@@ -1285,6 +1335,16 @@ window.__ModuleLoader__.load({
|
|
|
1285
1335
|
'settings.placement.immersive': '没入モード(全高表示・入力欄を非表示)',
|
|
1286
1336
|
'settings.placement.immersiveHint': 'オンにすると Git タブが会話エリアの高さいっぱいに広がり、入力欄は引っ込みます。承認や質問は通常どおり表示されます。',
|
|
1287
1337
|
'preview.openFile': 'ファイルプレビューを開く',
|
|
1338
|
+
'lf.added': '+{count}',
|
|
1339
|
+
'lf.deleted': '-{count}',
|
|
1340
|
+
'lf.selectFile': 'レビューするファイルを選択',
|
|
1341
|
+
'lf.split': '左右分割に切り替える',
|
|
1342
|
+
'lf.unified': '単欄に切り替える',
|
|
1343
|
+
'lf.wrap': '自動折り返しをオンにする',
|
|
1344
|
+
'lf.nowrap': '自動折り返しをオフにする',
|
|
1345
|
+
'lf.created': '新規作成されたファイル',
|
|
1346
|
+
'lf.removedFile': '削除されたファイル',
|
|
1347
|
+
'lf.truncated': '先頭 {count} 行のみ表示',
|
|
1288
1348
|
'preview.title': 'Git プレビュー',
|
|
1289
1349
|
'preview.hint': 'ファイルやコミットの「差分を表示」をクリックすると、差分がここに開きます。',
|
|
1290
1350
|
'settings.rail.title': 'アクションレールのボタン',
|
|
@@ -1500,6 +1560,16 @@ window.__ModuleLoader__.load({
|
|
|
1500
1560
|
'settings.placement.immersive': '몰입 모드(전체 높이, 입력창 숨김)',
|
|
1501
1561
|
'settings.placement.immersiveHint': '켜면 Git 탭이 대화 영역 전체 높이를 차지하고 입력창은 숨겨집니다. 승인과 질문은 정상적으로 표시됩니다.',
|
|
1502
1562
|
'preview.openFile': '파일 미리보기로 열기',
|
|
1563
|
+
'lf.added': '+{count}',
|
|
1564
|
+
'lf.deleted': '-{count}',
|
|
1565
|
+
'lf.selectFile': '검토할 파일 선택',
|
|
1566
|
+
'lf.split': '좌우 분할 보기로 전환',
|
|
1567
|
+
'lf.unified': '단일 보기로 전환',
|
|
1568
|
+
'lf.wrap': '자동 줄바꿈 켜기',
|
|
1569
|
+
'lf.nowrap': '자동 줄바꿈 끄기',
|
|
1570
|
+
'lf.created': '새로 만든 파일',
|
|
1571
|
+
'lf.removedFile': '삭제된 파일',
|
|
1572
|
+
'lf.truncated': '처음 {count}줄만 표시',
|
|
1503
1573
|
'preview.title': 'Git 미리보기',
|
|
1504
1574
|
'preview.hint': '파일이나 커밋의 「차이 보기」를 클릭하면 차이가 사이드바 여기에 열립니다.',
|
|
1505
1575
|
'settings.rail.title': '액션 레일 버튼',
|
|
@@ -1715,6 +1785,16 @@ window.__ModuleLoader__.load({
|
|
|
1715
1785
|
'settings.placement.immersive': 'Immersiver Modus (volle Höhe, ausgeblendetes Eingabefeld)',
|
|
1716
1786
|
'settings.placement.immersiveHint': 'Eingeschaltet füllt der Git-Tab die gesamte Gesprächshöhe und das Eingabefeld weicht zurück; Freigaben und Rückfragen bleiben sichtbar.',
|
|
1717
1787
|
'preview.openFile': 'In der Dateivorschau öffnen',
|
|
1788
|
+
'lf.added': '+{count}',
|
|
1789
|
+
'lf.deleted': '-{count}',
|
|
1790
|
+
'lf.selectFile': 'Zu prüfende Datei wählen',
|
|
1791
|
+
'lf.split': 'Zur geteilten Ansicht wechseln',
|
|
1792
|
+
'lf.unified': 'Zur gemeinsamen Ansicht wechseln',
|
|
1793
|
+
'lf.wrap': 'Zeilenumbruch aktivieren',
|
|
1794
|
+
'lf.nowrap': 'Zeilenumbruch deaktivieren',
|
|
1795
|
+
'lf.created': 'Neue Datei',
|
|
1796
|
+
'lf.removedFile': 'Gelöschte Datei',
|
|
1797
|
+
'lf.truncated': 'Nur die ersten {count} Zeilen',
|
|
1718
1798
|
'preview.title': 'Git-Vorschau',
|
|
1719
1799
|
'preview.hint': '„Diff anzeigen“ an einer Datei oder einem Commit öffnet den Diff hier in der Seitenleiste.',
|
|
1720
1800
|
'settings.rail.title': 'Schaltflächen der Aktionsleiste',
|
|
@@ -1930,6 +2010,16 @@ window.__ModuleLoader__.load({
|
|
|
1930
2010
|
'settings.placement.immersive': 'Mode immersif (pleine hauteur, zone de saisie masquée)',
|
|
1931
2011
|
'settings.placement.immersiveHint': 'Activé, l’onglet Git occupe toute la hauteur de la conversation et la zone de saisie s’efface ; approbations et questions restent visibles.',
|
|
1932
2012
|
'preview.openFile': 'Ouvrir dans l’aperçu du fichier',
|
|
2013
|
+
'lf.added': '+{count}',
|
|
2014
|
+
'lf.deleted': '-{count}',
|
|
2015
|
+
'lf.selectFile': 'Choisir le fichier à examiner',
|
|
2016
|
+
'lf.split': 'Passer à la vue scindée',
|
|
2017
|
+
'lf.unified': 'Passer à la vue unifiée',
|
|
2018
|
+
'lf.wrap': 'Activer le retour à la ligne',
|
|
2019
|
+
'lf.nowrap': 'Désactiver le retour à la ligne',
|
|
2020
|
+
'lf.created': 'Fichier créé',
|
|
2021
|
+
'lf.removedFile': 'Fichier supprimé',
|
|
2022
|
+
'lf.truncated': 'Affichage des {count} premières lignes',
|
|
1933
2023
|
'preview.title': 'Aperçu Git',
|
|
1934
2024
|
'preview.hint': 'Cliquez sur « Afficher le diff » sur un fichier ou un commit : le diff s’ouvre ici, dans la barre latérale.',
|
|
1935
2025
|
'settings.rail.title': 'Boutons de la barre d’actions',
|
|
@@ -2145,6 +2235,16 @@ window.__ModuleLoader__.load({
|
|
|
2145
2235
|
'settings.placement.immersive': 'Полноэкранный режим (во всю высоту, без поля ввода)',
|
|
2146
2236
|
'settings.placement.immersiveHint': 'Во включённом виде вкладка Git занимает всю высоту области диалога, поле ввода скрывается; подтверждения и вопросы остаются на виду.',
|
|
2147
2237
|
'preview.openFile': 'Открыть в предпросмотре файла',
|
|
2238
|
+
'lf.added': '+{count}',
|
|
2239
|
+
'lf.deleted': '-{count}',
|
|
2240
|
+
'lf.selectFile': 'Выберите файл для просмотра',
|
|
2241
|
+
'lf.split': 'Переключить на двухпанельный вид',
|
|
2242
|
+
'lf.unified': 'Переключить на однопанельный вид',
|
|
2243
|
+
'lf.wrap': 'Включить перенос строк',
|
|
2244
|
+
'lf.nowrap': 'Отключить перенос строк',
|
|
2245
|
+
'lf.created': 'Новый файл',
|
|
2246
|
+
'lf.removedFile': 'Удалённый файл',
|
|
2247
|
+
'lf.truncated': 'Показаны первые {count} строк',
|
|
2148
2248
|
'preview.title': 'Git-предпросмотр',
|
|
2149
2249
|
'preview.hint': 'Нажмите «Показать различия» у файла или коммита — различия откроются здесь, в боковой панели.',
|
|
2150
2250
|
'settings.rail.title': 'Кнопки панели действий',
|
|
@@ -2360,6 +2460,16 @@ window.__ModuleLoader__.load({
|
|
|
2360
2460
|
'settings.placement.immersive': 'Modo imersivo (altura total, campo de entrada oculto)',
|
|
2361
2461
|
'settings.placement.immersiveHint': 'Ativado, a aba Git ocupa toda a altura da conversa e o campo de entrada fica de lado; aprovações e perguntas continuam visíveis.',
|
|
2362
2462
|
'preview.openFile': 'Abrir na pré-visualização do arquivo',
|
|
2463
|
+
'lf.added': '+{count}',
|
|
2464
|
+
'lf.deleted': '-{count}',
|
|
2465
|
+
'lf.selectFile': 'Escolher o arquivo para revisar',
|
|
2466
|
+
'lf.split': 'Alternar para a vista dividida',
|
|
2467
|
+
'lf.unified': 'Alternar para a vista unificada',
|
|
2468
|
+
'lf.wrap': 'Ativar quebra de linha',
|
|
2469
|
+
'lf.nowrap': 'Desativar quebra de linha',
|
|
2470
|
+
'lf.created': 'Arquivo criado',
|
|
2471
|
+
'lf.removedFile': 'Arquivo excluído',
|
|
2472
|
+
'lf.truncated': 'Mostrando as primeiras {count} linhas',
|
|
2363
2473
|
'preview.title': 'Pré-visualização do Git',
|
|
2364
2474
|
'preview.hint': 'Clique em “Mostrar diff” num arquivo ou commit — o diff abre aqui, na barra lateral.',
|
|
2365
2475
|
'settings.rail.title': 'Botões da barra de ações',
|
|
@@ -2575,6 +2685,16 @@ window.__ModuleLoader__.load({
|
|
|
2575
2685
|
'settings.placement.immersive': 'Modalità immersiva (altezza piena, input nascosto)',
|
|
2576
2686
|
'settings.placement.immersiveHint': 'Attiva, la scheda Git occupa tutta l’altezza della conversazione e la barra di input resta nascosta; approvazioni e domande restano visibili.',
|
|
2577
2687
|
'preview.openFile': 'Apri nell’anteprima del file',
|
|
2688
|
+
'lf.added': '+{count}',
|
|
2689
|
+
'lf.deleted': '-{count}',
|
|
2690
|
+
'lf.selectFile': 'Scegli il file da esaminare',
|
|
2691
|
+
'lf.split': 'Passa alla vista affiancata',
|
|
2692
|
+
'lf.unified': 'Passa alla vista unificata',
|
|
2693
|
+
'lf.wrap': 'Attiva il ritorno a capo',
|
|
2694
|
+
'lf.nowrap': 'Disattiva il ritorno a capo',
|
|
2695
|
+
'lf.created': 'File creato',
|
|
2696
|
+
'lf.removedFile': 'File eliminato',
|
|
2697
|
+
'lf.truncated': 'Mostrate le prime {count} righe',
|
|
2578
2698
|
'preview.title': 'Anteprima Git',
|
|
2579
2699
|
'preview.hint': 'Fai clic su «Mostra diff» su un file o un commit: il diff si apre qui, nella barra laterale.',
|
|
2580
2700
|
'settings.rail.title': 'Pulsanti della barra azioni',
|
|
@@ -2790,6 +2910,16 @@ window.__ModuleLoader__.load({
|
|
|
2790
2910
|
'settings.placement.immersive': 'Meeslepende modus (volledige hoogte, verborgen invoerveld)',
|
|
2791
2911
|
'settings.placement.immersiveHint': 'Aan: het Git-tabblad vult de hele gespreksruimte en het invoerveld wijkt; goedkeuringen en vragen blijven zichtbaar.',
|
|
2792
2912
|
'preview.openFile': 'Openen in de bestandsvoorbeeld',
|
|
2913
|
+
'lf.added': '+{count}',
|
|
2914
|
+
'lf.deleted': '-{count}',
|
|
2915
|
+
'lf.selectFile': 'Kies het te bekijken bestand',
|
|
2916
|
+
'lf.split': 'Overschakelen naar gesplitste weergave',
|
|
2917
|
+
'lf.unified': 'Overschakelen naar gecombineerde weergave',
|
|
2918
|
+
'lf.wrap': 'Regelterugloop inschakelen',
|
|
2919
|
+
'lf.nowrap': 'Regelterugloop uitschakelen',
|
|
2920
|
+
'lf.created': 'Nieuw bestand',
|
|
2921
|
+
'lf.removedFile': 'Verwijderd bestand',
|
|
2922
|
+
'lf.truncated': 'Eerste {count} regels worden weergegeven',
|
|
2793
2923
|
'preview.title': 'Git-voorbeeld',
|
|
2794
2924
|
'preview.hint': 'Klik op „Diff tonen“ bij een bestand of commit — de diff opent hier in de zijbalk.',
|
|
2795
2925
|
'settings.rail.title': 'Knoppen van de actiebalk',
|
|
@@ -3005,6 +3135,16 @@ window.__ModuleLoader__.load({
|
|
|
3005
3135
|
'settings.placement.immersive': 'Tryb immersyjny (pełna wysokość, ukryte pole wpisywania)',
|
|
3006
3136
|
'settings.placement.immersiveHint': 'Po włączeniu karta Git wypełnia całą wysokość rozmowy, a pole wpisywania się chowa; zatwierdzenia i pytania pozostają widoczne.',
|
|
3007
3137
|
'preview.openFile': 'Otwórz w podglądzie pliku',
|
|
3138
|
+
'lf.added': '+{count}',
|
|
3139
|
+
'lf.deleted': '-{count}',
|
|
3140
|
+
'lf.selectFile': 'Wybierz plik do przeglądu',
|
|
3141
|
+
'lf.split': 'Przełącz na widok dzielony',
|
|
3142
|
+
'lf.unified': 'Przełącz na widok połączony',
|
|
3143
|
+
'lf.wrap': 'Włącz zawijanie wierszy',
|
|
3144
|
+
'lf.nowrap': 'Wyłącz zawijanie wierszy',
|
|
3145
|
+
'lf.created': 'Nowy plik',
|
|
3146
|
+
'lf.removedFile': 'Usunięty plik',
|
|
3147
|
+
'lf.truncated': 'Pokazano pierwsze {count} wierszy',
|
|
3008
3148
|
'preview.title': 'Podgląd Git',
|
|
3009
3149
|
'preview.hint': 'Kliknij „Pokaż różnice” przy pliku lub commicie — różnice otworzą się tutaj, na pasku bocznym.',
|
|
3010
3150
|
'settings.rail.title': 'Przyciski paska akcji',
|
|
@@ -3220,6 +3360,16 @@ window.__ModuleLoader__.load({
|
|
|
3220
3360
|
'settings.placement.immersive': 'Uppslukande läge (full höjd, dolt inmatningsfält)',
|
|
3221
3361
|
'settings.placement.immersiveHint': 'På: Git-fliken fyller hela konversationsytan och inmatningsfältet träder åt sidan; godkännanden och frågor visas fortfarande.',
|
|
3222
3362
|
'preview.openFile': 'Öppna i filförhandsvisningen',
|
|
3363
|
+
'lf.added': '+{count}',
|
|
3364
|
+
'lf.deleted': '-{count}',
|
|
3365
|
+
'lf.selectFile': 'Välj filen att granska',
|
|
3366
|
+
'lf.split': 'Byt till delad vy',
|
|
3367
|
+
'lf.unified': 'Byt till samlad vy',
|
|
3368
|
+
'lf.wrap': 'Aktivera radbrytning',
|
|
3369
|
+
'lf.nowrap': 'Inaktivera radbrytning',
|
|
3370
|
+
'lf.created': 'Ny fil',
|
|
3371
|
+
'lf.removedFile': 'Borttagen fil',
|
|
3372
|
+
'lf.truncated': 'Visar de första {count} raderna',
|
|
3223
3373
|
'preview.title': 'Git-förhandsvisning',
|
|
3224
3374
|
'preview.hint': 'Klicka på ”Visa diff” på en fil eller en commit — diffen öppnas här i sidopanelen.',
|
|
3225
3375
|
'settings.rail.title': 'Knappar i åtgärdsfältet',
|
|
@@ -3435,6 +3585,16 @@ window.__ModuleLoader__.load({
|
|
|
3435
3585
|
'settings.placement.immersive': 'Odaklanma modu (tam yükseklik, gizli giriş alanı)',
|
|
3436
3586
|
'settings.placement.immersiveHint': 'Açıkken Git sekmesi tüm konuşma alanını kaplar ve giriş alanı gizlenir; onaylar ve sorular yine de görünür.',
|
|
3437
3587
|
'preview.openFile': 'Dosya önizlemesinde aç',
|
|
3588
|
+
'lf.added': '+{count}',
|
|
3589
|
+
'lf.deleted': '-{count}',
|
|
3590
|
+
'lf.selectFile': 'İncelenecek dosyayı seçin',
|
|
3591
|
+
'lf.split': 'Bölünmüş görünüme geç',
|
|
3592
|
+
'lf.unified': 'Birleşik görünüme geç',
|
|
3593
|
+
'lf.wrap': 'Satır kaydırmayı aç',
|
|
3594
|
+
'lf.nowrap': 'Satır kaydırmayı kapat',
|
|
3595
|
+
'lf.created': 'Yeni dosya',
|
|
3596
|
+
'lf.removedFile': 'Silinen dosya',
|
|
3597
|
+
'lf.truncated': 'Yalnızca ilk {count} satır gösteriliyor',
|
|
3438
3598
|
'preview.title': 'Git Önizlemesi',
|
|
3439
3599
|
'preview.hint': 'Bir dosya veya commit üzerinde „Farkı göster”e tıklayın — fark burada, kenar çubuğunda açılır.',
|
|
3440
3600
|
'settings.rail.title': 'Eylem çubuğu düğmeleri',
|
|
@@ -3650,6 +3810,16 @@ window.__ModuleLoader__.load({
|
|
|
3650
3810
|
'settings.placement.immersive': 'Mode imersif (tinggi penuh, kolom masukan tersembunyi)',
|
|
3651
3811
|
'settings.placement.immersiveHint': 'Aktif: tab Git memenuhi seluruh tinggi area percakapan dan kolom masukan mengalah; persetujuan dan pertanyaan tetap tampil.',
|
|
3652
3812
|
'preview.openFile': 'Buka di pratinjau berkas',
|
|
3813
|
+
'lf.added': '+{count}',
|
|
3814
|
+
'lf.deleted': '-{count}',
|
|
3815
|
+
'lf.selectFile': 'Pilih berkas untuk ditinjau',
|
|
3816
|
+
'lf.split': 'Ganti ke tampilan terbagi',
|
|
3817
|
+
'lf.unified': 'Ganti ke tampilan tunggal',
|
|
3818
|
+
'lf.wrap': 'Aktifkan pelipatan baris',
|
|
3819
|
+
'lf.nowrap': 'Nonaktifkan pelipatan baris',
|
|
3820
|
+
'lf.created': 'Berkas baru',
|
|
3821
|
+
'lf.removedFile': 'Berkas dihapus',
|
|
3822
|
+
'lf.truncated': 'Menampilkan {count} baris pertama',
|
|
3653
3823
|
'preview.title': 'Pratinjau Git',
|
|
3654
3824
|
'preview.hint': 'Klik “Tampilkan diff” pada file atau commit — diff terbuka di sini, di bilah sisi.',
|
|
3655
3825
|
'settings.rail.title': 'Tombol bilah aksi',
|
|
@@ -3865,6 +4035,16 @@ window.__ModuleLoader__.load({
|
|
|
3865
4035
|
'settings.placement.immersive': 'Chế độ đắm chìm (chiều cao đầy đủ, ẩn ô nhập)',
|
|
3866
4036
|
'settings.placement.immersiveHint': 'Bật: thẻ Git chiếm toàn bộ chiều cao vùng hội thoại và ô nhập thu vào; phê duyệt và câu hỏi vẫn hiển thị bình thường.',
|
|
3867
4037
|
'preview.openFile': 'Mở trong xem trước tệp',
|
|
4038
|
+
'lf.added': '+{count}',
|
|
4039
|
+
'lf.deleted': '-{count}',
|
|
4040
|
+
'lf.selectFile': 'Chọn tệp để xem',
|
|
4041
|
+
'lf.split': 'Chuyển sang xem đôi',
|
|
4042
|
+
'lf.unified': 'Chuyển sang xem đơn',
|
|
4043
|
+
'lf.wrap': 'Bật tự động xuống dòng',
|
|
4044
|
+
'lf.nowrap': 'Tắt tự động xuống dòng',
|
|
4045
|
+
'lf.created': 'Tệp mới tạo',
|
|
4046
|
+
'lf.removedFile': 'Tệp bị xóa',
|
|
4047
|
+
'lf.truncated': 'Chỉ hiện {count} dòng đầu',
|
|
3868
4048
|
'preview.title': 'Xem trước Git',
|
|
3869
4049
|
'preview.hint': 'Bấm “Xem diff” trên tệp hoặc commit — diff sẽ mở ở đây, trên thanh bên.',
|
|
3870
4050
|
'settings.rail.title': 'Nút thanh tác vụ',
|
|
@@ -4080,6 +4260,16 @@ window.__ModuleLoader__.load({
|
|
|
4080
4260
|
'settings.placement.immersive': 'الوضع الغامر (ارتفاع كامل، إخفاء صندوق الكتابة)',
|
|
4081
4261
|
'settings.placement.immersiveHint': 'عند التشغيل يملأ تبويب Git منطقة المحادثة بكامل ارتفاعها ويتراجع صندوق الكتابة؛ تظل الموافقات والأسئلة ظاهرة كالمعتاد.',
|
|
4082
4262
|
'preview.openFile': 'افتح في معاينة الملف',
|
|
4263
|
+
'lf.added': '+{count}',
|
|
4264
|
+
'lf.deleted': '-{count}',
|
|
4265
|
+
'lf.selectFile': 'اختر الملف للمراجعة',
|
|
4266
|
+
'lf.split': 'التبديل إلى العرض المنقسم',
|
|
4267
|
+
'lf.unified': 'التبديل إلى العرض الموحد',
|
|
4268
|
+
'lf.wrap': 'تمكين التفاف الأسطر',
|
|
4269
|
+
'lf.nowrap': 'تعطيل التفاف الأسطر',
|
|
4270
|
+
'lf.created': 'ملف جديد',
|
|
4271
|
+
'lf.removedFile': 'ملف محذوف',
|
|
4272
|
+
'lf.truncated': 'عرض أول {count} سطرًا فقط',
|
|
4083
4273
|
'preview.title': 'معاينة Git',
|
|
4084
4274
|
'preview.hint': 'انقر «عرض الفروق» على ملف أو commit — تُفتح الفروق هنا في الشريط الجانبي.',
|
|
4085
4275
|
'settings.rail.title': 'أزرار شريط الإجراءات',
|
|
@@ -4295,6 +4485,16 @@ window.__ModuleLoader__.load({
|
|
|
4295
4485
|
'settings.placement.immersive': 'इमर्सिव मोड (पूरी ऊँचाई, छिपा इनपुट बॉक्स)',
|
|
4296
4486
|
'settings.placement.immersiveHint': 'चालू होने पर Git टैब पूरे संवाद क्षेत्र की ऊँचाई घेर लेता है और इनपुट बॉक्स हट जाता है; अनुमोदन और प्रश्न फिर भी दिखते हैं।',
|
|
4297
4487
|
'preview.openFile': 'फ़ाइल पूर्वावलोकन में खोलें',
|
|
4488
|
+
'lf.added': '+{count}',
|
|
4489
|
+
'lf.deleted': '-{count}',
|
|
4490
|
+
'lf.selectFile': 'समीक्षा की फ़ाइल चुनें',
|
|
4491
|
+
'lf.split': 'स्प्लिट व्यू पर स्विच करें',
|
|
4492
|
+
'lf.unified': 'यूनिफाइड व्यू पर स्विच करें',
|
|
4493
|
+
'lf.wrap': 'लाइन रैप चालू करें',
|
|
4494
|
+
'lf.nowrap': 'लाइन रैप बंद करें',
|
|
4495
|
+
'lf.created': 'नई फ़ाइल',
|
|
4496
|
+
'lf.removedFile': 'हटाई गई फ़ाइल',
|
|
4497
|
+
'lf.truncated': 'केवल पहली {count} पंक्तियाँ दिखाई जा रही हैं',
|
|
4298
4498
|
'preview.title': 'Git पूर्वावलोकन',
|
|
4299
4499
|
'preview.hint': 'फ़ाइल या कमिट पर “अंतर दिखाएँ” पर क्लिक करें — अंतर यहीं साइडबार में खुलेगा।',
|
|
4300
4500
|
'settings.rail.title': 'एक्शन रेल बटन',
|
|
@@ -4510,6 +4710,16 @@ window.__ModuleLoader__.load({
|
|
|
4510
4710
|
'settings.placement.immersive': 'โหมดดื่มด่ำ (เต็มความสูง, ซ่อนกล่องพิมพ์)',
|
|
4511
4711
|
'settings.placement.immersiveHint': 'เมื่อเปิด แท็บ Git จะกินพื้นที่สูงทั้งหมดของบทสนทนาและกล่องพิมพ์จะถอยออก; การอนุมัติและคำถามยังแสดงตามปกติ',
|
|
4512
4712
|
'preview.openFile': 'เปิดในตัวอย่างไฟล์',
|
|
4713
|
+
'lf.added': '+{count}',
|
|
4714
|
+
'lf.deleted': '-{count}',
|
|
4715
|
+
'lf.selectFile': 'เลือกไฟล์ที่จะตรวจสอบ',
|
|
4716
|
+
'lf.split': 'สลับเป็นมุมมองคู่',
|
|
4717
|
+
'lf.unified': 'สลับเป็นมุมมองเดียว',
|
|
4718
|
+
'lf.wrap': 'เปิดการตัดบรรทัด',
|
|
4719
|
+
'lf.nowrap': 'ปิดการตัดบรรทัด',
|
|
4720
|
+
'lf.created': 'ไฟล์ที่สร้างใหม่',
|
|
4721
|
+
'lf.removedFile': 'ไฟล์ที่ถูกลบ',
|
|
4722
|
+
'lf.truncated': 'แสดงเฉพาะ {count} บรรทัดแรก',
|
|
4513
4723
|
'preview.title': 'ดูตัวอย่าง Git',
|
|
4514
4724
|
'preview.hint': 'คลิก “แสดงความต่าง” ที่ไฟล์หรือคอมมิต — ความต่างจะเปิดที่นี่ในแถบข้าง',
|
|
4515
4725
|
'settings.rail.title': 'ปุ่มแถบการทำงาน',
|
|
@@ -6228,70 +6438,415 @@ window.__ModuleLoader__.load({
|
|
|
6228
6438
|
)))
|
|
6229
6439
|
}
|
|
6230
6440
|
|
|
6231
|
-
/*
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
languageForPath
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6441
|
+
/* ---- external preview diff (v0.14.3): a faithful port of the review view ----
|
|
6442
|
+
ReviewTab + FileDiff (ui-deliverables) are the reference; every building
|
|
6443
|
+
block that package imports from the platform seed is reused here
|
|
6444
|
+
verbatim: Menu / PathLabel / Tooltip / the split, wrap, inspect and
|
|
6445
|
+
chevron icons, useCodeHighlighter, languageForPath, and the file-diff
|
|
6446
|
+
alias tokens. Only the layer the official bundle boundary hides — the
|
|
6447
|
+
row layout, the hunk parser, the review-store-free state — lives in
|
|
6448
|
+
this file, and it follows the source file by file: header anatomy and
|
|
6449
|
+
CSS from ReviewTab.tsx + ReviewTab.module.css, rows/hunks/highlights
|
|
6450
|
+
from FileDiff.tsx + FileDiff.module.css. When ui-deliverables
|
|
6451
|
+
re-exports FileDiff (see the host-follow note in AGENTS.md), this whole
|
|
6452
|
+
block retires in favor of a plain import of the deliverables
|
|
6453
|
+
package's re-exported FileDiff. */
|
|
6454
|
+
|
|
6455
|
+
/* One hunk in the shape FileDiff consumes: {oldStart, oldLines, newStart,
|
|
6456
|
+
newLines, lines[]} where lines keep their +/-/space prefix. oldLines and
|
|
6457
|
+
newLines are COUNTED from content (git omits the count when it is 1),
|
|
6458
|
+
exactly what the reconstructed @@ header needs. */
|
|
6459
|
+
function parseHunks(body) {
|
|
6460
|
+
const text = typeof body === 'string' ? body : ''
|
|
6461
|
+
const out = []
|
|
6462
|
+
let current = null
|
|
6463
|
+
for (const line of text.split('\n')) {
|
|
6464
|
+
if (line.indexOf('@@') === 0) {
|
|
6465
|
+
const match = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line)
|
|
6466
|
+
if (match !== null) {
|
|
6467
|
+
if (current !== null && current.lines.length > 0) out.push(current)
|
|
6468
|
+
current = { oldStart: Number.parseInt(match[1], 10), newStart: Number.parseInt(match[3], 10), oldLines: 0, newLines: 0, lines: [] }
|
|
6469
|
+
continue
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6472
|
+
if (current === null) continue
|
|
6473
|
+
const marker = line.charAt(0)
|
|
6474
|
+
if (marker === '+' || marker === '-' || marker === ' ' || line === '') {
|
|
6475
|
+
current.lines.push(line)
|
|
6476
|
+
if (marker === '+') current.newLines += 1
|
|
6477
|
+
else if (marker === '-') current.oldLines += 1
|
|
6478
|
+
else { current.oldLines += 1; current.newLines += 1 }
|
|
6479
|
+
} else if (line.indexOf('\\') === 0) {
|
|
6480
|
+
current.lines.push(line)
|
|
6248
6481
|
}
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6482
|
+
}
|
|
6483
|
+
if (current !== null && current.lines.length > 0) out.push(current)
|
|
6484
|
+
/* The patch's trailing newline parses as one empty context line; the
|
|
6485
|
+
review drops it, and so does this. */
|
|
6486
|
+
for (const hunk of out) {
|
|
6487
|
+
const last = hunk.lines[hunk.lines.length - 1]
|
|
6488
|
+
if (last === '' && hunk.lines.length > 1) {
|
|
6489
|
+
hunk.lines.pop()
|
|
6490
|
+
hunk.oldLines -= 1
|
|
6491
|
+
hunk.newLines -= 1
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6494
|
+
return out
|
|
6495
|
+
}
|
|
6496
|
+
|
|
6497
|
+
/* One file segment of a (possibly multi-file) patch: path, hunks, ±
|
|
6498
|
+
counts, and the file-level facts FileDiff's notes need. */
|
|
6499
|
+
function splitPatchFiles(patch) {
|
|
6500
|
+
const text = typeof patch === 'string' ? patch : ''
|
|
6501
|
+
if (text.trim() === '') return []
|
|
6502
|
+
const segments = []
|
|
6503
|
+
let current = null
|
|
6504
|
+
for (const line of text.split('\n')) {
|
|
6505
|
+
if (line.indexOf('diff --git ') === 0) {
|
|
6506
|
+
if (current !== null) segments.push(current)
|
|
6507
|
+
current = { path: '', meta: [], body: [], binary: false, created: false, removed: false }
|
|
6508
|
+
continue
|
|
6509
|
+
}
|
|
6510
|
+
if (current === null) continue
|
|
6511
|
+
if (line.indexOf('+++ ') === 0) current.path = line.slice(4) === '/dev/null' ? current.path : line.slice(4).replace(/^b\//, '')
|
|
6512
|
+
else if (current.path === '' && line.indexOf('--- a/') === 0) current.path = line.slice(6)
|
|
6513
|
+
if (line.indexOf('Binary files') === 0 || line.indexOf('Binary file') === 0) current.binary = true
|
|
6514
|
+
if (line.indexOf('new file mode') === 0) current.created = true
|
|
6515
|
+
if (line.indexOf('deleted file mode') === 0) current.removed = true
|
|
6516
|
+
if (line.indexOf('diff --git ') === 0 || line.indexOf('index ') === 0 || line.indexOf('--- ') === 0 || line.indexOf('+++ ') === 0 || line.indexOf('new file') === 0 || line.indexOf('deleted file') === 0 || line.indexOf('similarity index') === 0 || line.indexOf('rename ') === 0 || line.indexOf('old mode') === 0 || line.indexOf('new mode') === 0) current.meta.push(line)
|
|
6517
|
+
else current.body.push(line)
|
|
6518
|
+
}
|
|
6519
|
+
if (current !== null) segments.push(current)
|
|
6520
|
+
const out = []
|
|
6521
|
+
for (const segment of segments) {
|
|
6522
|
+
const hunks = parseHunks(segment.body.join('\n'))
|
|
6523
|
+
let adds = 0
|
|
6524
|
+
let dels = 0
|
|
6525
|
+
for (const hunk of hunks) {
|
|
6526
|
+
for (const line of hunk.lines) {
|
|
6527
|
+
if (line.indexOf('+') === 0) adds += 1
|
|
6528
|
+
else if (line.indexOf('-') === 0) dels += 1
|
|
6257
6529
|
}
|
|
6258
6530
|
}
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6531
|
+
if (segment.path === '' && hunks.length === 0 && segment.binary === false) continue
|
|
6532
|
+
out.push({ path: segment.path, binary: segment.binary, created: segment.created, removed: segment.removed, hunks: hunks, adds: adds, dels: dels })
|
|
6533
|
+
}
|
|
6534
|
+
return out
|
|
6535
|
+
}
|
|
6536
|
+
|
|
6537
|
+
/* ---- pure ports of FileDiff.tsx's exported row functions ---- */
|
|
6538
|
+
|
|
6539
|
+
/* Number a hunk's lines: context lines count on both sides, deletions on
|
|
6540
|
+
the old side, additions on the new side. */
|
|
6541
|
+
function hunkRows(hunk) {
|
|
6542
|
+
let oldNo = hunk.oldStart
|
|
6543
|
+
let newNo = hunk.newStart
|
|
6544
|
+
return hunk.lines.map((line) => {
|
|
6545
|
+
const body = line.slice(1)
|
|
6546
|
+
if (line.indexOf('+') === 0) return { kind: 'add', old: undefined, new: newNo++, text: body }
|
|
6547
|
+
if (line.indexOf('-') === 0) return { kind: 'del', old: oldNo++, new: undefined, text: body }
|
|
6548
|
+
return { kind: 'context', old: oldNo++, new: newNo++, text: body }
|
|
6549
|
+
})
|
|
6550
|
+
}
|
|
6551
|
+
|
|
6552
|
+
/* Pair a hunk's lines for the side-by-side view: each run of deletions is
|
|
6553
|
+
aligned with the run of additions that follows it, row by row, and
|
|
6554
|
+
context lines sit on both sides. */
|
|
6555
|
+
function splitRows(hunk) {
|
|
6556
|
+
const rows = []
|
|
6557
|
+
let dels = []
|
|
6558
|
+
let adds = []
|
|
6559
|
+
const flush = () => {
|
|
6560
|
+
for (let at = 0; at < Math.max(dels.length, adds.length); at += 1) {
|
|
6561
|
+
const left = dels[at]
|
|
6562
|
+
const right = adds[at]
|
|
6563
|
+
rows.push(Object.assign(left === undefined ? {} : { left: left }, right === undefined ? {} : { right: right }))
|
|
6271
6564
|
}
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6565
|
+
dels = []
|
|
6566
|
+
adds = []
|
|
6567
|
+
}
|
|
6568
|
+
for (const row of hunkRows(hunk)) {
|
|
6569
|
+
if (row.kind === 'del') dels.push({ no: row.old, text: row.text, kind: 'del' })
|
|
6570
|
+
else if (row.kind === 'add') adds.push({ no: row.new, text: row.text, kind: 'add' })
|
|
6571
|
+
else {
|
|
6572
|
+
flush()
|
|
6573
|
+
rows.push({ left: { no: row.old, text: row.text, kind: 'context' }, right: { no: row.new, text: row.text, kind: 'context' } })
|
|
6574
|
+
}
|
|
6575
|
+
}
|
|
6576
|
+
flush()
|
|
6577
|
+
return rows
|
|
6578
|
+
}
|
|
6579
|
+
|
|
6580
|
+
/* The hunks to draw, cut at LINEDIFF_MAX_LINES lines in total. */
|
|
6581
|
+
const LINEDIFF_MAX_LINES = 5000
|
|
6582
|
+
function renderedHunks(hunks) {
|
|
6583
|
+
let budget = LINEDIFF_MAX_LINES
|
|
6584
|
+
const kept = []
|
|
6585
|
+
for (const hunk of hunks) {
|
|
6586
|
+
if (budget === 0) return { hunks: kept, truncated: true }
|
|
6587
|
+
kept.push(hunk.lines.length <= budget ? hunk : Object.assign({}, hunk, { lines: hunk.lines.slice(0, budget) }))
|
|
6588
|
+
budget -= Math.min(budget, hunk.lines.length)
|
|
6589
|
+
}
|
|
6590
|
+
return { hunks: kept, truncated: hunks.some((hunk, at) => kept[at] !== hunk) }
|
|
6591
|
+
}
|
|
6592
|
+
|
|
6593
|
+
function hunkHeader(hunk) {
|
|
6594
|
+
return '@@ -' + String(hunk.oldStart) + ',' + String(hunk.oldLines) + ' +' + String(hunk.newStart) + ',' + String(hunk.newLines) + ' @@'
|
|
6595
|
+
}
|
|
6596
|
+
|
|
6597
|
+
/* Per-hunk, per-side Shiki alignment (the FileDiff rule): each side's
|
|
6598
|
+
lines join into ONE fragment so multi-line grammars hold, and the
|
|
6599
|
+
per-line spans map back by line number. */
|
|
6600
|
+
function hunkSideSpans(rows, side, highlighter) {
|
|
6601
|
+
if (highlighter === undefined) return undefined
|
|
6602
|
+
const source = []
|
|
6603
|
+
for (const row of rows) {
|
|
6604
|
+
const no = row[side]
|
|
6605
|
+
if (no === undefined) continue
|
|
6606
|
+
source.push({ no: no, text: row.text })
|
|
6607
|
+
}
|
|
6608
|
+
if (source.length === 0) return new Map()
|
|
6609
|
+
const highlighted = highlighter(source.map((line) => line.text).join('\n'))
|
|
6610
|
+
if (highlighted === undefined) return undefined
|
|
6611
|
+
const map = new Map()
|
|
6612
|
+
source.forEach((line, index) => { map.set(line.no, highlighted[index] || []) })
|
|
6613
|
+
return map
|
|
6614
|
+
}
|
|
6615
|
+
|
|
6616
|
+
function hunkHighlights(hunk, highlighter) {
|
|
6617
|
+
const rows = hunkRows(hunk)
|
|
6618
|
+
return { old: hunkSideSpans(rows, 'old', highlighter), new: hunkSideSpans(rows, 'new', highlighter) }
|
|
6619
|
+
}
|
|
6620
|
+
|
|
6621
|
+
/* split/wrap preferences are habits, not tab state — one localStorage
|
|
6622
|
+
home, the same policy as the tree folds. */
|
|
6623
|
+
const LINEDIFF_KEY = 'dsh-ide-git.linediff.v1'
|
|
6624
|
+
function readLineDiffPrefs() {
|
|
6625
|
+
try {
|
|
6626
|
+
const raw = window.localStorage.getItem(LINEDIFF_KEY)
|
|
6627
|
+
const parsed = raw === null ? null : JSON.parse(raw)
|
|
6628
|
+
return parsed !== null && typeof parsed === 'object'
|
|
6629
|
+
? { split: parsed.split === true, wrap: parsed.wrap === true }
|
|
6630
|
+
: { split: false, wrap: false }
|
|
6631
|
+
} catch (error) { void error }
|
|
6632
|
+
return { split: false, wrap: false }
|
|
6633
|
+
}
|
|
6634
|
+
function writeLineDiffPrefs(prefs) {
|
|
6635
|
+
try { window.localStorage.setItem(LINEDIFF_KEY, JSON.stringify(prefs)) } catch (error) { void error }
|
|
6636
|
+
}
|
|
6637
|
+
|
|
6638
|
+
/* The seed blocks the official review uses, resolved once. Every consumer
|
|
6639
|
+
null-checks: a host whose primitives predate an export keeps working
|
|
6640
|
+
through the hand-drawn fallbacks (labels instead of icons, a plain
|
|
6641
|
+
select instead of Menu). */
|
|
6642
|
+
const SeedMenu = UIPrimitives !== null && typeof UIPrimitives.Menu === 'function' ? UIPrimitives.Menu : null
|
|
6643
|
+
const SeedPathLabel = UIPrimitives !== null && typeof UIPrimitives.PathLabel === 'function' ? UIPrimitives.PathLabel : null
|
|
6644
|
+
const SeedTooltip = UIPrimitives !== null && typeof UIPrimitives.Tooltip === 'function' ? UIPrimitives.Tooltip : null
|
|
6645
|
+
const SeedIcons = UIPrimitives !== null ? UIPrimitives : {}
|
|
6646
|
+
|
|
6647
|
+
function DiffText(props) {
|
|
6648
|
+
return E('span', { className: 'dig-lf-text', 'data-diff-code': props.spans === undefined ? undefined : '' },
|
|
6649
|
+
props.spans === undefined || props.spans === null || props.spans.length === 0
|
|
6650
|
+
? (props.text === '' ? ' ' : props.text)
|
|
6651
|
+
: props.spans.map((span, at) => E('span', { key: at, style: span.style }, span.text)))
|
|
6652
|
+
}
|
|
6653
|
+
|
|
6654
|
+
/* The unified row: old number, new number, sign, text (FileDiff's .line). */
|
|
6655
|
+
function UnifiedLine(props) {
|
|
6656
|
+
const row = props.row
|
|
6657
|
+
const spans = props.spans
|
|
6658
|
+
return E('div', { className: 'dig-lf-line dig-lf-' + row.kind, 'data-diff-line': row.kind },
|
|
6659
|
+
E('span', { className: 'dig-lf-number' }, row.old === undefined ? '' : String(row.old)),
|
|
6660
|
+
E('span', { className: 'dig-lf-number' }, row.new === undefined ? '' : String(row.new)),
|
|
6661
|
+
E('span', { className: 'dig-lf-sign' }, row.kind === 'add' ? '+' : row.kind === 'del' ? '\u2212' : ' '),
|
|
6662
|
+
E(DiffText, { text: row.text, spans: row.kind === 'add' ? spans.new.get(row.new) : spans.old.get(row.old) }))
|
|
6663
|
+
}
|
|
6664
|
+
|
|
6665
|
+
/* The wrapped split row: two cells, each its own number + text. */
|
|
6666
|
+
function SplitLine(props) {
|
|
6667
|
+
const row = props.row
|
|
6668
|
+
const spans = props.spans
|
|
6669
|
+
const kind = row.left !== undefined && row.left.kind === 'del' ? 'del' : row.right !== undefined && row.right.kind === 'add' ? 'add' : 'context'
|
|
6670
|
+
return E('div', { className: 'dig-lf-splitLine', 'data-diff-line': kind },
|
|
6671
|
+
E('span', { className: 'dig-lf-cell ' + (row.left === undefined ? 'dig-lf-empty' : 'dig-lf-' + row.left.kind) },
|
|
6672
|
+
E('span', { className: 'dig-lf-number' }, row.left === undefined ? '' : String(row.left.no)),
|
|
6673
|
+
E(DiffText, { text: row.left === undefined ? '' : row.left.text, spans: row.left === undefined || spans.old === undefined ? undefined : spans.old.get(row.left.no) })),
|
|
6674
|
+
E('span', { className: 'dig-lf-cell ' + (row.right === undefined ? 'dig-lf-empty' : 'dig-lf-' + row.right.kind) },
|
|
6675
|
+
E('span', { className: 'dig-lf-number' }, row.right === undefined ? '' : String(row.right.no)),
|
|
6676
|
+
E(DiffText, { text: row.right === undefined ? '' : row.right.text, spans: row.right === undefined || spans.new === undefined ? undefined : spans.new.get(row.right.no) })))
|
|
6677
|
+
}
|
|
6678
|
+
|
|
6679
|
+
/* The no-wrap split: two columns that scroll together (FileDiff's
|
|
6680
|
+
SplitColumns). The sync mirrors the source's offset-record loop. */
|
|
6681
|
+
function SplitColumns(props) {
|
|
6682
|
+
const hunks = props.hunks
|
|
6683
|
+
const highlights = props.highlights
|
|
6684
|
+
const paired = useMemo(() => hunks.map((hunk) => ({ header: hunkHeader(hunk), rows: splitRows(hunk) })), [hunks])
|
|
6685
|
+
const leftRef = useRef(null)
|
|
6686
|
+
const rightRef = useRef(null)
|
|
6687
|
+
const offsets = useRef({ left: { x: 0, y: 0 }, right: { x: 0, y: 0 } })
|
|
6688
|
+
const follow = (side) => (event) => {
|
|
6689
|
+
const peer = side === 'left' ? rightRef : leftRef
|
|
6690
|
+
const other = peer.current
|
|
6691
|
+
if (other === null) return
|
|
6692
|
+
for (const axis of ['scrollLeft', 'scrollTop']) {
|
|
6693
|
+
const value = event.currentTarget[axis]
|
|
6694
|
+
const key = axis === 'scrollLeft' ? 'x' : 'y'
|
|
6695
|
+
if (offsets.current[side][key] === value) continue
|
|
6696
|
+
offsets.current[side][key] = value
|
|
6697
|
+
other[axis] = value
|
|
6698
|
+
offsets.current[side === 'left' ? 'right' : 'left'][key] = other[axis]
|
|
6699
|
+
}
|
|
6700
|
+
}
|
|
6701
|
+
return E('div', { className: 'dig-lf-columns' },
|
|
6702
|
+
['left', 'right'].map((side) => E('div', {
|
|
6703
|
+
key: side,
|
|
6704
|
+
className: 'dig-lf-column',
|
|
6705
|
+
'data-diff-side': side,
|
|
6706
|
+
ref: side === 'left' ? leftRef : rightRef,
|
|
6707
|
+
onScroll: follow(side),
|
|
6708
|
+
}, paired.map((hunk, position) => E('section', { key: position, className: 'dig-lf-hunk' },
|
|
6709
|
+
E('div', { className: 'dig-lf-hunkHeader', 'data-diff-hunk-header': '' }, hunk.header),
|
|
6710
|
+
hunk.rows.map((row, at) => {
|
|
6711
|
+
const cell = row[side]
|
|
6712
|
+
const spans = cell === undefined ? undefined : highlights[position][side === 'left' ? 'old' : 'new']
|
|
6713
|
+
return E('div', {
|
|
6714
|
+
key: at,
|
|
6715
|
+
className: 'dig-lf-sideLine ' + (cell === undefined ? 'dig-lf-empty' : 'dig-lf-' + cell.kind),
|
|
6716
|
+
},
|
|
6717
|
+
E('span', { className: 'dig-lf-number' }, cell === undefined ? '' : String(cell.no)),
|
|
6718
|
+
E(DiffText, { text: cell === undefined ? '' : cell.text, spans: cell === undefined || spans === undefined ? undefined : spans.get(cell.no) }))
|
|
6719
|
+
}))))))
|
|
6720
|
+
}
|
|
6721
|
+
|
|
6722
|
+
/* One toolbar button in the review's tool style; Tooltip-wrapped when the
|
|
6723
|
+
seed provides it, a title attribute otherwise. */
|
|
6724
|
+
function LineDiffTool(props) {
|
|
6725
|
+
const inner = E('button', {
|
|
6726
|
+
type: 'button',
|
|
6727
|
+
className: 'dig-lf-tool',
|
|
6728
|
+
'aria-pressed': props.pressed,
|
|
6729
|
+
'aria-label': props.label,
|
|
6730
|
+
'data-review-tool': props.tool,
|
|
6731
|
+
onClick: props.onClick,
|
|
6732
|
+
}, props.children)
|
|
6733
|
+
if (SeedTooltip === null) {
|
|
6734
|
+
return E('span', { title: props.label }, inner)
|
|
6735
|
+
}
|
|
6736
|
+
return E(SeedTooltip, { label: props.label, side: 'bottom', delayMs: 500 }, inner)
|
|
6737
|
+
}
|
|
6738
|
+
|
|
6739
|
+
/* The external preview's diff view: the official review's header (file
|
|
6740
|
+
selector + counts + split/wrap/open tools) over the official row
|
|
6741
|
+
anatomy, fed by the plugin's own patch text instead of the host's
|
|
6742
|
+
workspace-changes events. */
|
|
6743
|
+
function LineDiff(props) {
|
|
6744
|
+
const t = props.t
|
|
6745
|
+
const files = useMemo(() => splitPatchFiles(props.patch), [props.patch])
|
|
6746
|
+
const [active, setActive] = useState(0)
|
|
6747
|
+
const [prefs, setPrefs] = useState(readLineDiffPrefs)
|
|
6748
|
+
useEffect(() => { writeLineDiffPrefs(prefs) }, [prefs])
|
|
6749
|
+
const [menuOpen, setMenuOpen] = useState(false)
|
|
6750
|
+
const index = active < files.length ? active : 0
|
|
6751
|
+
const file = files[index]
|
|
6752
|
+
const language = useMemo(() => (languageForPathSeed === null || file === undefined || file.path === '') ? undefined : languageForPathSeed(file.path), [file])
|
|
6753
|
+
const highlighter = useCodeHighlighterSeed === null ? undefined : useCodeHighlighterSeed(language)
|
|
6754
|
+
const cut = useMemo(() => {
|
|
6755
|
+
if (file === undefined) return { hunks: [], truncated: false, maps: [] }
|
|
6756
|
+
const result = renderedHunks(file.hunks)
|
|
6757
|
+
return { hunks: result.hunks, truncated: result.truncated, maps: result.hunks.map((hunk) => hunkHighlights(hunk, highlighter)) }
|
|
6758
|
+
}, [file, highlighter])
|
|
6759
|
+
const hasAdditions = file !== undefined && file.hunks.some((hunk) => hunk.lines.some((line) => line.indexOf('+') === 0))
|
|
6760
|
+
const hasDeletions = file !== undefined && file.hunks.some((hunk) => hunk.lines.some((line) => line.indexOf('-') === 0))
|
|
6761
|
+
const oneSided = hasAdditions !== hasDeletions
|
|
6762
|
+
const split = prefs.split === true && oneSided !== true
|
|
6763
|
+
const wrap = prefs.wrap === true
|
|
6764
|
+
if (props.loading === true) return E('div', { className: 'dig-lf-root' }, E('p', { className: 'dig-lf-status', role: 'status' }, t('diff.loading')))
|
|
6765
|
+
if (file === undefined) return E('div', { className: 'dig-lf-root' }, E('p', { className: 'dig-lf-status' }, t('diff.empty')))
|
|
6766
|
+
/* header: selector + counts + tools (ReviewTab anatomy) */
|
|
6767
|
+
const counts = file.binary === true
|
|
6768
|
+
? E('span', { className: 'dig-lf-label' }, t('diff.binary'))
|
|
6769
|
+
: E('span', { className: 'dig-lf-counts' },
|
|
6770
|
+
E('span', { className: 'dig-lf-added' }, fill(t('lf.added'), { count: String(file.adds) })),
|
|
6771
|
+
E('span', { className: 'dig-lf-deleted' }, fill(t('lf.deleted'), { count: String(file.dels) })))
|
|
6772
|
+
const selectorButton = E('button', {
|
|
6773
|
+
type: 'button',
|
|
6774
|
+
className: 'dig-lf-selectorButton',
|
|
6775
|
+
'aria-haspopup': 'menu',
|
|
6776
|
+
'aria-expanded': menuOpen,
|
|
6777
|
+
'aria-label': t('lf.selectFile'),
|
|
6778
|
+
title: file.path,
|
|
6779
|
+
'data-review-file': file.path,
|
|
6780
|
+
onClick: () => { setMenuOpen((value) => !value) },
|
|
6781
|
+
},
|
|
6782
|
+
SeedPathLabel === null ? file.path : E(SeedPathLabel, { path: file.path }),
|
|
6783
|
+
SeedIcons.IconChevronDownOutlineRegular === undefined ? '\u25be' : E(SeedIcons.IconChevronDownOutlineRegular, { size: 12 }))
|
|
6784
|
+
const selector = files.length > 1
|
|
6785
|
+
? (SeedMenu === null
|
|
6786
|
+
? E('select', {
|
|
6787
|
+
className: 'dig-lf-selectorFallback',
|
|
6788
|
+
value: String(index),
|
|
6789
|
+
'aria-label': t('lf.selectFile'),
|
|
6790
|
+
onChange: (event) => { setActive(Number(event.target.value)) },
|
|
6791
|
+
}, files.map((entry, at) => E('option', { key: at, value: String(at) }, entry.path + ' +' + String(entry.adds) + ' -' + String(entry.dels))))
|
|
6792
|
+
: E(SeedMenu, {
|
|
6793
|
+
className: 'dig-lf-selector',
|
|
6794
|
+
open: menuOpen,
|
|
6795
|
+
autoFocus: true,
|
|
6796
|
+
portal: true,
|
|
6797
|
+
align: 'start',
|
|
6798
|
+
dense: true,
|
|
6799
|
+
onClose: () => { setMenuOpen(false) },
|
|
6800
|
+
anchor: selectorButton,
|
|
6801
|
+
items: files.map((entry, at) => ({
|
|
6802
|
+
id: String(at),
|
|
6803
|
+
label: E('span', { className: 'dig-lf-item' },
|
|
6804
|
+
E('span', { className: 'dig-lf-itemPath' }, entry.path),
|
|
6805
|
+
E('span', { className: 'dig-lf-itemCounts' },
|
|
6806
|
+
E('span', { className: 'dig-lf-added' }, fill(t('lf.added'), { count: String(entry.adds) })),
|
|
6807
|
+
E('span', { className: 'dig-lf-deleted' }, fill(t('lf.deleted'), { count: String(entry.dels) })))),
|
|
6808
|
+
})),
|
|
6809
|
+
selectedId: String(index),
|
|
6810
|
+
onSelect: (id) => { setActive(Number(id)); setMenuOpen(false) },
|
|
6811
|
+
}))
|
|
6812
|
+
: E('span', { className: 'dig-lf-selectorStatic', title: file.path },
|
|
6813
|
+
SeedPathLabel === null ? file.path : E(SeedPathLabel, { path: file.path }))
|
|
6814
|
+
return E('div', { className: 'dig-lf-root' },
|
|
6815
|
+
E('div', { className: 'dig-lf-header' },
|
|
6816
|
+
selector,
|
|
6817
|
+
counts,
|
|
6818
|
+
E('span', { className: 'dig-lf-tools' },
|
|
6819
|
+
E(LineDiffTool, {
|
|
6820
|
+
tool: 'split', pressed: split, label: t(split === true ? 'lf.unified' : 'lf.split'),
|
|
6821
|
+
onClick: () => { setPrefs((now) => Object.assign({}, now, { split: now.split !== true })) },
|
|
6822
|
+
}, SeedIcons.IconCompareSplitOutlineRegular === undefined ? E(Icon, { name: 'split', size: 13 }) : E(SeedIcons.IconCompareSplitOutlineRegular, { className: 'dig-lf-compareIcon' })),
|
|
6823
|
+
E(LineDiffTool, {
|
|
6824
|
+
tool: 'wrap', pressed: wrap, label: t(wrap === true ? 'lf.nowrap' : 'lf.wrap'),
|
|
6825
|
+
onClick: () => { setPrefs((now) => Object.assign({}, now, { wrap: now.wrap !== true })) },
|
|
6826
|
+
}, SeedIcons.IconWrapFillRegular === undefined || SeedIcons.IconNowrapFillRegular === undefined
|
|
6827
|
+
? E(Icon, { name: 'wrap', size: 13 })
|
|
6828
|
+
: (wrap === true ? E(SeedIcons.IconNowrapFillRegular) : E(SeedIcons.IconWrapFillRegular))),
|
|
6829
|
+
props.onOpenFile === undefined ? null : E(LineDiffTool, {
|
|
6830
|
+
tool: 'open-file', label: t('preview.openFile'),
|
|
6831
|
+
onClick: props.onOpenFile,
|
|
6832
|
+
}, SeedIcons.IconInspectOutlineRegular === undefined ? E(Icon, { name: 'file', size: 13 }) : E(SeedIcons.IconInspectOutlineRegular)),
|
|
6833
|
+
)),
|
|
6834
|
+
file.binary === true
|
|
6835
|
+
? E('p', { className: 'dig-lf-status' }, t('diff.binary'))
|
|
6836
|
+
: E('div', { className: 'dig-lf-body', 'data-review-view': split === true ? 'split' : 'unified', 'data-review-wrap': wrap === true ? '' : undefined },
|
|
6837
|
+
file.created === true ? E('p', { className: 'dig-lf-note' }, t('lf.created')) : null,
|
|
6838
|
+
file.removed === true ? E('p', { className: 'dig-lf-note' }, t('lf.removedFile')) : null,
|
|
6839
|
+
cut.truncated === true ? E('p', { className: 'dig-lf-note' }, fill(t('lf.truncated'), { count: String(LINEDIFF_MAX_LINES) })) : null,
|
|
6840
|
+
split === true && wrap !== true
|
|
6841
|
+
? E(SplitColumns, { hunks: cut.hunks, highlights: cut.maps })
|
|
6842
|
+
: cut.hunks.map((hunk, position) => {
|
|
6843
|
+
const paired = split === true ? splitRows(hunk) : null
|
|
6844
|
+
return E('section', { key: position, className: 'dig-lf-hunk' },
|
|
6845
|
+
E('div', { className: 'dig-lf-hunkHeader', 'data-diff-hunk-header': '' }, hunkHeader(hunk)),
|
|
6846
|
+
hunkRows(hunk).map((row, at) => split === true
|
|
6847
|
+
? E(SplitLine, { key: at, row: paired[at], spans: cut.maps[position] })
|
|
6848
|
+
: E(UnifiedLine, { key: at, row: row, spans: cut.maps[position] })))
|
|
6849
|
+
})))
|
|
6295
6850
|
}
|
|
6296
6851
|
|
|
6297
6852
|
/* The leading glyph of a change row (v0.14): the host's FileTypeIcon —
|
|
@@ -9599,23 +10154,57 @@ window.__ModuleLoader__.load({
|
|
|
9599
10154
|
'.dig-preview-actions{display:flex;align-items:center;gap:4px;flex:none}',
|
|
9600
10155
|
'.dig-preview-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}',
|
|
9601
10156
|
'.dig-preview-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}',
|
|
9602
|
-
/* LineDiff: the
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
'.dig-
|
|
9607
|
-
'.dig-
|
|
9608
|
-
'.dig-
|
|
9609
|
-
'.dig-
|
|
9610
|
-
'.dig-
|
|
9611
|
-
'.dig-
|
|
9612
|
-
'.dig-
|
|
9613
|
-
'.dig-
|
|
9614
|
-
'.dig-
|
|
9615
|
-
'.dig-
|
|
9616
|
-
'.dig-
|
|
9617
|
-
'.dig-
|
|
9618
|
-
'.dig-
|
|
10157
|
+
/* LineDiff (v0.14.3): the review view's anatomy on its own tokens —
|
|
10158
|
+
every rule below mirrors FileDiff.module.css / ReviewTab.module.css
|
|
10159
|
+
line for line (class dig-lf- stands in for their css modules), so the
|
|
10160
|
+
official theme and reading habits carry over. */
|
|
10161
|
+
'.dig-lf-root{--diff-empty-fill:color-mix(in srgb,var(--dsw-alias-interactive-bg-hover) 50%,transparent);display:flex;flex-direction:column;box-sizing:border-box;width:100%;min-height:0;color:var(--dsw-alias-label-primary)}',
|
|
10162
|
+
'.dig-lf-header{display:flex;flex:0 0 auto;gap:6px;align-items:center;box-sizing:border-box;min-height:38px;padding:0 6px 0 8px;border-bottom:0.5px solid var(--dsw-alias-border-l3)}',
|
|
10163
|
+
'.dig-lf-status{display:flex;gap:12px;align-items:center;margin:0;padding:16px;font-size:13px;color:var(--dsw-alias-label-secondary)}',
|
|
10164
|
+
'.dig-lf-body{display:flex;flex:1 1 auto;flex-direction:column;min-height:0;overflow:auto;padding:8px 0 16px;font:var(--dsw-font-markdown-code-block)}',
|
|
10165
|
+
'.dig-lf-columns{display:grid;flex:1 1 auto;grid-template-columns:minmax(0,1fr) minmax(0,1fr);min-height:0}',
|
|
10166
|
+
'.dig-lf-column,.dig-lf-body[data-review-view=unified]:not([data-review-wrap]){display:grid;grid-template-columns:minmax(max-content,100%);align-content:start}',
|
|
10167
|
+
'.dig-lf-column{min-width:0;overflow-x:scroll;overscroll-behavior:none}',
|
|
10168
|
+
'.dig-lf-column + .dig-lf-column{border-left:0.5px solid var(--dsw-alias-border-l3)}',
|
|
10169
|
+
'.dig-lf-sideLine{display:grid;grid-template-columns:3.5em max-content;box-sizing:border-box;min-width:100%;width:max-content;min-height:22px;line-height:22px;white-space:pre}',
|
|
10170
|
+
'.dig-lf-note{margin:0;padding:4px 16px 8px;font:var(--dsw-font-xs-13,var(--dsw-font-markdown-code-block));color:var(--dsw-alias-label-tertiary)}',
|
|
10171
|
+
'.dig-lf-hunk{margin-bottom:8px}',
|
|
10172
|
+
'.dig-lf-hunkHeader{padding:4px 16px;color:var(--dsw-alias-label-tertiary);white-space:pre}',
|
|
10173
|
+
'.dig-lf-line{display:grid;grid-template-columns:3.5em 3.5em 1.2em minmax(0,1fr);box-sizing:border-box;min-height:22px;line-height:22px;white-space:pre}',
|
|
10174
|
+
'.dig-lf-splitLine{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);min-height:22px;line-height:22px;white-space:pre}',
|
|
10175
|
+
'.dig-lf-cell{display:grid;grid-template-columns:3.5em minmax(0,1fr);box-sizing:border-box;min-width:0}',
|
|
10176
|
+
'.dig-lf-cell + .dig-lf-cell{border-left:0.5px solid var(--dsw-alias-border-l3)}',
|
|
10177
|
+
'.dig-lf-number{padding-right:8px;color:var(--dsw-alias-label-tertiary);text-align:right;user-select:none}',
|
|
10178
|
+
'.dig-lf-sign{text-align:center;user-select:none}',
|
|
10179
|
+
'.dig-lf-text{padding-right:16px}',
|
|
10180
|
+
'.dig-lf-body[data-review-wrap] .dig-lf-line,.dig-lf-body[data-review-wrap] .dig-lf-splitLine{white-space:pre-wrap}',
|
|
10181
|
+
'.dig-lf-body[data-review-wrap] .dig-lf-text{overflow-wrap:anywhere}',
|
|
10182
|
+
'.dig-lf-add{--diff-gutter-fill:var(--dsw-alias-file-diff-added-gutter);--diff-marker:var(--dsw-alias-file-diff-added-marker);background:var(--dsw-alias-file-diff-added-bg)}',
|
|
10183
|
+
'.dig-lf-del{--diff-gutter-fill:var(--dsw-alias-file-diff-deleted-gutter);--diff-marker:var(--dsw-alias-file-diff-deleted-marker);background:var(--dsw-alias-file-diff-deleted-bg)}',
|
|
10184
|
+
'.dig-lf-add .dig-lf-number,.dig-lf-del .dig-lf-number{background:var(--diff-gutter-fill);color:var(--diff-marker)}',
|
|
10185
|
+
'.dig-lf-add .dig-lf-number:first-child,.dig-lf-del .dig-lf-number:first-child{box-shadow:inset 3px 0 0 var(--diff-marker)}',
|
|
10186
|
+
'.dig-lf-add .dig-lf-sign,.dig-lf-del .dig-lf-sign{color:var(--diff-marker)}',
|
|
10187
|
+
'.dig-lf-context .dig-lf-text{color:var(--dsw-alias-label-secondary)}',
|
|
10188
|
+
'.dig-lf-empty{background:var(--diff-empty-fill)}',
|
|
10189
|
+
/* header pieces from ReviewTab.module.css */
|
|
10190
|
+
'.dig-lf-selector{flex:0 1 auto;min-width:0}',
|
|
10191
|
+
'.dig-lf-selectorStatic{flex:0 1 auto;min-width:0;overflow:hidden;font-size:12px;text-overflow:ellipsis;white-space:nowrap;font-weight:600}',
|
|
10192
|
+
'.dig-lf-selectorFallback{max-width:60%;padding:2px 6px;border:none;border-radius:var(--dsw-radius-sm,8px);background:var(--dsw-alias-bg-layer-2,var(--dsw-alias-bg-layer-1));color:inherit;font:inherit;font-size:12px}',
|
|
10193
|
+
'.dig-lf-selectorButton{display:inline-flex;gap:4px;align-items:center;box-sizing:border-box;max-width:100%;height:28px;padding:0 6px 0 8px;border:0;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:12px;line-height:20px}',
|
|
10194
|
+
'.dig-lf-selectorButton:hover,.dig-lf-selectorButton[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}',
|
|
10195
|
+
'.dig-lf-selectorButton svg{display:block;flex:none}',
|
|
10196
|
+
'.dig-lf-item{display:flex;gap:12px;align-items:center;justify-content:space-between;min-width:0}',
|
|
10197
|
+
'.dig-lf-itemPath{min-width:0;overflow:hidden;line-height:20px;text-overflow:ellipsis;white-space:nowrap}',
|
|
10198
|
+
'.dig-lf-itemCounts,.dig-lf-counts{display:inline-flex;flex:none;gap:6px;align-items:center;font-family:var(--ds-font-family-code);font-size:12px;line-height:20px;color:var(--dsw-alias-label-tertiary)}',
|
|
10199
|
+
'.dig-lf-counts{min-width:0;margin-right:auto}',
|
|
10200
|
+
'.dig-lf-added{color:var(--dsw-alias-state-success-primary)}',
|
|
10201
|
+
'.dig-lf-deleted{color:var(--dsw-alias-state-error-primary)}',
|
|
10202
|
+
'.dig-lf-label{color:var(--dsw-alias-label-tertiary)}',
|
|
10203
|
+
'.dig-lf-tools{display:inline-flex;flex:none;gap:2px;align-items:center;margin-left:auto}',
|
|
10204
|
+
'.dig-lf-tool{display:inline-flex;flex:none;align-items:center;justify-content:center;width:28px;height:28px;padding:6px;border:0;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer}',
|
|
10205
|
+
'.dig-lf-tool svg{width:15px;height:15px}',
|
|
10206
|
+
'.dig-lf-tool:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}',
|
|
10207
|
+
'.dig-lf-tool[aria-pressed=true] .dig-lf-compareIcon{transform:rotate(90deg)}',
|
|
9619
10208
|
].join('\n')
|
|
9620
10209
|
|
|
9621
10210
|
/* ============================== plugin ============================== */
|
|
@@ -9984,10 +10573,6 @@ window.__ModuleLoader__.load({
|
|
|
9984
10573
|
E('div', { className: 'dig-preview-head' },
|
|
9985
10574
|
E('span', { className: 'dig-preview-title', title: title }, title === '' ? t('preview.title') : title),
|
|
9986
10575
|
seed === null ? null : E('div', { className: 'dig-preview-actions' },
|
|
9987
|
-
seed.path !== undefined && seed.path !== null && seed.path !== ''
|
|
9988
|
-
? E('button', { type: 'button', className: 'dig-preview-btn', 'aria-label': t('preview.openFile'), title: t('preview.openFile'), onClick: openInFilePreview },
|
|
9989
|
-
E(Icon, { name: 'file', size: 13 }))
|
|
9990
|
-
: null,
|
|
9991
10576
|
E('button', { type: 'button', className: 'dig-preview-btn', 'aria-label': t('diff.copy'), title: t('diff.copy'), onClick: copyPatch },
|
|
9992
10577
|
E(Icon, { name: copied === true ? 'check' : 'copy', size: 13 })),
|
|
9993
10578
|
E('button', { type: 'button', className: 'dig-preview-btn', 'aria-label': t('toolbar.refresh'), title: t('toolbar.refresh'), onClick: () => { setRefreshTick((n) => n + 1) } },
|
|
@@ -9996,7 +10581,14 @@ window.__ModuleLoader__.load({
|
|
|
9996
10581
|
? E('div', { className: 'dig-preview-body' }, E('div', { className: 'dig-empty' }, t('preview.hint')))
|
|
9997
10582
|
: state.error !== null
|
|
9998
10583
|
? E('div', { className: 'dig-preview-body' }, E('div', { className: 'dig-empty' }, state.error))
|
|
9999
|
-
: E('div', { className: 'dig-preview-body' }, E(LineDiff, {
|
|
10584
|
+
: E('div', { className: 'dig-preview-body' }, E(LineDiff, {
|
|
10585
|
+
patch: state.patch,
|
|
10586
|
+
loading: state.loading,
|
|
10587
|
+
t: t,
|
|
10588
|
+
/* worktree seeds carry the file path: the review's open-file
|
|
10589
|
+
tool jumps to the host's whole-file preview. */
|
|
10590
|
+
onOpenFile: seed.path !== undefined && seed.path !== null && seed.path !== '' ? openInFilePreview : undefined,
|
|
10591
|
+
})))
|
|
10000
10592
|
}
|
|
10001
10593
|
|
|
10002
10594
|
function apply(ctx) {
|