🚀 chore: update stuff
parent
6a196928e4
commit
9616d906ea
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
displayTypes: ['feat', 'fix', 'styles', 'pref'],
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
displayTypes: ['feat', 'fix', 'styles', 'pref'],
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module.exports = {
|
||||
extends: require.resolve('@umijs/lint/dist/config/eslint'),
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'no-param-reassign': 1,
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: 'npm' # See documentation for possible values
|
||||
directory: '/' # Location of package manifests
|
||||
open-pull-requests-limit: 20
|
||||
schedule:
|
||||
interval: 'daily'
|
||||
time: '19:00'
|
||||
timezone: 'Asia/Shanghai'
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
name: Dependabot Auto Merge
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, edited]
|
||||
|
||||
jobs:
|
||||
merge:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'dependencies')
|
||||
name: Dependabot Auto Merge
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Merge
|
||||
uses: ahmadnassri/action-dependabot-auto-merge@v2
|
||||
with:
|
||||
command: merge
|
||||
target: minor
|
||||
github-token: ${{ secrets.GH_TOKEN }}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
name: Build and Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Test
|
||||
run: pnpm run test
|
||||
build:
|
||||
needs: test
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Release
|
||||
id: release
|
||||
run: pnpm run release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
name: Test CI
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
|
||||
- name: Setup Node.js environment
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install deps
|
||||
run: pnpm install
|
||||
|
||||
- name: lint
|
||||
run: pnpm run test
|
||||
|
|
@ -1,3 +1,26 @@
|
|||
**/*.svg
|
||||
**/*.ejs
|
||||
**/*.html
|
||||
.umi
|
||||
.umi-production
|
||||
/dist
|
||||
.dockerignore
|
||||
.DS_Store
|
||||
.eslintignore
|
||||
*.png
|
||||
*.jpg
|
||||
*.webp
|
||||
*.toml
|
||||
*.py
|
||||
docker
|
||||
.editorconfig
|
||||
Dockerfile*
|
||||
.gitignore
|
||||
.prettierignore
|
||||
LICENSE
|
||||
.eslintcache
|
||||
*.lock
|
||||
yarn-error.log
|
||||
.idea
|
||||
.husky
|
||||
.npmrc
|
||||
.env
|
||||
.env.local
|
||||
|
|
|
|||
10
.prettierrc
10
.prettierrc
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"trailingComma": "all",
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"arrowParens": "always",
|
||||
"singleQuote": true
|
||||
}
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 120
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 120
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
extends: ['semantic-release-config-gitmoji'],
|
||||
branches: ['master'],
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
module.exports = require('@umijs/lint/dist/config/stylelint')
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 CanisMinor
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
74
README.md
74
README.md
|
|
@ -1,6 +1,72 @@
|
|||
# Kitchen Theme for stable-diffusion-web-ui
|
||||
<p align="center">
|
||||
<img width="160" src="https://gw.alipayobjects.com/mdn/rms_7d1485/afts/img/A*XDYxSJXBjjwAAAAAAAAAAAAAARQnAQ">
|
||||
</p>
|
||||
<h1 align="center">Kitchen Stable Diffusion WebUI</h1>
|
||||
|
||||
> ⚠️⚠️⚠️ Warning: minimum requirements gradio-3.23.0 & sd-webui [4c1ad74](https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/4c1ad743e3baf1246db0711aa0107debf036a12b)
|
||||
<div align="center">
|
||||
Kitchen Theme for <a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui" target="_blank">AUTOMATIC1111/stable-diffusion-web-ui</a>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<!-- SHIELD GROUP -->
|
||||
|
||||
[![release][release-shield]][release-url]
|
||||
[![releaseDate][release-date-shield]][release-date-url]
|
||||
[![ciTest][ci-test-shield]][ci-test-url]
|
||||
[![ciRelease][ci-release-shield]][ci-release-url]
|
||||
[![contributors][contributors-shield]][contributors-url]
|
||||
[![forks][forks-shield]][forks-url]
|
||||
[![stargazers][stargazers-shield]][stargazers-url]
|
||||
[![issues][issues-shield]][issues-url]
|
||||
|
||||
<!-- SHIELD LINK GROUP -->
|
||||
|
||||
<!-- release -->
|
||||
|
||||
[release-shield]: https://img.shields.io/github/v/release/canisminor1990/sd-web-ui-kitchen-theme?style=flat&sort=semver&logo=github
|
||||
[release-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/releases
|
||||
|
||||
<!-- releaseDate -->
|
||||
|
||||
[release-date-shield]: https://img.shields.io/github/release-date/canisminor1990/sd-web-ui-kitchen-theme?style=flat
|
||||
[release-date-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/releases
|
||||
|
||||
<!-- ciTest -->
|
||||
|
||||
[ci-test-shield]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/workflows/Test%20CI/badge.svg
|
||||
[ci-test-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/actions/workflows/test.yml
|
||||
|
||||
<!-- ciRelease -->
|
||||
|
||||
[ci-release-shield]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/workflows/Build%20and%20Release/badge.svg
|
||||
[ci-release-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/actions/workflows/release.yml
|
||||
|
||||
<!-- contributors -->
|
||||
|
||||
[contributors-shield]: https://img.shields.io/github/contributors/canisminor1990/sd-web-ui-kitchen-theme.svg?style=flat
|
||||
[contributors-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/graphs/contributors
|
||||
|
||||
<!-- forks -->
|
||||
|
||||
[forks-shield]: https://img.shields.io/github/forks/canisminor1990/sd-web-ui-kitchen-theme.svg?style=flat
|
||||
[forks-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/network/members
|
||||
|
||||
<!-- stargazers -->
|
||||
|
||||
[stargazers-shield]: https://img.shields.io/github/stars/canisminor1990/sd-web-ui-kitchen-theme.svg?style=flat
|
||||
[stargazers-url]: https://github.com/canisminor1990/sd-web-ui-kitchen-theme/stargazers
|
||||
|
||||
<!-- issues -->
|
||||
|
||||
[issues-shield]: https://img.shields.io/github/issues/canisminor1990/sd-web-ui-kitchen-theme.svg?style=flat
|
||||
[issues-url]: https://img.shields.io/github/issues/canisminor1990/sd-web-ui-kitchen-theme.svg?style=flat
|
||||
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
> ⚠️⚠️⚠️ Warning: minimum requirements gradio-3.23.0 & sd-webui [4c1ad74](https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/4c1ad743e3baf1246db0711aa0107debf036a12b)
|
||||
|
||||
Launch your WebUI with argument --theme=dark. For example, on Windows your webui-user.bat should include:
|
||||
|
||||
|
|
@ -8,11 +74,11 @@ Launch your WebUI with argument --theme=dark. For example, on Windows your webui
|
|||
set COMMANDLINE_ARGS= --theme=dark
|
||||
```
|
||||
|
||||
## Screenshots
|
||||
## 👀 Screenshots
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
## 📦 Installation
|
||||
|
||||
As an extension (recommended)
|
||||
Either clone the repo into your extensions folder:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: ['gitmoji'],
|
||||
}
|
||||
25
gulpfile.js
25
gulpfile.js
|
|
@ -1,10 +1,19 @@
|
|||
const gulp = require('gulp');
|
||||
const less = require('gulp-less');
|
||||
const gulp = require('gulp')
|
||||
const less = require('gulp-less')
|
||||
const ts = require('gulp-typescript')
|
||||
|
||||
gulp.task('less', function () {
|
||||
return gulp.src('src/theme/*.less').pipe(less()).pipe(gulp.dest('./'));
|
||||
});
|
||||
const tsProject = ts.createProject('tsconfig.json')
|
||||
gulp.task('compile', () => {
|
||||
return gulp.src('src/script/**/*.ts').pipe(tsProject()).pipe(gulp.dest('javascript'))
|
||||
})
|
||||
|
||||
gulp.task('watch', function () {
|
||||
gulp.watch('src/theme/**/*', gulp.parallel('less'));
|
||||
});
|
||||
gulp.task('less', () => {
|
||||
return gulp.src('src/theme/*.less').pipe(less()).pipe(gulp.dest('./'))
|
||||
})
|
||||
|
||||
gulp.task('build', gulp.parallel('compile', 'less'))
|
||||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch('src/theme/**/*', gulp.parallel('less'))
|
||||
gulp.watch('src/script/**/*', gulp.parallel('compile'))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
'use strict'
|
||||
/**
|
||||
* 处理网站的 favicon 图标
|
||||
*/
|
||||
class FaviconHandler {
|
||||
/**
|
||||
* 设置网站的 favicon 图标
|
||||
*/
|
||||
static setFavicon() {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'icon';
|
||||
link.type = 'image/svg+xml';
|
||||
link.href =
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/51a51720-8a30-4430-b6c9-be5712364f04.svg';
|
||||
document.getElementsByTagName('head')[0].appendChild(link);
|
||||
const link = document.createElement('link')
|
||||
link.rel = 'icon'
|
||||
link.type = 'image/svg+xml'
|
||||
link.href = 'https://gw.alipayobjects.com/zos/bmw-prod/51a51720-8a30-4430-b6c9-be5712364f04.svg'
|
||||
document.getElementsByTagName('head')[0].appendChild(link)
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
FaviconHandler.setFavicon();
|
||||
});
|
||||
FaviconHandler.setFavicon()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,220 +1,249 @@
|
|||
'use strict'
|
||||
/**
|
||||
* 转换器工具类
|
||||
*/
|
||||
class Converter {
|
||||
/**
|
||||
* 将数字四舍五入到小数点后四位
|
||||
* @param value 数字
|
||||
* @returns 四舍五入后的数字
|
||||
*/
|
||||
static round(value) {
|
||||
return Math.round(value * 10000) / 10000;
|
||||
return Math.round(value * 10000) / 10000
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串中的中文冒号和括号转换成英文冒号和括号
|
||||
* @param srt 字符串
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
static convertStr(srt) {
|
||||
return srt.replace(/:/g, ':').replace(/(/g, '(').replace(/)/g, ')');
|
||||
return srt.replace(/:/g, ':').replace(/(/g, '(').replace(/)/g, ')')
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串按照括号分割成数组
|
||||
* @param str 字符串
|
||||
* @returns 分割后的数组
|
||||
*/
|
||||
static convertStr2Array(str) {
|
||||
// 匹配各种括号中的内容,包括括号本身
|
||||
const bracketRegex = /(\(|\)|<|>|\[|\])/g;
|
||||
|
||||
// 将字符串按照各种括号分割成数组
|
||||
const bracketRegex = /(\(|\)|<|>|\[|\])/g
|
||||
/**
|
||||
* 将字符串按照各种括号分割成数组
|
||||
* @param str 字符串
|
||||
* @returns 分割后的数组
|
||||
*/
|
||||
const splitByBracket = (str) => {
|
||||
const arr = [];
|
||||
let start = 0;
|
||||
let depth = 0;
|
||||
let match;
|
||||
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;
|
||||
arr.push(str.substring(start, match.index))
|
||||
start = match.index
|
||||
}
|
||||
if (match[0] === '(' || match[0] === '<' || match[0] === '[') {
|
||||
depth++;
|
||||
depth++
|
||||
} else if (match[0] === ')' || match[0] === '>' || match[0] === ']') {
|
||||
depth--;
|
||||
depth--
|
||||
}
|
||||
if (depth === 0) {
|
||||
arr.push(str.substring(start, match.index + 1));
|
||||
start = match.index + 1;
|
||||
arr.push(str.substring(start, match.index + 1))
|
||||
start = match.index + 1
|
||||
}
|
||||
}
|
||||
if (start < str.length) {
|
||||
arr.push(str.substring(start));
|
||||
arr.push(str.substring(start))
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
// 将字符串按照逗号和各种括号分割成数组
|
||||
return arr
|
||||
}
|
||||
/**
|
||||
* 将字符串按照逗号和各种括号分割成数组
|
||||
* @param str 字符串
|
||||
* @returns 分割后的数组
|
||||
*/
|
||||
const splitByComma = (str) => {
|
||||
const arr = [];
|
||||
let start = 0;
|
||||
let inBracket = false;
|
||||
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;
|
||||
arr.push(str.substring(start, i).trim())
|
||||
start = i + 1
|
||||
} else if (str[i].match(bracketRegex)) {
|
||||
inBracket = !inBracket;
|
||||
inBracket = !inBracket
|
||||
}
|
||||
}
|
||||
arr.push(str.substring(start).trim());
|
||||
return arr;
|
||||
};
|
||||
|
||||
// 清洗字符串并输出数组
|
||||
arr.push(str.substring(start).trim())
|
||||
return arr
|
||||
}
|
||||
/**
|
||||
* 清洗字符串并输出数组
|
||||
* @param str 字符串
|
||||
* @returns 清洗后的数组
|
||||
*/
|
||||
const cleanStr = (str) => {
|
||||
let arr = splitByBracket(str);
|
||||
arr = arr.flatMap((s) => splitByComma(s));
|
||||
return arr.filter((s) => s !== '');
|
||||
};
|
||||
|
||||
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);
|
||||
const pattern = /^[,\s, ]+$/
|
||||
return !pattern.test(item)
|
||||
})
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => {
|
||||
return a.includes('<') && !b.includes('<')
|
||||
? 1
|
||||
: b.includes('<') && !a.includes('<')
|
||||
? -1
|
||||
: 0;
|
||||
});
|
||||
return a.includes('<') && !b.includes('<') ? 1 : b.includes('<') && !a.includes('<') ? -1 : 0
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数组转换成字符串
|
||||
* @param array 数组
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
static convertArray2Str(array) {
|
||||
const newArray = array.map((item) => {
|
||||
if (item.includes('<')) return item;
|
||||
if (item.includes('<')) return item
|
||||
const newItem = item
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace([/\,|\.|\。/g, ','])
|
||||
.replace([/\“|\‘|\”|\"|\\|\//g, ''])
|
||||
.replace(/\,|\.|\。/g, ',')
|
||||
.replace(/\“|\‘|\”|\"|\\|\//g, '')
|
||||
.replace(/\, /g, ',')
|
||||
.replace(/\,\,/g, ',')
|
||||
.replace(/\,/g, ', ');
|
||||
return Converter.convertStr2Array(newItem).join(', ');
|
||||
});
|
||||
return newArray.join(', ');
|
||||
.replace(/\,/g, ', ')
|
||||
return Converter.convertStr2Array(newItem).join(', ')
|
||||
})
|
||||
return newArray.join(', ')
|
||||
}
|
||||
|
||||
/**
|
||||
* 将输入的字符串转换成特定格式的字符串
|
||||
* @param input 输入的字符串
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
static convert(input) {
|
||||
const re_attention = /\{|\[|\}|\]|[^\{\}\[\]]+/gmu;
|
||||
|
||||
let text = Converter.convertStr(input);
|
||||
text = Converter.convertStr2Array(text);
|
||||
text = Converter.convertArray2Str(text);
|
||||
|
||||
let res = [];
|
||||
|
||||
const curly_bracket_multiplier = 1.05;
|
||||
const square_bracket_multiplier = 1 / 1.05;
|
||||
|
||||
const re_attention = /\{|\[|\}|\]|[^\{\}\[\]]+/gmu
|
||||
let text = Converter.convertStr(input)
|
||||
const textArray = Converter.convertStr2Array(text)
|
||||
text = Converter.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 },
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* 将指定范围内的数字乘以指定倍数
|
||||
* @param start_position 起始位置
|
||||
* @param multiplier 倍数
|
||||
*/
|
||||
function multiply_range(start_position, multiplier) {
|
||||
for (let pos = start_position; pos < res.length; pos++) {
|
||||
res[pos][1] = Converter.round(res[pos][1] * multiplier);
|
||||
res[pos][1] = Converter.round(res[pos][1] * multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
for (const match of text.matchAll(re_attention)) {
|
||||
let word = match[0];
|
||||
|
||||
let word = match[0]
|
||||
if (word in brackets) {
|
||||
brackets[word].stack.push(res.length);
|
||||
brackets[word].stack.push(res.length)
|
||||
} else if (word == '}' || word == ']') {
|
||||
const bracket = brackets[word === '}' ? '{' : '['];
|
||||
const bracket = brackets[word === '}' ? '{' : '[']
|
||||
if (bracket.stack.length > 0) {
|
||||
multiply_range(bracket.stack.pop(), bracket.multiplier);
|
||||
multiply_range(bracket.stack.pop(), bracket.multiplier)
|
||||
}
|
||||
} else {
|
||||
res.push([word, 1.0]);
|
||||
res.push([word, 1.0])
|
||||
}
|
||||
}
|
||||
|
||||
for (const bracketType in brackets) {
|
||||
for (const pos of brackets[bracketType].stack) {
|
||||
multiply_range(pos, brackets[bracketType].multiplier);
|
||||
multiply_range(pos, brackets[bracketType].multiplier)
|
||||
}
|
||||
}
|
||||
|
||||
if (res.length == 0) {
|
||||
res = [['', 1.0]];
|
||||
res = [['', 1.0]]
|
||||
}
|
||||
|
||||
let i = 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);
|
||||
res[i][0] += res[i + 1][0]
|
||||
res.splice(i + 1, 1)
|
||||
} else {
|
||||
i += 1;
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
let result = '';
|
||||
let result = ''
|
||||
for (const [word, value] of res) {
|
||||
result += value === 1.0 ? word : `(${word}:${value.toString()})`;
|
||||
result += value === 1.0 ? word : `(${word}:${value.toString()})`
|
||||
}
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发 input 事件
|
||||
* @param target 目标元素
|
||||
*/
|
||||
static dispatchInputEvent(target) {
|
||||
let inputEvent = new Event('input');
|
||||
Object.defineProperty(inputEvent, 'target', { value: target });
|
||||
target.dispatchEvent(inputEvent);
|
||||
let inputEvent = new Event('input')
|
||||
Object.defineProperty(inputEvent, 'target', { value: target })
|
||||
target.dispatchEvent(inputEvent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击转换按钮的事件处理函数
|
||||
* @param type 类型
|
||||
*/
|
||||
static onClickConvert(type) {
|
||||
const default_prompt = '';
|
||||
const default_negative = '';
|
||||
|
||||
const prompt = gradioApp().querySelector(
|
||||
`#${type}_prompt > label > textarea`,
|
||||
);
|
||||
const result = Converter.convert(prompt.value);
|
||||
prompt.value =
|
||||
result.match(/^masterpiece, best quality,/) === null
|
||||
? default_prompt + result
|
||||
: result;
|
||||
Converter.dispatchInputEvent(prompt);
|
||||
const negprompt = gradioApp().querySelector(
|
||||
`#${type}_neg_prompt > label > textarea`,
|
||||
);
|
||||
const negResult = Converter.convert(negprompt.value);
|
||||
const default_prompt = ''
|
||||
const default_negative = ''
|
||||
const prompt = gradioApp().querySelector(`#${type}_prompt > label > textarea`)
|
||||
const result = Converter.convert(prompt.value)
|
||||
prompt.value = result.match(/^masterpiece, best quality,/) === null ? default_prompt + result : result
|
||||
Converter.dispatchInputEvent(prompt)
|
||||
const negprompt = gradioApp().querySelector(`#${type}_neg_prompt > label > textarea`)
|
||||
const negResult = Converter.convert(negprompt.value)
|
||||
negprompt.value =
|
||||
negResult.match(/^lowres,/) === null
|
||||
? negResult.length === 0
|
||||
? default_negative
|
||||
: default_negative + negResult
|
||||
: negResult;
|
||||
Converter.dispatchInputEvent(negprompt);
|
||||
: negResult
|
||||
Converter.dispatchInputEvent(negprompt)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建转换按钮
|
||||
* @param id 按钮 id
|
||||
* @param innerHTML 按钮文本
|
||||
* @param onClick 点击事件处理函数
|
||||
* @returns 新建的按钮元素
|
||||
*/
|
||||
static createButton(id, innerHTML, onClick) {
|
||||
const button = document.createElement('button');
|
||||
button.id = id;
|
||||
button.type = 'button';
|
||||
button.innerHTML = innerHTML;
|
||||
button.title = 'Format prompt~🪄';
|
||||
button.className = 'lg secondary gradio-button tool svelte-1ipelgc';
|
||||
button.addEventListener('click', onClick);
|
||||
return button;
|
||||
const button = document.createElement('button')
|
||||
button.id = id
|
||||
button.type = 'button'
|
||||
button.innerHTML = innerHTML
|
||||
button.title = 'Format prompt~🪄'
|
||||
button.className = 'lg secondary gradio-button tool svelte-1ipelgc'
|
||||
button.addEventListener('click', onClick)
|
||||
return button
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加转换按钮
|
||||
* @param type - 组件类型
|
||||
*/
|
||||
static addPromptButton(type) {
|
||||
const generateBtn = gradioApp().querySelector(`#${type}_generate`);
|
||||
const actionsColumn = gradioApp().querySelector(`#${type}_style_create`);
|
||||
const nai2local = gradioApp().querySelector(`#${type}_formatconvert`);
|
||||
if (!generateBtn || !actionsColumn || nai2local) return;
|
||||
const convertBtn = Converter.createButton(
|
||||
`${type}_formatconvert`,
|
||||
'🪄',
|
||||
() => Converter.onClickConvert(type),
|
||||
);
|
||||
actionsColumn.parentNode.append(convertBtn);
|
||||
const generateBtn = gradioApp().querySelector(`#${type}_generate`)
|
||||
const actionsColumn = gradioApp().querySelector(`#${type}_style_create`)
|
||||
const nai2local = gradioApp().querySelector(`#${type}_formatconvert`)
|
||||
if (!generateBtn || !actionsColumn || nai2local) return
|
||||
const convertBtn = Converter.createButton(`${type}_formatconvert`, '🪄', () => Converter.onClickConvert(type))
|
||||
actionsColumn.parentNode?.append(convertBtn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册UI更新回调函数
|
||||
* 在UI更新时添加提示按钮
|
||||
*/
|
||||
onUiUpdate(() => {
|
||||
Converter.addPromptButton('txt2img');
|
||||
Converter.addPromptButton('img2img');
|
||||
});
|
||||
Converter.addPromptButton('txt2img')
|
||||
Converter.addPromptButton('img2img')
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,68 +1,68 @@
|
|||
'use strict'
|
||||
class BracketChecker {
|
||||
textArea
|
||||
counterElt
|
||||
errorStrings
|
||||
constructor(textArea, counterElt) {
|
||||
this.textArea = textArea;
|
||||
this.counterElt = counterElt;
|
||||
this.textArea = textArea
|
||||
this.counterElt = counterElt
|
||||
this.errorStrings = [
|
||||
{
|
||||
regex: /\(/g,
|
||||
error:
|
||||
'(...) - Different number of opening and closing parentheses detected.\n',
|
||||
regex: '\\(',
|
||||
error: '(...) - Different number of opening and closing parentheses detected.\n',
|
||||
},
|
||||
{
|
||||
regex: /\[/g,
|
||||
error:
|
||||
'[...] - Different number of opening and closing square brackets detected.\n',
|
||||
regex: '\\[',
|
||||
error: '[...] - Different number of opening and closing square brackets detected.\n',
|
||||
},
|
||||
{
|
||||
regex: /\{/g,
|
||||
error:
|
||||
'{...} - Different number of opening and closing curly brackets detected.\n',
|
||||
regex: '\\{',
|
||||
error: '{...} - Different number of opening and closing curly brackets detected.\n',
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
|
||||
check() {
|
||||
var title = '';
|
||||
/**
|
||||
* 检查文本框中的括号是否匹配,并更新计数器元素的标题和样式
|
||||
*/
|
||||
check = () => {
|
||||
let title = ''
|
||||
this.errorStrings.forEach(({ regex, error }) => {
|
||||
var openMatches = (this.textArea.value.match(regex) || []).length;
|
||||
var closeMatches = (
|
||||
this.textArea.value.match(
|
||||
regex.replace(/\(/g, ')').replace(/\[/g, ']').replace(/\{/g, '}'),
|
||||
) || []
|
||||
).length;
|
||||
if (openMatches != closeMatches) {
|
||||
const openMatches = (this.textArea.value.match(new RegExp(regex, 'g')) || []).length
|
||||
const closeMatches = (
|
||||
this.textArea.value.match(new RegExp(regex.replace(/\(/g, ')').replace(/\[/g, ']').replace(/\{/g, '}'), 'g')) ||
|
||||
[]
|
||||
).length
|
||||
if (openMatches !== closeMatches) {
|
||||
if (!this.counterElt.title.includes(error)) {
|
||||
title += error;
|
||||
title += error
|
||||
}
|
||||
} else {
|
||||
title = this.counterElt.title.replace(error, '');
|
||||
title = this.counterElt.title.replace(error, '')
|
||||
}
|
||||
});
|
||||
this.counterElt.title = title;
|
||||
this.counterElt.classList.toggle('error', !!title);
|
||||
})
|
||||
this.counterElt.title = title
|
||||
this.counterElt.classList.toggle('error', !!title)
|
||||
}
|
||||
}
|
||||
|
||||
function setupBracketChecking(id_prompt, id_counter) {
|
||||
var textarea = gradioApp().querySelector(`#${id_prompt} > label > textarea`);
|
||||
var counter = gradioApp().getElementById(id_counter);
|
||||
var bracketChecker = new BracketChecker(textarea, counter);
|
||||
textarea.addEventListener('input', () => bracketChecker.check());
|
||||
/**
|
||||
* 初始化括号匹配检查器
|
||||
* @param id_prompt 包含文本框的元素的 ID
|
||||
* @param id_counter 显示计数器的元素的 ID
|
||||
*/
|
||||
function setupBracketChecking(idPrompt, idCounter) {
|
||||
const textarea = gradioApp().querySelector(`#${idPrompt} > label > textarea`)
|
||||
const counter = gradioApp().getElementById(idCounter)
|
||||
const bracketChecker = new BracketChecker(textarea, counter)
|
||||
textarea.addEventListener('input', bracketChecker.check)
|
||||
}
|
||||
|
||||
const shadowRootLoaded = setInterval(() => {
|
||||
var shadowRoot = document.querySelector('gradio-app').shadowRoot;
|
||||
if (!shadowRoot) return;
|
||||
var shadowTextArea = shadowRoot.querySelector(
|
||||
`#txt2img_prompt > label > textarea`,
|
||||
);
|
||||
if (!shadowTextArea) return;
|
||||
clearInterval(shadowRootLoaded);
|
||||
['txt2img', 'txt2img_neg', 'img2img', 'img2img_neg'].forEach((prompt) => {
|
||||
setupBracketChecking(`${prompt}_prompt`, `${prompt}_token_counter`);
|
||||
setupBracketChecking(
|
||||
`${prompt}_prompt`,
|
||||
`${prompt}_negative_token_counter`,
|
||||
);
|
||||
});
|
||||
}, 1000);
|
||||
const shadowRoot = document.querySelector('gradio-app')?.shadowRoot
|
||||
if (!shadowRoot) return
|
||||
const shadowTextArea = shadowRoot.querySelector(`#txt2img_prompt > label > textarea`)
|
||||
if (!shadowTextArea) return
|
||||
clearInterval(shadowRootLoaded)
|
||||
;['txt2img', 'txt2img_neg', 'img2img', 'img2img_neg'].forEach((prompt) => {
|
||||
setupBracketChecking(`${prompt}_prompt`, `${prompt}_token_counter`)
|
||||
setupBracketChecking(`${prompt}_prompt`, `${prompt}_negative_token_counter`)
|
||||
})
|
||||
}, 1000)
|
||||
|
|
|
|||
44
package.json
44
package.json
|
|
@ -1,25 +1,45 @@
|
|||
{
|
||||
"name": "sd-web-ui-kitchen-theme",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"author": "canisminor1990 <i@canisminor.cc>",
|
||||
"license": "MIT",
|
||||
"author": "canisminor1990 <i@canisminor.cc>",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"dev": "gulp watch",
|
||||
"build": "gulp less",
|
||||
"prettier": "prettier --write **/*.{js,jsx,tsx,ts,less,css,md,json}"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"husky": "4.3.8",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-less": "^5.0.0",
|
||||
"lint-staged": "^13.2.0",
|
||||
"prettier": "^2.8.7"
|
||||
"lint": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\" --fix",
|
||||
"prepare": "husky install",
|
||||
"prettier": "prettier -c --write \"**/**\"",
|
||||
"release": "semantic-release",
|
||||
"setup": "umi setup"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,less,css,md,json}": [
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17",
|
||||
"@umijs/lint": "^4.0.64",
|
||||
"commitlint": "^17",
|
||||
"commitlint-config-gitmoji": "^2",
|
||||
"eslint": "^8",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-import-resolver-typescript": "^2.2.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-less": "^5.0.0",
|
||||
"gulp-typescript": "^6.0.0-alpha.1",
|
||||
"gulp-use-tsconfig": "^1.5.4",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^13.2.0",
|
||||
"prettier": "^2",
|
||||
"prettier-plugin-organize-imports": "^3",
|
||||
"prettier-plugin-packagejson": "^2",
|
||||
"semantic-release": "^19",
|
||||
"semantic-release-config-gitmoji": "^1",
|
||||
"stylelint": "^15.4.0",
|
||||
"typescript": "^5.0.0",
|
||||
"umi": "^4.0.64"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* 处理网站的 favicon 图标
|
||||
*/
|
||||
class FaviconHandler {
|
||||
/**
|
||||
* 设置网站的 favicon 图标
|
||||
*/
|
||||
static setFavicon(): void {
|
||||
const link: HTMLLinkElement = document.createElement('link')
|
||||
link.rel = 'icon'
|
||||
link.type = 'image/svg+xml'
|
||||
link.href = 'https://gw.alipayobjects.com/zos/bmw-prod/51a51720-8a30-4430-b6c9-be5712364f04.svg'
|
||||
document.getElementsByTagName('head')[0].appendChild(link)
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
FaviconHandler.setFavicon()
|
||||
})
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
/**
|
||||
* 转换器工具类
|
||||
*/
|
||||
class Converter {
|
||||
/**
|
||||
* 将数字四舍五入到小数点后四位
|
||||
* @param value 数字
|
||||
* @returns 四舍五入后的数字
|
||||
*/
|
||||
static round(value: number): number {
|
||||
return Math.round(value * 10000) / 10000
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串中的中文冒号和括号转换成英文冒号和括号
|
||||
* @param srt 字符串
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
static convertStr(srt: string): string {
|
||||
return srt.replace(/:/g, ':').replace(/(/g, '(').replace(/)/g, ')')
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串按照括号分割成数组
|
||||
* @param str 字符串
|
||||
* @returns 分割后的数组
|
||||
*/
|
||||
static convertStr2Array(str: string): string[] {
|
||||
// 匹配各种括号中的内容,包括括号本身
|
||||
const bracketRegex = /(\(|\)|<|>|\[|\])/g
|
||||
|
||||
/**
|
||||
* 将字符串按照各种括号分割成数组
|
||||
* @param str 字符串
|
||||
* @returns 分割后的数组
|
||||
*/
|
||||
const splitByBracket = (str: string): string[] => {
|
||||
const arr: string[] = []
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串按照逗号和各种括号分割成数组
|
||||
* @param str 字符串
|
||||
* @returns 分割后的数组
|
||||
*/
|
||||
const splitByComma = (str: string): string[] => {
|
||||
const arr: string[] = []
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* 清洗字符串并输出数组
|
||||
* @param str 字符串
|
||||
* @returns 清洗后的数组
|
||||
*/
|
||||
const cleanStr = (str: string): string[] => {
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数组转换成字符串
|
||||
* @param array 数组
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
static convertArray2Str(array: string[]): string {
|
||||
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 Converter.convertStr2Array(newItem).join(', ')
|
||||
})
|
||||
return newArray.join(', ')
|
||||
}
|
||||
|
||||
/**
|
||||
* 将输入的字符串转换成特定格式的字符串
|
||||
* @param input 输入的字符串
|
||||
* @returns 转换后的字符串
|
||||
*/
|
||||
static convert(input: string): string {
|
||||
const re_attention = /\{|\[|\}|\]|[^\{\}\[\]]+/gmu
|
||||
|
||||
let text = Converter.convertStr(input)
|
||||
const textArray = Converter.convertStr2Array(text)
|
||||
text = Converter.convertArray2Str(textArray)
|
||||
|
||||
let res: [string, number][] = []
|
||||
|
||||
const curly_bracket_multiplier = 1.05
|
||||
const square_bracket_multiplier = 1 / 1.05
|
||||
|
||||
const brackets: Record<string, { stack: number[]; multiplier: number }> = {
|
||||
'{': { stack: [], multiplier: curly_bracket_multiplier },
|
||||
'[': { stack: [], multiplier: square_bracket_multiplier },
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定范围内的数字乘以指定倍数
|
||||
* @param start_position 起始位置
|
||||
* @param multiplier 倍数
|
||||
*/
|
||||
function multiply_range(start_position: number, multiplier: number) {
|
||||
for (let pos = start_position; pos < res.length; pos++) {
|
||||
res[pos][1] = Converter.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])
|
||||
}
|
||||
}
|
||||
|
||||
for (const bracketType in brackets) {
|
||||
for (const pos of brackets[bracketType].stack) {
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发 input 事件
|
||||
* @param target 目标元素
|
||||
*/
|
||||
static dispatchInputEvent(target: EventTarget) {
|
||||
let inputEvent = new Event('input')
|
||||
Object.defineProperty(inputEvent, 'target', { value: target })
|
||||
target.dispatchEvent(inputEvent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击转换按钮的事件处理函数
|
||||
* @param type 类型
|
||||
*/
|
||||
static onClickConvert(type: string) {
|
||||
const default_prompt = ''
|
||||
const default_negative = ''
|
||||
|
||||
const prompt = gradioApp().querySelector(`#${type}_prompt > label > textarea`) as HTMLTextAreaElement
|
||||
const result = Converter.convert(prompt.value)
|
||||
prompt.value = result.match(/^masterpiece, best quality,/) === null ? default_prompt + result : result
|
||||
Converter.dispatchInputEvent(prompt)
|
||||
const negprompt = gradioApp().querySelector(`#${type}_neg_prompt > label > textarea`) as HTMLTextAreaElement
|
||||
const negResult = Converter.convert(negprompt.value)
|
||||
negprompt.value =
|
||||
negResult.match(/^lowres,/) === null
|
||||
? negResult.length === 0
|
||||
? default_negative
|
||||
: default_negative + negResult
|
||||
: negResult
|
||||
Converter.dispatchInputEvent(negprompt)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建转换按钮
|
||||
* @param id 按钮 id
|
||||
* @param innerHTML 按钮文本
|
||||
* @param onClick 点击事件处理函数
|
||||
* @returns 新建的按钮元素
|
||||
*/
|
||||
static createButton(id: string, innerHTML: string, onClick: () => void): HTMLButtonElement {
|
||||
const button = document.createElement('button')
|
||||
button.id = id
|
||||
button.type = 'button'
|
||||
button.innerHTML = innerHTML
|
||||
button.title = 'Format prompt~🪄'
|
||||
button.className = 'lg secondary gradio-button tool svelte-1ipelgc'
|
||||
button.addEventListener('click', onClick)
|
||||
return button
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加转换按钮
|
||||
* @param type - 组件类型
|
||||
*/
|
||||
static addPromptButton(type: string): void {
|
||||
const generateBtn: HTMLElement | null = gradioApp().querySelector(`#${type}_generate`)
|
||||
const actionsColumn: HTMLElement | null = gradioApp().querySelector(`#${type}_style_create`)
|
||||
const nai2local: HTMLElement | null = gradioApp().querySelector(`#${type}_formatconvert`)
|
||||
if (!generateBtn || !actionsColumn || nai2local) return
|
||||
const convertBtn: HTMLElement = Converter.createButton(`${type}_formatconvert`, '🪄', () =>
|
||||
Converter.onClickConvert(type)
|
||||
)
|
||||
actionsColumn.parentNode?.append(convertBtn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册UI更新回调函数
|
||||
* 在UI更新时添加提示按钮
|
||||
*/
|
||||
onUiUpdate(() => {
|
||||
Converter.addPromptButton('txt2img')
|
||||
Converter.addPromptButton('img2img')
|
||||
})
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
interface ErrorString {
|
||||
regex: string
|
||||
error: string
|
||||
}
|
||||
|
||||
class BracketChecker {
|
||||
private textArea: HTMLTextAreaElement
|
||||
private counterElt: HTMLElement
|
||||
private errorStrings: ErrorString[]
|
||||
|
||||
constructor(textArea: HTMLTextAreaElement, counterElt: HTMLElement) {
|
||||
this.textArea = textArea
|
||||
this.counterElt = counterElt
|
||||
this.errorStrings = [
|
||||
{
|
||||
regex: '\\(',
|
||||
error: '(...) - Different number of opening and closing parentheses detected.\n',
|
||||
},
|
||||
{
|
||||
regex: '\\[',
|
||||
error: '[...] - Different number of opening and closing square brackets detected.\n',
|
||||
},
|
||||
{
|
||||
regex: '\\{',
|
||||
error: '{...} - Different number of opening and closing curly brackets detected.\n',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文本框中的括号是否匹配,并更新计数器元素的标题和样式
|
||||
*/
|
||||
public check = (): void => {
|
||||
let title = ''
|
||||
this.errorStrings.forEach(({ regex, error }) => {
|
||||
const openMatches = (this.textArea.value.match(new RegExp(regex, 'g')) || []).length
|
||||
const closeMatches = (
|
||||
this.textArea.value.match(new RegExp(regex.replace(/\(/g, ')').replace(/\[/g, ']').replace(/\{/g, '}'), 'g')) ||
|
||||
[]
|
||||
).length
|
||||
if (openMatches !== closeMatches) {
|
||||
if (!this.counterElt.title.includes(error)) {
|
||||
title += error
|
||||
}
|
||||
} else {
|
||||
title = this.counterElt.title.replace(error, '')
|
||||
}
|
||||
})
|
||||
this.counterElt.title = title
|
||||
this.counterElt.classList.toggle('error', !!title)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化括号匹配检查器
|
||||
* @param id_prompt 包含文本框的元素的 ID
|
||||
* @param id_counter 显示计数器的元素的 ID
|
||||
*/
|
||||
function setupBracketChecking(idPrompt: string, idCounter: string): void {
|
||||
const textarea = gradioApp().querySelector(`#${idPrompt} > label > textarea`) as HTMLTextAreaElement
|
||||
const counter = gradioApp().getElementById(idCounter) as HTMLElement
|
||||
const bracketChecker = new BracketChecker(textarea, counter)
|
||||
textarea.addEventListener('input', bracketChecker.check)
|
||||
}
|
||||
|
||||
const shadowRootLoaded = setInterval(() => {
|
||||
const shadowRoot = document.querySelector('gradio-app')?.shadowRoot
|
||||
if (!shadowRoot) return
|
||||
const shadowTextArea = shadowRoot.querySelector(`#txt2img_prompt > label > textarea`) as HTMLTextAreaElement
|
||||
if (!shadowTextArea) return
|
||||
clearInterval(shadowRootLoaded)
|
||||
;['txt2img', 'txt2img_neg', 'img2img', 'img2img_neg'].forEach((prompt) => {
|
||||
setupBracketChecking(`${prompt}_prompt`, `${prompt}_token_counter`)
|
||||
setupBracketChecking(`${prompt}_prompt`, `${prompt}_negative_token_counter`)
|
||||
})
|
||||
}, 1000)
|
||||
|
|
@ -9,11 +9,7 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0.8),
|
||||
transparent
|
||||
) !important;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), transparent) !important;
|
||||
opacity: 0;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
|
|
|
|||
|
|
@ -63,10 +63,9 @@
|
|||
--paddingXL: calc(8px * var(--paddingBase));
|
||||
|
||||
/* Shadow */
|
||||
--boxShadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadowSecondary: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadowSecondary: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
|
||||
/* Border */
|
||||
--borderRadiusBase: 2;
|
||||
|
|
|
|||
|
|
@ -54,9 +54,8 @@
|
|||
--loader-color: var(--color-accent);
|
||||
|
||||
/* Typography */
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font-mono: 'Hack', 'IBM Plex Mono', 'ui-monospace', 'Consolas', monospace;
|
||||
--prose-header-text-weight: 600;
|
||||
--prose-text-weight: 400;
|
||||
|
|
@ -132,10 +131,8 @@
|
|||
--block-title-text-color: var(--neutral-200);
|
||||
--block-info-text-size: var(--text-sm);
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px);
|
||||
--block-label-text-size: var(--text-sm);
|
||||
--block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px);
|
||||
--block-radius: var(--radius-lg);
|
||||
|
|
@ -168,9 +165,7 @@
|
|||
--button-primary-border-color-hover: var(--button-primary-border-color);
|
||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||
--button-secondary-background-fill: var(--neutral-600);
|
||||
--button-secondary-background-fill-hover: var(
|
||||
--button-secondary-background-fill
|
||||
);
|
||||
--button-secondary-background-fill-hover: var(--button-secondary-background-fill);
|
||||
--button-secondary-border-color: var(--neutral-600);
|
||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
||||
|
|
@ -195,12 +190,8 @@
|
|||
--checkbox-border-color-selected: var(--secondary-600);
|
||||
--checkbox-border-width: var(--input-border-width);
|
||||
--checkbox-label-background-fill: var(--button-secondary-background-fill);
|
||||
--checkbox-label-background-fill-hover: var(
|
||||
--button-secondary-background-fill-hover
|
||||
);
|
||||
--checkbox-label-background-fill-selected: var(
|
||||
--checkbox-label-background-fill
|
||||
);
|
||||
--checkbox-label-background-fill-hover: var(--button-secondary-background-fill-hover);
|
||||
--checkbox-label-background-fill-selected: var(--checkbox-label-background-fill);
|
||||
--checkbox-label-border-color: var(--border-color-primary);
|
||||
--checkbox-label-border-color-hover: var(--checkbox-label-border-color);
|
||||
--checkbox-label-border-width: var(--input-border-width);
|
||||
|
|
|
|||
|
|
@ -54,9 +54,8 @@
|
|||
--loader-color: var(--color-accent);
|
||||
|
||||
/* Typography */
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font-mono: 'Hack', 'IBM Plex Mono', 'ui-monospace', 'Consolas', monospace;
|
||||
--prose-header-text-weight: 600;
|
||||
--prose-text-weight: 400;
|
||||
|
|
@ -130,10 +129,8 @@
|
|||
--block-label-background-fill: var(--background-fill-primary);
|
||||
--block-label-border-color: var(--border-color-primary);
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px);
|
||||
--block-label-text-color: var(--neutral-500);
|
||||
--block-label-text-size: var(--text-sm);
|
||||
--block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px);
|
||||
|
|
@ -170,9 +167,7 @@
|
|||
--button-primary-text-color: var(--primary-600);
|
||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||
--button-secondary-background-fill: var(--neutral-200);
|
||||
--button-secondary-background-fill-hover: var(
|
||||
--button-secondary-background-fill
|
||||
);
|
||||
--button-secondary-background-fill-hover: var(--button-secondary-background-fill);
|
||||
--button-secondary-border-color: var(--neutral-200);
|
||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||
--button-secondary-text-color: var(--neutral-700);
|
||||
|
|
@ -196,12 +191,8 @@
|
|||
--checkbox-border-radius: var(--radius-sm);
|
||||
--checkbox-border-width: var(--input-border-width);
|
||||
--checkbox-label-background-fill: var(--button-secondary-background-fill);
|
||||
--checkbox-label-background-fill-hover: var(
|
||||
--button-secondary-background-fill-hover
|
||||
);
|
||||
--checkbox-label-background-fill-selected: var(
|
||||
--checkbox-label-background-fill
|
||||
);
|
||||
--checkbox-label-background-fill-hover: var(--button-secondary-background-fill-hover);
|
||||
--checkbox-label-background-fill-selected: var(--checkbox-label-background-fill);
|
||||
--checkbox-label-border-color: var(--border-color-primary);
|
||||
--checkbox-label-border-color-hover: var(--checkbox-label-border-color);
|
||||
--checkbox-label-border-width: var(--input-border-width);
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
declare const gradioApp: () => DocumentFragment
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
declare const onUiUpdate: (callback: () => void) => void
|
||||
declare const onUiLoaded: (callback: () => void) => void
|
||||
declare const onUiTabChange: (callback: () => void) => void
|
||||
declare const switch_to_txt2img: () => void
|
||||
declare const switch_to_img2img: () => void
|
||||
interface Window {
|
||||
threedopenpose: {
|
||||
onResize: (width: number, height: number) => void
|
||||
onChangeCameraNear: (value: number) => void
|
||||
onChangeCameraFar: (value: number) => void
|
||||
onChangeCameraFocalLength: (value: number) => void
|
||||
onChangeHeadSize: (value: number) => void
|
||||
onChangeNoseToNeck: (value: number) => void
|
||||
onChangeShoulderWidth: (value: number) => void
|
||||
onChangeShoulderToHip: (value: number) => void
|
||||
onChangeArmLength: (value: number) => void
|
||||
onChangeForearm: (value: number) => void
|
||||
onChangeUpperArm: (value: number) => void
|
||||
onChangeHandSize: (value: number) => void
|
||||
onChangeHips: (value: number) => void
|
||||
onChangeLegLength: (value: number) => void
|
||||
onChangeThigh: (value: number) => void
|
||||
onChangeLowerLeg: (value: number) => void
|
||||
onChangeFootSize: (value: number) => void
|
||||
detectImage: () => void
|
||||
setBackground: () => void
|
||||
saveScene: () => void
|
||||
loadScene: () => void
|
||||
restoreLastSavedScene: () => void
|
||||
undo: () => void
|
||||
redo: () => void
|
||||
randomPose: () => void
|
||||
copyBodyZ: () => void
|
||||
copyBodyX: () => void
|
||||
removeBody: () => void
|
||||
onChangeMoveMode: (value: boolean) => void
|
||||
onChangeOnlyHand: (value: boolean) => void
|
||||
onChangeEnablePreview: (value: boolean) => void
|
||||
makeImages: () => void
|
||||
sendTxt2img: (
|
||||
pose_image: string | null,
|
||||
pose_target: string,
|
||||
depth_image: string | null,
|
||||
depth_target: string,
|
||||
normal_image: string | null,
|
||||
normal_target: string,
|
||||
canny_image: string | null,
|
||||
canny_target: string
|
||||
) => void
|
||||
sendImg2img: (
|
||||
pose_image: string,
|
||||
pose_target: string,
|
||||
depth_image: string,
|
||||
depth_target: string,
|
||||
normal_image: string,
|
||||
normal_target: string,
|
||||
canny_image: string,
|
||||
canny_target: string
|
||||
) => void
|
||||
downloadPoseImage: (image: string | null) => void
|
||||
downloadDepthImage: (image: string | null) => void
|
||||
downloadNormalImage: (image: string | null) => void
|
||||
downloadCannyImage: (image: string | null) => void
|
||||
}
|
||||
}
|
||||
59
style.css
59
style.css
|
|
@ -366,10 +366,9 @@ template {
|
|||
--paddingLG: calc(6px * var(--paddingBase));
|
||||
--paddingXL: calc(8px * var(--paddingBase));
|
||||
/* Shadow */
|
||||
--boxShadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadowSecondary: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
|
||||
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
--boxShadowSecondary: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
||||
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
||||
/* Border */
|
||||
--borderRadiusBase: 2;
|
||||
--borderRadiusXS: calc(1px * var(--borderRadiusBase));
|
||||
|
|
@ -430,9 +429,8 @@ template {
|
|||
--link-text-color-visited: var(--secondary-500);
|
||||
--loader-color: var(--color-accent);
|
||||
/* Typography */
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font-mono: 'Hack', 'IBM Plex Mono', 'ui-monospace', 'Consolas', monospace;
|
||||
--prose-header-text-weight: 600;
|
||||
--prose-text-weight: 400;
|
||||
|
|
@ -501,10 +499,8 @@ template {
|
|||
--block-label-background-fill: var(--background-fill-primary);
|
||||
--block-label-border-color: var(--border-color-primary);
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px);
|
||||
--block-label-text-color: var(--neutral-500);
|
||||
--block-label-text-size: var(--text-sm);
|
||||
--block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px);
|
||||
|
|
@ -539,9 +535,7 @@ template {
|
|||
--button-primary-text-color: var(--primary-600);
|
||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||
--button-secondary-background-fill: var(--neutral-200);
|
||||
--button-secondary-background-fill-hover: var(
|
||||
--button-secondary-background-fill
|
||||
);
|
||||
--button-secondary-background-fill-hover: var(--button-secondary-background-fill);
|
||||
--button-secondary-border-color: var(--neutral-200);
|
||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||
--button-secondary-text-color: var(--neutral-700);
|
||||
|
|
@ -564,12 +558,8 @@ template {
|
|||
--checkbox-border-radius: var(--radius-sm);
|
||||
--checkbox-border-width: var(--input-border-width);
|
||||
--checkbox-label-background-fill: var(--button-secondary-background-fill);
|
||||
--checkbox-label-background-fill-hover: var(
|
||||
--button-secondary-background-fill-hover
|
||||
);
|
||||
--checkbox-label-background-fill-selected: var(
|
||||
--checkbox-label-background-fill
|
||||
);
|
||||
--checkbox-label-background-fill-hover: var(--button-secondary-background-fill-hover);
|
||||
--checkbox-label-background-fill-selected: var(--checkbox-label-background-fill);
|
||||
--checkbox-label-border-color: var(--border-color-primary);
|
||||
--checkbox-label-border-color-hover: var(--checkbox-label-border-color);
|
||||
--checkbox-label-border-width: var(--input-border-width);
|
||||
|
|
@ -651,9 +641,8 @@ template {
|
|||
--color-accent-soft: var(--neutral-700);
|
||||
--loader-color: var(--color-accent);
|
||||
/* Typography */
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
--font-mono: 'Hack', 'IBM Plex Mono', 'ui-monospace', 'Consolas', monospace;
|
||||
--prose-header-text-weight: 600;
|
||||
--prose-text-weight: 400;
|
||||
|
|
@ -724,10 +713,8 @@ template {
|
|||
--block-title-text-color: var(--neutral-200);
|
||||
--block-info-text-size: var(--text-sm);
|
||||
--block-label-padding: var(--spacing-sm) var(--spacing-lg);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0
|
||||
calc(var(--radius-lg) - 1px);
|
||||
--block-label-radius: calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px) 0;
|
||||
--block-label-right-radius: 0 calc(var(--radius-lg) - 1px) 0 calc(var(--radius-lg) - 1px);
|
||||
--block-label-text-size: var(--text-sm);
|
||||
--block-padding: var(--spacing-xl) calc(var(--spacing-xl) + 2px);
|
||||
--block-radius: var(--radius-lg);
|
||||
|
|
@ -758,9 +745,7 @@ template {
|
|||
--button-primary-border-color-hover: var(--button-primary-border-color);
|
||||
--button-primary-text-color-hover: var(--button-primary-text-color);
|
||||
--button-secondary-background-fill: var(--neutral-600);
|
||||
--button-secondary-background-fill-hover: var(
|
||||
--button-secondary-background-fill
|
||||
);
|
||||
--button-secondary-background-fill-hover: var(--button-secondary-background-fill);
|
||||
--button-secondary-border-color: var(--neutral-600);
|
||||
--button-secondary-border-color-hover: var(--button-secondary-border-color);
|
||||
--button-secondary-text-color-hover: var(--button-secondary-text-color);
|
||||
|
|
@ -784,12 +769,8 @@ template {
|
|||
--checkbox-border-color-selected: var(--secondary-600);
|
||||
--checkbox-border-width: var(--input-border-width);
|
||||
--checkbox-label-background-fill: var(--button-secondary-background-fill);
|
||||
--checkbox-label-background-fill-hover: var(
|
||||
--button-secondary-background-fill-hover
|
||||
);
|
||||
--checkbox-label-background-fill-selected: var(
|
||||
--checkbox-label-background-fill
|
||||
);
|
||||
--checkbox-label-background-fill-hover: var(--button-secondary-background-fill-hover);
|
||||
--checkbox-label-background-fill-selected: var(--checkbox-label-background-fill);
|
||||
--checkbox-label-border-color: var(--border-color-primary);
|
||||
--checkbox-label-border-color-hover: var(--checkbox-label-border-color);
|
||||
--checkbox-label-border-width: var(--input-border-width);
|
||||
|
|
@ -1127,11 +1108,7 @@ div.svelte-awbtu4 .gradio-file {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(0, 0, 0, 0.8),
|
||||
transparent
|
||||
) !important;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.8), transparent) !important;
|
||||
opacity: 0;
|
||||
}
|
||||
.extra-network-thumbs .actions .additional > ul:hover {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"extends": "./src/.umi/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
import 'umi/typings'
|
||||
|
|
@ -1,27 +1,27 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
// 从本地文件读取CSS
|
||||
const cssFilePath = path.resolve(__dirname, 'style.css');
|
||||
const css = fs.readFileSync(cssFilePath, 'utf-8');
|
||||
const cssFilePath = path.resolve(__dirname, 'style.css')
|
||||
const css = fs.readFileSync(cssFilePath, 'utf-8')
|
||||
|
||||
// 用于存储变量及其值的对象
|
||||
const cssVariables = {};
|
||||
const cssVariables = {}
|
||||
|
||||
// 正则表达式用于匹配CSS变量及其值
|
||||
const cssVarRegex = /--\w+[^:]*:\s*([^;]*);/g;
|
||||
const cssVarReferenceRegex = /var\((--\w+)\)/g;
|
||||
const cssVarRegex = /--\w+[^:]*:\s*([^;]*);/g
|
||||
const cssVarReferenceRegex = /var\((--\w+)\)/g
|
||||
|
||||
// 解析CSS变量及其值
|
||||
let match;
|
||||
let match
|
||||
while ((match = cssVarRegex.exec(css))) {
|
||||
const variable = match[0].split(':')[0].trim();
|
||||
const value = match[1].trim();
|
||||
cssVariables[variable] = value;
|
||||
const variable = match[0].split(':')[0].trim()
|
||||
const value = match[1].trim()
|
||||
cssVariables[variable] = value
|
||||
}
|
||||
|
||||
// 对变量进行排序,确保被引用的变量在引用它的变量之前
|
||||
const sortedVariables = Object.keys(cssVariables);
|
||||
const sortedVariables = Object.keys(cssVariables)
|
||||
|
||||
// 按类别对变量进行分组
|
||||
const groups = {
|
||||
|
|
@ -38,68 +38,63 @@ const groups = {
|
|||
input: [],
|
||||
table: [],
|
||||
other: [],
|
||||
};
|
||||
}
|
||||
|
||||
sortedVariables.forEach((variable) => {
|
||||
const value = cssVariables[variable];
|
||||
const value = cssVariables[variable]
|
||||
const isColor =
|
||||
value.startsWith('#') ||
|
||||
value.includes('rgb') ||
|
||||
value.includes('color') ||
|
||||
variable.includes('color') ||
|
||||
variable.includes('fill') ||
|
||||
variable.includes('neutral');
|
||||
variable.includes('neutral')
|
||||
const isTypography =
|
||||
variable.includes('text') ||
|
||||
variable.includes('font') ||
|
||||
variable.includes('prose') ||
|
||||
variable.includes('link');
|
||||
variable.includes('text') || variable.includes('font') || variable.includes('prose') || variable.includes('link')
|
||||
const isSpacing =
|
||||
variable.includes('spacing') ||
|
||||
variable.includes('padding') ||
|
||||
variable.includes('gap') ||
|
||||
variable.includes('margin');
|
||||
value.includes('padding') || value.includes('margin');
|
||||
const isBorder = variable.includes('radius') || variable.includes('border');
|
||||
const isBoxShadow = variable.includes('shadow');
|
||||
variable.includes('margin')
|
||||
value.includes('padding') || value.includes('margin')
|
||||
const isBorder = variable.includes('radius') || variable.includes('border')
|
||||
const isBoxShadow = variable.includes('shadow')
|
||||
if (variable.includes('--body')) {
|
||||
groups.body.push(variable);
|
||||
groups.body.push(variable)
|
||||
} else if (variable.includes('--block')) {
|
||||
groups.block.push(variable);
|
||||
groups.block.push(variable)
|
||||
} else if (variable.includes('--panel')) {
|
||||
groups.panel.push(variable);
|
||||
groups.panel.push(variable)
|
||||
} else if (variable.includes('--button')) {
|
||||
groups.button.push(variable);
|
||||
groups.button.push(variable)
|
||||
} else if (variable.includes('--checkbox')) {
|
||||
groups.checkbox.push(variable);
|
||||
groups.checkbox.push(variable)
|
||||
} else if (variable.includes('--input')) {
|
||||
groups.input.push(variable);
|
||||
groups.input.push(variable)
|
||||
} else if (variable.includes('--table')) {
|
||||
groups.table.push(variable);
|
||||
groups.table.push(variable)
|
||||
} else if (isBorder) {
|
||||
groups.border.push(variable);
|
||||
groups.border.push(variable)
|
||||
} else if (isBoxShadow) {
|
||||
groups.boxShadow.push(variable);
|
||||
groups.boxShadow.push(variable)
|
||||
} else if (isColor) {
|
||||
groups.colors.push(variable);
|
||||
groups.colors.push(variable)
|
||||
} else if (isTypography) {
|
||||
groups.typography.push(variable);
|
||||
groups.typography.push(variable)
|
||||
} else if (isSpacing) {
|
||||
groups.spacing.push(variable);
|
||||
groups.spacing.push(variable)
|
||||
} else {
|
||||
groups.other.push(variable);
|
||||
groups.other.push(variable)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// 生成排序后的CSS变量
|
||||
const generateGroupCss = (groupName) => {
|
||||
const cache = groups[groupName].map(
|
||||
(variable) => `${variable}: ${cssVariables[variable]};`,
|
||||
);
|
||||
const firstPart = cache.filter((item) => item.includes('var'));
|
||||
const secondPart = cache.filter((item) => !item.includes('var'));
|
||||
return [...secondPart, ...firstPart].join('\n');
|
||||
};
|
||||
const cache = groups[groupName].map((variable) => `${variable}: ${cssVariables[variable]};`)
|
||||
const firstPart = cache.filter((item) => item.includes('var'))
|
||||
const secondPart = cache.filter((item) => !item.includes('var'))
|
||||
return [...secondPart, ...firstPart].join('\n')
|
||||
}
|
||||
|
||||
const sortedCss =
|
||||
'#output {\n' +
|
||||
|
|
@ -129,9 +124,9 @@ const sortedCss =
|
|||
generateGroupCss('table') +
|
||||
`\n\n/* Other */\n` +
|
||||
generateGroupCss('other') +
|
||||
'}';
|
||||
'}'
|
||||
|
||||
console.log(sortedCss);
|
||||
console.log(sortedCss)
|
||||
|
||||
// 将排序后的CSS变量写入文件
|
||||
fs.writeFileSync('sorted-css-variables.css', sortedCss);
|
||||
fs.writeFileSync('sorted-css-variables.css', sortedCss)
|
||||
|
|
|
|||
Loading…
Reference in New Issue