Merge pull request #49 from BlakeNeko/feature/auto_format_on_blur
Feature/#48 auto format on blur
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { settingValues } from './settings.js';
|
||||
|
||||
/**
|
||||
* Event handler for auto-formatting functionality
|
||||
*/
|
||||
export class AutoFormatterEventHandler {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Handle blur event to trigger auto-formatting
|
||||
* @param {Event} event - The blur event
|
||||
*/
|
||||
handleBlur(event) {
|
||||
if (
|
||||
settingValues.enableAutoFormat &&
|
||||
event.target.tagName === 'TEXTAREA'
|
||||
) {
|
||||
formatTextareaOnBlur(event.target);
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder methods to maintain consistency with other event handlers
|
||||
handleInput(event) {}
|
||||
handleFocus(event) {}
|
||||
handleKeyDown(event) {}
|
||||
handleKeyUp(event) {}
|
||||
handleMouseMove(event) {}
|
||||
handleClick(event) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the prompt text: add a comma and space after each tag, and remove extra spaces.
|
||||
* Preserve special syntax such as weights (tag:1.2), parentheses, and wildcards.
|
||||
* @param {string} text - The original text.
|
||||
* @returns {string} - The formatted text.
|
||||
*/
|
||||
export function formatPromptText(text) {
|
||||
if (!text || text.trim().length === 0) return text;
|
||||
|
||||
// Split text into individual lines for processing
|
||||
const lines = text.split('\n');
|
||||
const formattedLines = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
// Keep empty lines unchanged
|
||||
if (trimmedLine.length === 0) {
|
||||
formattedLines.push('');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Split the line by commas into raw tag segments
|
||||
const rawTags = trimmedLine.split(',');
|
||||
|
||||
const cleanedTags = [];
|
||||
for (const tag of rawTags) {
|
||||
// Trim spaces around each tag
|
||||
const trimmedTag = tag.trim();
|
||||
|
||||
// Keep only non-empty tags
|
||||
if (trimmedTag.length > 0) {
|
||||
cleanedTags.push(trimmedTag);
|
||||
}
|
||||
}
|
||||
|
||||
// Rejoin cleaned tags with ", "
|
||||
let formattedLine = cleanedTags.join(', ');
|
||||
|
||||
// Add a trailing comma and space if the line contains valid tags
|
||||
if (formattedLine.length > 0) {
|
||||
formattedLine += ', ';
|
||||
}
|
||||
|
||||
formattedLines.push(formattedLine);
|
||||
}
|
||||
|
||||
// Rejoin all lines with newline characters
|
||||
return formattedLines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the content of a textarea when it loses focus.
|
||||
* @param {HTMLTextAreaElement} textarea - The target textarea element.
|
||||
*/
|
||||
export function formatTextareaOnBlur(textarea) {
|
||||
const originalText = textarea.value;
|
||||
const formattedText = formatPromptText(originalText);
|
||||
|
||||
if (originalText !== formattedText) {
|
||||
const cursorPos = textarea.selectionStart;
|
||||
textarea.value = formattedText;
|
||||
|
||||
// Try to preserve cursor position
|
||||
const newCursorPos = Math.min(cursorPos, formattedText.length);
|
||||
textarea.setSelectionRange(newCursorPos, newCursorPos);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { loadCSS } from "./utils.js";
|
||||
import { TagSource, loadDataAsync } from "./data.js";
|
||||
import { AutocompleteEventHandler } from "./autocomplete.js";
|
||||
import { RelatedTagsEventHandler } from "./related-tags.js";
|
||||
import { AutoFormatterEventHandler } from "./auto-formatter.js";
|
||||
|
||||
// --- Constants ---
|
||||
const id = "AutocompletePlus";
|
||||
@@ -18,6 +19,7 @@ const name = "Autocomplete Plus";
|
||||
function initializeEventHandlers() {
|
||||
const autocompleteEventHandler = new AutocompleteEventHandler();
|
||||
const relatedTagsEventHandler = new RelatedTagsEventHandler();
|
||||
const autoFormatterEventHandler = new AutoFormatterEventHandler();
|
||||
const attachedElements = new WeakSet(); // Keep track of elements that have listeners attached
|
||||
|
||||
// Function to attach listeners
|
||||
@@ -105,6 +107,7 @@ function initializeEventHandlers() {
|
||||
function handleBlur(event) {
|
||||
autocompleteEventHandler.handleBlur(event);
|
||||
relatedTagsEventHandler.handleBlur(event);
|
||||
autoFormatterEventHandler.handleBlur(event);
|
||||
}
|
||||
|
||||
function handleKeyDown(event) {
|
||||
@@ -416,5 +419,17 @@ app.registerExtension({
|
||||
settingValues.hideAlias = newVal;
|
||||
}
|
||||
},
|
||||
|
||||
// --- Auto format settings ---
|
||||
{
|
||||
id: id + '.AutoFormatter.EnableAutoFormat',
|
||||
name: 'Enable Auto Format',
|
||||
type: 'boolean',
|
||||
defaultValue: true,
|
||||
category: [name, 'AutoFormatter', 'Enable Auto Format'],
|
||||
onChange: (newVal, oldVal) => {
|
||||
settingValues.enableAutoFormat = newVal;
|
||||
},
|
||||
},
|
||||
]
|
||||
});
|
||||
@@ -21,6 +21,9 @@ export const settingValues = {
|
||||
// Display settings
|
||||
hideAlias: false, // Hide alias in the autocomplete and related tags display
|
||||
|
||||
// Auto format settings
|
||||
enableAutoFormat: true,
|
||||
|
||||
|
||||
// Internal logic settings
|
||||
_useFallbackAttachmentForEventListener: false, // Fallback to attach event listener when somthing goes wrong
|
||||
|
||||
Reference in New Issue
Block a user