mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-04-10 04:42:14 -03:00
feat(autocomplete): auto-format textarea on blur (#884)
This commit is contained in:
@@ -69,6 +69,9 @@ describe('AutoComplete widget interactions', () => {
|
|||||||
if (key === 'loramanager.autocomplete_append_comma') {
|
if (key === 'loramanager.autocomplete_append_comma') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (key === 'loramanager.autocomplete_auto_format') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (key === 'loramanager.autocomplete_accept_key') {
|
if (key === 'loramanager.autocomplete_accept_key') {
|
||||||
return 'both';
|
return 'both';
|
||||||
}
|
}
|
||||||
@@ -188,6 +191,59 @@ describe('AutoComplete widget interactions', () => {
|
|||||||
expect(insertSelectionSpy).toHaveBeenCalledWith('example_completion');
|
expect(insertSelectionSpy).toHaveBeenCalledWith('example_completion');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('formats duplicate commas and extra spaces when the textarea loses focus', async () => {
|
||||||
|
const input = document.createElement('textarea');
|
||||||
|
input.value = 'foo bar, , baz ,, qux';
|
||||||
|
document.body.append(input);
|
||||||
|
|
||||||
|
const inputListener = vi.fn();
|
||||||
|
input.addEventListener('input', inputListener);
|
||||||
|
|
||||||
|
const { AutoComplete } = await import(AUTOCOMPLETE_MODULE);
|
||||||
|
new AutoComplete(input,'prompt', { showPreview: false });
|
||||||
|
|
||||||
|
input.dispatchEvent(new Event('blur', { bubbles: true }));
|
||||||
|
|
||||||
|
expect(input.value).toBe('foo bar, baz, qux');
|
||||||
|
expect(inputListener).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('skips blur formatting when autocomplete auto format is disabled', async () => {
|
||||||
|
settingGetMock.mockImplementation((key) => {
|
||||||
|
if (key === 'loramanager.autocomplete_append_comma') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (key === 'loramanager.autocomplete_auto_format') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (key === 'loramanager.autocomplete_accept_key') {
|
||||||
|
return 'both';
|
||||||
|
}
|
||||||
|
if (key === 'loramanager.prompt_tag_autocomplete') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (key === 'loramanager.tag_space_replacement') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
const input = document.createElement('textarea');
|
||||||
|
input.value = 'foo bar, , baz ,, qux';
|
||||||
|
document.body.append(input);
|
||||||
|
|
||||||
|
const inputListener = vi.fn();
|
||||||
|
input.addEventListener('input', inputListener);
|
||||||
|
|
||||||
|
const { AutoComplete } = await import(AUTOCOMPLETE_MODULE);
|
||||||
|
new AutoComplete(input,'prompt', { showPreview: false });
|
||||||
|
|
||||||
|
input.dispatchEvent(new Event('blur', { bubbles: true }));
|
||||||
|
|
||||||
|
expect(input.value).toBe('foo bar, , baz ,, qux');
|
||||||
|
expect(inputListener).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('accepts the selected suggestion with Enter', async () => {
|
it('accepts the selected suggestion with Enter', async () => {
|
||||||
caretHelperInstance.getBeforeCursor.mockReturnValue('example');
|
caretHelperInstance.getBeforeCursor.mockReturnValue('example');
|
||||||
|
|
||||||
@@ -275,6 +331,9 @@ describe('AutoComplete widget interactions', () => {
|
|||||||
if (key === 'loramanager.autocomplete_append_comma') {
|
if (key === 'loramanager.autocomplete_append_comma') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (key === 'loramanager.autocomplete_auto_format') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (key === 'loramanager.autocomplete_accept_key') {
|
if (key === 'loramanager.autocomplete_accept_key') {
|
||||||
return 'tab_only';
|
return 'tab_only';
|
||||||
}
|
}
|
||||||
@@ -322,6 +381,9 @@ describe('AutoComplete widget interactions', () => {
|
|||||||
if (key === 'loramanager.autocomplete_append_comma') {
|
if (key === 'loramanager.autocomplete_append_comma') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (key === 'loramanager.autocomplete_auto_format') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (key === 'loramanager.autocomplete_accept_key') {
|
if (key === 'loramanager.autocomplete_accept_key') {
|
||||||
return 'enter_only';
|
return 'enter_only';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { app } from "../../scripts/app.js";
|
|||||||
import { TextAreaCaretHelper } from "./textarea_caret_helper.js";
|
import { TextAreaCaretHelper } from "./textarea_caret_helper.js";
|
||||||
import {
|
import {
|
||||||
getAutocompleteAppendCommaPreference,
|
getAutocompleteAppendCommaPreference,
|
||||||
|
getAutocompleteAutoFormatPreference,
|
||||||
getAutocompleteAcceptKeyPreference,
|
getAutocompleteAcceptKeyPreference,
|
||||||
getPromptTagAutocompletePreference,
|
getPromptTagAutocompletePreference,
|
||||||
getTagSpaceReplacementPreference,
|
getTagSpaceReplacementPreference,
|
||||||
@@ -122,6 +123,32 @@ function formatAutocompleteInsertion(text = '') {
|
|||||||
return getAutocompleteAppendCommaPreference() ? `${trimmed},` : `${trimmed} `;
|
return getAutocompleteAppendCommaPreference() ? `${trimmed},` : `${trimmed} `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeAutocompleteSegment(segment = '') {
|
||||||
|
return segment.replace(/\s+/g, ' ').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatAutocompleteTextOnBlur(text = '') {
|
||||||
|
if (typeof text !== 'string') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
.split('\n')
|
||||||
|
.map((line) => {
|
||||||
|
if (!line.trim()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanedSegments = line
|
||||||
|
.split(',')
|
||||||
|
.map(normalizeAutocompleteSegment)
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
return cleanedSegments.join(', ');
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
function shouldAcceptAutocompleteKey(key) {
|
function shouldAcceptAutocompleteKey(key) {
|
||||||
const mode = getAutocompleteAcceptKeyPreference();
|
const mode = getAutocompleteAcceptKeyPreference();
|
||||||
|
|
||||||
@@ -481,6 +508,14 @@ class AutoComplete {
|
|||||||
|
|
||||||
// Handle focus out to hide dropdown
|
// Handle focus out to hide dropdown
|
||||||
this.onBlur = () => {
|
this.onBlur = () => {
|
||||||
|
if (getAutocompleteAutoFormatPreference()) {
|
||||||
|
const formattedValue = formatAutocompleteTextOnBlur(this.inputElement.value);
|
||||||
|
if (formattedValue !== this.inputElement.value) {
|
||||||
|
this.inputElement.value = formattedValue;
|
||||||
|
this.inputElement.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delay hiding to allow for clicks on dropdown items
|
// Delay hiding to allow for clicks on dropdown items
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.hide();
|
this.hide();
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ const PROMPT_TAG_AUTOCOMPLETE_DEFAULT = true;
|
|||||||
const AUTOCOMPLETE_APPEND_COMMA_SETTING_ID = "loramanager.autocomplete_append_comma";
|
const AUTOCOMPLETE_APPEND_COMMA_SETTING_ID = "loramanager.autocomplete_append_comma";
|
||||||
const AUTOCOMPLETE_APPEND_COMMA_DEFAULT = true;
|
const AUTOCOMPLETE_APPEND_COMMA_DEFAULT = true;
|
||||||
|
|
||||||
|
const AUTOCOMPLETE_AUTO_FORMAT_SETTING_ID = "loramanager.autocomplete_auto_format";
|
||||||
|
const AUTOCOMPLETE_AUTO_FORMAT_DEFAULT = true;
|
||||||
|
|
||||||
const AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID = "loramanager.autocomplete_accept_key";
|
const AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID = "loramanager.autocomplete_accept_key";
|
||||||
const AUTOCOMPLETE_ACCEPT_KEY_DEFAULT = "both";
|
const AUTOCOMPLETE_ACCEPT_KEY_DEFAULT = "both";
|
||||||
const AUTOCOMPLETE_ACCEPT_KEY_OPTION_BOTH = "Tab or Enter";
|
const AUTOCOMPLETE_ACCEPT_KEY_OPTION_BOTH = "Tab or Enter";
|
||||||
@@ -192,6 +195,32 @@ const getAutocompleteAppendCommaPreference = (() => {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
const getAutocompleteAutoFormatPreference = (() => {
|
||||||
|
let settingsUnavailableLogged = false;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const settingManager = app?.extensionManager?.setting;
|
||||||
|
if (!settingManager || typeof settingManager.get !== "function") {
|
||||||
|
if (!settingsUnavailableLogged) {
|
||||||
|
console.warn("LoRA Manager: settings API unavailable, using default autocomplete auto format setting.");
|
||||||
|
settingsUnavailableLogged = true;
|
||||||
|
}
|
||||||
|
return AUTOCOMPLETE_AUTO_FORMAT_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const value = settingManager.get(AUTOCOMPLETE_AUTO_FORMAT_SETTING_ID);
|
||||||
|
return value ?? AUTOCOMPLETE_AUTO_FORMAT_DEFAULT;
|
||||||
|
} catch (error) {
|
||||||
|
if (!settingsUnavailableLogged) {
|
||||||
|
console.warn("LoRA Manager: unable to read autocomplete auto format setting, using default.", error);
|
||||||
|
settingsUnavailableLogged = true;
|
||||||
|
}
|
||||||
|
return AUTOCOMPLETE_AUTO_FORMAT_DEFAULT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
const getAutocompleteAcceptKeyPreference = (() => {
|
const getAutocompleteAcceptKeyPreference = (() => {
|
||||||
let settingsUnavailableLogged = false;
|
let settingsUnavailableLogged = false;
|
||||||
|
|
||||||
@@ -375,6 +404,14 @@ app.registerExtension({
|
|||||||
tooltip: "When enabled, accepted autocomplete suggestions append ', ' to the inserted text.",
|
tooltip: "When enabled, accepted autocomplete suggestions append ', ' to the inserted text.",
|
||||||
category: ["LoRA Manager", "Autocomplete", "Append comma"],
|
category: ["LoRA Manager", "Autocomplete", "Append comma"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: AUTOCOMPLETE_AUTO_FORMAT_SETTING_ID,
|
||||||
|
name: "Auto format autocomplete text on blur",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: AUTOCOMPLETE_AUTO_FORMAT_DEFAULT,
|
||||||
|
tooltip: "When enabled, leaving an autocomplete textarea removes duplicate commas and collapses unnecessary spaces.",
|
||||||
|
category: ["LoRA Manager", "Autocomplete", "Auto Format"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID,
|
id: AUTOCOMPLETE_ACCEPT_KEY_SETTING_ID,
|
||||||
name: "Autocomplete accept key",
|
name: "Autocomplete accept key",
|
||||||
@@ -505,6 +542,7 @@ export {
|
|||||||
getWheelSensitivity,
|
getWheelSensitivity,
|
||||||
getAutoPathCorrectionPreference,
|
getAutoPathCorrectionPreference,
|
||||||
getAutocompleteAppendCommaPreference,
|
getAutocompleteAppendCommaPreference,
|
||||||
|
getAutocompleteAutoFormatPreference,
|
||||||
getAutocompleteAcceptKeyPreference,
|
getAutocompleteAcceptKeyPreference,
|
||||||
getPromptTagAutocompletePreference,
|
getPromptTagAutocompletePreference,
|
||||||
getTagSpaceReplacementPreference,
|
getTagSpaceReplacementPreference,
|
||||||
|
|||||||
Reference in New Issue
Block a user