wpsjs
Version:
用于开发wps加载项的工具包
209 lines (186 loc) • 7.55 kB
JavaScript
const inquirer = require('inquirer')
const fs = require('fs')
const fsEx = require('fs-extra')
const path = require('path')
const _7z = require('node-7z');
const _7zBin = require('7zip-bin')
const jsUtil = require('./util.js')
let projectCfg = jsUtil.projectCfg()
const chalk = require('chalk');
const { serialize } = require('v8');
const buildDirectory = jsUtil.GetBuildDir()
async function build(cmd) {
if (cmd.parent.rawArgs[cmd.parent.rawArgs.length - 1].includes("exe"))
{
if (false == new RegExp("^[!-~]+$").test(projectCfg.name)){
console.log(`${chalk.red("项目名只能是字母、数字和下划线")}...`)
return
}
buildwithSelfArchive()
return
}
inquirer.prompt({
name: 'pluginType',
type: 'list',
message: `选择 WPS 加载项发布类型:`,
choices: [{
name: '在线插件',
value: 'online'
},
{
name: '离线插件',
value: 'offline'
}
]
}).then(answers => {
return buildWithArgs(answers)
}).then(buildDir=>{
console.log(chalk.cyan(`\n==>> 编译成功。请将目录${buildDir}下的文件署到服务器...`))
})
}
async function buildWithArgs(answers) {
return new Promise((r,j)=>{
let debugTemp = jsUtil.GetDebugTempPath(true);
fsEx.removeSync(debugTemp)
let curDir = process.cwd()
let buildDir = curDir
if (projectCfg.scripts && typeof projectCfg.scripts.build == 'string') {
let buildCmd = projectCfg.scripts.build.trim();
if (buildCmd.includes("vite")) {
buildDir = require('./buildvue')(answers)
} else if (buildCmd.includes("react-scripts")) {
buildDir = require('./buildreact')(answers)
}
}
let publishRoot = path.resolve(curDir, jsUtil.GetPublishDir());
fsEx.removeSync(publishRoot);
let buildRoot = path.resolve(curDir, buildDirectory);
let distPath = buildRoot
if (answers.pluginType == "offline")
distPath = path.resolve(buildRoot, `${projectCfg.name}_${projectCfg.version}`)
fsEx.removeSync(buildRoot)
fs.readdir(buildDir, (_, files) => {
files.forEach(file => {
if (file != buildDirectory && file != "node_modules" &&
file != ".vscode" && file != ".git" &&
file != "package.json" && file != "package-lock.json") {
const srcPath = path.resolve(buildDir, file)
fsEx.copySync(srcPath, path.resolve(distPath, file))
}
})
if (answers.pluginType == "offline") {
let path7z = path.resolve(buildRoot, `${projectCfg.name}.7z`)
let inputPaths = [distPath]
const stream7z = _7z.add(path7z, inputPaths, {
recursive: false,
$bin: _7zBin.path7za
});
stream7z.on('end', ()=>{
fsEx.removeSync(distPath)
})
}
const buildResultDir = path.resolve(process.cwd(), buildDirectory)
r(buildResultDir)
})
})
}
async function buildwithSelfArchive(){
buildWithArgs('online').then(buildDir=>{
let curDir = process.cwd()
let buildRoot = path.resolve(curDir, 'dist')
if (!projectCfg.scripts){
fsEx.removeSync(buildRoot)
fsEx.copySync(buildDir, buildRoot)
}
let exePath = path.resolve(buildDir, `${projectCfg.name}.exe`)
createSelfExtractingExe(buildDir, buildRoot, exePath)
})
}
async function createSelfExtractingExe(buildDir, inputFolder, outputFile) {
const sfxPath = path.join(__dirname, 'res/7zsd.sfx');
if (!fs.existsSync(sfxPath)) {
console.error('7zsd.sfx not found. Please make sure it exists in the same folder as this script');
return;
}
const configFileBuffer = createSfxConfig(outputFile);
const zipBuffer = await create7ZipBuffer(buildDir, inputFolder);
// 创建自解压 exe 文件
const ws = fs.createWriteStream(outputFile);
ws.write(fs.readFileSync(sfxPath));
ws.write(configFileBuffer);
let path7z = path.resolve(buildDir, `${projectCfg.name}.7z`)
ws.write(fs.readFileSync(path7z));
ws.end(()=>{fsEx.removeSync(path7z)});
console.log('Self-extracting EXE created:', outputFile);
}
function createSfxConfig(outputFile) {
return Buffer.from(`
;!@Install@!UTF-8!
Title="install wps jsaddons"
BeginPrompt="确定要安装${projectCfg.name}?"
RunProgram="copy.bat"
;!@InstallEnd@!
`, 'utf-8');
}
function CreateCopyBat() {
return Buffer.from(`
@echo off
set source_folder=${projectCfg.name}_${projectCfg.version}
set destination_folder=%appdata%/kingsoft/wps/jsaddons
if not exist "%destination_folder%" (
mkdir "%destination_folder%"
)
if not exist "%destination_folder%/%source_folder%" (
mkdir "%destination_folder%/%source_folder%"
)
xcopy /E /I /Y "%source_folder%" "%destination_folder%/%source_folder%"
xcopy /E /I /Y "publish.xml" "%destination_folder%"
`, 'utf-8');
}
function CreatePublishXml(nameStr, typeStr, versionStr){
return Buffer.from(`
<jsplugins>
<jsplugin name="${nameStr}" type="${typeStr}" url="${nameStr}_${versionStr}" version="${versionStr}" enable="enable_dev" install="null" customDomain=""/>
</jsplugins>
`);
}
async function create7ZipBuffer(buildDir, inputFolder) {
return new Promise((resolve, reject) => {
let distDir = path.resolve(process.cwd(), 'dist')
let tmp7zDir = path.resolve(buildDir, '7ztmpDir')
let projDir = path.resolve(tmp7zDir, projectCfg.name + '_' + projectCfg.version)
fsEx.ensureDirSync(tmp7zDir)
fsEx.copy(distDir, projDir).then(()=>{
new Promise(r=>{
let batPath = path.resolve(tmp7zDir, "copy.bat")
const ws = fs.createWriteStream(batPath)
ws.write(CreateCopyBat())
ws.end(()=>{r()})
}).then(()=>{
new Promise(r=>{
let publishXmlPath = path.resolve(tmp7zDir, "publish.xml")
const ws = fs.createWriteStream(publishXmlPath)
ws.write(CreatePublishXml(projectCfg.name, projectCfg.addonType, projectCfg.version))
ws.end(()=>{r()})
})
}).then(()=>{
let path7z = path.resolve(buildDir, `${projectCfg.name}.7z`)
let inputPaths = [path.resolve(tmp7zDir, "copy.bat"), path.resolve(tmp7zDir, "publish.xml"), projDir]
const stream7z = _7z.add(path7z, inputPaths, {
recursive: false,
$bin: _7zBin.path7za
});
stream7z.on('end', info=>{
fsEx.removeSync(tmp7zDir)
resolve()
}).on('error', err=>{
reject(err)
})
})
})
})
}
module.exports = {
build,
buildWithArgs
}