dikdimon's picture
Upload fc using SD-Hub extension
50261d7 verified
onUiLoaded(() => {
addFormatButton('txt2img');
addFormatButton('img2img');
});
function addFormatButton(type) {
let formatButton = gradioApp().querySelector(`#${type}_format_prompt`);
const lastButton = gradioApp().querySelector(`#${type}_clear_prompt`);
if (formatButton || !lastButton || !lastButton.parentNode)
return;
formatButton = createFormatButton(`${type}_format_prompt`, type);
lastButton.parentNode.append(formatButton);
}
function createFormatButton(id, type) {
const button = document.createElement('button');
button.id = id;
button.type = 'button';
button.innerHTML = '🪄';
button.title = 'Format prompt~🪄'
button.className = 'lg secondary gradio-button tool svelte-cmf5ev';
button.addEventListener('click', () => formatPrompts(type));
return button;
}
function formatPrompts(type) {
for (let kind of ['_prompt', '_neg_prompt']) {
const prompt = gradioApp().querySelector(`#${type + kind} > label > textarea`);
const result = formatPrompt(prompt.value);
prompt.value = result;
dispatchInputEvent(prompt);
}
}
function dispatchInputEvent(target) {
let inputEvent = new Event('input');
Object.defineProperty(inputEvent, 'target', { value: target });
target.dispatchEvent(inputEvent);
}
function round(value) {
return Math.round(value * 10000) / 10000
}
function convertStr(str) {
return str.replace(/:/g, ':').replace(/(/g, '(').replace(/)/g, ')')
}
function convertStr2Array(str) {
const bracketRegex = /([()<>[\]])/g
const splitByBracket = str => {
const arr = []
let start = 0
let depth = 0
let match
while ((match = bracketRegex.exec(str)) !== null) {
if (depth === 0 && match.index > start) {
arr.push(str.substring(start, match.index))
start = match.index
}
if (match[0] === '(' || match[0] === '<' || match[0] === '[') {
depth++
} else if (match[0] === ')' || match[0] === '>' || match[0] === ']') {
depth--
}
if (depth === 0) {
arr.push(str.substring(start, match.index + 1))
start = match.index + 1
}
}
if (start < str.length) {
arr.push(str.substring(start))
}
return arr
}
const splitByComma = str => {
const arr = []
let start = 0
let inBracket = false
for (let i = 0; i < str.length; i++) {
if (str[i] === ',' && !inBracket) {
arr.push(str.substring(start, i).trim())
start = i + 1
} else if (str[i].match(bracketRegex)) {
inBracket = !inBracket
}
}
arr.push(str.substring(start).trim())
return arr
}
const cleanStr = str => {
let arr = splitByBracket(str)
arr = arr.flatMap((s) => splitByComma(s))
return arr.filter((s) => s !== '')
}
return cleanStr(str)
.filter((item) => {
const pattern = /^[,\s, ]+$/
return !pattern.test(item)
})
.filter(Boolean)
.sort((a, b) => {
return a.includes('<') && !b.includes('<') ? 1 : b.includes('<') && !a.includes('<') ? -1 : 0
})
}
function convertArray2Str(array) {
const newArray = array.map((item) => {
if (item.includes('<')) return item
const newItem = item
.replace(/\s+/g, ' ')
.replace(/,|\.\|。/g, ',')
.replace(/“|‘|”|"|\/'/g, '')
.replace(/, /g, ',')
.replace(/,,/g, ',')
.replace(/,/g, ', ')
return convertStr2Array(newItem).join(', ')
})
return newArray.join(', ')
}
function formatPrompt(input) {
const re_attention = /\{|\[|\}|\]|[^{}[\]]+/gmu
let text = convertStr(input)
const textArray = convertStr2Array(text)
text = convertArray2Str(textArray)
let res = []
const curly_bracket_multiplier = 1.05
const square_bracket_multiplier = 1 / 1.05
const brackets = {
'{': { stack: [], multiplier: curly_bracket_multiplier },
'[': { stack: [], multiplier: square_bracket_multiplier },
}
function multiply_range(start_position, multiplier) {
for (let pos = start_position; pos < res.length; pos++) {
res[pos][1] = round(res[pos][1] * multiplier)
}
}
for (const match of text.matchAll(re_attention)) {
let word = match[0]
if (word in brackets) {
brackets[word].stack.push(res.length)
} else if (word === '}' || word === ']') {
const bracket = brackets[word === '}' ? '{' : '[']
if (bracket.stack.length > 0) {
multiply_range(bracket.stack.pop(), bracket.multiplier)
}
} else {
res.push([word, 1.0])
}
}
Object.keys(brackets).forEach((bracketType) => {
brackets[bracketType].stack.forEach((pos) => {
multiply_range(pos, brackets[bracketType].multiplier)
})
})
if (res.length === 0) {
res = [['', 1.0]]
}
let i = 0
while (i + 1 < res.length) {
if (res[i][1] === res[i + 1][1]) {
res[i][0] += res[i + 1][0]
res.splice(i + 1, 1)
} else {
i += 1
}
}
let result = ''
for (const [word, value] of res) {
result += value === 1.0 ? word : `(${word}:${value.toString()})`
}
return result
}