From bb7ebece8e29fb8e9df91d5c7ddb265e9baf4b66 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:52:54 +0530 Subject: [PATCH 1/2] feat(editor): add setting to disable HTML tag auto closing (#2051) Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/cm/supportedModes.ts | 68 +++++++++++++++++++++++++++++++++- src/lang/ar-ye.json | 4 +- src/lang/be-by.json | 4 +- src/lang/bn-bd.json | 4 +- src/lang/cs-cz.json | 4 +- src/lang/de-de.json | 4 +- src/lang/en-us.json | 2 + src/lang/es-sv.json | 4 +- src/lang/fr-fr.json | 4 +- src/lang/he-il.json | 4 +- src/lang/hi-in.json | 4 +- src/lang/hu-hu.json | 4 +- src/lang/id-id.json | 4 +- src/lang/ir-fa.json | 4 +- src/lang/it-it.json | 4 +- src/lang/ja-jp.json | 4 +- src/lang/ko-kr.json | 4 +- src/lang/ml-in.json | 4 +- src/lang/mm-unicode.json | 4 +- src/lang/mm-zawgyi.json | 4 +- src/lang/pl-pl.json | 4 +- src/lang/pt-br.json | 4 +- src/lang/pu-in.json | 4 +- src/lang/ru-ru.json | 4 +- src/lang/tl-ph.json | 4 +- src/lang/tr-tr.json | 4 +- src/lang/uk-ua.json | 4 +- src/lang/uz-uz.json | 4 +- src/lang/vi-vn.json | 4 +- src/lang/zh-cn.json | 4 +- src/lang/zh-hant.json | 4 +- src/lang/zh-tw.json | 4 +- src/lib/editorManager.js | 5 +++ src/lib/settings.js | 1 + src/settings/editorSettings.js | 7 ++++ 35 files changed, 172 insertions(+), 31 deletions(-) diff --git a/src/cm/supportedModes.ts b/src/cm/supportedModes.ts index 5b6e3f519..3214aca86 100644 --- a/src/cm/supportedModes.ts +++ b/src/cm/supportedModes.ts @@ -57,6 +57,72 @@ function escapeRegExp(value: string): string { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } +async function shouldAutoCloseTags(): Promise { + const { default: appSettings } = await import("lib/settings"); + return appSettings.value.autoCloseTags !== false; +} + +function createLanguageLoader(name: string, lang: LanguageDescription) { + const normalizedName = normalizeModeKey(name); + + switch (normalizedName) { + case "html": + return async () => { + const { html } = await import("@codemirror/lang-html"); + return html({ autoCloseTags: await shouldAutoCloseTags() }); + }; + + case "xml": + return async () => { + const { xml } = await import("@codemirror/lang-xml"); + return xml({ autoCloseTags: await shouldAutoCloseTags() }); + }; + + case "vue": + return async () => { + const [{ vue }, { html }] = await Promise.all([ + import("@codemirror/lang-vue"), + import("@codemirror/lang-html"), + ]); + return vue({ + base: html({ autoCloseTags: await shouldAutoCloseTags() }), + }); + }; + + case "angular": + return async () => { + const [{ angular }, { html }] = await Promise.all([ + import("@codemirror/lang-angular"), + import("@codemirror/lang-html"), + ]); + return angular({ + base: html({ + autoCloseTags: await shouldAutoCloseTags(), + selfClosingTags: true, + }), + }); + }; + + case "php": + return async () => { + const [{ php }, { html }] = await Promise.all([ + import("@codemirror/lang-php"), + import("@codemirror/lang-html"), + ]); + const htmlSupport = html({ + autoCloseTags: await shouldAutoCloseTags(), + matchClosingTags: false, + }); + return [ + php({ baseLanguage: htmlSupport.language }), + htmlSupport.support, + ]; + }; + } + + return typeof lang.load === "function" ? () => lang.load!() : null; +} + // 1) Always register a plain text fallback addMode("Text", "txt|text|log|plain", "Plain Text", () => []); @@ -106,7 +172,7 @@ for (const lang of languages as readonly LanguageDescription[]) { // Wrap language-data loader as our modelist language provider // lang.load() returns a Promise; we let the editor handle async loading - const loader = typeof lang.load === "function" ? () => lang.load!() : null; + const loader = createLanguageLoader(name, lang); addMode(modeId, pattern, name, loader, { aliases, diff --git a/src/lang/ar-ye.json b/src/lang/ar-ye.json index 11263e963..61e2c75f3 100644 --- a/src/lang/ar-ye.json +++ b/src/lang/ar-ye.json @@ -721,5 +721,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/be-by.json b/src/lang/be-by.json index b1cd086fc..b55a36f8a 100644 --- a/src/lang/be-by.json +++ b/src/lang/be-by.json @@ -723,5 +723,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/bn-bd.json b/src/lang/bn-bd.json index 5e5c246c1..c47372ce4 100644 --- a/src/lang/bn-bd.json +++ b/src/lang/bn-bd.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/cs-cz.json b/src/lang/cs-cz.json index 85cb9886e..bd85b2d23 100644 --- a/src/lang/cs-cz.json +++ b/src/lang/cs-cz.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/de-de.json b/src/lang/de-de.json index ec1172fd3..649cb5bcc 100644 --- a/src/lang/de-de.json +++ b/src/lang/de-de.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/en-us.json b/src/lang/en-us.json index be26799fa..7afdbe784 100644 --- a/src/lang/en-us.json +++ b/src/lang/en-us.json @@ -130,6 +130,7 @@ "invalid backup file": "Invalid backup file", "add path": "Add path", "live autocompletion": "Live autocompletion", + "auto close tags": "Auto close tags", "file properties": "File properties", "path": "Path", "type": "Type", @@ -662,6 +663,7 @@ "settings-info-editor-line-numbers": "Show line numbers in the gutter.", "settings-info-editor-lint-gutter": "Show diagnostics and lint markers in the gutter.", "settings-info-editor-live-autocomplete": "Show suggestions while you type.", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files.", "settings-info-editor-rainbow-brackets": "Color matching brackets by nesting depth.", "settings-info-editor-relative-line-numbers": "Show distance from the current line.", "settings-info-editor-rtl-text": "Switch right-to-left behavior per line.", diff --git a/src/lang/es-sv.json b/src/lang/es-sv.json index 970fdc751..95940af2b 100644 --- a/src/lang/es-sv.json +++ b/src/lang/es-sv.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/fr-fr.json b/src/lang/fr-fr.json index ac8c2f2bb..8fa02be5b 100644 --- a/src/lang/fr-fr.json +++ b/src/lang/fr-fr.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/he-il.json b/src/lang/he-il.json index 6094f6e0c..0a50d14b3 100644 --- a/src/lang/he-il.json +++ b/src/lang/he-il.json @@ -723,5 +723,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/hi-in.json b/src/lang/hi-in.json index c761da8f3..e86614e33 100644 --- a/src/lang/hi-in.json +++ b/src/lang/hi-in.json @@ -723,5 +723,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/hu-hu.json b/src/lang/hu-hu.json index fdf3231f4..dc51cad8e 100644 --- a/src/lang/hu-hu.json +++ b/src/lang/hu-hu.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Biztosan bezárja a kiválasztott lapokat? A nem mentett módosítások elvesznek, és ez a művelet nem vonható vissza.", "close tabs to right": "Jobbra lévő lapok bezárása", "close tabs to left": "Balra lévő lapok bezárása", - "close other tabs": "Többi lap bezárása" + "close other tabs": "Többi lap bezárása", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/id-id.json b/src/lang/id-id.json index 2c5d66e81..a0ac7d2a7 100644 --- a/src/lang/id-id.json +++ b/src/lang/id-id.json @@ -723,5 +723,7 @@ "close selected tabs warning": "Apakah Anda yakin ingin menutup tab terpilih? Anda akan kehilangan perubahan yang belum disimpan dan aksi ini tidak dapat dibatalkan.", "close tabs to right": "Tutup Kanan", "close tabs to left": "Tutup Kiri", - "close other tabs": "Tutup Lainnya" + "close other tabs": "Tutup Lainnya", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/ir-fa.json b/src/lang/ir-fa.json index e8d7401a0..14183a9e4 100644 --- a/src/lang/ir-fa.json +++ b/src/lang/ir-fa.json @@ -723,5 +723,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/it-it.json b/src/lang/it-it.json index 1ed8a27ca..4e9ae8f0c 100644 --- a/src/lang/it-it.json +++ b/src/lang/it-it.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/ja-jp.json b/src/lang/ja-jp.json index 48b544aef..a7064f19b 100644 --- a/src/lang/ja-jp.json +++ b/src/lang/ja-jp.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/ko-kr.json b/src/lang/ko-kr.json index c74558450..5ae7a483b 100644 --- a/src/lang/ko-kr.json +++ b/src/lang/ko-kr.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/ml-in.json b/src/lang/ml-in.json index 7705c326a..4d2569065 100644 --- a/src/lang/ml-in.json +++ b/src/lang/ml-in.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/mm-unicode.json b/src/lang/mm-unicode.json index baf19f397..8ccde8ab6 100644 --- a/src/lang/mm-unicode.json +++ b/src/lang/mm-unicode.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/mm-zawgyi.json b/src/lang/mm-zawgyi.json index b929f9725..5ba55464b 100644 --- a/src/lang/mm-zawgyi.json +++ b/src/lang/mm-zawgyi.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/pl-pl.json b/src/lang/pl-pl.json index b36c87247..5f7d432cf 100644 --- a/src/lang/pl-pl.json +++ b/src/lang/pl-pl.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/pt-br.json b/src/lang/pt-br.json index c69067213..d50eeaa6f 100644 --- a/src/lang/pt-br.json +++ b/src/lang/pt-br.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/pu-in.json b/src/lang/pu-in.json index 221168db6..125fdc795 100644 --- a/src/lang/pu-in.json +++ b/src/lang/pu-in.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/ru-ru.json b/src/lang/ru-ru.json index f72f6dda9..e80989061 100644 --- a/src/lang/ru-ru.json +++ b/src/lang/ru-ru.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/tl-ph.json b/src/lang/tl-ph.json index 6375e9672..aa1c28f8b 100644 --- a/src/lang/tl-ph.json +++ b/src/lang/tl-ph.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/tr-tr.json b/src/lang/tr-tr.json index 75a7b7508..87a8ba3a3 100644 --- a/src/lang/tr-tr.json +++ b/src/lang/tr-tr.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/uk-ua.json b/src/lang/uk-ua.json index a63ce30fa..6f6a0ff0d 100644 --- a/src/lang/uk-ua.json +++ b/src/lang/uk-ua.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/uz-uz.json b/src/lang/uz-uz.json index 098b7a84b..269df5d32 100644 --- a/src/lang/uz-uz.json +++ b/src/lang/uz-uz.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/vi-vn.json b/src/lang/vi-vn.json index 7a85c06d6..1d0a4f519 100644 --- a/src/lang/vi-vn.json +++ b/src/lang/vi-vn.json @@ -723,5 +723,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/zh-cn.json b/src/lang/zh-cn.json index 55415e5b5..d3ab1bb60 100644 --- a/src/lang/zh-cn.json +++ b/src/lang/zh-cn.json @@ -722,5 +722,7 @@ "close selected tabs warning": "确定要关闭选中的标签页吗?未保存的更改将丢失且无法恢复。", "close tabs to right": "关闭右侧标签页", "close tabs to left": "关闭左侧标签页", - "close other tabs": "关闭其他标签页" + "close other tabs": "关闭其他标签页", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/zh-hant.json b/src/lang/zh-hant.json index 0f2f6e659..5a63e5b12 100644 --- a/src/lang/zh-hant.json +++ b/src/lang/zh-hant.json @@ -722,5 +722,7 @@ "close selected tabs warning": "確定要關閉選取的標籤頁嗎?未保存的變更將會遺失且無法恢復。", "close tabs to right": "關閉右側標籤頁", "close tabs to left": "關閉左側標籤頁", - "close other tabs": "關閉其他標籤頁" + "close other tabs": "關閉其他標籤頁", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lang/zh-tw.json b/src/lang/zh-tw.json index 17d1bf2d4..d5b400365 100644 --- a/src/lang/zh-tw.json +++ b/src/lang/zh-tw.json @@ -722,5 +722,7 @@ "close selected tabs warning": "Are you sure you want to close the selected tabs? You will lose the unsaved changes and this action cannot be reversed.", "close tabs to right": "Close Right", "close tabs to left": "Close Left", - "close other tabs": "Close Others" + "close other tabs": "Close Others", + "auto close tags": "Auto close tags", + "settings-info-editor-auto-close-tags": "Automatically insert closing tags in HTML, XML, Vue, Angular, and PHP template files." } diff --git a/src/lib/editorManager.js b/src/lib/editorManager.js index d20c07592..efae0a183 100644 --- a/src/lib/editorManager.js +++ b/src/lib/editorManager.js @@ -1575,6 +1575,11 @@ async function EditorManager($header, $body) { applyOptions(["liveAutoCompletion"]); }); + appSettings.on("update:autoCloseTags", function () { + const file = manager.activeFile; + if (file?.type === "editor") applyFileToEditor(file); + }); + appSettings.on("update:linenumbers", function () { updateMargin(true); updateEditorLineNumbersFromSettings(); diff --git a/src/lib/settings.js b/src/lib/settings.js index 3bfc49005..4beddd844 100644 --- a/src/lib/settings.js +++ b/src/lib/settings.js @@ -143,6 +143,7 @@ class Settings { fullscreen: false, floatingButton: !this.#IS_TABLET, liveAutoCompletion: true, + autoCloseTags: true, showPrintMargin: false, printMargin: 80, scrollbarSize: 20, diff --git a/src/settings/editorSettings.js b/src/settings/editorSettings.js index ee983fe09..f346522b1 100644 --- a/src/settings/editorSettings.js +++ b/src/settings/editorSettings.js @@ -126,6 +126,13 @@ export default function editorSettings() { info: strings["settings-info-editor-live-autocomplete"], category: categories.assistance, }, + { + key: "autoCloseTags", + text: strings["auto close tags"], + checkbox: values.autoCloseTags, + info: strings["settings-info-editor-auto-close-tags"], + category: categories.assistance, + }, { key: "colorPreview", text: strings["color preview"], From d97ce3c766f4cd64ff67f2d347e3e2f2cb0128e3 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:30:37 +0530 Subject: [PATCH 2/2] feat(editor): select line on CodeMirror line number gutter click (#2052) --- src/cm/lineNumberSelection.ts | 115 ++++++++++++++++++++++++++++++++++ src/lib/editorManager.js | 14 ++++- 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/cm/lineNumberSelection.ts diff --git a/src/cm/lineNumberSelection.ts b/src/cm/lineNumberSelection.ts new file mode 100644 index 000000000..f6ae02bdb --- /dev/null +++ b/src/cm/lineNumberSelection.ts @@ -0,0 +1,115 @@ +import { EditorSelection } from "@codemirror/state"; +import type { BlockInfo, EditorView } from "@codemirror/view"; + +type LineInfo = Pick | null | undefined; + +type LineNumberClickEvent = Pick< + MouseEvent, + | "button" + | "shiftKey" + | "altKey" + | "ctrlKey" + | "metaKey" + | "preventDefault" + | "defaultPrevented" +>; + +function toDocumentOffset( + value: number | null | undefined, + fallback = 0, +): number { + const resolved = value != null ? Number(value) : fallback; + return Number.isFinite(resolved) ? resolved : fallback; +} + +/** + * Resolve the selection range for a clicked document line. + * Includes the trailing line break when one exists to mirror Ace's + * full-line selection behavior. + */ +export function getLineSelectionRange( + state: EditorView["state"], + line: LineInfo, +): { from: number; to: number } | null { + if (!line) return null; + const from = Math.max(0, toDocumentOffset(line.from)); + const to = Math.max(from, toDocumentOffset(line.to, from)); + return { + from, + to: Math.min(to + 1, state.doc.length), + }; +} + +function getCurrentSelectionLineRange(state: EditorView["state"]): { + from: number; + to: number; +} { + const selection = state.selection.main; + const startLine = state.doc.lineAt(selection.from); + const endPos = selection.empty + ? selection.head + : Math.max(selection.to - 1, selection.from); + const endLine = state.doc.lineAt(endPos); + const startRange = getLineSelectionRange(state, startLine); + const endRange = getLineSelectionRange(state, endLine); + + return { + from: startRange?.from ?? selection.from, + to: endRange?.to ?? selection.to, + }; +} + +function createLineSelection(range: { + from: number; + to: number; +}): EditorSelection { + return EditorSelection.single(range.to, range.from); +} + +function createExtendedLineSelection( + state: EditorView["state"], + clickedRange: { from: number; to: number }, +): EditorSelection { + const currentRange = getCurrentSelectionLineRange(state); + const from = Math.min(currentRange.from, clickedRange.from); + const to = Math.max(currentRange.to, clickedRange.to); + + if (clickedRange.from <= currentRange.from) { + return EditorSelection.single(to, from); + } + + return EditorSelection.single(from, to); +} + +/** + * Select the clicked line from the line-number gutter. + * Shift-click extends the current selection by whole lines. + * Other modified or non-primary clicks are ignored so they don't interfere + * with context menus or alternate selection gestures. + */ +export function handleLineNumberClick( + view: EditorView | null | undefined, + line: LineInfo, + event: LineNumberClickEvent | null | undefined, +): boolean { + if (!view || !event || event.defaultPrevented) return false; + if ((event.button ?? 0) !== 0) return false; + if (event.altKey || event.ctrlKey || event.metaKey) { + return false; + } + + const range = getLineSelectionRange(view.state, line); + if (!range) return false; + + event.preventDefault(); + view.dispatch({ + selection: event.shiftKey + ? createExtendedLineSelection(view.state, range) + : createLineSelection(range), + userEvent: event.shiftKey ? "select.extend.pointer" : "select.pointer", + }); + view.focus(); + return true; +} + +export default handleLineNumberClick; diff --git a/src/lib/editorManager.js b/src/lib/editorManager.js index efae0a183..cc2ec4afa 100644 --- a/src/lib/editorManager.js +++ b/src/lib/editorManager.js @@ -31,6 +31,7 @@ import { registerExternalCommand, removeExternalCommand, } from "cm/commandRegistry"; +import { handleLineNumberClick } from "cm/lineNumberSelection"; import lspApi from "cm/lsp/api"; import lspClientManager from "cm/lsp/clientManager"; import { @@ -289,6 +290,13 @@ async function EditorManager($header, $body) { function makeLineNumberExtension() { const { linenumbers = true, relativeLineNumbers = false } = appSettings?.value || {}; + const lineNumberConfig = { + domEventHandlers: { + click(view, line, event) { + return handleLineNumberClick(view, line, event); + }, + }, + }; if (!linenumbers) return EditorView.theme({ ".cm-gutter": { @@ -299,9 +307,13 @@ async function EditorManager($header, $body) { }, }); if (!relativeLineNumbers) - return Prec.highest([lineNumbers(), highlightActiveLineGutter()]); + return Prec.highest([ + lineNumbers(lineNumberConfig), + highlightActiveLineGutter(), + ]); return Prec.highest([ lineNumbers({ + ...lineNumberConfig, formatNumber: (lineNo, state) => { try { const cur = state.doc.lineAt(state.selection.main.head).number;