forked from extern/easydiffusion
Expand curly braces in prompts, for e.g. 'hello {foo,bar}' => 'hello foo' and 'hello bar'
This commit is contained in:
parent
946dfdf7b8
commit
105f071847
@ -17,7 +17,7 @@
|
||||
<div id="container">
|
||||
<div id="top-nav">
|
||||
<div id="logo">
|
||||
<h1>Stable Diffusion UI <small>v2.29 <span id="updateBranchLabel"></span></small></h1>
|
||||
<h1>Stable Diffusion UI <small>v2.3 <span id="updateBranchLabel"></span></small></h1>
|
||||
</div>
|
||||
<ul id="top-nav-items">
|
||||
<li class="dropdown">
|
||||
|
@ -940,14 +940,34 @@ function getPrompts() {
|
||||
}
|
||||
|
||||
prompts = prompts.split('\n')
|
||||
prompts = prompts.map(prompt => prompt.trim())
|
||||
prompts = prompts.filter(prompt => prompt !== '')
|
||||
|
||||
let promptsToMake = applySetOperator(prompts)
|
||||
promptsToMake = applyPermuteOperator(promptsToMake)
|
||||
|
||||
if (activeTags.length <= 0) {
|
||||
return promptsToMake
|
||||
}
|
||||
|
||||
const promptTags = activeTags.map(x => x.name).join(", ")
|
||||
return promptsToMake.map((prompt) => `${prompt}, ${promptTags}`)
|
||||
}
|
||||
|
||||
function applySetOperator(prompts) {
|
||||
let promptsToMake = []
|
||||
let braceExpander = new BraceExpander()
|
||||
prompts.forEach(prompt => {
|
||||
let expandedPrompts = braceExpander.expand(prompt)
|
||||
promptsToMake = promptsToMake.concat(expandedPrompts)
|
||||
})
|
||||
|
||||
return promptsToMake
|
||||
}
|
||||
|
||||
function applyPermuteOperator(prompts) {
|
||||
let promptsToMake = []
|
||||
prompts.forEach(prompt => {
|
||||
prompt = prompt.trim()
|
||||
if (prompt === '') {
|
||||
return
|
||||
}
|
||||
|
||||
let promptMatrix = prompt.split('|')
|
||||
prompt = promptMatrix.shift().trim()
|
||||
promptsToMake.push(prompt)
|
||||
@ -960,11 +980,8 @@ function getPrompts() {
|
||||
promptsToMake = promptsToMake.concat(promptPermutations)
|
||||
}
|
||||
})
|
||||
if (activeTags.length <= 0) {
|
||||
return promptsToMake
|
||||
}
|
||||
const promptTags = activeTags.map(x => x.name).join(", ")
|
||||
return promptsToMake.map((prompt) => `${prompt}, ${promptTags}`)
|
||||
|
||||
return promptsToMake
|
||||
}
|
||||
|
||||
function permutePrompts(promptBase, promptMatrix) {
|
||||
|
@ -100,4 +100,177 @@ function millisecondsToStr(milliseconds) {
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// https://rosettacode.org/wiki/Brace_expansion#JavaScript
|
||||
function BraceExpander() {
|
||||
'use strict'
|
||||
|
||||
// Index of any closing brace matching the opening
|
||||
// brace at iPosn,
|
||||
// with the indices of any immediately-enclosed commas.
|
||||
function bracePair(tkns, iPosn, iNest, lstCommas) {
|
||||
if (iPosn >= tkns.length || iPosn < 0) return null;
|
||||
|
||||
var t = tkns[iPosn],
|
||||
n = (t === '{') ? (
|
||||
iNest + 1
|
||||
) : (t === '}' ? (
|
||||
iNest - 1
|
||||
) : iNest),
|
||||
lst = (t === ',' && iNest === 1) ? (
|
||||
lstCommas.concat(iPosn)
|
||||
) : lstCommas;
|
||||
|
||||
return n ? bracePair(tkns, iPosn + 1, n, lst) : {
|
||||
close: iPosn,
|
||||
commas: lst
|
||||
};
|
||||
}
|
||||
|
||||
// Parse of a SYNTAGM subtree
|
||||
function andTree(dctSofar, tkns) {
|
||||
if (!tkns.length) return [dctSofar, []];
|
||||
|
||||
var dctParse = dctSofar ? dctSofar : {
|
||||
fn: and,
|
||||
args: []
|
||||
},
|
||||
|
||||
head = tkns[0],
|
||||
tail = head ? tkns.slice(1) : [],
|
||||
|
||||
dctBrace = head === '{' ? bracePair(
|
||||
tkns, 0, 0, []
|
||||
) : null,
|
||||
|
||||
lstOR = dctBrace && (
|
||||
dctBrace.close
|
||||
) && dctBrace.commas.length ? (
|
||||
splitAt(dctBrace.close + 1, tkns)
|
||||
) : null;
|
||||
|
||||
return andTree({
|
||||
fn: and,
|
||||
args: dctParse.args.concat(
|
||||
lstOR ? (
|
||||
orTree(dctParse, lstOR[0], dctBrace.commas)
|
||||
) : head
|
||||
)
|
||||
}, lstOR ? (
|
||||
lstOR[1]
|
||||
) : tail);
|
||||
}
|
||||
|
||||
// Parse of a PARADIGM subtree
|
||||
function orTree(dctSofar, tkns, lstCommas) {
|
||||
if (!tkns.length) return [dctSofar, []];
|
||||
var iLast = lstCommas.length;
|
||||
|
||||
return {
|
||||
fn: or,
|
||||
args: splitsAt(
|
||||
lstCommas, tkns
|
||||
).map(function (x, i) {
|
||||
var ts = x.slice(
|
||||
1, i === iLast ? (
|
||||
-1
|
||||
) : void 0
|
||||
);
|
||||
|
||||
return ts.length ? ts : [''];
|
||||
}).map(function (ts) {
|
||||
return ts.length > 1 ? (
|
||||
andTree(null, ts)[0]
|
||||
) : ts[0];
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
// List of unescaped braces and commas, and remaining strings
|
||||
function tokens(str) {
|
||||
// Filter function excludes empty splitting artefacts
|
||||
var toS = function (x) {
|
||||
return x.toString();
|
||||
};
|
||||
|
||||
return str.split(/(\\\\)/).filter(toS).reduce(function (a, s) {
|
||||
return a.concat(s.charAt(0) === '\\' ? s : s.split(
|
||||
/(\\*[{,}])/
|
||||
).filter(toS));
|
||||
}, []);
|
||||
}
|
||||
|
||||
// PARSE TREE OPERATOR (1 of 2)
|
||||
// Each possible head * each possible tail
|
||||
function and(args) {
|
||||
var lng = args.length,
|
||||
head = lng ? args[0] : null,
|
||||
lstHead = "string" === typeof head ? (
|
||||
[head]
|
||||
) : head;
|
||||
|
||||
return lng ? (
|
||||
1 < lng ? lstHead.reduce(function (a, h) {
|
||||
return a.concat(
|
||||
and(args.slice(1)).map(function (t) {
|
||||
return h + t;
|
||||
})
|
||||
);
|
||||
}, []) : lstHead
|
||||
) : [];
|
||||
}
|
||||
|
||||
// PARSE TREE OPERATOR (2 of 2)
|
||||
// Each option flattened
|
||||
function or(args) {
|
||||
return args.reduce(function (a, b) {
|
||||
return a.concat(b);
|
||||
}, []);
|
||||
}
|
||||
|
||||
// One list split into two (first sublist length n)
|
||||
function splitAt(n, lst) {
|
||||
return n < lst.length + 1 ? [
|
||||
lst.slice(0, n), lst.slice(n)
|
||||
] : [lst, []];
|
||||
}
|
||||
|
||||
// One list split into several (sublist lengths [n])
|
||||
function splitsAt(lstN, lst) {
|
||||
return lstN.reduceRight(function (a, x) {
|
||||
return splitAt(x, a[0]).concat(a.slice(1));
|
||||
}, [lst]);
|
||||
}
|
||||
|
||||
// Value of the parse tree
|
||||
function evaluated(e) {
|
||||
return typeof e === 'string' ? e :
|
||||
e.fn(e.args.map(evaluated));
|
||||
}
|
||||
|
||||
// JSON prettyprint (for parse tree, token list etc)
|
||||
function pp(e) {
|
||||
return JSON.stringify(e, function (k, v) {
|
||||
return typeof v === 'function' ? (
|
||||
'[function ' + v.name + ']'
|
||||
) : v;
|
||||
}, 2)
|
||||
}
|
||||
|
||||
|
||||
// ----------------------- MAIN ------------------------
|
||||
|
||||
// s -> [s]
|
||||
this.expand = function(s) {
|
||||
// BRACE EXPRESSION PARSED
|
||||
var dctParse = andTree(null, tokens(s))[0];
|
||||
|
||||
// ABSTRACT SYNTAX TREE LOGGED
|
||||
// console.log(pp(dctParse));
|
||||
|
||||
// AST EVALUATED TO LIST OF STRINGS
|
||||
return evaluated(dctParse);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user