mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-05-13 16:47:38 -03:00
feat(recipes): add toggle to strip <lora:> tags when copying prompt/negative_prompt
Adds a compact inline toggle in the Generation Parameters section of the Recipe Modal that, when enabled, strips <lora:name:weight> tags and cleans up residual punctuation before copying to clipboard. The setting persists across sessions via localStorage.
This commit is contained in:
@@ -396,14 +396,54 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipe-gen-params h3 {
|
.gen-params-header-row {
|
||||||
margin-top: 0;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
margin-bottom: var(--space-2);
|
margin-bottom: var(--space-2);
|
||||||
font-size: 1.2em;
|
|
||||||
color: var(--text-color);
|
|
||||||
padding-bottom: var(--space-1);
|
padding-bottom: var(--space-1);
|
||||||
border-bottom: 1px solid var(--border-color);
|
border-bottom: 1px solid var(--border-color);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gen-params-header-row h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inline toggle for lora strip setting */
|
||||||
|
.lora-strip-toggle {
|
||||||
|
flex-shrink: 0;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lora-strip-toggle .inline-toggle-label {
|
||||||
|
font-size: 0.78em;
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 0.7;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lora-strip-toggle:hover .inline-toggle-label {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lora-strip-toggle .toggle-switch {
|
||||||
|
width: 32px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lora-strip-toggle .toggle-slider:before {
|
||||||
|
height: 10px;
|
||||||
|
width: 10px;
|
||||||
|
left: 3px;
|
||||||
|
bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lora-strip-toggle .toggle-switch input:checked + .toggle-slider:before {
|
||||||
|
transform: translateX(16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.gen-params-container {
|
.gen-params-container {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { showToast, copyToClipboard, sendLoraToWorkflow, sendModelPathToWorkflow, openCivitaiByMetadata } from '../utils/uiHelpers.js';
|
import { showToast, copyToClipboard, sendLoraToWorkflow, sendModelPathToWorkflow, openCivitaiByMetadata } from '../utils/uiHelpers.js';
|
||||||
import { translate } from '../utils/i18nHelpers.js';
|
import { translate } from '../utils/i18nHelpers.js';
|
||||||
import { state } from '../state/index.js';
|
import { state } from '../state/index.js';
|
||||||
import { setSessionItem, removeSessionItem } from '../utils/storageHelpers.js';
|
import { setSessionItem, removeSessionItem, getStorageItem, setStorageItem } from '../utils/storageHelpers.js';
|
||||||
import { fetchRecipeDetails, updateRecipeMetadata } from '../api/recipeApi.js';
|
import { fetchRecipeDetails, updateRecipeMetadata } from '../api/recipeApi.js';
|
||||||
import { downloadManager } from '../managers/DownloadManager.js';
|
import { downloadManager } from '../managers/DownloadManager.js';
|
||||||
import { MODEL_TYPES } from '../api/apiConfig.js';
|
import { MODEL_TYPES } from '../api/apiConfig.js';
|
||||||
@@ -105,6 +105,7 @@ class RecipeModal {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.setupCopyButtons();
|
this.setupCopyButtons();
|
||||||
|
this.setupStripLoraToggle();
|
||||||
this.setupPromptEditors();
|
this.setupPromptEditors();
|
||||||
// Set up tooltip positioning handlers after DOM is ready
|
// Set up tooltip positioning handlers after DOM is ready
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
@@ -1350,14 +1351,20 @@ class RecipeModal {
|
|||||||
|
|
||||||
if (copyPromptBtn) {
|
if (copyPromptBtn) {
|
||||||
copyPromptBtn.addEventListener('click', () => {
|
copyPromptBtn.addEventListener('click', () => {
|
||||||
const promptText = this.currentRecipe?.gen_params?.prompt || '';
|
let promptText = this.currentRecipe?.gen_params?.prompt || '';
|
||||||
|
if (this.shouldStripLoraOnCopy()) {
|
||||||
|
promptText = RecipeModal.stripLoraTags(promptText);
|
||||||
|
}
|
||||||
this.copyToClipboard(promptText, 'Prompt copied to clipboard');
|
this.copyToClipboard(promptText, 'Prompt copied to clipboard');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copyNegativePromptBtn) {
|
if (copyNegativePromptBtn) {
|
||||||
copyNegativePromptBtn.addEventListener('click', () => {
|
copyNegativePromptBtn.addEventListener('click', () => {
|
||||||
const negativePromptText = this.currentRecipe?.gen_params?.negative_prompt || '';
|
let negativePromptText = this.currentRecipe?.gen_params?.negative_prompt || '';
|
||||||
|
if (this.shouldStripLoraOnCopy()) {
|
||||||
|
negativePromptText = RecipeModal.stripLoraTags(negativePromptText);
|
||||||
|
}
|
||||||
this.copyToClipboard(negativePromptText, 'Negative prompt copied to clipboard');
|
this.copyToClipboard(negativePromptText, 'Negative prompt copied to clipboard');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1377,6 +1384,43 @@ class RecipeModal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip <lora:...> tags from prompt text and clean up residual punctuation/whitespace.
|
||||||
|
* Handles both unescaped (<lora:...>) and HTML-escaped (<lora:...>) variants.
|
||||||
|
* Cleans up artifacts like leading ", ", double commas, and extra whitespace.
|
||||||
|
*/
|
||||||
|
static stripLoraTags(text) {
|
||||||
|
return text
|
||||||
|
.replace(/<lora:[^>]*>/gi, '')
|
||||||
|
.replace(/<lora:[^&]*>/gi, '')
|
||||||
|
.replace(/,(\s*,)+/g, ',')
|
||||||
|
.replace(/^,\s*/, '')
|
||||||
|
.replace(/,\s*$/, '')
|
||||||
|
.replace(/\s{2,}/g, ' ')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldStripLoraOnCopy() {
|
||||||
|
const toggle = document.getElementById('stripLoraOnCopyToggle');
|
||||||
|
return toggle ? toggle.checked : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupStripLoraToggle() {
|
||||||
|
const toggle = document.getElementById('stripLoraOnCopyToggle');
|
||||||
|
if (!toggle) return;
|
||||||
|
|
||||||
|
const stored = getStorageItem('strip_lora_on_copy');
|
||||||
|
if (stored !== null) {
|
||||||
|
toggle.checked = stored === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle.addEventListener('change', () => {
|
||||||
|
const checked = toggle.checked;
|
||||||
|
setStorageItem('strip_lora_on_copy', checked);
|
||||||
|
state.global.settings.strip_lora_on_copy = checked;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch recipe syntax from backend and copy to clipboard
|
// Fetch recipe syntax from backend and copy to clipboard
|
||||||
async fetchAndCopyRecipeSyntax() {
|
async fetchAndCopyRecipeSyntax() {
|
||||||
if (!this.recipeId) {
|
if (!this.recipeId) {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({
|
|||||||
download_skip_base_models: [],
|
download_skip_base_models: [],
|
||||||
backup_auto_enabled: true,
|
backup_auto_enabled: true,
|
||||||
backup_retention_count: 5,
|
backup_retention_count: 5,
|
||||||
|
strip_lora_on_copy: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export function createDefaultSettings() {
|
export function createDefaultSettings() {
|
||||||
|
|||||||
@@ -22,7 +22,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="info-section recipe-gen-params">
|
<div class="info-section recipe-gen-params">
|
||||||
<h3>Generation Parameters</h3>
|
<div class="gen-params-header-row">
|
||||||
|
<h3>Generation Parameters</h3>
|
||||||
|
<label class="inline-toggle-container lora-strip-toggle" title="When enabled, <lora:...> tags are removed from prompt text when copying">
|
||||||
|
<span class="inline-toggle-label">Strip <lora:></span>
|
||||||
|
<div class="toggle-switch">
|
||||||
|
<input type="checkbox" id="stripLoraOnCopyToggle">
|
||||||
|
<span class="toggle-slider"></span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gen-params-container">
|
<div class="gen-params-container">
|
||||||
<!-- Prompt -->
|
<!-- Prompt -->
|
||||||
|
|||||||
Reference in New Issue
Block a user