From aca0ed63263dddba9c619b74ba4c112b107bb393 Mon Sep 17 00:00:00 2001 From: newtextdoc1111 Date: Fri, 24 Oct 2025 06:16:11 +0900 Subject: [PATCH] feat: Add setting to replace underscores with spaces in tag insertion (#39) --- README.md | 1 + docs/README_jp.md | 1 + tests/js/utils.test.js | 58 ++++++++++++++++++++++++++++++++++++++++++ web/js/main.js | 12 +++++++++ web/js/settings.js | 1 + web/js/utils.js | 4 +-- 6 files changed, 75 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d4cdbb1..484bcce 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ When the browser is reloaded, you can check the list of loaded CSV files in the - **Enable Autocomplete**: Enable/disable the autocomplete feature. - **Max suggestions**: Maximum number of autocomplete suggestions to display. +- **Replace '_' with 'Space'**: Replaces underscores with spaces when inserting tags. This setting also affects related tag display. - **Enable Loras and Embeddings**: Display Lora and Embedding in the suggestions. - **Use Fast Search**: Switch autocomplete suggestions search to fast processing (see [About Fast Search for Autocomplete](#about-fast-search-for-autocomplete) for details). diff --git a/docs/README_jp.md b/docs/README_jp.md index 35d3c96..557dc14 100644 --- a/docs/README_jp.md +++ b/docs/README_jp.md @@ -131,6 +131,7 @@ worst_quality,5,9999999, - **Enable Autocomplete**: オートコンプリート機能の有効化/無効化 - **Max Suggestions**: オートコンプリート候補の最大表示件数 +- **Replace '_' with 'Space'**: タグ挿入時にアンダースコアをスペースに置き換えます。この設定は関連タグ表示にも影響します - **Enable Loras and Embeddings**: LoraとEmbeddingを候補に表示する - **Use Fast Search**: オートコンプリート候補の検索を高速な処理に切り替える(詳細は [オートコンプリートの高速検索について](#オートコンプリートの高速検索について) を確認してください) diff --git a/tests/js/utils.test.js b/tests/js/utils.test.js index 31cd917..073e579 100644 --- a/tests/js/utils.test.js +++ b/tests/js/utils.test.js @@ -1,3 +1,4 @@ +import { settingValues } from '../../web/js/settings.js'; import { extractTagsFromTextArea, normalizeTagToSearch, @@ -135,6 +136,11 @@ describe('normalizeTagToSearch', () => { }); describe('normalizeTagToInsert', () => { + const originalValue = settingValues.replaceUnderscoreWithSpace; + afterEach(() => { + settingValues.replaceUnderscoreWithSpace = originalValue; + }); + test('should return null or empty string for invalid inputs', () => { expect(normalizeTagToInsert(null)).toBeNull(); expect(normalizeTagToInsert(undefined)).toBeUndefined(); @@ -167,6 +173,58 @@ describe('normalizeTagToInsert', () => { expect(normalizeTagToInsert('year:2000')).toBe('year:2000'); expect(normalizeTagToInsert('foo:bar')).toBe('foo:bar'); }); + + test('should respect replaceUnderscoreWithSpace setting when true', () => { + settingValues.replaceUnderscoreWithSpace = true; + + expect(normalizeTagToInsert('blue_hair')).toBe('blue hair'); + expect(normalizeTagToInsert('red_eyes')).toBe('red eyes'); + expect(normalizeTagToInsert('long_curly_hair')).toBe('long curly hair'); + }); + + test('should respect replaceUnderscoreWithSpace setting when false', () => { + settingValues.replaceUnderscoreWithSpace = false; + + expect(normalizeTagToInsert('blue_hair')).toBe('blue_hair'); + expect(normalizeTagToInsert('red_eyes')).toBe('red_eyes'); + expect(normalizeTagToInsert('long_curly_hair')).toBe('long_curly_hair'); + }); + + test('should respect replaceUnderscoreWithSpace setting with parentheses', () => { + settingValues.replaceUnderscoreWithSpace = true; + expect(normalizeTagToInsert('blue_hair(style)')).toBe('blue hair\\(style\\)'); + + settingValues.replaceUnderscoreWithSpace = false; + expect(normalizeTagToInsert('blue_hair(style)')).toBe('blue_hair\\(style\\)'); + + settingValues.replaceUnderscoreWithSpace = originalValue; + }); + + test('should not replace underscores in wildcard syntax regardless of setting', () => { + const originalValue = settingValues.replaceUnderscoreWithSpace; + + // Wildcard syntax should preserve underscores regardless of setting + settingValues.replaceUnderscoreWithSpace = true; + expect(normalizeTagToInsert('__wildcard__')).toBe('__wildcard__'); + + settingValues.replaceUnderscoreWithSpace = false; + expect(normalizeTagToInsert('__wildcard__')).toBe('__wildcard__'); + + settingValues.replaceUnderscoreWithSpace = originalValue; + }); + + test('should not replace underscores in symbol-only tags regardless of setting', () => { + const originalValue = settingValues.replaceUnderscoreWithSpace; + + // Symbol-only tags should not be affected by the setting + settingValues.replaceUnderscoreWithSpace = true; + expect(normalizeTagToInsert('^_^')).toBe('^_^'); + + settingValues.replaceUnderscoreWithSpace = false; + expect(normalizeTagToInsert('^_^')).toBe('^_^'); + + settingValues.replaceUnderscoreWithSpace = originalValue; + }); }); describe('getCurrentTagRange', () => { diff --git a/web/js/main.js b/web/js/main.js index 5e5d9a2..4ac711a 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -282,6 +282,7 @@ app.registerExtension({ settingValues.tagSource = newVal; } }, + // --- Autocomplete Settings --- { id: id + ".use_fast_search", @@ -305,6 +306,17 @@ app.registerExtension({ settingValues.enableModels = newVal; } }, + { + id: id + ".replace_underscore_with_space", + name: "Replace '_' with 'Space'", + tooltip: "This setting also affects related tags display.", + type: "boolean", + defaultValue: true, + category: [name, "Autocompletion", "Replace Underscore with Space"], + onChange: (newVal, oldVal) => { + settingValues.replaceUnderscoreWithSpace = newVal; + } + }, { id: id + ".max_suggestions", name: "Max suggestions", diff --git a/web/js/settings.js b/web/js/settings.js index 29f958f..c1d8397 100644 --- a/web/js/settings.js +++ b/web/js/settings.js @@ -9,6 +9,7 @@ export const settingValues = { maxSuggestions: 10, enableModels: true, // Enable Lora and Embedding suggestions useFastSearch: false, + replaceUnderscoreWithSpace: true, // Replace underscores with spaces in tag insertion // Related tags feature settings enableRelatedTags: true, diff --git a/web/js/utils.js b/web/js/utils.js index 0067475..11c8530 100644 --- a/web/js/utils.js +++ b/web/js/utils.js @@ -232,8 +232,8 @@ export function normalizeTagToInsert(str) { if (isContainsLetterOrNumber(str)) { const isWildcardCall = str.startsWith('__') && str.endsWith('__') && str.length > 4; - if (!isWildcardCall) { - // If doesn't wildcard call, replace underscores with spaces + if (!isWildcardCall && settingValues.replaceUnderscoreWithSpace) { + // If doesn't wildcard call and setting is enabled, replace underscores with spaces return escapeParentheses(str.replace(/_/g, " ")); } }