feat: migrated packages to ts
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -138,4 +138,5 @@ _*.json
|
||||
assets/*
|
||||
temp/*
|
||||
.turbo
|
||||
data/*
|
||||
data/*
|
||||
release
|
||||
|
||||
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "Launch Chrome",
|
||||
"request": "launch",
|
||||
@@ -110,6 +111,15 @@
|
||||
"request": "launch",
|
||||
"command": "pnpm run deploy",
|
||||
"cwd": "${workspaceFolder}"
|
||||
},{
|
||||
"type": "bun",
|
||||
"name": "Run Script: build",
|
||||
"request": "launch",
|
||||
"env": {
|
||||
"mode": "build"
|
||||
},
|
||||
"program": "index.ts",
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ import react from 'eslint-plugin-react'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [
|
||||
@@ -27,4 +30,21 @@ export default [
|
||||
],
|
||||
},
|
||||
},
|
||||
...tsConfig,
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev:directory": "vite --clearScreen false",
|
||||
"build": "mode=build node runner.js",
|
||||
"build": "mode=build bun runner.ts",
|
||||
"preview:directory": "vite preview",
|
||||
"lint": "eslint \"src/**/*.js\" \"src/**/*.jsx\" && stylelint \"src/**/*.css\" \"src/**/*.scss\" && prettier --check ."
|
||||
"lint": "eslint && stylelint \"src/**/*.css\" \"src/**/*.scss\" && prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.0.0",
|
||||
@@ -28,6 +28,11 @@
|
||||
"@aklive2d/module": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import path from 'node:path'
|
||||
import { DIST_DIR } from '@aklive2d/showcase'
|
||||
import { build as viteBuild } from 'vite'
|
||||
import { envParser } from '@aklive2d/libs'
|
||||
import { envParser, file } from '@aklive2d/libs'
|
||||
|
||||
const build = async (namesToBuild) => {
|
||||
const build = async (namesToBuild: string[]) => {
|
||||
if (!namesToBuild.length) {
|
||||
// skip as directory can only build
|
||||
// when all operators are built
|
||||
await viteBuild()
|
||||
const releaseDir = path.resolve(DIST_DIR)
|
||||
file.rmdir(releaseDir)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +22,7 @@ async function main() {
|
||||
default: [],
|
||||
},
|
||||
})
|
||||
await build(name)
|
||||
await build(name as string[])
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -192,7 +192,7 @@ export default function Home() {
|
||||
>
|
||||
{officialUpdate.dates
|
||||
.reduce((acc, cur) => {
|
||||
const op = officialUpdate[cur]
|
||||
const op = officialUpdate.info[cur]
|
||||
return [...acc, ...op]
|
||||
}, [])
|
||||
.slice(
|
||||
|
||||
25
apps/directory/tsconfig.json
Normal file
25
apps/directory/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["spine-ts/**/*"]
|
||||
}
|
||||
@@ -8,12 +8,12 @@ import { copyDirectoryData } from '@aklive2d/vite-helpers'
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig(async () => {
|
||||
const dataDir = path.resolve(import.meta.dirname, config.dir_name.data)
|
||||
const publicDir = path.resolve(showcaseDirs.DIST_DIR)
|
||||
await copyDirectoryData({ dataDir, publicDir })
|
||||
const releaseDir = path.resolve(showcaseDirs.DIST_DIR)
|
||||
await copyDirectoryData({ dataDir, publicDir: releaseDir })
|
||||
return {
|
||||
envDir: dataDir,
|
||||
plugins: [react()],
|
||||
publicDir,
|
||||
publicDir: releaseDir,
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve('./src'),
|
||||
@@ -22,7 +22,12 @@ export default defineConfig(async () => {
|
||||
},
|
||||
build: {
|
||||
emptyOutDir: false,
|
||||
outDir: publicDir,
|
||||
outDir: path.resolve(
|
||||
import.meta.dirname,
|
||||
'..',
|
||||
'..',
|
||||
config.dir_name.dist
|
||||
),
|
||||
rollupOptions: {
|
||||
output: {
|
||||
entryFileNames: `${config.directory.assets_dir}/[name]-[hash:8].js`,
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import eslint from '@eslint/js'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
eslintPluginPrettierRecommended,
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'spine-ts'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.{js,jsx}', '**/*.{ts,tsx}'],
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Player } from './src/player.ts'
|
||||
import { Player, PlayerConfig } from './src/player.ts'
|
||||
|
||||
export { Player }
|
||||
export type { PlayerConfig }
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
"scripts": {
|
||||
"lint": "eslint && prettier --check ."
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklive2d/postcss-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
"@aklive2d/stylelint-config": "workspace:*",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"globals": "^16.0.0",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.31.1"
|
||||
"@aklive2d/eslint-config": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig, { ignores: ['src/libs/*'] }]
|
||||
export default tseslint.config(
|
||||
...baseConfig,
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'spine-ts'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.browser,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -12,5 +12,5 @@ export const DIST_DIR = path.resolve(
|
||||
import.meta.dirname,
|
||||
'..',
|
||||
'..',
|
||||
config.dir_name.dist
|
||||
config.app.showcase.release
|
||||
)
|
||||
@@ -3,12 +3,17 @@
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"dev:showcase": "vite --clearScreen false",
|
||||
"build": "mode=build node runner.js",
|
||||
"build": "mode=build bun runner.ts",
|
||||
"preview:showcase": "vite preview",
|
||||
"lint": "eslint \"src/**/*.js\" && stylelint \"**/*.css\" && prettier --check ."
|
||||
"lint": "eslint && prettier --check ."
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^6.1.5",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { envParser, file } from '@aklive2d/libs'
|
||||
import { copyShowcaseData, copyProjectJSON } from '@aklive2d/vite-helpers'
|
||||
import * as dirs from './index.js'
|
||||
|
||||
const build = async (namesToBuild) => {
|
||||
const build = async (namesToBuild: string[]) => {
|
||||
const names = !namesToBuild.length ? Object.keys(operators) : namesToBuild
|
||||
console.log('Generating assets for', names.length, 'operators')
|
||||
for (const name of names) {
|
||||
@@ -32,7 +32,7 @@ async function main() {
|
||||
default: [],
|
||||
},
|
||||
})
|
||||
await build(name)
|
||||
await build(name as string[])
|
||||
}
|
||||
|
||||
main()
|
||||
25
apps/showcase/tsconfig.json
Normal file
25
apps/showcase/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["spine-ts/**/*"]
|
||||
}
|
||||
102
bun.lock
102
bun.lock
@@ -4,12 +4,14 @@
|
||||
"": {
|
||||
"name": "aklive2d",
|
||||
"devDependencies": {
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"eslint": "^9.25.1",
|
||||
"http-server": "^14.1.1",
|
||||
"prettier": "^3.5.3",
|
||||
"stylelint": "^16.19.1",
|
||||
"turbo": "^2.5.2",
|
||||
"typescript": "5.8.2",
|
||||
},
|
||||
},
|
||||
"apps/directory": {
|
||||
@@ -46,18 +48,25 @@
|
||||
"sass": "^1.84.0",
|
||||
"vite": "^6.1.5",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"apps/module": {
|
||||
"name": "@aklive2d/module",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/postcss-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
"@aklive2d/stylelint-config": "workspace:*",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"globals": "^16.0.0",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.31.1",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"apps/showcase": {
|
||||
@@ -76,6 +85,11 @@
|
||||
"@aklive2d/vite-helpers": "workspace:*",
|
||||
"vite": "^6.1.5",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/assets": {
|
||||
"name": "@aklive2d/assets",
|
||||
@@ -89,6 +103,11 @@
|
||||
"@aklive2d/operator": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/background": {
|
||||
"name": "@aklive2d/background",
|
||||
@@ -101,6 +120,11 @@
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
"sharp": "^0.33.5",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/charword-table": {
|
||||
"name": "@aklive2d/charword-table",
|
||||
@@ -113,6 +137,11 @@
|
||||
"@aklive2d/operator": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/config": {
|
||||
"name": "@aklive2d/config",
|
||||
@@ -122,6 +151,11 @@
|
||||
"@aklive2d/libs": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/downloader": {
|
||||
"name": "@aklive2d/downloader",
|
||||
@@ -140,8 +174,10 @@
|
||||
"@eslint/js": "^9.19.0",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"globals": "^15.14.0",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"globals": "^16.0.0",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/libs": {
|
||||
@@ -155,6 +191,15 @@
|
||||
"yauzl-promise": "^4.0.0",
|
||||
"yazl": "^3.3.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/yauzl-promise": "^4.0.1",
|
||||
"@types/yazl": "^2.4.6",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/music": {
|
||||
"name": "@aklive2d/music",
|
||||
@@ -166,6 +211,11 @@
|
||||
"@aklive2d/libs": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/official-info": {
|
||||
"name": "@aklive2d/official-info",
|
||||
@@ -177,6 +227,11 @@
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
"jsdom": "^26.0.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/operator": {
|
||||
"name": "@aklive2d/operator",
|
||||
@@ -189,6 +244,11 @@
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
"yaml": "^2.7.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/postcss-config": {
|
||||
"name": "@aklive2d/postcss-config",
|
||||
@@ -202,6 +262,7 @@
|
||||
"version": "0.0.0",
|
||||
"peerDependencies": {
|
||||
"prettier": ">=3.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
},
|
||||
},
|
||||
"packages/project-json": {
|
||||
@@ -217,6 +278,11 @@
|
||||
"@aklive2d/operator": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/stylelint-config": {
|
||||
"name": "@aklive2d/stylelint-config",
|
||||
@@ -240,6 +306,11 @@
|
||||
"@aklive2d/operator": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
"packages/wrangler": {
|
||||
"name": "@aklive2d/wrangler",
|
||||
@@ -256,6 +327,11 @@
|
||||
"@aklive2d/showcase": "workspace:*",
|
||||
"p-throttle": "^7.0.0",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript": ">=5.8.2",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
"trustedDependencies": [
|
||||
@@ -597,6 +673,8 @@
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="],
|
||||
|
||||
"@types/jsdom": ["@types/jsdom@21.1.7", "", { "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", "parse5": "^7.0.0" } }, "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/node": ["@types/node@22.15.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw=="],
|
||||
@@ -605,6 +683,12 @@
|
||||
|
||||
"@types/react-dom": ["@types/react-dom@19.1.3", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg=="],
|
||||
|
||||
"@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="],
|
||||
|
||||
"@types/yauzl-promise": ["@types/yauzl-promise@4.0.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-qYEC3rJwqiJpdQ9b+bPNeuSY0c3JUM8vIuDy08qfuVN7xHm3ZDsHn2kGphUIB0ruEXrPGNXZ64nMUcu4fDjViQ=="],
|
||||
|
||||
"@types/yazl": ["@types/yazl@2.4.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-/ifFjQtcKaoZOjl5NNCQRR0fAKafB3Foxd7J/WvFPTMea46zekapcR30uzkwIkKAAuq5T6d0dkwz754RFH27hg=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.31.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.31.1", "@typescript-eslint/type-utils": "8.31.1", "@typescript-eslint/utils": "8.31.1", "@typescript-eslint/visitor-keys": "8.31.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.31.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.31.1", "@typescript-eslint/types": "8.31.1", "@typescript-eslint/typescript-estree": "8.31.1", "@typescript-eslint/visitor-keys": "8.31.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q=="],
|
||||
@@ -919,7 +1003,7 @@
|
||||
|
||||
"global-prefix": ["global-prefix@3.0.0", "", { "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", "which": "^1.3.1" } }, "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg=="],
|
||||
|
||||
"globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="],
|
||||
"globals": ["globals@16.0.0", "", {}, "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A=="],
|
||||
|
||||
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
|
||||
|
||||
@@ -1443,7 +1527,7 @@
|
||||
|
||||
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
|
||||
|
||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
"typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="],
|
||||
|
||||
"typescript-eslint": ["typescript-eslint@8.31.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "@typescript-eslint/utils": "8.31.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA=="],
|
||||
|
||||
@@ -1509,7 +1593,7 @@
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"@aklive2d/module/globals": ["globals@16.0.0", "", {}, "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A=="],
|
||||
"@aklive2d/eslint-config/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||
|
||||
"@commitlint/config-validator/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
||||
|
||||
|
||||
75
package.json
75
package.json
@@ -1,37 +1,42 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
"dev:showcase": "turbo run dev:showcase --ui tui",
|
||||
"preview:showcase": "turbo run preview:showcase --ui tui",
|
||||
"dev:directory": "turbo run dev:directory --ui tui",
|
||||
"preview:directory": "turbo run preview:directory --ui tui",
|
||||
"preview": "http-server ./dist",
|
||||
"lint": "turbo run lint",
|
||||
"update": "turbo run update",
|
||||
"init": "turbo run init",
|
||||
"download:game": "turbo run download:game",
|
||||
"build:cleanup": "turbo run build:cleanup"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"eslint": "^9.25.1",
|
||||
"http-server": "^14.1.1",
|
||||
"prettier": "^3.5.3",
|
||||
"stylelint": "^16.19.1",
|
||||
"turbo": "^2.5.2"
|
||||
},
|
||||
"name": "aklive2d",
|
||||
"type": "module",
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"packageManager": "bun@1.2.11",
|
||||
"workspaces": ["packages/*", "apps/*"],
|
||||
"trustedDependencies": [
|
||||
"@parcel/watcher",
|
||||
"@swc/core"
|
||||
]
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
"dev:showcase": "turbo run dev:showcase --ui tui",
|
||||
"preview:showcase": "turbo run preview:showcase --ui tui",
|
||||
"dev:directory": "turbo run dev:directory --ui tui",
|
||||
"preview:directory": "turbo run preview:directory --ui tui",
|
||||
"preview": "http-server ./dist",
|
||||
"lint": "turbo run lint",
|
||||
"update": "turbo run update",
|
||||
"init": "turbo run init",
|
||||
"download:game": "turbo run download:game",
|
||||
"build:cleanup": "turbo run build:cleanup"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"eslint": "^9.25.1",
|
||||
"http-server": "^14.1.1",
|
||||
"prettier": "^3.5.3",
|
||||
"stylelint": "^16.19.1",
|
||||
"turbo": "^2.5.2",
|
||||
"typescript": "5.8.2"
|
||||
},
|
||||
"name": "aklive2d",
|
||||
"type": "module",
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"packageManager": "bun@1.2.11",
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"apps/*"
|
||||
],
|
||||
"trustedDependencies": [
|
||||
"@parcel/watcher",
|
||||
"@swc/core"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import path from 'node:path'
|
||||
import config from '@aklive2d/config'
|
||||
import { yaml } from '@aklive2d/libs'
|
||||
import type { Config } from './types.ts'
|
||||
|
||||
export const DIST_DIR = path.resolve(import.meta.dirname, config.dir_name.dist)
|
||||
export const CONFIG_PATH = path.resolve(
|
||||
import.meta.dirname,
|
||||
config.module.assets.config_yaml
|
||||
)
|
||||
const selfConfig = yaml.read(CONFIG_PATH)
|
||||
const selfConfig: Config = yaml.read(CONFIG_PATH)
|
||||
|
||||
export default selfConfig
|
||||
@@ -1,9 +1,9 @@
|
||||
import path from 'node:path'
|
||||
import { file } from '@aklive2d/libs'
|
||||
import config from '@aklive2d/config'
|
||||
import { DIST_DIR } from '../index.js'
|
||||
import { DIST_DIR } from '../index.ts'
|
||||
|
||||
export default async (packageDir) => {
|
||||
export default async (packageDir: string) => {
|
||||
const copyQueue = [
|
||||
{
|
||||
fn: file.symlink,
|
||||
@@ -1,22 +1,23 @@
|
||||
import path from 'node:path'
|
||||
import { file } from '@aklive2d/libs'
|
||||
import { unzipDownload } from '@aklive2d/downloader'
|
||||
import { unzipDownload, type UnzipDownloadItem } from '@aklive2d/downloader'
|
||||
import { getOperatorId, getOperatorAlternativeId } from '@aklive2d/operator'
|
||||
import { mapping } from '@aklive2d/music'
|
||||
import config from '../index.js'
|
||||
import config from '../index.ts'
|
||||
import type { UpdateList, ItemToDownload, AbInfosItem } from '../types.ts'
|
||||
|
||||
export default async (dataDir) => {
|
||||
const pidSet = new Set()
|
||||
const versionRes = await fetch(
|
||||
export default async (dataDir: string) => {
|
||||
const pidSet: Set<string> = new Set()
|
||||
const versionRes: Response = await fetch(
|
||||
'https://ak-conf.hypergryph.com/config/prod/official/Android/version'
|
||||
)
|
||||
const version = (await versionRes.json()).resVersion
|
||||
const lpacksRes = await fetch(
|
||||
const version: string = (await versionRes.json()).resVersion
|
||||
const lpacksRes: Response = await fetch(
|
||||
`https://ak.hycdn.cn/assetbundle/official/Android/assets/${version}/hot_update_list.json`
|
||||
)
|
||||
const updateList = await lpacksRes.json()
|
||||
const itemToDownload = new Set(config.item_to_download)
|
||||
updateList.abInfos.map((item) => {
|
||||
const updateList: UpdateList = await lpacksRes.json()
|
||||
const itemToDownload: Set<ItemToDownload> = new Set(config.item_to_download)
|
||||
updateList.abInfos.map((item: AbInfosItem) => {
|
||||
if (item.name.includes(config.dynchars)) {
|
||||
const id = getOperatorId(item.name).replace('.ab', '')
|
||||
itemToDownload.add(id)
|
||||
@@ -32,12 +33,12 @@ export default async (dataDir) => {
|
||||
const itemToDownloadRegExp = new RegExp(
|
||||
`(.*)(${Array.from(itemToDownload).join('|')})(.*)`
|
||||
)
|
||||
updateList.abInfos.map((item) => {
|
||||
updateList.abInfos.map((item: AbInfosItem) => {
|
||||
if (itemToDownloadRegExp.test(item.name)) {
|
||||
item.pid && pidSet.add(item.pid)
|
||||
if (item.pid) pidSet.add(item.pid)
|
||||
}
|
||||
})
|
||||
const lpacksToDownload = []
|
||||
const lpacksToDownload: UnzipDownloadItem[] = []
|
||||
pidSet.forEach((item) => {
|
||||
lpacksToDownload.push({
|
||||
name: item,
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@aklive2d/assets",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -13,10 +13,15 @@
|
||||
"@aklive2d/operator": "workspace:*",
|
||||
"@aklive2d/music": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "mode=build node runner.js",
|
||||
"download:game": "mode=download node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check .",
|
||||
"build": "mode=build bun runner.ts",
|
||||
"download:game": "mode=download bun runner.ts",
|
||||
"lint": "eslint && prettier --check .",
|
||||
"build:cleanup": "rm -rf ./dist"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import path from 'node:path'
|
||||
import { envParser } from '@aklive2d/libs'
|
||||
import config from '@aklive2d/config'
|
||||
import build from './libs/build.js'
|
||||
import download from './libs/download.js'
|
||||
import build from './libs/build.ts'
|
||||
import download from './libs/download.ts'
|
||||
|
||||
const packageDir = path.resolve(import.meta.dirname, '..')
|
||||
const dataDir = path.resolve(import.meta.dirname, config.dir_name.data)
|
||||
25
packages/assets/tsconfig.json
Normal file
25
packages/assets/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
35
packages/assets/types.ts
Normal file
35
packages/assets/types.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export type Config = {
|
||||
dynchars: string
|
||||
item_to_download: ItemToDownload[]
|
||||
additional_regex: string[]
|
||||
}
|
||||
|
||||
export type ItemToDownload = string
|
||||
|
||||
export type UpdateList = {
|
||||
versionId: string
|
||||
abInfos: AbInfosItem[]
|
||||
manifestName: string
|
||||
manifestVersion: string
|
||||
packInfos: PackInfosItem[]
|
||||
}
|
||||
|
||||
export type AbInfosItem = {
|
||||
name: string
|
||||
hash: string
|
||||
md5: string
|
||||
totalSize: number
|
||||
abSize: number
|
||||
cid: number
|
||||
cat?: number
|
||||
pid?: string
|
||||
}
|
||||
|
||||
export type PackInfosItem = {
|
||||
name: string
|
||||
hash: string
|
||||
md5: string
|
||||
totalSize: number
|
||||
abSize: number
|
||||
cid: number
|
||||
}
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -66,12 +66,18 @@ export const build = async () => {
|
||||
return err
|
||||
}
|
||||
|
||||
const composite = async (filenamePrefix, fileExt) => {
|
||||
const composite = async (filenamePrefix: string, fileExt: string) => {
|
||||
const image = sharp(
|
||||
path.join(EXTRACTED_DIR, `${filenamePrefix}_left${fileExt}`)
|
||||
)
|
||||
const metadata = await image.metadata()
|
||||
|
||||
if (!metadata.width || !metadata.height) {
|
||||
throw new Error(
|
||||
`Width and height metadata for ${filenamePrefix}_left${fileExt} is not found.`
|
||||
)
|
||||
}
|
||||
|
||||
image
|
||||
.resize(2 * metadata.width, metadata.height, {
|
||||
kernel: sharp.kernel.nearest,
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/background",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"sharp": "^0.33.5",
|
||||
@@ -12,9 +12,14 @@
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "mode=build node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check .",
|
||||
"build": "mode=build bun runner.js",
|
||||
"lint": "eslint && prettier --check .",
|
||||
"build:cleanup": "rm -rf ./dist ./data"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { build } from './index.js'
|
||||
import { build } from './index.ts'
|
||||
import { envParser, error } from '@aklive2d/libs'
|
||||
|
||||
async function main() {
|
||||
25
packages/background/tsconfig.json
Normal file
25
packages/background/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -7,17 +7,26 @@ import operators, {
|
||||
getOperatorAlternativeId,
|
||||
OPERATOR_SOURCE_FOLDER,
|
||||
} from '@aklive2d/operator'
|
||||
import type {
|
||||
Region,
|
||||
CharwordTableJson,
|
||||
OperatorCharwordTable,
|
||||
CharwordTable,
|
||||
VoiceRegionObject,
|
||||
InfoRegionObject,
|
||||
} from './types.ts'
|
||||
|
||||
// zh_TW uses an older version of charword_table.json
|
||||
// zh_TW is removed
|
||||
const REGIONS = ['zh_CN', 'en_US', 'ja_JP', 'ko_KR']
|
||||
const REGIONS: Region[] = ['zh_CN', 'en_US', 'ja_JP', 'ko_KR']
|
||||
|
||||
const REGION_URLS = {
|
||||
zh_CN: 'Kengxxiao/ArknightsGameData',
|
||||
en_US: 'Kengxxiao/ArknightsGameData_YoStar',
|
||||
ja_JP: 'Kengxxiao/ArknightsGameData_YoStar',
|
||||
ko_KR: 'Kengxxiao/ArknightsGameData_YoStar',
|
||||
}
|
||||
const DEFAULT_REGION = REGIONS[0]
|
||||
const DEFAULT_REGION: Region = REGIONS[0]
|
||||
export const defaultRegion = DEFAULT_REGION.replace('_', '-')
|
||||
const NICKNAME = {
|
||||
zh_CN: '博士',
|
||||
@@ -34,22 +43,18 @@ const AUTO_UPDATE_FOLDER = path.resolve(
|
||||
import.meta.dirname,
|
||||
config.dir_name.auto_update
|
||||
)
|
||||
const CHARWORD_TABLE_FILE = path.resolve(
|
||||
AUTO_UPDATE_FOLDER,
|
||||
config.module.charword_table.charword_table_json
|
||||
)
|
||||
const CHARWORD_TABLE = JSON.parse(file.readSync(CHARWORD_TABLE_FILE)) || {}
|
||||
|
||||
const DIST_DIR = path.resolve(import.meta.dirname, config.dir_name.dist)
|
||||
|
||||
export const lookup = (operatorName) => {
|
||||
const lookup = (operatorName: string, charwordTable: CharwordTable) => {
|
||||
const operatorId = getOperatorId(operators[operatorName].filename)
|
||||
const operatorBlock = CHARWORD_TABLE[operatorId]
|
||||
const operatorBlock = charwordTable[operatorId]
|
||||
return operatorBlock.ref
|
||||
? CHARWORD_TABLE[operatorBlock.alternativeId]
|
||||
? charwordTable[operatorBlock.alternativeId]
|
||||
: operatorBlock
|
||||
}
|
||||
|
||||
const getDistDir = (name) => {
|
||||
const getDistDir = (name: string) => {
|
||||
return path.join(
|
||||
DIST_DIR,
|
||||
name,
|
||||
@@ -57,27 +62,37 @@ const getDistDir = (name) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const getLangs = (name, voiceJson = null) => {
|
||||
voiceJson = voiceJson
|
||||
? voiceJson
|
||||
: JSON.parse(file.readSync(getDistDir(name)))
|
||||
const voiceLangs = Object.keys(voiceJson.voiceLangs['zh-CN'])
|
||||
const subtitleLangs = Object.keys(voiceJson.subtitleLangs)
|
||||
export const getLangs = (
|
||||
name: string,
|
||||
voiceJson: OperatorCharwordTable | null = null
|
||||
) => {
|
||||
let data: OperatorCharwordTable
|
||||
if (!voiceJson) {
|
||||
const text = file.readSync(getDistDir(name))
|
||||
if (!text) throw new Error(`File not found: ${getDistDir(name)}`)
|
||||
data = JSON.parse(text)
|
||||
} else {
|
||||
data = voiceJson
|
||||
}
|
||||
const voiceLangs = Object.keys(data.voiceLangs['zh-CN'])
|
||||
const subtitleLangs = Object.keys(data.subtitleLangs)
|
||||
return { voiceLangs, subtitleLangs }
|
||||
}
|
||||
|
||||
export const build = async (namesToBuild) => {
|
||||
const err = []
|
||||
export const build = async (namesToBuild: string[]) => {
|
||||
const err: string[] = []
|
||||
const names = !namesToBuild.length ? Object.keys(operators) : namesToBuild
|
||||
console.log('Generating charword_table for', names.length, 'operators')
|
||||
await updateFn(true)
|
||||
const charwordTable = await updateFn(true)
|
||||
for (const name of names) {
|
||||
const charwordTableLookup = lookup(name)
|
||||
const voiceJson = {}
|
||||
const charwordTableLookup = lookup(name, charwordTable)
|
||||
const voiceJson = {} as OperatorCharwordTable
|
||||
voiceJson.voiceLangs = {}
|
||||
voiceJson.subtitleLangs = {}
|
||||
const subtitleInfo = Object.keys(charwordTableLookup.info)
|
||||
let voiceList = {}
|
||||
const subtitleInfo = Object.keys(charwordTableLookup.info) as Region[]
|
||||
const voiceList = {} as {
|
||||
[key: string]: string[]
|
||||
}
|
||||
subtitleInfo.forEach((item) => {
|
||||
if (Object.keys(charwordTableLookup.info[item]).length > 0) {
|
||||
const key = item.replace('_', '-')
|
||||
@@ -104,7 +119,7 @@ export const build = async (namesToBuild) => {
|
||||
)
|
||||
}
|
||||
})
|
||||
let voiceLangs = []
|
||||
let voiceLangs = [] as string[]
|
||||
try {
|
||||
voiceLangs = getLangs(name, voiceJson).voiceLangs
|
||||
|
||||
@@ -161,36 +176,57 @@ const updateFn = async (isLocalOnly = false) => {
|
||||
(acc, cur) => ({ ...acc, [cur]: {} }),
|
||||
{}
|
||||
)
|
||||
const charwordTable = {} as CharwordTable
|
||||
OPERATOR_IDS.forEach((id) => {
|
||||
CHARWORD_TABLE[id] = {
|
||||
charwordTable[id] = {
|
||||
alternativeId: getOperatorAlternativeId(id),
|
||||
voice: structuredClone(regionObject),
|
||||
info: structuredClone(regionObject),
|
||||
voice: structuredClone(regionObject) as VoiceRegionObject,
|
||||
info: structuredClone(regionObject) as InfoRegionObject,
|
||||
infile: false,
|
||||
ref: false,
|
||||
}
|
||||
})
|
||||
await load(DEFAULT_REGION, isLocalOnly)
|
||||
await load(DEFAULT_REGION, charwordTable, isLocalOnly)
|
||||
await Promise.all(
|
||||
REGIONS.slice(1).map(async (region) => {
|
||||
await load(region, isLocalOnly)
|
||||
await load(region, charwordTable, isLocalOnly)
|
||||
})
|
||||
)
|
||||
return charwordTable
|
||||
}
|
||||
|
||||
const load = async (region, isLocalOnly = false) => {
|
||||
const load = async (
|
||||
region: Region,
|
||||
charwordTable: CharwordTable,
|
||||
isLocalOnly = false
|
||||
) => {
|
||||
const basename = `charword_table_${region}`
|
||||
const filename = file
|
||||
.readdirSync(AUTO_UPDATE_FOLDER)
|
||||
.filter((item) => item.startsWith(`charword_table_${region}`))[0]
|
||||
const localFilePath = path.join(AUTO_UPDATE_FOLDER, filename)
|
||||
const data = isLocalOnly
|
||||
? JSON.parse(file.readSync(localFilePath))
|
||||
: await download(
|
||||
region,
|
||||
path.join(path.dirname(localFilePath), `${basename}.json`)
|
||||
)
|
||||
let data: CharwordTableJson
|
||||
|
||||
const getOnlineData = async () => {
|
||||
return await download(
|
||||
region,
|
||||
path.join(path.dirname(localFilePath), `${basename}.json`)
|
||||
)
|
||||
}
|
||||
|
||||
if (isLocalOnly) {
|
||||
const text = file.readSync(localFilePath)
|
||||
if (!text) {
|
||||
data = await getOnlineData()
|
||||
} else {
|
||||
data = JSON.parse(text)
|
||||
}
|
||||
} else {
|
||||
data = await getOnlineData()
|
||||
}
|
||||
|
||||
// put voice actor info into charword_table
|
||||
for (const [id, element] of Object.entries(CHARWORD_TABLE)) {
|
||||
for (const [id, element] of Object.entries(charwordTable)) {
|
||||
let operatorId = id
|
||||
let useAlternativeId = false
|
||||
if (typeof data.voiceLangDict[operatorId] === 'undefined') {
|
||||
@@ -236,7 +272,7 @@ const load = async (region, isLocalOnly = false) => {
|
||||
|
||||
// put voice lines into charword_table
|
||||
Object.values(data.charWords).forEach((item) => {
|
||||
const operatorInfo = Object.values(CHARWORD_TABLE).filter(
|
||||
const operatorInfo = Object.values(charwordTable).filter(
|
||||
(element) => element.info[region][item.wordKey]
|
||||
)
|
||||
if (operatorInfo.length > 0) {
|
||||
@@ -256,9 +292,14 @@ const load = async (region, isLocalOnly = false) => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return charwordTable
|
||||
}
|
||||
|
||||
const download = async (region, targetFilePath) => {
|
||||
const download = async (
|
||||
region: keyof typeof REGION_URLS,
|
||||
targetFilePath: string
|
||||
) => {
|
||||
return await githubDownload(
|
||||
`https://api.github.com/repos/${REGION_URLS[region]}/commits?path=${region}/gamedata/excel/charword_table.json`,
|
||||
`https://raw.githubusercontent.com/${REGION_URLS[region]}/master/${region}/gamedata/excel/charword_table.json`,
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/charword-table",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@aklive2d/libs": "workspace:*",
|
||||
@@ -12,10 +12,15 @@
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"update": "mode=update node runner.js",
|
||||
"build": "mode=build node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check .",
|
||||
"update": "mode=update bun runner.ts",
|
||||
"build": "mode=build bun runner.ts",
|
||||
"lint": "eslint && prettier --check .",
|
||||
"build:cleanup": "rm -rf ./dist"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { build, update } from './index.js'
|
||||
import { build, update } from './index.ts'
|
||||
import { envParser, error } from '@aklive2d/libs'
|
||||
|
||||
async function main() {
|
||||
let err = []
|
||||
let err: string[] = []
|
||||
const { mode, name } = envParser.parse({
|
||||
mode: {
|
||||
type: 'string',
|
||||
@@ -17,7 +17,7 @@ async function main() {
|
||||
})
|
||||
switch (mode) {
|
||||
case 'build':
|
||||
err = await build(name)
|
||||
err = await build(name as string[])
|
||||
break
|
||||
case 'update':
|
||||
await update()
|
||||
25
packages/charword-table/tsconfig.json
Normal file
25
packages/charword-table/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
139
packages/charword-table/types.ts
Normal file
139
packages/charword-table/types.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
export type Region = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR'
|
||||
|
||||
interface CharWordBase {
|
||||
wordKey: string
|
||||
charId: string
|
||||
voiceId: string
|
||||
voiceText: string
|
||||
}
|
||||
|
||||
interface CharWord extends CharWordBase {
|
||||
charWordId: string
|
||||
voiceTitle: string
|
||||
voiceIndex: number
|
||||
voiceType: string
|
||||
unlockType: string
|
||||
unlockParam: unknown
|
||||
lockDescription: string
|
||||
placeType: string
|
||||
voiceAsset: string
|
||||
}
|
||||
|
||||
type VoiceLangInfo = {
|
||||
wordkey: string
|
||||
voiceLangType: string
|
||||
cvName: string[]
|
||||
voicePath: string | null
|
||||
}
|
||||
|
||||
type CharVoiceLangDict = {
|
||||
wordkeys: string[]
|
||||
charId: string
|
||||
dict: Record<string, VoiceLangInfo>
|
||||
}
|
||||
|
||||
type VoiceLangType = {
|
||||
name: string
|
||||
groupType: string
|
||||
}
|
||||
|
||||
type VoiceLangGroupType = {
|
||||
name: string
|
||||
members: string[]
|
||||
}
|
||||
|
||||
type TimestampCharSet = {
|
||||
timestamp: number
|
||||
charSet: string[]
|
||||
}
|
||||
|
||||
type TimeData = {
|
||||
timeType: string
|
||||
interval: {
|
||||
startTs: number
|
||||
endTs: number
|
||||
}
|
||||
}
|
||||
|
||||
type FesVoiceData = {
|
||||
showType: string
|
||||
timeData: TimeData[]
|
||||
}
|
||||
|
||||
type FesVoiceWeight = {
|
||||
showType: string
|
||||
weight: number
|
||||
priority: number
|
||||
}
|
||||
|
||||
type ExtraVoiceConfig = {
|
||||
voiceId: string
|
||||
validVoiceLang: string[]
|
||||
}
|
||||
|
||||
export type CharwordTableJson = {
|
||||
charWords: Record<string, CharWord>
|
||||
charExtraWords: Record<string, CharWordBase>
|
||||
voiceLangDict: Record<string, CharVoiceLangDict>
|
||||
defaultLangType: string
|
||||
newTagList: string[]
|
||||
voiceLangTypeDict: Record<string, VoiceLangType>
|
||||
voiceLangGroupTypeDict: Record<string, VoiceLangGroupType>
|
||||
charDefaultTypeDict: Record<string, string>
|
||||
startTimeWithTypeDict: Record<string, TimestampCharSet[]>
|
||||
displayGroupTypeList: string[]
|
||||
displayTypeList: string[]
|
||||
playVoiceRange: string
|
||||
fesVoiceData: Record<string, FesVoiceData>
|
||||
fesVoiceWeight: Record<string, FesVoiceWeight>
|
||||
extraVoiceConfigData: Record<string, ExtraVoiceConfig>
|
||||
}
|
||||
|
||||
export type OperatorCharwordTable = {
|
||||
voiceLangs: {
|
||||
[languageCode: string]: {
|
||||
[voiceLangType: string]: string[]
|
||||
}
|
||||
}
|
||||
subtitleLangs: {
|
||||
[languageCode: string]: {
|
||||
[voiceKey: 'default' | string]: {
|
||||
[voiceId: string]: {
|
||||
title: string
|
||||
text: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type VoiceRegionObject = {
|
||||
// eslint-disable-next-line
|
||||
[region in Region]: {
|
||||
[wordkey: string]: {
|
||||
[voiceId: string]: {
|
||||
title: string
|
||||
text: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type InfoRegionObject = {
|
||||
// eslint-disable-next-line
|
||||
[region in Region]: {
|
||||
[wordkey: string]: {
|
||||
[voiceLangType: string]: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type CharwordTable = {
|
||||
[name: string]: {
|
||||
alternativeId: string
|
||||
voice: VoiceRegionObject
|
||||
info: InfoRegionObject
|
||||
infile: boolean
|
||||
ref: boolean
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ app:
|
||||
showcase:
|
||||
public: public
|
||||
assets: assets
|
||||
release: release
|
||||
dir_name:
|
||||
data: data
|
||||
dist: dist
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import path from 'node:path'
|
||||
import { yaml } from '@aklive2d/libs'
|
||||
|
||||
export default yaml.read(path.resolve(import.meta.dirname, 'config.yaml'))
|
||||
9
packages/config/index.ts
Normal file
9
packages/config/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import path from 'node:path'
|
||||
import { yaml } from '@aklive2d/libs'
|
||||
import type { Config } from './types'
|
||||
|
||||
const config: Config = yaml.read(
|
||||
path.resolve(import.meta.dirname, 'config.yaml')
|
||||
)
|
||||
|
||||
export default config
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@aklive2d/config",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -9,7 +9,12 @@
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check ."
|
||||
"lint": "eslint && prettier --check ."
|
||||
}
|
||||
}
|
||||
|
||||
25
packages/config/tsconfig.json
Normal file
25
packages/config/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
103
packages/config/types.ts
Normal file
103
packages/config/types.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
export type Config = {
|
||||
site_id: string
|
||||
total_size: number
|
||||
akassets: {
|
||||
project_name: string
|
||||
url: string
|
||||
}
|
||||
insight: {
|
||||
id: string
|
||||
url: string
|
||||
}
|
||||
module: {
|
||||
assets: {
|
||||
config_yaml: string
|
||||
background: string
|
||||
music: string
|
||||
charword_table: string
|
||||
project_json: string
|
||||
}
|
||||
background: {
|
||||
operator_bg_png: string
|
||||
}
|
||||
charword_table: {
|
||||
charword_table_json: string
|
||||
}
|
||||
music: {
|
||||
music_table_json: string
|
||||
display_meta_table_json: string
|
||||
audio_data_json: string
|
||||
}
|
||||
official_info: {
|
||||
official_info_json: string
|
||||
}
|
||||
operator: {
|
||||
operator: string
|
||||
config: string
|
||||
template_yaml: string
|
||||
config_yaml: string
|
||||
portraits: string
|
||||
logos_assets: string
|
||||
logos: string
|
||||
directory_assets: string
|
||||
MonoBehaviour: string
|
||||
Texture2D: string
|
||||
title: {
|
||||
'zh-CN': string
|
||||
'en-US': string
|
||||
}
|
||||
}
|
||||
project_json: {
|
||||
project_json: string
|
||||
preview_jpg: string
|
||||
template_yaml: string
|
||||
}
|
||||
wrangler: {
|
||||
index_json: string
|
||||
}
|
||||
vite_helpers: {
|
||||
config_json: string
|
||||
}
|
||||
}
|
||||
app: {
|
||||
showcase: {
|
||||
public: string
|
||||
assets: string
|
||||
release: string
|
||||
}
|
||||
}
|
||||
dir_name: {
|
||||
data: string
|
||||
dist: string
|
||||
extracted: string
|
||||
auto_update: string
|
||||
voice: {
|
||||
main: string
|
||||
sub: {
|
||||
name: string
|
||||
lang: string
|
||||
lookup_region: string
|
||||
}[]
|
||||
}
|
||||
}
|
||||
directory: {
|
||||
assets_dir: string
|
||||
title: string
|
||||
voice: string
|
||||
error: {
|
||||
files: {
|
||||
key: string
|
||||
paddings: {
|
||||
left: string
|
||||
right: string
|
||||
top: string
|
||||
bottom: string
|
||||
}
|
||||
}[]
|
||||
voice: {
|
||||
file: string
|
||||
target: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -5,7 +5,16 @@ import { pipeline } from 'node:stream/promises'
|
||||
import pThrottle from 'p-throttle'
|
||||
import { file as fileLib } from '@aklive2d/libs'
|
||||
|
||||
export const githubDownload = async (history_url, raw_url, filepath) => {
|
||||
export type UnzipDownloadItem = {
|
||||
name: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export const githubDownload = async (
|
||||
history_url: string,
|
||||
raw_url: string,
|
||||
filepath: string
|
||||
) => {
|
||||
const historyResponse = await fetch(history_url)
|
||||
const historyData = await historyResponse.json()
|
||||
const lastCommit = historyData[0]
|
||||
@@ -21,7 +30,8 @@ export const githubDownload = async (history_url, raw_url, filepath) => {
|
||||
|
||||
if (fileLib.exists(filepath)) {
|
||||
console.log(`${basename} is the latest version.`)
|
||||
return JSON.parse(fileLib.readSync(filepath))
|
||||
const content = fileLib.readSync(filepath)
|
||||
return content ? JSON.parse(content) : null
|
||||
}
|
||||
const response = await fetch(raw_url)
|
||||
const data = await response.json()
|
||||
@@ -39,9 +49,12 @@ export const githubDownload = async (history_url, raw_url, filepath) => {
|
||||
}
|
||||
|
||||
export const unzipDownload = async (
|
||||
filesToDownload,
|
||||
targetDir,
|
||||
opts = {
|
||||
filesToDownload: UnzipDownloadItem[],
|
||||
targetDir: string,
|
||||
opts: {
|
||||
defaultRegex: RegExp | null
|
||||
matchRegExps: RegExp[]
|
||||
} = {
|
||||
defaultRegex: null,
|
||||
matchRegExps: [],
|
||||
}
|
||||
@@ -52,7 +65,7 @@ export const unzipDownload = async (
|
||||
interval: 1000,
|
||||
})
|
||||
while (retry.length > 0) {
|
||||
const newRetry = []
|
||||
const newRetry: UnzipDownloadItem[] = []
|
||||
await Promise.all(
|
||||
retry.map(
|
||||
throttle(async (item) => {
|
||||
@@ -72,7 +85,9 @@ export const unzipDownload = async (
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
return null
|
||||
})
|
||||
if (!zip) return
|
||||
try {
|
||||
for await (const entry of zip) {
|
||||
if (
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/downloader",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
@@ -11,6 +11,6 @@
|
||||
"p-throttle": "^7.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check ."
|
||||
"lint": "eslint && prettier --check ."
|
||||
}
|
||||
}
|
||||
|
||||
25
packages/downloader/tsconfig.json
Normal file
25
packages/downloader/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import js from '@eslint/js'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
import globals from 'globals'
|
||||
import tsConfig from './ts.js'
|
||||
|
||||
export default [
|
||||
{ ignores: ['dist'] },
|
||||
@@ -24,3 +25,5 @@ export default [
|
||||
},
|
||||
eslintPluginPrettierRecommended,
|
||||
]
|
||||
|
||||
export { tsConfig }
|
||||
|
||||
4
packages/eslint-config/js.js
Normal file
4
packages/eslint-config/js.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import eslint from '@eslint/js'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
|
||||
export default [eslint.configs.recommended, eslintPluginPrettierRecommended]
|
||||
@@ -1,17 +1,16 @@
|
||||
{
|
||||
"name": "@aklive2d/eslint-config",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.19.0",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"globals": "^15.14.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
"name": "@aklive2d/eslint-config",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.19.0",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"globals": "^16.0.0",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.31.1"
|
||||
}
|
||||
}
|
||||
|
||||
10
packages/eslint-config/ts.js
Normal file
10
packages/eslint-config/ts.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import eslint from '@eslint/js'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
eslintPluginPrettierRecommended
|
||||
)
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import * as file from './libs/file.js'
|
||||
import * as yaml from './libs/yaml.js'
|
||||
import * as env from './libs/env.js'
|
||||
import * as error from './libs/error.js'
|
||||
import * as alphaComposite from './libs/alpha_composite.js'
|
||||
import * as envParser from './libs/env_parser.js'
|
||||
|
||||
export { file }
|
||||
export { yaml }
|
||||
export { env }
|
||||
export { error }
|
||||
export { alphaComposite }
|
||||
export { envParser }
|
||||
13
packages/libs/index.ts
Normal file
13
packages/libs/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as file from './libs/file.ts'
|
||||
import * as yaml from './libs/yaml.ts'
|
||||
import * as env from './libs/env.ts'
|
||||
import * as error from './libs/error.ts'
|
||||
import * as alphaComposite from './libs/alpha_composite.ts'
|
||||
import * as envParser from './libs/env_parser.ts'
|
||||
|
||||
export { file }
|
||||
export { yaml }
|
||||
export { env }
|
||||
export { error }
|
||||
export { alphaComposite }
|
||||
export { envParser }
|
||||
@@ -1,7 +1,19 @@
|
||||
import sharp from 'sharp'
|
||||
import path from 'node:path'
|
||||
|
||||
export const process = async (filename, maskFilename, extractedDir) => {
|
||||
export type Rect = {
|
||||
x: number
|
||||
y: number
|
||||
w: number
|
||||
h: number
|
||||
rotate: number
|
||||
}
|
||||
|
||||
export const process = async (
|
||||
filename: string,
|
||||
maskFilename: string,
|
||||
extractedDir: string
|
||||
) => {
|
||||
const image = sharp(path.join(extractedDir, filename)).removeAlpha()
|
||||
const imageMeta = await image.metadata()
|
||||
const imageBuffer = await image.toBuffer()
|
||||
@@ -13,7 +25,22 @@ export const process = async (filename, maskFilename, extractedDir) => {
|
||||
return sharp(imageBuffer).joinChannel(mask).toBuffer()
|
||||
}
|
||||
|
||||
export const crop = async (buffer, rect) => {
|
||||
export const crop = async (
|
||||
buffer:
|
||||
| Buffer
|
||||
| ArrayBuffer
|
||||
| Uint8Array
|
||||
| Uint8ClampedArray
|
||||
| Int8Array
|
||||
| Uint16Array
|
||||
| Int16Array
|
||||
| Uint32Array
|
||||
| Int32Array
|
||||
| Float32Array
|
||||
| Float64Array
|
||||
| string,
|
||||
rect: Rect
|
||||
) => {
|
||||
const left = rect.y
|
||||
const top = rect.x
|
||||
const width = rect.h
|
||||
@@ -28,7 +55,7 @@ export const crop = async (buffer, rect) => {
|
||||
return await sharp(newImage).rotate(rotate).toBuffer()
|
||||
}
|
||||
|
||||
export const toBuffer = async (filename, extractedDir) => {
|
||||
export const toBuffer = async (filename: string, extractedDir: string) => {
|
||||
const file = path.join(extractedDir, filename)
|
||||
const { data, info } = await sharp(file)
|
||||
.raw()
|
||||
@@ -36,7 +63,7 @@ export const toBuffer = async (filename, extractedDir) => {
|
||||
const { width, height, channels } = info
|
||||
const pixelArray = new Uint8ClampedArray(data.buffer)
|
||||
for (let i = 0; i < pixelArray.length; i += 4) {
|
||||
let alpha = pixelArray[i + 3] / 255
|
||||
const alpha = pixelArray[i + 3] / 255
|
||||
pixelArray[i + 0] = pixelArray[i + 0] * alpha
|
||||
pixelArray[i + 1] = pixelArray[i + 1] * alpha
|
||||
pixelArray[i + 2] = pixelArray[i + 2] * alpha
|
||||
@@ -1,4 +1,9 @@
|
||||
export function generate(values) {
|
||||
export function generate(
|
||||
values: {
|
||||
key: string
|
||||
value: string
|
||||
}[]
|
||||
) {
|
||||
return values
|
||||
.map((value) => {
|
||||
return `VITE_${value.key.toUpperCase()}=${value.value}`
|
||||
@@ -1,28 +1,40 @@
|
||||
import process from 'node:process'
|
||||
|
||||
export const parse = (args) => {
|
||||
type Args = {
|
||||
[name: string]: {
|
||||
type?: string
|
||||
default?: unknown
|
||||
multiple?: boolean
|
||||
short?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const parse = (args: Args) => {
|
||||
const envVars = process.env
|
||||
const argKeys = Object.keys(args)
|
||||
const values = {}
|
||||
const values: Record<string, unknown | unknown[]> = {}
|
||||
argKeys.map((key) => {
|
||||
let noInput = false
|
||||
let value,
|
||||
type = args[key].type || 'string',
|
||||
let value: unknown
|
||||
const type = args[key].type || 'string',
|
||||
defaultVal = args[key].default,
|
||||
multiple = args[key].multiple || false,
|
||||
short = args[key].short
|
||||
value = envVars[key] || envVars[short]
|
||||
value = short
|
||||
? envVars[short]
|
||||
? envVars[short]
|
||||
: envVars[key]
|
||||
: envVars[key]
|
||||
if (!value) noInput = true
|
||||
value = noInput ? defaultVal : value
|
||||
if (noInput) {
|
||||
values[key] = value
|
||||
} else {
|
||||
value = multiple ? value.split(',') : value
|
||||
const cValue = multiple ? (value as string).split(',') : value
|
||||
if (multiple) {
|
||||
values[key] = []
|
||||
value.map((item) => {
|
||||
values[key].push(typeCast(type, item))
|
||||
})
|
||||
values[key] = (cValue as string[]).map((item: string) =>
|
||||
typeCast(type, item)
|
||||
)
|
||||
} else {
|
||||
values[key] = typeCast(type, value)
|
||||
}
|
||||
@@ -31,7 +43,7 @@ export const parse = (args) => {
|
||||
return values
|
||||
}
|
||||
|
||||
const typeCast = (type, value) => {
|
||||
const typeCast = (type: 'number' | 'boolean' | string, value: unknown) => {
|
||||
switch (type) {
|
||||
case 'number':
|
||||
return Number(value)
|
||||
@@ -1,4 +1,4 @@
|
||||
export const handle = (err) => {
|
||||
export const handle = (err: string[]) => {
|
||||
if (err.length > 0) {
|
||||
const str = `${err.length} error${err.length > 1 ? 's were' : ' was'} found:\n${err.join('\n')}`
|
||||
throw new Error(str)
|
||||
@@ -3,52 +3,61 @@ import path from 'node:path'
|
||||
import yauzl from 'yauzl-promise'
|
||||
import yazl from 'yazl'
|
||||
|
||||
export async function write(content, filePath) {
|
||||
export async function write(
|
||||
content: string | NodeJS.ArrayBufferView,
|
||||
filePath: string
|
||||
) {
|
||||
mkdir(path.dirname(filePath))
|
||||
return await fsP.writeFile(filePath, content, { flag: 'w' })
|
||||
}
|
||||
|
||||
export function writeSync(content, filePath) {
|
||||
export function writeSync(
|
||||
content: string | NodeJS.ArrayBufferView,
|
||||
filePath: string
|
||||
) {
|
||||
mkdir(path.dirname(filePath))
|
||||
return fs.writeFileSync(filePath, content, { flag: 'w' })
|
||||
}
|
||||
|
||||
export async function read(filePath, encoding = 'utf8') {
|
||||
return await fsP.readFile(filePath, encoding, { flag: 'r' })
|
||||
export async function read(
|
||||
filePath: string,
|
||||
encoding: BufferEncoding = 'utf8'
|
||||
) {
|
||||
return await fsP.readFile(filePath, { encoding, flag: 'r' })
|
||||
}
|
||||
|
||||
export function readSync(filePath, encoding = 'utf8') {
|
||||
export function readSync(filePath: string, encoding: BufferEncoding = 'utf8') {
|
||||
if (exists(filePath)) {
|
||||
return fs.readFileSync(filePath, encoding, { flag: 'r' })
|
||||
return fs.readFileSync(filePath, { encoding, flag: 'r' })
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function exists(filePath) {
|
||||
export function exists(filePath: string) {
|
||||
return fs.existsSync(filePath)
|
||||
}
|
||||
|
||||
export function rmdir(dir) {
|
||||
export function rmdir(dir: string) {
|
||||
if (exists(dir)) {
|
||||
fs.rmSync(dir, { recursive: true })
|
||||
}
|
||||
}
|
||||
|
||||
export function rm(dir) {
|
||||
export function rm(dir: string) {
|
||||
if (exists(dir)) {
|
||||
fs.rmSync(dir, { recursive: true })
|
||||
}
|
||||
}
|
||||
|
||||
export function mkdir(dir) {
|
||||
export function mkdir(dir: string) {
|
||||
if (!exists(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true })
|
||||
}
|
||||
}
|
||||
|
||||
export async function copy(
|
||||
sourcePath,
|
||||
targetPath,
|
||||
sourcePath: string,
|
||||
targetPath: string,
|
||||
mode = fs.constants.COPYFILE_FICLONE
|
||||
) {
|
||||
if (!exists(sourcePath)) {
|
||||
@@ -60,8 +69,8 @@ export async function copy(
|
||||
}
|
||||
|
||||
export async function copyDir(
|
||||
sourcePath,
|
||||
targetPath,
|
||||
sourcePath: string,
|
||||
targetPath: string,
|
||||
mode = fs.constants.COPYFILE_FICLONE
|
||||
) {
|
||||
if (!exists(sourcePath)) {
|
||||
@@ -72,11 +81,11 @@ export async function copyDir(
|
||||
return await fsP.cp(sourcePath, targetPath, { recursive: true, mode })
|
||||
}
|
||||
|
||||
export function appendSync(content, filePath) {
|
||||
export function appendSync(content: string | Uint8Array, filePath: string) {
|
||||
return fs.appendFileSync(filePath, content, 'utf8')
|
||||
}
|
||||
|
||||
export function readdirSync(dir) {
|
||||
export function readdirSync(dir: string) {
|
||||
if (!exists(dir)) {
|
||||
console.warn(`Source ${dir} does not exist.`)
|
||||
return []
|
||||
@@ -84,7 +93,7 @@ export function readdirSync(dir) {
|
||||
return fs.readdirSync(dir)
|
||||
}
|
||||
|
||||
export function fileTypeSync(dir) {
|
||||
export function fileTypeSync(dir: string) {
|
||||
if (!exists(dir)) {
|
||||
console.warn(`Source ${dir} does not exist.`)
|
||||
return null
|
||||
@@ -92,7 +101,7 @@ export function fileTypeSync(dir) {
|
||||
return fs.statSync(dir).isDirectory() ? 'dir' : 'file'
|
||||
}
|
||||
|
||||
export const symlink = (source, target) => {
|
||||
export const symlink = (source: string, target: string) => {
|
||||
if (!exists(source)) {
|
||||
console.warn(`Source ${source} does not exist.`)
|
||||
return
|
||||
@@ -105,14 +114,14 @@ export const symlink = (source, target) => {
|
||||
fs.symlinkSync(relative, target)
|
||||
}
|
||||
|
||||
export const symlinkAll = (source, target) => {
|
||||
export const symlinkAll = (source: string, target: string) => {
|
||||
const files = readdirSync(source)
|
||||
files.map((file) => {
|
||||
symlink(path.join(source, file), path.join(target, file))
|
||||
})
|
||||
}
|
||||
|
||||
export const mv = (source, target) => {
|
||||
export const mv = (source: string, target: string) => {
|
||||
if (!exists(source)) {
|
||||
console.warn(`Source file ${source} does not exist.`)
|
||||
return
|
||||
@@ -125,8 +134,8 @@ export const mv = (source, target) => {
|
||||
}
|
||||
|
||||
export const cpSync = (
|
||||
source,
|
||||
target,
|
||||
source: string,
|
||||
target: string,
|
||||
opts = {
|
||||
dereference: false,
|
||||
}
|
||||
@@ -146,7 +155,7 @@ export const cpSync = (
|
||||
})
|
||||
}
|
||||
|
||||
export const relative = (source, target) => {
|
||||
export const relative = (source: string, target: string) => {
|
||||
if (!exists(source)) {
|
||||
console.warn(`Source file ${source} does not exist.`)
|
||||
return
|
||||
@@ -154,7 +163,7 @@ export const relative = (source, target) => {
|
||||
return path.relative(source, target)
|
||||
}
|
||||
|
||||
export const size = (source) => {
|
||||
export const size = (source: string) => {
|
||||
if (!exists(source)) {
|
||||
console.warn(`Source file ${source} does not exist.`)
|
||||
return
|
||||
@@ -1,12 +1,17 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { parse } from 'yaml'
|
||||
import type { Tags, ScalarTag, SchemaOptions, CollectionTag } from 'yaml'
|
||||
|
||||
export function read(file_dir, customTags = []) {
|
||||
const include = {
|
||||
identify: (value) => value.startsWith('!include'),
|
||||
export function read(
|
||||
file_dir: string,
|
||||
customTags: ScalarTag[] | CollectionTag[] = []
|
||||
) {
|
||||
const include: ScalarTag = {
|
||||
identify: (value: unknown) =>
|
||||
typeof value === 'string' && value.startsWith('!include'),
|
||||
tag: '!include',
|
||||
resolve(str) {
|
||||
resolve(str: string) {
|
||||
const dir = path.resolve(path.dirname(file_dir), str)
|
||||
const data = read(dir)
|
||||
return data
|
||||
@@ -15,5 +20,5 @@ export function read(file_dir, customTags = []) {
|
||||
const file = fs.readFileSync(file_dir, 'utf8')
|
||||
return parse(file, {
|
||||
customTags: [include, ...customTags],
|
||||
})
|
||||
} as SchemaOptions)
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/libs",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
@@ -12,7 +12,16 @@
|
||||
"yauzl-promise": "^4.0.0",
|
||||
"yazl": "^3.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check ."
|
||||
"lint": "eslint && prettier --check ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/yauzl-promise": "^4.0.1",
|
||||
"@types/yazl": "^2.4.6"
|
||||
}
|
||||
}
|
||||
|
||||
25
packages/libs/tsconfig.json
Normal file
25
packages/libs/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["libs/**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -2,6 +2,16 @@ import path from 'node:path'
|
||||
import { file } from '@aklive2d/libs'
|
||||
import { githubDownload } from '@aklive2d/downloader'
|
||||
import config from '@aklive2d/config'
|
||||
import type {
|
||||
DisplayMetaTable,
|
||||
AudioDataTable,
|
||||
MusicTable,
|
||||
MusicFileMapping,
|
||||
MusicFiles,
|
||||
MusicItem,
|
||||
MusicDataItem,
|
||||
MusicMapping,
|
||||
} from './types.ts'
|
||||
|
||||
const AUTO_UPDATE_FOLDER = path.resolve(
|
||||
import.meta.dirname,
|
||||
@@ -22,12 +32,12 @@ const download = async () => {
|
||||
AUTO_UPDATE_FOLDER,
|
||||
config.module.music.audio_data_json
|
||||
)
|
||||
const metaTable = await githubDownload(
|
||||
const metaTable: DisplayMetaTable = await githubDownload(
|
||||
`https://api.github.com/repos/Kengxxiao/ArknightsGameData/commits?path=zh_CN/gamedata/excel/display_meta_table.json`,
|
||||
`https://raw.githubusercontent.com/Kengxxiao/ArknightsGameData/master/zh_CN/gamedata/excel/display_meta_table.json`,
|
||||
display_meta_table_json
|
||||
)
|
||||
const audioDataTable = await githubDownload(
|
||||
const audioDataTable: AudioDataTable = await githubDownload(
|
||||
`https://api.github.com/repos/Kengxxiao/ArknightsGameData/commits?path=zh_CN/gamedata/excel/audio_data.json`,
|
||||
`https://raw.githubusercontent.com/Kengxxiao/ArknightsGameData/master/zh_CN/gamedata/excel/audio_data.json`,
|
||||
audio_data_json
|
||||
@@ -40,14 +50,17 @@ const download = async () => {
|
||||
|
||||
const generateMapping = () => {
|
||||
const musicFolder = DATA_DIR
|
||||
const musicTable = JSON.parse(file.readSync(MUSIC_TABLE_JSON))
|
||||
const musicFileMapping = {}
|
||||
const musicFiles = []
|
||||
const musicTableContent = file.readSync(MUSIC_TABLE_JSON)
|
||||
const musicTable: MusicTable = musicTableContent
|
||||
? JSON.parse(musicTableContent)
|
||||
: null
|
||||
const musicFileMapping: MusicFileMapping = {}
|
||||
const musicFiles: MusicFiles = []
|
||||
|
||||
if (!musicTable) return
|
||||
if (!musicTable) throw new Error('Music table not found')
|
||||
for (const item of musicTable) {
|
||||
const key = `${item.id}.png`
|
||||
musicFileMapping[key] = {}
|
||||
musicFileMapping[key] = {} as MusicItem
|
||||
|
||||
if (item.intro) {
|
||||
const filename = `${item.intro.split('/').pop()}.ogg`
|
||||
@@ -78,34 +91,37 @@ const generateMapping = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const mapping = generateMapping()
|
||||
export const mapping: MusicMapping = generateMapping()
|
||||
|
||||
export const update = async () => {
|
||||
const { metaTable, audioDataTable } = await download()
|
||||
const musicTable = audioDataTable.musics
|
||||
const musicBank = audioDataTable.bgmBanks
|
||||
const musicBankAlias = audioDataTable.bankAlias
|
||||
const musicData = metaTable.homeBackgroundData.homeBgDataList.reduce(
|
||||
(acc, cur) => {
|
||||
const musicData: MusicDataItem[] =
|
||||
metaTable.homeBackgroundData.homeBgDataList.reduce((acc, cur) => {
|
||||
acc.push({
|
||||
id: cur.bgId,
|
||||
musicId: cur.bgMusicId,
|
||||
})
|
||||
return acc
|
||||
},
|
||||
[]
|
||||
)
|
||||
}, [] as MusicDataItem[])
|
||||
const list = []
|
||||
for (const item of musicData) {
|
||||
let bankName = musicTable.find((el) => item.musicId === el.id).bank
|
||||
const bankItem = musicTable.find((el) => item.musicId === el.id)
|
||||
if (typeof bankItem === 'undefined')
|
||||
console.warn(`No music found for id ${item.musicId}`)
|
||||
let bankName = bankItem!.bank
|
||||
if (typeof musicBankAlias[bankName] !== 'undefined') {
|
||||
bankName = musicBankAlias[bankName]
|
||||
}
|
||||
const obj = musicBank.find((el) => bankName === el.name)
|
||||
if (typeof obj === 'undefined')
|
||||
console.warn(`No bank found for name ${bankName}`)
|
||||
list.push({
|
||||
id: item.id,
|
||||
intro: obj.intro,
|
||||
loop: obj.loop,
|
||||
intro: obj!.intro,
|
||||
loop: obj!.loop,
|
||||
})
|
||||
}
|
||||
list.push({
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/music",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@aklive2d/libs": "workspace:*",
|
||||
@@ -11,9 +11,14 @@
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"update": "mode=update node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check .",
|
||||
"update": "mode=update bun runner.ts",
|
||||
"lint": "eslint && prettier --check .",
|
||||
"build:cleanup": "rm -rf ./data"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { envParser } from '@aklive2d/libs'
|
||||
import { update } from './index.js'
|
||||
import { update } from './index.ts'
|
||||
|
||||
async function main() {
|
||||
const { mode } = envParser.parse({
|
||||
25
packages/music/tsconfig.json
Normal file
25
packages/music/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
295
packages/music/types.ts
Normal file
295
packages/music/types.ts
Normal file
@@ -0,0 +1,295 @@
|
||||
export type MusicMapping = {
|
||||
musicFiles: MusicFiles
|
||||
musicFileMapping: MusicFileMapping
|
||||
}
|
||||
|
||||
export type MusicItem = {
|
||||
id?: string
|
||||
intro: string | null
|
||||
loop: string | null
|
||||
}
|
||||
|
||||
export type MusicTable = MusicItem[]
|
||||
|
||||
export type MusicFileMapping = Record<string, MusicItem>
|
||||
|
||||
export type MusicFile = {
|
||||
filename: string
|
||||
source: string
|
||||
}
|
||||
|
||||
export type MusicFiles = MusicFile[]
|
||||
|
||||
export type DisplayMetaTable = {
|
||||
playerAvatarData: {
|
||||
defaultAvatarId: string
|
||||
avatarList: {
|
||||
avatarId: string
|
||||
avatarType: string
|
||||
avatarIdSort: number
|
||||
avatarIdDesc: string
|
||||
avatarItemName: string
|
||||
avatarItemDesc: string
|
||||
avatarItemUsage: string
|
||||
obtainApproach: string
|
||||
dynAvatarId: null | unknown
|
||||
}[]
|
||||
avatarTypeData: {
|
||||
[key: string]: {
|
||||
avatarType: string
|
||||
typeName: string
|
||||
sortId: number
|
||||
avatarIdList: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
homeBackgroundData: {
|
||||
defaultBackgroundId: string
|
||||
defaultThemeId: string
|
||||
homeBgDataList: {
|
||||
bgId: string
|
||||
bgSortId: number
|
||||
bgStartTime: number
|
||||
bgName: string
|
||||
bgMusicId: string
|
||||
bgDes: string
|
||||
bgUsage: string
|
||||
obtainApproach: string
|
||||
unlockDesList: string[]
|
||||
}[]
|
||||
themeList: {
|
||||
id: string
|
||||
type: string
|
||||
sortId: number
|
||||
startTime: number
|
||||
tmName: string
|
||||
tmDes: string
|
||||
tmUsage: string
|
||||
obtainApproach: string
|
||||
unlockDesList: string[]
|
||||
isLimitObtain: boolean
|
||||
hideWhenLimit: boolean
|
||||
rarity: string
|
||||
}[]
|
||||
backgroundLimitData: {
|
||||
[key: string]: {
|
||||
bgId: string
|
||||
limitInfos: {
|
||||
limitInfoId: string
|
||||
startTime: Date
|
||||
endTime: Date
|
||||
invalidObtainDesc: string
|
||||
displayAfterEndTime: boolean
|
||||
}[]
|
||||
}
|
||||
}
|
||||
themeLimitData: {
|
||||
[key: string]: {
|
||||
id: string
|
||||
limitInfos: {
|
||||
startTime: Date
|
||||
endTime: Date
|
||||
invalidObtainDesc: string
|
||||
}[]
|
||||
}
|
||||
}
|
||||
defaultBgMusicId: string
|
||||
themeStartTime: Date
|
||||
}
|
||||
nameCardV2Data: {
|
||||
fixedModuleData: {
|
||||
[key: string]: {
|
||||
id: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
removableModuleData: {
|
||||
[key: string]: {
|
||||
sortId: number
|
||||
subType: string
|
||||
name: string
|
||||
id: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
skinData: {
|
||||
[key: string]: {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
sortId: number
|
||||
isSpTheme: boolean
|
||||
defaultShowDetail: boolean
|
||||
themeName: string
|
||||
themeEnName: string
|
||||
skinStartTime: number
|
||||
skinDesc: string
|
||||
usageDesc: string
|
||||
skinApproach: string
|
||||
unlockConditionCnt: number
|
||||
unlockDescList: unknown[]
|
||||
fixedModuleList: string[]
|
||||
rarity: string
|
||||
skinTmplCnt: number
|
||||
canChangeTmpl: boolean
|
||||
isTimeLimit: boolean
|
||||
timeLimitInfoList: unknown[]
|
||||
}
|
||||
}
|
||||
consts: {
|
||||
defaultNameCardSkinId: string
|
||||
canUidHide: boolean
|
||||
removableModuleMaxCount: number
|
||||
}
|
||||
}
|
||||
mailArchiveData: {
|
||||
mailArchiveInfoDict: {
|
||||
[key: string]: {
|
||||
id: string
|
||||
type: string
|
||||
sortId: number
|
||||
displayReceiveTs: number
|
||||
year: number
|
||||
dateDelta: number
|
||||
senderId: string
|
||||
title: string
|
||||
content: string
|
||||
rewardList: {
|
||||
id: string
|
||||
count: number
|
||||
type: string
|
||||
}[]
|
||||
}
|
||||
}
|
||||
constData: {
|
||||
funcOpenTs: number
|
||||
}
|
||||
}
|
||||
mailSenderData: {
|
||||
senderDict: {
|
||||
[key: string]: {
|
||||
senderId: string
|
||||
senderName: string
|
||||
avatarId: string
|
||||
}
|
||||
}
|
||||
}
|
||||
emoticonData: {
|
||||
emojiDataDict: {
|
||||
[key: string]: {
|
||||
id: string
|
||||
type: string
|
||||
sortId: number
|
||||
picId: string
|
||||
desc: string
|
||||
}
|
||||
}
|
||||
emoticonThemeDataDict: { [key: string]: string[] }
|
||||
}
|
||||
storyVariantData: {
|
||||
[key: string]: {
|
||||
plotTaskId: string
|
||||
spStoryId: string
|
||||
storyId: string
|
||||
priority: number
|
||||
startTime: number
|
||||
endTime: number
|
||||
template: string
|
||||
param: string[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type AudioDataTable = {
|
||||
bgmBanks: {
|
||||
intro: string
|
||||
loop: string
|
||||
volume: number
|
||||
crossfade: number
|
||||
delay: number
|
||||
fadeStyleId: null | string
|
||||
name: string
|
||||
}[]
|
||||
soundFXBanks: {
|
||||
sounds: {
|
||||
asset: string
|
||||
weight: number
|
||||
important: boolean
|
||||
is2D: boolean
|
||||
delay: number
|
||||
minPitch: number
|
||||
maxPitch: number
|
||||
minVolume: number
|
||||
maxVolume: number
|
||||
ignoreTimeScale: boolean
|
||||
}[]
|
||||
maxSoundAllowed: number
|
||||
popOldest: boolean
|
||||
customMixerGroup: string
|
||||
loop: boolean
|
||||
name: string
|
||||
mixerDesc: null | string
|
||||
}[]
|
||||
soundFXCtrlBanks: {
|
||||
targetBank: string
|
||||
ctrlStop: boolean
|
||||
ctrlStopFadetime: number
|
||||
name: string
|
||||
}[]
|
||||
snapshotBanks: {
|
||||
targetSnapshot: string
|
||||
hookSoundFxBank: string
|
||||
delay: number
|
||||
duration: number
|
||||
name: string
|
||||
}[]
|
||||
battleVoice: {
|
||||
crossfade: number
|
||||
minTimeDeltaForEnemyEncounter: number
|
||||
minSpCostForImportantPassiveSkill: number
|
||||
voiceTypeOptions: {
|
||||
voiceType: string
|
||||
priority: number
|
||||
overlapIfSamePriority: boolean
|
||||
cooldown: number
|
||||
delay: number
|
||||
}[]
|
||||
}
|
||||
musics: {
|
||||
id: string
|
||||
name: string
|
||||
bank: string
|
||||
}[]
|
||||
duckings: {
|
||||
bank: string
|
||||
volume: number
|
||||
fadeTime: number
|
||||
delay: number
|
||||
fadeStyleId: null | string
|
||||
}[]
|
||||
fadeStyles: {
|
||||
styleName: string
|
||||
fadeinTime: number
|
||||
fadeoutTime: number
|
||||
fadeinType: string
|
||||
fadeoutType: string
|
||||
}[]
|
||||
soundFxVoiceLang: {
|
||||
[key: string]: {
|
||||
[key: string]: {
|
||||
JP: string
|
||||
CN_MANDARIN: string
|
||||
KR: string
|
||||
EN?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
bankAlias: {
|
||||
[key: string]: string
|
||||
}
|
||||
}
|
||||
|
||||
export type MusicDataItem = {
|
||||
id: string
|
||||
musicId: string
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -2,6 +2,13 @@ import jsdom from 'jsdom'
|
||||
import path from 'node:path'
|
||||
import { file } from '@aklive2d/libs'
|
||||
import config from '@aklive2d/config'
|
||||
import type {
|
||||
OfficialArray,
|
||||
OfficialInfo,
|
||||
OfficialOperatorInfo,
|
||||
OfficialInfoMapping,
|
||||
OfficialInfoOperatorConfig,
|
||||
} from './types'
|
||||
|
||||
const AUTO_UPDATE_FOLDER = path.resolve(
|
||||
import.meta.dirname,
|
||||
@@ -18,22 +25,24 @@ export const update = async () => {
|
||||
|
||||
const dom = new jsdom.JSDOM(html_text)
|
||||
const scripts = dom.window.document.body.querySelectorAll('script')
|
||||
let data
|
||||
let data: OfficialArray | null = null
|
||||
scripts.forEach((e) => {
|
||||
if (e.textContent.includes('干员晋升')) {
|
||||
if (e.textContent?.includes('干员晋升')) {
|
||||
data = JSON.parse(
|
||||
e.textContent
|
||||
.replace('self.__next_f.push([1,"c:', '')
|
||||
.replace('\\n"])', '')
|
||||
.replaceAll('\\', '')
|
||||
)
|
||||
) as OfficialArray
|
||||
}
|
||||
})
|
||||
const rows = data[0][3].initialData
|
||||
if (!data) throw new Error('No data found')
|
||||
const rows = (data as OfficialArray)[0][3].initialData
|
||||
|
||||
const dict = {
|
||||
const dict: OfficialInfo = {
|
||||
length: rows.length,
|
||||
dates: [],
|
||||
info: {},
|
||||
}
|
||||
|
||||
let current_displayTime = rows[0].displayTime
|
||||
@@ -42,22 +51,22 @@ export const update = async () => {
|
||||
for (const row of rows) {
|
||||
const displayTime = row.displayTime
|
||||
if (displayTime !== current_displayTime) {
|
||||
dict[current_displayTime] = current_block
|
||||
dict.info[current_displayTime] = current_block
|
||||
dict.dates.push(current_displayTime)
|
||||
current_displayTime = row.displayTime
|
||||
current_block = []
|
||||
}
|
||||
current_block.push(get_row(row))
|
||||
}
|
||||
dict[current_displayTime] = current_block
|
||||
dict.info[current_displayTime] = current_block
|
||||
dict.dates.push(current_displayTime)
|
||||
|
||||
file.writeSync(JSON.stringify(dict, null, 4), OFFICIAL_INFO_JSON)
|
||||
}
|
||||
|
||||
const get_row = (row) => {
|
||||
const get_row = (row: OfficialOperatorInfo): OfficialInfoOperatorConfig => {
|
||||
const type = row.type
|
||||
let codename_zhCN, item_type
|
||||
let codename_zhCN, item_type: 'operator' | 'skin'
|
||||
switch (type) {
|
||||
case 0:
|
||||
codename_zhCN = row.charName
|
||||
@@ -82,18 +91,18 @@ const get_row = (row) => {
|
||||
}
|
||||
|
||||
const generateMapping = () => {
|
||||
const mapping = {}
|
||||
const data = JSON.parse(file.readSync(OFFICIAL_INFO_JSON))
|
||||
if (!data) return
|
||||
Object.keys(data).forEach((key) => {
|
||||
if (typeof data[key] === 'object') {
|
||||
data[key].forEach((operator) => {
|
||||
mapping[operator.id] = {
|
||||
date: key,
|
||||
...operator,
|
||||
}
|
||||
})
|
||||
}
|
||||
const mapping: OfficialInfoMapping = {}
|
||||
const content = file.readSync(OFFICIAL_INFO_JSON)
|
||||
if (!content) throw new Error('Failed to read official info JSON')
|
||||
const data: OfficialInfo = JSON.parse(content)
|
||||
if (!data) throw new Error('Failed to parse official info JSON')
|
||||
Object.keys(data.info).forEach((date) => {
|
||||
data.info[date].forEach((operator) => {
|
||||
mapping[operator.id] = {
|
||||
date,
|
||||
...operator,
|
||||
}
|
||||
})
|
||||
})
|
||||
return mapping
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/official-info",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"jsdom": "^26.0.0",
|
||||
@@ -11,8 +11,13 @@
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"update": "mode=update node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check ."
|
||||
"update": "mode=update bun runner.ts",
|
||||
"lint": "eslint && prettier --check ."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { envParser } from '@aklive2d/libs'
|
||||
import { update } from './index.js'
|
||||
import { update } from './index.ts'
|
||||
|
||||
async function main() {
|
||||
const { mode } = envParser.parse({
|
||||
25
packages/official-info/tsconfig.json
Normal file
25
packages/official-info/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
48
packages/official-info/types.ts
Normal file
48
packages/official-info/types.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
export type OfficialOperatorInfo = {
|
||||
cid: string
|
||||
charName: string
|
||||
suitName: string
|
||||
codename: string
|
||||
type: number
|
||||
displayTime: string
|
||||
portraitSrc: string
|
||||
}
|
||||
|
||||
export type OfficialDataArray = [
|
||||
'$',
|
||||
string,
|
||||
null,
|
||||
{
|
||||
initialData: OfficialOperatorInfo[]
|
||||
},
|
||||
]
|
||||
|
||||
type UnrelatedDataArray = ['$', string, null, unknown]
|
||||
|
||||
export type OfficialArray = [OfficialDataArray, UnrelatedDataArray]
|
||||
|
||||
export type OfficialInfo = {
|
||||
length: number
|
||||
dates: string[]
|
||||
info: {
|
||||
[date: string]: OfficialInfoOperatorConfig[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface OfficialInfoOperatorConfig {
|
||||
codename: {
|
||||
'zh-CN': string
|
||||
'en-US': string
|
||||
}
|
||||
type: 'operator' | 'skin'
|
||||
link: string
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface OperatorConfig extends OfficialInfoOperatorConfig {
|
||||
date: string
|
||||
}
|
||||
|
||||
export type OfficialInfoMapping = {
|
||||
[id: string]: OperatorConfig
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
dist
|
||||
data
|
||||
auto_update
|
||||
auto_update
|
||||
config
|
||||
config.yaml
|
||||
|
||||
@@ -61,3 +61,7 @@ yu: !include config/yu.yaml
|
||||
logos_radiant_serenity: !include config/logos_radiant_serenity.yaml
|
||||
muelsyse_golden_reverie: !include config/muelsyse_golden_reverie.yaml
|
||||
ines_melodic_flutter: !include config/ines_melodic_flutter.yaml
|
||||
wisadel_supernova: !include config/wisadel_supernova.yaml
|
||||
archetto_glory_of_the_devout: !include config/archetto_glory_of_the_devout.yaml
|
||||
kroos_moonlit_voyage: !include config/kroos_moonlit_voyage.yaml
|
||||
exusiai_the_new_covenant: !include config/exusiai_the_new_covenant.yaml
|
||||
|
||||
13
packages/operator/config/archetto_glory_of_the_devout.yaml
Normal file
13
packages/operator/config/archetto_glory_of_the_devout.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
filename: dyn_illust_char_332_archet_sale#14
|
||||
logo: logo_Laterano
|
||||
fallback_name: char_332_archet_sale#14
|
||||
viewport_left: 0
|
||||
viewport_right: 0
|
||||
viewport_top: 0
|
||||
viewport_bottom: 0
|
||||
invert_filter: true
|
||||
codename:
|
||||
zh-CN: 至虔者荣光 · 空弦
|
||||
en-US: Glory of the Devout / Archetto
|
||||
use_json: false
|
||||
official_id: '202504953'
|
||||
13
packages/operator/config/exusiai_the_new_covenant.yaml
Normal file
13
packages/operator/config/exusiai_the_new_covenant.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
filename: dyn_illust_char_1041_angel2
|
||||
logo: logo_penguin
|
||||
fallback_name: char_1041_angel2_2
|
||||
viewport_left: 0
|
||||
viewport_right: 0
|
||||
viewport_top: 0
|
||||
viewport_bottom: 0
|
||||
invert_filter: true
|
||||
codename:
|
||||
zh-CN: 新约能天使
|
||||
en-US: Exusiai the New Covenant
|
||||
use_json: false
|
||||
official_id: '202504941'
|
||||
13
packages/operator/config/kroos_moonlit_voyage.yaml
Normal file
13
packages/operator/config/kroos_moonlit_voyage.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
filename: dyn_illust_char_124_kroos_sale#14
|
||||
logo: logo_reserve1
|
||||
fallback_name: char_124_kroos_sale#14
|
||||
viewport_left: 0
|
||||
viewport_right: 0
|
||||
viewport_top: 0
|
||||
viewport_bottom: 0
|
||||
invert_filter: true
|
||||
codename:
|
||||
zh-CN: 星月漂流记 · 克洛丝
|
||||
en-US: Moonlit Voyage / Kroos
|
||||
use_json: false
|
||||
official_id: '202504992'
|
||||
13
packages/operator/config/wisadel_supernova.yaml
Normal file
13
packages/operator/config/wisadel_supernova.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
filename: dyn_illust_char_1035_wisdel_sale#14
|
||||
logo: logo_babel
|
||||
fallback_name: char_1035_wisdel_sale#14
|
||||
viewport_left: 0
|
||||
viewport_right: 0
|
||||
viewport_top: 0
|
||||
viewport_bottom: 0
|
||||
invert_filter: true
|
||||
codename:
|
||||
zh-CN: 超新星 · 维什戴尔
|
||||
en-US: Supernova / Wisadel
|
||||
use_json: false
|
||||
official_id: '202504974'
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3,19 +3,20 @@ import { stringify } from 'yaml'
|
||||
import { yaml, file, alphaComposite } from '@aklive2d/libs'
|
||||
import config from '@aklive2d/config'
|
||||
import { mapping as officialInfoMapping } from '@aklive2d/official-info'
|
||||
import type { Config, PortraitHub, PortraitJson, AssetsJson } from './types.ts'
|
||||
|
||||
export const CONFIG_PATH = path.resolve(
|
||||
import.meta.dirname,
|
||||
config.module.operator.config_yaml
|
||||
)
|
||||
const CONFIG = yaml.read(CONFIG_PATH)
|
||||
const CONFIG: Config = yaml.read(CONFIG_PATH)
|
||||
export const OPERATOR_SOURCE_FOLDER = path.resolve(
|
||||
import.meta.dirname,
|
||||
config.dir_name.data
|
||||
)
|
||||
const DIST_DIR = path.join(import.meta.dirname, config.dir_name.dist)
|
||||
|
||||
const getVoiceFolders = (name) => {
|
||||
const getVoiceFolders = (name: string) => {
|
||||
return config.dir_name.voice.sub.map((sub) =>
|
||||
path.join(
|
||||
OPERATOR_SOURCE_FOLDER,
|
||||
@@ -26,7 +27,7 @@ const getVoiceFolders = (name) => {
|
||||
)
|
||||
}
|
||||
|
||||
const getExtractedFolder = (name) => {
|
||||
const getExtractedFolder = (name: string) => {
|
||||
return path.join(OPERATOR_SOURCE_FOLDER, name, config.dir_name.extracted)
|
||||
}
|
||||
|
||||
@@ -34,11 +35,11 @@ const getConfigFolder = () => {
|
||||
return path.join(import.meta.dirname, config.module.operator.config)
|
||||
}
|
||||
|
||||
const getDistFolder = (name) => {
|
||||
const getDistFolder = (name: string) => {
|
||||
return path.join(DIST_DIR, config.module.operator.operator, name)
|
||||
}
|
||||
|
||||
export const has = (name) => {
|
||||
export const has = (name: string) => {
|
||||
return Object.keys(operators).includes(name)
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ const generateMapping = () => {
|
||||
return CONFIG
|
||||
}
|
||||
|
||||
const copyVoices = (name) => {
|
||||
const copyVoices = (name: string) => {
|
||||
file.symlinkAll(
|
||||
path.join(OPERATOR_SOURCE_FOLDER, name, config.dir_name.voice.main),
|
||||
path.join(DIST_DIR, config.dir_name.voice.main, name)
|
||||
@@ -85,15 +86,15 @@ const operators = generateMapping()
|
||||
|
||||
export default operators
|
||||
|
||||
export function getOperatorId(name, matcher = '$2$3$4') {
|
||||
export function getOperatorId(name: string, matcher = '$2$3$4') {
|
||||
return name.replace(/^(.*)(char_[\d]+)(_[A-Za-z0-9]+)(|_.*)$/g, matcher)
|
||||
}
|
||||
|
||||
export const getOperatorAlternativeId = (id) => {
|
||||
export const getOperatorAlternativeId = (id: string) => {
|
||||
return getOperatorId(id, '$2$3')
|
||||
}
|
||||
|
||||
export const build = async (namesToBuild) => {
|
||||
export const build = async (namesToBuild: string[]) => {
|
||||
const names = !namesToBuild.length ? Object.keys(operators) : namesToBuild
|
||||
console.log('Generating assets for', names.length, 'operators')
|
||||
for (const name of names) {
|
||||
@@ -103,7 +104,7 @@ export const build = async (namesToBuild) => {
|
||||
copyLogos()
|
||||
}
|
||||
|
||||
const generateAssets = async (name) => {
|
||||
const generateAssets = async (name: string) => {
|
||||
const extractedDir = getExtractedFolder(name)
|
||||
const outDir = getDistFolder(name)
|
||||
file.rmdir(outDir)
|
||||
@@ -134,31 +135,35 @@ const generateAssets = async (name) => {
|
||||
OPERATOR_SOURCE_FOLDER,
|
||||
config.module.operator.portraits
|
||||
)
|
||||
const portraitHub = JSON.parse(
|
||||
file.readSync(
|
||||
path.join(
|
||||
portraitDir,
|
||||
config.module.operator.MonoBehaviour,
|
||||
'portrait_hub.json'
|
||||
)
|
||||
const portraitHubContent = file.readSync(
|
||||
path.join(
|
||||
portraitDir,
|
||||
config.module.operator.MonoBehaviour,
|
||||
'portrait_hub.json'
|
||||
)
|
||||
)
|
||||
if (!portraitHubContent) throw new Error('portrait_hub.json not found')
|
||||
const portraitHub: PortraitHub = JSON.parse(portraitHubContent)
|
||||
const fallback_name_lowerCase = fallback_name.toLowerCase()
|
||||
const portraitAtlas = portraitHub._sprites.find(
|
||||
const portraitItem = portraitHub._sprites.find(
|
||||
(item) => item.name.toLowerCase() === fallback_name_lowerCase
|
||||
).atlas
|
||||
const portraitJson = JSON.parse(
|
||||
file.readSync(
|
||||
path.join(
|
||||
portraitDir,
|
||||
config.module.operator.MonoBehaviour,
|
||||
`portraits#${portraitAtlas}.json`
|
||||
)
|
||||
)
|
||||
if (!portraitItem) throw new Error(`portrait ${fallback_name} not found`)
|
||||
const portraitAtlas = portraitItem.atlas
|
||||
const portraitJsonText = file.readSync(
|
||||
path.join(
|
||||
portraitDir,
|
||||
config.module.operator.MonoBehaviour,
|
||||
`portraits#${portraitAtlas}.json`
|
||||
)
|
||||
)
|
||||
if (!portraitJsonText)
|
||||
throw new Error(`portrait ${fallback_name} json not found`)
|
||||
const portraitJson: PortraitJson = JSON.parse(portraitJsonText)
|
||||
const item = portraitJson._sprites.find(
|
||||
(item) => item.name.toLowerCase() === fallback_name_lowerCase
|
||||
)
|
||||
if (!item) throw new Error(`portrait ${fallback_name} not found`)
|
||||
const rect = {
|
||||
...item.rect,
|
||||
rotate: item.rotate,
|
||||
@@ -186,15 +191,18 @@ const generateAssets = async (name) => {
|
||||
}
|
||||
|
||||
export const generateAssetsJson = async (
|
||||
filename,
|
||||
extractedDir,
|
||||
targetDir,
|
||||
_opts = {
|
||||
filename: string,
|
||||
extractedDir: string,
|
||||
targetDir: string,
|
||||
_opts: {
|
||||
useJSON?: boolean
|
||||
useSymLink?: boolean
|
||||
} = {
|
||||
useJSON: false,
|
||||
useSymLink: true,
|
||||
}
|
||||
) => {
|
||||
const assetsJson = []
|
||||
const assetsJson: AssetsJson = []
|
||||
|
||||
let skelFilename
|
||||
if (_opts.useJSON) {
|
||||
@@ -206,6 +214,8 @@ export const generateAssetsJson = async (
|
||||
const atlasPath = path.join(extractedDir, atlasFilename)
|
||||
let atlas = await file.read(atlasPath)
|
||||
const matches = atlas.match(new RegExp(/(.*).png/g))
|
||||
if (!matches)
|
||||
throw new Error(`No matches found in atlas file ${atlasFilename}`)
|
||||
for (const item of matches) {
|
||||
let buffer
|
||||
const alphaCompositeFilename = `${path.parse(item).name}[alpha].png`
|
||||
@@ -236,17 +246,19 @@ export const generateAssetsJson = async (
|
||||
const dir = path.join(targetDir, item.filename)
|
||||
if (item.content) {
|
||||
file.writeSync(item.content, dir)
|
||||
} else {
|
||||
} else if (item.path) {
|
||||
if (_opts.useSymLink) {
|
||||
file.symlink(item.path, dir)
|
||||
} else {
|
||||
file.cpSync(item.path, dir)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Invalid asset item: ${item}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const init = (name, id) => {
|
||||
export const init = (name: string, id: string) => {
|
||||
const voiceFolders = getVoiceFolders(name)
|
||||
const extractedFolder = getExtractedFolder(name)
|
||||
const operatorConfigFolder = getConfigFolder()
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@aklive2d/operator",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"yaml": "^2.7.0",
|
||||
@@ -12,10 +12,15 @@
|
||||
"@aklive2d/eslint-config": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "mode=build node runner.js",
|
||||
"init": "mode=init node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check .",
|
||||
"build": "mode=build bun runner.ts",
|
||||
"init": "mode=init bun runner.ts",
|
||||
"lint": "eslint && prettier --check .",
|
||||
"build:cleanup": "rm -rf ./dist ./data"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { envParser } from '@aklive2d/libs'
|
||||
import { build, init } from './index.js'
|
||||
import { build, init } from './index.ts'
|
||||
|
||||
type Args = {
|
||||
mode: string
|
||||
name: string[]
|
||||
id: string
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { mode, name, id } = envParser.parse({
|
||||
@@ -16,7 +22,7 @@ async function main() {
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
})
|
||||
}) as Args
|
||||
switch (mode) {
|
||||
case 'build':
|
||||
await build(name)
|
||||
25
packages/operator/tsconfig.json
Normal file
25
packages/operator/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
93
packages/operator/types.ts
Normal file
93
packages/operator/types.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
export type Codename = { 'zh-CN': string; 'en-US': string }
|
||||
|
||||
export interface OperatorConfig {
|
||||
filename: string
|
||||
logo: string
|
||||
fallback_name: string
|
||||
viewport_left: number
|
||||
viewport_right: number
|
||||
viewport_top: number
|
||||
viewport_bottom: number
|
||||
invert_filter: boolean
|
||||
codename: Codename
|
||||
use_json: boolean
|
||||
official_id: string
|
||||
title: string
|
||||
type: 'operator' | 'skin'
|
||||
link: string
|
||||
id: string
|
||||
date: string
|
||||
}
|
||||
|
||||
export type Config = {
|
||||
[name: string]: OperatorConfig
|
||||
}
|
||||
|
||||
type FileIDPathID = {
|
||||
m_FileID: number
|
||||
m_PathID: number
|
||||
}
|
||||
|
||||
export type PortraitHub = {
|
||||
m_GameObject: FileIDPathID
|
||||
m_Enabled: number
|
||||
m_Script: FileIDPathID
|
||||
m_Name: string
|
||||
_sprites: {
|
||||
name: string
|
||||
atlas: number
|
||||
}[]
|
||||
_atlases: string[]
|
||||
_inputSpriteDir: string
|
||||
_outputAtlasDir: string
|
||||
_rootAtlasName: string
|
||||
_spriteSize: {
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
_cntPerAtlas: number
|
||||
_maxAtlasSize: number
|
||||
}
|
||||
|
||||
type SignedItem = {
|
||||
name: string
|
||||
guid: string
|
||||
md5: string
|
||||
}
|
||||
|
||||
export type PortraitJson = {
|
||||
m_GameObject: FileIDPathID
|
||||
m_Enabled: number
|
||||
m_Script: FileIDPathID
|
||||
m_Name: string
|
||||
_sprites: {
|
||||
name: string
|
||||
guid: string
|
||||
atlas: number
|
||||
rect: {
|
||||
x: number
|
||||
y: number
|
||||
w: number
|
||||
h: number
|
||||
}
|
||||
rotate: number
|
||||
}[]
|
||||
_atlas: {
|
||||
index: number
|
||||
texture: FileIDPathID
|
||||
alpha: FileIDPathID
|
||||
size: number
|
||||
}
|
||||
_index: number
|
||||
_sign: {
|
||||
m_sprites: SignedItem[]
|
||||
m_atlases: SignedItem[]
|
||||
m_alphas: SignedItem[]
|
||||
}
|
||||
}
|
||||
|
||||
export type AssetsJson = {
|
||||
filename: string
|
||||
path?: string
|
||||
content?: string | Buffer<ArrayBufferLike> | Buffer
|
||||
}[]
|
||||
@@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@aklive2d/postcss-config",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"postcss": "^8.5.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
"name": "@aklive2d/postcss-config",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"postcss": "^8.5.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
// prettier.config.js, .prettierrc.js, prettier.config.mjs, or .prettierrc.mjs
|
||||
|
||||
/**
|
||||
* @see https://prettier.io/docs/en/configuration.html
|
||||
* @type {import("prettier").Config}
|
||||
*/
|
||||
const config = {
|
||||
trailingComma: "es5",
|
||||
trailingComma: 'es5',
|
||||
tabWidth: 4,
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
};
|
||||
}
|
||||
|
||||
export default config;
|
||||
export default config
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "@aklive2d/prettier-config",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"peerDependencies": {
|
||||
"prettier": ">=3.0.0"
|
||||
}
|
||||
"name": "@aklive2d/prettier-config",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"peerDependencies": {
|
||||
"prettier": ">=3.0.0",
|
||||
"typescript": ">=5.8.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,27 @@
|
||||
import baseConfig from '@aklive2d/eslint-config'
|
||||
import { tsConfig } from '@aklive2d/eslint-config'
|
||||
import tseslint from 'typescript-eslint'
|
||||
import globals from 'globals'
|
||||
|
||||
/** @type {import('eslint').Config} */
|
||||
export default [...baseConfig]
|
||||
export default tseslint.config(
|
||||
...tsConfig,
|
||||
{
|
||||
ignores: ['dist', 'data'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.js', '**/*.ts'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2022,
|
||||
globals: {
|
||||
...globals.node,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{ argsIgnorePattern: '^_' },
|
||||
],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import path from 'node:path'
|
||||
import Matcher from './libs/content_processor.js'
|
||||
import Matcher from './libs/content_processor.ts'
|
||||
import { yaml, file } from '@aklive2d/libs'
|
||||
import config from '@aklive2d/config'
|
||||
import operators, { OPERATOR_SOURCE_FOLDER } from '@aklive2d/operator'
|
||||
import { files as backgrounds } from '@aklive2d/background'
|
||||
import { mapping as musics } from '@aklive2d/music'
|
||||
import { getLangs } from '@aklive2d/charword-table'
|
||||
import type { ScalarTag } from 'yaml'
|
||||
import type {
|
||||
Assets,
|
||||
TemplateYAML,
|
||||
ProjectJSON,
|
||||
ProjectJSONProperty,
|
||||
} from './types.ts'
|
||||
|
||||
const DIST_DIR = path.join(import.meta.dirname, config.dir_name.dist)
|
||||
|
||||
export const build = (namesToBuild) => {
|
||||
export const build = (namesToBuild: string[]) => {
|
||||
const err = []
|
||||
const names = !namesToBuild.length ? Object.keys(operators) : namesToBuild
|
||||
console.log('Generating assets for', names.length, 'operators')
|
||||
@@ -43,15 +50,15 @@ export const build = (namesToBuild) => {
|
||||
return err
|
||||
}
|
||||
|
||||
const getDistDir = (name) => {
|
||||
const getDistDir = (name: string) => {
|
||||
return path.join(DIST_DIR, name)
|
||||
}
|
||||
|
||||
const getDefaultPath = (name) => {
|
||||
const getDefaultPath = (name: string) => {
|
||||
return path.join(OPERATOR_SOURCE_FOLDER, name)
|
||||
}
|
||||
|
||||
const getPath = (name) => {
|
||||
const getPath = (name: string) => {
|
||||
// if exists, do not use the template
|
||||
const defaultPath = path.join(
|
||||
getDefaultPath(name),
|
||||
@@ -67,7 +74,15 @@ const getPath = (name) => {
|
||||
}
|
||||
}
|
||||
|
||||
const process = ({ name, data, template }) => {
|
||||
const process = ({
|
||||
name,
|
||||
data,
|
||||
template,
|
||||
}: {
|
||||
name: string
|
||||
data: ProjectJSON
|
||||
template: TemplateYAML
|
||||
}) => {
|
||||
return {
|
||||
...data,
|
||||
description: template.description,
|
||||
@@ -79,12 +94,14 @@ const process = ({ name, data, template }) => {
|
||||
...getProperties(template),
|
||||
},
|
||||
},
|
||||
}
|
||||
} as ProjectJSON
|
||||
}
|
||||
|
||||
const getProperties = (template) => {
|
||||
const getProperties = (template: TemplateYAML) => {
|
||||
const properties = template.properties
|
||||
const output = {}
|
||||
const output = {} as {
|
||||
[key: string]: ProjectJSONProperty
|
||||
}
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
output[properties[i].key] = {
|
||||
index: i,
|
||||
@@ -95,13 +112,15 @@ const getProperties = (template) => {
|
||||
return output
|
||||
}
|
||||
|
||||
const load = async (name, assets) => {
|
||||
const load = async (name: string, assets: Assets) => {
|
||||
// load json from file
|
||||
let data = JSON.parse(await file.read(getPath(name)))
|
||||
let data = JSON.parse(await file.read(getPath(name))) as ProjectJSON
|
||||
const matcher = new Matcher('~{', '}', operators[name], {
|
||||
...assets,
|
||||
...(() => {
|
||||
const output = {}
|
||||
const output = {} as {
|
||||
[key: string]: { label: string; value: string }[]
|
||||
}
|
||||
for (const [key, value] of Object.entries(assets)) {
|
||||
output[`${key}Options`] = value.map((b) => {
|
||||
return {
|
||||
@@ -114,20 +133,21 @@ const load = async (name, assets) => {
|
||||
})(),
|
||||
})
|
||||
const match = {
|
||||
identify: (value) => value.startsWith('!match'),
|
||||
identify: (value: unknown) =>
|
||||
typeof value === 'string' && value.startsWith('!match'),
|
||||
tag: '!match',
|
||||
resolve(str) {
|
||||
resolve(str: string) {
|
||||
matcher.content = str
|
||||
return matcher.result
|
||||
},
|
||||
}
|
||||
} as ScalarTag
|
||||
const template = yaml.read(
|
||||
path.resolve(
|
||||
import.meta.dirname,
|
||||
config.module.project_json.template_yaml
|
||||
),
|
||||
[match]
|
||||
)
|
||||
) as TemplateYAML
|
||||
data = process({
|
||||
name,
|
||||
data,
|
||||
@@ -1,11 +1,20 @@
|
||||
import type { OperatorConfig, Codename } from '@aklive2d/operator/types'
|
||||
import type { Assets } from '../types.ts'
|
||||
|
||||
export default class Matcher {
|
||||
#start
|
||||
#end
|
||||
#reExp
|
||||
#config
|
||||
#assets
|
||||
content: string = ''
|
||||
|
||||
constructor(start, end, config, assets) {
|
||||
constructor(
|
||||
start: string,
|
||||
end: string,
|
||||
config: OperatorConfig,
|
||||
assets: Assets
|
||||
) {
|
||||
this.#start = start
|
||||
this.#end = end
|
||||
this.#reExp = new RegExp(`${start}.+?${end}`, 'g')
|
||||
@@ -40,27 +49,50 @@ class Evalable {
|
||||
#config
|
||||
#assets
|
||||
|
||||
constructor(config, assets) {
|
||||
constructor(config: OperatorConfig, assets: Assets) {
|
||||
this.#config = config
|
||||
this.#assets = assets
|
||||
}
|
||||
|
||||
split(location, varName, separator) {
|
||||
return this.#step(location, varName).split(separator)
|
||||
split(location: 'config' | 'assets', varName: string, separator: string) {
|
||||
return (this.#step(location, varName) as string).split(separator)
|
||||
}
|
||||
|
||||
var(location, varName) {
|
||||
var(location: 'config' | 'assets', varName: string) {
|
||||
return this.#step(location, varName)
|
||||
}
|
||||
|
||||
#step(location, varName) {
|
||||
let content = this.#config
|
||||
#step(
|
||||
location: 'config' | 'assets',
|
||||
varName: string
|
||||
):
|
||||
| OperatorConfig
|
||||
| Assets
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| Codename
|
||||
| string[] {
|
||||
let content:
|
||||
| OperatorConfig
|
||||
| Assets
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| Codename
|
||||
| string[] = this.#config
|
||||
if (location === 'assets') content = this.#assets
|
||||
varName.split('->').forEach((item) => {
|
||||
try {
|
||||
content = content[item]
|
||||
} catch (e) {
|
||||
throw new Error(`Cannot step ${varName}.`, e)
|
||||
if (location === 'config') {
|
||||
content = (content as OperatorConfig)[
|
||||
item as keyof OperatorConfig
|
||||
]
|
||||
} else {
|
||||
content = (content as Assets)[item as keyof Assets]
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
throw new Error(`Cannot step ${varName}. ${e}`)
|
||||
}
|
||||
})
|
||||
return content
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@aklive2d/project-json",
|
||||
"version": "0.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.ts",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -14,8 +14,13 @@
|
||||
"@aklive2d/music": "workspace:*",
|
||||
"@aklive2d/prettier-config": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"globals": ">=16.0.0",
|
||||
"typescript-eslint": ">=8.31.1",
|
||||
"typescript": ">=5.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "mode=build node runner.js",
|
||||
"lint": "eslint \"*.js\" \"**/*.js\" && prettier --check ."
|
||||
"build": "mode=build bun runner.ts",
|
||||
"lint": "eslint && prettier --check ."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ async function main() {
|
||||
multiple: true,
|
||||
default: [],
|
||||
},
|
||||
})
|
||||
}) as { mode: string; name: string[] }
|
||||
switch (mode) {
|
||||
case 'build':
|
||||
err = build(name)
|
||||
25
packages/project-json/tsconfig.json
Normal file
25
packages/project-json/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2024", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["**/*"],
|
||||
"exclude": ["dist/**/*", "data/**/*"]
|
||||
}
|
||||
66
packages/project-json/types.ts
Normal file
66
packages/project-json/types.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
export type Assets = {
|
||||
backgrounds: string[]
|
||||
voiceLangs: string[]
|
||||
subtitleLangs: string[]
|
||||
music: string[]
|
||||
}
|
||||
|
||||
export interface Property {
|
||||
text: string
|
||||
type?: 'bool' | 'file' | 'slider' | 'combo' | 'textinput'
|
||||
value?: boolean | string
|
||||
condition?: string
|
||||
fraction?: boolean
|
||||
max?: number
|
||||
min?: number
|
||||
step?: number
|
||||
precision?: number
|
||||
options?: string[]
|
||||
fileType?: 'video'
|
||||
}
|
||||
|
||||
export interface ProjectJSONProperty extends Property {
|
||||
index: number
|
||||
order: number
|
||||
}
|
||||
|
||||
interface Template {
|
||||
description: string
|
||||
localization: {
|
||||
'en-us': Record<string, string>
|
||||
'zh-chs': Record<string, string>
|
||||
}
|
||||
}
|
||||
|
||||
export interface TemplateYAML extends Template {
|
||||
properties: {
|
||||
key: string
|
||||
value: Property
|
||||
}[]
|
||||
}
|
||||
|
||||
interface TemplateJSON extends Template {
|
||||
properties: {
|
||||
[key: string]: ProjectJSONProperty
|
||||
}
|
||||
}
|
||||
|
||||
export interface ProjectJSONBase {
|
||||
contentrating: string
|
||||
description: string
|
||||
file: string
|
||||
preview: string
|
||||
ratingsex: string
|
||||
ratingviolence: string
|
||||
snapshotformat: number
|
||||
snapshotoverlay: string
|
||||
tags: string[]
|
||||
title: string
|
||||
type: string
|
||||
version: number
|
||||
workshopid: string
|
||||
}
|
||||
|
||||
export interface ProjectJSON extends ProjectJSONBase {
|
||||
general: TemplateJSON
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"name": "@aklive2d/stylelint-config",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"stylelint-config-standard-scss": "^14.0.0",
|
||||
"stylelint-prettier": "^5.0.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
"name": "@aklive2d/stylelint-config",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"stylelint-config-standard-scss": "^14.0.0",
|
||||
"stylelint-prettier": "^5.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user