parent
ae065172b7
commit
61d8512c3a
|
|
@ -0,0 +1 @@
|
||||||
|
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||||
BIN
Demo.jpg
BIN
Demo.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 130 B |
27
README.md
27
README.md
|
|
@ -1,16 +1,23 @@
|
||||||
# SD Webui Prompt Format
|
# SD Webui Prompt Format
|
||||||
This is an Extension for the [Automatic1111 Webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui), which helps formatting prompts.
|
This is an Extension for the [Automatic1111 Webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui), which helps formatting prompts.
|
||||||
|
|
||||||
<p align="center"><img src="Demo.jpg"></p>
|
<p align="center"><img src="Demo.jpg" width=512></p>
|
||||||
|
|
||||||
## What is This ?
|
> The above demo was achieved in just 1 process
|
||||||
- Sometimes, when you type too fast or copy prompts from all over the places, you end up with duplicated **spaces** or **commas**.
|
|
||||||
- This simple script helps removing them whenever you click **Generate**.
|
Sometimes, when you type too fast or copy prompts from all over the places, you end up with duplicated **spaces** or **commas**. This simple Extension helps removing them whenever you click **Generate**.
|
||||||
- Works in both `txt2img` and `img2img`.
|
|
||||||
- You can also toggle `Remove Duplicates` to remove duplicated tags found in the prompts. *(This is optional, since you may want duplicate tags to strengthen the concept sometimes.)*
|
## Feature List
|
||||||
- **Note:** Only works for tag-based prompt but not for sentence-based prompt
|
- [x] Works in both `txt2img` and `img2img`
|
||||||
|
- [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
|
||||||
- **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
|
||||||
- You can also toggle `Remove Underscores` to replace all `_` with spaces. *(Some newer anime checkpoints claim to fix the need of using underscores in tags)*
|
- [x] Toggle `Remove Underscores` to replace `_` with **space**
|
||||||
- Now respect line breaks too
|
- *Some newer anime checkpoints claim to eliminate the need of using underscores*
|
||||||
- **Note:** Dedupe only works within the same line
|
- [x] Respect line breaks
|
||||||
|
- **Note:** `Remove Duplicates` only checks within the same line
|
||||||
|
- [x] **[New]** Pressing `Ctrl + \` to quickly escape the **brackets** of the hovered tag
|
||||||
|
- Normally, **brackets** *(parentheses)* are used to increase the weight of a prompt. Therefore, for tags like `mejiro mcqueen (umamusume)`, you will need to escape it like `mejiro mcqueen \(umamusume\)`.
|
||||||
|
|
@ -27,6 +27,70 @@ class LeFormatter {
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static injectBracketEscape(id) {
|
||||||
|
const textarea = gradioApp().getElementById(id).querySelector('textarea')
|
||||||
|
|
||||||
|
textarea.addEventListener('keydown', (event) => {
|
||||||
|
if (event.ctrlKey && event.key === '\\') {
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
let cursorPosition = textarea.selectionStart;
|
||||||
|
|
||||||
|
if (textarea.selectionStart !== textarea.selectionEnd)
|
||||||
|
cursorPosition++
|
||||||
|
|
||||||
|
let result = pf_GrabBrackets(textarea.value, cursorPosition)
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
const original = textarea.value
|
||||||
|
|
||||||
|
if (result[0] !== 0 && textarea.value[result[0] - 1] === '\\' && textarea.value[result[1] - 1] === '\\') {
|
||||||
|
textarea.value = original.slice(0, result[0] - 1) + original.slice(result[0] - 1, result[1]).replace(/\\/g, '') + original.slice(result[1])
|
||||||
|
textarea.selectionStart = result[0] - 1
|
||||||
|
textarea.selectionEnd = result[1] - 1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
textarea.value = original.slice(0, result[0]) + '\\' + original.slice(result[0], result[1]) + '\\' + original.slice(result[1])
|
||||||
|
textarea.selectionStart = result[0]
|
||||||
|
textarea.selectionEnd = result[1] + 3
|
||||||
|
}
|
||||||
|
|
||||||
|
updateInput(textarea)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function pf_GrabBrackets(str, index) {
|
||||||
|
let openBracket = -1;
|
||||||
|
let closeBracket = -1;
|
||||||
|
|
||||||
|
for (let i = index; i >= 0; i--) {
|
||||||
|
if (str[i] === '(') {
|
||||||
|
openBracket = i
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (str[i] === ')' && i !== index) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = index; i < str.length; i++) {
|
||||||
|
if (str[i] === ')') {
|
||||||
|
closeBracket = i
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (str[i] === '(' && i !== index) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openBracket !== -1 && closeBracket !== -1 && openBracket !== closeBracket)
|
||||||
|
return [openBracket, closeBracket];
|
||||||
|
else
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixBracketComma(input) {
|
function fixBracketComma(input) {
|
||||||
|
|
@ -38,7 +102,13 @@ function fixBracketSpace(input) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixBracketEmpty(input) {
|
function fixBracketEmpty(input) {
|
||||||
return input.replace(/\(\)/g, '').replace(/\[\]/g, '')
|
let temp = input.replace(/\(\s+\)/g, '').replace(/\[\s+\]/g, '')
|
||||||
|
|
||||||
|
while (temp.includes('()'))
|
||||||
|
temp = temp.replace(/\(\s*\)/g, '')
|
||||||
|
while (temp.includes('[]'))
|
||||||
|
temp = temp.replace(/\[\s*\]/g, '')
|
||||||
|
return temp
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatString(input, dedupe, deunderline) {
|
function formatString(input, dedupe, deunderline) {
|
||||||
|
|
@ -48,10 +118,9 @@ function formatString(input, dedupe, deunderline) {
|
||||||
}
|
}
|
||||||
|
|
||||||
onUiLoaded(async () => {
|
onUiLoaded(async () => {
|
||||||
var dedupe = false
|
let dedupe = false
|
||||||
var deunderline = false
|
let deunderline = false
|
||||||
|
|
||||||
// Checkbox
|
|
||||||
const dedupeCB = LeFormatter.checkbox('Remove Duplicates', {
|
const dedupeCB = LeFormatter.checkbox('Remove Duplicates', {
|
||||||
onChange: (checked) => { dedupe = checked }
|
onChange: (checked) => { dedupe = checked }
|
||||||
})
|
})
|
||||||
|
|
@ -60,7 +129,7 @@ onUiLoaded(async () => {
|
||||||
onChange: (checked) => { deunderline = checked }
|
onChange: (checked) => { deunderline = checked }
|
||||||
})
|
})
|
||||||
|
|
||||||
let formatter = document.createElement('div')
|
const formatter = document.createElement('div')
|
||||||
formatter.id = 'le-formatter'
|
formatter.id = 'le-formatter'
|
||||||
formatter.style.display = 'flex';
|
formatter.style.display = 'flex';
|
||||||
formatter.style.flex.direction = 'row';
|
formatter.style.flex.direction = 'row';
|
||||||
|
|
@ -71,13 +140,16 @@ onUiLoaded(async () => {
|
||||||
const tools = document.getElementById('quicksettings')
|
const tools = document.getElementById('quicksettings')
|
||||||
tools.after(formatter)
|
tools.after(formatter)
|
||||||
|
|
||||||
// Formatter
|
const Modes = ['txt', 'img']
|
||||||
LeFormatter.injectButton('txt2img_generate', {
|
|
||||||
|
Modes.forEach((mode) => {
|
||||||
|
|
||||||
|
LeFormatter.injectButton(mode + '2img_generate', {
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const ids = ['txt2img_prompt', 'txt2img_neg_prompt']
|
const ids = [mode + '2img_prompt', mode + '2img_neg_prompt']
|
||||||
const textAreas = [gradioApp().getElementById(ids[0]).querySelector('textarea'), gradioApp().getElementById(ids[1]).querySelector('textarea')]
|
const textAreas = [gradioApp().getElementById(ids[0]).querySelector('textarea'), gradioApp().getElementById(ids[1]).querySelector('textarea')]
|
||||||
|
|
||||||
var lines = [textAreas[0].value.split('\n'), textAreas[1].value.split('\n')]
|
let lines = [textAreas[0].value.split('\n'), textAreas[1].value.split('\n')]
|
||||||
|
|
||||||
for (let i = 0; i < lines[0].length; i++)
|
for (let i = 0; i < lines[0].length; i++)
|
||||||
lines[0][i] = formatString(lines[0][i], dedupe, deunderline)
|
lines[0][i] = formatString(lines[0][i], dedupe, deunderline)
|
||||||
|
|
@ -94,26 +166,8 @@ onUiLoaded(async () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
LeFormatter.injectButton('img2img_generate', {
|
LeFormatter.injectBracketEscape(mode + '2img_prompt')
|
||||||
onClick: () => {
|
LeFormatter.injectBracketEscape(mode + '2img_neg_prompt')
|
||||||
const ids = ['img2img_prompt', 'img2img_neg_prompt']
|
|
||||||
const textAreas = [gradioApp().getElementById(ids[0]).querySelector('textarea'), gradioApp().getElementById(ids[1]).querySelector('textarea')]
|
|
||||||
|
|
||||||
var lines = [textAreas[0].value.split('\n'), textAreas[1].value.split('\n')]
|
|
||||||
|
|
||||||
for (let i = 0; i < lines[0].length; i++)
|
|
||||||
lines[0][i] = formatString(lines[0][i], dedupe)
|
|
||||||
|
|
||||||
for (let i = 0; i < lines[1].length; i++)
|
|
||||||
lines[1][i] = formatString(lines[1][i], dedupe)
|
|
||||||
|
|
||||||
|
|
||||||
textAreas[0].value = lines[0].join('\n')
|
|
||||||
updateInput(textAreas[0])
|
|
||||||
|
|
||||||
textAreas[1].value = lines[1].join('\n')
|
|
||||||
updateInput(textAreas[1])
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
Loading…
Reference in New Issue