diff --git a/lerna.json b/lerna.json index 577c7193e..b9933894c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "packages": ["packages/*"], - "version": "independent", - "npmClient": "yarn" + "packages": ["packages/*"], + "version": "independent", + "npmClient": "yarn" } diff --git a/package.json b/package.json index 75fed9f33..ba172b423 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "artplayer-packages", "type": "module", - "version": "5.2.0", + "version": "6.0.0", "private": true, "description": "ArtPlayer.js is a modern and full featured HTML5 video player", "workspaces": [ @@ -25,17 +25,17 @@ "node": ">= 20.0.0" }, "scripts": { - "build:all": "npm run build all && npm run build:i18n && npm run build:ts && npm run build:docs", - "lint": "npx eslint packages/*/{src,types,package.json} --fix", + "bootstrap": "npx lerna link", + "postinstall": "npx lerna run prepare", "build:ts": "node ./scripts/build-ts.js", "build:docs": "node ./scripts/build-docs.js", "build:i18n": "node ./scripts/build-i18n.js", "trans:docs": "node ./scripts/trans-docs.js", "create:plugin": "node ./scripts/plugin/create.js", + "lint": "npx eslint packages/*/{src,types,package.json} --fix", "dev": "npx cross-env NODE_ENV=development node ./scripts/dev.js", "build": "npx cross-env NODE_ENV=production node ./scripts/build.js", - "postinstall": "npx lerna run prepare", - "bootstrap": "npx lerna link" + "build:all": "npm run build all && npm run build:i18n && npm run build:ts && npm run build:docs" }, "browserslist": "last 1 Chrome version", "dependencies": { @@ -52,7 +52,6 @@ "dotenv": "^17.2.1", "eslint": "^9.32.0", "glob": "^11.0.3", - "globals": "^16.3.0", "lerna": "^8.2.3", "prompts": "^2.4.2", "servor": "^4.0.2", diff --git a/scripts/build-docs.js b/scripts/build-docs.js index 5e463e251..b18b86771 100644 --- a/scripts/build-docs.js +++ b/scripts/build-docs.js @@ -1,8 +1,9 @@ -import spawn from 'cross-spawn'; +import process from 'node:process' +import spawn from 'cross-spawn' const proc = spawn('npm', ['run', 'build'], { - cwd: './packages/artplayer-vitepress/', -}); + cwd: './packages/artplayer-vitepress/', +}) -proc.stdout.pipe(process.stdout); -proc.stderr.pipe(process.stderr); +proc.stdout.pipe(process.stdout) +proc.stderr.pipe(process.stderr) diff --git a/scripts/build-i18n.js b/scripts/build-i18n.js index 9f552a91a..d30f4a633 100644 --- a/scripts/build-i18n.js +++ b/scripts/build-i18n.js @@ -1,45 +1,46 @@ -import fs from 'fs'; -import path from 'path'; -import { glob } from 'glob'; -import { Parcel } from '@parcel/core'; +import fs from 'node:fs' +import path from 'node:path' +import { Parcel } from '@parcel/core' +import { glob } from 'glob' -const basePath = 'packages/artplayer'; +const basePath = 'packages/artplayer' const entries = glob.sync(path.join(basePath, 'src/i18n/*.js'), { - ignore: [path.join(basePath, 'src/i18n/index.js'), path.join(basePath, 'src/i18n/zh-cn.js')], -}); + ignore: [path.join(basePath, 'src/i18n/index.js'), path.join(basePath, 'src/i18n/zh-cn.js')], +}) -const packagePath = path.join(basePath, 'package.json'); +const packagePath = path.join(basePath, 'package.json') const backupPackagePath = path.join(basePath, 'package_backup.json'); (async function build() { - fs.renameSync(packagePath, backupPackagePath); + fs.renameSync(packagePath, backupPackagePath) - const bundler = new Parcel({ - entries: entries, - defaultConfig: '@parcel/config-default', - mode: 'production', - defaultTargetOptions: { - distDir: 'packages/artplayer/dist/i18n', - outputFormat: 'global', - sourceMaps: false, - isLibrary: true, - engines: { - browsers: ['last 1 Chrome version'], - }, - }, - env: { - NODE_ENV: 'production', - }, - }); + const bundler = new Parcel({ + entries, + defaultConfig: '@parcel/config-default', + mode: 'production', + defaultTargetOptions: { + distDir: 'packages/artplayer/dist/i18n', + outputFormat: 'global', + sourceMaps: false, + isLibrary: true, + engines: { + browsers: ['last 1 Chrome version'], + }, + }, + env: { + NODE_ENV: 'production', + }, + }) - try { - const { bundleGraph, buildTime } = await bundler.run(); - const bundles = bundleGraph.getBundles(); - console.log(`✨ Built [i18n] ${bundles.length} bundles in ${buildTime}ms`); - fs.renameSync(backupPackagePath, packagePath); - } catch (err) { - console.log(err.diagnostics); - fs.renameSync(backupPackagePath, packagePath); - } -})(); + try { + const { bundleGraph, buildTime } = await bundler.run() + const bundles = bundleGraph.getBundles() + console.log(`✨ Built [i18n] ${bundles.length} bundles in ${buildTime}ms`) + fs.renameSync(backupPackagePath, packagePath) + } + catch (err) { + console.log(err.diagnostics) + fs.renameSync(backupPackagePath, packagePath) + } +})() diff --git a/scripts/build.js b/scripts/build.js index ebf91abd5..b55026da2 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -1,161 +1,163 @@ -import fs from 'fs'; -import cpy from 'cpy'; -import path from 'path'; -import prompts from 'prompts'; -import { Parcel } from '@parcel/core'; -import { getProjects } from './utils.js'; +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import { Parcel } from '@parcel/core' +import cpy from 'cpy' +import prompts from 'prompts' +import { getProjects } from './utils.js' -const projects = getProjects(); -const compiledPath = path.resolve('docs/compiled'); +const projects = getProjects() +const compiledPath = path.resolve('docs/compiled') function compressString(input) { - return input - .replace(/\s*(<[^>]+>)\s*/g, '$1') - .replace(/(\r\n|\n|\r)/gm, ' ') - .replace(/\s+/g, ' ') - .trim(); + return input + .replace(/\s*(<[^>]+>)\s*/g, '$1') + .replace(/(\r\n|\n|\r)/g, ' ') + .replace(/\s+/g, ' ') + .trim() } async function build(name, targetName) { - const projectPackageJson = path.join(projects[name], 'package.json'); - const { version } = JSON.parse(fs.readFileSync(projectPackageJson, 'utf-8')); + const projectPackageJson = path.join(projects[name], 'package.json') + const { version } = JSON.parse(fs.readFileSync(projectPackageJson, 'utf-8')) - process.chdir(projects[name]); + process.chdir(projects[name]) - const targets = { - main: { - context: 'browser', - distDir: path.join(projects[name], 'dist'), - sourceMap: false, - outputFormat: 'global', - isLibrary: true, - engines: { - browsers: 'last 1 Chrome version', - }, - }, - legacy: { - context: 'browser', - distDir: path.join(projects[name], 'dist'), - sourceMap: false, - outputFormat: 'global', - isLibrary: true, - engines: { - browsers: 'IE 11', - }, - }, - esm: { - context: 'browser', - distDir: path.join(projects[name], 'dist'), - sourceMap: true, - outputFormat: 'esmodule', - isLibrary: true, - engines: { - browsers: 'last 1 Chrome version', - }, - }, - }; + const targets = { + main: { + context: 'browser', + distDir: path.join(projects[name], 'dist'), + sourceMap: false, + outputFormat: 'global', + isLibrary: true, + engines: { + browsers: 'last 1 Chrome version', + }, + }, + legacy: { + context: 'browser', + distDir: path.join(projects[name], 'dist'), + sourceMap: false, + outputFormat: 'global', + isLibrary: true, + engines: { + browsers: 'IE 11', + }, + }, + esm: { + context: 'browser', + distDir: path.join(projects[name], 'dist'), + sourceMap: true, + outputFormat: 'esmodule', + isLibrary: true, + engines: { + browsers: 'last 1 Chrome version', + }, + }, + } - const names = { - main: name, - legacy: `${name}.legacy`, - esm: `${name}.esm`, - }; + const names = { + main: name, + legacy: `${name}.legacy`, + esm: `${name}.esm`, + } - const entryFile = path.join(projects[name], 'src/index.js'); + const entryFile = path.join(projects[name], 'src/index.js') - const bundler = new Parcel({ - entries: entryFile, - defaultConfig: '@parcel/config-default', - mode: 'production', - targets: { - [targetName]: targets[targetName], - }, - env: { - NODE_ENV: 'production', - }, - }); + const bundler = new Parcel({ + entries: entryFile, + defaultConfig: '@parcel/config-default', + mode: 'production', + targets: { + [targetName]: targets[targetName], + }, + env: { + NODE_ENV: 'production', + }, + }) - const banner = ` + const banner = ` /*! * ${name}.js v${version} * Github: https://github.com/zhw2590582/ArtPlayer * (c) 2017-${new Date().getFullYear()} Harvey Zack * Released under the MIT License. */ -`; +` - const { bundleGraph, buildTime } = await bundler.run(); - const bundles = bundleGraph.getBundles(); + const { bundleGraph, buildTime } = await bundler.run() + const bundles = bundleGraph.getBundles() - const filePath = path.join(projects[name], 'dist/index.js'); - const newFilePath = path.join(projects[name], `dist/${names[targetName]}.js`); - const code = fs.readFileSync(filePath, 'utf-8'); + const filePath = path.join(projects[name], 'dist/index.js') + const newFilePath = path.join(projects[name], `dist/${names[targetName]}.js`) + const code = fs.readFileSync(filePath, 'utf-8') - fs.writeFileSync(filePath, banner + compressString(code)); - fs.renameSync(filePath, newFilePath); - const size = fs.statSync(newFilePath).size / 1024; - await cpy(newFilePath, compiledPath); + fs.writeFileSync(filePath, banner + compressString(code)) + fs.renameSync(filePath, newFilePath) + const size = fs.statSync(newFilePath).size / 1024 + await cpy(newFilePath, compiledPath) - if (targetName === 'esm') { - const jsFile = path.join(projects[name], `dist/${names.esm}.js`); - const oldMapName = 'index.js.map'; - const newMapName = `${names.esm}.js.map`; + if (targetName === 'esm') { + const jsFile = path.join(projects[name], `dist/${names.esm}.js`) + const oldMapName = 'index.js.map' + const newMapName = `${names.esm}.js.map` - const oldMapPath = path.join(projects[name], 'dist', oldMapName); - const newMapPath = path.join(projects[name], 'dist', newMapName); - if (fs.existsSync(oldMapPath)) { - fs.renameSync(oldMapPath, newMapPath); - } - - let jsContent = fs.readFileSync(jsFile, 'utf8'); - jsContent = jsContent.replace(/\/\/# sourceMappingURL=.*\.js\.map/, `\n//# sourceMappingURL=${newMapName}`); - fs.writeFileSync(jsFile, jsContent); - await cpy(newMapPath, compiledPath); - await cpy(newFilePath, compiledPath); + const oldMapPath = path.join(projects[name], 'dist', oldMapName) + const newMapPath = path.join(projects[name], 'dist', newMapName) + if (fs.existsSync(oldMapPath)) { + fs.renameSync(oldMapPath, newMapPath) } - console.log( - `✨ Built@${targetName} ${name}@${version}`, - `Bundles@${bundles.length}`, - `Time@${buildTime}ms`, - `Size@${size.toFixed(2)}kb`, - ); + let jsContent = fs.readFileSync(jsFile, 'utf8') + jsContent = jsContent.replace(/\/\/# sourceMappingURL=.*\.js\.map/, `\n//# sourceMappingURL=${newMapName}`) + fs.writeFileSync(jsFile, jsContent) + await cpy(newMapPath, compiledPath) + await cpy(newFilePath, compiledPath) + } + + console.log( + `✨ Built@${targetName} ${name}@${version}`, + `Bundles@${bundles.length}`, + `Time@${buildTime}ms`, + `Size@${size.toFixed(2)}kb`, + ) } async function runBuild() { - if (process.argv.pop() === 'all') { - const bundles = Object.keys(projects).map((name) => async () => { - await build(name, 'main'); - await build(name, 'legacy'); - await build(name, 'esm'); - }); + if (process.argv.pop() === 'all') { + const bundles = Object.keys(projects).map(name => async () => { + await build(name, 'main') + await build(name, 'legacy') + await build(name, 'esm') + }) - await runPromisesInSeries(bundles); - console.log('✅ Finished building all packages!'); - } else { - const response = await prompts({ - type: 'select', - name: 'value', - message: 'Which project do you want to build?', - choices: Object.keys(projects).map((name) => ({ - title: name, - value: name, - })), - initial: 0, - }); + await runPromisesInSeries(bundles) + console.log('✅ Finished building all packages!') + } + else { + const response = await prompts({ + type: 'select', + name: 'value', + message: 'Which project do you want to build?', + choices: Object.keys(projects).map(name => ({ + title: name, + value: name, + })), + initial: 0, + }) - if (response.value) { - await build(response.value, 'main'); - await build(response.value, 'legacy'); - await build(response.value, 'esm'); - } + if (response.value) { + await build(response.value, 'main') + await build(response.value, 'legacy') + await build(response.value, 'esm') } + } } function runPromisesInSeries(ps) { - return ps.reduce((p, next) => p.then(next), Promise.resolve()); + return ps.reduce((p, next) => p.then(next), Promise.resolve()) } runBuild().catch((error) => { - console.error('❌ Build script encountered an error:', error); -}); + console.error('❌ Build script encountered an error:', error) +}) diff --git a/scripts/dev.js b/scripts/dev.js index 8deb92423..92ed26239 100644 --- a/scripts/dev.js +++ b/scripts/dev.js @@ -1,92 +1,94 @@ -import path from 'path'; -import servor from 'servor'; -import prompts from 'prompts'; -import { Parcel } from '@parcel/core'; -import { fileURLToPath } from 'url'; -import { getProjects } from './utils.js'; -import openBrowser from 'servor/utils/openBrowser.js'; +import path from 'node:path' +import process from 'node:process' +import { fileURLToPath } from 'node:url' +import { Parcel } from '@parcel/core' +import prompts from 'prompts' +import servor from 'servor' +import openBrowser from 'servor/utils/openBrowser.js' +import { getProjects } from './utils.js' -const projects = getProjects(); +const projects = getProjects() async function develop(name) { - const projectPath = projects[name]; - const uncompiledPath = path.resolve(`docs/uncompiled/${name}`); - const entryFile = path.join(projectPath, 'src/index.js'); + const projectPath = projects[name] + const uncompiledPath = path.resolve(`docs/uncompiled/${name}`) + const entryFile = path.join(projectPath, 'src/index.js') - let isOpenBrowser = false; + let isOpenBrowser = false - const { url } = await servor({ - root: 'docs', - fallback: 'index.html', - reload: true, - port: 8082, - }); + const { url } = await servor({ + root: 'docs', + fallback: 'index.html', + reload: true, + port: 8082, + }) - process.chdir(projectPath); + process.chdir(projectPath) - const bundler = new Parcel({ - entries: entryFile, - defaultConfig: '@parcel/config-default', - mode: 'development', - targets: { - main: { - distDir: uncompiledPath, - outputFormat: 'global', - isLibrary: true, - engines: { - browsers: ['last 1 Chrome version'], - }, - }, + const bundler = new Parcel({ + entries: entryFile, + defaultConfig: '@parcel/config-default', + mode: 'development', + targets: { + main: { + distDir: uncompiledPath, + outputFormat: 'global', + isLibrary: true, + engines: { + browsers: ['last 1 Chrome version'], }, - env: { - NODE_ENV: 'development', - }, - additionalReporters: [ - { - packageName: '@parcel/reporter-cli', - resolveFrom: fileURLToPath(import.meta.url), - }, - ], - }); + }, + }, + env: { + NODE_ENV: 'development', + }, + additionalReporters: [ + { + packageName: '@parcel/reporter-cli', + resolveFrom: fileURLToPath(import.meta.url), + }, + ], + }) - bundler.watch((error, event) => { - if (error) { - console.error(`[${name}] ❌ Build error:`, error); - return; - } + bundler.watch((error, event) => { + if (error) { + console.error(`[${name}] ❌ Build error:`, error) + return + } - if (event.type === 'buildSuccess') { - const bundles = event.bundleGraph.getBundles(); - console.log(`[${name}] ✅ Built ${bundles.length} bundles in ${event.buildTime}ms`); - if (!isOpenBrowser) { - isOpenBrowser = true; - openBrowser(url); - } - } + if (event.type === 'buildSuccess') { + const bundles = event.bundleGraph.getBundles() + console.log(`[${name}] ✅ Built ${bundles.length} bundles in ${event.buildTime}ms`) + if (!isOpenBrowser) { + isOpenBrowser = true + openBrowser(url) + } + } - if (event.type === 'buildFailure') { - console.error(`[${name}] ❌ Build failure:`, event.diagnostics); - } - }); + if (event.type === 'buildFailure') { + console.error(`[${name}] ❌ Build failure:`, event.diagnostics) + } + }) } (async () => { - try { - const response = await prompts({ - type: 'select', - name: 'value', - message: 'Which project do you want to develop?', - choices: Object.keys(projects).map((name) => ({ - title: name, - value: name, - })), - initial: 0, - }); + try { + const response = await prompts({ + type: 'select', + name: 'value', + message: 'Which project do you want to develop?', + choices: Object.keys(projects).map(name => ({ + title: name, + value: name, + })), + initial: 0, + }) - if (response.value) { - await develop(response.value); - } - } catch (error) { - console.error(`❌ Prompt error: ${error.message}`); + if (response.value) { + await develop(response.value) } -})(); + } + catch (error) { + console.error(`❌ Prompt error: ${error.message}`) + } +})() diff --git a/scripts/plugin/create.js b/scripts/plugin/create.js index 4962bdb51..7df945fcb 100644 --- a/scripts/plugin/create.js +++ b/scripts/plugin/create.js @@ -1,81 +1,83 @@ -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import { fileURLToPath } from 'node:url' // Get the current file path -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) // Get the plugin name from command line arguments -const args = process.argv.slice(2); -const pluginName = args[0]; +const args = process.argv.slice(2) +const pluginName = args[0] if (!pluginName) { - console.error('Please provide a plugin name, e.g., npm run create:plugin somePluginName'); - process.exit(1); + console.error('Please provide a plugin name, e.g., npm run create:plugin somePluginName') + process.exit(1) } // Validate plugin name -const pluginNameRegex = /^[a-z-]+$/; +const pluginNameRegex = /^[a-z-]+$/ if (!pluginNameRegex.test(pluginName)) { - console.error('Invalid plugin name. Only lowercase letters and hyphens are allowed.'); - process.exit(1); + console.error('Invalid plugin name. Only lowercase letters and hyphens are allowed.') + process.exit(1) } // Convert plugin name to export name (PascalCase) const exportName = pluginName - .split('-') - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) - .join(''); -const exportNameFull = `artplayerPlugin${exportName}`; + .split('-') + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join('') +const exportNameFull = `artplayerPlugin${exportName}` // Define paths -const templateDir = path.join(__dirname, 'template'); -const destDir = path.join(__dirname, '../../packages', `artplayer-plugin-${pluginName}`); -const exampleDir = path.join(__dirname, '../../docs/assets/example'); -const exampleFileName = `${pluginName.replace(/-/g, '.')}.js`; -const exampleFile = path.join(exampleDir, exampleFileName); +const templateDir = path.join(__dirname, 'template') +const destDir = path.join(__dirname, '../../packages', `artplayer-plugin-${pluginName}`) +const exampleDir = path.join(__dirname, '../../docs/assets/example') +const exampleFileName = `${pluginName.replace(/-/g, '.')}.js` +const exampleFile = path.join(exampleDir, exampleFileName) // Check if a plugin with the same name already exists if (fs.existsSync(destDir)) { - console.error(`Plugin ${pluginName} already exists. Please choose another name.`); - process.exit(1); + console.error(`Plugin ${pluginName} already exists. Please choose another name.`) + process.exit(1) } // Create the destination directory -fs.mkdirSync(destDir, { recursive: true }); +fs.mkdirSync(destDir, { recursive: true }) // Read files from the template directory and copy them to the destination directory function copyTemplateFiles(templateDir, destDir) { - const files = fs.readdirSync(templateDir); + const files = fs.readdirSync(templateDir) - files.forEach((file) => { - const templateFilePath = path.join(templateDir, file); - let destFilePath = path.join(destDir, file); + files.forEach((file) => { + const templateFilePath = path.join(templateDir, file) + let destFilePath = path.join(destDir, file) - const stats = fs.statSync(templateFilePath); + const stats = fs.statSync(templateFilePath) - if (stats.isDirectory()) { - fs.mkdirSync(destFilePath, { recursive: true }); - copyTemplateFiles(templateFilePath, destFilePath); - } else { - // Replace placeholders in the file name - destFilePath = destFilePath.replace(/{{name}}/g, pluginName); + if (stats.isDirectory()) { + fs.mkdirSync(destFilePath, { recursive: true }) + copyTemplateFiles(templateFilePath, destFilePath) + } + else { + // Replace placeholders in the file name + destFilePath = destFilePath.replace(/\{\{name\}\}/g, pluginName) - let content = fs.readFileSync(templateFilePath, 'utf8'); + let content = fs.readFileSync(templateFilePath, 'utf8') - // Replace placeholders in the file content - content = content.replace(/{{name}}/g, pluginName); - content = content.replace(/{{export}}/g, exportNameFull); + // Replace placeholders in the file content + content = content.replace(/\{\{name\}\}/g, pluginName) + content = content.replace(/\{\{export\}\}/g, exportNameFull) - fs.writeFileSync(destFilePath, content); - } - }); + fs.writeFileSync(destFilePath, content) + } + }) } // Create the example file function createExampleFile() { - const exampleContent = ` + const exampleContent = ` // npm i artplayer-plugin-${pluginName} // import ${exportNameFull} from 'artplayer-plugin-${pluginName}'; @@ -88,18 +90,18 @@ var art = new Artplayer({ }), ], }); - `.trim(); + `.trim() - if (!fs.existsSync(exampleDir)) { - fs.mkdirSync(exampleDir, { recursive: true }); - } + if (!fs.existsSync(exampleDir)) { + fs.mkdirSync(exampleDir, { recursive: true }) + } - fs.writeFileSync(exampleFile, exampleContent); - console.log(`Example file created at ${exampleFile}`); + fs.writeFileSync(exampleFile, exampleContent) + console.log(`Example file created at ${exampleFile}`) } // Start copying template files and creating example file -copyTemplateFiles(templateDir, destDir); -createExampleFile(); +copyTemplateFiles(templateDir, destDir) +createExampleFile() -console.log(`Plugin ${pluginName} has been successfully created at ${destDir}`); +console.log(`Plugin ${pluginName} has been successfully created at ${destDir}`) diff --git a/scripts/plugin/template/package.json b/scripts/plugin/template/package.json index 8d4a3d6e4..5baca1781 100644 --- a/scripts/plugin/template/package.json +++ b/scripts/plugin/template/package.json @@ -1,24 +1,24 @@ { - "license": "MIT", - "version": "1.0.0", - "name": "artplayer-plugin-{{name}}", - "types": "types/artplayer-plugin-{{name}}.d.ts", - "description": "{{name}} plugin for ArtPlayer", - "main": "dist/artplayer-plugin-{{name}}.js", - "legacy": "dist/artplayer-plugin-{{name}}.legacy.js", - "author": "Harvey Zack ", - "browserslist": "last 1 Chrome version", - "homepage": "https://artplayer.org", - "repository": { - "type": "git", - "url": "git+https://github.com/zhw2590582/ArtPlayer.git" - }, - "bugs": { - "url": "https://github.com/zhw2590582/ArtPlayer/issues" - }, - "keywords": [ - "html5", - "video", - "player" - ] + "name": "artplayer-plugin-{{name}}", + "version": "1.0.0", + "description": "{{name}} plugin for ArtPlayer", + "author": "Harvey Zack ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "main": "dist/artplayer-plugin-{{name}}.js", + "types": "types/artplayer-plugin-{{name}}.d.ts", + "legacy": "dist/artplayer-plugin-{{name}}.legacy.js", + "browserslist": "last 1 Chrome version" } diff --git a/scripts/trans-docs.js b/scripts/trans-docs.js index e25e1da66..d3f79c1a7 100644 --- a/scripts/trans-docs.js +++ b/scripts/trans-docs.js @@ -1,171 +1,175 @@ -import fs from 'fs'; -import cpy from 'cpy'; -import path from 'path'; -import { glob } from 'glob'; -import { removeDir } from './utils.js'; -import dotenv from 'dotenv'; +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import cpy from 'cpy' +import dotenv from 'dotenv' +import { glob } from 'glob' +import { removeDir } from './utils.js' -dotenv.config(); +dotenv.config() // 配置常量 -const MAX_RETRIES = 3; -const RETRY_DELAY = 1000; // 1秒 -const MAX_CHARS_PER_REQUEST = 128000; -const BASE_PATH = 'packages/artplayer-vitepress/docs'; -const EN_PATH = 'packages/artplayer-vitepress/docs/en'; -const COPY_DIRS = ['advanced', 'component', 'plugin', 'start']; +const MAX_RETRIES = 3 +const RETRY_DELAY = 1000 // 1秒 +const MAX_CHARS_PER_REQUEST = 128000 +const BASE_PATH = 'packages/artplayer-vitepress/docs' +const EN_PATH = 'packages/artplayer-vitepress/docs/en' +const COPY_DIRS = ['advanced', 'component', 'plugin', 'start'] function splitMarkdown(text, maxChars) { - const parts = []; - let currentPart = ''; - let inCodeBlock = false; - let inSpecialBlock = false; + const parts = [] + let currentPart = '' + let inCodeBlock = false + let inSpecialBlock = false - const lines = text.split('\n'); - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; + const lines = text.split('\n') + for (let i = 0; i < lines.length; i++) { + const line = lines[i] - // 检测代码块 - if (line.trim().startsWith('```')) { - inCodeBlock = !inCodeBlock; - } - - // 检测特殊块 - if (line.trim().startsWith(':::')) { - inSpecialBlock = !inSpecialBlock; - } - - // 添加当前行到当前部分 - currentPart += line + '\n'; - - // 检测是否达到字符限制 - if (!inCodeBlock && !inSpecialBlock && currentPart.length > maxChars && i < lines.length - 1) { - parts.push(currentPart); - currentPart = ''; - } + // 检测代码块 + if (line.trim().startsWith('```')) { + inCodeBlock = !inCodeBlock } - // 添加最后一部分 - if (currentPart !== '') { - parts.push(currentPart); + // 检测特殊块 + if (line.trim().startsWith(':::')) { + inSpecialBlock = !inSpecialBlock } - return parts; + // 添加当前行到当前部分 + currentPart += `${line}\n` + + // 检测是否达到字符限制 + if (!inCodeBlock && !inSpecialBlock && currentPart.length > maxChars && i < lines.length - 1) { + parts.push(currentPart) + currentPart = '' + } + } + + // 添加最后一部分 + if (currentPart !== '') { + parts.push(currentPart) + } + + return parts } async function fetchWithRetry(url, options, retries = MAX_RETRIES) { - try { - const response = await fetch(url, { - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers, - }, - }); + try { + const response = await fetch(url, { + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers, + }, + }) - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - return await response.json(); - } catch (error) { - if (retries > 0) { - console.log(`Retrying... (${MAX_RETRIES - retries + 1}/${MAX_RETRIES})`); - await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY)); - return fetchWithRetry(url, options, retries - 1); - } - throw error; + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`) } + + return await response.json() + } + catch (error) { + if (retries > 0) { + console.log(`Retrying... (${MAX_RETRIES - retries + 1}/${MAX_RETRIES})`) + await new Promise(resolve => setTimeout(resolve, RETRY_DELAY)) + return fetchWithRetry(url, options, retries - 1) + } + throw error + } } -const translateContent = async (content, targetLanguage) => { - try { - const TRANSLATE_URL = 'https://api.deepseek.com/chat/completions'; - const response = await fetchWithRetry(TRANSLATE_URL, { - headers: { - Authorization: `Bearer ${process.env.DEEPL_API_KEY}`, - }, - method: 'POST', - body: JSON.stringify({ - stream: false, - model: 'deepseek-chat', - messages: [ - { - role: 'user', - content: `The following text is written in VitePress's extended Markdown syntax, Please translate it into ${targetLanguage}, and keep the Markdown format and don't add your explanation:\n\n${content}`, - }, - ], - }), - }); +async function translateContent(content, targetLanguage) { + try { + const TRANSLATE_URL = 'https://api.deepseek.com/chat/completions' + const response = await fetchWithRetry(TRANSLATE_URL, { + headers: { + Authorization: `Bearer ${process.env.DEEPL_API_KEY}`, + }, + method: 'POST', + body: JSON.stringify({ + stream: false, + model: 'deepseek-chat', + messages: [ + { + role: 'user', + content: `The following text is written in VitePress's extended Markdown syntax, Please translate it into ${targetLanguage}, and keep the Markdown format and don't add your explanation:\n\n${content}`, + }, + ], + }), + }) - return response.choices[0].message.content; - } catch (error) { - console.error(`Translation failed: ${error.message}`); - return content; // 返回原文作为回退 - } -}; + return response.choices[0].message.content + } + catch (error) { + console.error(`Translation failed: ${error.message}`) + return content // 返回原文作为回退 + } +} class ProgressTracker { - constructor(totalParts) { - this.totalParts = totalParts; - this.translatedPartsCount = 0; - } + constructor(totalParts) { + this.totalParts = totalParts + this.translatedPartsCount = 0 + } - update() { - this.translatedPartsCount++; - const progressPercentage = ((this.translatedPartsCount / this.totalParts) * 100).toFixed(2); - console.log(`Overall progress: ${progressPercentage}% (${this.translatedPartsCount}/${this.totalParts})`); - } + update() { + this.translatedPartsCount++ + const progressPercentage = ((this.translatedPartsCount / this.totalParts) * 100).toFixed(2) + console.log(`Overall progress: ${progressPercentage}% (${this.translatedPartsCount}/${this.totalParts})`) + } } -const translateMarkdownFiles = async (filePaths, targetLanguage, maxCharsPerRequest) => { - // 先计算总共有多少部分需要翻译 - let totalParts = 0; - for (const filePath of filePaths) { - const content = fs.readFileSync(filePath, 'utf-8'); - totalParts += splitMarkdown(content, maxCharsPerRequest).length; +async function translateMarkdownFiles(filePaths, targetLanguage, maxCharsPerRequest) { + // 先计算总共有多少部分需要翻译 + let totalParts = 0 + for (const filePath of filePaths) { + const content = fs.readFileSync(filePath, 'utf-8') + totalParts += splitMarkdown(content, maxCharsPerRequest).length + } + + console.log(`Starting translation of ${filePaths.length} files, total ${totalParts} parts.`) + const progressTracker = new ProgressTracker(totalParts) + + for (const filePath of filePaths) { + console.log(`Translating: ${path.relative(EN_PATH, filePath)}`) + + const content = fs.readFileSync(filePath, 'utf-8') + const parts = splitMarkdown(content, maxCharsPerRequest) + const translatedParts = [] + + for (const part of parts) { + const translatedPart = await translateContent(part, targetLanguage) + translatedParts.push(translatedPart) + progressTracker.update() } - console.log(`Starting translation of ${filePaths.length} files, total ${totalParts} parts.`); - const progressTracker = new ProgressTracker(totalParts); - - for (const filePath of filePaths) { - console.log(`Translating: ${path.relative(EN_PATH, filePath)}`); - - const content = fs.readFileSync(filePath, 'utf-8'); - const parts = splitMarkdown(content, maxCharsPerRequest); - const translatedParts = []; - - for (const part of parts) { - const translatedPart = await translateContent(part, targetLanguage); - translatedParts.push(translatedPart); - progressTracker.update(); - } - - const translatedContent = translatedParts.join('\n'); - fs.writeFileSync(filePath, translatedContent); - } -}; + const translatedContent = translatedParts.join('\n') + fs.writeFileSync(filePath, translatedContent) + } +} async function setupDirectoryStructure() { - // 清理并创建目录结构 - removeDir(EN_PATH); - await cpy(path.resolve(BASE_PATH, 'index.md'), path.resolve(EN_PATH)); + // 清理并创建目录结构 + removeDir(EN_PATH) + await cpy(path.resolve(BASE_PATH, 'index.md'), path.resolve(EN_PATH)) - // 并行复制所有目录 - await Promise.all( - COPY_DIRS.map((dir) => cpy(path.resolve(BASE_PATH, dir), path.resolve(EN_PATH, dir), { flat: true })), - ); + // 并行复制所有目录 + await Promise.all( + COPY_DIRS.map(dir => cpy(path.resolve(BASE_PATH, dir), path.resolve(EN_PATH, dir), { flat: true })), + ) } (async () => { - try { - await setupDirectoryStructure(); - const mdsPaths = glob.sync(path.resolve(EN_PATH, '**/*.md')); - await translateMarkdownFiles(mdsPaths, 'English', MAX_CHARS_PER_REQUEST); - console.log('Translation completed successfully!'); - } catch (error) { - console.error('Translation failed:', error); - process.exit(1); - } -})(); + try { + await setupDirectoryStructure() + const mdsPaths = glob.sync(path.resolve(EN_PATH, '**/*.md')) + await translateMarkdownFiles(mdsPaths, 'English', MAX_CHARS_PER_REQUEST) + console.log('Translation completed successfully!') + } + catch (error) { + console.error('Translation failed:', error) + process.exit(1) + } +})() diff --git a/scripts/utils.js b/scripts/utils.js index 6d472dd26..37d44a922 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -1,30 +1,32 @@ -import fs from 'fs'; -import path from 'path'; -import { glob } from 'glob'; +import fs from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import { glob } from 'glob' export function getProjects() { - return glob - .sync('packages/*') - .sort() - .filter((item) => !item.endsWith('artplayer-template') && !item.endsWith('artplayer-vitepress')) - .reduce((result, item) => { - const name = item.split(/\/|\\/g).pop(); - result[name] = path.resolve(process.cwd(), item); - return result; - }, {}); + return glob + .sync('packages/*') + .sort() + .filter(item => !item.endsWith('artplayer-template') && !item.endsWith('artplayer-vitepress')) + .reduce((result, item) => { + const name = item.split(/\/|\\/g).pop() + result[name] = path.resolve(process.cwd(), item) + return result + }, {}) } export function removeDir(dir) { - if (fs.existsSync(dir)) { - const files = fs.readdirSync(dir); - files.forEach((file) => { - const curPath = path.join(dir, file); - if (fs.statSync(curPath).isDirectory()) { - removeDir(curPath); - } else { - fs.unlinkSync(curPath); - } - }); - fs.rmdirSync(dir); - } + if (fs.existsSync(dir)) { + const files = fs.readdirSync(dir) + files.forEach((file) => { + const curPath = path.join(dir, file) + if (fs.statSync(curPath).isDirectory()) { + removeDir(curPath) + } + else { + fs.unlinkSync(curPath) + } + }) + fs.rmdirSync(dir) + } } diff --git a/svgo.config.json b/svgo.config.json index e8557bd42..fa18b9ef5 100644 --- a/svgo.config.json +++ b/svgo.config.json @@ -1,12 +1,12 @@ { - "plugins": [ - { - "name": "preset-default", - "params": { - "overrides": { - "removeViewBox": false - } - } + "plugins": [ + { + "name": "preset-default", + "params": { + "overrides": { + "removeViewBox": false } - ] + } + } + ] }