feat(aklive2d): use cf pages to store assets (upload) [1/2]

This commit is contained in:
Haoyu Xu
2024-08-14 17:29:42 +08:00
parent 4e4f6ada50
commit 0a7ef8531a
26 changed files with 1010 additions and 107 deletions

View File

@@ -1,4 +0,0 @@
**/*
!.git
!CNAME
!.nojekyll

View File

@@ -16,9 +16,9 @@ jobs:
- name: Install dependencies
run: pnpm i
- name: Build all
run: pnpm run build-all
run: pnpm run operator:build-all
- name: Build directory
run: pnpm run vite:directory:build
run: pnpm run directory:build
- name: Publish to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:

View File

@@ -22,8 +22,6 @@ jobs:
run: pnpm i
- name: Update charwords
run: pnpm run charwords:update
- name: Build operator charwords
run: pnpm run charwords:build
- name: Commit changes if any
uses: stefanzweifel/git-auto-commit-action@v4
with:

2
.gitignore vendored
View File

@@ -138,3 +138,5 @@ _*.json
*_v2/*
assets/*
temp/*
operator/*
data/operator/*

9
.vscode/launch.json vendored
View File

@@ -25,7 +25,7 @@
"type": "node-terminal",
"name": "Run Script: build-all",
"request": "launch",
"command": "pnpm run build-all",
"command": "pnpm run operator:build-all",
"cwd": "${workspaceFolder}"
},
{
@@ -76,6 +76,13 @@
"request": "launch",
"command": "pnpm run offical_update",
"cwd": "${workspaceFolder}"
},
{
"type": "node-terminal",
"name": "Run Script: cf:upload",
"request": "launch",
"command": "pnpm run cf:upload",
"cwd": "${workspaceFolder}"
}
]
}

View File

@@ -7,7 +7,7 @@ import { fork } from 'child_process';
import getConfig from './libs/config.js'
import ProjectJson from './libs/project_json.js'
import EnvGenerator from './libs/env_generator.js'
import { write, rmdir, copy, writeSync, copyDir, readdirSync, exists } from './libs/file.js'
import { write, rmdir, copy, writeSync, copyDir, readdirSync, exists, mkdir } from './libs/file.js'
import AssetsProcessor from './libs/assets_processor.js'
import init from './libs/initializer.js'
import directory from './libs/directory.js'
@@ -15,14 +15,18 @@ import Background from './libs/background.js'
import CharwordTable from './libs/charword_table.js';
import Music from './libs/music.js';
import OfficalInfo from './libs/offical_info.js';
import CFPages from './libs/cf_pages.js';
async function main() {
global.__projectRoot = path.dirname(fileURLToPath(import.meta.url))
const officalInfo = new OfficalInfo()
global.__config = getConfig(officalInfo)
global.__error = []
const OPERATOR_SOURCE_FOLDER = path.join(__projectRoot, __config.folder.operator)
const OPERATOR_SOURCE_DATA_FOLDER = path.join(__projectRoot, __config.folder.operator_data)
const OPERATOR_SHARE_FOLDER = path.join(OPERATOR_SOURCE_DATA_FOLDER, __config.folder.share)
const op = process.argv[2]
let OPERATOR_NAMES = process.argv.slice(3);
@@ -35,17 +39,12 @@ async function main() {
* directory: build directory
*/
switch (op) {
case 'directory':
assert(OPERATOR_NAMES.length !== 0, 'Please set a mode for Directory.')
fork(path.join(__projectRoot, 'vite.config.js'), [op, OPERATOR_NAMES])
return
case 'build-all':
case 'charwords:build':
case 'operator:build-all':
for (const [key,] of Object.entries(__config.operators)) {
OPERATOR_NAMES.push(key)
}
break
case 'preview':
case 'operator:preview':
assert(OPERATOR_NAMES.length !== 0, 'Please set the operator name.')
fork(path.join(__projectRoot, 'vite.config.js'), [op, OPERATOR_NAMES])
return
@@ -58,16 +57,22 @@ async function main() {
case 'offical_update':
await officalInfo.update()
process.exit(0)
case 'cf:upload':
(new CFPages()).upload()
process.exit(0)
case 'cf:download':
(new CFPages()).download()
process.exit(0)
default:
break
}
assert(OPERATOR_NAMES.length !== 0, 'Please set the operator name.')
const background = new Background()
const background = new Background(OPERATOR_SHARE_FOLDER, OPERATOR_SOURCE_FOLDER)
await background.process()
const backgrounds = ['operator_bg.png', ...background.files]
const { musicToCopy, musicMapping } = musicTable.copy()
const { musicToCopy, musicMapping } = musicTable.copy(OPERATOR_SHARE_FOLDER)
for (const e of musicToCopy) {
const musicPath = path.join(e.source, e.filename)
@@ -83,12 +88,10 @@ async function main() {
}
for (const OPERATOR_NAME of OPERATOR_NAMES) {
const OPERATOR_SOURCE_FOLDER = path.join(__projectRoot, __config.folder.operator)
const OPERATOR_RELEASE_FOLDER = path.join(__projectRoot, __config.folder.release, OPERATOR_NAME)
const SHOWCASE_PUBLIC_ASSSETS_FOLDER = path.join(OPERATOR_RELEASE_FOLDER, "assets")
const EXTRACTED_FOLDER = path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, 'extracted')
const VOICE_FOLDERS = __config.folder.voice.sub.map((sub) => path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, __config.folder.voice.main, sub.name))
const OPERATOR_SHARE_FOLDER = path.join(OPERATOR_SOURCE_FOLDER, __config.folder.share)
const EXTRACTED_FOLDER = path.join(OPERATOR_SOURCE_DATA_FOLDER, OPERATOR_NAME, 'extracted')
const VOICE_FOLDERS = __config.folder.voice.sub.map((sub) => path.join(OPERATOR_SOURCE_DATA_FOLDER, OPERATOR_NAME, __config.folder.voice.main, sub.name))
/**
* Skip assets generation part
@@ -104,6 +107,7 @@ async function main() {
}
rmdir(OPERATOR_RELEASE_FOLDER)
mkdir(path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME))
const charwordTableLookup = charwordTable.lookup(OPERATOR_NAME)
const voiceJson = {}
@@ -143,13 +147,6 @@ async function main() {
console.log(`charword_table is not available`)
}
switch (op) {
case 'charwords:build':
continue
default:
break
}
// check whether voice files has been added
const customVoiceName = voiceLangs.filter(i => !__config.folder.voice.sub.map(e => e.lang).includes(i))[0]
const voiceLangMapping = __config.folder.voice.sub.filter(e => {
@@ -161,7 +158,7 @@ async function main() {
}
})
for (const voiceSubFolderMapping of voiceLangMapping) {
const voiceSubFolder = path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, __config.folder.voice.main, voiceSubFolderMapping.name)
const voiceSubFolder = path.join(OPERATOR_SOURCE_DATA_FOLDER, OPERATOR_NAME, __config.folder.voice.main, voiceSubFolderMapping.name)
if (readdirSync(voiceSubFolder).length === 0) {
__error.push(`Voice folder ${voiceSubFolderMapping.name} for ${OPERATOR_NAME} is empty.`)
}
@@ -237,10 +234,10 @@ async function main() {
})
const assetsProcessor = new AssetsProcessor(OPERATOR_NAME, OPERATOR_SHARE_FOLDER)
assetsProcessor.process(EXTRACTED_FOLDER).then((content) => {
write(JSON.stringify(content.assetsJson, null), path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, `assets.json`))
})
const assetContent = await assetsProcessor.process(EXTRACTED_FOLDER)
write(JSON.stringify(assetContent.assetsJson, null), path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, `assets.json`))
// copy remaining files
const filesToCopy = [
...background.getFilesToCopy(SHOWCASE_PUBLIC_ASSSETS_FOLDER),
...musicToCopy.map(entry => {
@@ -251,7 +248,7 @@ async function main() {
}),
{
filename: 'preview.jpg',
source: path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME),
source: path.join(OPERATOR_SOURCE_DATA_FOLDER, OPERATOR_NAME),
target: path.join(OPERATOR_RELEASE_FOLDER)
},
{
@@ -281,7 +278,7 @@ async function main() {
const foldersToCopy = [
{
source: path.join(OPERATOR_SOURCE_FOLDER, OPERATOR_NAME, __config.folder.voice.main),
source: path.join(OPERATOR_SOURCE_DATA_FOLDER, OPERATOR_NAME, __config.folder.voice.main),
target: path.join(SHOWCASE_PUBLIC_ASSSETS_FOLDER, __config.folder.voice.main)
}
]
@@ -289,20 +286,18 @@ async function main() {
copyDir(folder.source, folder.target)
})
}
directory({ backgrounds, musicMapping })
switch (op) {
case op.startsWith('directory'):
directory(OPERATOR_SOURCE_DATA_FOLDER, { backgrounds, musicMapping })
default:
break
}
if (__error.length > 0) {
const str = `${__error.length} error${__error.length > 1 ? 's were' : ' was'} found:\n${__error.join('\n')}`
throw new Error(str)
} else {
switch (op) {
case 'charwords:build':
return
default:
for (const OPERATOR_NAME of OPERATOR_NAMES) {
fork(path.join(__projectRoot, 'vite.config.js'), [op, OPERATOR_NAME])
}
return
for (const OPERATOR_NAME of OPERATOR_NAMES) {
fork(path.join(__projectRoot, 'vite.config.js'), [op, OPERATOR_NAME])
}
}
}

View File

@@ -1,4 +1,6 @@
folder:
auto_update_data: ./data/auto_update
operator_data: ./data/operator/
directory_src: directory
showcase_src: showcase
operator: ./operator/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"id":"bg_rhodes_day","intro":"Audio/Sound_Beta_2/Music/beta1_180603/m_sys_void_intro","loop":"Audio/Sound_Beta_2/Music/beta1_180603/m_sys_void_loop"},{"id":"bg_rhodes_night","intro":"Audio/Sound_Beta_2/Music/beta2_180603/m_sys_tech_intro","loop":"Audio/Sound_Beta_2/Music/beta2_180603/m_sys_tech_loop"},{"id":"bg_main_victoria_1","intro":"Audio/Sound_Beta_2/Music/AVG/m_avg_ghosthunter_intro","loop":"Audio/Sound_Beta_2/Music/AVG/m_avg_ghosthunter_loop"},{"id":"bg_siesta_1","intro":"Audio/Sound_Beta_2/Music/obt/m_sys_ddd_intro","loop":"Audio/Sound_Beta_2/Music/obt/m_sys_ddd_loop"},{"id":"bg_kazimierz_1","intro":"Audio/Sound_Beta_2/Music/beta3_181101/m_dia_street_intro","loop":"Audio/Sound_Beta_2/Music/beta3_181101/m_dia_street_loop"},{"id":"bg_ursus_1","intro":"Audio/Sound_Beta_2/Music/static/m_avg/m_avg_loneliness_intro","loop":"Audio/Sound_Beta_2/Music/static/m_avg/m_avg_loneliness_loop"},{"id":"bg_yan_1","intro":null,"loop":"Audio/Sound_Beta_2/Music/act15side/m_sys_bitw_loop"},{"id":"bg_iberia_1","intro":"Audio/Sound_Beta_2/Music/act18d3d0/m_sys_act18d3d0_intro","loop":"Audio/Sound_Beta_2/Music/act18d3d0/m_sys_act18d3d0_loop"},{"id":"bg_anniversary_1","intro":"Audio/Sound_Beta_2/Music/beta2_180603/m_dia_nightoflongmen_intro","loop":"Audio/Sound_Beta_2/Music/beta2_180603/m_dia_nightoflongmen_loop"},{"id":"bg_rogue_1","intro":null,"loop":"Audio/Sound_Beta_2/Music/rogue_1/m_avg_rglk1secretevent_loop"},{"id":"bg_rogue_2","intro":null,"loop":"Audio/Sound_Beta_2/Music/rogue_2/m_sys_rglk2DLC_loop"},{"id":"bg_laterano_1","intro":"Audio/Sound_Beta_2/Music/act16side/m_sys_act16side_intro","loop":"Audio/Sound_Beta_2/Music/act16side/m_sys_act16side_loop"},{"id":"bg_rhine_1","intro":"Audio/Sound_Beta_2/Music/act19side/m_sys_act19side_intro","loop":"Audio/Sound_Beta_2/Music/act19side/m_sys_act19side_loop"},{"id":"bg_kalts_1","intro":"Audio/Sound_Beta_2/Music/act18d0d0/m_sys_act18d0d0_intro","loop":"Audio/Sound_Beta_2/Music/act18d0d0/m_sys_act18d0d0_loop"},{"id":"bg_rogue_3","intro":"Audio/Sound_Beta_2/Music/rogue_3/m_bat_rglk3DLC_intro","loop":"Audio/Sound_Beta_2/Music/rogue_3/m_bat_rglk3DLC_loop"},{"id":"bg_rainbowsix_1","intro":null,"loop":"Audio/Sound_Beta_2/Music/act32side/m_act32side_sys_loop"},{"id":"bg_rhodes_flower_1","intro":"Audio/Sound_Beta_2/Music/act16mini/m_sys_act16mini_intro","loop":"Audio/Sound_Beta_2/Music/act16mini/m_sys_act16mini_loop"},{"id":"bg_sanrio_1","intro":null,"loop":"Audio/Sound_Beta_2/Music/act27side/m_avg_SiestaCity"},{"id":"operator_bg","intro":"m_sys_void_intro","loop":"m_sys_void_loop"}]

View File

@@ -3,7 +3,7 @@ VITE_APP_VOICE_URL=jp/CN_037.ogg
VITE_VOICE_FOLDERS={"main":"voice","sub":[{"name":"jp","lang":"JP"},{"name":"cn","lang":"CN_MANDARIN"},{"name":"en","lang":"EN"},{"name":"kr","lang":"KR"},{"name":"custom","lang":"CUSTOM"}]}
VITE_DIRECTORY_FOLDER="_assets"
VITE_BACKGROUND_FOLDER="background"
VITE_AVAILABLE_OPERATORS=["chen","dusk","dusk_everything_is_a_miracle","ling","nearl","nian","nian_unfettered_freedom","phatom_focus","rosmontis","skadi","skadi_sublimation","w","w_wonder","specter","gavial","surtr_colorful_wonderland","lee_trust_your_eyes","texas_the_omertosa","nearl_relight","rosmontis_become_anew","passager_dream_in_a_moment","mizuki_summer_feast","chongyue","ling_it_does_wash_the_strings","pozemka_snowy_plains_in_words","chen_ten_thousand_mountains","specter_born_as_one","muelsyse","kaltsit_remnant","eyjafjalla_the_hvit_aska","goldenglow_summer_flowers_fa394","gavial_the_invincible_holiday_hd26","ling_towering_is_cliff_of_nostalgia","virtuosa","texas_the_omertosa_wingbreaker","mwynar_w_dali","reed_the_frame_shadow_curator","shu","lin_heavenly_mirage","chongyue_alighting","wisadel","muelsyse_young_branch","skadi_the_corrupting_heart_red_countess","ines_under_the_flaming_dome","silverash_never_melting_ice","reed_the_frame_shadow_summer_flower"]
VITE_AVAILABLE_OPERATORS=["chen","dusk","dusk_everything_is_a_miracle","ling","nearl","nian","nian_unfettered_freedom","phatom_focus","rosmontis","skadi","skadi_sublimation","w","w_wonder","specter","gavial","surtr_colorful_wonderland","lee_trust_your_eyes","texas_the_omertosa","nearl_relight","rosmontis_become_anew","passager_dream_in_a_moment","mizuki_summer_feast","chongyue","ling_it_does_wash_the_strings","pozemka_snowy_plains_in_words","chen_ten_thousand_mountains","specter_born_as_one","muelsyse","kaltsit_remnant","eyjafjalla_the_hvit_aska","goldenglow_summer_flowers_fa394","gavial_the_invincible_holiday_hd26","ling_towering_is_cliff_of_nostalgia","virtuosa","texas_the_omertosa_wingbreaker","mwynar_w_dali","reed_the_frame_shadow_curator","shu","lin_heavenly_mirage","chongyue_alighting","wisadel","muelsyse_young_branch","skadi_the_corrupting_heart_red_countess","ines_under_the_flaming_dome","silverash_never_melting_ice","reed_the_frame_shadow_summer_flower","eyjafjalla_the_hvit_aska_a_picnic_before_a_long_trip","pepe","nightingale_iakhu_of_flows"]
VITE_ERROR_FILES={"files":[{"key":"build_char_128_plosis_epoque%233","paddings":{"left":-120,"right":150,"top":10,"bottom":0}},{"key":"build_char_128_plosis","paddings":{"left":-90,"right":100,"top":10,"bottom":0}}],"voice":"CN_034.ogg"}
VITE_MUSIC_FOLDER=music
VITE_MUSIC_MAPPING={"bg_rhodes_day.png":{"intro":"m_sys_void_intro.ogg","loop":"m_sys_void_loop.ogg"},"bg_rhodes_night.png":{"intro":"m_sys_tech_intro.ogg","loop":"m_sys_tech_loop.ogg"},"bg_main_victoria_1.png":{"intro":"m_avg_ghosthunter_intro.ogg","loop":"m_avg_ghosthunter_loop.ogg"},"bg_siesta_1.png":{"intro":"m_sys_ddd_intro.ogg","loop":"m_sys_ddd_loop.ogg"},"bg_kazimierz_1.png":{"intro":"m_dia_street_intro.ogg","loop":"m_dia_street_loop.ogg"},"bg_ursus_1.png":{"intro":"m_avg_loneliness_intro.ogg","loop":"m_avg_loneliness_loop.ogg"},"bg_yan_1.png":{"intro":null,"loop":"m_sys_bitw_loop.ogg"},"bg_iberia_1.png":{"intro":"m_sys_act18d3d0_intro.ogg","loop":"m_sys_act18d3d0_loop.ogg"},"bg_anniversary_1.png":{"intro":"m_dia_nightoflongmen_intro.ogg","loop":"m_dia_nightoflongmen_loop.ogg"},"bg_rogue_1.png":{"intro":null,"loop":"m_avg_rglk1secretevent_loop.ogg"},"bg_rogue_2.png":{"intro":null,"loop":"m_sys_rglk2DLC_loop.ogg"},"bg_laterano_1.png":{"intro":"m_sys_act16side_intro.ogg","loop":"m_sys_act16side_loop.ogg"},"bg_rhine_1.png":{"intro":"m_sys_act19side_intro.ogg","loop":"m_sys_act19side_loop.ogg"},"bg_kalts_1.png":{"intro":"m_sys_act18d0d0_intro.ogg","loop":"m_sys_act18d0d0_loop.ogg"},"bg_rogue_3.png":{"intro":"m_bat_rglk3DLC_intro.ogg","loop":"m_bat_rglk3DLC_loop.ogg"},"bg_rainbowsix_1.png":{"intro":null,"loop":"m_act32side_sys_loop.ogg"},"bg_rhodes_flower_1.png":{"intro":"m_sys_act16mini_intro.ogg","loop":"m_sys_act16mini_loop.ogg"},"bg_sanrio_1.png":{"intro":null,"loop":"m_avg_SiestaCity.ogg"},"operator_bg.png":{"intro":"m_sys_void_intro.ogg","loop":"m_sys_void_loop.ogg"}}

View File

@@ -0,0 +1,142 @@
@use "@/scss/_page_base.scss";
.main {
padding: 3rem 0 2rem 0;
display: flex;
justify-content: space-between;
align-items: flex-start;
.container {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
width: 100%;
position: relative;
margin-bottom: 2rem;
user-select: none;
&:before {
content: "";
display: block;
padding-top: 100%;
}
.wrapper {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
@media (max-width: 1280px) {
width: 100%;
position: relative;
margin-bottom: 2rem;
&:before {
content: "";
display: block;
padding-top: 100%;
}
}
}
.settings {
margin-right: 1.5rem;
user-select: none;
margin-left: 1rem;
.title {
font-size: 1.25rem;
border-left: 3px solid currentColor;
padding-left: 0.75rem;
margin-bottom: 0.8rem;
display: flex;
justify-content: space-between;
cursor: pointer;
.switch {
bottom: -10px;
position: relative;
}
}
}
.text {
color: var(--text-color);
line-height: 1.2;
}
.logo {
position: absolute;
top: 0;
left: 0;
width: 30%;
height: auto;
opacity: 0.3;
}
.voice {
position: absolute;
left: 0;
bottom: 20%;
z-index: 1;
max-width: 480px;
width: 85%;
opacity: 0;
margin: 16px;
transition: all 0.5s cubic-bezier(0.65, 0.05, 0.36, 1);
visibility: hidden;
font-family: 'Noto Sans SC', 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans', sans-serif;
.type {
background-color: #9e9e9e;
color: #000;
display: inline-block;
position: absolute;
top: -12px;
left: -8px;
padding: 2px 8px;
font-size: 14px;
max-width: 180px;
width: 65%;
box-shadow: 0 3px 6px #00000080;
z-index: 1;
}
.subtitle {
background-color: #000000a6;
color: #fff;
padding: 16px;
font-size: 18px;
box-shadow: 0 6px 12px #00000080;
position: relative;
word-break: break-word;
}
.triangle {
position: absolute;
bottom: 0px;
right: 8px;
width: 0;
height: 0;
border-style: solid;
border-width: 8px 8px 8px 8px;
border-color: white transparent transparent transparent;
}
&.active {
opacity: 1;
visibility: visible;
}
@media (max-width: 1280px) {
bottom: 0;
}
}
@media (max-width: 1280px) {
flex-direction: column-reverse;
align-items: stretch;
}
}

View File

@@ -2,29 +2,29 @@
import path from 'path';
import fs from 'fs';
import sharp from "sharp";
import { mkdir } from './file.js'
export default class Background {
#backgroundFolder
#backgroundOutputFolder
#extractFolder
#files
constructor() {
this.#backgroundFolder = path.join(__projectRoot, __config.folder.operator, __config.folder.share, __config.folder.background);
constructor(shareDir, targetDir) {
this.#backgroundFolder = path.join(shareDir, __config.folder.background);
this.#backgroundOutputFolder = path.join(targetDir, `_${__config.folder.background}`);
this.#extractFolder = path.join(this.#backgroundFolder, 'extracted');
mkdir(this.#backgroundOutputFolder);
}
async process() {
this.#files = fs.readdirSync(this.#extractFolder).filter((f) => {
return f.endsWith('.png') && f.includes('_left');
})
if (this.#files.length !== fs.readdirSync(this.#backgroundFolder).length - 1) {
await Promise.all(this.#files.map(async (f) => {
const filenamePrefix = path.parse(f).name.replace('_left', '');
await this.#composite(filenamePrefix, '.png');
}))
} else {
console.log('Background images already exist, skip generation.')
}
await Promise.all(this.#files.map(async (f) => {
const filenamePrefix = path.parse(f).name.replace('_left', '');
await this.#composite(filenamePrefix, '.png');
}))
}
async #composite(filenamePrefix, fileExt) {
@@ -45,7 +45,7 @@ export default class Background {
left: metadata.width,
},
])
.toFile(path.join(this.#backgroundFolder, `${filenamePrefix}${fileExt}`));
.toFile(path.join(this.#backgroundOutputFolder, `${filenamePrefix}${fileExt}`));
}
get files() {
@@ -56,7 +56,7 @@ export default class Background {
return this.#files.map((f) => {
return {
filename: f.replace('_left', ''),
source: path.join(this.#backgroundFolder),
source: path.join(this.#backgroundOutputFolder),
target: path.join(publicAssetsDir, __config.folder.background)
};
})

66
libs/cf_pages.js Normal file
View File

@@ -0,0 +1,66 @@
/* eslint-disable no-undef */
import path from 'path';
import { spawnSync } from 'child_process';
import { readdirSync, fileTypeSync, writeSync } from './file.js';
export default class CFPages {
#uploadPath = path.join(__projectRoot, __config.folder.operator_data);
#gitignorePath = path.join(__projectRoot, '.gitignore');
constructor() {
}
upload() {
const tree = this.#generateDirTree(this.#uploadPath);
writeSync(JSON.stringify(tree, null), path.join(this.#uploadPath, 'index.json'));
const wrangler = spawnSync('pnpm', ['wrangler', 'pages', 'deploy', this.#uploadPath]);
console.log('error', wrangler.error);
console.log('stdout ', wrangler.stdout.toString());
console.log('stderr ', wrangler.stderr.toString());
}
download() {
}
#generateDirTree(dir) {
const files = readdirSync(dir);
let tree = {
name: path.basename(dir),
type: 'dir',
children: []
};
for (const file of files) {
if (this.#isToIgnore(file)) {
continue;
}
const filePath = path.join(dir, file);
const dirType = fileTypeSync(filePath);
if (dirType === 'dir') {
tree.children.push(this.#generateDirTree(filePath))
} else {
tree.children.push({
name: file,
type: 'file'
});
}
}
if (tree.children.length === 0) {
return null;
}
return tree
}
// TODO
#isToIgnore(file) {
switch (file) {
case '.DS_Store':
case 'index.json':
return true;
default:
return false;
}
}
}

View File

@@ -30,7 +30,7 @@ export function getOperatorId(operatorConfig) {
export default class CharwordTable {
#operatorIDs = Object.values(__config.operators).map(operator => { return getOperatorId(operator) })
#charwordTablePath = path.join(__projectRoot, __config.folder.operator, __config.folder.share)
#charwordTablePath = path.join(__projectRoot, __config.folder.auto_update_data)
#charwordTableFile = path.join(this.#charwordTablePath, 'charword_table.json')
#charwordTable = JSON.parse(readSync(this.#charwordTableFile)) || {
config: {

View File

@@ -1,12 +1,11 @@
/* eslint-disable no-undef */
import path from 'path'
import { writeSync, copy, readSync as readFile } from './file.js'
import { read } from './yaml.js';
import AssetsProcessor from './assets_processor.js'
import EnvGenerator from './env_generator.js'
export default function ({ backgrounds, musicMapping }) {
const extractedFolder = path.join(__projectRoot, __config.folder.operator, '_directory')
export default function (dataDir, { backgrounds, musicMapping }) {
const extractedFolder = path.join(dataDir, '_directory')
const targetFolder = path.join(__projectRoot, __config.folder.release, __config.folder.directory);
const directoryAssetFolder = path.join(__projectRoot, 'directory', 'src');
const sourceFolder = path.join(__projectRoot, __config.folder.operator);
@@ -24,7 +23,7 @@ export default function ({ backgrounds, musicMapping }) {
cur.workshopId = null
try {
cur.workshopId = JSON.parse(readFile(path.join(__projectRoot, __config.folder.operator, cur.link, 'project.json'))).workshopid
cur.workshopId = JSON.parse(readFile(path.join(dataDir, cur.link, 'project.json'))).workshopid
} catch (e) {
console.log(`No workshop id for ${cur.link}!`)
}

View File

@@ -73,3 +73,11 @@ export function readdirSync(dir) {
}
return fs.readdirSync(dir)
}
export function fileTypeSync(dir) {
if (!exists(dir)) {
console.warn(`Source ${dir} does not exist.`)
return null
}
return fs.statSync(dir).isDirectory() ? 'dir' : 'file'
}

View File

@@ -5,7 +5,7 @@ import Downloader from "./downloader.js"
export default class Music {
#downloader = new Downloader()
#sharedPath = path.join(__projectRoot, __config.folder.operator, __config.folder.share)
#sharedPath = path.join(__projectRoot, __config.folder.auto_update_data)
async process() {
const { metaTable, audioDataTable } = await this.#download()
@@ -49,8 +49,8 @@ export default class Music {
}
}
copy() {
const musicFolder = path.join(__projectRoot, __config.folder.operator, __config.folder.share, __config.folder.music);
copy(shareDir) {
const musicFolder = path.join(shareDir, __config.folder.music);
const musicTable = JSON.parse(readSync(path.join(this.#sharedPath, `music_table.json`)))
const musicMapping = {}
const musicToCopy = []

View File

@@ -4,23 +4,18 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "node aklive2d dev",
"build": "node aklive2d build",
"build-all": "node aklive2d build-all",
"preview": "node aklive2d preview",
"operator:dev": "node aklive2d operator:dev",
"operator:build": "node aklive2d operator:build",
"operator:build-all": "node aklive2d operator:build-all",
"init": "node aklive2d init",
"directory": "node aklive2d directory",
"charwords:update": "node aklive2d charwords:update",
"charwords:build": "node aklive2d charwords:build",
"logo": "node aklive2d logo",
"music": "node aklive2d music",
"vite:dev": "vite",
"vite:build": "vite build",
"vite:preview": "vite preview",
"vite:directory:dev": "vite dev",
"vite:directory:build": "vite build",
"vite:directory:preview": "vite preview",
"offical_update": "node aklive2d offical_update"
"directory:dev": "vite dev",
"directory:build": "vite build",
"directory:preview": "vite preview",
"offical_update": "node aklive2d offical_update",
"cf:upload": "node aklive2d cf:upload",
"cf:download": "node aklive2d cf:download"
},
"devDependencies": {
"@types/react": "^18.3.3",
@@ -37,7 +32,8 @@
"stylelint": "^16.8.1",
"stylelint-config-standard": "^36.0.1",
"stylelint-config-standard-scss": "^13.1.0",
"vite": "^5.3.5"
"vite": "^5.3.5",
"wrangler": "^3.71.0"
},
"dependencies": {
"@parcellab/react-use-umami": "^2.0.1",

697
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-undef */
import path from 'path'
import { fileURLToPath } from 'url'
import { defineConfig, splitVendorChunkPlugin } from 'vite'
import { defineConfig } from 'vite'
import assert from 'assert'
import react from '@vitejs/plugin-react-swc'
import getConfig from './libs/config.js'
@@ -18,7 +18,6 @@ class ViteRunner {
#globalConfig = getConfig(this.#officalInfo)
#mode
#baseViteConfig = {
plugins: [splitVendorChunkPlugin()],
configFile: false,
base: "",
server: {
@@ -32,22 +31,19 @@ class ViteRunner {
get config() {
let result;
const temp = process.env.npm_lifecycle_event.split(':')
this.#mode = temp[0] === "vite" ? temp[1] : process.argv[2]
switch (this.#mode) {
const runType = temp[0]
this.#mode = temp[1]
switch (runType) {
case 'directory':
result = {
data: this.#directoryConfig,
}
const op = temp[2] || process.argv[3]
if (op !== 'preview') {
if (this.#mode !== 'preview') {
rmdir(path.resolve(__projectRoot, this.#globalConfig.folder.release, "_directory"))
rmdir(path.resolve(__projectRoot, this.#globalConfig.folder.release, "index.html"))
}
break
case 'dev':
case 'build':
case 'build-all':
case 'preview':
case 'operator':
result = {
data: this.#operatorConfig,
}
@@ -143,12 +139,10 @@ class ViteRunner {
}
get #directoryConfig() {
if (process.env.npm_lifecycle_event === 'vite:directory:build') {
if (process.env.npm_lifecycle_event === 'directory:build') {
global.__config = this.#globalConfig
}
const directoryDir = path.resolve(__projectRoot, this.#globalConfig.folder.directory_src)
this.#mode = process.argv[3]
// const publicDir = path.resolve(__projectRoot, this.#globalConfig.folder.release)
const assetsDir = '_directory'
return {
...this.#baseViteConfig,
@@ -191,15 +185,18 @@ class ViteRunner {
}
async function main() {
if (process.env.npm_lifecycle_event.includes('vite')) {
if (process.env.npm_lifecycle_event.includes('directory')) {
const officalInfo = new OfficalInfo()
global.__config = getConfig(officalInfo)
const background = new Background()
const OPERATOR_SOURCE_FOLDER = path.join(__projectRoot, __config.folder.operator)
const OPERATOR_SOURCE_DATA_FOLDER = path.join(__projectRoot, __config.folder.operator_data)
const OPERATOR_SHARE_FOLDER = path.join(OPERATOR_SOURCE_DATA_FOLDER, __config.folder.share)
const background = new Background(OPERATOR_SHARE_FOLDER, OPERATOR_SOURCE_FOLDER)
await background.process()
const backgrounds = ['operator_bg.png', ...background.files]
const { musicMapping } = (new Music()).copy()
const { musicMapping } = (new Music()).copy(OPERATOR_SHARE_FOLDER)
directory({ backgrounds, musicMapping })
directory(OPERATOR_SOURCE_DATA_FOLDER, { backgrounds, musicMapping })
return
}
const runner = new ViteRunner()