separate & optimize logics

main
Haoming 2024-07-11 17:13:26 +08:00
parent 91b39272ad
commit a5473abcfe
7 changed files with 129 additions and 81 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Haoming
Copyright (c) 2024 Haoming
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@ -14,7 +14,7 @@ Sometimes, when you type too fast or copy prompts from all over the places, you
- [x] Remove duplicated **spaces** and **commas**
- [x] Fix misplaced **brackets** and **commas**
- [x] Toggle `Remove Duplicates` to remove identical tags found in the prompts
- **Note:** Only works for tag-based prompt, not sentence-based prompt
- **Note:** Only works for tag-based prompt, not sentence-based prompt
- **eg.** `1girl, solo, smile, 1girl` will become `1girl, solo, smile`
- **eg.** `a girl smiling, a girl standing` will not be changed
- [x] Toggle `Remove Underscores` to replace `_` with `space`
@ -25,10 +25,11 @@ Sometimes, when you type too fast or copy prompts from all over the places, you
- In `Auto`: The process is ran whenever you press **Generate**
- In `Manual`: The process is only ran when you press the **Format** button
- [x] Toggle which above features is enabled/disabled by default in `System` section of the **Settings** tab
- [x] Pressing `Alt` + `Shift` + `F` can also trigger formatting
## Note
1. Since the formatting in `Auto` mode is triggered at the same time as the generation,
the immediate image will not have its metadata updated (unless you already did manual formatting beforehand).
1. Since the formatting in `Auto` mode is triggered at the same time as the generation,
the immediate image will not have its metadata updated (unless you already did manual formatting beforehand).
2. Some Extensions *(**eg.** [tagcomplete](https://github.com/DominikDoom/a1111-sd-webui-tagcomplete))* listen to the text editing event,
meaning the formatting will cause them to trigger. You can disable updating the actual prompts in the `System` section of the **Settings** tab.

View File

@ -25,6 +25,7 @@
- `自動`: 每次按下 **生成 (Generate)** 時處裡
- `手動`: 手動按下 **Format** 時才處裡
- [x] 在 **Settings** 頁面的 `System` 區 開啟/關閉 上述預設功能
- [x] 按下 `Alt` + `Shift` + `F` 亦可觸發格式化
## 注意
1. 由於`自動`校正和生成是同時觸發,除非有先用過`手動`校正,不然當下所產的第一張圖片之內部資料並不會被更新。

View File

@ -16,42 +16,6 @@ class LeFormatter {
});
}
// ===== UI Related =====
static button({ onClick }) {
const button = document.createElement('button');
button.id = 'manual-format';
button.classList.add(['lg', 'secondary', 'gradio-button']);
button.textContent = 'Format';
button.style.padding = '2px 8px';
button.style.borderRadius = '0.2em';
button.style.border = 'var(--button-border-width) solid var(--button-secondary-border-color)';
button.style.background = 'var(--button-secondary-background-fill)';
button.addEventListener('click', onClick);
return button;
}
static checkbox(text, default_value, { onChange }) {
const label = gradioApp().getElementById('tab_settings').querySelector('input[type=checkbox]').parentNode.cloneNode(true);
label.removeAttribute('id');
const checkbox = label.children[0];
checkbox.checked = default_value;
checkbox.addEventListener('change', (event) => {
onChange(event.target.checked);
});
const span = label.children[1];
span.textContent = text;
label.style.display = 'flex';
label.style.alignItems = 'center';
label.style.margin = '2px 8px';
return label;
}
// ===== Main Format Logics =====
static formatPipeline(textArea, dedupe, removeUnderscore, autoRefresh) {
const lines = textArea.value.split('\n');
@ -138,33 +102,44 @@ class LeFormatter {
}
// ===== Load Settings =====
/** @returns {boolean} */
static shouldRefresh() {
const config = gradioApp().getElementById('setting_pf_disableupdateinput').querySelector('input[type=checkbox]');
return !config.checked;
}
/** @returns {boolean} */
static defaultAuto() {
const config = gradioApp().getElementById('setting_pf_startinauto').querySelector('input[type=checkbox]');
return config.checked;
}
/** @returns {boolean} */
static defaultDedupe() {
const config = gradioApp().getElementById('setting_pf_startwithdedupe').querySelector('input[type=checkbox]');
return config.checked;
}
/** @returns {boolean} */
static defaultRemoveUnderscore() {
const config = gradioApp().getElementById('setting_pf_startwithrmudscr').querySelector('input[type=checkbox]');
return config.checked;
}
// ===== Cache All Prompt Fields =====
/** @returns {Array<Element>} */
static getPromptFields() {
// Expandable ID List in 1 place
const ids = ['txt2img_prompt', 'txt2img_neg_prompt', 'img2img_prompt', 'img2img_neg_prompt', 'hires_prompt', 'hires_neg_prompt'];
const textareas = [];
ids.forEach((id) => {
// Expandable ID List in 1 place
[
'txt2img_prompt',
'txt2img_neg_prompt',
'img2img_prompt',
'img2img_neg_prompt',
'hires_prompt',
'hires_neg_prompt'
].forEach((id) => {
const textArea = gradioApp().getElementById(id)?.querySelector('textarea');
if (textArea != null)
textareas.push(textArea);
@ -176,11 +151,11 @@ class LeFormatter {
onUiLoaded(async () => {
const promptFields = LeFormatter.getPromptFields();
const refresh = LeFormatter.shouldRefresh();
var autoRun = LeFormatter.defaultAuto();
var dedupe = LeFormatter.defaultDedupe();
var removeUnderscore = LeFormatter.defaultRemoveUnderscore();
const refresh = LeFormatter.shouldRefresh();
document.addEventListener('keydown', (e) => {
if (e.altKey && e.shiftKey && e.code === 'KeyF') {
@ -189,55 +164,41 @@ onUiLoaded(async () => {
}
});
const manualBtn = LeFormatter.button({
onClick: () => {
const formatter = LeFormatterUI.setupUIs(
() => {
promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, true));
}
},
autoRun, dedupe, removeUnderscore
);
formatter.checkboxs[0].addEventListener("change", (e) => {
autoRun = e.target.checked;
formatter.btn.style.display = autoRun ? 'none' : 'flex';
});
manualBtn.style.display = autoRun ? 'none' : 'block';
const autoCB = LeFormatter.checkbox('Auto Format', autoRun, {
onChange: (checked) => {
autoRun = checked;
manualBtn.style.display = autoRun ? 'none' : 'block';
}
formatter.checkboxs[1].addEventListener("change", (e) => {
dedupe = e.target.checked;
});
const dedupeCB = LeFormatter.checkbox('Remove Duplicates', dedupe, {
onChange: (checked) => { dedupe = checked; }
formatter.checkboxs[2].addEventListener("change", (e) => {
removeUnderscore = e.target.checked;
});
const underlineCB = LeFormatter.checkbox('Remove Underscores', removeUnderscore, {
onChange: (checked) => { removeUnderscore = checked; }
});
const formatter = document.createElement('div');
formatter.id = 'le-formatter';
formatter.style.display = 'flex';
formatter.style.flex.direction = 'row';
formatter.appendChild(autoCB);
formatter.appendChild(manualBtn);
formatter.appendChild(dedupeCB);
formatter.appendChild(underlineCB);
const tools = document.getElementById('quicksettings');
tools.after(formatter);
['txt', 'img'].forEach((mode) => {
const generateButton = gradioApp().getElementById(`${mode}2img_generate`);
const enqueueButton = gradioApp().getElementById(`${mode}2img_enqueue`);
const handleClick = () => {
if (autoRun) {
generateButton?.addEventListener('click', () => {
if (autoRun)
promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, refresh));
}
};
generateButton.addEventListener('click', handleClick);
if (enqueueButton) {
enqueueButton.addEventListener('click', handleClick);
}
});
enqueueButton?.addEventListener('click', () => {
if (autoRun)
promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, refresh));
});
});
});

View File

@ -0,0 +1,61 @@
class LeFormatterUI {
/** @param {Function} onClick @returns {Element} */
static #button(onClick) {
const button = document.createElement('button');
button.textContent = 'Format';
button.id = 'manual-format';
button.classList.add(['lg', 'secondary', 'gradio-button']);
button.addEventListener('click', onClick);
return button;
}
/** @param {boolean} default_value @param {string} text @returns {Element} */
static #checkbox(default_value, text) {
const label = gradioApp().getElementById('tab_settings').querySelector('input[type=checkbox]').parentNode.cloneNode(true);
label.removeAttribute('id');
label.classList.add("pf-checkbox");
const checkbox = label.children[0];
checkbox.checked = default_value;
const span = label.children[1];
span.textContent = text;
return label;
}
/**
* @param {Function} onManual
* @param {boolean} autoRun @param {boolean} dedupe @param {boolean} removeUnderscore
* @returns {Element}
* */
static setupUIs(onManual, autoRun, dedupe, removeUnderscore) {
const formatter = document.createElement('div');
formatter.id = 'le-formatter';
const manualBtn = this.#button(onManual);
manualBtn.style.display = autoRun ? 'none' : 'flex';
const autoCB = this.#checkbox(autoRun, 'Auto Format');
const dedupeCB = this.#checkbox(dedupe, 'Remove Duplicates');
const underscoreCB = this.#checkbox(removeUnderscore, 'Remove Underscores');
formatter.appendChild(autoCB);
formatter.appendChild(manualBtn);
formatter.appendChild(dedupeCB);
formatter.appendChild(underscoreCB);
formatter.btn = manualBtn;
formatter.checkboxs = [
autoCB.children[0],
dedupeCB.children[0],
underscoreCB.children[0]
];
return formatter;
}
}

23
style.css Normal file
View File

@ -0,0 +1,23 @@
#le-formatter {
display: flex;
flex-direction: row;
user-select: none;
}
#manual-format {
height: 24px;
padding: 2px 8px;
border-radius: 0.2em;
border: var(--button-border-width) solid var(--button-secondary-border-color);
background: var(--button-secondary-background-fill);
display: flex;
justify-content: center;
align-items: center;
}
.pf-checkbox {
display: flex;
align-items: center;
margin: 2px 8px;
}