├── .gitignore ├── LICENSE ├── README.md ├── javascript ├── easy_prompt_selector.js └── js-yaml.min.js ├── scripts ├── easy_prompt_selector.py ├── settings.py └── setup.py ├── style.css ├── tags ├── 人物.yml ├── 人物_五官.yml ├── 人物_头发.yml ├── 人物_表情.yml ├── 服装.yml ├── 画质.yml ├── 视线.yml └── 视角.yml └── tags_examples ├── 人.yml ├── 人_顔.yml └── 人_髪.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Adi Eyal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Easy Prompt Selector 2 | 3 | 4 | -------------------------------------------------------------------------------- /javascript/easy_prompt_selector.js: -------------------------------------------------------------------------------- 1 | class EPSElementBuilder { 2 | // Templates 3 | static baseButton(text, { size = 'sm', color = 'primary' }) { 4 | const button = gradioApp().getElementById('txt2img_generate').cloneNode() 5 | button.id = '' 6 | button.classList.remove('gr-button-lg', 'gr-button-primary', 'lg', 'primary') 7 | button.classList.add( 8 | // gradio 3.16 9 | `gr-button-${size}`, 10 | `gr-button-${color}`, 11 | // gradio 3.22 12 | size, 13 | color 14 | ) 15 | button.textContent = text 16 | 17 | return button 18 | } 19 | 20 | static tagFields() { 21 | const fields = document.createElement('div') 22 | fields.style.display = 'flex' 23 | fields.style.flexDirection = 'row' 24 | fields.style.flexWrap = 'wrap' 25 | fields.style.minWidth = 'min(320px, 100%)' 26 | fields.style.maxWidth = '100%' 27 | fields.style.flex = '1 calc(50% - 20px)' 28 | fields.style.borderWidth = '1px' 29 | fields.style.borderColor = 'var(--block-border-color,#374151)' 30 | fields.style.borderRadius = 'var(--block-radius,8px)' 31 | fields.style.padding = '8px' 32 | fields.style.height = 'fit-content' 33 | 34 | return fields 35 | } 36 | 37 | // Elements 38 | static openButton({ onClick }) { 39 | const button = EPSElementBuilder.baseButton('🔯选择标记', { size: 'sm', color: 'secondary' }) 40 | button.classList.add('easy_prompt_selector_button') 41 | button.addEventListener('click', onClick) 42 | 43 | return button 44 | } 45 | 46 | static areaContainer(id = undefined) { 47 | const container = gradioApp().getElementById('txt2img_results').cloneNode() 48 | container.id = id 49 | container.style.gap = 0 50 | container.style.display = 'none' 51 | 52 | return container 53 | } 54 | 55 | static tagButton({ title, onClick, onRightClick, color = 'primary' }) { 56 | const button = EPSElementBuilder.baseButton(title, { color }) 57 | button.style.height = '2rem' 58 | button.style.flexGrow = '0' 59 | button.style.margin = '2px' 60 | 61 | button.addEventListener('click', onClick) 62 | button.addEventListener('contextmenu', onRightClick) 63 | 64 | return button 65 | } 66 | 67 | static dropDown(id, options, { onChange }) { 68 | const select = document.createElement('select') 69 | select.id = id 70 | 71 | // gradio 3.16 72 | select.classList.add('gr-box', 'gr-input') 73 | 74 | // gradio 3.22 75 | select.style.color = 'var(--body-text-color)' 76 | select.style.backgroundColor = 'var(--input-background-fill)' 77 | select.style.borderColor = 'var(--block-border-color)' 78 | select.style.borderRadius = 'var(--block-radius)' 79 | select.style.margin = '2px' 80 | select.addEventListener('change', (event) => { onChange(event.target.value) }) 81 | 82 | const none = ['なし'] 83 | none.concat(options).forEach((key) => { 84 | const option = document.createElement('option') 85 | option.value = key 86 | option.textContent = key 87 | select.appendChild(option) 88 | }) 89 | 90 | return select 91 | } 92 | 93 | static checkbox(text, { onChange }) { 94 | const label = document.createElement('label') 95 | label.style.display = 'flex' 96 | label.style.alignItems = 'center' 97 | 98 | const checkbox = gradioApp().querySelector('input[type=checkbox]').cloneNode() 99 | checkbox.checked = false 100 | checkbox.addEventListener('change', (event) => { 101 | onChange(event.target.checked) 102 | }) 103 | 104 | const span = document.createElement('span') 105 | span.style.marginLeft = 'var(--size-2, 8px)' 106 | span.textContent = text 107 | 108 | label.appendChild(checkbox) 109 | label.appendChild(span) 110 | 111 | return label 112 | } 113 | } 114 | 115 | class EasyPromptSelector { 116 | PATH_FILE = 'tmp/easyPromptSelector.txt' 117 | AREA_ID = 'easy-prompt-selector' 118 | SELECT_ID = 'easy-prompt-selector-select' 119 | CONTENT_ID = 'easy-prompt-selector-content' 120 | TO_NEGATIVE_PROMPT_ID = 'easy-prompt-selector-to-negative-prompt' 121 | 122 | constructor(yaml, gradioApp) { 123 | this.yaml = yaml 124 | this.gradioApp = gradioApp 125 | this.visible = false 126 | this.toNegative = false 127 | this.tags = undefined 128 | } 129 | 130 | async init() { 131 | this.tags = await this.parseFiles() 132 | 133 | const tagArea = gradioApp().querySelector(`#${this.AREA_ID}`) 134 | if (tagArea != null) { 135 | this.visible = false 136 | this.changeVisibility(tagArea, this.visible) 137 | tagArea.remove() 138 | } 139 | 140 | gradioApp() 141 | .getElementById('txt2img_toprow') 142 | .after(this.render()) 143 | } 144 | 145 | async readFile(filepath) { 146 | const response = await fetch(`file=${filepath}?${new Date().getTime()}`); 147 | 148 | return await response.text(); 149 | } 150 | 151 | async parseFiles() { 152 | const text = await this.readFile(this.PATH_FILE); 153 | if (text === '') { return {} } 154 | 155 | const paths = text.split(/\r\n|\n/) 156 | 157 | const tags = {} 158 | for (const path of paths) { 159 | const filename = path.split('/').pop().split('.').shift() 160 | const data = await this.readFile(path) 161 | yaml.loadAll(data, function (doc) { 162 | tags[filename] = doc 163 | }) 164 | } 165 | 166 | return tags 167 | } 168 | 169 | // Render 170 | render() { 171 | const row = document.createElement('div') 172 | row.style.display = 'flex' 173 | row.style.alignItems = 'center' 174 | row.style.gap = '10px' 175 | 176 | const dropDown = this.renderDropdown() 177 | dropDown.style.flex = '1' 178 | dropDown.style.minWidth = '1' 179 | row.appendChild(dropDown) 180 | 181 | const settings = document.createElement('div') 182 | const checkbox = EPSElementBuilder.checkbox('负面提示词中输入', { 183 | onChange: (checked) => { this.toNegative = checked } 184 | }) 185 | settings.style.flex = '1' 186 | settings.appendChild(checkbox) 187 | 188 | row.appendChild(settings) 189 | 190 | const container = EPSElementBuilder.areaContainer(this.AREA_ID) 191 | 192 | container.appendChild(row) 193 | container.appendChild(this.renderContent()) 194 | 195 | return container 196 | } 197 | 198 | renderDropdown() { 199 | const dropDown = EPSElementBuilder.dropDown( 200 | this.SELECT_ID, 201 | Object.keys(this.tags), { 202 | onChange: (selected) => { 203 | const content = gradioApp().getElementById(this.CONTENT_ID) 204 | Array.from(content.childNodes).forEach((node) => { 205 | const visible = node.id === `easy-prompt-selector-container-${selected}` 206 | this.changeVisibility(node, visible) 207 | }) 208 | } 209 | } 210 | ) 211 | 212 | return dropDown 213 | } 214 | 215 | renderContent() { 216 | const content = document.createElement('div') 217 | content.id = this.CONTENT_ID 218 | 219 | Object.keys(this.tags).forEach((key) => { 220 | const values = this.tags[key] 221 | 222 | const fields = EPSElementBuilder.tagFields() 223 | fields.id = `easy-prompt-selector-container-${key}` 224 | fields.style.display = 'none' 225 | fields.style.flexDirection = 'row' 226 | fields.style.marginTop = '10px' 227 | 228 | this.renderTagButtons(values, key).forEach((group) => { 229 | fields.appendChild(group) 230 | }) 231 | 232 | content.appendChild(fields) 233 | }) 234 | 235 | return content 236 | } 237 | 238 | renderTagButtons(tags, prefix = '') { 239 | if (Array.isArray(tags)) { 240 | return tags.map((tag) => this.renderTagButton(tag, tag, 'secondary')) 241 | } else { 242 | return Object.keys(tags).map((key) => { 243 | const values = tags[key] 244 | const randomKey = `${prefix}:${key}` 245 | 246 | if (typeof values === 'string') { return this.renderTagButton(key, values, 'secondary') } 247 | 248 | const fields = EPSElementBuilder.tagFields() 249 | fields.style.flexDirection = 'column' 250 | 251 | fields.append(this.renderTagButton(key, `@${randomKey}@`)) 252 | 253 | const buttons = EPSElementBuilder.tagFields() 254 | buttons.id = 'buttons' 255 | fields.append(buttons) 256 | this.renderTagButtons(values, randomKey).forEach((button) => { 257 | buttons.appendChild(button) 258 | }) 259 | 260 | return fields 261 | }) 262 | } 263 | } 264 | 265 | renderTagButton(title, value, color = 'primary') { 266 | return EPSElementBuilder.tagButton({ 267 | title, 268 | onClick: (e) => { 269 | e.preventDefault(); 270 | 271 | this.addTag(value, this.toNegative || e.metaKey || e.ctrlKey) 272 | }, 273 | onRightClick: (e) => { 274 | e.preventDefault(); 275 | 276 | this.removeTag(value, this.toNegative || e.metaKey || e.ctrlKey) 277 | }, 278 | color 279 | }) 280 | } 281 | 282 | // Util 283 | changeVisibility(node, visible) { 284 | node.style.display = visible ? 'flex' : 'none' 285 | } 286 | 287 | addTag(tag, toNegative = false) { 288 | const id = toNegative ? 'txt2img_neg_prompt' : 'txt2img_prompt' 289 | const textarea = gradioApp().getElementById(id).querySelector('textarea') 290 | 291 | if (textarea.value.trim() === '') { 292 | textarea.value = tag 293 | } else if (textarea.value.trim().endsWith(',')) { 294 | textarea.value += ' ' + tag 295 | } else { 296 | textarea.value += ', ' + tag 297 | } 298 | 299 | updateInput(textarea) 300 | } 301 | 302 | removeTag(tag, toNegative = false) { 303 | const id = toNegative ? 'txt2img_neg_prompt' : 'txt2img_prompt' 304 | const textarea = gradioApp().getElementById(id).querySelector('textarea') 305 | 306 | if (textarea.value.trimStart().startsWith(tag)) { 307 | const matched = textarea.value.match(new RegExp(`${tag.replace(/[-\/\\^$*+?.()|\[\]{}]/g, '\\$&') },*`)) 308 | textarea.value = textarea.value.replace(matched[0], '').trimStart() 309 | } else { 310 | textarea.value = textarea.value.replace(`, ${tag}`, '') 311 | } 312 | 313 | updateInput(textarea) 314 | } 315 | } 316 | 317 | onUiLoaded(async () => { 318 | yaml = window.jsyaml 319 | const easyPromptSelector = new EasyPromptSelector(yaml, gradioApp()) 320 | 321 | const button = EPSElementBuilder.openButton({ 322 | onClick: () => { 323 | const tagArea = gradioApp().querySelector(`#${easyPromptSelector.AREA_ID}`) 324 | easyPromptSelector.changeVisibility(tagArea, easyPromptSelector.visible = !easyPromptSelector.visible) 325 | } 326 | }) 327 | 328 | const reloadButton = gradioApp().getElementById('easy_prompt_selector_reload_button') 329 | reloadButton.addEventListener('click', async () => { 330 | await easyPromptSelector.init() 331 | }) 332 | 333 | const txt2imgActionColumn = gradioApp().getElementById('txt2img_actions_column') 334 | const container = document.createElement('div') 335 | container.classList.add('easy_prompt_selector_container') 336 | container.appendChild(button) 337 | container.appendChild(reloadButton) 338 | 339 | txt2imgActionColumn.appendChild(container) 340 | 341 | await easyPromptSelector.init() 342 | }) 343 | -------------------------------------------------------------------------------- /javascript/js-yaml.min.js: -------------------------------------------------------------------------------- 1 | /*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */ 2 | !function (e, t) { "object" == typeof exports && "undefined" != typeof module ? t(exports) : "function" == typeof define && define.amd ? define(["exports"], t) : t((e = "undefined" != typeof globalThis ? globalThis : e || self).jsyaml = {}) }(this, (function (e) { "use strict"; function t(e) { return null == e } var n = { isNothing: t, isObject: function (e) { return "object" == typeof e && null !== e }, toArray: function (e) { return Array.isArray(e) ? e : t(e) ? [] : [e] }, repeat: function (e, t) { var n, i = ""; for (n = 0; n < t; n += 1)i += e; return i }, isNegativeZero: function (e) { return 0 === e && Number.NEGATIVE_INFINITY === 1 / e }, extend: function (e, t) { var n, i, r, o; if (t) for (n = 0, i = (o = Object.keys(t)).length; n < i; n += 1)e[r = o[n]] = t[r]; return e } }; function i(e, t) { var n = "", i = e.reason || "(unknown reason)"; return e.mark ? (e.mark.name && (n += 'in "' + e.mark.name + '" '), n += "(" + (e.mark.line + 1) + ":" + (e.mark.column + 1) + ")", !t && e.mark.snippet && (n += "\n\n" + e.mark.snippet), i + " " + n) : i } function r(e, t) { Error.call(this), this.name = "YAMLException", this.reason = e, this.mark = t, this.message = i(this, !1), Error.captureStackTrace ? Error.captureStackTrace(this, this.constructor) : this.stack = (new Error).stack || "" } r.prototype = Object.create(Error.prototype), r.prototype.constructor = r, r.prototype.toString = function (e) { return this.name + ": " + i(this, e) }; var o = r; function a(e, t, n, i, r) { var o = "", a = "", l = Math.floor(r / 2) - 1; return i - t > l && (t = i - l + (o = " ... ").length), n - i > l && (n = i + l - (a = " ...").length), { str: o + e.slice(t, n).replace(/\t/g, "→") + a, pos: i - t + o.length } } function l(e, t) { return n.repeat(" ", t - e.length) + e } var c = function (e, t) { if (t = Object.create(t || null), !e.buffer) return null; t.maxLength || (t.maxLength = 79), "number" != typeof t.indent && (t.indent = 1), "number" != typeof t.linesBefore && (t.linesBefore = 3), "number" != typeof t.linesAfter && (t.linesAfter = 2); for (var i, r = /\r?\n|\r|\0/g, o = [0], c = [], s = -1; i = r.exec(e.buffer);)c.push(i.index), o.push(i.index + i[0].length), e.position <= i.index && s < 0 && (s = o.length - 2); s < 0 && (s = o.length - 1); var u, p, f = "", d = Math.min(e.line + t.linesAfter, c.length).toString().length, h = t.maxLength - (t.indent + d + 3); for (u = 1; u <= t.linesBefore && !(s - u < 0); u++)p = a(e.buffer, o[s - u], c[s - u], e.position - (o[s] - o[s - u]), h), f = n.repeat(" ", t.indent) + l((e.line - u + 1).toString(), d) + " | " + p.str + "\n" + f; for (p = a(e.buffer, o[s], c[s], e.position, h), f += n.repeat(" ", t.indent) + l((e.line + 1).toString(), d) + " | " + p.str + "\n", f += n.repeat("-", t.indent + d + 3 + p.pos) + "^\n", u = 1; u <= t.linesAfter && !(s + u >= c.length); u++)p = a(e.buffer, o[s + u], c[s + u], e.position - (o[s] - o[s + u]), h), f += n.repeat(" ", t.indent) + l((e.line + u + 1).toString(), d) + " | " + p.str + "\n"; return f.replace(/\n$/, "") }, s = ["kind", "multi", "resolve", "construct", "instanceOf", "predicate", "represent", "representName", "defaultStyle", "styleAliases"], u = ["scalar", "sequence", "mapping"]; var p = function (e, t) { if (t = t || {}, Object.keys(t).forEach((function (t) { if (-1 === s.indexOf(t)) throw new o('Unknown option "' + t + '" is met in definition of "' + e + '" YAML type.') })), this.options = t, this.tag = e, this.kind = t.kind || null, this.resolve = t.resolve || function () { return !0 }, this.construct = t.construct || function (e) { return e }, this.instanceOf = t.instanceOf || null, this.predicate = t.predicate || null, this.represent = t.represent || null, this.representName = t.representName || null, this.defaultStyle = t.defaultStyle || null, this.multi = t.multi || !1, this.styleAliases = function (e) { var t = {}; return null !== e && Object.keys(e).forEach((function (n) { e[n].forEach((function (e) { t[String(e)] = n })) })), t }(t.styleAliases || null), -1 === u.indexOf(this.kind)) throw new o('Unknown kind "' + this.kind + '" is specified for "' + e + '" YAML type.') }; function f(e, t) { var n = []; return e[t].forEach((function (e) { var t = n.length; n.forEach((function (n, i) { n.tag === e.tag && n.kind === e.kind && n.multi === e.multi && (t = i) })), n[t] = e })), n } function d(e) { return this.extend(e) } d.prototype.extend = function (e) { var t = [], n = []; if (e instanceof p) n.push(e); else if (Array.isArray(e)) n = n.concat(e); else { if (!e || !Array.isArray(e.implicit) && !Array.isArray(e.explicit)) throw new o("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })"); e.implicit && (t = t.concat(e.implicit)), e.explicit && (n = n.concat(e.explicit)) } t.forEach((function (e) { if (!(e instanceof p)) throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object."); if (e.loadKind && "scalar" !== e.loadKind) throw new o("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported."); if (e.multi) throw new o("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.") })), n.forEach((function (e) { if (!(e instanceof p)) throw new o("Specified list of YAML types (or a single Type object) contains a non-Type object.") })); var i = Object.create(d.prototype); return i.implicit = (this.implicit || []).concat(t), i.explicit = (this.explicit || []).concat(n), i.compiledImplicit = f(i, "implicit"), i.compiledExplicit = f(i, "explicit"), i.compiledTypeMap = function () { var e, t, n = { scalar: {}, sequence: {}, mapping: {}, fallback: {}, multi: { scalar: [], sequence: [], mapping: [], fallback: [] } }; function i(e) { e.multi ? (n.multi[e.kind].push(e), n.multi.fallback.push(e)) : n[e.kind][e.tag] = n.fallback[e.tag] = e } for (e = 0, t = arguments.length; e < t; e += 1)arguments[e].forEach(i); return n }(i.compiledImplicit, i.compiledExplicit), i }; var h = d, g = new p("tag:yaml.org,2002:str", { kind: "scalar", construct: function (e) { return null !== e ? e : "" } }), m = new p("tag:yaml.org,2002:seq", { kind: "sequence", construct: function (e) { return null !== e ? e : [] } }), y = new p("tag:yaml.org,2002:map", { kind: "mapping", construct: function (e) { return null !== e ? e : {} } }), b = new h({ explicit: [g, m, y] }); var A = new p("tag:yaml.org,2002:null", { kind: "scalar", resolve: function (e) { if (null === e) return !0; var t = e.length; return 1 === t && "~" === e || 4 === t && ("null" === e || "Null" === e || "NULL" === e) }, construct: function () { return null }, predicate: function (e) { return null === e }, represent: { canonical: function () { return "~" }, lowercase: function () { return "null" }, uppercase: function () { return "NULL" }, camelcase: function () { return "Null" }, empty: function () { return "" } }, defaultStyle: "lowercase" }); var v = new p("tag:yaml.org,2002:bool", { kind: "scalar", resolve: function (e) { if (null === e) return !1; var t = e.length; return 4 === t && ("true" === e || "True" === e || "TRUE" === e) || 5 === t && ("false" === e || "False" === e || "FALSE" === e) }, construct: function (e) { return "true" === e || "True" === e || "TRUE" === e }, predicate: function (e) { return "[object Boolean]" === Object.prototype.toString.call(e) }, represent: { lowercase: function (e) { return e ? "true" : "false" }, uppercase: function (e) { return e ? "TRUE" : "FALSE" }, camelcase: function (e) { return e ? "True" : "False" } }, defaultStyle: "lowercase" }); function w(e) { return 48 <= e && e <= 55 } function k(e) { return 48 <= e && e <= 57 } var C = new p("tag:yaml.org,2002:int", { kind: "scalar", resolve: function (e) { if (null === e) return !1; var t, n, i = e.length, r = 0, o = !1; if (!i) return !1; if ("-" !== (t = e[r]) && "+" !== t || (t = e[++r]), "0" === t) { if (r + 1 === i) return !0; if ("b" === (t = e[++r])) { for (r++; r < i; r++)if ("_" !== (t = e[r])) { if ("0" !== t && "1" !== t) return !1; o = !0 } return o && "_" !== t } if ("x" === t) { for (r++; r < i; r++)if ("_" !== (t = e[r])) { if (!(48 <= (n = e.charCodeAt(r)) && n <= 57 || 65 <= n && n <= 70 || 97 <= n && n <= 102)) return !1; o = !0 } return o && "_" !== t } if ("o" === t) { for (r++; r < i; r++)if ("_" !== (t = e[r])) { if (!w(e.charCodeAt(r))) return !1; o = !0 } return o && "_" !== t } } if ("_" === t) return !1; for (; r < i; r++)if ("_" !== (t = e[r])) { if (!k(e.charCodeAt(r))) return !1; o = !0 } return !(!o || "_" === t) }, construct: function (e) { var t, n = e, i = 1; if (-1 !== n.indexOf("_") && (n = n.replace(/_/g, "")), "-" !== (t = n[0]) && "+" !== t || ("-" === t && (i = -1), t = (n = n.slice(1))[0]), "0" === n) return 0; if ("0" === t) { if ("b" === n[1]) return i * parseInt(n.slice(2), 2); if ("x" === n[1]) return i * parseInt(n.slice(2), 16); if ("o" === n[1]) return i * parseInt(n.slice(2), 8) } return i * parseInt(n, 10) }, predicate: function (e) { return "[object Number]" === Object.prototype.toString.call(e) && e % 1 == 0 && !n.isNegativeZero(e) }, represent: { binary: function (e) { return e >= 0 ? "0b" + e.toString(2) : "-0b" + e.toString(2).slice(1) }, octal: function (e) { return e >= 0 ? "0o" + e.toString(8) : "-0o" + e.toString(8).slice(1) }, decimal: function (e) { return e.toString(10) }, hexadecimal: function (e) { return e >= 0 ? "0x" + e.toString(16).toUpperCase() : "-0x" + e.toString(16).toUpperCase().slice(1) } }, defaultStyle: "decimal", styleAliases: { binary: [2, "bin"], octal: [8, "oct"], decimal: [10, "dec"], hexadecimal: [16, "hex"] } }), x = new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"); var I = /^[-+]?[0-9]+e/; var S = new p("tag:yaml.org,2002:float", { kind: "scalar", resolve: function (e) { return null !== e && !(!x.test(e) || "_" === e[e.length - 1]) }, construct: function (e) { var t, n; return n = "-" === (t = e.replace(/_/g, "").toLowerCase())[0] ? -1 : 1, "+-".indexOf(t[0]) >= 0 && (t = t.slice(1)), ".inf" === t ? 1 === n ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY : ".nan" === t ? NaN : n * parseFloat(t, 10) }, predicate: function (e) { return "[object Number]" === Object.prototype.toString.call(e) && (e % 1 != 0 || n.isNegativeZero(e)) }, represent: function (e, t) { var i; if (isNaN(e)) switch (t) { case "lowercase": return ".nan"; case "uppercase": return ".NAN"; case "camelcase": return ".NaN" } else if (Number.POSITIVE_INFINITY === e) switch (t) { case "lowercase": return ".inf"; case "uppercase": return ".INF"; case "camelcase": return ".Inf" } else if (Number.NEGATIVE_INFINITY === e) switch (t) { case "lowercase": return "-.inf"; case "uppercase": return "-.INF"; case "camelcase": return "-.Inf" } else if (n.isNegativeZero(e)) return "-0.0"; return i = e.toString(10), I.test(i) ? i.replace("e", ".e") : i }, defaultStyle: "lowercase" }), O = b.extend({ implicit: [A, v, C, S] }), j = O, T = new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"), N = new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"); var F = new p("tag:yaml.org,2002:timestamp", { kind: "scalar", resolve: function (e) { return null !== e && (null !== T.exec(e) || null !== N.exec(e)) }, construct: function (e) { var t, n, i, r, o, a, l, c, s = 0, u = null; if (null === (t = T.exec(e)) && (t = N.exec(e)), null === t) throw new Error("Date resolve error"); if (n = +t[1], i = +t[2] - 1, r = +t[3], !t[4]) return new Date(Date.UTC(n, i, r)); if (o = +t[4], a = +t[5], l = +t[6], t[7]) { for (s = t[7].slice(0, 3); s.length < 3;)s += "0"; s = +s } return t[9] && (u = 6e4 * (60 * +t[10] + +(t[11] || 0)), "-" === t[9] && (u = -u)), c = new Date(Date.UTC(n, i, r, o, a, l, s)), u && c.setTime(c.getTime() - u), c }, instanceOf: Date, represent: function (e) { return e.toISOString() } }); var E = new p("tag:yaml.org,2002:merge", { kind: "scalar", resolve: function (e) { return "<<" === e || null === e } }), M = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r"; var L = new p("tag:yaml.org,2002:binary", { kind: "scalar", resolve: function (e) { if (null === e) return !1; var t, n, i = 0, r = e.length, o = M; for (n = 0; n < r; n++)if (!((t = o.indexOf(e.charAt(n))) > 64)) { if (t < 0) return !1; i += 6 } return i % 8 == 0 }, construct: function (e) { var t, n, i = e.replace(/[\r\n=]/g, ""), r = i.length, o = M, a = 0, l = []; for (t = 0; t < r; t++)t % 4 == 0 && t && (l.push(a >> 16 & 255), l.push(a >> 8 & 255), l.push(255 & a)), a = a << 6 | o.indexOf(i.charAt(t)); return 0 === (n = r % 4 * 6) ? (l.push(a >> 16 & 255), l.push(a >> 8 & 255), l.push(255 & a)) : 18 === n ? (l.push(a >> 10 & 255), l.push(a >> 2 & 255)) : 12 === n && l.push(a >> 4 & 255), new Uint8Array(l) }, predicate: function (e) { return "[object Uint8Array]" === Object.prototype.toString.call(e) }, represent: function (e) { var t, n, i = "", r = 0, o = e.length, a = M; for (t = 0; t < o; t++)t % 3 == 0 && t && (i += a[r >> 18 & 63], i += a[r >> 12 & 63], i += a[r >> 6 & 63], i += a[63 & r]), r = (r << 8) + e[t]; return 0 === (n = o % 3) ? (i += a[r >> 18 & 63], i += a[r >> 12 & 63], i += a[r >> 6 & 63], i += a[63 & r]) : 2 === n ? (i += a[r >> 10 & 63], i += a[r >> 4 & 63], i += a[r << 2 & 63], i += a[64]) : 1 === n && (i += a[r >> 2 & 63], i += a[r << 4 & 63], i += a[64], i += a[64]), i } }), _ = Object.prototype.hasOwnProperty, D = Object.prototype.toString; var U = new p("tag:yaml.org,2002:omap", { kind: "sequence", resolve: function (e) { if (null === e) return !0; var t, n, i, r, o, a = [], l = e; for (t = 0, n = l.length; t < n; t += 1) { if (i = l[t], o = !1, "[object Object]" !== D.call(i)) return !1; for (r in i) if (_.call(i, r)) { if (o) return !1; o = !0 } if (!o) return !1; if (-1 !== a.indexOf(r)) return !1; a.push(r) } return !0 }, construct: function (e) { return null !== e ? e : [] } }), q = Object.prototype.toString; var Y = new p("tag:yaml.org,2002:pairs", { kind: "sequence", resolve: function (e) { if (null === e) return !0; var t, n, i, r, o, a = e; for (o = new Array(a.length), t = 0, n = a.length; t < n; t += 1) { if (i = a[t], "[object Object]" !== q.call(i)) return !1; if (1 !== (r = Object.keys(i)).length) return !1; o[t] = [r[0], i[r[0]]] } return !0 }, construct: function (e) { if (null === e) return []; var t, n, i, r, o, a = e; for (o = new Array(a.length), t = 0, n = a.length; t < n; t += 1)i = a[t], r = Object.keys(i), o[t] = [r[0], i[r[0]]]; return o } }), R = Object.prototype.hasOwnProperty; var B = new p("tag:yaml.org,2002:set", { kind: "mapping", resolve: function (e) { if (null === e) return !0; var t, n = e; for (t in n) if (R.call(n, t) && null !== n[t]) return !1; return !0 }, construct: function (e) { return null !== e ? e : {} } }), K = j.extend({ implicit: [F, E], explicit: [L, U, Y, B] }), P = Object.prototype.hasOwnProperty, W = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/, H = /[\x85\u2028\u2029]/, $ = /[,\[\]\{\}]/, G = /^(?:!|!!|![a-z\-]+!)$/i, V = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; function Z(e) { return Object.prototype.toString.call(e) } function J(e) { return 10 === e || 13 === e } function Q(e) { return 9 === e || 32 === e } function z(e) { return 9 === e || 32 === e || 10 === e || 13 === e } function X(e) { return 44 === e || 91 === e || 93 === e || 123 === e || 125 === e } function ee(e) { var t; return 48 <= e && e <= 57 ? e - 48 : 97 <= (t = 32 | e) && t <= 102 ? t - 97 + 10 : -1 } function te(e) { return 48 === e ? "\0" : 97 === e ? "" : 98 === e ? "\b" : 116 === e || 9 === e ? "\t" : 110 === e ? "\n" : 118 === e ? "\v" : 102 === e ? "\f" : 114 === e ? "\r" : 101 === e ? "" : 32 === e ? " " : 34 === e ? '"' : 47 === e ? "/" : 92 === e ? "\\" : 78 === e ? "Â…" : 95 === e ? " " : 76 === e ? "\u2028" : 80 === e ? "\u2029" : "" } function ne(e) { return e <= 65535 ? String.fromCharCode(e) : String.fromCharCode(55296 + (e - 65536 >> 10), 56320 + (e - 65536 & 1023)) } for (var ie = new Array(256), re = new Array(256), oe = 0; oe < 256; oe++)ie[oe] = te(oe) ? 1 : 0, re[oe] = te(oe); function ae(e, t) { this.input = e, this.filename = t.filename || null, this.schema = t.schema || K, this.onWarning = t.onWarning || null, this.legacy = t.legacy || !1, this.json = t.json || !1, this.listener = t.listener || null, this.implicitTypes = this.schema.compiledImplicit, this.typeMap = this.schema.compiledTypeMap, this.length = e.length, this.position = 0, this.line = 0, this.lineStart = 0, this.lineIndent = 0, this.firstTabInLine = -1, this.documents = [] } function le(e, t) { var n = { name: e.filename, buffer: e.input.slice(0, -1), position: e.position, line: e.line, column: e.position - e.lineStart }; return n.snippet = c(n), new o(t, n) } function ce(e, t) { throw le(e, t) } function se(e, t) { e.onWarning && e.onWarning.call(null, le(e, t)) } var ue = { YAML: function (e, t, n) { var i, r, o; null !== e.version && ce(e, "duplication of %YAML directive"), 1 !== n.length && ce(e, "YAML directive accepts exactly one argument"), null === (i = /^([0-9]+)\.([0-9]+)$/.exec(n[0])) && ce(e, "ill-formed argument of the YAML directive"), r = parseInt(i[1], 10), o = parseInt(i[2], 10), 1 !== r && ce(e, "unacceptable YAML version of the document"), e.version = n[0], e.checkLineBreaks = o < 2, 1 !== o && 2 !== o && se(e, "unsupported YAML version of the document") }, TAG: function (e, t, n) { var i, r; 2 !== n.length && ce(e, "TAG directive accepts exactly two arguments"), i = n[0], r = n[1], G.test(i) || ce(e, "ill-formed tag handle (first argument) of the TAG directive"), P.call(e.tagMap, i) && ce(e, 'there is a previously declared suffix for "' + i + '" tag handle'), V.test(r) || ce(e, "ill-formed tag prefix (second argument) of the TAG directive"); try { r = decodeURIComponent(r) } catch (t) { ce(e, "tag prefix is malformed: " + r) } e.tagMap[i] = r } }; function pe(e, t, n, i) { var r, o, a, l; if (t < n) { if (l = e.input.slice(t, n), i) for (r = 0, o = l.length; r < o; r += 1)9 === (a = l.charCodeAt(r)) || 32 <= a && a <= 1114111 || ce(e, "expected valid JSON character"); else W.test(l) && ce(e, "the stream contains non-printable characters"); e.result += l } } function fe(e, t, i, r) { var o, a, l, c; for (n.isObject(i) || ce(e, "cannot merge mappings; the provided source object is unacceptable"), l = 0, c = (o = Object.keys(i)).length; l < c; l += 1)a = o[l], P.call(t, a) || (t[a] = i[a], r[a] = !0) } function de(e, t, n, i, r, o, a, l, c) { var s, u; if (Array.isArray(r)) for (s = 0, u = (r = Array.prototype.slice.call(r)).length; s < u; s += 1)Array.isArray(r[s]) && ce(e, "nested arrays are not supported inside keys"), "object" == typeof r && "[object Object]" === Z(r[s]) && (r[s] = "[object Object]"); if ("object" == typeof r && "[object Object]" === Z(r) && (r = "[object Object]"), r = String(r), null === t && (t = {}), "tag:yaml.org,2002:merge" === i) if (Array.isArray(o)) for (s = 0, u = o.length; s < u; s += 1)fe(e, t, o[s], n); else fe(e, t, o, n); else e.json || P.call(n, r) || !P.call(t, r) || (e.line = a || e.line, e.lineStart = l || e.lineStart, e.position = c || e.position, ce(e, "duplicated mapping key")), "__proto__" === r ? Object.defineProperty(t, r, { configurable: !0, enumerable: !0, writable: !0, value: o }) : t[r] = o, delete n[r]; return t } function he(e) { var t; 10 === (t = e.input.charCodeAt(e.position)) ? e.position++ : 13 === t ? (e.position++, 10 === e.input.charCodeAt(e.position) && e.position++) : ce(e, "a line break is expected"), e.line += 1, e.lineStart = e.position, e.firstTabInLine = -1 } function ge(e, t, n) { for (var i = 0, r = e.input.charCodeAt(e.position); 0 !== r;) { for (; Q(r);)9 === r && -1 === e.firstTabInLine && (e.firstTabInLine = e.position), r = e.input.charCodeAt(++e.position); if (t && 35 === r) do { r = e.input.charCodeAt(++e.position) } while (10 !== r && 13 !== r && 0 !== r); if (!J(r)) break; for (he(e), r = e.input.charCodeAt(e.position), i++, e.lineIndent = 0; 32 === r;)e.lineIndent++, r = e.input.charCodeAt(++e.position) } return -1 !== n && 0 !== i && e.lineIndent < n && se(e, "deficient indentation"), i } function me(e) { var t, n = e.position; return !(45 !== (t = e.input.charCodeAt(n)) && 46 !== t || t !== e.input.charCodeAt(n + 1) || t !== e.input.charCodeAt(n + 2) || (n += 3, 0 !== (t = e.input.charCodeAt(n)) && !z(t))) } function ye(e, t) { 1 === t ? e.result += " " : t > 1 && (e.result += n.repeat("\n", t - 1)) } function be(e, t) { var n, i, r = e.tag, o = e.anchor, a = [], l = !1; if (-1 !== e.firstTabInLine) return !1; for (null !== e.anchor && (e.anchorMap[e.anchor] = a), i = e.input.charCodeAt(e.position); 0 !== i && (-1 !== e.firstTabInLine && (e.position = e.firstTabInLine, ce(e, "tab characters must not be used in indentation")), 45 === i) && z(e.input.charCodeAt(e.position + 1));)if (l = !0, e.position++, ge(e, !0, -1) && e.lineIndent <= t) a.push(null), i = e.input.charCodeAt(e.position); else if (n = e.line, we(e, t, 3, !1, !0), a.push(e.result), ge(e, !0, -1), i = e.input.charCodeAt(e.position), (e.line === n || e.lineIndent > t) && 0 !== i) ce(e, "bad indentation of a sequence entry"); else if (e.lineIndent < t) break; return !!l && (e.tag = r, e.anchor = o, e.kind = "sequence", e.result = a, !0) } function Ae(e) { var t, n, i, r, o = !1, a = !1; if (33 !== (r = e.input.charCodeAt(e.position))) return !1; if (null !== e.tag && ce(e, "duplication of a tag property"), 60 === (r = e.input.charCodeAt(++e.position)) ? (o = !0, r = e.input.charCodeAt(++e.position)) : 33 === r ? (a = !0, n = "!!", r = e.input.charCodeAt(++e.position)) : n = "!", t = e.position, o) { do { r = e.input.charCodeAt(++e.position) } while (0 !== r && 62 !== r); e.position < e.length ? (i = e.input.slice(t, e.position), r = e.input.charCodeAt(++e.position)) : ce(e, "unexpected end of the stream within a verbatim tag") } else { for (; 0 !== r && !z(r);)33 === r && (a ? ce(e, "tag suffix cannot contain exclamation marks") : (n = e.input.slice(t - 1, e.position + 1), G.test(n) || ce(e, "named tag handle cannot contain such characters"), a = !0, t = e.position + 1)), r = e.input.charCodeAt(++e.position); i = e.input.slice(t, e.position), $.test(i) && ce(e, "tag suffix cannot contain flow indicator characters") } i && !V.test(i) && ce(e, "tag name cannot contain such characters: " + i); try { i = decodeURIComponent(i) } catch (t) { ce(e, "tag name is malformed: " + i) } return o ? e.tag = i : P.call(e.tagMap, n) ? e.tag = e.tagMap[n] + i : "!" === n ? e.tag = "!" + i : "!!" === n ? e.tag = "tag:yaml.org,2002:" + i : ce(e, 'undeclared tag handle "' + n + '"'), !0 } function ve(e) { var t, n; if (38 !== (n = e.input.charCodeAt(e.position))) return !1; for (null !== e.anchor && ce(e, "duplication of an anchor property"), n = e.input.charCodeAt(++e.position), t = e.position; 0 !== n && !z(n) && !X(n);)n = e.input.charCodeAt(++e.position); return e.position === t && ce(e, "name of an anchor node must contain at least one character"), e.anchor = e.input.slice(t, e.position), !0 } function we(e, t, i, r, o) { var a, l, c, s, u, p, f, d, h, g = 1, m = !1, y = !1; if (null !== e.listener && e.listener("open", e), e.tag = null, e.anchor = null, e.kind = null, e.result = null, a = l = c = 4 === i || 3 === i, r && ge(e, !0, -1) && (m = !0, e.lineIndent > t ? g = 1 : e.lineIndent === t ? g = 0 : e.lineIndent < t && (g = -1)), 1 === g) for (; Ae(e) || ve(e);)ge(e, !0, -1) ? (m = !0, c = a, e.lineIndent > t ? g = 1 : e.lineIndent === t ? g = 0 : e.lineIndent < t && (g = -1)) : c = !1; if (c && (c = m || o), 1 !== g && 4 !== i || (d = 1 === i || 2 === i ? t : t + 1, h = e.position - e.lineStart, 1 === g ? c && (be(e, h) || function (e, t, n) { var i, r, o, a, l, c, s, u = e.tag, p = e.anchor, f = {}, d = Object.create(null), h = null, g = null, m = null, y = !1, b = !1; if (-1 !== e.firstTabInLine) return !1; for (null !== e.anchor && (e.anchorMap[e.anchor] = f), s = e.input.charCodeAt(e.position); 0 !== s;) { if (y || -1 === e.firstTabInLine || (e.position = e.firstTabInLine, ce(e, "tab characters must not be used in indentation")), i = e.input.charCodeAt(e.position + 1), o = e.line, 63 !== s && 58 !== s || !z(i)) { if (a = e.line, l = e.lineStart, c = e.position, !we(e, n, 2, !1, !0)) break; if (e.line === o) { for (s = e.input.charCodeAt(e.position); Q(s);)s = e.input.charCodeAt(++e.position); if (58 === s) z(s = e.input.charCodeAt(++e.position)) || ce(e, "a whitespace character is expected after the key-value separator within a block mapping"), y && (de(e, f, d, h, g, null, a, l, c), h = g = m = null), b = !0, y = !1, r = !1, h = e.tag, g = e.result; else { if (!b) return e.tag = u, e.anchor = p, !0; ce(e, "can not read an implicit mapping pair; a colon is missed") } } else { if (!b) return e.tag = u, e.anchor = p, !0; ce(e, "can not read a block mapping entry; a multiline key may not be an implicit key") } } else 63 === s ? (y && (de(e, f, d, h, g, null, a, l, c), h = g = m = null), b = !0, y = !0, r = !0) : y ? (y = !1, r = !0) : ce(e, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"), e.position += 1, s = i; if ((e.line === o || e.lineIndent > t) && (y && (a = e.line, l = e.lineStart, c = e.position), we(e, t, 4, !0, r) && (y ? g = e.result : m = e.result), y || (de(e, f, d, h, g, m, a, l, c), h = g = m = null), ge(e, !0, -1), s = e.input.charCodeAt(e.position)), (e.line === o || e.lineIndent > t) && 0 !== s) ce(e, "bad indentation of a mapping entry"); else if (e.lineIndent < t) break } return y && de(e, f, d, h, g, null, a, l, c), b && (e.tag = u, e.anchor = p, e.kind = "mapping", e.result = f), b }(e, h, d)) || function (e, t) { var n, i, r, o, a, l, c, s, u, p, f, d, h = !0, g = e.tag, m = e.anchor, y = Object.create(null); if (91 === (d = e.input.charCodeAt(e.position))) a = 93, s = !1, o = []; else { if (123 !== d) return !1; a = 125, s = !0, o = {} } for (null !== e.anchor && (e.anchorMap[e.anchor] = o), d = e.input.charCodeAt(++e.position); 0 !== d;) { if (ge(e, !0, t), (d = e.input.charCodeAt(e.position)) === a) return e.position++, e.tag = g, e.anchor = m, e.kind = s ? "mapping" : "sequence", e.result = o, !0; h ? 44 === d && ce(e, "expected the node content, but found ','") : ce(e, "missed comma between flow collection entries"), f = null, l = c = !1, 63 === d && z(e.input.charCodeAt(e.position + 1)) && (l = c = !0, e.position++, ge(e, !0, t)), n = e.line, i = e.lineStart, r = e.position, we(e, t, 1, !1, !0), p = e.tag, u = e.result, ge(e, !0, t), d = e.input.charCodeAt(e.position), !c && e.line !== n || 58 !== d || (l = !0, d = e.input.charCodeAt(++e.position), ge(e, !0, t), we(e, t, 1, !1, !0), f = e.result), s ? de(e, o, y, p, u, f, n, i, r) : l ? o.push(de(e, null, y, p, u, f, n, i, r)) : o.push(u), ge(e, !0, t), 44 === (d = e.input.charCodeAt(e.position)) ? (h = !0, d = e.input.charCodeAt(++e.position)) : h = !1 } ce(e, "unexpected end of the stream within a flow collection") }(e, d) ? y = !0 : (l && function (e, t) { var i, r, o, a, l, c = 1, s = !1, u = !1, p = t, f = 0, d = !1; if (124 === (a = e.input.charCodeAt(e.position))) r = !1; else { if (62 !== a) return !1; r = !0 } for (e.kind = "scalar", e.result = ""; 0 !== a;)if (43 === (a = e.input.charCodeAt(++e.position)) || 45 === a) 1 === c ? c = 43 === a ? 3 : 2 : ce(e, "repeat of a chomping mode identifier"); else { if (!((o = 48 <= (l = a) && l <= 57 ? l - 48 : -1) >= 0)) break; 0 === o ? ce(e, "bad explicit indentation width of a block scalar; it cannot be less than one") : u ? ce(e, "repeat of an indentation width identifier") : (p = t + o - 1, u = !0) } if (Q(a)) { do { a = e.input.charCodeAt(++e.position) } while (Q(a)); if (35 === a) do { a = e.input.charCodeAt(++e.position) } while (!J(a) && 0 !== a) } for (; 0 !== a;) { for (he(e), e.lineIndent = 0, a = e.input.charCodeAt(e.position); (!u || e.lineIndent < p) && 32 === a;)e.lineIndent++, a = e.input.charCodeAt(++e.position); if (!u && e.lineIndent > p && (p = e.lineIndent), J(a)) f++; else { if (e.lineIndent < p) { 3 === c ? e.result += n.repeat("\n", s ? 1 + f : f) : 1 === c && s && (e.result += "\n"); break } for (r ? Q(a) ? (d = !0, e.result += n.repeat("\n", s ? 1 + f : f)) : d ? (d = !1, e.result += n.repeat("\n", f + 1)) : 0 === f ? s && (e.result += " ") : e.result += n.repeat("\n", f) : e.result += n.repeat("\n", s ? 1 + f : f), s = !0, u = !0, f = 0, i = e.position; !J(a) && 0 !== a;)a = e.input.charCodeAt(++e.position); pe(e, i, e.position, !1) } } return !0 }(e, d) || function (e, t) { var n, i, r; if (39 !== (n = e.input.charCodeAt(e.position))) return !1; for (e.kind = "scalar", e.result = "", e.position++, i = r = e.position; 0 !== (n = e.input.charCodeAt(e.position));)if (39 === n) { if (pe(e, i, e.position, !0), 39 !== (n = e.input.charCodeAt(++e.position))) return !0; i = e.position, e.position++, r = e.position } else J(n) ? (pe(e, i, r, !0), ye(e, ge(e, !1, t)), i = r = e.position) : e.position === e.lineStart && me(e) ? ce(e, "unexpected end of the document within a single quoted scalar") : (e.position++, r = e.position); ce(e, "unexpected end of the stream within a single quoted scalar") }(e, d) || function (e, t) { var n, i, r, o, a, l, c; if (34 !== (l = e.input.charCodeAt(e.position))) return !1; for (e.kind = "scalar", e.result = "", e.position++, n = i = e.position; 0 !== (l = e.input.charCodeAt(e.position));) { if (34 === l) return pe(e, n, e.position, !0), e.position++, !0; if (92 === l) { if (pe(e, n, e.position, !0), J(l = e.input.charCodeAt(++e.position))) ge(e, !1, t); else if (l < 256 && ie[l]) e.result += re[l], e.position++; else if ((a = 120 === (c = l) ? 2 : 117 === c ? 4 : 85 === c ? 8 : 0) > 0) { for (r = a, o = 0; r > 0; r--)(a = ee(l = e.input.charCodeAt(++e.position))) >= 0 ? o = (o << 4) + a : ce(e, "expected hexadecimal character"); e.result += ne(o), e.position++ } else ce(e, "unknown escape sequence"); n = i = e.position } else J(l) ? (pe(e, n, i, !0), ye(e, ge(e, !1, t)), n = i = e.position) : e.position === e.lineStart && me(e) ? ce(e, "unexpected end of the document within a double quoted scalar") : (e.position++, i = e.position) } ce(e, "unexpected end of the stream within a double quoted scalar") }(e, d) ? y = !0 : !function (e) { var t, n, i; if (42 !== (i = e.input.charCodeAt(e.position))) return !1; for (i = e.input.charCodeAt(++e.position), t = e.position; 0 !== i && !z(i) && !X(i);)i = e.input.charCodeAt(++e.position); return e.position === t && ce(e, "name of an alias node must contain at least one character"), n = e.input.slice(t, e.position), P.call(e.anchorMap, n) || ce(e, 'unidentified alias "' + n + '"'), e.result = e.anchorMap[n], ge(e, !0, -1), !0 }(e) ? function (e, t, n) { var i, r, o, a, l, c, s, u, p = e.kind, f = e.result; if (z(u = e.input.charCodeAt(e.position)) || X(u) || 35 === u || 38 === u || 42 === u || 33 === u || 124 === u || 62 === u || 39 === u || 34 === u || 37 === u || 64 === u || 96 === u) return !1; if ((63 === u || 45 === u) && (z(i = e.input.charCodeAt(e.position + 1)) || n && X(i))) return !1; for (e.kind = "scalar", e.result = "", r = o = e.position, a = !1; 0 !== u;) { if (58 === u) { if (z(i = e.input.charCodeAt(e.position + 1)) || n && X(i)) break } else if (35 === u) { if (z(e.input.charCodeAt(e.position - 1))) break } else { if (e.position === e.lineStart && me(e) || n && X(u)) break; if (J(u)) { if (l = e.line, c = e.lineStart, s = e.lineIndent, ge(e, !1, -1), e.lineIndent >= t) { a = !0, u = e.input.charCodeAt(e.position); continue } e.position = o, e.line = l, e.lineStart = c, e.lineIndent = s; break } } a && (pe(e, r, o, !1), ye(e, e.line - l), r = o = e.position, a = !1), Q(u) || (o = e.position + 1), u = e.input.charCodeAt(++e.position) } return pe(e, r, o, !1), !!e.result || (e.kind = p, e.result = f, !1) }(e, d, 1 === i) && (y = !0, null === e.tag && (e.tag = "?")) : (y = !0, null === e.tag && null === e.anchor || ce(e, "alias node should not have any properties")), null !== e.anchor && (e.anchorMap[e.anchor] = e.result)) : 0 === g && (y = c && be(e, h))), null === e.tag) null !== e.anchor && (e.anchorMap[e.anchor] = e.result); else if ("?" === e.tag) { for (null !== e.result && "scalar" !== e.kind && ce(e, 'unacceptable node kind for ! tag; it should be "scalar", not "' + e.kind + '"'), s = 0, u = e.implicitTypes.length; s < u; s += 1)if ((f = e.implicitTypes[s]).resolve(e.result)) { e.result = f.construct(e.result), e.tag = f.tag, null !== e.anchor && (e.anchorMap[e.anchor] = e.result); break } } else if ("!" !== e.tag) { if (P.call(e.typeMap[e.kind || "fallback"], e.tag)) f = e.typeMap[e.kind || "fallback"][e.tag]; else for (f = null, s = 0, u = (p = e.typeMap.multi[e.kind || "fallback"]).length; s < u; s += 1)if (e.tag.slice(0, p[s].tag.length) === p[s].tag) { f = p[s]; break } f || ce(e, "unknown tag !<" + e.tag + ">"), null !== e.result && f.kind !== e.kind && ce(e, "unacceptable node kind for !<" + e.tag + '> tag; it should be "' + f.kind + '", not "' + e.kind + '"'), f.resolve(e.result, e.tag) ? (e.result = f.construct(e.result, e.tag), null !== e.anchor && (e.anchorMap[e.anchor] = e.result)) : ce(e, "cannot resolve a node with !<" + e.tag + "> explicit tag") } return null !== e.listener && e.listener("close", e), null !== e.tag || null !== e.anchor || y } function ke(e) { var t, n, i, r, o = e.position, a = !1; for (e.version = null, e.checkLineBreaks = e.legacy, e.tagMap = Object.create(null), e.anchorMap = Object.create(null); 0 !== (r = e.input.charCodeAt(e.position)) && (ge(e, !0, -1), r = e.input.charCodeAt(e.position), !(e.lineIndent > 0 || 37 !== r));) { for (a = !0, r = e.input.charCodeAt(++e.position), t = e.position; 0 !== r && !z(r);)r = e.input.charCodeAt(++e.position); for (i = [], (n = e.input.slice(t, e.position)).length < 1 && ce(e, "directive name must not be less than one character in length"); 0 !== r;) { for (; Q(r);)r = e.input.charCodeAt(++e.position); if (35 === r) { do { r = e.input.charCodeAt(++e.position) } while (0 !== r && !J(r)); break } if (J(r)) break; for (t = e.position; 0 !== r && !z(r);)r = e.input.charCodeAt(++e.position); i.push(e.input.slice(t, e.position)) } 0 !== r && he(e), P.call(ue, n) ? ue[n](e, n, i) : se(e, 'unknown document directive "' + n + '"') } ge(e, !0, -1), 0 === e.lineIndent && 45 === e.input.charCodeAt(e.position) && 45 === e.input.charCodeAt(e.position + 1) && 45 === e.input.charCodeAt(e.position + 2) ? (e.position += 3, ge(e, !0, -1)) : a && ce(e, "directives end mark is expected"), we(e, e.lineIndent - 1, 4, !1, !0), ge(e, !0, -1), e.checkLineBreaks && H.test(e.input.slice(o, e.position)) && se(e, "non-ASCII line breaks are interpreted as content"), e.documents.push(e.result), e.position === e.lineStart && me(e) ? 46 === e.input.charCodeAt(e.position) && (e.position += 3, ge(e, !0, -1)) : e.position < e.length - 1 && ce(e, "end of the stream or a document separator is expected") } function Ce(e, t) { t = t || {}, 0 !== (e = String(e)).length && (10 !== e.charCodeAt(e.length - 1) && 13 !== e.charCodeAt(e.length - 1) && (e += "\n"), 65279 === e.charCodeAt(0) && (e = e.slice(1))); var n = new ae(e, t), i = e.indexOf("\0"); for (-1 !== i && (n.position = i, ce(n, "null byte is not allowed in input")), n.input += "\0"; 32 === n.input.charCodeAt(n.position);)n.lineIndent += 1, n.position += 1; for (; n.position < n.length - 1;)ke(n); return n.documents } var xe = { loadAll: function (e, t, n) { null !== t && "object" == typeof t && void 0 === n && (n = t, t = null); var i = Ce(e, n); if ("function" != typeof t) return i; for (var r = 0, o = i.length; r < o; r += 1)t(i[r]) }, load: function (e, t) { var n = Ce(e, t); if (0 !== n.length) { if (1 === n.length) return n[0]; throw new o("expected a single document in the stream, but found more") } } }, Ie = Object.prototype.toString, Se = Object.prototype.hasOwnProperty, Oe = 65279, je = { 0: "\\0", 7: "\\a", 8: "\\b", 9: "\\t", 10: "\\n", 11: "\\v", 12: "\\f", 13: "\\r", 27: "\\e", 34: '\\"', 92: "\\\\", 133: "\\N", 160: "\\_", 8232: "\\L", 8233: "\\P" }, Te = ["y", "Y", "yes", "Yes", "YES", "on", "On", "ON", "n", "N", "no", "No", "NO", "off", "Off", "OFF"], Ne = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; function Fe(e) { var t, i, r; if (t = e.toString(16).toUpperCase(), e <= 255) i = "x", r = 2; else if (e <= 65535) i = "u", r = 4; else { if (!(e <= 4294967295)) throw new o("code point within a string may not be greater than 0xFFFFFFFF"); i = "U", r = 8 } return "\\" + i + n.repeat("0", r - t.length) + t } function Ee(e) { this.schema = e.schema || K, this.indent = Math.max(1, e.indent || 2), this.noArrayIndent = e.noArrayIndent || !1, this.skipInvalid = e.skipInvalid || !1, this.flowLevel = n.isNothing(e.flowLevel) ? -1 : e.flowLevel, this.styleMap = function (e, t) { var n, i, r, o, a, l, c; if (null === t) return {}; for (n = {}, r = 0, o = (i = Object.keys(t)).length; r < o; r += 1)a = i[r], l = String(t[a]), "!!" === a.slice(0, 2) && (a = "tag:yaml.org,2002:" + a.slice(2)), (c = e.compiledTypeMap.fallback[a]) && Se.call(c.styleAliases, l) && (l = c.styleAliases[l]), n[a] = l; return n }(this.schema, e.styles || null), this.sortKeys = e.sortKeys || !1, this.lineWidth = e.lineWidth || 80, this.noRefs = e.noRefs || !1, this.noCompatMode = e.noCompatMode || !1, this.condenseFlow = e.condenseFlow || !1, this.quotingType = '"' === e.quotingType ? 2 : 1, this.forceQuotes = e.forceQuotes || !1, this.replacer = "function" == typeof e.replacer ? e.replacer : null, this.implicitTypes = this.schema.compiledImplicit, this.explicitTypes = this.schema.compiledExplicit, this.tag = null, this.result = "", this.duplicates = [], this.usedDuplicates = null } function Me(e, t) { for (var i, r = n.repeat(" ", t), o = 0, a = -1, l = "", c = e.length; o < c;)-1 === (a = e.indexOf("\n", o)) ? (i = e.slice(o), o = c) : (i = e.slice(o, a + 1), o = a + 1), i.length && "\n" !== i && (l += r), l += i; return l } function Le(e, t) { return "\n" + n.repeat(" ", e.indent * t) } function _e(e) { return 32 === e || 9 === e } function De(e) { return 32 <= e && e <= 126 || 161 <= e && e <= 55295 && 8232 !== e && 8233 !== e || 57344 <= e && e <= 65533 && e !== Oe || 65536 <= e && e <= 1114111 } function Ue(e) { return De(e) && e !== Oe && 13 !== e && 10 !== e } function qe(e, t, n) { var i = Ue(e), r = i && !_e(e); return (n ? i : i && 44 !== e && 91 !== e && 93 !== e && 123 !== e && 125 !== e) && 35 !== e && !(58 === t && !r) || Ue(t) && !_e(t) && 35 === e || 58 === t && r } function Ye(e, t) { var n, i = e.charCodeAt(t); return i >= 55296 && i <= 56319 && t + 1 < e.length && (n = e.charCodeAt(t + 1)) >= 56320 && n <= 57343 ? 1024 * (i - 55296) + n - 56320 + 65536 : i } function Re(e) { return /^\n* /.test(e) } function Be(e, t, n, i, r, o, a, l) { var c, s, u = 0, p = null, f = !1, d = !1, h = -1 !== i, g = -1, m = De(s = Ye(e, 0)) && s !== Oe && !_e(s) && 45 !== s && 63 !== s && 58 !== s && 44 !== s && 91 !== s && 93 !== s && 123 !== s && 125 !== s && 35 !== s && 38 !== s && 42 !== s && 33 !== s && 124 !== s && 61 !== s && 62 !== s && 39 !== s && 34 !== s && 37 !== s && 64 !== s && 96 !== s && function (e) { return !_e(e) && 58 !== e }(Ye(e, e.length - 1)); if (t || a) for (c = 0; c < e.length; u >= 65536 ? c += 2 : c++) { if (!De(u = Ye(e, c))) return 5; m = m && qe(u, p, l), p = u } else { for (c = 0; c < e.length; u >= 65536 ? c += 2 : c++) { if (10 === (u = Ye(e, c))) f = !0, h && (d = d || c - g - 1 > i && " " !== e[g + 1], g = c); else if (!De(u)) return 5; m = m && qe(u, p, l), p = u } d = d || h && c - g - 1 > i && " " !== e[g + 1] } return f || d ? n > 9 && Re(e) ? 5 : a ? 2 === o ? 5 : 2 : d ? 4 : 3 : !m || a || r(e) ? 2 === o ? 5 : 2 : 1 } function Ke(e, t, n, i, r) { e.dump = function () { if (0 === t.length) return 2 === e.quotingType ? '""' : "''"; if (!e.noCompatMode && (-1 !== Te.indexOf(t) || Ne.test(t))) return 2 === e.quotingType ? '"' + t + '"' : "'" + t + "'"; var a = e.indent * Math.max(1, n), l = -1 === e.lineWidth ? -1 : Math.max(Math.min(e.lineWidth, 40), e.lineWidth - a), c = i || e.flowLevel > -1 && n >= e.flowLevel; switch (Be(t, c, e.indent, l, (function (t) { return function (e, t) { var n, i; for (n = 0, i = e.implicitTypes.length; n < i; n += 1)if (e.implicitTypes[n].resolve(t)) return !0; return !1 }(e, t) }), e.quotingType, e.forceQuotes && !i, r)) { case 1: return t; case 2: return "'" + t.replace(/'/g, "''") + "'"; case 3: return "|" + Pe(t, e.indent) + We(Me(t, a)); case 4: return ">" + Pe(t, e.indent) + We(Me(function (e, t) { var n, i, r = /(\n+)([^\n]*)/g, o = (l = e.indexOf("\n"), l = -1 !== l ? l : e.length, r.lastIndex = l, He(e.slice(0, l), t)), a = "\n" === e[0] || " " === e[0]; var l; for (; i = r.exec(e);) { var c = i[1], s = i[2]; n = " " === s[0], o += c + (a || n || "" === s ? "" : "\n") + He(s, t), a = n } return o }(t, l), a)); case 5: return '"' + function (e) { for (var t, n = "", i = 0, r = 0; r < e.length; i >= 65536 ? r += 2 : r++)i = Ye(e, r), !(t = je[i]) && De(i) ? (n += e[r], i >= 65536 && (n += e[r + 1])) : n += t || Fe(i); return n }(t) + '"'; default: throw new o("impossible error: invalid scalar style") } }() } function Pe(e, t) { var n = Re(e) ? String(t) : "", i = "\n" === e[e.length - 1]; return n + (i && ("\n" === e[e.length - 2] || "\n" === e) ? "+" : i ? "" : "-") + "\n" } function We(e) { return "\n" === e[e.length - 1] ? e.slice(0, -1) : e } function He(e, t) { if ("" === e || " " === e[0]) return e; for (var n, i, r = / [^ ]/g, o = 0, a = 0, l = 0, c = ""; n = r.exec(e);)(l = n.index) - o > t && (i = a > o ? a : l, c += "\n" + e.slice(o, i), o = i + 1), a = l; return c += "\n", e.length - o > t && a > o ? c += e.slice(o, a) + "\n" + e.slice(a + 1) : c += e.slice(o), c.slice(1) } function $e(e, t, n, i) { var r, o, a, l = "", c = e.tag; for (r = 0, o = n.length; r < o; r += 1)a = n[r], e.replacer && (a = e.replacer.call(n, String(r), a)), (Ve(e, t + 1, a, !0, !0, !1, !0) || void 0 === a && Ve(e, t + 1, null, !0, !0, !1, !0)) && (i && "" === l || (l += Le(e, t)), e.dump && 10 === e.dump.charCodeAt(0) ? l += "-" : l += "- ", l += e.dump); e.tag = c, e.dump = l || "[]" } function Ge(e, t, n) { var i, r, a, l, c, s; for (a = 0, l = (r = n ? e.explicitTypes : e.implicitTypes).length; a < l; a += 1)if (((c = r[a]).instanceOf || c.predicate) && (!c.instanceOf || "object" == typeof t && t instanceof c.instanceOf) && (!c.predicate || c.predicate(t))) { if (n ? c.multi && c.representName ? e.tag = c.representName(t) : e.tag = c.tag : e.tag = "?", c.represent) { if (s = e.styleMap[c.tag] || c.defaultStyle, "[object Function]" === Ie.call(c.represent)) i = c.represent(t, s); else { if (!Se.call(c.represent, s)) throw new o("!<" + c.tag + '> tag resolver accepts not "' + s + '" style'); i = c.represent[s](t, s) } e.dump = i } return !0 } return !1 } function Ve(e, t, n, i, r, a, l) { e.tag = null, e.dump = n, Ge(e, n, !1) || Ge(e, n, !0); var c, s = Ie.call(e.dump), u = i; i && (i = e.flowLevel < 0 || e.flowLevel > t); var p, f, d = "[object Object]" === s || "[object Array]" === s; if (d && (f = -1 !== (p = e.duplicates.indexOf(n))), (null !== e.tag && "?" !== e.tag || f || 2 !== e.indent && t > 0) && (r = !1), f && e.usedDuplicates[p]) e.dump = "*ref_" + p; else { if (d && f && !e.usedDuplicates[p] && (e.usedDuplicates[p] = !0), "[object Object]" === s) i && 0 !== Object.keys(e.dump).length ? (!function (e, t, n, i) { var r, a, l, c, s, u, p = "", f = e.tag, d = Object.keys(n); if (!0 === e.sortKeys) d.sort(); else if ("function" == typeof e.sortKeys) d.sort(e.sortKeys); else if (e.sortKeys) throw new o("sortKeys must be a boolean or a function"); for (r = 0, a = d.length; r < a; r += 1)u = "", i && "" === p || (u += Le(e, t)), c = n[l = d[r]], e.replacer && (c = e.replacer.call(n, l, c)), Ve(e, t + 1, l, !0, !0, !0) && ((s = null !== e.tag && "?" !== e.tag || e.dump && e.dump.length > 1024) && (e.dump && 10 === e.dump.charCodeAt(0) ? u += "?" : u += "? "), u += e.dump, s && (u += Le(e, t)), Ve(e, t + 1, c, !0, s) && (e.dump && 10 === e.dump.charCodeAt(0) ? u += ":" : u += ": ", p += u += e.dump)); e.tag = f, e.dump = p || "{}" }(e, t, e.dump, r), f && (e.dump = "&ref_" + p + e.dump)) : (!function (e, t, n) { var i, r, o, a, l, c = "", s = e.tag, u = Object.keys(n); for (i = 0, r = u.length; i < r; i += 1)l = "", "" !== c && (l += ", "), e.condenseFlow && (l += '"'), a = n[o = u[i]], e.replacer && (a = e.replacer.call(n, o, a)), Ve(e, t, o, !1, !1) && (e.dump.length > 1024 && (l += "? "), l += e.dump + (e.condenseFlow ? '"' : "") + ":" + (e.condenseFlow ? "" : " "), Ve(e, t, a, !1, !1) && (c += l += e.dump)); e.tag = s, e.dump = "{" + c + "}" }(e, t, e.dump), f && (e.dump = "&ref_" + p + " " + e.dump)); else if ("[object Array]" === s) i && 0 !== e.dump.length ? (e.noArrayIndent && !l && t > 0 ? $e(e, t - 1, e.dump, r) : $e(e, t, e.dump, r), f && (e.dump = "&ref_" + p + e.dump)) : (!function (e, t, n) { var i, r, o, a = "", l = e.tag; for (i = 0, r = n.length; i < r; i += 1)o = n[i], e.replacer && (o = e.replacer.call(n, String(i), o)), (Ve(e, t, o, !1, !1) || void 0 === o && Ve(e, t, null, !1, !1)) && ("" !== a && (a += "," + (e.condenseFlow ? "" : " ")), a += e.dump); e.tag = l, e.dump = "[" + a + "]" }(e, t, e.dump), f && (e.dump = "&ref_" + p + " " + e.dump)); else { if ("[object String]" !== s) { if ("[object Undefined]" === s) return !1; if (e.skipInvalid) return !1; throw new o("unacceptable kind of an object to dump " + s) } "?" !== e.tag && Ke(e, e.dump, t, a, u) } null !== e.tag && "?" !== e.tag && (c = encodeURI("!" === e.tag[0] ? e.tag.slice(1) : e.tag).replace(/!/g, "%21"), c = "!" === e.tag[0] ? "!" + c : "tag:yaml.org,2002:" === c.slice(0, 18) ? "!!" + c.slice(18) : "!<" + c + ">", e.dump = c + " " + e.dump) } return !0 } function Ze(e, t) { var n, i, r = [], o = []; for (Je(e, r, o), n = 0, i = o.length; n < i; n += 1)t.duplicates.push(r[o[n]]); t.usedDuplicates = new Array(i) } function Je(e, t, n) { var i, r, o; if (null !== e && "object" == typeof e) if (-1 !== (r = t.indexOf(e))) -1 === n.indexOf(r) && n.push(r); else if (t.push(e), Array.isArray(e)) for (r = 0, o = e.length; r < o; r += 1)Je(e[r], t, n); else for (r = 0, o = (i = Object.keys(e)).length; r < o; r += 1)Je(e[i[r]], t, n) } function Qe(e, t) { return function () { throw new Error("Function yaml." + e + " is removed in js-yaml 4. Use yaml." + t + " instead, which is now safe by default.") } } var ze = p, Xe = h, et = b, tt = O, nt = j, it = K, rt = xe.load, ot = xe.loadAll, at = { dump: function (e, t) { var n = new Ee(t = t || {}); n.noRefs || Ze(e, n); var i = e; return n.replacer && (i = n.replacer.call({ "": i }, "", i)), Ve(n, 0, i, !0, !0) ? n.dump + "\n" : "" } }.dump, lt = o, ct = { binary: L, float: S, map: y, null: A, pairs: Y, set: B, timestamp: F, bool: v, int: C, merge: E, omap: U, seq: m, str: g }, st = Qe("safeLoad", "load"), ut = Qe("safeLoadAll", "loadAll"), pt = Qe("safeDump", "dump"), ft = { Type: ze, Schema: Xe, FAILSAFE_SCHEMA: et, JSON_SCHEMA: tt, CORE_SCHEMA: nt, DEFAULT_SCHEMA: it, load: rt, loadAll: ot, dump: at, YAMLException: lt, types: ct, safeLoad: st, safeLoadAll: ut, safeDump: pt }; e.CORE_SCHEMA = nt, e.DEFAULT_SCHEMA = it, e.FAILSAFE_SCHEMA = et, e.JSON_SCHEMA = tt, e.Schema = Xe, e.Type = ze, e.YAMLException = lt, e.default = ft, e.dump = at, e.load = rt, e.loadAll = ot, e.safeDump = pt, e.safeLoad = st, e.safeLoadAll = ut, e.types = ct, Object.defineProperty(e, "__esModule", { value: !0 }) })); 3 | -------------------------------------------------------------------------------- /scripts/easy_prompt_selector.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import random 3 | import re 4 | import yaml 5 | import gradio as gr 6 | 7 | import modules.scripts as scripts 8 | from modules.scripts import AlwaysVisible, basedir 9 | from modules import shared 10 | from scripts.setup import write_filename_list 11 | 12 | FILE_DIR = Path().absolute() 13 | BASE_DIR = Path(basedir()) 14 | TAGS_DIR = BASE_DIR.joinpath('tags') 15 | 16 | def tag_files(): 17 | return TAGS_DIR.rglob("*.yml") 18 | 19 | def load_tags(): 20 | tags = {} 21 | for filepath in tag_files(): 22 | with open(filepath, "r", encoding="utf-8") as file: 23 | yml = yaml.safe_load(file) 24 | tags[filepath.stem] = yml 25 | 26 | return tags 27 | 28 | def find_tag(tags, location): 29 | if type(location) == str: 30 | return tags[location] 31 | 32 | value = '' 33 | if len(location) > 0: 34 | value = tags 35 | for tag in location: 36 | value = value[tag] 37 | 38 | if type(value) == dict: 39 | key = random.choice(list(value.keys())) 40 | tag = value[key] 41 | if type(tag) == dict: 42 | value = find_tag(tag, [random.choice(list(tag.keys()))]) 43 | else: 44 | value = find_tag(value, key) 45 | 46 | if (type(value) == list): 47 | value = random.choice(value) 48 | 49 | return value 50 | 51 | def replace_template(tags, prompt): 52 | count = 0 53 | while count < 100: 54 | if not '@' in prompt: 55 | break 56 | 57 | for match in re.finditer(r'(@((?P\d+(-\d+)?)\$\$)?(?P[^>]+?)@)', prompt): 58 | template = match.group() 59 | try: 60 | try: 61 | result = list(map(lambda x: int(x), match.group('num').split('-'))) 62 | min_count = min(result) 63 | max_count = max(result) 64 | except Exception as e: 65 | min_count, max_count = 1, 1 66 | count = random.randint(min_count, max_count) 67 | 68 | values = list(map(lambda x: find_tag(tags, match.group('ref').split(':')), list(range(count)))) 69 | prompt = prompt.replace(template, ', '.join(values), 1) 70 | except Exception as e: 71 | prompt = prompt.replace(template, '', 1) 72 | count += 1 73 | 74 | return prompt 75 | 76 | class Script(scripts.Script): 77 | tags = {} 78 | 79 | def __init__(self): 80 | super().__init__() 81 | self.tags = load_tags() 82 | 83 | def title(self): 84 | return "EasyPromptSelector" 85 | 86 | def show(self, is_img2img): 87 | if (is_img2img): 88 | return None 89 | 90 | return AlwaysVisible 91 | 92 | def ui(self, is_img2img): 93 | reload_button = gr.Button('🔄', variant='secondary', elem_id='easy_prompt_selector_reload_button') 94 | reload_button.style(size='sm') 95 | 96 | def reload(): 97 | self.tags = load_tags() 98 | write_filename_list() 99 | 100 | reload_button.click(fn=reload) 101 | 102 | return [reload_button] 103 | 104 | def replace_template_tags(self, p): 105 | if shared.opts.eps_use_old_template_feature == False: 106 | if ('@' in p.prompt): 107 | for i in range(len(p.all_prompts)): 108 | self.save_prompt_to_pnginfo(p) 109 | 110 | prompt = "".join(replace_template(self.tags, p.all_prompts[i])) 111 | p.all_prompts[i] = prompt 112 | 113 | if ('@' in p.negative_prompt): 114 | for i in range(len(p.all_negative_prompts)): 115 | self.save_prompt_to_pnginfo(p, True) 116 | 117 | negative_prompt = "".join(replace_template(self.tags, p.all_negative_prompts[i])) 118 | p.all_negative_prompts[i] = negative_prompt 119 | else: 120 | if ('@' in p.prompt): 121 | self.save_prompt_to_pnginfo(p) 122 | 123 | p.prompt = replace_template(self.tags, p.prompt) 124 | for i in range(len(p.all_prompts)): 125 | p.all_prompts[i] = p.prompt 126 | 127 | if ('@' in p.negative_prompt): 128 | self.save_prompt_to_pnginfo(p, True) 129 | 130 | p.negative_prompt = replace_template(self.tags, p.negative_prompt) 131 | for i in range(len(p.all_negative_prompts)): 132 | p.all_negative_prompts[i] = p.negative_prompt 133 | 134 | def save_prompt_to_pnginfo(self, p, is_negative = False): 135 | if shared.opts.eps_enable_save_raw_prompt_to_pnginfo == False: 136 | return 137 | 138 | if is_negative == False: 139 | prompt = p.prompt.replace('\n', ' ') 140 | param_name = "Input Prompt" 141 | else: 142 | prompt = p.negative_prompt.replace('\n', ' ') 143 | param_name = "Input NegativePrompt" 144 | 145 | p.extra_generation_params.update({param_name: prompt}) 146 | 147 | def process(self, p, *args): 148 | self.replace_template_tags(p) 149 | -------------------------------------------------------------------------------- /scripts/settings.py: -------------------------------------------------------------------------------- 1 | from modules import script_callbacks, shared 2 | 3 | def on_ui_settings(): 4 | shared.opts.add_option("eps_enable_save_raw_prompt_to_pnginfo", shared.OptionInfo(False, "元プロンプトを pngninfo に保存する", section=("easy_prompt_selector", "EasyPromptSelector"))) 5 | shared.opts.add_option("eps_use_old_template_feature", shared.OptionInfo(False, "古いランダム機能の実装を使用する(sdweb-eagle-pnginfo との互換性のため)", section=("easy_prompt_selector", "EasyPromptSelector"))) 6 | 7 | script_callbacks.on_ui_settings(on_ui_settings) 8 | -------------------------------------------------------------------------------- /scripts/setup.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import shutil 3 | import os 4 | 5 | from modules import scripts 6 | 7 | FILE_DIR = Path().absolute() 8 | BASE_DIR = Path(scripts.basedir()) 9 | TEMP_DIR = FILE_DIR.joinpath('tmp') 10 | 11 | TAGS_DIR = BASE_DIR.joinpath('tags') 12 | EXAMPLES_DIR = BASE_DIR.joinpath('tags_examples') 13 | 14 | FILENAME_LIST = 'easyPromptSelector.txt' 15 | 16 | os.makedirs(TEMP_DIR, exist_ok=True) 17 | 18 | def examples(): 19 | return EXAMPLES_DIR.rglob("*.yml") 20 | 21 | def copy_examples(): 22 | for file in examples(): 23 | file_path = str(file).replace('tags_examples', 'tags') 24 | shutil.copy2(file, file_path) 25 | 26 | def tags(): 27 | return TAGS_DIR.rglob("*.yml") 28 | 29 | def write_filename_list(): 30 | filepaths = map(lambda path: path.relative_to(FILE_DIR).as_posix(), list(tags())) 31 | 32 | with open(TEMP_DIR.joinpath(FILENAME_LIST), 'w', encoding="utf-8") as f: 33 | f.write('\n'.join(sorted(filepaths))) 34 | 35 | if len(list(TAGS_DIR.rglob("*.yml"))) == 0: 36 | copy_examples() 37 | 38 | write_filename_list() 39 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .easy_prompt_selector_container { 2 | display: flex; 3 | flex-direction: row; 4 | gap: 0.5em; 5 | margin-top: 0.5em; 6 | } 7 | 8 | .easy_prompt_selector_button { 9 | flex: 1; 10 | } 11 | -------------------------------------------------------------------------------- /tags/人物.yml: -------------------------------------------------------------------------------- 1 | 対象: 2 | - 1girl 3 | - 1boy 4 | - 1other 5 | - multiple girls 6 | 7 | 年龄: 8 | 十几岁: teen 9 | 少年: early teen 10 | 大人: adult 11 | 老人: elder 12 | 小儿: child 13 | 幼儿园儿: kindergartener 14 | 幼儿: toddler 15 | 萝莉: loli 16 | 正太: shota 17 | 18 | 肤色: 19 | 白: white skin 20 | 色白: pale skin 21 | 褐色: dark skin 22 | 明亮: shiny skin 23 | 有色: colored skin 24 | 25 | 皮肤性质: 26 | 日晒: tan 27 | 晒痕: tanlines 28 | 纹身: tattoo 29 | 油性: oil 30 | 31 | 体形: 32 | 运动员: athlete 33 | 模特: model 34 | 苗条: slender 35 | 诱惑: glamor 36 | 丰满: plump 37 | 胖: fat 38 | 高: tall 39 | 纤弱: petite 40 | 矮: chibi 41 | 怀孕: pregnant 42 | 肌肉: muscular 43 | 细腰: narrow waist 44 | 大屁股: wide hips 45 | 46 | 胸: 47 | 平胸: flat chest 48 | 贫乳: small breasts 49 | 普通: medium breasts 50 | 巨乳: large breasts 51 | 爆乳: huge breasts 52 | 垂乳: hanging breasts 53 | 54 | 身体部位: 55 | 腋: armpits 56 | 锁骨: collarbone 57 | 肚脐: navel 58 | 屁股: ass 59 | 大腿: thighs 60 | 61 | 翅膀: 62 | 翅膀: wings 63 | 蝙蝠翅膀: bat wings 64 | 蝴蝶翅膀: butterfly wings 65 | 恶魔翅膀: demon wings 66 | 龙翅膀: dragon wings 67 | -------------------------------------------------------------------------------- /tags/人物_五官.yml: -------------------------------------------------------------------------------- 1 | 眼睛: 2 | 色: 3 | 黒: black eyes 4 | 白: white eyes 5 | 红: red eyes 6 | 青: blue eyes 7 | 绿: green eyes 8 | 紫: purple eyes 9 | 银色: silver eyes 10 | 金色: golden eyes 11 | 灰色: gray eyes 12 | 水色: aqua eyes 13 | 茶色: brown eyes 14 | 粉色: pink eyes 15 | 橙色: orange eyes 16 | 异色: heterochromia 17 | 状态: 18 | 半闭眼: half-closed eyes 19 | 闭眼: closed eyes 20 | 21 | 耳朵: 22 | 精灵耳: elf ears 23 | 动物耳: animal ears 24 | 猫耳: cat ears 25 | 狐狸耳: fox ears 26 | 27 | 口: 28 | 唇: lip 29 | 张嘴: open mouth 30 | 闭嘴: closed mouth 31 | 牙齿: teeth 32 | 龅牙: buck teeth 33 | 上牙: upper teeth 34 | 圆牙: round teeth 35 | 咬牙切齿: clenched teeth 36 | 牙: fang 37 | 舔嘴唇: licking lips 38 | 吐舌头: tongue out 39 | 长舌头: long tongue 40 | 手背捂嘴: tehepero 41 | 口水: saliva 42 | -------------------------------------------------------------------------------- /tags/人物_头发.yml: -------------------------------------------------------------------------------- 1 | 发色: 2 | 単色: 3 | 黑发: black hair 4 | 金发: blonde hair 5 | 茶发: brown hair 6 | 赤发: red hair 7 | 粉发: pink hair 8 | 蓝发: blue hair 9 | 水色发: aqua hair 10 | 緑发: green hair 11 | 紫发: purple hair 12 | 橙发: orange hair 13 | 银发: silver hair 14 | 灰发: gray hair 15 | 白发: white hair 16 | 多色: 17 | 多色: multicolored hair 18 | 条纹色: streaked hair 19 | 渐变色: gradient hair 20 | 内侧彩色: colored inner hair 21 | 分叉色: split-color hair 22 | 23 | 发型: 24 | 长度: 25 | 极短发: very short hair 26 | 短发: short hair 27 | 中等长度: medium hair 28 | 长发: long hair 29 | 超长发: very long hair 30 | 超超长发: absurdly long hair 31 | 种类: 32 | 乱发: messy hair 33 | 直发: straight hair 34 | 波浪发: wavy hair 35 | 翻卷发: flipped hair 36 | 非対称: asymmetrical hair 37 | 马尾: 38 | 马尾: ponytail 39 | 高马尾: high ponytail 40 | 低马尾: low ponytail 41 | 前马尾: front ponytail 42 | 侧马尾: side ponytail 43 | 分叉马尾: split ponytail 44 | 折叠马尾: folded ponytail 45 | 短马尾: short ponytail 46 | 双马尾: 47 | 双马尾: twintails 48 | 低双马尾: low twintails 49 | 短双马尾: short twintails 50 | 三马尾: tri tails 51 | 四马尾: quad tails 52 | 辫子: braid 53 | 半向上: half updo 54 | 一边向上: one side up 55 | 两边向上: two side up 56 | 多股头发: multi-tied hair 57 | 头顶结: topknot 58 | 卷发: curly hair 59 | 钻头毛: drill hair 60 | 双钻头毛: twin drills 61 | 垂长卷: ringlets 62 | 弓型发: bow-shaped hair 63 | 发髻: hair bun 64 | 发圈: hair rings 65 | 长发绺: dreadlocks 66 | 67 | 前发: 68 | 钝刘海: blunt bangs 69 | 非対称刘海: asymmetrical bangs 70 | 眼睛上方刘海: hair over eyes 71 | 一直眼睛上方刘海: hair over one eye 72 | 分刘海: parted bangs 73 | 齐刘海: swept bangs 74 | 眼睛间头发: hair between eyes 75 | 发量: hair intakes 76 | 触角: sidelocks 77 | 78 | 其他: 79 | 横发: hair flaps 80 | 傻毛: ahoge 81 | 天线毛: antenna hair 82 | -------------------------------------------------------------------------------- /tags/人物_表情.yml: -------------------------------------------------------------------------------- 1 | 表情: 2 | 笑: smile 3 | 惨笑: sad smile 4 | 邪恶笑: evil smile 5 | 天使笑: angelic smile 6 | 强笑: forced smile 7 | 诱人笑: seductive smile 8 | 咧嘴笑: grin 9 | 邪恶咧嘴笑: evil grin 10 | 傻笑: smirk 11 | 怒: angry 12 | 悲伤: sad 13 | 哭: crying 14 | 泪: tears 15 | 恐怖: scared 16 | 不好的: serious 17 | 恼怒: annoyed 18 | 黑暗人格: dark persona 19 | 多亚脸: doyagao 20 | 脸红: blush 21 | 脸通红: full-face blush 22 | 无聊: bored 23 | 罪恶感: guilt 24 | 无感情: expressionless 25 | 决心: determined 26 | 接吻: incoming kiss 27 | 失望: disappointed 28 | 轻蔑: disdain 29 | 嫉妒: envy 30 | 厌恶: disgust 31 | 困惑: confused 32 | 烦恼挑眉: troubled eyebrows 33 | V型眉: v-shaped eyebrows 34 | 羞耻: embarrassed 35 | 顽皮: naughty 36 | 困乏: sleepy 37 | 38 | -------------------------------------------------------------------------------- /tags/服装.yml: -------------------------------------------------------------------------------- 1 | 上衣: 2 | 衬衣: 3 | 衬衫:shirt 4 | 白衬衫:white_shirt 5 | 领衬衫:collared_shirt 6 | 黑色衬衫:black_shirt 7 | 开衬衫:open_shirt 8 | 礼服衬衫:dress_shirt 9 | 无袖上衣:sleeveless_shirt 10 | 蓝衬衫:blue_shirt 11 | T恤:t-shirt 12 | 灰色衬衫:grey_shirt 13 | 粉红色衬衫:pink_shirt 14 | 条纹衬衫:striped_shirt 15 | 露肩衬衫:off-shoulder_shirt 16 | 衬衫塞进去:shirt_tucked_in 17 | 裸衬衫:naked_shirt 18 | 水手衬衫:sailor_shirt 19 | 湿衬衫:wet_shirt 20 | 褶皱衬衫:frilled_shirt 21 | 汗衫:undershirt 22 | 拉紧衬衫:taut_shirt 23 | 拉衬衫:shirt_pull 24 | 格子衬衫:plaid_shirt 25 | 解开的衬衫:unbuttoned_shirt 26 | 衬衫脱下:shirt_removed 27 | 透明衬衫:see-through_shirt 28 | 无肩带衬衫:strapless_shirt 29 | Polo衫:polo_shirt 30 | 运动衫:sweatshirt 31 | 水衬衫:aqua_shirt 32 | 紧身衬衫:tight_shirt 33 | 夏威夷衬衫:hawaiian_shirt 34 | 松散的衬衫:loose_shirt 35 | 拿着衬衫:holding_shirt 36 | 腰间衬衫:shirt_around_waist 37 | 衬衫悬垂:shirt_overhang 38 | 背心衬衫:vest_over_shirt 39 | 睡衣:nightshirt 40 | 卸下胸罩衬衫:removing_bra_under_shirt 41 | 夹克: 42 | 夹克:jacket 43 | 开夹克:open_jacket 44 | 白夹克:white_jacket 45 | 连帽外套:hooded_jacket 46 | 田径外套:track_jacket 47 | 肩膀上的夹克:jacket_on_shoulders 48 | 毛皮夹克:fur-trimmed_jacket 49 | 军事外套:military_jacket 50 | 无袖外套:sleeveless_jacket 51 | 皮夹克:leather_jacket 52 | 领夹克:collared_jacket 53 | 西装外套:suit_jacket 54 | 轰炸机外套:bomber_jacket 55 | 海峡夹克:straitjacket 56 | 裸夹克:naked_jacket 57 | 连帽田径夹克:hooded_track_jacket 58 | 牛仔外套:denim_jacket 59 | 拿着夹克:holding_jacket 60 | 没有外套:no_jacket 61 | 夹克女孩(Dipp):jacket_girl_(dipp) 62 | 褶皱外套:frilled_jacket 63 | 夹克在肩膀上:jacket_over_shoulder 64 | 长外套:long_jacket 65 | 皮夹克:fur_jacket 66 | 羽绒服:down_jacket 67 | 毛衣外套:sweater_jacket 68 | 消防员夹克:firefighter_jacket 69 | 防弹背心:flak_jacket 70 | 衬衫外套:padded_jacket 71 | 全金属外壳:full_metal_jacket 72 | 圆点夹克:polka_dot_jacket 73 | 74 | 75 | 裤子: 76 | 裤子: 77 | 78 | 裙子: 79 | 80 | 81 | 鞋子: 82 | 83 | 84 | 配饰: -------------------------------------------------------------------------------- /tags/画质.yml: -------------------------------------------------------------------------------- 1 | 画质: 2 | 提高质量: HDR,UHD,8K 3 | 最佳质量: best quality 4 | 杰作: masterpiece 5 | 更多细节: Highly detailed 6 | 演播室灯光: Studio lighting 7 | 超精细绘画: ultra-fine painting 8 | 聚焦清晰: sharp focus 9 | 物理渲染: physically-based rendering 10 | 极详细刻画: extreme detail description 11 | 改善细节: Professional 12 | 添加鲜艳色彩: Vivid Colors 13 | 虚化模糊景: Bokeh 14 | 相机设置: (EOS R8,50mm,F1.2,8K,RAW photo:1.2) 15 | 老照片: High resolution scan 16 | 素描: Sketch 17 | 绘画: Painting 18 | 19 | 20 | -------------------------------------------------------------------------------- /tags/视线.yml: -------------------------------------------------------------------------------- 1 | 视线: 2 | 面对画面或观众: looking at viewer 3 | 两个角色对视: looking at another 4 | 看着别的方: looking away 5 | 回头看: looking back 6 | 向上看: looking up 7 | 8 | 9 | -------------------------------------------------------------------------------- /tags/视角.yml: -------------------------------------------------------------------------------- 1 | 视角: 2 | 动态角度: dynamic angle 3 | 从左侧视角: from the left 4 | 从右侧视角: from the right 5 | 从上方: from above 6 | 从下面: from below 7 | 从下往上看: looking up 8 | 从上往下看: looking down 9 | 从正上方往下看: top down 10 | 从侧面往上看: side view up 11 | 从侧面往下看: side view down 12 | 从人物的角度往上看: subject look up 13 | 从人物的角度往下看: subject look down 14 | 在地面往上看: ground view up 15 | 在地面往下看: ground view down 16 | 全景: panoramic view 17 | 广角宽景: wide shot 18 | 广角: wide-angle view 19 | 空中俯瞰视图: aerial view 20 | 在高处往下看: bird view 21 | 鸟瞰视角: bird’s-eye view 22 | 蚯蚓视角: worm’s eye view 23 | 带有角度的视角: angled 24 | 低角度视角: low-angle view 25 | 俯视视角: top-down 26 | 放大镜效果: zoomed in 27 | 缩小镜效果: zoomed out 28 | 俯视: top-down view 29 | 高角度视角: high-angle view 30 | 平视: eye level view/level gaze/straight gaze 31 | 特写: close-up view 32 | 极端特写: extreme close-up view 33 | 34 | 35 | -------------------------------------------------------------------------------- /tags_examples/人.yml: -------------------------------------------------------------------------------- 1 | 対象: 2 | - 1girl 3 | - 1boy 4 | - 1other 5 | - multiple girls 6 | 7 | 年齢: 8 | ティーン: teen 9 | ローティーン: early teen 10 | 大人: adult 11 | 老人: elder 12 | 子供: child 13 | 幼稚園児: kindergartener 14 | 幼児: toddler 15 | ロリ: loli 16 | ショタ: shota 17 | 18 | 肌の色: 19 | 白: white skin 20 | 色白: pale skin 21 | 褐色: dark skin 22 | 明るい: shiny skin 23 | 有色: colored skin 24 | 25 | 肌の装飾: 26 | 日焼け: tan 27 | 日焼け跡: tanlines 28 | 入れ墨: tattoo 29 | 油: oil 30 | 31 | 体形: 32 | アスリート: athlete 33 | モデル: model 34 | スレンダー: slender 35 | グラマー: glamor 36 | ムチムチ: plump 37 | 太い: fat 38 | 大柄: tall 39 | 小柄: petite 40 | チビ: chibi 41 | 妊娠: pregnant 42 | 筋肉質: muscular 43 | 細ウェスト: narrow waist 44 | 大きな尻: wide hips 45 | 46 | 胸: 47 | まな板: flat chest 48 | 貧乳: small breasts 49 | 普通: medium breasts 50 | 巨乳: large breasts 51 | 爆乳: huge breasts 52 | 垂れ乳: hanging breasts 53 | 54 | 体のパーツ: 55 | 腋: armpits 56 | 鎖骨: collarbone 57 | へそ: navel 58 | 尻: ass 59 | 太もも: thighs 60 | 61 | 翼: 62 | 翼: wings 63 | コウモリの翼: bat wings 64 | 蝶の翼: butterfly wings 65 | 悪魔の翼: demon wings 66 | ドラゴンの翼: dragon wings 67 | -------------------------------------------------------------------------------- /tags_examples/人_顔.yml: -------------------------------------------------------------------------------- 1 | 目: 2 | 色: 3 | 黒: black eyes 4 | 白: white eyes 5 | 赤: red eyes 6 | 青: blue eyes 7 | 緑: green eyes 8 | 紫: purple eyes 9 | 銀色: silver eyes 10 | 金色: golden eyes 11 | 灰色: gray eyes 12 | 水色: aqua eyes 13 | 茶色: brown eyes 14 | ピンク: pink eyes 15 | オレンジ: orange eyes 16 | オッドアイ: heterochromia 17 | 状態: 18 | 半目: half-closed eyes 19 | 閉じた目: closed eyes 20 | 21 | 耳: 22 | エルフ耳: elf ears 23 | ケモミミ: animal ears 24 | ネコミミ: cat ears 25 | キツネ耳: fox ears 26 | 27 | 表情: 28 | 笑い: smile 29 | 悲しい笑い: sad smile 30 | 邪悪な笑い: evil smile 31 | 天使の笑い: angelic smile 32 | 笑い(強制): forced smile 33 | 蠱惑的な笑み: seductive smile 34 | 歯を見せる笑い: grin 35 | 歯を見せる笑い(邪悪): evil grin 36 | ニヤニヤ: smirk 37 | 怒り: angry 38 | 悲しみ: sad 39 | 泣く: crying 40 | 涙: tears 41 | 恐怖: scared 42 | 真剣: serious 43 | イライラ: annoyed 44 | 闇堕ち: dark persona 45 | ドヤ顔: doyagao 46 | 頬染め: blush 47 | 頬染め(強): full-face blush 48 | 退屈: bored 49 | 罪悪感: guilt 50 | 無感情: expressionless 51 | 決意: determined 52 | キス顔: incoming kiss 53 | 失望: disappointed 54 | 軽蔑: disdain 55 | 嫉妬: envy 56 | 嫌悪: disgust 57 | 困惑: confused 58 | 困り眉: troubled eyebrows 59 | 怒り眉: v-shaped eyebrows 60 | 羞恥: embarrassed 61 | いたずら顔: naughty 62 | 眠気: sleepy 63 | 64 | 口: 65 | 唇: lip 66 | 開いた口: open mouth 67 | 閉じた口: closed mouth 68 | 歯: teeth 69 | 出っ歯: buck teeth 70 | 上の歯: upper teeth 71 | 丸い歯: round teeth 72 | ギザギザ歯: clenched teeth 73 | 牙: fang 74 | 舌舐めずり: licking lips 75 | 舌だし: tongue out 76 | 長舌: long tongue 77 | てへぺろ: tehepero 78 | よだれ: saliva 79 | -------------------------------------------------------------------------------- /tags_examples/人_髪.yml: -------------------------------------------------------------------------------- 1 | 髪色: 2 | 単色: 3 | 黒髪: black hair 4 | 金髪: blonde hair 5 | 茶髪: brown hair 6 | 赤髪: red hair 7 | ピンク髪: pink hair 8 | 青髪: blue hair 9 | 水色髪: aqua hair 10 | 緑髪: green hair 11 | 紫髪: purple hair 12 | オレンジ髪: orange hair 13 | 銀髪: silver hair 14 | 灰髪: gray hair 15 | 白髪: white hair 16 | 複数色: 17 | マルチカラー: multicolored hair 18 | メッシュ: streaked hair 19 | グラデーション: gradient hair 20 | インナーカラー: colored inner hair 21 | スプリットカラー: split-color hair 22 | 23 | 髪型: 24 | 長さ: 25 | ベリーショート: very short hair 26 | ショートヘア: short hair 27 | ミディアムヘア: medium hair 28 | ロングヘアー: long hair 29 | 超ロングヘアー: very long hair 30 | 超超ロングヘアー: absurdly long hair 31 | 種類: 32 | くせ毛: messy hair 33 | 直毛: straight hair 34 | ウェーブヘア: wavy hair 35 | 外ハネ: flipped hair 36 | 非対称: asymmetrical hair 37 | ポニーテール: 38 | ポニーテール: ponytail 39 | ハイポニーテール: high ponytail 40 | ローポニーテール: low ponytail 41 | フロントポニーテール: front ponytail 42 | サイドポニーテール: side ponytail 43 | スプリットポニーテール: split ponytail 44 | 畳みポニーテール: folded ponytail 45 | ショートポニーテール: short ponytail 46 | ツインテール: 47 | ツインテール: twintails 48 | ローツインテール: low twintails 49 | ショートツインテール: short twintails 50 | トリプルテール: tri tails 51 | クアッドテール: quad tails 52 | 三つ編み: braid 53 | ハーフアップ: half updo 54 | ワンサイドアップ: one side up 55 | ツーサイドアップ: two side up 56 | マルチタイヘアー: multi-tied hair 57 | 頭頂部結び: topknot 58 | 巻き毛: curly hair 59 | 縦ロール: drill hair 60 | ツイン縦ロール: twin drills 61 | リングレット: ringlets 62 | 弓型髪: bow-shaped hair 63 | お団子頭: hair bun 64 | 輪っか髪: hair rings 65 | ドレッドヘア: dreadlocks 66 | 67 | 前髪: 68 | パッツン: blunt bangs 69 | 非対称: asymmetrical bangs 70 | 両目隠れ: hair over eyes 71 | 片目隠れ: hair over one eye 72 | センター分け: parted bangs 73 | センター分け(ゆるめ): swept bangs 74 | 目の間: hair between eyes 75 | インテーク: hair intakes 76 | 触角: sidelocks 77 | 78 | 他: 79 | 横髪: hair flaps 80 | アホ毛: ahoge 81 | アンテナ: antenna hair 82 | --------------------------------------------------------------------------------