separate & optimize logics
parent
91b39272ad
commit
a5473abcfe
|
|
@ -0,0 +1 @@
|
|||
__pycache__
|
||||
4
LICENSE
4
LICENSE
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
- `自動`: 每次按下 **生成 (Generate)** 時處裡
|
||||
- `手動`: 手動按下 **Format** 時才處裡
|
||||
- [x] 在 **Settings** 頁面的 `System` 區 開啟/關閉 上述預設功能
|
||||
- [x] 按下 `Alt` + `Shift` + `F` 亦可觸發格式化
|
||||
|
||||
## 注意
|
||||
1. 由於`自動`校正和生成是同時觸發,除非有先用過`手動`校正,不然當下所產的第一張圖片之內部資料並不會被更新。
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue