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 MIT License
Copyright (c) 2023 Haoming Copyright (c) 2024 Haoming
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 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] Remove duplicated **spaces** and **commas**
- [x] Fix misplaced **brackets** and **commas** - [x] Fix misplaced **brackets** and **commas**
- [x] Toggle `Remove Duplicates` to remove identical tags found in the prompts - [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.** `1girl, solo, smile, 1girl` will become `1girl, solo, smile`
- **eg.** `a girl smiling, a girl standing` will not be changed - **eg.** `a girl smiling, a girl standing` will not be changed
- [x] Toggle `Remove Underscores` to replace `_` with `space` - [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 `Auto`: The process is ran whenever you press **Generate**
- In `Manual`: The process is only ran when you press the **Format** button - 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] 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 ## Note
1. Since the formatting in `Auto` mode is triggered at the same time as the generation, 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). 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, 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. 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)** 時處裡 - `自動`: 每次按下 **生成 (Generate)** 時處裡
- `手動`: 手動按下 **Format** 時才處裡 - `手動`: 手動按下 **Format** 時才處裡
- [x] 在 **Settings** 頁面的 `System` 區 開啟/關閉 上述預設功能 - [x] 在 **Settings** 頁面的 `System` 區 開啟/關閉 上述預設功能
- [x] 按下 `Alt` + `Shift` + `F` 亦可觸發格式化
## 注意 ## 注意
1. 由於`自動`校正和生成是同時觸發,除非有先用過`手動`校正,不然當下所產的第一張圖片之內部資料並不會被更新。 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 ===== // ===== Main Format Logics =====
static formatPipeline(textArea, dedupe, removeUnderscore, autoRefresh) { static formatPipeline(textArea, dedupe, removeUnderscore, autoRefresh) {
const lines = textArea.value.split('\n'); const lines = textArea.value.split('\n');
@ -138,33 +102,44 @@ class LeFormatter {
} }
// ===== Load Settings ===== // ===== Load Settings =====
/** @returns {boolean} */
static shouldRefresh() { static shouldRefresh() {
const config = gradioApp().getElementById('setting_pf_disableupdateinput').querySelector('input[type=checkbox]'); const config = gradioApp().getElementById('setting_pf_disableupdateinput').querySelector('input[type=checkbox]');
return !config.checked; return !config.checked;
} }
/** @returns {boolean} */
static defaultAuto() { static defaultAuto() {
const config = gradioApp().getElementById('setting_pf_startinauto').querySelector('input[type=checkbox]'); const config = gradioApp().getElementById('setting_pf_startinauto').querySelector('input[type=checkbox]');
return config.checked; return config.checked;
} }
/** @returns {boolean} */
static defaultDedupe() { static defaultDedupe() {
const config = gradioApp().getElementById('setting_pf_startwithdedupe').querySelector('input[type=checkbox]'); const config = gradioApp().getElementById('setting_pf_startwithdedupe').querySelector('input[type=checkbox]');
return config.checked; return config.checked;
} }
/** @returns {boolean} */
static defaultRemoveUnderscore() { static defaultRemoveUnderscore() {
const config = gradioApp().getElementById('setting_pf_startwithrmudscr').querySelector('input[type=checkbox]'); const config = gradioApp().getElementById('setting_pf_startwithrmudscr').querySelector('input[type=checkbox]');
return config.checked; return config.checked;
} }
// ===== Cache All Prompt Fields ===== // ===== Cache All Prompt Fields =====
/** @returns {Array<Element>} */
static getPromptFields() { 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 = []; 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'); const textArea = gradioApp().getElementById(id)?.querySelector('textarea');
if (textArea != null) if (textArea != null)
textareas.push(textArea); textareas.push(textArea);
@ -176,11 +151,11 @@ class LeFormatter {
onUiLoaded(async () => { onUiLoaded(async () => {
const promptFields = LeFormatter.getPromptFields(); const promptFields = LeFormatter.getPromptFields();
const refresh = LeFormatter.shouldRefresh();
var autoRun = LeFormatter.defaultAuto(); var autoRun = LeFormatter.defaultAuto();
var dedupe = LeFormatter.defaultDedupe(); var dedupe = LeFormatter.defaultDedupe();
var removeUnderscore = LeFormatter.defaultRemoveUnderscore(); var removeUnderscore = LeFormatter.defaultRemoveUnderscore();
const refresh = LeFormatter.shouldRefresh();
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (e.altKey && e.shiftKey && e.code === 'KeyF') { if (e.altKey && e.shiftKey && e.code === 'KeyF') {
@ -189,55 +164,41 @@ onUiLoaded(async () => {
} }
}); });
const manualBtn = LeFormatter.button({ const formatter = LeFormatterUI.setupUIs(
onClick: () => { () => {
promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, true)); 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'; formatter.checkboxs[1].addEventListener("change", (e) => {
dedupe = e.target.checked;
const autoCB = LeFormatter.checkbox('Auto Format', autoRun, {
onChange: (checked) => {
autoRun = checked;
manualBtn.style.display = autoRun ? 'none' : 'block';
}
}); });
const dedupeCB = LeFormatter.checkbox('Remove Duplicates', dedupe, { formatter.checkboxs[2].addEventListener("change", (e) => {
onChange: (checked) => { dedupe = checked; } 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'); const tools = document.getElementById('quicksettings');
tools.after(formatter); tools.after(formatter);
['txt', 'img'].forEach((mode) => { ['txt', 'img'].forEach((mode) => {
const generateButton = gradioApp().getElementById(`${mode}2img_generate`); const generateButton = gradioApp().getElementById(`${mode}2img_generate`);
const enqueueButton = gradioApp().getElementById(`${mode}2img_enqueue`); const enqueueButton = gradioApp().getElementById(`${mode}2img_enqueue`);
const handleClick = () => { generateButton?.addEventListener('click', () => {
if (autoRun) { if (autoRun)
promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, refresh)); promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, refresh));
} });
};
enqueueButton?.addEventListener('click', () => {
generateButton.addEventListener('click', handleClick); if (autoRun)
if (enqueueButton) { promptFields.forEach((field) => LeFormatter.formatPipeline(field, dedupe, removeUnderscore, refresh));
enqueueButton.addEventListener('click', handleClick); });
}
}); });
}); });

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;
}