feat: add builder configuration file
feat: add cocos-service configuration file feat: add device configuration file feat: add engine configuration file feat: add information configuration file feat: add program configuration file feat: add project configuration file feat: add TypeScript configuration file
This commit is contained in:
104
extensions/quick-compress-image/.gitignore
vendored
Normal file
104
extensions/quick-compress-image/.gitignore
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
21
extensions/quick-compress-image/LICENSE
Normal file
21
extensions/quick-compress-image/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 McvCar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
2
extensions/quick-compress-image/README.md
Normal file
2
extensions/quick-compress-image/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# quickCompressImage
|
||||
这是cocos creator 快速压缩图片插件
|
||||
9
extensions/quick-compress-image/i18n/en.js
Normal file
9
extensions/quick-compress-image/i18n/en.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* menu
|
||||
*/
|
||||
'name': 'x',
|
||||
'compressPicture': 'Compress Picture',
|
||||
'menu': 'Compress Picture',
|
||||
'setting': 'Setting',
|
||||
};
|
||||
9
extensions/quick-compress-image/i18n/zh.js
Normal file
9
extensions/quick-compress-image/i18n/zh.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* 菜单
|
||||
*/
|
||||
'name': 'x',
|
||||
'compressPicture': '压缩图片',
|
||||
'menu': '快闪·压缩图片',
|
||||
'setting': '设置',
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "mozjpeg",
|
||||
"version": "8.0.0",
|
||||
"description": "mozjpeg wrapper that makes it seamlessly available as a local dependency",
|
||||
"license": "MIT",
|
||||
"repository": "imagemin/mozjpeg-bin",
|
||||
"type": "module",
|
||||
"exports": "./index.js",
|
||||
"bin": "cli.js",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node lib/install.js",
|
||||
"test": "xo && ava --timeout=120s",
|
||||
"build-linux": "docker build --tag imagemin/mozjpeg docker && docker run --rm --volume $(pwd)/vendor/linux:/src/out imagemin/mozjpeg cp cjpeg /src/out"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"cli.js",
|
||||
"lib",
|
||||
"vendor/source"
|
||||
],
|
||||
"keywords": [
|
||||
"imagemin",
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"img",
|
||||
"image",
|
||||
"compress",
|
||||
"minify",
|
||||
"mozjpeg",
|
||||
"optimize"
|
||||
],
|
||||
"dependencies": {
|
||||
"bin-build": "^3.0.0",
|
||||
"bin-wrapper": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^3.8.0",
|
||||
"bin-check": "^4.1.0",
|
||||
"compare-size": "^3.0.0",
|
||||
"execa": "^5.1.1",
|
||||
"tempy": "^2.0.0",
|
||||
"xo": "^0.45.0"
|
||||
},
|
||||
"ava": {
|
||||
"serial": true
|
||||
}
|
||||
}
|
||||
13098
extensions/quick-compress-image/lib/imagemin.min.js
vendored
Normal file
13098
extensions/quick-compress-image/lib/imagemin.min.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
||||
/*!
|
||||
* fill-range <https://github.com/jonschlinkert/fill-range>
|
||||
*
|
||||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* is-extglob <https://github.com/jonschlinkert/is-extglob>
|
||||
*
|
||||
* Copyright (c) 2014-2016, Jon Schlinkert.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* is-glob <https://github.com/jonschlinkert/is-glob>
|
||||
*
|
||||
* Copyright (c) 2014-2017, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* is-number <https://github.com/jonschlinkert/is-number>
|
||||
*
|
||||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* to-regex-range <https://github.com/micromatch/to-regex-range>
|
||||
*
|
||||
* Copyright (c) 2015-present, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
77
extensions/quick-compress-image/lib/imageminApi.js
Normal file
77
extensions/quick-compress-image/lib/imageminApi.js
Normal file
@@ -0,0 +1,77 @@
|
||||
let Path = require('path')
|
||||
let Fs = require('fs');
|
||||
let imageminApi = require('../lib/imagemin.min')
|
||||
let packageCfg = require('../package.json')
|
||||
|
||||
module.exports = {
|
||||
|
||||
async getZipRate(){
|
||||
let rate = parseInt(await Editor.Profile.getConfig(packageCfg.name,'zipRate')) || 30;
|
||||
if(rate<0){
|
||||
rate = 1;
|
||||
}else if(rate>100){
|
||||
rate = 100
|
||||
}
|
||||
|
||||
return rate;
|
||||
},
|
||||
|
||||
/**
|
||||
* 调用压缩工具api
|
||||
* @param {Array<{file:string,uuid:string}>} fileInfo
|
||||
*/
|
||||
async compressPicture(arrList,imageFileList){
|
||||
let rate = await this.getZipRate();
|
||||
let pngRate = rate*0.01;
|
||||
|
||||
console.log("压缩值:",rate+"%");
|
||||
|
||||
imageminApi.imagemin(arrList, {
|
||||
plugins: [
|
||||
imageminApi.imageminMozjpeg({ quality: rate }), //压缩质量(0,1)
|
||||
imageminApi.imageminPngquant({
|
||||
quality: [pngRate, Math.min(pngRate+0.25,1)] //压缩质量(0,1)
|
||||
})
|
||||
]
|
||||
|
||||
}).then((arrRes) => {
|
||||
console.log("压缩成功,详情:\n")
|
||||
for (let i = 0; i < arrRes.length; i++) {
|
||||
const res = arrRes[i];
|
||||
this.onCompressedSucceed(imageFileList,res)
|
||||
}
|
||||
|
||||
}).catch(err => {
|
||||
console.log("压缩失败:",err)
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 压缩成功
|
||||
* @param {Array<{file:string,uuid:string,size:number}>} imageFileList
|
||||
* @param {Object<{data:Buffer,sourcePath:string}>} res
|
||||
*/
|
||||
onCompressedSucceed(imageFileList,res){
|
||||
let desc = ""
|
||||
for (let i = 0; i < imageFileList.length; i++) {
|
||||
const fileInfo = imageFileList[i];
|
||||
if(fileInfo.file.replace(/\\/g,'/') == res.sourcePath){
|
||||
const fileName = Path.basename(fileInfo.file);
|
||||
const newSize = res.data.byteLength;
|
||||
const rate = (fileInfo.size-newSize)/fileInfo.size;
|
||||
const oldMb = (fileInfo.size / 1024).toFixed(1) + " KB";
|
||||
const newMb = (newSize / 1024).toFixed(1) + " KB";
|
||||
if(newSize < fileInfo.size){
|
||||
Fs.writeFileSync(res.sourcePath, res.data)
|
||||
desc += `${fileName}、压缩率:${parseInt(rate*100)}%、压缩前后大小:${newMb} / ${oldMb}`
|
||||
}else{
|
||||
desc += `${fileName}、无法继续压缩`
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
console.log(desc);
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
89
extensions/quick-compress-image/lib/tinypngApi.js
Normal file
89
extensions/quick-compress-image/lib/tinypngApi.js
Normal file
@@ -0,0 +1,89 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const https = require("https");
|
||||
const URL = require("url").URL;
|
||||
const EventEmitter = require("events");
|
||||
const err = (msg) => new EventEmitter().emit("error", msg);
|
||||
|
||||
/**
|
||||
* TinyPng 远程压缩 HTTPS 请求的配置生成方法
|
||||
*/
|
||||
|
||||
function getAjaxOptions() {
|
||||
return {
|
||||
method: "POST",
|
||||
hostname: "tinypng.com",
|
||||
path: "/web/shrink",
|
||||
headers: {
|
||||
rejectUnauthorized: false,
|
||||
"X-Forwarded-For": Array(4)
|
||||
.fill(1)
|
||||
.map(() => parseInt(Math.random() * 254 + 1))
|
||||
.join("."),
|
||||
"Postman-Token": Date.now(),
|
||||
"Cache-Control": "no-cache",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* TinyPng 远程压缩 HTTPS 请求
|
||||
* @param {string} img 待处理的文件
|
||||
* @success {
|
||||
* "input": { "size": 887, "type": "image/png" },
|
||||
* "output": { "size": 785, "type": "image/png", "width": 81, "height": 81, "ratio": 0.885, "url": "https://tinypng.com/web/output/7aztz90nq5p9545zch8gjzqg5ubdatd6" }
|
||||
* }
|
||||
* @error {"error": "Bad request", "message" : "Request is invalid"}
|
||||
*/
|
||||
function fileUpload(imgPath) {
|
||||
let req = https.request(getAjaxOptions(), (res) => {
|
||||
res.on("data", (buf) => {
|
||||
let obj = JSON.parse(buf.toString());
|
||||
if (obj.error)
|
||||
console.log(`压缩失败!\n 当前文件:${imgPath} \n ${obj.message}`);
|
||||
else fileUpdate(imgPath, obj);
|
||||
});
|
||||
});
|
||||
|
||||
req.write(fs.readFileSync(imgPath), "binary");
|
||||
req.on("error", (e) =>
|
||||
console.log(`请求错误! 当前文件:${path.basename(imgPath)} \n`, e)
|
||||
);
|
||||
req.end();
|
||||
}
|
||||
|
||||
// 该方法被循环调用,请求图片数据
|
||||
function fileUpdate(entryImgPath, obj) {
|
||||
let options = new URL(obj.output.url);
|
||||
let req = https.request(options, (res) => {
|
||||
let body = "";
|
||||
res.setEncoding("binary");
|
||||
res.on("data", (data) => (body += data));
|
||||
res.on("end", () => {
|
||||
fs.writeFile(entryImgPath, body, "binary", (err) => {
|
||||
if (err) return console.error(err);
|
||||
let log = `压缩成功:`;
|
||||
log += `${path.basename(entryImgPath)}、压缩率:${ ((1 - obj.output.ratio) * 100).toFixed(2) }%、压缩前后大小:${(obj.output.size / 1024).toFixed(2)} / ${(obj.input.size / 1024).toFixed(2)}`
|
||||
console.log(log);
|
||||
});
|
||||
});
|
||||
});
|
||||
req.on("error", (e) => console.warn('压缩失败:',path.basename(entryImgPath) ,e));
|
||||
req.end();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* 调用压缩工具api
|
||||
* @param {Array<{file:string,uuid:string}>} fileInfo
|
||||
*/
|
||||
async compressPicture(arrList,imageFileList){
|
||||
for (let i = 0; i < arrList.length; i++) {
|
||||
const imgPath = arrList[i];
|
||||
fileUpload(imgPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
extensions/quick-compress-image/lib/vendor/cjpeg
vendored
Normal file
BIN
extensions/quick-compress-image/lib/vendor/cjpeg
vendored
Normal file
Binary file not shown.
BIN
extensions/quick-compress-image/lib/vendor/cjpeg.exe
vendored
Normal file
BIN
extensions/quick-compress-image/lib/vendor/cjpeg.exe
vendored
Normal file
Binary file not shown.
BIN
extensions/quick-compress-image/lib/vendor/pngquant
vendored
Normal file
BIN
extensions/quick-compress-image/lib/vendor/pngquant
vendored
Normal file
Binary file not shown.
BIN
extensions/quick-compress-image/lib/vendor/pngquant-ppc
vendored
Normal file
BIN
extensions/quick-compress-image/lib/vendor/pngquant-ppc
vendored
Normal file
Binary file not shown.
BIN
extensions/quick-compress-image/lib/vendor/pngquant.exe
vendored
Normal file
BIN
extensions/quick-compress-image/lib/vendor/pngquant.exe
vendored
Normal file
Binary file not shown.
10651
extensions/quick-compress-image/package-lock.json
generated
Normal file
10651
extensions/quick-compress-image/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
78
extensions/quick-compress-image/package.json
Normal file
78
extensions/quick-compress-image/package.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"name": "quick-compress-image",
|
||||
"package_version": 2,
|
||||
"version": "1.0.1",
|
||||
"description": "Compress a picture",
|
||||
"author": "嘉年华",
|
||||
"main": "./src/browser.js",
|
||||
"contributions": {
|
||||
"menu": [{
|
||||
"path": "i18n:menu.extension/i18n:quick-compress-image.menu",
|
||||
"label": "i18n:quick-compress-image.setting",
|
||||
"message": "setting"
|
||||
}],
|
||||
"messages": {
|
||||
"setting": {
|
||||
"methods": ["setting"]
|
||||
}
|
||||
},
|
||||
"assets": {
|
||||
"menu": {
|
||||
"methods": "./src/assets-menu.js",
|
||||
"createMenu": "onCreateMenu",
|
||||
"assetMenu": "onAssetMenu"
|
||||
}
|
||||
},
|
||||
|
||||
"profile": {
|
||||
"editor": {
|
||||
"zipRate": {
|
||||
"default": 70,
|
||||
"label": "压缩值(0-100%)"
|
||||
},
|
||||
"zipMode":{
|
||||
"default": 0,
|
||||
"label": "压缩模式"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"preferences": {
|
||||
"label" : "图片压缩",
|
||||
"properties": {
|
||||
"zipRate": {
|
||||
"ui": "ui-num-input"
|
||||
},
|
||||
"zipMode": {
|
||||
"ui": "ui-select",
|
||||
"items": [
|
||||
{
|
||||
"value": 0,
|
||||
"label": "Imagemin"
|
||||
},
|
||||
{
|
||||
"value": 1,
|
||||
"label": "Tinypng"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"panels": {
|
||||
"default": {
|
||||
"title": "快闪·压缩图片",
|
||||
"type": "dockable",
|
||||
"main": "src/setting-panel",
|
||||
"size": {
|
||||
"width": 280,
|
||||
"height": 260
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
}
|
||||
}
|
||||
113
extensions/quick-compress-image/src/assets-menu.js
Normal file
113
extensions/quick-compress-image/src/assets-menu.js
Normal file
@@ -0,0 +1,113 @@
|
||||
let Path = require('path')
|
||||
let Fs = require('fs');
|
||||
let imageminApi = require('../lib/imageminApi')
|
||||
let tinypngApi = require('../lib/tinypngApi')
|
||||
let statistical = require('./tools/statistical')
|
||||
let packageCfg = require('../package.json');
|
||||
const tools = require('./tools/tools');
|
||||
|
||||
let AssetsMenu = {
|
||||
|
||||
onAssetMenu(assetInfo) {
|
||||
if(assetInfo.importer != 'image'){
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: 'i18n:quick-compress-image.compressPicture',
|
||||
enabled: true,
|
||||
click() {
|
||||
if(confirm('确定压缩图片?')){
|
||||
AssetsMenu.onStartCompressPicture(assetInfo)
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
onCreateMenu(assetInfo) {
|
||||
statistical.countStartupTimes();
|
||||
return [];
|
||||
},
|
||||
|
||||
isImageFile(filePath){
|
||||
let extname = Path.extname(filePath).toLocaleLowerCase()
|
||||
if(extname == '.png' || extname == '.jpg' || extname == '.jpeg'){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
getFileSize(fsPath){
|
||||
try {
|
||||
return Fs.statSync(fsPath).size
|
||||
} catch (error) {
|
||||
return -1
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 返回选中的图片
|
||||
* @param {*} assetInfo
|
||||
* @returns {Promise<Array<{file:string,uuid:string,size:number}>>}
|
||||
*/
|
||||
async getImageFileList(assetInfo){
|
||||
let fileUuidList = Editor.Selection.getSelected('asset');
|
||||
let imageFileList = [];
|
||||
|
||||
if(fileUuidList.includes(assetInfo.uuid)){
|
||||
for (let i = 0; i < fileUuidList.length; i++) {
|
||||
const uuid = fileUuidList[i];
|
||||
const fsPath = await Editor.Message.request("asset-db",'query-path',uuid);
|
||||
|
||||
if(fsPath && this.isImageFile(fsPath)){
|
||||
imageFileList.push({
|
||||
file: fsPath,
|
||||
uuid: uuid,
|
||||
size: this.getFileSize(fsPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
if(assetInfo.file && this.isImageFile(assetInfo.file)){
|
||||
imageFileList.push({
|
||||
file: assetInfo.file,
|
||||
uuid: assetInfo.uuid,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return imageFileList;
|
||||
},
|
||||
|
||||
async getMode(){
|
||||
let mode = tools.isX64() ? await Editor.Profile.getConfig(packageCfg.name,'zipMode') || 0 : 1;
|
||||
return mode;
|
||||
},
|
||||
|
||||
async onStartCompressPicture(assetInfo){
|
||||
let imageFileList = await this.getImageFileList(assetInfo);
|
||||
if(imageFileList.length == 0){
|
||||
return console.log("不支持该图片格式的压缩")
|
||||
}
|
||||
let arrList = [];
|
||||
for (let i = 0; i < imageFileList.length; i++) {
|
||||
const fileInfo = imageFileList[i];
|
||||
arrList.push(fileInfo.file);
|
||||
}
|
||||
|
||||
let mode = await this.getMode();
|
||||
if(mode == 0){
|
||||
console.log("---------------------压缩模式:Imagemin---------------------------");
|
||||
imageminApi.compressPicture(arrList,imageFileList);
|
||||
}else{
|
||||
console.log("---------------------压缩模式:TinyPng---------------------------");
|
||||
tinypngApi.compressPicture(arrList,imageFileList);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = AssetsMenu;
|
||||
|
||||
15
extensions/quick-compress-image/src/browser.js
Normal file
15
extensions/quick-compress-image/src/browser.js
Normal file
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
exports.methods={
|
||||
'setting'(){
|
||||
Editor.Panel.open('quick-compress-image')
|
||||
}
|
||||
}
|
||||
|
||||
exports.load=function(){
|
||||
|
||||
}
|
||||
|
||||
exports.unload=function(){
|
||||
|
||||
};
|
||||
58
extensions/quick-compress-image/src/setting-panel.js
Normal file
58
extensions/quick-compress-image/src/setting-panel.js
Normal file
@@ -0,0 +1,58 @@
|
||||
let fs = require('fs')
|
||||
let path = require('path')
|
||||
let packageCfg = require('../package.json')
|
||||
const tools = require('./tools/tools')
|
||||
Editor.Panel.define = Editor.Panel.define || ((args)=>{return args})
|
||||
|
||||
|
||||
function saveConfig(doms){
|
||||
Editor.Profile.setConfig(packageCfg.name,'zipRate',doms.zipRateSlider.value);
|
||||
Editor.Profile.setConfig(packageCfg.name,'zipMode',doms.zipModeTab.value);
|
||||
}
|
||||
|
||||
async function getMode(){
|
||||
let mode = tools.isX64() ? await Editor.Profile.getConfig(packageCfg.name,'zipMode') || 0 : 1;
|
||||
return mode;
|
||||
}
|
||||
|
||||
module.exports = Editor.Panel.define({
|
||||
template: fs.readFileSync(path.join(__dirname, '../template/setting.html'), 'utf-8'),
|
||||
style: fs.readFileSync(path.join(__dirname, '../template/setting.css'), 'utf-8'),
|
||||
|
||||
$: {
|
||||
zipRateSlider: '#zipRateSlider',
|
||||
saveBtn: '#saveBtn',
|
||||
zipModeTab: '#zipModeTab',
|
||||
},
|
||||
|
||||
async ready() {
|
||||
this.$.zipRateSlider.value = parseInt(await Editor.Profile.getConfig(packageCfg.name,'zipRate')) || 30;
|
||||
this.$.zipModeTab.value = await getMode();
|
||||
this.$.zipModeTab.value == 1 ? this.$.zipRateSlider.disabled = true : this.$.zipRateSlider.removeAttribute('disabled');
|
||||
this.$.zipModeTab.addEventListener('click',()=>{
|
||||
let mode = this.$.zipModeTab.value;
|
||||
if(!tools.isX64() && mode == 0){
|
||||
this.$.zipModeTab.value = 1;
|
||||
this.$.zipRateSlider.disabled = true
|
||||
alert('CPU不支持该模式');
|
||||
}else{
|
||||
this.$.zipModeTab.value == 1 ? this.$.zipRateSlider.disabled = true : this.$.zipRateSlider.removeAttribute('disabled');
|
||||
saveConfig(this.$);
|
||||
}
|
||||
},0)
|
||||
|
||||
this.$.saveBtn.addEventListener('click',()=>{
|
||||
saveConfig(this.$);
|
||||
},0)
|
||||
},
|
||||
|
||||
|
||||
listeners: {
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
beforeClose() { },
|
||||
close() {
|
||||
saveConfig(this.$);
|
||||
},
|
||||
});
|
||||
20
extensions/quick-compress-image/src/tools/statistical.js
Normal file
20
extensions/quick-compress-image/src/tools/statistical.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const tools = require("./tools")
|
||||
|
||||
let isStatistical = false;
|
||||
module.exports = {
|
||||
|
||||
// 用户使用次数统计
|
||||
countStartupTimes(){
|
||||
if(!isStatistical && Editor.User && Editor.User.getData){
|
||||
Editor.User.getData().then((post_data)=>{
|
||||
if(!post_data) {
|
||||
return
|
||||
}
|
||||
post_data.version = Editor.App ? Editor.App.version : "?";
|
||||
tools.httpPost('120.77.174.207','/compressImageLogincount',8081,post_data);
|
||||
});
|
||||
isStatistical = true;
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
560
extensions/quick-compress-image/src/tools/tools.js
Normal file
560
extensions/quick-compress-image/src/tools/tools.js
Normal file
@@ -0,0 +1,560 @@
|
||||
let fs = require("fs");
|
||||
let path = require("path");
|
||||
let packageCfg = require("../../package.json")
|
||||
var http = require('http');
|
||||
var querystring = require('querystring');
|
||||
var os = require('os');
|
||||
|
||||
const inputType = { "text": 1, "password": 1, "number": 1, "date": 1, "color": 1, "range": 1, "month": 1, "week": 1, "time": 1, "email": 1, "search": 1, "url": 1, "textarea": 1 }
|
||||
let checkFsPath = new RegExp("\\.\\./", "g");
|
||||
let readFileQueue = []
|
||||
let readFileMaxCount = 50
|
||||
let readFileCount = 0
|
||||
|
||||
let translateMap = {}
|
||||
|
||||
module.exports = {
|
||||
|
||||
isX64(){
|
||||
return os.arch() == 'x64'
|
||||
},
|
||||
|
||||
// 不是输入状态是时
|
||||
inputTypeChk(e) {
|
||||
if (e.path[0]) {
|
||||
let type = e.path[0].type;
|
||||
if (inputType[type]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getLanguage(){
|
||||
return window.navigator && window.navigator.language && window.navigator.language.split('-')[0];
|
||||
},
|
||||
|
||||
// 更新i18翻译文本,解决creator不重启不会刷新修改问题
|
||||
initI18t(){
|
||||
let locale = this.getLanguage() || 'zh';
|
||||
let filePath = Editor2D.url('packages://simple-code/i18n/'+locale+'.js');
|
||||
if(!this.isFileExit(filePath)){
|
||||
return
|
||||
}
|
||||
let mapList = require(filePath);
|
||||
let converList = {}
|
||||
for (const key in mapList) {
|
||||
const converText = mapList[key];
|
||||
converList[packageCfg.name+'.'+key] = converText
|
||||
}
|
||||
translateMap = converList;
|
||||
// Editor.i18n.extend(converList)
|
||||
},
|
||||
|
||||
translate(key){
|
||||
let name = packageCfg.name+'.'+key
|
||||
return translateMap[name] || Editor2D.T(name) || name
|
||||
},
|
||||
|
||||
translateZhAndEn(zeText,enText){
|
||||
return this.getLanguage() == 'zh' ? zeText : enText;
|
||||
},
|
||||
|
||||
// 翻译中英文
|
||||
T(zeText,enText){
|
||||
return this.translateZhAndEn(zeText,enText);
|
||||
},
|
||||
|
||||
isEmptyObject(obj){
|
||||
if(obj){
|
||||
for (const key in obj) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// 拷贝本对象方法到目标对象
|
||||
// newObj 子类
|
||||
// baseObj 父类
|
||||
// mergeFuncs = ["init"]; 新旧类的同名函数合并一起
|
||||
extendTo(newObj, baseObj, mergeFuncs = []) {
|
||||
if (!baseObj || !newObj) return;
|
||||
|
||||
for (let k in baseObj) {
|
||||
let v = baseObj[k]
|
||||
if (newObj[k] == null) {
|
||||
newObj[k] = v
|
||||
}
|
||||
// 函数继承使用 "this._super()" 调用父类
|
||||
else if (typeof v == "function" && typeof newObj[k] == "function" && !newObj[k]._isExend) {
|
||||
let newFunc = newObj[k];
|
||||
newObj[k] = function () {
|
||||
this._super = v;
|
||||
let ret = newFunc.apply(this, arguments);// 执行函数并传入传参
|
||||
delete this._super;
|
||||
return ret;
|
||||
};
|
||||
newObj[k]._isExend = true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copyToClipboard(str) {
|
||||
var input = str;
|
||||
const el = document.createElement('textarea');
|
||||
el.value = input;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style.contain = 'strict';
|
||||
el.style.position = 'absolute';
|
||||
el.style.left = '-9999px';
|
||||
el.style.fontSize = '12pt'; // Prevent zooming on iOS
|
||||
|
||||
const selection = getSelection();
|
||||
var originalRange = false;
|
||||
if (selection.rangeCount > 0) {
|
||||
originalRange = selection.getRangeAt(0);
|
||||
}
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
el.selectionStart = 0;
|
||||
el.selectionEnd = input.length;
|
||||
|
||||
var success = false;
|
||||
try {
|
||||
success = document.execCommand('copy');
|
||||
} catch (err) { }
|
||||
|
||||
document.body.removeChild(el);
|
||||
|
||||
if (originalRange) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(originalRange);
|
||||
}
|
||||
|
||||
return success;
|
||||
},
|
||||
|
||||
parseJson(text){
|
||||
try {
|
||||
return JSON.parse(text)
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
objectCount(obj){
|
||||
let len = 0
|
||||
for (const key in obj) {
|
||||
len++
|
||||
}
|
||||
return len;
|
||||
},
|
||||
|
||||
// 获得import路径
|
||||
getImportStringPaths(codeText) {
|
||||
|
||||
var regEx = /(require\(|import |reference path=)(.{0,}['"])(.+)['"]/g;
|
||||
var match = regEx.exec(codeText);
|
||||
var imports = []
|
||||
while (match) {
|
||||
let start = match.index + match[1].length + match[2].length;
|
||||
imports.push({
|
||||
path: match[3],
|
||||
start: start,
|
||||
length: match[3].length,
|
||||
})
|
||||
match = regEx.exec(codeText);
|
||||
}
|
||||
return imports
|
||||
},
|
||||
|
||||
//将相对路径转为绝对路径
|
||||
relativePathTofsPath(absolutePath, relativePath) {
|
||||
var uplayCount = 0; // 相对路径中返回上层的次数。
|
||||
var m = relativePath.match(checkFsPath);
|
||||
if (m) uplayCount = m.length;
|
||||
|
||||
var lastIndex = absolutePath.length - 1;
|
||||
var subString = absolutePath
|
||||
for (var i = 0; i <= uplayCount; i++) {
|
||||
lastIndex = subString.lastIndexOf("/", lastIndex);
|
||||
subString = subString.substr(0, lastIndex)
|
||||
}
|
||||
return this.normPath( subString + "/" + relativePath.substr(relativePath.lastIndexOf('./') + 2));
|
||||
},
|
||||
|
||||
//将绝对路径转为相对路径
|
||||
fsPathToRelativePath(currPath, importPath) {
|
||||
let s_i = currPath.lastIndexOf('/')
|
||||
if (s_i != -1) currPath = currPath.substr(0, s_i);
|
||||
let relativePath = path.relative(currPath, importPath);
|
||||
if (relativePath[0] != '.') {
|
||||
relativePath = './' + relativePath;
|
||||
}
|
||||
return this.normPath(relativePath);
|
||||
},
|
||||
|
||||
|
||||
//转换相对路径
|
||||
converRelative(relativePath, oldFilePath, newFilePath) {
|
||||
let s_i = oldFilePath.lastIndexOf('/')
|
||||
if (s_i != -1) oldFilePath = oldFilePath.substr(0, s_i);
|
||||
s_i = newFilePath.lastIndexOf('/')
|
||||
if (s_i != -1) newFilePath = newFilePath.substr(0, s_i);
|
||||
|
||||
let rve_to_abs = this.normPath(path.resolve(oldFilePath, relativePath));
|
||||
relativePath = this.normPath(path.relative(newFilePath, rve_to_abs));
|
||||
if (relativePath[0] != '.') {
|
||||
relativePath = './' + relativePath;
|
||||
}
|
||||
return relativePath;
|
||||
},
|
||||
|
||||
|
||||
|
||||
normPath(filePath) {
|
||||
return filePath.replace(/\\/g, '/');
|
||||
},
|
||||
|
||||
// 异步读取文件
|
||||
readFileAsyn(filePath,callback)
|
||||
{
|
||||
let args = {filePath,callback};
|
||||
readFileQueue.push(args)
|
||||
// 最多同时读取50个文件
|
||||
readFileCount++;
|
||||
if(readFileCount >= readFileMaxCount){
|
||||
// console.log("readFileAsyn:读取超出最大文件数量",readFileCount);
|
||||
return;
|
||||
}
|
||||
this._handleReadFileQueue()
|
||||
},
|
||||
|
||||
// 处理 readFileAsyn 队列
|
||||
_handleReadFileQueue(){
|
||||
// 1 == Math.min(50,1)
|
||||
let len = Math.min( readFileMaxCount , readFileQueue.length );
|
||||
for (let i = 0; i < len; i++) {
|
||||
// 处理队列
|
||||
let args = readFileQueue.splice(0,1)[0];
|
||||
fs.readFile(args.filePath,(err,data)=>
|
||||
{
|
||||
readFileCount--
|
||||
if(readFileCount > 500){
|
||||
setTimeout(this._handleReadFileQueue.bind(this),100)
|
||||
}else{
|
||||
this._handleReadFileQueue()
|
||||
}
|
||||
|
||||
try {
|
||||
args.callback(err,data);
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
copyFile(sourcePath, toPath) {
|
||||
fs.writeFileSync(toPath, fs.readFileSync(sourcePath))
|
||||
},
|
||||
|
||||
// copyFile(sourcePath,toPath){
|
||||
// fs.readFile(sourcePath,function(err,data){
|
||||
// if(err) throw new Error('复制失败:'+sourcePath+" TO "+data);
|
||||
// fs.writeFile(toPath,data,function(err){
|
||||
// if(err) throw new Error('复制写入失败'+sourcePath+" TO "+data);
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
|
||||
moveDir(sourcePath, toPath) {
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
console.log("不存在目录:", sourcePath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sourcePath[sourcePath.length - 1] != path.sep) {
|
||||
sourcePath += path.sep;// 加猴嘴
|
||||
}
|
||||
if (toPath[toPath.length - 1] != path.sep) {
|
||||
toPath += path.sep;// 加猴嘴
|
||||
}
|
||||
|
||||
let list = this.getDirAllFiles(sourcePath, []);
|
||||
list.forEach((fileName, i) => {
|
||||
|
||||
let toFilePath = fileName.replace(sourcePath, toPath);
|
||||
console.log("执行:", fileName, toFilePath);
|
||||
let dirName = path.dirname(toFilePath);
|
||||
this.createDir(dirName);
|
||||
// 移动文件
|
||||
fs.renameSync(fileName, toFilePath);
|
||||
})
|
||||
},
|
||||
|
||||
createDir(dirPath) {
|
||||
if (fs.existsSync(dirPath)) return;
|
||||
let paths = dirPath.split(path.sep);//分割路径
|
||||
let path_ = "";
|
||||
|
||||
// c:\
|
||||
let n = 0
|
||||
let max = paths.length
|
||||
if (paths[0].indexOf(":") != -1) {
|
||||
path_ = paths[0];
|
||||
n++;
|
||||
}
|
||||
|
||||
if (paths[max - 1].indexOf(".") != -1) {
|
||||
max--;
|
||||
}
|
||||
|
||||
for (n; n < max; n++) {
|
||||
path_ += path.sep + paths[n];
|
||||
if (!fs.existsSync(path_)) {
|
||||
fs.mkdirSync(path_);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 获得文件夹列表
|
||||
getDirList(dirPath, result) {
|
||||
let files = fs.readdirSync(dirPath);
|
||||
files.forEach((val, index) => {
|
||||
let fPath = path.join(dirPath, val);
|
||||
if (fs.existsSync(fPath) && fs.statSync(fPath).isDirectory()) {
|
||||
result.push(fPath);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
// 获得文件列表
|
||||
getFileList(dirPath, result = []) {
|
||||
let files = fs.readdirSync(dirPath);
|
||||
files.forEach((val, index) => {
|
||||
let fPath = path.join(dirPath, val);
|
||||
if (fs.existsSync(fPath) && fs.statSync(fPath).isFile()) {
|
||||
result.push(fPath);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
isDirectory(fPath) {
|
||||
return fs.existsSync(fPath) && fs.statSync(fPath).isDirectory()
|
||||
},
|
||||
|
||||
getDirAllFiles(dirPath, result = []) {
|
||||
let files = fs.readdirSync(dirPath);
|
||||
files.forEach((val, index) => {
|
||||
let fPath = path.join(dirPath, val);
|
||||
if (fs.existsSync(fPath) && fs.statSync(fPath).isDirectory()) {
|
||||
this.getDirAllFiles(fPath, result);
|
||||
} else if (fs.statSync(fPath).isFile()) {
|
||||
result.push(fPath);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
getFileString(fileList, options) {
|
||||
let curIndex = 0;
|
||||
let totalIndex = fileList.length;
|
||||
let str = {};
|
||||
for (let key in fileList) {
|
||||
let filePath = fileList[key];
|
||||
let b = this._isFileExit(filePath);
|
||||
if (b) {
|
||||
fs.readFile(filePath, 'utf-8', function (err, data) {
|
||||
if (!err) {
|
||||
self._collectString(data, str);
|
||||
} else {
|
||||
console.log("error: " + filePath);
|
||||
}
|
||||
self._onCollectStep(filePath, ++curIndex, totalIndex, str, options);
|
||||
})
|
||||
} else {
|
||||
self._onCollectStep(filePath, ++curIndex, totalIndex, str, options);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onCollectStep(filePath, cur, total, str, data) {
|
||||
if (data && data.stepCb) {
|
||||
data.stepCb(filePath, cur, total);
|
||||
}
|
||||
if (cur >= total) {
|
||||
self._onCollectOver(str, data);
|
||||
}
|
||||
},
|
||||
_onCollectOver(collectObjArr, data) {
|
||||
let strArr = [];
|
||||
let str = "";
|
||||
for (let k in collectObjArr) {
|
||||
str += k;
|
||||
strArr.push(k);
|
||||
}
|
||||
// console.log("一共有" + strArr.length + "个字符, " + strArr);
|
||||
console.log("一共有" + strArr.length + "个字符");
|
||||
if (data && data.compCb) {
|
||||
data.compCb(str);
|
||||
}
|
||||
},
|
||||
mkDir(path) {
|
||||
try {
|
||||
fs.mkdirSync(path);
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') throw e;
|
||||
}
|
||||
},
|
||||
isFileExit(file) {
|
||||
try {
|
||||
fs.accessSync(file, fs.F_OK);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
async isFileExitAsync(file) {
|
||||
return new Promise((resolev)=>{
|
||||
fs.access(file,(err)=>{
|
||||
resolev(err == null);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_collectString(data, collectObject) {
|
||||
for (let i in data) {
|
||||
let char = data.charAt(i);
|
||||
if (collectObject[char]) {
|
||||
collectObject[char]++;
|
||||
} else {
|
||||
collectObject[char] = 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
emptyDir(rootFile) {
|
||||
//删除所有的文件(将所有文件夹置空)
|
||||
let emptyDir = function (fileUrl) {
|
||||
let files = fs.readdirSync(fileUrl);//读取该文件夹
|
||||
for (let k in files) {
|
||||
let filePath = path.join(fileUrl, files[k]);
|
||||
let stats = fs.statSync(filePath);
|
||||
if (stats.isDirectory()) {
|
||||
emptyDir(filePath);
|
||||
} else {
|
||||
fs.unlinkSync(filePath);
|
||||
console.log("删除文件:" + filePath);
|
||||
}
|
||||
}
|
||||
};
|
||||
//删除所有的空文件夹
|
||||
let rmEmptyDir = function (fileUrl) {
|
||||
let files = fs.readdirSync(fileUrl);
|
||||
if (files.length > 0) {
|
||||
for (let k in files) {
|
||||
let rmDir = path.join(fileUrl, files[k]);
|
||||
rmEmptyDir(rmDir);
|
||||
}
|
||||
if (fileUrl !== rootFile) {// 不删除根目录
|
||||
fs.rmdirSync(fileUrl);
|
||||
console.log('删除空文件夹' + fileUrl);
|
||||
}
|
||||
} else {
|
||||
if (fileUrl !== rootFile) {// 不删除根目录
|
||||
fs.rmdirSync(fileUrl);
|
||||
console.log('删除空文件夹' + fileUrl);
|
||||
}
|
||||
}
|
||||
};
|
||||
emptyDir(rootFile);
|
||||
rmEmptyDir(rootFile);
|
||||
},
|
||||
/*
|
||||
is_fileType($('#uploadfile').val(), 'doc,pdf,txt,wps,odf,md,png,gif,jpg')
|
||||
* */
|
||||
is_fileType(filename, types) {
|
||||
types = types.split(',');
|
||||
let pattern = '\.(';
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
if (0 !== i) {
|
||||
pattern += '|';
|
||||
}
|
||||
pattern += types[i].trim();
|
||||
}
|
||||
pattern += ')$';
|
||||
return new RegExp(pattern, 'i').test(filename);
|
||||
},
|
||||
|
||||
getFileName(filePath) {
|
||||
let s_i = filePath.lastIndexOf('/');
|
||||
if (s_i == -1) s_i = filePath.lastIndexOf('\\');
|
||||
let name = filePath
|
||||
if (s_i != -1) name = name.substr(s_i + 1)
|
||||
s_i = name.lastIndexOf('.');
|
||||
if (s_i != -1) {
|
||||
name = name.substr(0, s_i)
|
||||
}
|
||||
return name;
|
||||
},
|
||||
|
||||
getFileExtname(filePath) {
|
||||
let s_i = filePath.lastIndexOf('.');
|
||||
let extname = ""
|
||||
if (s_i != -1) {
|
||||
extname = filePath.substr(s_i).toLowerCase()
|
||||
}
|
||||
return extname;
|
||||
},
|
||||
|
||||
|
||||
getUrlInfo(url) {
|
||||
let s_i = url.lastIndexOf('/');
|
||||
if (s_i == -1) s_i = url.lastIndexOf('\\');
|
||||
|
||||
let name = ""
|
||||
if (s_i != -1) name = url.substr(s_i + 1)
|
||||
|
||||
s_i = name.lastIndexOf('.');
|
||||
let extname = ""
|
||||
if (s_i != -1) {
|
||||
extname = name.substr(s_i).toLowerCase()
|
||||
}
|
||||
return { name, extname, url }
|
||||
},
|
||||
|
||||
|
||||
httpPost(ip,path,port,args,callback){
|
||||
var options = {
|
||||
hostname: ip,
|
||||
port: port,
|
||||
path: path,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
||||
}
|
||||
};
|
||||
|
||||
var req = http.request(options, function (res) {
|
||||
// console.log('STATUS: ' + res.statusCode);
|
||||
// console.log('HEADERS: ' + JSON.stringify(res.headers));
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function (chunk) {
|
||||
if(callback) callback(chunk);
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', function (e) {
|
||||
if(callback) callback();
|
||||
});
|
||||
|
||||
// write data to request body
|
||||
var content = querystring.stringify(args);
|
||||
req.write(content);
|
||||
req.end();
|
||||
},
|
||||
|
||||
}
|
||||
136
extensions/quick-compress-image/src/tools/updater.js
Normal file
136
extensions/quick-compress-image/src/tools/updater.js
Normal file
@@ -0,0 +1,136 @@
|
||||
const fetch = require('./node-fetch');
|
||||
|
||||
/**
|
||||
* 更新器
|
||||
*/
|
||||
const Updater = {
|
||||
|
||||
/**
|
||||
* 远端地址
|
||||
* @type {string}
|
||||
*/
|
||||
remoteUrl: 'https://gitee.com/mcv/simple-code-describe',
|
||||
|
||||
/**
|
||||
* 获取远端的 package.json
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
async getRemotePackageJson() {
|
||||
const packageJsonUrl = `${this.remoteUrl}/raw/master/package3.json`;
|
||||
// 发起网络请求
|
||||
const response = await fetch(packageJsonUrl, {
|
||||
method: 'GET',
|
||||
cache: 'no-cache',
|
||||
mode: 'no-cors',
|
||||
});
|
||||
// 请求结果
|
||||
if (response.status !== 200) {
|
||||
return null;
|
||||
}
|
||||
// 读取 json
|
||||
const json = response.json();
|
||||
return json;
|
||||
},
|
||||
|
||||
async getRemoteDesc() {
|
||||
const descUrl = `${this.remoteUrl}/raw/master/README3.md`;
|
||||
// 发起网络请求
|
||||
const response = await fetch(descUrl, {
|
||||
method: 'GET',
|
||||
cache: 'no-cache',
|
||||
mode: 'no-cors',
|
||||
});
|
||||
// 请求结果
|
||||
if (response.status !== 200) {
|
||||
return '';
|
||||
}
|
||||
const text = response.text();
|
||||
return text;
|
||||
},
|
||||
/**
|
||||
* 获取远端版本号
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async getRemoteVersion() {
|
||||
const package = await this.getRemotePackageJson();
|
||||
if (!package) {
|
||||
return null;
|
||||
}
|
||||
const version = package.version || null;
|
||||
return version;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取本地版本号
|
||||
* @returns {string}
|
||||
*/
|
||||
getLocalVersion() {
|
||||
return require('../package.json').version;
|
||||
},
|
||||
|
||||
/**
|
||||
* 拆分版本号
|
||||
* @param {string} version 版本号文本
|
||||
* @returns {number[]}
|
||||
* @example
|
||||
* splitVersionString('1.2.0'); // [1, 2, 0]
|
||||
*/
|
||||
splitVersionString(version) {
|
||||
return (
|
||||
version.replace(/-/g, '.')
|
||||
.split('.')
|
||||
.map(v => (parseInt(v) || 0))
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* 对比版本号
|
||||
* @param {string} a 版本 a
|
||||
* @param {string} b 版本 b
|
||||
* @returns {-1 | 0 | 1}
|
||||
* @example
|
||||
* compareVersion('1.0.0', '1.0.1'); // -1
|
||||
* compareVersion('1.1.0', '1.1.0'); // 0
|
||||
* compareVersion('1.2.1', '1.2.0'); // 1
|
||||
* compareVersion('1.2.0.1', '1.2.0'); // 1
|
||||
*/
|
||||
compareVersion(a, b) {
|
||||
const acs = this.splitVersionString(a),
|
||||
bcs = this.splitVersionString(b);
|
||||
const count = Math.max(acs.length, bcs.length);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const ac = acs[i],
|
||||
bc = bcs[i];
|
||||
// 前者缺少分量或前者小于后者
|
||||
if (ac == null || ac < bc) {
|
||||
return -1;
|
||||
}
|
||||
// 后者缺少分量或前者大于后者
|
||||
if (bc == null || ac > bc) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查远端是否有新版本
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async check() {
|
||||
// 远端版本号
|
||||
const remoteVersion = await this.getRemoteVersion();
|
||||
if (!remoteVersion) {
|
||||
return '';
|
||||
}
|
||||
// 本地版本号
|
||||
const localVersion = this.getLocalVersion();
|
||||
// 对比版本号
|
||||
const result = this.compareVersion(localVersion, remoteVersion);
|
||||
const remoteDesc = await this.getRemoteDesc() || '';
|
||||
return (result < 0) ? remoteDesc : '';
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = Updater;
|
||||
214
extensions/quick-compress-image/src/tools/watchFile.js
Normal file
214
extensions/quick-compress-image/src/tools/watchFile.js
Normal file
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* 1.监听文件变动
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const tools = require("./tools");
|
||||
|
||||
|
||||
/**
|
||||
* 事件回调
|
||||
*
|
||||
* @callback WatchEventCallback
|
||||
* @param {string} eventName - 事件名 create | delete | change | init
|
||||
* @param {Array<string>} files - 改变的文件
|
||||
*/
|
||||
|
||||
/**
|
||||
* 监听事件
|
||||
*/
|
||||
class WatchFile {
|
||||
/**
|
||||
* @param {WatchFile} watchObj
|
||||
* @param {string} pathName
|
||||
* @param {WatchEventCallback} eventCallback
|
||||
*/
|
||||
constructor(watchObj,pathName,eventCallback){
|
||||
this.pathName = pathName;
|
||||
this.eventCallback = eventCallback;
|
||||
this._watchObj = watchObj;
|
||||
/** @type Object<string,fs.Stats> */
|
||||
this._files = {}
|
||||
this._isChecking = false;
|
||||
this._isInit = false;
|
||||
this._isExistPath = false;
|
||||
this.check();
|
||||
}
|
||||
|
||||
stop(){
|
||||
this._watchObj.removeWatch(this.eventCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新文件状态
|
||||
*/
|
||||
async check(){
|
||||
if(this._isChecking){
|
||||
return;
|
||||
}
|
||||
let pathStat = fs.existsSync(this.pathName) ? fs.statSync(this.pathName) : undefined;
|
||||
if(!pathStat){
|
||||
// 监听的目录被删除
|
||||
if(this._isExistPath) setTimeout(this._removeAllFile.bind(this),1);
|
||||
this._isExistPath = false;
|
||||
return ;
|
||||
}
|
||||
|
||||
this._isExistPath = true;
|
||||
this._isChecking = true;
|
||||
let newFiles = {}
|
||||
if(pathStat && pathStat.isDirectory())
|
||||
{
|
||||
newFiles = await getDirAllFiles(this.pathName,newFiles)
|
||||
this._update(newFiles)
|
||||
}else if(pathStat.isFile())
|
||||
{
|
||||
newFiles[this.pathName] = pathStat;
|
||||
// 延迟执行防止循环调用
|
||||
setTimeout(()=>this._update(newFiles),1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
* @param {Object<string,fs.Stats>} newFiles
|
||||
*/
|
||||
_update(newFiles){
|
||||
let deleteFiles = [];
|
||||
let changeFiles = [];
|
||||
let createFiles = [];
|
||||
for (const filePath in this._files) {
|
||||
const oldFileStats = this._files[filePath];
|
||||
const newFileStats = newFiles[filePath]
|
||||
if(newFileStats == null){
|
||||
// 文件被删
|
||||
deleteFiles.push(filePath);
|
||||
}else if(newFileStats.mtimeMs != oldFileStats.mtimeMs){
|
||||
// 文件被修改
|
||||
changeFiles.push(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
for (const filePath in newFiles) {
|
||||
/** @type fs.Stats */
|
||||
const oldFileStats = this._files[filePath];
|
||||
if(oldFileStats == null){
|
||||
// 新创文件
|
||||
createFiles.push(filePath);
|
||||
}
|
||||
}
|
||||
let isInit = this._isInit;
|
||||
this._files = newFiles;
|
||||
this._isChecking = false;
|
||||
this._isInit = true;
|
||||
|
||||
// 调用事件
|
||||
if(this.eventCallback){
|
||||
if(!isInit){
|
||||
this.eventCallback('init',createFiles);
|
||||
}else{
|
||||
if(deleteFiles.length) this.eventCallback('delete',deleteFiles);
|
||||
if(changeFiles.length) this.eventCallback('change',changeFiles);
|
||||
if(createFiles.length) this.eventCallback('create',createFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_removeAllFile(){
|
||||
let deleteFiles = [];
|
||||
for (const filePath in this._files) {
|
||||
deleteFiles.push(filePath);
|
||||
}
|
||||
this._files = {};
|
||||
if(deleteFiles.length) this.eventCallback('delete',deleteFiles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听文件类
|
||||
*/
|
||||
class WatchMgr{
|
||||
constructor(){
|
||||
/** @type [WatchFile] */
|
||||
this.eventListens = []
|
||||
this.watchFileBuffs = {}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} pathName
|
||||
* @param {WatchEventCallback} eventCallback
|
||||
* @returns {WatchFile}
|
||||
*/
|
||||
addWatchPath(pathName,eventCallback) {
|
||||
let watchFile = new WatchFile(this,pathName,eventCallback);
|
||||
this.eventListens.push(watchFile);
|
||||
return watchFile;
|
||||
}
|
||||
|
||||
checkAll() {
|
||||
for (let i = 0; i < this.eventListens.length; i++) {
|
||||
const watchFile = this.eventListens[i];
|
||||
watchFile.check();
|
||||
}
|
||||
}
|
||||
|
||||
check(pathName) {
|
||||
for (let i = 0; i < this.eventListens.length; i++) {
|
||||
const watchFile = this.eventListens[i];
|
||||
if(watchFile.pathName == pathName){
|
||||
watchFile.check();
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeWatch(pathName) {
|
||||
for (let i = 0; i < this.eventListens.length; i++) {
|
||||
const watchFile = this.eventListens[i];
|
||||
if(watchFile.pathName == pathName){
|
||||
this.eventListens.splice(i,1);
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function getDirAllFiles(dirPath ,result = {}) {
|
||||
return new Promise((resolve, reject )=>
|
||||
{
|
||||
fs.readdir(dirPath,(err,files)=>
|
||||
{
|
||||
if(err) return reject(err);
|
||||
let len = files.length;
|
||||
if(len == 0){
|
||||
resolve(result); // 没有文件
|
||||
return;
|
||||
}
|
||||
|
||||
let cur_ind = 0;
|
||||
files.forEach((val) => {
|
||||
let fPath = path.join(dirPath, val);
|
||||
fs.stat(fPath,async (err,stat)=>
|
||||
{
|
||||
if(err) return reject(err);
|
||||
if (stat.isDirectory()) {
|
||||
result = await getDirAllFiles(fPath,result);
|
||||
} else if (stat.isFile()) {
|
||||
result[fPath] = stat ;
|
||||
}
|
||||
cur_ind ++;
|
||||
if(cur_ind == len) {
|
||||
resolve(result)
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
exports.WatchMgr = WatchMgr;
|
||||
exports.WatchFile = WatchFile;
|
||||
21
extensions/quick-compress-image/template/setting.css
Normal file
21
extensions/quick-compress-image/template/setting.css
Normal file
@@ -0,0 +1,21 @@
|
||||
#box {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: column;
|
||||
align-content: flex-start;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
height: -webkit-fill-available;
|
||||
|
||||
margin-left: 22px;
|
||||
margin-right: 22px;
|
||||
margin-top: 22px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.layoutItem {
|
||||
flex: 0.5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 0;
|
||||
}
|
||||
15
extensions/quick-compress-image/template/setting.html
Normal file
15
extensions/quick-compress-image/template/setting.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<div id="box">
|
||||
<div class="layoutItem">
|
||||
压缩模式 :<br/>
|
||||
<ui-tab id = 'zipModeTab' value="0">
|
||||
<ui-button>Imagemin(离线)</ui-button>
|
||||
<ui-button>TinyPng(在线)</ui-button>
|
||||
</ui-tab>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="layoutItem">
|
||||
压缩值 (越小压缩率越大):
|
||||
<ui-slider id = 'zipRateSlider' step="1" value="70" min="1" max="100"></ui-slider>
|
||||
</div>
|
||||
<ui-button class="layoutItem" id = 'saveBtn' class="green">保存</ui-button>
|
||||
</div>
|
||||
1342
extensions/quick-compress-image/type/editor.d.ts
vendored
Normal file
1342
extensions/quick-compress-image/type/editor.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1191
extensions/we_sane/@types/editor.d.ts
vendored
Normal file
1191
extensions/we_sane/@types/editor.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16092
extensions/we_sane/@types/electron.d.ts
vendored
Normal file
16092
extensions/we_sane/@types/electron.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
57
extensions/we_sane/@types/extension.d.ts
vendored
Normal file
57
extensions/we_sane/@types/extension.d.ts
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
declare namespace Editor {
|
||||
|
||||
namespace Interface {
|
||||
// ---- Package ---- start
|
||||
interface PackageInfo {
|
||||
debug: boolean;
|
||||
enable: boolean;
|
||||
info: PackageJson;
|
||||
invalid: boolean;
|
||||
name: string;
|
||||
path: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
interface PackageJson {
|
||||
name: string;
|
||||
version: string;
|
||||
|
||||
title?: string;
|
||||
author?: string;
|
||||
debug?: boolean;
|
||||
description?: string;
|
||||
main?: string;
|
||||
editor?: string;
|
||||
panel?: any;
|
||||
contributions?: { [key: string]: any };
|
||||
}
|
||||
// ---- Package ---- end
|
||||
|
||||
// ---- UI ---- start
|
||||
interface PanelInfo {
|
||||
template?: string;
|
||||
style?: string;
|
||||
listeners?: { [key: string]: () => {} };
|
||||
methods?: { [key: string]: Function };
|
||||
$?: { [key: string]: string };
|
||||
ready?(): void;
|
||||
update?(...args: any[]): void;
|
||||
beforeClose?(): void;
|
||||
close?(): void;
|
||||
}
|
||||
|
||||
namespace UIKit {
|
||||
interface UIPanelInfo extends PanelInfo {
|
||||
// 向上触发事件
|
||||
dispath(eventName: string, ...arg: any): void;
|
||||
}
|
||||
|
||||
interface EditorElementBase extends HTMLElement {
|
||||
value: any;
|
||||
dispath: (name: string, event: any) => void;
|
||||
}
|
||||
|
||||
}
|
||||
// ---- UI ---- end
|
||||
}
|
||||
}
|
||||
2
extensions/we_sane/@types/index.d.ts
vendored
Normal file
2
extensions/we_sane/@types/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/// <reference path="./editor.d.ts"/>
|
||||
/// <reference path="./message.d.ts"/>
|
||||
27
extensions/we_sane/@types/message.d.ts
vendored
Normal file
27
extensions/we_sane/@types/message.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as AssetDB from './packages/asset-db/@types/message';
|
||||
import * as Scene from './packages/scene/@types/message';
|
||||
import * as Engine from './packages/engine/@types/message';
|
||||
import * as Builder from './packages/builder/@types/public/message';
|
||||
import * as Programming from './packages/programming/@types/message';
|
||||
// import * as Extension from './packages/extension/@types/message';
|
||||
|
||||
declare global {
|
||||
interface EditorMessageContent {
|
||||
params: any[],
|
||||
result: any;
|
||||
}
|
||||
|
||||
interface EditorMessageMap {
|
||||
[x: string]: EditorMessageContent;
|
||||
}
|
||||
|
||||
interface EditorMessageMaps {
|
||||
[x: string]: EditorMessageMap;
|
||||
'asset-db': AssetDB.message;
|
||||
'scene': Scene.message;
|
||||
'engine': Engine.message;
|
||||
'builder': Builder.message;
|
||||
'programming': Programming.message,
|
||||
// 'extension': Extension.message;
|
||||
}
|
||||
}
|
||||
179
extensions/we_sane/@types/packages/asset-db/@types/message.d.ts
vendored
Normal file
179
extensions/we_sane/@types/packages/asset-db/@types/message.d.ts
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
import { AssetInfo, QueryAssetsOption, AssetOperationOption, AssetDBOptions, IAssetMeta } from './public';
|
||||
|
||||
export interface message extends EditorMessageMap {
|
||||
'query-ready': {
|
||||
params: [],
|
||||
result: boolean,
|
||||
},
|
||||
'create-asset': {
|
||||
params: [
|
||||
string,
|
||||
string | Buffer | null,
|
||||
] | [
|
||||
string,
|
||||
string | Buffer | null,
|
||||
AssetOperationOption,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'import-asset': {
|
||||
params: [
|
||||
string,
|
||||
string,
|
||||
] | [
|
||||
string,
|
||||
string,
|
||||
AssetOperationOption,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'copy-asset': {
|
||||
params: [
|
||||
string,
|
||||
string,
|
||||
] | [
|
||||
string,
|
||||
string,
|
||||
AssetOperationOption,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'move-asset': {
|
||||
params: [
|
||||
string,
|
||||
string,
|
||||
] | [
|
||||
string,
|
||||
string,
|
||||
AssetOperationOption,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'delete-asset': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'open-asset': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: void,
|
||||
},
|
||||
'save-asset': {
|
||||
params: [
|
||||
string,
|
||||
string | Buffer,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'save-asset-meta': {
|
||||
params: [
|
||||
string,
|
||||
string,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'reimport-asset': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: boolean,
|
||||
},
|
||||
'refresh-asset': {
|
||||
params: [
|
||||
string
|
||||
],
|
||||
result: boolean,
|
||||
},
|
||||
'query-asset-info': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'query-asset-meta': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: IAssetMeta | null,
|
||||
},
|
||||
'query-path': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: string | null,
|
||||
},
|
||||
'query-url': {
|
||||
params: [
|
||||
string
|
||||
],
|
||||
result: string | null,
|
||||
},
|
||||
'query-uuid': {
|
||||
params: [
|
||||
string
|
||||
],
|
||||
result: string | null,
|
||||
},
|
||||
'query-assets': {
|
||||
params: [] | [
|
||||
QueryAssetsOption,
|
||||
],
|
||||
result: AssetInfo[],
|
||||
},
|
||||
'generate-available-url': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: string,
|
||||
},
|
||||
|
||||
// private
|
||||
|
||||
'query-asset-mtime': {
|
||||
params: [
|
||||
string
|
||||
],
|
||||
result: string | null,
|
||||
},
|
||||
'refresh': {
|
||||
params: [],
|
||||
result: void,
|
||||
},
|
||||
'open-devtools': {
|
||||
params: [],
|
||||
result: void,
|
||||
},
|
||||
'query-db-info': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: AssetDBOptions,
|
||||
},
|
||||
'create-asset-dialog': {
|
||||
params: [
|
||||
string,
|
||||
] | [
|
||||
string,
|
||||
string,
|
||||
],
|
||||
result: string | null,
|
||||
},
|
||||
'init-asset': {
|
||||
params: [
|
||||
string,
|
||||
string,
|
||||
],
|
||||
result: AssetInfo | null,
|
||||
},
|
||||
'query-all-importer': {
|
||||
params: [],
|
||||
result: string[],
|
||||
},
|
||||
'query-all-asset-types': {
|
||||
params: [],
|
||||
result: string[],
|
||||
},
|
||||
}
|
||||
115
extensions/we_sane/@types/packages/asset-db/@types/public.d.ts
vendored
Normal file
115
extensions/we_sane/@types/packages/asset-db/@types/public.d.ts
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Basic information about the resource
|
||||
// 资源的基础信息
|
||||
export interface AssetInfo {
|
||||
// Asset name
|
||||
// 资源名字
|
||||
name: string;
|
||||
// Asset display name
|
||||
// 资源用于显示的名字
|
||||
displayName: string;
|
||||
// URL
|
||||
source: string;
|
||||
// loader 加载的层级地址
|
||||
path: string;
|
||||
// loader 加载地址会去掉扩展名,这个参数不去掉
|
||||
url: string;
|
||||
// 绝对路径
|
||||
file: string;
|
||||
// 资源的唯一 ID
|
||||
uuid: string;
|
||||
// 使用的导入器名字
|
||||
importer: string;
|
||||
// 类型
|
||||
type: string;
|
||||
// 是否是文件夹
|
||||
isDirectory: boolean;
|
||||
// 导入资源的 map
|
||||
library: { [key: string]: string };
|
||||
// 子资源 map
|
||||
subAssets: { [key: string]: AssetInfo };
|
||||
// 是否显示
|
||||
visible: boolean;
|
||||
// 是否只读
|
||||
readonly: boolean;
|
||||
|
||||
// 虚拟资源可以实例化成实体的话,会带上这个扩展名
|
||||
instantiation?: string;
|
||||
// 跳转指向资源
|
||||
redirect?: IRedirectInfo;
|
||||
// 继承类型
|
||||
extends?: string[];
|
||||
// 是否导入完成
|
||||
imported: boolean;
|
||||
// 是否导入失败
|
||||
invalid: boolean;
|
||||
}
|
||||
|
||||
export interface IRedirectInfo {
|
||||
// 跳转资源的类型
|
||||
type: string;
|
||||
// 跳转资源的 uuid
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface QueryAssetsOption {
|
||||
type?: string;
|
||||
pattern?: string;
|
||||
ccType?: string;
|
||||
extname?: string;
|
||||
importer?: string;
|
||||
isBundle?: boolean;
|
||||
}
|
||||
|
||||
export interface AssetOperationOption {
|
||||
// 是否强制覆盖已经存在的文件,默认 false
|
||||
overwrite?: boolean;
|
||||
// 是否自动重命名冲突文件,默认 false
|
||||
rename?: boolean;
|
||||
}
|
||||
|
||||
export interface AssetDBOptions {
|
||||
name: string;
|
||||
target: string;
|
||||
library: string;
|
||||
temp: string;
|
||||
/**
|
||||
* 0: 忽略错误
|
||||
* 1: 仅仅打印错误
|
||||
* 2: 打印错误、警告
|
||||
* 3: 打印错误、警告、日志
|
||||
* 4: 打印错误、警告、日志、调试信息
|
||||
*/
|
||||
level: number;
|
||||
ignoreFiles: string[];
|
||||
readonly: boolean;
|
||||
}
|
||||
|
||||
export interface ContributionInfo {
|
||||
mount?: {
|
||||
path: string;
|
||||
readonly?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ExecuteAssetDBScriptMethodOptions {
|
||||
name: string;
|
||||
method: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export interface IAssetMeta {
|
||||
ver: string;
|
||||
importer: string;
|
||||
imported: boolean;
|
||||
uuid: string;
|
||||
files: string[];
|
||||
subMetas: {
|
||||
[index: string]: IAssetMeta;
|
||||
};
|
||||
userData: {
|
||||
[index: string]: any;
|
||||
};
|
||||
displayName: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
2
extensions/we_sane/@types/packages/builder/@types/index.d.ts
vendored
Normal file
2
extensions/we_sane/@types/packages/builder/@types/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
export * from './public';
|
||||
117
extensions/we_sane/@types/packages/builder/@types/protect/asset-manager.d.ts
vendored
Normal file
117
extensions/we_sane/@types/packages/builder/@types/protect/asset-manager.d.ts
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import { AssetInfo } from "../../../asset-db/@types/public";
|
||||
import { UUID } from "../public";
|
||||
import { IInternalBuildOptions } from "./options";
|
||||
export interface IBuildStatiscInfo {
|
||||
packageName: string;
|
||||
gameName: string;
|
||||
platform: string;
|
||||
scenesNum: number;
|
||||
assetsNum: number;
|
||||
scriptNum: number;
|
||||
|
||||
includeModules: string[];
|
||||
orientation: string;
|
||||
remoteServerAddress: string;
|
||||
appid: string;
|
||||
|
||||
size: number;
|
||||
time: number;
|
||||
err: string;
|
||||
}
|
||||
|
||||
// ********************************* asset-manager *********************************
|
||||
|
||||
export class BuilderAssetCache {
|
||||
// 场景资源的 assets 信息缓存
|
||||
public readonly sceneUuids: Array<string>;
|
||||
|
||||
// 脚本资源的 assets 信息缓存
|
||||
public readonly scriptUuids: Array<string>;
|
||||
|
||||
// 除场景、脚本资源外的资源 assets uuid 缓存
|
||||
public readonly assetUuids: Array<string>;
|
||||
|
||||
init: () => Promise<void>;
|
||||
addAsset: (asset: IAssetInfo) => void;
|
||||
addInstance: (instance: any) => void;
|
||||
clearAsset: (uuid: string) => void;
|
||||
getMeta: (uuid: string) => Promise<any>;
|
||||
getAssetInfo: (uuid: string) => IAssetInfo;
|
||||
getDependUuids: (uuid: string) => Promise<readonly string[]>;
|
||||
getDependUuidsDeep: (uuid: string) => Promise<readonly string[]>;
|
||||
/**
|
||||
* 获取序列化文件
|
||||
*/
|
||||
getLibraryJSON: (uuid: string) => Promise<any>;
|
||||
getSerializedJSON: (uuid: string, options: IInternalBuildOptions) => Promise<any>;
|
||||
forEach: (type: string, handle: Function) => Promise<void>;
|
||||
getInstance: (uuid: string) => Promise<any>;
|
||||
__addStaticsInfo: (info: any) => void;
|
||||
}
|
||||
|
||||
export interface IAssetInfo extends AssetInfo {
|
||||
meta?: any;
|
||||
temp?: string; // 资源的构建缓存目录
|
||||
fatherInfo?: any;
|
||||
// fatherUuid?: string | undefined;
|
||||
userData?: any;
|
||||
subAssets: Record<string, IAssetInfo>;
|
||||
dirty?: boolean;
|
||||
// 内置资源没有 mtime
|
||||
mtime?: number;
|
||||
}
|
||||
export type IUrl = string; // 需要的是符合 url 标准的字符串,例如 asset/script/text.ts
|
||||
export type IAssetInfoMap = Record<UUID, IAssetInfo>;
|
||||
export type IUuidDependMap = Record<UUID, UUID[]>;
|
||||
export type IJsonGroupMap = Record<UUID, IJSONGroupItem>;
|
||||
export type IAssetGroupMap = Record<UUID, IAssetGroupItem>;
|
||||
|
||||
// TODO meta 的类型定义
|
||||
export type IMetaMap = Record<UUID, any>;
|
||||
export type IJsonMap = Record<UUID, any>;
|
||||
export type IInstanceMap = Record<UUID, any>;
|
||||
|
||||
export type ICompressOptions = Record<string, number>;
|
||||
export interface IAssetGroupItem {
|
||||
// 分组名字
|
||||
// name: string;
|
||||
// 分组的根 url
|
||||
baseUrls: string[];
|
||||
// 脚本编译后的实际地址
|
||||
scriptDest: string;
|
||||
// 脚本 uuid 列表
|
||||
scriptUuids: UUID[];
|
||||
// raw 资源 uuid 列表
|
||||
assetUuids: UUID[];
|
||||
}
|
||||
|
||||
export interface IJSONGroupItem {
|
||||
// 分组名字
|
||||
name?: string;
|
||||
// 分组名字
|
||||
type: string;
|
||||
// json 资源 uuid 列表
|
||||
uuids: UUID[];
|
||||
}
|
||||
|
||||
export interface IAssetGroupOptions {
|
||||
// 脚本打包后的输出路径
|
||||
scriptUrl: string;
|
||||
baseUrl: string;
|
||||
}
|
||||
|
||||
export type IGroupType = 'json' | 'script' | 'asset';
|
||||
export interface PacInfo {
|
||||
meta: any;
|
||||
asset: IAssetInfo;
|
||||
spriteFrames: any[];
|
||||
relativePath: string;
|
||||
relativeDir: string;
|
||||
}
|
||||
|
||||
export type IUpdateType = 'asset-change' | 'asset-add' | 'asset-delete';
|
||||
export interface IUpdateInfo {
|
||||
type: IUpdateType;
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
152
extensions/we_sane/@types/packages/builder/@types/protect/build-plugin.d.ts
vendored
Normal file
152
extensions/we_sane/@types/packages/builder/@types/protect/build-plugin.d.ts
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// ********************************* plugin ****************************************
|
||||
|
||||
import { BundleCompressionType, IBuildPluginConfig, IBuildTaskOption, IDisplayOptions, ISettings, IVerificationRuleMap } from '../public';
|
||||
import { BuilderAssetCache } from './asset-manager';
|
||||
import { InternalBuildResult } from './build-result';
|
||||
import { IInternalBuildOptions } from './options';
|
||||
import { ITextureCompressPlatform, ITextureCompressType } from '../public/texture-compress';
|
||||
|
||||
export interface IBuildWorkerPluginInfo {
|
||||
assetHandlers?: string;
|
||||
// 注册到各个平台的钩子函数
|
||||
hooks?: Record<string, string>;
|
||||
pkgName: string;
|
||||
internal: boolean; // 是否为内置插件
|
||||
priority: number; // 优先级
|
||||
}
|
||||
|
||||
export type IPluginHookName =
|
||||
| 'onBeforeBuild'
|
||||
| 'onAfterInit'
|
||||
| 'onBeforeInit'
|
||||
| 'onAfterInit'
|
||||
| 'onBeforeBuildAssets'
|
||||
| 'onAfterBuildAssets'
|
||||
| 'onBeforeCompressSettings'
|
||||
| 'onAfterCompressSettings'
|
||||
| 'onAfterBuild';
|
||||
// | 'onBeforeCompile'
|
||||
// | 'compile'
|
||||
// | 'onAfterCompile'
|
||||
// | 'run';
|
||||
|
||||
export type IPluginHook = Record<IPluginHookName, IInternalBaseHooks>;
|
||||
export interface IInternalHook {
|
||||
throwError?: boolean; // 插件注入的钩子函数,在执行失败时是否直接退出构建流程
|
||||
title?: string; // 插件任务整体 title,支持 i18n 写法
|
||||
// ------------------ 钩子函数 --------------------------
|
||||
onBeforeBuild?: IInternalBaseHooks;
|
||||
onBeforeInit?: IInternalBaseHooks;
|
||||
onAfterInit?: IInternalBaseHooks;
|
||||
onBeforeBuildAssets?: IInternalBaseHooks;
|
||||
onAfterBuildAssets?: IInternalBaseHooks;
|
||||
onBeforeCompressSettings?: IInternalBaseHooks;
|
||||
onAfterCompressSettings?: IInternalBaseHooks;
|
||||
onAfterBuild?: IInternalBaseHooks;
|
||||
// ------------------ 其他操作函数 ---------------------
|
||||
// 内置插件才有可能触发这个函数
|
||||
run?: (dest: string, options: IBuildTaskOption) => Promise<boolean>;
|
||||
// 内置插件才有可能触发这个函数
|
||||
compile?: (dest: string, options: IBuildTaskOption) => boolean;
|
||||
}
|
||||
|
||||
export type IInternalBaseHooks = (options: IInternalBuildOptions, result: InternalBuildResult, cache: BuilderAssetCache, ...args: any[]) => void;
|
||||
export interface IBuildTask {
|
||||
handle: (options: IInternalBuildOptions, result: InternalBuildResult, cache: BuilderAssetCache, settings?: ISettings) => {};
|
||||
title: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface IBuildHooksInfo {
|
||||
pkgNameOrder: string[];
|
||||
infos: Record<string, { path: string; internal: boolean }>;
|
||||
}
|
||||
export interface IBuildAssetHandlerInfo {
|
||||
pkgNameOrder: string[];
|
||||
handles: {[pkgName: string]: Function};
|
||||
}
|
||||
export interface IInternalBuildPluginConfig extends IBuildPluginConfig {
|
||||
platformName?: string; // 平台名,可以指定为 i18n 写法, 只有官方构建插件的该字段有效
|
||||
hooks?: string; // 钩子函数的存储路径
|
||||
panel?: string; // 存储导出 vue 组件、button 配置的脚本路径
|
||||
textureCompressConfig?: {
|
||||
// 仅对内部插件开放
|
||||
platformType: ITextureCompressPlatform; // 注册的纹理压缩平台类型
|
||||
support: {
|
||||
rgba: ITextureCompressType[];
|
||||
rgb: ITextureCompressType[];
|
||||
}; // 该平台支持的纹理压缩格式,按照推荐优先级排列
|
||||
};
|
||||
assetBundleConfig?: {
|
||||
// asset bundle 的配置
|
||||
supportedCompressionTypes: BundleCompressionType[];
|
||||
};
|
||||
priority?: number;
|
||||
wrapWithFold?: boolean; // 是否将选项显示在折叠框内(默认 true )
|
||||
options?: IDisplayOptions; // 需要注入的平台参数配置
|
||||
verifyRuleMap?: IVerificationRuleMap; // 注入的需要更改原有参数校验规则的函数
|
||||
commonOptions?: Record<string, boolean>;
|
||||
// TODO 之前为 ios-app-clip HACK 出来的接口,之后需要重新设计
|
||||
realInFileExplorer?: (options: IInternalBuildOptions | any) => void; // 根据构建配置计算输出地址(界面中的在文件夹中显示)
|
||||
debugConfig?: IDebugConfig;
|
||||
internal?: boolean;
|
||||
}
|
||||
|
||||
export interface BuildCheckResult {
|
||||
error: string;
|
||||
newValue: any;
|
||||
}
|
||||
|
||||
export type IBuildVerificationFunc = (value: any, options: IBuildTaskOption) => boolean | Promise<boolean>;
|
||||
|
||||
export interface IButtonConfigItem {
|
||||
label: string; // 按钮名称
|
||||
click?: (event: Event, options: IBuildTaskOption) => void; // 点击事件响应函数
|
||||
hookHandle?: string; // 点击后执行的方法,与 click 二选一
|
||||
tooltip?: string; // 鼠标上移到按钮上的文本提示
|
||||
// 只有指定 hookHandle 配置的按钮,才可以影响进度条,构建将会自动为每个按钮创建一个构建内置任务,并提供对应的进度 log 更新等等。
|
||||
// attributes?: any; // 想要添加在按钮上的一些属性值(class, style, title)
|
||||
}
|
||||
|
||||
export interface IDebugConfig {
|
||||
options?: IDisplayOptions; // 显示在构建平台编译运行调试工具上的配置选项
|
||||
custom?: string; // 显示在构建平台编译运行调试工具上的配置 vue 组件
|
||||
}
|
||||
|
||||
// ui-panel 注册数据
|
||||
export interface PanelInfo {
|
||||
$?: { [name: string]: string | HTMLElement | null };
|
||||
template?: string; // TODO 暂时设置为可选
|
||||
style?: string;
|
||||
methods?: { [name: string]: Function };
|
||||
ready?: Function;
|
||||
close?: Function;
|
||||
update?: (options: IBuildTaskOption, path: string, value: any) => void | Promise<void>;
|
||||
}
|
||||
|
||||
export interface IPanelThis {
|
||||
$: Record<string, HTMLElement>;
|
||||
dispatch: (name: string, ...args: any[]) => void;
|
||||
}
|
||||
|
||||
export interface IPanelInfo extends PanelInfo {
|
||||
component?: any; // 注入面板的 vue 组件,可与与 options 共存,options 会优先显示
|
||||
buttonConfig?: IButtonConfig; // 要注入的构建选项脚本
|
||||
}
|
||||
|
||||
export interface IButtonConfig {
|
||||
configs?: Record<string, IButtonConfigItem>;
|
||||
custom?: any;
|
||||
}
|
||||
|
||||
export interface ICompInfo {
|
||||
custom?: any;
|
||||
options?: IDisplayOptions;
|
||||
panelInfo?: PanelInfo;
|
||||
displayName?: string;
|
||||
wrapWithFold: boolean;
|
||||
|
||||
// ..... 初始化时未存在的字段 .....
|
||||
panel?: any; // 实例化后的 panel 对象
|
||||
pkgName?: string; // 插件名称
|
||||
}
|
||||
141
extensions/we_sane/@types/packages/builder/@types/protect/build-result.d.ts
vendored
Normal file
141
extensions/we_sane/@types/packages/builder/@types/protect/build-result.d.ts
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
import { BundleCompressionType, IAssetPathInfo, IBuildPaths, IBuildTaskOption, IBundleConfig, IJsonPathInfo, ISettings, UUID } from "../public";
|
||||
import { IAssetInfo } from "./asset-manager";
|
||||
import { ImportMapWithImports } from "./import-map";
|
||||
|
||||
export class InternalBuildResult {
|
||||
settings: ISettings;
|
||||
readonly bundles: IBundle[];
|
||||
readonly bundleMap: Record<string, IBundle>;
|
||||
// 构建实际使用到的插件脚本 uuid 列表
|
||||
plugins: UUID[];
|
||||
// 脚本资源包分组(子包/分包)
|
||||
scriptPackages: string[];
|
||||
// MD5 后缀 map
|
||||
pluginVers: Record<UUID, string>;
|
||||
// 纹理压缩任务
|
||||
imageTaskMap: Record<UUID, IImageTask>;
|
||||
compressImageResult: ICompressImageResult;
|
||||
importMap: ImportMapWithImports;
|
||||
// 传入构建的 options
|
||||
rawOptions: IBuildTaskOption;
|
||||
// 输出路径集合
|
||||
paths: IBuildPaths;
|
||||
// 允许自定义编译选项
|
||||
compileOptions?: any;
|
||||
addBundle: (bundle: IBundle) => void;
|
||||
addPlugin: (plugin: IAssetInfo) => void;
|
||||
}
|
||||
|
||||
export interface IImageTask {
|
||||
src: string;
|
||||
// TODO 这个名称已和意义有冲突需要整理调整
|
||||
dest: string[];
|
||||
presetId: string;
|
||||
hasAlpha: boolean;
|
||||
mtime?: any;
|
||||
// 生成阶段将会重新获取 bundle 的输出地址
|
||||
bundleNames: string[];
|
||||
}
|
||||
|
||||
export interface IVersionMap {
|
||||
import: Record<UUID, string>;
|
||||
native: Record<UUID, string>;
|
||||
}
|
||||
|
||||
export interface IMD5Map {
|
||||
'raw-assets': Record<UUID, string>;
|
||||
import: Record<UUID, string>;
|
||||
plugin?: Record<UUID, string>;
|
||||
}
|
||||
export interface IAtlasResult {
|
||||
assetsToImage: Record<string, string>;
|
||||
imageToAtlas: Record<string, string>;
|
||||
atlasToImages: Record<string, string[]>;
|
||||
}
|
||||
|
||||
export class IBundle {
|
||||
readonly scenes: UUID[]; // 该 bundle 中的所有场景,包含重定向的
|
||||
readonly assets: UUID[]; // 该 bundle 中的所有资源,包含重定向的
|
||||
readonly assetsWithoutRedirect: UUID[]; // 该 bundle 中的未重定向的资源
|
||||
readonly scripts: UUID[]; // 该 bundle 中的所有脚本
|
||||
readonly rootAssets: UUID[]; // 该 bundle 中的根资源,即直接放在 bundle 目录下的资源,包含重定向的资源
|
||||
readonly isSubpackage: boolean; // 该 bundle 是否是子包
|
||||
root: string; // bundle 的根目录, 开发者勾选的目录,如果是 main 包,这个字段为 ''
|
||||
dest: string; // bundle 的输出目录
|
||||
importBase: string;
|
||||
nativeBase: string;
|
||||
scriptDest: string; // 脚本的输出目录
|
||||
name: string; // bundle 的名称
|
||||
priority: number; // bundle 的优先级
|
||||
compressionType: BundleCompressionType; // bundle 的压缩类型
|
||||
assetVer: IVersionMap; // bundle 内的资源版本
|
||||
version: string; // bundle 本身的版本信息
|
||||
readonly isRemote: boolean; // bundle 是否是远程包
|
||||
redirect: Record<UUID, string>; // bundle 中的重定向资源
|
||||
deps: Set<string>; // bundle 的依赖 bundle
|
||||
groups: IGroup[]; // 该 bundle 中的资源分组
|
||||
cache: any;
|
||||
configOutPutName: string;
|
||||
config: IBundleConfig; // 该 bundle 的资源清单
|
||||
readonly isZip: boolean; // 该 bundle 是否是 zip 模式
|
||||
zipVer: string; // Zip 压缩模式,压缩包的版本
|
||||
atlasRes: IAtlasResult;
|
||||
_rootAssets: Set<UUID>; // 该 bundle 直接包含的资源
|
||||
_scenes: Set<UUID>;
|
||||
_scripts: Set<UUID>;
|
||||
_assets: Set<UUID>;
|
||||
|
||||
addScene(scene: IAssetInfo): void;
|
||||
addScript(script: IAssetInfo): void;
|
||||
addRootAsset(asset: IAssetInfo): void;
|
||||
addAsset(asset: IAssetInfo): void;
|
||||
removeAsset(asset: UUID): void;
|
||||
addRedirectWithUuid(asset: UUID, redirect: string): void;
|
||||
addRedirect(asset: IAssetInfo, redirect: string): void;
|
||||
addAssetWithUuid(asset: UUID): void;
|
||||
getRedirect(uuid: UUID): string | undefined;
|
||||
addGroup(type: IJSONGroupType, uuids: UUID[]): void;
|
||||
addToGroup(type: IJSONGroupType, uuid: UUID): void;
|
||||
removeFromGroups(uuid: UUID): void;
|
||||
getJsonPath(uuid: string): string;
|
||||
getAssetPathInfo(uuid: string): IAssetPathInfo | null;
|
||||
containsAsset(uuid: string): boolean;
|
||||
getRawAssetPaths(uuid: string): string[];
|
||||
getJsonPathInfo(uuid: string): IJsonPathInfo | null;
|
||||
|
||||
_resolveImportPath: (name: string) => string;
|
||||
_resolveNativePath: (libraryPath: string, extName: string) => string;
|
||||
}
|
||||
|
||||
export type ICompressImageResult = Record<UUID, {
|
||||
formats: string[],
|
||||
files: string[],
|
||||
}>;
|
||||
|
||||
export interface IGroup {
|
||||
// 分组名字
|
||||
name?: string;
|
||||
// 分组类型
|
||||
type: IJSONGroupType;
|
||||
// 该组中的资源 uuid 列表
|
||||
uuids: UUID[];
|
||||
}
|
||||
|
||||
export type IJSONGroupType = 'NORMAL' | 'TEXTURE' | 'IMAGE';
|
||||
|
||||
export interface IDefaultGroup {
|
||||
assetUuids: UUID[];
|
||||
scriptUuids: UUID[];
|
||||
jsonUuids: UUID[];
|
||||
}
|
||||
|
||||
export interface IBundleOptions {
|
||||
root: string, // bundle 的根目录, 开发者勾选的目录,如果是 main 包,这个字段为''
|
||||
dest: string, // bundle 的输出目录
|
||||
scriptDest: string, // 脚本的输出目录
|
||||
name: string, // bundle 的名称
|
||||
priority: number, // bundle 的优先级
|
||||
compressionType: BundleCompressionType, // bundle 的压缩类型
|
||||
isRemote: boolean // bundle 是否是远程包
|
||||
// isEncrypted: boolean // bundle 中的代码是否加密,原生平台使用
|
||||
}
|
||||
18
extensions/we_sane/@types/packages/builder/@types/protect/global.d.ts
vendored
Normal file
18
extensions/we_sane/@types/packages/builder/@types/protect/global.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { IBuildPanel, IInternalBuild } from ".";
|
||||
|
||||
// 定义 builder 进程内的全局变量
|
||||
declare global {
|
||||
// 构建进程可用
|
||||
// @ts-ignore
|
||||
const Build: IInternalBuild;
|
||||
|
||||
const __manager: {
|
||||
taskManager: any;
|
||||
currentCompileTask: any;
|
||||
currentBuildTask: any;
|
||||
__taskId: string;
|
||||
};
|
||||
|
||||
// 渲染进程可用
|
||||
const BuildPanel: IBuildPanel;
|
||||
}
|
||||
7
extensions/we_sane/@types/packages/builder/@types/protect/import-map.d.ts
vendored
Normal file
7
extensions/we_sane/@types/packages/builder/@types/protect/import-map.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
export interface ImportMap {
|
||||
imports?: Record<string, string>;
|
||||
scopes?: Record<string, Record<string, string>>;
|
||||
}
|
||||
|
||||
export type ImportMapWithImports = ImportMap & { imports: NonNullable<ImportMap['imports']> };
|
||||
89
extensions/we_sane/@types/packages/builder/@types/protect/index.d.ts
vendored
Normal file
89
extensions/we_sane/@types/packages/builder/@types/protect/index.d.ts
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
import { IBuild, IBuildUtils, ITaskState } from '../public';
|
||||
import { InternalBuildResult } from './build-result';
|
||||
|
||||
export * from './asset-manager';
|
||||
export * from './import-map';
|
||||
export * from './options';
|
||||
export * from './build-result';
|
||||
export * from './build-plugin';
|
||||
export * from '../public';
|
||||
|
||||
export type Physics = 'cannon' | 'ammo' | 'builtin';
|
||||
export type Url = string; // 需要的是符合 url 标准的字符串
|
||||
export type AssetInfoArr = Array<string | number>; // 固定两位或三位数组 [url,ccType,isSubAsset]
|
||||
export type IProcessingFunc = (process: number, message: string, state?: ITaskState) => void;
|
||||
export interface IBuildManager {
|
||||
taskManager: any;
|
||||
currentCompileTask: any;
|
||||
currentBuildTask: any;
|
||||
__taskId: string;
|
||||
}
|
||||
|
||||
export interface IQuickSpawnOption {
|
||||
cwd?: string;
|
||||
env?: any;
|
||||
downGradeWaring?: boolean; // 将会转为 log 打印,默认为 false
|
||||
downGradeLog?: boolean; // 将会转为 debug 打印,默认为 true
|
||||
downGradeError?: boolean; // 将会转为警告,默认为 false
|
||||
ignoreLog?: boolean; // 忽略 log 信息
|
||||
}
|
||||
export interface IInternalBuildUtils extends IBuildUtils {
|
||||
/**
|
||||
* 获取构建出的所有模块或者模块包文件。
|
||||
*/
|
||||
getModuleFiles(result: InternalBuildResult): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* 快速开启子进程
|
||||
* @param command
|
||||
* @param cmdParams
|
||||
* @param options
|
||||
*/
|
||||
quickSpawn(command: string, cmdParams: string[], options?: IQuickSpawnOption): Promise<number | boolean>;
|
||||
|
||||
/**
|
||||
* 将某个 hash 值添加到某个路径上
|
||||
* @param targetPath
|
||||
* @param hash
|
||||
* @returns
|
||||
*/
|
||||
patchMd5ToPath(targetPath: string, hash: string): string;
|
||||
}
|
||||
|
||||
export interface IInternalBuild extends IBuild {
|
||||
Utils: IInternalBuildUtils;
|
||||
}
|
||||
|
||||
export interface IBuildProcessInfo {
|
||||
state: ITaskState; // 任务状态
|
||||
progress: number; // 任务进度
|
||||
message: string; // 最后一次更新的进度消息
|
||||
id: string; // 任务唯一标识符
|
||||
options: any; // 构建参数
|
||||
}
|
||||
|
||||
export interface fileMap {
|
||||
src: string;
|
||||
dest: string;
|
||||
}
|
||||
|
||||
export interface IScriptInfo {
|
||||
file: string;
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
type ICheckRule = 'pathExist' | 'valid' | 'required' | 'normalName' | 'noChinese' | 'array' | 'string' | 'number' | 'http';
|
||||
|
||||
export interface IBuildPanel {
|
||||
// 内部使用的 Vue
|
||||
Vue: any;
|
||||
// 内置 vue 组件
|
||||
vueComps: {
|
||||
buildProp: any;
|
||||
templateComp: any;
|
||||
},
|
||||
validator: {
|
||||
has: (ruleName: string) => boolean;
|
||||
check: (ruleName: ICheckRule, val: any) => boolean;
|
||||
},
|
||||
}
|
||||
145
extensions/we_sane/@types/packages/builder/@types/protect/options.d.ts
vendored
Normal file
145
extensions/we_sane/@types/packages/builder/@types/protect/options.d.ts
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import { IBuildTimeConstantValue } from "@cocos/build-engine/dist/build-time-constants";
|
||||
import { IBuildDesignResolution, IBuildTaskOption } from "../public";
|
||||
|
||||
export interface ScriptAssetuserData {
|
||||
isPlugin?: boolean;
|
||||
isNative?: boolean;
|
||||
loadPluginInNative?: boolean;
|
||||
loadPluginInWeb?: boolean;
|
||||
}
|
||||
|
||||
export interface IBuildScriptParam {
|
||||
/**
|
||||
* 若存在,表示将 import map 转换为指定的模块格式。
|
||||
*/
|
||||
importMapFormat?: 'commonjs' | 'esm';
|
||||
|
||||
polyfills?: IPolyFills;
|
||||
|
||||
/**
|
||||
* 擦除模块结构。当选择后会获得更快的脚本导入速度,但无法再使用模块特性,如 `import.meta`、`import()` 等。
|
||||
* @experimental
|
||||
*/
|
||||
experimentalEraseModules?: boolean;
|
||||
outputName: string; // 输出文件夹名称(带后缀)
|
||||
targets?: ITransformTarget;
|
||||
|
||||
system?: {
|
||||
preset?: 'web' | 'commonjs-like',
|
||||
},
|
||||
|
||||
flags: Record<string, IBuildTimeConstantValue>,
|
||||
}
|
||||
|
||||
export interface IPolyFills {
|
||||
/**
|
||||
* True if async functions polyfills(i.e. regeneratorRuntime) needs to be included.
|
||||
* You need to turn on this field if you want to use async functions in language.
|
||||
*/
|
||||
asyncFunctions?: boolean;
|
||||
|
||||
/**
|
||||
* If true, [core-js](https://github.com/zloirock/core-js) polyfills are included.
|
||||
* The default options of [core-js-builder](https://github.com/zloirock/core-js/tree/master/packages/core-js-builder)
|
||||
* will be used to build the core-js.
|
||||
*/
|
||||
coreJs?: boolean;
|
||||
|
||||
targets?: string;
|
||||
}
|
||||
/**
|
||||
* 模块保留选项。
|
||||
* - 'erase' 擦除模块信息。生成的代码中将不会保留模块信息。
|
||||
* - 'preserve' 保留原始模块信息。生成的文件将和原始模块文件结构一致。
|
||||
* - 'facade' 保留原始模块信息,将所有模块转化为一个 SystemJS 模块,但这些模块都打包在一个单独的 IIFE bundle 模块中。
|
||||
* 当这个 bundle 模块执行时,所有模块都会被注册。
|
||||
* 当你希望代码中仍旧使用模块化的特性(如动态导入、import.meta.url),但又不希望模块零散在多个文件时可以使用这个选项。
|
||||
*/
|
||||
export type ModulePreservation = 'erase' | 'preserve' | 'facade';
|
||||
|
||||
export type INewConsoleType = 'log' | 'warn' | 'error' | 'debug';
|
||||
|
||||
export interface IInternalBuildOptions extends IBuildTaskOption {
|
||||
dest: string;
|
||||
// 编译 application.js 参数配置
|
||||
appTemplateData: appTemplateData;
|
||||
// 编译引擎参数配置
|
||||
buildEngineParam: IBuildEngineParam;
|
||||
// 编译脚本配置选项
|
||||
buildScriptParam: IBuildScriptParam;
|
||||
// 序列化打包资源时的特殊处理
|
||||
assetSerializeOptions: {
|
||||
'cc.EffectAsset': {
|
||||
glsl1: boolean;
|
||||
glsl3: boolean;
|
||||
glsl4: boolean;
|
||||
};
|
||||
// 是否输出 ccon 格式
|
||||
exportCCON?: boolean;
|
||||
|
||||
allowCCONExtension?: boolean;
|
||||
};
|
||||
updateOnly: boolean;
|
||||
nextTasks?: string[];
|
||||
generateCompileConfig?: boolean;
|
||||
recompileConfig?: IRecompileConfig;
|
||||
logDest?: string; // log 输出地址
|
||||
|
||||
// 项目设置,重复定义为必选参数
|
||||
includeModules: string[];
|
||||
renderPipeline: string;
|
||||
designResolution: IBuildDesignResolution;
|
||||
physicsConfig: any;
|
||||
flags: Record<string, boolean>;
|
||||
}
|
||||
|
||||
|
||||
export interface appTemplateData {
|
||||
debugMode: boolean;
|
||||
renderMode: boolean; // !!options.renderMode,
|
||||
// ImportMapSupported: boolean;
|
||||
// NonconformingCommonJs: boolean;
|
||||
showFPS: boolean;
|
||||
importMapFile?: string;
|
||||
resolution: {
|
||||
policy: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
// hasPhysicsAmmo: boolean;
|
||||
md5Cache: boolean;
|
||||
server: string; // 服务器地址
|
||||
|
||||
cocosTemplate?: string; // 注入的子模板路径
|
||||
}
|
||||
|
||||
export interface IBuildEngineParam {
|
||||
entry?: string; // 引擎入口文件
|
||||
debug: boolean;
|
||||
sourceMaps: boolean;
|
||||
platform: string;
|
||||
includeModules: string[];
|
||||
engineVersion: string;
|
||||
md5Map: string[];
|
||||
engineName: string;
|
||||
useCache: boolean;
|
||||
split?: boolean;
|
||||
targets?: ITransformTarget;
|
||||
skip?: boolean;
|
||||
ammoJsWasm?: boolean | 'fallback';
|
||||
assetURLFormat?:
|
||||
| 'relative-from-out'
|
||||
| 'relative-from-chunk'
|
||||
| 'runtime-resolved';
|
||||
baseUrl?: string;
|
||||
}
|
||||
|
||||
export type ITransformTarget = string | string[] | Record<string, string>;
|
||||
|
||||
export interface IRecompileConfig {
|
||||
enable: boolean;
|
||||
generateAssets: boolean;
|
||||
generateScripts: boolean;
|
||||
generateEngine: boolean; // 是否生成引擎
|
||||
generateEngineByCache: boolean; // 是否使用缓存引擎
|
||||
}
|
||||
76
extensions/we_sane/@types/packages/builder/@types/public/build-plugin.d.ts
vendored
Normal file
76
extensions/we_sane/@types/packages/builder/@types/public/build-plugin.d.ts
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import { ITextureCompressType, IPVRQuality, IASTCQuality, IETCQuality } from './texture-compress';
|
||||
import { IBuildTaskOption } from './options';
|
||||
import { IBuildResult } from './build-result';
|
||||
|
||||
export interface IBuildPluginConfig {
|
||||
hooks?: string; // relate url about IHook
|
||||
options?: IDisplayOptions; // config of options
|
||||
verifyRuleMap?: IVerificationRuleMap;
|
||||
}
|
||||
|
||||
export type IVerificationFunc = (val: any, ...arg: any[]) => boolean | Promise<boolean>;
|
||||
|
||||
export type IVerificationRuleMap = Record<
|
||||
string,
|
||||
{
|
||||
func?: IVerificationFunc;
|
||||
message?: string;
|
||||
}
|
||||
>;
|
||||
|
||||
export type IDisplayOptions = Record<string, IConfigItem>;
|
||||
|
||||
export type ArrayItem = {
|
||||
label: string;
|
||||
value: string;
|
||||
};
|
||||
export interface IConfigItem {
|
||||
// 配置显示的名字,如果需要翻译,则传入 i18n:${key}
|
||||
label?: string;
|
||||
// 设置的简单说明
|
||||
description?: string;
|
||||
// 默认值
|
||||
default?: any;
|
||||
// 配置的类型
|
||||
type?: 'array' | 'object';
|
||||
itemConfigs?: IConfigItem[] | Record<string, IConfigItem>;
|
||||
verifyRules?: string[];
|
||||
attributes?: any;
|
||||
render?: {
|
||||
ui: string;
|
||||
attributes?: any;
|
||||
items?: ArrayItem[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface IBuildPlugin {
|
||||
configs?: BuildPlugin.Configs;
|
||||
assetHandlers?: BuildPlugin.AssetHandlers;
|
||||
load?: BuildPlugin.load;
|
||||
unload?: BuildPlugin.Unload;
|
||||
}
|
||||
export type IBaseHooks = (options: IBuildTaskOption, result: IBuildResult) => Promise<void> | void;
|
||||
|
||||
export namespace BuildPlugin {
|
||||
export type Configs = Record<string, IBuildPluginConfig>;
|
||||
export type AssetHandlers = string;
|
||||
export type load = () => Promise<void> | void;
|
||||
export type Unload = () => Promise<void> | void;
|
||||
}
|
||||
|
||||
export namespace BuildHook {
|
||||
export type throwError = boolean; // 插件注入的钩子函数,在执行失败时是否直接退出构建流程
|
||||
export type title = string; // 插件任务整体 title,支持 i18n 写法
|
||||
export type onBeforeBuild = IBaseHooks;
|
||||
export type onBeforeCompressSettings = IBaseHooks;
|
||||
export type onAfterCompressSettings = IBaseHooks;
|
||||
export type onAfterBuild = IBaseHooks;
|
||||
export type load = () => Promise<void> | void;
|
||||
export type unload = () => Promise<void> | void;
|
||||
}
|
||||
|
||||
export namespace AssetHandlers {
|
||||
export type compressTextures = (
|
||||
tasks: { src: string; dest: string; quality: number | IPVRQuality | IASTCQuality | IETCQuality; format: ITextureCompressType }[],
|
||||
) => Promise<void>;
|
||||
}
|
||||
189
extensions/we_sane/@types/packages/builder/@types/public/build-result.d.ts
vendored
Normal file
189
extensions/we_sane/@types/packages/builder/@types/public/build-result.d.ts
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* settings.js 里定义的数据
|
||||
*/
|
||||
|
||||
import { ISplashSetting, ICustomJointTextureLayout, UUID } from "./options";
|
||||
|
||||
// ****************************** settings ************************************************
|
||||
|
||||
// debug: true
|
||||
// designResolution: {width: "960", height: "640", policy: 4}
|
||||
// jsList: ["assets/resources/b.js", "assets/resources/a.js"]
|
||||
// launchScene: "db://assets/New Scene-001.scene"
|
||||
// platform: "web-desktop"
|
||||
// rawAssets: {
|
||||
// assets: {
|
||||
// "0e95a9f8-d4e7-4849-875a-7a11dd692b34": ["mesh/env/gltf/textures/birch_yellow_mat_baseColor.png", "cc.ImageAsset"]
|
||||
// }
|
||||
// internal: {
|
||||
// "1baf0fc9-befa-459c-8bdd-af1a450a0319": ["effects/builtin-standard.effect", "cc.EffectAsset"]
|
||||
// }
|
||||
// }
|
||||
// scenes: [{url: "db://assets/New Scene-001.scene", uuid: "69dc4a42-cc6c-49fb-9a57-7de0c212f83d"},…]
|
||||
// startScene: "current_scene"
|
||||
export interface ISettings {
|
||||
CocosEngine: string;
|
||||
debug: boolean;
|
||||
designResolution: ISettingsDesignResolution;
|
||||
jsList: string[];
|
||||
launchScene: string;
|
||||
moduleIds: string[];
|
||||
platform: string;
|
||||
renderPipeline: string;
|
||||
physics?: IPhysicsConfig;
|
||||
exactFitScreen: boolean;
|
||||
|
||||
bundleVers: Record<string, string>;
|
||||
subpackages: string[];
|
||||
remoteBundles: string[];
|
||||
server: string;
|
||||
hasResourcesBundle: boolean;
|
||||
hasStartSceneBundle: boolean;
|
||||
|
||||
scriptPackages?: string[];
|
||||
splashScreen?: ISplashSetting;
|
||||
|
||||
customJointTextureLayouts?: ICustomJointTextureLayout[];
|
||||
|
||||
importMaps?: Array<{
|
||||
url: string;
|
||||
map: any;
|
||||
}>;
|
||||
|
||||
macros?: Record<string, any>;
|
||||
collisionMatrix?: any;
|
||||
groupList?: any;
|
||||
// preview
|
||||
engineModules: string[];
|
||||
customLayers: {name: string, bit: number}[];
|
||||
}
|
||||
|
||||
// 物理配置
|
||||
export interface IVec3Like {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
}
|
||||
|
||||
export interface ICollisionMatrix {
|
||||
[x: string]: number;
|
||||
}
|
||||
|
||||
export interface IPhysicsMaterial {
|
||||
friction: number; // 0.5
|
||||
rollingFriction: number; // 0.1
|
||||
spinningFriction: number; // 0.1
|
||||
restitution: number; // 0.1
|
||||
}
|
||||
|
||||
export interface IPhysicsConfig {
|
||||
gravity: IVec3Like; // (0,-10, 0)
|
||||
allowSleep: boolean; // true
|
||||
sleepThreshold: number; // 0.1,最小 0
|
||||
autoSimulation: boolean; // true
|
||||
fixedTimeStep: number; // 1 / 60 ,最小 0
|
||||
maxSubSteps: number; // 1,最小 0
|
||||
defaultMaterial: IPhysicsMaterial;
|
||||
useNodeChains: boolean; // true
|
||||
collisionMatrix: ICollisionMatrix;
|
||||
physicsEngine: string;
|
||||
}
|
||||
|
||||
export interface IPackageInfo {
|
||||
name: string;
|
||||
path: string;
|
||||
uuids: UUID[];
|
||||
}
|
||||
|
||||
export interface ISettingsDesignResolution {
|
||||
width: number;
|
||||
height: number;
|
||||
policy: number;
|
||||
}
|
||||
|
||||
interface IAssetPathBase {
|
||||
bundleName?: string;
|
||||
redirect?: string; // 重定向的 bundle 包名
|
||||
}
|
||||
|
||||
export interface IRawAssetPathInfo extends IAssetPathBase {
|
||||
raw: string[];
|
||||
}
|
||||
export declare interface IAssetPathInfo extends IAssetPathBase {
|
||||
raw?: string[];
|
||||
json?: string;
|
||||
groupIndex?: number;
|
||||
}
|
||||
|
||||
export interface IJsonPathInfo extends IAssetPathBase {
|
||||
json?: string;
|
||||
groupIndex?: number;
|
||||
}
|
||||
|
||||
export interface IBuildPaths {
|
||||
dir: string; // 构建资源输出地址( assets 所在的目录,并不一定与构建目录对应)
|
||||
settings: string; // settings.json 输出地址
|
||||
systemJs?: string; // system.js 生成地址
|
||||
engineDir?: string; // 引擎生成地址
|
||||
polyfillsJs?: string; // polyfill.js 生成地址
|
||||
assets: string; // assets 目录
|
||||
subpackages: string; // subpackages 目录
|
||||
remote: string; // remote 目录
|
||||
bundleScripts: string // bundle 的脚本,某些平台无法下载脚本,则将远程包中的脚本移到本地
|
||||
applicationJS: string; // application.js 的生成地址
|
||||
compileConfig?: string; // cocos.compile.config.json
|
||||
importMap: string; // import-map 文件地址
|
||||
}
|
||||
|
||||
export declare class IBuildResult {
|
||||
dest: string; // options 指定的构建目录
|
||||
|
||||
paths: IBuildPaths; // 构建后资源相关地址集合
|
||||
|
||||
settings?: ISettings;
|
||||
|
||||
/**
|
||||
* 指定的 uuid 资源是否包含在构建资源中
|
||||
*/
|
||||
containsAsset: (uuid: string) => boolean;
|
||||
|
||||
/**
|
||||
* 获取指定 uuid 原始资源的存放路径(不包括序列化 json)
|
||||
* 自动图集的小图 uuid 和自动图集的 uuid 都将会查询到合图大图的生成路径
|
||||
* 实际返回多个路径的情况:查询 uuid 为自动图集资源,且对应图集生成多张大图,纹理压缩会有多个图片格式路径
|
||||
*/
|
||||
getRawAssetPaths: (uuid: string) => IRawAssetPathInfo[];
|
||||
|
||||
/**
|
||||
* 获取指定 uuid 资源的序列化 json 路径
|
||||
*/
|
||||
getJsonPathInfo: (uuid: string) => IJsonPathInfo[];
|
||||
|
||||
/**
|
||||
* 获取指定 uuid 资源的路径相关信息
|
||||
* @return {raw?: string[]; json?: string; groupIndex?: number;}
|
||||
* @return.raw: 该资源源文件的实际存储位置
|
||||
* @return.json: 该资源序列化 json 的实际存储位置,不存在为空
|
||||
* @return.groupIndex: 若该资源的序列化 json 在某个 json 分组内,这里标识在分组内的 index,不存在为空
|
||||
*/
|
||||
getAssetPathInfo: (uuid: string) => IAssetPathInfo[];
|
||||
}
|
||||
|
||||
export interface IBundleConfig {
|
||||
importBase: string; // bundle 中 import 目录的名称,通常是 'import'
|
||||
nativeBase: string; // native 中 native 目录的名称,通常是 'native'
|
||||
name: string; // bundle 的名称,可以通过 bundle 名称加载 bundle
|
||||
deps: string[]; // 该 bundle 依赖的其他 bundle 名称
|
||||
uuids: UUID[]; // 该 bundle 中的所有资源的 uuid
|
||||
paths: Record<string, any[]>; // 该 bundle 中可以通过路径加载的资源,参考以前 settings 中 rawAssets 的定义
|
||||
scenes: Record<string, UUID|number>; // 该 bundle 中所有场景,场景名为 key, uuid 为 value
|
||||
packs: Record<UUID, UUID[]>; // 该 bundle 中所有合并的 json, 参考以前 settings 中 packedAssets 的定义
|
||||
versions: { import: Array<string|number>, native: Array<string|number> }; // 该 bundle 中所有资源的版本号,参考以前 settings 中 md5AssetsMap 的定义
|
||||
redirect: Array<string|number>; // 该 bundle 中重定向到其他 bundle 的资源
|
||||
debug: boolean; // 是否是 debug 模式,debug 模式会对 config.json 的数据进行压缩,所以运行时得解压
|
||||
types?: string[]; // paths 中的类型数组,参考以前 settings 中 assetTypes 的定义
|
||||
encrypted?: boolean; // 原生上使用,标记该 bundle 中的脚本是否加密
|
||||
isZip?: boolean; // 是否是 zip 模式
|
||||
zipVersion?: string;
|
||||
extensionMap: Record<string, UUID[]>
|
||||
}
|
||||
7
extensions/we_sane/@types/packages/builder/@types/public/global.d.ts
vendored
Normal file
7
extensions/we_sane/@types/packages/builder/@types/public/global.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { IBuild } from ".";
|
||||
|
||||
// 定义 builder 进程内的全局变量
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
const Build: IBuild;
|
||||
}
|
||||
100
extensions/we_sane/@types/packages/builder/@types/public/index.d.ts
vendored
Normal file
100
extensions/we_sane/@types/packages/builder/@types/public/index.d.ts
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import { ITransformOptions } from './options';
|
||||
|
||||
export * from './build-result';
|
||||
export * from './build-plugin';
|
||||
export * from './texture-compress';
|
||||
export * from './options';
|
||||
|
||||
interface IAppendRes {
|
||||
hash: string;
|
||||
paths: string[];
|
||||
}
|
||||
|
||||
interface ICreateBundleOptions {
|
||||
excludes?: string[];
|
||||
debug?: boolean;
|
||||
sourceMap?: boolean;
|
||||
}
|
||||
export interface IBuildUtils {
|
||||
/**
|
||||
* 压缩 uuid
|
||||
* 'fc991dd7-0033-4b80-9d41-c8a86a702e59' -> 'fc9913XADNLgJ1ByKhqcC5Z'
|
||||
*/
|
||||
compressUuid: (uuid: string, min: boolean) => string;
|
||||
|
||||
/**
|
||||
* 解压缩 uuid
|
||||
* 'fc9913XADNLgJ1ByKhqcC5Z' -> 'fc991dd7-0033-4b80-9d41-c8a86a702e59'
|
||||
*/
|
||||
decompressUuid: (uuid: string) => string;
|
||||
|
||||
/**
|
||||
* 翻译带有 i18n 开头的名称(i18n:test)(待定)
|
||||
* 'i18n:test' -> '测试'
|
||||
*/
|
||||
transI18nName: (name: string) => string;
|
||||
|
||||
/**
|
||||
* 移除 db 前缀
|
||||
* 'db://assets/test.jpg' -> 'assets/test.jpg'
|
||||
*/
|
||||
removeDbHeader: (url: string) => string;
|
||||
|
||||
/**
|
||||
* 将 db 开头的 url 转为项目里的实际 url
|
||||
* 'db://assets/test.jpg' -> 'c:/project/assets/test.jpg'
|
||||
*/
|
||||
dbUrlToRawPath: (url: string) => string;
|
||||
|
||||
/**
|
||||
* 从路径里获取存在的 uuid
|
||||
* 'E:\test3d\library\oc\0c0c1f5742-89b0-4a1e-b5eb-914d84f48c1c.json' -> '0c0c1f5742-89b0-4a1e-b5eb-914d84f48c1c'
|
||||
*/
|
||||
getUuidFromPath: (path: string) => string;
|
||||
|
||||
/**
|
||||
* 检查是否全局安装了 nodejs
|
||||
*/
|
||||
isInstallNodeJs: () => Promise<boolean>;
|
||||
|
||||
/**
|
||||
* 逐文件拷贝
|
||||
*/
|
||||
copyDirSync: (src: string, dest: string) => void;
|
||||
|
||||
/**
|
||||
* 获取相对路径接口
|
||||
* 返回 / 拼接的相对路径
|
||||
*/
|
||||
relativeUrl: (from: string, to: string) => string;
|
||||
|
||||
transformCode: (code: string, options: ITransformOptions) => Promise<string>;
|
||||
|
||||
/**
|
||||
* 给指定路径添加 md5
|
||||
*/
|
||||
appendMd5ToPaths: (paths: string[]) => Promise<IAppendRes | null>;
|
||||
|
||||
calcMd5: (data: Buffer | string) => string;
|
||||
|
||||
copyPaths: (paths: { src: string; dest: string }[]) => Promise<void[]>;
|
||||
|
||||
createBundle: (src: string, dest: string, options?: ICreateBundleOptions) => Promise<unknown>;
|
||||
}
|
||||
export interface IBuild {
|
||||
Utils: IBuildUtils;
|
||||
|
||||
LIBRARY_NAME: string;
|
||||
IMPORT_HEADER: string;
|
||||
NATIVE_HEADER: string;
|
||||
ASSETS_HEADER: string;
|
||||
SUBPACKAGES_HEADER: string;
|
||||
REMOTE_HEADER: string;
|
||||
BUNDLE_SCRIPTS_HEADER: string;
|
||||
SCRIPT_NAME: string;
|
||||
CONFIG_NAME: string;
|
||||
BUNDLE_ZIP_NAME: string;
|
||||
projectTempDir: string;
|
||||
globalTempDir: string;
|
||||
buildTemplateDir: string; // 构建模板地址 build-templates
|
||||
}
|
||||
40
extensions/we_sane/@types/packages/builder/@types/public/message.d.ts
vendored
Normal file
40
extensions/we_sane/@types/packages/builder/@types/public/message.d.ts
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { IBundleConfig, ISettings } from "./build-result";
|
||||
import { ITaskItemJSON } from "./options";
|
||||
export interface message extends EditorMessageMap {
|
||||
'open-devtools': {
|
||||
params: [],
|
||||
result: void,
|
||||
},
|
||||
open: {
|
||||
params: [],
|
||||
result: void,
|
||||
},
|
||||
'generate-preview-setting': {
|
||||
params: any[],
|
||||
result: Promise<{
|
||||
settings: ISettings;
|
||||
script2library: Record<string, string>;
|
||||
bundleConfigs: IBundleConfig[];
|
||||
}>,
|
||||
},
|
||||
'query-tasks-info': {
|
||||
params: [],
|
||||
result: {
|
||||
queue: Record<string, ITaskItemJSON>,
|
||||
free: Promise<boolean>,
|
||||
},
|
||||
},
|
||||
'query-task': {
|
||||
params: string[],
|
||||
result: Promise<ITaskItemJSON>,
|
||||
},
|
||||
/**
|
||||
* 预览合图
|
||||
* @param {object} pacUuid
|
||||
*/
|
||||
'preview-pac': {
|
||||
params: string[],
|
||||
result: Promise<ITaskItemJSON>,
|
||||
},
|
||||
|
||||
}
|
||||
132
extensions/we_sane/@types/packages/builder/@types/public/options.d.ts
vendored
Normal file
132
extensions/we_sane/@types/packages/builder/@types/public/options.d.ts
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 构建所需的完整参数
|
||||
*/
|
||||
export interface IBuildTaskOption {
|
||||
// 构建后的游戏文件夹生成的路径
|
||||
buildPath: string;
|
||||
debug: boolean;
|
||||
inlineSpriteFrames: boolean;
|
||||
md5Cache: boolean;
|
||||
// bundle 设置
|
||||
mainBundleCompressionType: BundleCompressionType;
|
||||
mainBundleIsRemote: boolean;
|
||||
moveRemoteBundleScript: boolean;
|
||||
mergeJson: boolean;
|
||||
name: string;
|
||||
packAutoAtlas: boolean;
|
||||
platform: Platform;
|
||||
scenes: IBuildSceneItem[];
|
||||
compressTexture: boolean;
|
||||
sourceMaps: boolean;
|
||||
startScene: string;
|
||||
outputName: string;
|
||||
experimentalEraseModules: boolean;
|
||||
|
||||
/**
|
||||
* 是否是预览进程发送的构建请求。
|
||||
* @default false
|
||||
*/
|
||||
preview?: boolean;
|
||||
|
||||
// 项目设置
|
||||
includeModules?: string[];
|
||||
renderPipeline?: string;
|
||||
designResolution?: IBuildDesignResolution;
|
||||
physicsConfig?: any;
|
||||
flags?: Record<string, boolean>;
|
||||
|
||||
|
||||
// 是否使用自定义插屏选项
|
||||
replaceSplashScreen?: boolean;
|
||||
splashScreen: ISplashSetting;
|
||||
|
||||
packages?: Record<string, any>;
|
||||
id?: string; // 手动配置构建任务 id
|
||||
// recompileConfig?: IRecompileConfig;
|
||||
|
||||
customLayers: {name: string, value: number}[];
|
||||
}
|
||||
|
||||
export type UUID = string;
|
||||
|
||||
export interface ISplashSetting {
|
||||
base64src: string;
|
||||
displayRatio: number;
|
||||
totalTime: number;
|
||||
effect: string;
|
||||
clearColor: { x: number; y: number; z: number; w: number };
|
||||
displayWatermark: boolean;
|
||||
}
|
||||
|
||||
export interface ICustomJointTextureLayout {
|
||||
textureLength: number;
|
||||
contents: IChunkContent[];
|
||||
}
|
||||
|
||||
export interface IChunkContent {
|
||||
skeleton: null | string;
|
||||
clips: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建使用的设计分辨率数据
|
||||
*/
|
||||
export interface IBuildDesignResolution {
|
||||
height: number;
|
||||
width: number;
|
||||
fitWidth?: boolean;
|
||||
fitHeight?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建使用的场景的数据
|
||||
*/
|
||||
export interface IBuildSceneItem {
|
||||
url: string;
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
// **************************** options *******************************************
|
||||
export type Platform =
|
||||
| 'web-desktop'
|
||||
| 'web-mobile'
|
||||
| 'wechatgame'
|
||||
| 'oppo-mini-game'
|
||||
| 'vivo-mini-game'
|
||||
| 'huawei-quick-game'
|
||||
| 'alipay-mini-game'
|
||||
| 'mac'
|
||||
| 'ios'
|
||||
// | 'ios-app-clip'
|
||||
| 'android'
|
||||
| 'ohos'
|
||||
| 'windows'
|
||||
| 'xiaomi-quick-game'
|
||||
| 'baidu-mini-game'
|
||||
| 'bytedance-mini-game'
|
||||
| 'cocos-play'
|
||||
| 'huawei-agc'
|
||||
| 'link-sure'
|
||||
| 'qtt'
|
||||
| 'cocos-runtime'
|
||||
;
|
||||
|
||||
export type BundleCompressionType = 'none' | 'merge_dep' | 'merge_all_json' | 'subpackage' | 'zip';
|
||||
export type IModules = 'esm' | 'commonjs' | 'systemjs';
|
||||
|
||||
export interface ITransformOptions {
|
||||
importMapFormat: IModules;
|
||||
}
|
||||
|
||||
export type ITaskState = 'waiting' | 'success' | 'failure' | 'cancel' | 'processing';
|
||||
|
||||
export interface ITaskItemJSON {
|
||||
id: string;
|
||||
progress: number;
|
||||
state: ITaskState;
|
||||
message: string;
|
||||
options: IBuildTaskOption;
|
||||
time: string;
|
||||
dirty: boolean;
|
||||
rawOptions: IBuildTaskOption;
|
||||
}
|
||||
43
extensions/we_sane/@types/packages/builder/@types/public/texture-compress.d.ts
vendored
Normal file
43
extensions/we_sane/@types/packages/builder/@types/public/texture-compress.d.ts
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
export type ITextureCompressType =
|
||||
| 'jpg'
|
||||
| 'png'
|
||||
| 'webp'
|
||||
| 'pvrtc_4bits_rgb'
|
||||
| 'pvrtc_4bits_rgba'
|
||||
| 'pvrtc_4bits_rgb_a'
|
||||
| 'pvrtc_2bits_rgb'
|
||||
| 'pvrtc_2bits_rgba'
|
||||
| 'pvrtc_2bits_rgb_a'
|
||||
| 'etc1_rgb'
|
||||
| 'etc1_rgb_a'
|
||||
| 'etc2_rgb'
|
||||
| 'etc2_rgba'
|
||||
| 'astc_4x4'
|
||||
| 'astc_5x5'
|
||||
| 'astc_6x6'
|
||||
| 'astc_8x8'
|
||||
| 'astc_10x5'
|
||||
| 'astc_10x10'
|
||||
| 'astc_12x12';
|
||||
export type ITextureCompressPlatform = 'miniGame' | 'web' | 'ios' | 'android';
|
||||
export type IQualityType = 'etc' | 'pvr' | 'number' | 'astc';
|
||||
export interface ITextureFormatInfo {
|
||||
displayName: string;
|
||||
qualityType: IQualityType;
|
||||
alpha?: boolean;
|
||||
}
|
||||
export interface ISupportFormat {
|
||||
rgb: ITextureCompressType[];
|
||||
rgba: ITextureCompressType[];
|
||||
}
|
||||
export interface IConfigGroupsInfo {
|
||||
defaultSupport?: ISupportFormat,
|
||||
support: ISupportFormat,
|
||||
displayName: string;
|
||||
icon: string;
|
||||
}
|
||||
export type IConfigGroups = Record<ITextureCompressPlatform, IConfigGroupsInfo>;
|
||||
|
||||
export type IPVRQuality = 'fastest' | 'fast' | 'normal' | 'high' | 'best';
|
||||
export type IETCQuality = 'slow' | 'fast';
|
||||
export type IASTCQuality = 'veryfast' | 'fast' | 'medium' | 'thorough' | 'exhaustive';
|
||||
16
extensions/we_sane/@types/packages/console/@types/pritate.d.ts
vendored
Normal file
16
extensions/we_sane/@types/packages/console/@types/pritate.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export interface IMessageItem {
|
||||
rows: number;
|
||||
translateY: number;
|
||||
show: boolean;
|
||||
title: string;
|
||||
content: string[];
|
||||
count: number;
|
||||
fold: boolean;
|
||||
type: string;
|
||||
message: any;
|
||||
texture: string;
|
||||
date?: number;
|
||||
time?: number;
|
||||
process?: string;
|
||||
stack: string[];
|
||||
}
|
||||
16
extensions/we_sane/@types/packages/engine/@types/message.d.ts
vendored
Normal file
16
extensions/we_sane/@types/packages/engine/@types/message.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export interface message extends EditorMessageMap {
|
||||
'query-info': {
|
||||
params: [] | [
|
||||
string,
|
||||
],
|
||||
result: {
|
||||
type: string;
|
||||
version: string;
|
||||
path: string;
|
||||
nativeVersion: string; // 原生引擎类型 'custom' 'builtin'
|
||||
nativePath: string;
|
||||
editor: string;
|
||||
renderPipeline: string;
|
||||
},
|
||||
},
|
||||
}
|
||||
1
extensions/we_sane/@types/packages/preview/@types/index.d.ts
vendored
Normal file
1
extensions/we_sane/@types/packages/preview/@types/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from './protect/';
|
||||
33
extensions/we_sane/@types/packages/preview/@types/protect/index.d.ts
vendored
Normal file
33
extensions/we_sane/@types/packages/preview/@types/protect/index.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Platform } from "../../../builder/@types/public";
|
||||
|
||||
export type IPreviewType = 'game-view' | 'simulator' | 'browser';
|
||||
|
||||
export type ISupportDataType = 'settings' | 'renderData';
|
||||
|
||||
export interface IHookConfig {
|
||||
methods: string;
|
||||
hook: string;
|
||||
}
|
||||
export interface IGenerateSettingsOptions {
|
||||
type: IPreviewType;
|
||||
startScene?: string;
|
||||
platform?: Platform;
|
||||
}
|
||||
|
||||
export interface IPreviewPluginConfig {
|
||||
methods?: string;
|
||||
hooks?: Record<string, string>;
|
||||
}
|
||||
|
||||
// 界面渲染配置
|
||||
export interface IRenderData {
|
||||
title: string; // 预览页面 title
|
||||
enableDebugger: boolean; // 是否开启 vConsole
|
||||
config: { // 预览页面菜单栏配置
|
||||
device: string; // 设备名称
|
||||
// https://github.com/cocos-creator/engine/blob/3d/cocos/core/platform/debug.ts
|
||||
debugMode: string; // cc.DebugMode 枚举名称
|
||||
showFps: boolean;
|
||||
fps: number;
|
||||
}
|
||||
}
|
||||
19
extensions/we_sane/@types/packages/programming/@types/message.d.ts
vendored
Normal file
19
extensions/we_sane/@types/packages/programming/@types/message.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
export interface message extends EditorMessageMap {
|
||||
'query-shared-settings': {
|
||||
params: [],
|
||||
result: {
|
||||
useDefineForClassFields: boolean;
|
||||
allowDeclareFields: boolean;
|
||||
loose: boolean;
|
||||
guessCommonJsExports: boolean;
|
||||
exportsConditions: string[];
|
||||
importMap?: {
|
||||
json: {
|
||||
imports?: Record<string, string>;
|
||||
scopes?: Record<string, Record<string, string>>;
|
||||
};
|
||||
url: string;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
68
extensions/we_sane/@types/packages/scene/@types/message.d.ts
vendored
Normal file
68
extensions/we_sane/@types/packages/scene/@types/message.d.ts
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
SetPropertyOptions,
|
||||
} from './public';
|
||||
|
||||
export interface message extends EditorMessageMap {
|
||||
'update-create-node-template': {
|
||||
params: [],
|
||||
result: any,
|
||||
},
|
||||
'open': {
|
||||
params: [],
|
||||
result: any,
|
||||
},
|
||||
'open-devtools': {
|
||||
params: [],
|
||||
result: any,
|
||||
},
|
||||
'graphical-tools': {
|
||||
params: [
|
||||
boolean,
|
||||
],
|
||||
result: void,
|
||||
},
|
||||
'open-scene': {
|
||||
params: [
|
||||
string,
|
||||
],
|
||||
result: boolean,
|
||||
},
|
||||
'save-scene': {
|
||||
params: [] | [
|
||||
boolean,
|
||||
],
|
||||
result: boolean,
|
||||
},
|
||||
'save-as-scene': {
|
||||
params: [
|
||||
boolean,
|
||||
],
|
||||
result: boolean,
|
||||
},
|
||||
'close-scene': {
|
||||
params: [],
|
||||
result: boolean,
|
||||
},
|
||||
'set-property': {
|
||||
params: [
|
||||
SetPropertyOptions,
|
||||
],
|
||||
result: boolean,
|
||||
},
|
||||
'query-node-tree': {
|
||||
params: [] | [
|
||||
string,
|
||||
],
|
||||
result: any,
|
||||
},
|
||||
'execute-scene-script': {
|
||||
params: [] | [
|
||||
{
|
||||
name: string;
|
||||
method: string;
|
||||
args: any[];
|
||||
}
|
||||
],
|
||||
result: any,
|
||||
},
|
||||
}
|
||||
407
extensions/we_sane/@types/packages/scene/@types/public.d.ts
vendored
Normal file
407
extensions/we_sane/@types/packages/scene/@types/public.d.ts
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
// ---- 一些 engine 基础数据 ---- start
|
||||
interface Vec2 {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export interface Vec3 {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
}
|
||||
|
||||
interface Vec4 {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
w: number;
|
||||
}
|
||||
|
||||
interface Quat {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
w: number;
|
||||
}
|
||||
|
||||
interface Color3 {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
}
|
||||
|
||||
interface Color4 {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
a: number;
|
||||
}
|
||||
|
||||
interface Mat3 {
|
||||
m00: number;
|
||||
m01: number;
|
||||
m02: number;
|
||||
|
||||
m03: number;
|
||||
m04: number;
|
||||
m05: number;
|
||||
|
||||
m06: number;
|
||||
m07: number;
|
||||
m08: number;
|
||||
}
|
||||
|
||||
interface Mat4 {
|
||||
m00: number;
|
||||
m01: number;
|
||||
m02: number;
|
||||
m03: number;
|
||||
|
||||
m04: number;
|
||||
m05: number;
|
||||
m06: number;
|
||||
m07: number;
|
||||
|
||||
m08: number;
|
||||
m09: number;
|
||||
m10: number;
|
||||
m11: number;
|
||||
|
||||
m12: number;
|
||||
m13: number;
|
||||
m14: number;
|
||||
m15: number;
|
||||
}
|
||||
// ---- 一些 engine 基础数据 ---- end
|
||||
|
||||
// ---- 操作消息的参数定义 --- strart
|
||||
|
||||
// set-property 消息的 options 定义
|
||||
export interface SetPropertyOptions {
|
||||
uuid: string; // 修改属性的对象的 uuid
|
||||
path: string; // 属性挂载对象的搜索路径
|
||||
// key: string; // 属性的 key
|
||||
dump: IProperty; // 属性 dump 出来的数据
|
||||
}
|
||||
|
||||
// move-array-element 消息的 options 定义
|
||||
export interface MoveArrayOptions {
|
||||
uuid: string;
|
||||
path: string;
|
||||
target: number;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
// remove-array-element 消息的 options 定义
|
||||
export interface RemoveArrayOptions {
|
||||
uuid: string;
|
||||
path: string;
|
||||
index: number;
|
||||
}
|
||||
|
||||
export interface PasteNodeOptions {
|
||||
target: string; // 目标节点
|
||||
uuids: string | string[]; // 被复制的节点 uuids
|
||||
keepWorldTransform?: boolean; // 是否保持新节点的世界坐标不变
|
||||
}
|
||||
|
||||
export interface CutNodeOptions {
|
||||
parent: string; // 父节点
|
||||
uuids: string | string[]; // 被移入的节点 uuids
|
||||
keepWorldTransform?: boolean; // 是否保持新节点的世界坐标不变
|
||||
}
|
||||
|
||||
// create-node 消息的 options 定义
|
||||
export interface CreateNodeOptions {
|
||||
parent?: string;
|
||||
components?: string[];
|
||||
|
||||
name?: string;
|
||||
dump?: INode | IScene; // node 初始化应用的数据
|
||||
keepWorldTransform?: boolean; // 是否保持新节点的世界坐标不变
|
||||
type?: string; // 资源类型
|
||||
assetUuid?: string; // asset uuid , type value 格式保持兼容拖动的数据格式,有资源 id,则从资源内创建对应的节点
|
||||
canvasRequired?: boolean; // 是否需要有 Canvas
|
||||
unlinkPrefab?: boolean; // 创建后取消 prefab 状态
|
||||
position?: Vec3; // 指定生成的位置
|
||||
}
|
||||
|
||||
export interface ResetNodeOptions {
|
||||
uuid: string | string[];
|
||||
}
|
||||
|
||||
export interface RemoveNodeOptions {
|
||||
uuid: string | string[];
|
||||
keepWorldTransform?: boolean;
|
||||
}
|
||||
|
||||
export interface CreateComponentOptions {
|
||||
uuid: string;
|
||||
component: string;
|
||||
}
|
||||
|
||||
export interface ResetComponentOptions {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface RemoveComponentOptions {
|
||||
uuid: string;
|
||||
component: string;
|
||||
}
|
||||
|
||||
export interface ExecuteComponentMethodOptions {
|
||||
uuid: string;
|
||||
name: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export interface IAnimOperation {
|
||||
funcName: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export interface ExecuteSceneScriptMethodOptions {
|
||||
name: string;
|
||||
method: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export type IPropertyValueType = IProperty | IProperty[] | null | undefined | number | boolean | string | Vec3 | Vec2;
|
||||
|
||||
export interface IPropertyGroupOptions {
|
||||
id: string // 默认 'default'
|
||||
name: string,
|
||||
displayOrder: number, // 默认 Infinity, 排在最后面
|
||||
style: string // 默认为 'tab'
|
||||
}
|
||||
|
||||
export interface IProperty {
|
||||
value: { [key: string]: IPropertyValueType } | IPropertyValueType;
|
||||
default?: any; // 默认值
|
||||
|
||||
// 多选节点之后,这里存储多个数据,用于自行判断多选后的显示效果,无需更新该数据
|
||||
values?: ({ [key: string]: IPropertyValueType } | IPropertyValueType)[];
|
||||
|
||||
cid?: string;
|
||||
type?: string;
|
||||
readonly?: boolean;
|
||||
visible?: boolean;
|
||||
name?: string;
|
||||
|
||||
elementTypeData?: IProperty; // 数组里的数据的默认值 dump
|
||||
|
||||
path?: string; // 数据的搜索路径,这个是由使用方填充的
|
||||
|
||||
isArray?: boolean;
|
||||
invalid?: boolean;
|
||||
extends?: string[]; // 继承链
|
||||
displayName?: string; // 显示到界面上的名字
|
||||
displayOrder?: number; // 显示排序
|
||||
group?: IPropertyGroupOptions; // tab
|
||||
tooltip?: string; // 提示文本
|
||||
editor?: any; // 组件上定义的编辑器数据
|
||||
animatable?: boolean; // 是否可以在动画中编辑
|
||||
|
||||
// Enum
|
||||
enumList?: any[]; // enum 类型的 list 选项数组
|
||||
|
||||
bitmaskList?: any[];
|
||||
|
||||
// Number
|
||||
min?: number; // 数值类型的最小值
|
||||
max?: number; // 数值类型的最大值
|
||||
step?: number; // 数值类型的步进值
|
||||
slide?: boolean; // 数组是否显示为滑块
|
||||
unit?: string; // 显示的单位
|
||||
radian?: boolean; // 标识是否为角度
|
||||
|
||||
// Label
|
||||
multiline?: boolean; // 字符串是否允许换行
|
||||
// nullable?: boolean; 属性是否允许为空
|
||||
}
|
||||
|
||||
export interface IRemovedComponentInfo {
|
||||
name: string;
|
||||
fileID: string;
|
||||
}
|
||||
|
||||
export interface INode {
|
||||
active: IProperty;
|
||||
locked: IProperty;
|
||||
name: IProperty;
|
||||
position: IProperty;
|
||||
|
||||
/**
|
||||
* 此为 dump 数据,非 node.rotation
|
||||
* 实际指向 node.eulerAngles
|
||||
* rotation 为了给用户更友好的文案
|
||||
*/
|
||||
rotation: IProperty;
|
||||
|
||||
scale: IProperty;
|
||||
layer: IProperty;
|
||||
uuid: IProperty;
|
||||
|
||||
children: any[];
|
||||
parent: any;
|
||||
|
||||
__comps__: IProperty[];
|
||||
__type__: string;
|
||||
__prefab__?: any;
|
||||
_prefabInstance?: any;
|
||||
removedComponents?: IRemovedComponentInfo[];
|
||||
mountedRoot?: string;
|
||||
}
|
||||
|
||||
export interface IComponent extends IProperty {
|
||||
value: {
|
||||
enabled: IPropertyValueType;
|
||||
uuid: IPropertyValueType;
|
||||
name: IPropertyValueType;
|
||||
} & Record<string, IPropertyValueType>;
|
||||
mountedRoot?: string;
|
||||
}
|
||||
|
||||
export interface IScene {
|
||||
name: IProperty;
|
||||
active: IProperty;
|
||||
locked: IProperty;
|
||||
_globals: any;
|
||||
isScene: boolean;
|
||||
autoReleaseAssets: IProperty;
|
||||
|
||||
uuid: IProperty;
|
||||
children: any[];
|
||||
parent: any;
|
||||
__type__: string;
|
||||
targetOverrides?: any;
|
||||
}
|
||||
|
||||
export interface ITargetOverrideInfo {
|
||||
source: string;
|
||||
sourceInfo?: string[];
|
||||
propertyPath: string[];
|
||||
target: string;
|
||||
targetInfo?: string[];
|
||||
}
|
||||
// ---- 操作消息的参数定义 --- end
|
||||
|
||||
// ---- 场景插件返回的 info 信息 ---- start
|
||||
interface ScenePluginNodeInfo {
|
||||
uuid: string;
|
||||
components: ScenePluginComponentInfo[];
|
||||
}
|
||||
|
||||
// 场景插件传回的场景信息
|
||||
export interface ScenePluginInfo {
|
||||
// 选中节点列表
|
||||
nodes: ScenePluginNodeInfo[];
|
||||
|
||||
// gizmo 的一些信息
|
||||
gizmo: {
|
||||
is2D: boolean;
|
||||
};
|
||||
// 当前编辑模式数组
|
||||
modes: string[];
|
||||
}
|
||||
|
||||
// 场景插件传回的组件信息
|
||||
export interface ScenePluginComponentInfo {
|
||||
uuid: string;
|
||||
enabled: boolean;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface QueryClassesOptions {
|
||||
extends?: string | string[];
|
||||
excludeSelf?: boolean;
|
||||
}
|
||||
|
||||
// ---- 场景插件返回的 info 信息 ---- end
|
||||
|
||||
// ---- 动画数据 ---- start
|
||||
|
||||
export interface IKeyDumpData {
|
||||
frame: number;
|
||||
dump: any; // value的dump数据
|
||||
inTangent?: number;
|
||||
inTangentWeight?: number;
|
||||
outTangent?: number;
|
||||
outTangentWeight?: number;
|
||||
interpMode?: number;
|
||||
broken?: boolean;
|
||||
tangentWeightMode?: number;
|
||||
imgUrl?: string;
|
||||
easingMethod?: number;
|
||||
}
|
||||
|
||||
export interface IDumpType {
|
||||
value: string;
|
||||
extends?: string[];
|
||||
}
|
||||
|
||||
export interface IPropCurveDumpData {
|
||||
nodePath: string;
|
||||
keyframes: IKeyDumpData[];
|
||||
displayName: string;
|
||||
key: string;
|
||||
type?: IDumpType;
|
||||
preExtrap: number;
|
||||
postExtrap: number;
|
||||
isCurveSupport: boolean; // 是否支持贝塞尔曲线编辑
|
||||
}
|
||||
|
||||
export interface IAnimCopyKeySrcInfo {
|
||||
curvesDump: IPropCurveDumpData[];
|
||||
}
|
||||
|
||||
export interface IAnimCopyNodeSrcInfo {
|
||||
curvesDump: IPropCurveDumpData[];
|
||||
}
|
||||
|
||||
export interface IAnimCopyNodeDstInfo {
|
||||
nodePath: string;
|
||||
}
|
||||
|
||||
interface IEventDump {
|
||||
frame: number;
|
||||
func: string;
|
||||
params: string[];
|
||||
}
|
||||
|
||||
export interface IAnimCopyEventSrcInfo {
|
||||
eventsDump: IEventDump[];
|
||||
}
|
||||
|
||||
export interface IAnimCopyPropSrcInfo {
|
||||
curvesDump: IPropCurveDumpData[];
|
||||
}
|
||||
|
||||
export interface IAnimCopyPropDstInfo {
|
||||
nodePath: string;
|
||||
propKeys?: string[];
|
||||
}
|
||||
|
||||
export interface IAnimCopyKeyDstInfo {
|
||||
nodePath: string;
|
||||
propKeys?: string[];
|
||||
startFrame: number;
|
||||
}
|
||||
|
||||
export interface IAnimCopyEventDstInfo {
|
||||
startFrame: number;
|
||||
}
|
||||
// ---- 动画数据 ---- end
|
||||
|
||||
// ---- Contributions ---- start
|
||||
|
||||
export interface ContributionDropItem {
|
||||
type: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// ---- Contributions ---- end
|
||||
|
||||
export interface UnitTestInfo {
|
||||
name: string;
|
||||
}
|
||||
27
extensions/we_sane/@types/packages/server/@types/package.d.ts
vendored
Normal file
27
extensions/we_sane/@types/packages/server/@types/package.d.ts
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// 消息定义
|
||||
interface MessageInterface {
|
||||
params: any[],
|
||||
result: any;
|
||||
}
|
||||
|
||||
// host
|
||||
export interface HostInfo {
|
||||
host: string;
|
||||
ip: string;
|
||||
port: number;
|
||||
}
|
||||
|
||||
// 消息定义
|
||||
export interface main {
|
||||
scene: {
|
||||
[x: string]: MessageInterface;
|
||||
'query-port': {
|
||||
params: [],
|
||||
result: number,
|
||||
};
|
||||
'scan-lan': {
|
||||
params: [],
|
||||
result: HostInfo[],
|
||||
};
|
||||
}
|
||||
}
|
||||
19
extensions/we_sane/@types/packages/shortcuts/@types/shortcut.d.ts
vendored
Normal file
19
extensions/we_sane/@types/packages/shortcuts/@types/shortcut.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
export interface ShortcutItem {
|
||||
when: string;
|
||||
message: string;
|
||||
shortcut: string;
|
||||
pkgName: string;
|
||||
rawShortcut?: string;
|
||||
key: string;
|
||||
missing?: boolean;
|
||||
}
|
||||
|
||||
export type IShortcutItemMap = Record<string, ShortcutItem>;
|
||||
|
||||
export interface IShortcutEditInfo {
|
||||
key: string;
|
||||
shortcut: string;
|
||||
searches: ShortcutItem[];
|
||||
conflict: boolean;
|
||||
when: string;
|
||||
}
|
||||
16
extensions/we_sane/README-CN.md
Normal file
16
extensions/we_sane/README-CN.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 项目简介
|
||||
|
||||
一份空白的扩展。
|
||||
|
||||
## 开发环境
|
||||
|
||||
Node.js
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
# 安装依赖模块
|
||||
npm install
|
||||
# 构建
|
||||
npm run build
|
||||
```
|
||||
16
extensions/we_sane/README-EN.md
Normal file
16
extensions/we_sane/README-EN.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Project Title
|
||||
|
||||
An blank extension.
|
||||
|
||||
## Development Environment
|
||||
|
||||
Node.js
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
# Install dependent modules
|
||||
npm install
|
||||
# build
|
||||
npm run build
|
||||
```
|
||||
105
extensions/we_sane/dist/buildH5.js
vendored
Normal file
105
extensions/we_sane/dist/buildH5.js
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
var Fs = require("fs");
|
||||
var fsextra = require("fs-extra");
|
||||
var zlib = require('zlib');
|
||||
var archiver = require('archiver');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
load() {
|
||||
this.webUrl = Editor.Project.path + "/build/web-mobile"; //打h5包的路径
|
||||
this.replaceUrl = Editor.Project.path + "/build/replace_H5"; //替换文件路径
|
||||
this.indexUrl = this.webUrl + "/index.html"; //index 位置
|
||||
|
||||
//需要 复制 的文件
|
||||
this.replaceUrls = [
|
||||
"/weSane.js",
|
||||
"/res",
|
||||
]
|
||||
/** index 需要写入的 数据 row行数 */
|
||||
this.writeIndexData = [
|
||||
{ rowNum: 35, writeType: 'ADD', str: ' <meta data-react-helmet="true" property="og:title" content="Game Name"> ' },
|
||||
{ rowNum: 36, writeType: 'ADD', str: ' <meta data-react-helmet="true" property="og:description" content="Game Description">' },
|
||||
{ rowNum: 37, writeType: 'ADD', str: ' <meta data-react-helmet="true" property="og:image" content="res/share.jpg"> ' },
|
||||
{ rowNum: 38, writeType: 'ADD', str: ' <meta http-equiv="cache-control" content="no-cache,no-store,must-revalidate" /> ' },
|
||||
{ rowNum: 39, writeType: 'ADD', str: ' <meta http-equiv="Pragma" content="no-cache" /> ' },
|
||||
{ rowNum: 40, writeType: 'ADD', str: ' <meta http-equiv="expires" content="-1" /> ' },
|
||||
|
||||
{ rowNum: 49, writeType: 'ADD', str: '<div id="splash"><div class="progress-bar stripes"><span style="width: 0%"></span></div></div>' },
|
||||
{ rowNum: 51, writeType: 'ADD', str: '<div id="loadingImg" style="top:24%;align:center;width:100%;position:absolute;z-index:10;"> <img style="border-radius: 15px;" src="res/logo.png" width="90" height="90" /> </div>' },
|
||||
{ rowNum: 52, writeType: 'ADD', str: '<div id="webText" type="text" style="width:100%;text-align:center;position:absolute;top:38%;z-index:99;font-size:16px;color:#1e2222" > </div> ' },
|
||||
{ rowNum: 53, writeType: 'ADD', str: '<div id="loadingText" type="text" style="width:100%;text-align:center;position:absolute;top:56%;z-index:99;font-size:17px;color:#e86c00" > </div> ' },
|
||||
{ rowNum: 54, writeType: 'ADD', str: '<div style="align:center;display: none"><img src="res/share.jpg" width="10%" /></div> ' },
|
||||
|
||||
{ rowNum: 55, writeType: 'ADD', str: ' <script src="weSane.js" charset="utf-8"> </script> ' },
|
||||
|
||||
// { rowNum: 56, writeType: 'ADD', str: ' <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> ' },
|
||||
// { rowNum: 57, writeType: 'ADD', str: ' <script src="https://www.wesane.com/Public/js/Anti-addiction.js"></script> ' },
|
||||
]
|
||||
},
|
||||
|
||||
/** 写入 index 文件 */
|
||||
writeIndex() {
|
||||
let indexStr = Fs.readFileSync(this.indexUrl, 'utf8');//读取文件
|
||||
let strArr = indexStr.split("\n"); //按回车分割成数组
|
||||
this.addStrArrData(this.writeIndexData, strArr);
|
||||
|
||||
let weSaneJs = Fs.readFileSync(this.replaceUrl + "/weSane.js", 'utf8').split("\n");
|
||||
strArr[5] = " <title>" + weSaneJs[4].split('"')[1] + '</title>'; //修改标题
|
||||
|
||||
let writeStr = ""; //写入inex的字符串
|
||||
for (let i = 0; i < strArr.length; i++) {
|
||||
if (i < strArr.length - 1) {
|
||||
writeStr += (strArr[i] + "\n");
|
||||
}
|
||||
}
|
||||
Fs.writeFileSync(this.indexUrl, writeStr, 'utf8');
|
||||
console.log("index 写入成功");
|
||||
},
|
||||
/** 复制文件 打包zip 的名字 */
|
||||
copyFloder(zipName) {
|
||||
for (let i = 0; i < this.replaceUrls.length; i++) {
|
||||
fsextra.copySync(this.replaceUrl + this.replaceUrls[i], this.webUrl + this.replaceUrls[i], 0);
|
||||
}
|
||||
console.log("复制文件完成");
|
||||
// this.gzip(Editor.Project.path + "/build/web-mobile/weSane.js" );
|
||||
let outurl = Editor.Project.path + '/build/' + zipName + '.zip'; //zip 输出目录
|
||||
this.deleteFile(outurl);
|
||||
|
||||
this.zipFolder(this.webUrl, outurl, function (err, msg) {
|
||||
console.log(err, msg);
|
||||
});
|
||||
},
|
||||
/** 删除文件 */
|
||||
deleteFile(url) {
|
||||
if (Fs.existsSync(url)) {
|
||||
Fs.unlinkSync(url);
|
||||
}
|
||||
},
|
||||
/** 打包Zip */
|
||||
zipFolder(sourceFolder, destZip, cb, subdir) {
|
||||
var output = Fs.createWriteStream(destZip);
|
||||
var archive = archiver('zip', {
|
||||
zlib: { level: 9 }
|
||||
});
|
||||
archive.pipe(output);
|
||||
archive.directory(sourceFolder, subdir ? sourceFolder.substr(path.dirname(sourceFolder).length + 1) : false);
|
||||
archive.finalize();
|
||||
console.log("打包zip 完成");
|
||||
},
|
||||
|
||||
/** 添加 需要写入的配置里面的字符串 */
|
||||
addStrArrData(dataArr, strArr) {
|
||||
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
if (dataArr[i].writeType == 'ADD') {
|
||||
if (strArr[dataArr[i].rowNum - 1] == dataArr[i].str) { continue; }
|
||||
strArr.splice(dataArr[i].rowNum - 1, 0, dataArr[i].str);
|
||||
} else if (dataArr[i].writeType == 'REVISE') {
|
||||
strArr[dataArr[i].rowNum - 1] = dataArr[i].str;
|
||||
} else if (dataArr[i].writeType == 'DELETE') {
|
||||
strArr[dataArr[i].rowNum - 1] = '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
44
extensions/we_sane/dist/main.js
vendored
Normal file
44
extensions/we_sane/dist/main.js
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
var Fs = require("fs");
|
||||
const buildH5 = require("./buildH5");
|
||||
|
||||
exports.methods = {
|
||||
/** 打微伞包 */
|
||||
weSaneZip(){
|
||||
buildH5.writeIndex(); //写入Index
|
||||
buildH5.copyFloder("web-mobile_WeSane"); //复制替换文件 并打包zip
|
||||
},
|
||||
/** 打通用包 */
|
||||
commonH5Zip(){
|
||||
buildH5.writeIndex(); //写入Index
|
||||
buildH5.copyFloder("web-mobile_Other"); //复制替换文件 并打包zip
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 启动的时候执行的初始化方法
|
||||
*/
|
||||
exports.load = function() {
|
||||
buildH5.load(); //初始化 打包H5
|
||||
console.warn("we_sane is not compiled yet.");
|
||||
};
|
||||
/**
|
||||
* 插件被关闭的时候执行的卸载方法
|
||||
*/
|
||||
exports.unload = function() {};
|
||||
|
||||
|
||||
/** buildH5Json 配置信息
|
||||
* indexUrl index.html 的工程路径
|
||||
* replaceUrls 替换文件的 配置路径
|
||||
* webUrls 对应替换文件 需要copy 到 web里面的路径
|
||||
* writeIndexData 写入index.html 文件的配置 rowNum:行数 str:需要添加的代码
|
||||
*/
|
||||
1
extensions/we_sane/i18n/en.js
Normal file
1
extensions/we_sane/i18n/en.js
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";module.exports={description:"A blank extension"};
|
||||
1
extensions/we_sane/i18n/zh.js
Normal file
1
extensions/we_sane/i18n/zh.js
Normal file
@@ -0,0 +1 @@
|
||||
"use strict";module.exports={description:"一份空白的扩展"};
|
||||
39
extensions/we_sane/package.json
Normal file
39
extensions/we_sane/package.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"package_version": 2,
|
||||
"version": "1.0.0",
|
||||
"name": "we_sane",
|
||||
"description": "i18n:we_sane.description",
|
||||
"main": "./dist/main.js",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.0.1",
|
||||
"typescript": "^4.3.4"
|
||||
},
|
||||
"author": "Chao",
|
||||
"editor": ">=3.4.0",
|
||||
"scripts": {
|
||||
"build": "tsc -b",
|
||||
"watch": "tsc -w"
|
||||
},
|
||||
"contributions": {
|
||||
"menu": [
|
||||
{
|
||||
"path": "weSane/上线H5",
|
||||
"label": "打包-微伞zip",
|
||||
"message": "build-wesane"
|
||||
},
|
||||
{
|
||||
"path": "weSane/上线H5",
|
||||
"label": "打包-通用zip",
|
||||
"message": "build-h5"
|
||||
}
|
||||
],
|
||||
"messages": {
|
||||
"build-wesane": {
|
||||
"methods": ["weSaneZip"]
|
||||
},
|
||||
"build-h5": {
|
||||
"methods": ["commonH5Zip"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
extensions/we_sane/src/main.ts
Normal file
18
extensions/we_sane/src/main.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
/**
|
||||
* @en Registration method for the main process of Extension
|
||||
* @zh 为扩展的主进程的注册方法
|
||||
*/
|
||||
export const methods: { [key: string]: (...any: any) => any } = { };
|
||||
|
||||
/**
|
||||
* @en Hooks triggered after extension loading is complete
|
||||
* @zh 扩展加载完成后触发的钩子
|
||||
*/
|
||||
export const load = function() { };
|
||||
|
||||
/**
|
||||
* @en Hooks triggered after extension uninstallation is complete
|
||||
* @zh 扩展卸载完成后触发的钩子
|
||||
*/
|
||||
export const unload = function() { };
|
||||
14
extensions/we_sane/tsconfig.json
Normal file
14
extensions/we_sane/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2017",
|
||||
"module": "CommonJS",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
}
|
||||
}
|
||||
181
extensions/web-easy-obfus/README-CN.md
Normal file
181
extensions/web-easy-obfus/README-CN.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# CC3.WebEasyObfus
|
||||
|
||||
  
|
||||
|
||||
*EN | [中文](/README-CN.md)
|
||||
|
||||
<p align="center"><img src="./logo.jpg" width="256"></p>
|
||||
|
||||
勾勾、选选就完事,WebEasyObfus 混淆項目代码就这样简单。
|
||||
|
||||
> *「走過路過,別錯過,點顆星星,支持我!」*
|
||||
|
||||
> *(注:对插件的意见反馈请至 [Cocos 中文论坛](https://forum.cocos.org/t/topic/164539)。)*
|
||||
|
||||
|
||||
## 安装方法
|
||||
|
||||
1. 下载项目成 ZIP 文件。
|
||||
|
||||
2. 解压后将内容复制到 `${your_project_path}/extensions/web-easy-obfus`。
|
||||
|
||||
3. 打开终端
|
||||
|
||||
* 输入 `cd ${your_project_path}/extensions/web-zip-bundle`
|
||||
|
||||
* 安装扩展依赖包 `npm install`
|
||||
|
||||
* 构建扩展 `npm run build`
|
||||
|
||||
4. 到 Editor 菜单 Extension -> Extension Manager -> Installed 启用 `web-easy-obfus`。
|
||||
|
||||
<p align="center"><img src="doc/img/extension_manager.png" width="450"></p>
|
||||
|
||||
>(*注:安装方法也可参考官方文档 [【扩展 安装与分享】](https://docs.cocos.com/creator/3.8/manual/zh/editor/extension/install.html) 。*)
|
||||
|
||||
|
||||
## 如何使用
|
||||
|
||||
1. 到 Build Setting 新增 New Build Task 并选择平台 WebMobile/WebDesktop。到 Panel 中下拉找到 web-easy-obfus 选项。
|
||||
|
||||
* Enable:启用或关闭功能。
|
||||
|
||||
* Include All Bundle: 包含所有Bundle
|
||||
|
||||
* 启用后,所有 Bundle 内的 JS 档案将进行混淆,否则只有 `assets/main/bundle.js` 下的JS档案将进行混淆。
|
||||
|
||||
* Select Obfus Level:混淆分为五个等级,等级越高,混淆程度越彻底,但文件体积会增大,执行性能可能略受影响。
|
||||
|
||||
* 基础 (Minimal),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Disables converting code into a more complex control flow structure.
|
||||
"controlFlowFlattening": false,
|
||||
// Disables adding redundant dead code blocks.
|
||||
"deadCodeInjection": false,
|
||||
// Keeps global variable names unchanged.
|
||||
"renameGlobals": false,
|
||||
// Avoids extracting strings into a separate array for simplicity.
|
||||
"stringArray": false
|
||||
}
|
||||
```
|
||||
|
||||
* 标准 (Standard),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 75% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.75,
|
||||
// Avoids injecting unnecessary dead code.
|
||||
"deadCodeInjection": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Applies string array obfuscation to 75% of strings.
|
||||
"stringArrayThreshold": 0.75
|
||||
}
|
||||
```
|
||||
|
||||
* 增强 (Enhanced),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 90% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.9,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 40% of places.
|
||||
"deadCodeInjectionThreshold": 0.4,
|
||||
// Keeps global variable names unchanged for compatibility.
|
||||
"renameGlobals": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using Base64.
|
||||
"stringArrayEncoding": ["base64"],
|
||||
// Applies string array obfuscation to 90% of strings.
|
||||
"stringArrayThreshold": 0.9,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* 安全 (Secure),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 50% of places.
|
||||
"deadCodeInjectionThreshold": 0.5,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using RC4 encryption.
|
||||
"stringArrayEncoding": ["rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* 极致 (Ultimate),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in all possible places.
|
||||
"deadCodeInjectionThreshold": 1,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings using both Base64 and RC4 encryption.
|
||||
"stringArrayEncoding": ["base64", "rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true,
|
||||
// Converts characters to Unicode escape sequences for obfuscation.
|
||||
"unicodeEscapeSequence": true,
|
||||
// Replaces console output calls with empty functions to hide debugging messages.
|
||||
"disableConsoleOutput": true
|
||||
}
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
本插件天然支持 CI/CD,只需從 Build Panel 导出当前平台的构建选项配置为 json 文件,用于[命令行构建](https://docs.cocos.com/creator/3.8/manual/zh/editor/publish/publish-in-command-line.html)。
|
||||
|
||||
<p align="center"><img src="./doc/img/build_panel_export.png" width="400"></p>
|
||||
|
||||
|
||||
## 参考文献
|
||||
|
||||
* [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator)
|
||||
|
||||
* [Cocos Creator 官方的 UI 範例 GitHub:Cocos UI Example](https://github.com/cocos/cocos-example-ui)
|
||||
173
extensions/web-easy-obfus/README.en.md
Normal file
173
extensions/web-easy-obfus/README.en.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# CC3.WebEasyObfus
|
||||
|
||||
  
|
||||
|
||||
Just check and select, and you're done, Obfuscator code with WebEasyObfus is simple.
|
||||
|
||||
> *"Don’t just pass by, give it a try—hit a star and show your support!"*
|
||||
|
||||
> *Note:If you have any feedback on the plugin, please go to [Cocos 中文论坛](https://forum.cocos.org/t/topic/163849)*
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download ZIP package from github.
|
||||
|
||||
2. Decompress the file and copy the contents to `${your_project_path}/extensions/web-easy-obfus`.
|
||||
|
||||
3. Open the terminal
|
||||
|
||||
* `cd ${your_project_path}/extensions/web-zip-bundle`
|
||||
|
||||
* Enter `npm install`, install dependency packages.
|
||||
|
||||
* Enter `npm run build`, build the extension.
|
||||
|
||||
4. Go to the Editor menu `Extension -> Extension Manager -> Installed` to active the extension.
|
||||
|
||||
>*Note:You can also check out the official docs for installation instructions. [【扩展 安装与分享】](https://docs.cocos.com/creator/3.8/manual/zh/editor/extension/install.html).*
|
||||
|
||||
|
||||
## How to Use
|
||||
|
||||
1. Go to the Build Setting, add a Ner Build Task, and select the platform as WebModule or WebDesktop. In the Panel, scroll down to find the web-easy=obfus option.
|
||||
|
||||
* Enable:Turn on/off the extension.
|
||||
|
||||
* Include All Bundle
|
||||
|
||||
* Check this: all bundle JS files will be obfuscated; otherwhile, only `assets/main/bundle.js` will be obfuscated.
|
||||
|
||||
* Select Obfus Level:There are five levels of obfuscation. The higher the level, the more thorough the obfuscation, but the file size wil increase, and execution performance may be affected.
|
||||
|
||||
* Minimal,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Disables converting code into a more complex control flow structure.
|
||||
"controlFlowFlattening": false,
|
||||
// Disables adding redundant dead code blocks.
|
||||
"deadCodeInjection": false,
|
||||
// Keeps global variable names unchanged.
|
||||
"renameGlobals": false,
|
||||
// Avoids extracting strings into a separate array for simplicity.
|
||||
"stringArray": false
|
||||
}
|
||||
```
|
||||
|
||||
* Standard,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 75% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.75,
|
||||
// Avoids injecting unnecessary dead code.
|
||||
"deadCodeInjection": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Applies string array obfuscation to 75% of strings.
|
||||
"stringArrayThreshold": 0.75
|
||||
}
|
||||
```
|
||||
|
||||
* Enhanced,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 90% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.9,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 40% of places.
|
||||
"deadCodeInjectionThreshold": 0.4,
|
||||
// Keeps global variable names unchanged for compatibility.
|
||||
"renameGlobals": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using Base64.
|
||||
"stringArrayEncoding": ["base64"],
|
||||
// Applies string array obfuscation to 90% of strings.
|
||||
"stringArrayThreshold": 0.9,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* Secure,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 50% of places.
|
||||
"deadCodeInjectionThreshold": 0.5,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using RC4 encryption.
|
||||
"stringArrayEncoding": ["rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* Ultimate,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in all possible places.
|
||||
"deadCodeInjectionThreshold": 1,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings using both Base64 and RC4 encryption.
|
||||
"stringArrayEncoding": ["base64", "rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true,
|
||||
// Converts characters to Unicode escape sequences for obfuscation.
|
||||
"unicodeEscapeSequence": true,
|
||||
// Replaces console output calls with empty functions to hide debugging messages.
|
||||
"disableConsoleOutput": true
|
||||
}
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
This exrension natively supports CI/CD. Export the current platform's build config as a JSON file from the Build Panel for [命令行构建](https://docs.cocos.com/creator/3.8/manual/zh/editor/publish/publish-in-command-line.html)。
|
||||
|
||||
|
||||
## References
|
||||
|
||||
* [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator)
|
||||
|
||||
* [Cocos Creator 官方的 UI 範例 GitHub:Cocos UI Example](https://github.com/cocos/cocos-example-ui)
|
||||
183
extensions/web-easy-obfus/README.md
Normal file
183
extensions/web-easy-obfus/README.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# CC3.WebEasyObfus
|
||||
|
||||
  
|
||||
|
||||
*EN | [中文](/README-CN.md)
|
||||
|
||||
<p align="center"><img src="./logo.jpg" width="256"></p>
|
||||
|
||||
Just check and select, and you're done, Obfuscator code with WebEasyObfus is simple.
|
||||
|
||||
> *"Don’t just pass by, give it a try—hit a star and show your support!"*
|
||||
|
||||
|
||||
> *Note:If you have any feedback on the plugin, please go to [Cocos 中文论坛](https://forum.cocos.org/t/topic/164539)*
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download ZIP package from github.
|
||||
|
||||
2. Decompress the file and copy the contents to `${your_project_path}/extensions/web-easy-obfus`.
|
||||
|
||||
3. Open the terminal
|
||||
|
||||
* `cd ${your_project_path}/extensions/web-zip-bundle`
|
||||
|
||||
* Enter `npm install`, install dependency packages.
|
||||
|
||||
* Enter `npm run build`, build the extension.
|
||||
|
||||
4. Go to the Editor menu `Extension -> Extension Manager -> Installed` to active the extension.
|
||||
|
||||
<p align="center"><img src="doc/img/extension_manager.png" width="450"></p>
|
||||
|
||||
>*Note:You can also check out the official docs for installation instructions. [【扩展 安装与分享】](https://docs.cocos.com/creator/3.8/manual/zh/editor/extension/install.html).*
|
||||
|
||||
|
||||
## How to Use
|
||||
|
||||
1. Go to the Build Setting, add a Ner Build Task, and select the platform as WebModule or WebDesktop. In the Panel, scroll down to find the web-easy=obfus option.
|
||||
|
||||
* Enable:Turn on/off the extension.
|
||||
|
||||
* Include All Bundle
|
||||
|
||||
* Check this: all bundle JS files will be obfuscated; otherwhile, only `assets/main/bundle.js` will be obfuscated.
|
||||
|
||||
* Select Obfus Level:There are five levels of obfuscation. The higher the level, the more thorough the obfuscation, but the file size wil increase, and execution performance may be affected.
|
||||
|
||||
* Minimal,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Disables converting code into a more complex control flow structure.
|
||||
"controlFlowFlattening": false,
|
||||
// Disables adding redundant dead code blocks.
|
||||
"deadCodeInjection": false,
|
||||
// Keeps global variable names unchanged.
|
||||
"renameGlobals": false,
|
||||
// Avoids extracting strings into a separate array for simplicity.
|
||||
"stringArray": false
|
||||
}
|
||||
```
|
||||
|
||||
* Standard,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 75% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.75,
|
||||
// Avoids injecting unnecessary dead code.
|
||||
"deadCodeInjection": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Applies string array obfuscation to 75% of strings.
|
||||
"stringArrayThreshold": 0.75
|
||||
}
|
||||
```
|
||||
|
||||
* Enhanced,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 90% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.9,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 40% of places.
|
||||
"deadCodeInjectionThreshold": 0.4,
|
||||
// Keeps global variable names unchanged for compatibility.
|
||||
"renameGlobals": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using Base64.
|
||||
"stringArrayEncoding": ["base64"],
|
||||
// Applies string array obfuscation to 90% of strings.
|
||||
"stringArrayThreshold": 0.9,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* Secure,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 50% of places.
|
||||
"deadCodeInjectionThreshold": 0.5,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using RC4 encryption.
|
||||
"stringArrayEncoding": ["rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* Ultimate,The settings for javascript-obfuscator are as folloes:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in all possible places.
|
||||
"deadCodeInjectionThreshold": 1,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings using both Base64 and RC4 encryption.
|
||||
"stringArrayEncoding": ["base64", "rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true,
|
||||
// Converts characters to Unicode escape sequences for obfuscation.
|
||||
"unicodeEscapeSequence": true,
|
||||
// Replaces console output calls with empty functions to hide debugging messages.
|
||||
"disableConsoleOutput": true
|
||||
}
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
This exrension natively supports CI/CD. Export the current platform's build config as a JSON file from the Build Panel for [命令行构建](https://docs.cocos.com/creator/3.8/manual/zh/editor/publish/publish-in-command-line.html)。
|
||||
|
||||
|
||||
<p align="center"><img src="./doc/img/build_panel_export.png" width="400"></p>
|
||||
|
||||
|
||||
## References
|
||||
|
||||
* [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator)
|
||||
|
||||
* [Cocos Creator 官方的 UI 範例 GitHub:Cocos UI Example](https://github.com/cocos/cocos-example-ui)
|
||||
175
extensions/web-easy-obfus/README.zh.md
Normal file
175
extensions/web-easy-obfus/README.zh.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# CC3.WebEasyObfus
|
||||
|
||||
  
|
||||
|
||||
|
||||
虽然 CC 在建置时已经做了些混淆,但为了不让有心人一键带走项目,进一步的保护就成了钢需。与此同时,开发团队的 "老板" 会预期这是简单勾勾、选选就完成事...,这就是 WebEasyObfus 要做的事。
|
||||
|
||||
> *「走過路過,別錯過,點顆星星,支持我!」*
|
||||
|
||||
> *(注:对插件的意见反馈请至 [Cocos 中文论坛](https://forum.cocos.org/t/topic/163849)。)*
|
||||
|
||||
|
||||
## 安装方法
|
||||
|
||||
1. 下载项目成 ZIP 文件。
|
||||
|
||||
2. 解压后将内容复制到 `${your_project_path}/extensions/web-easy-obfus`。
|
||||
|
||||
3. 打开终端
|
||||
|
||||
* 输入 `cd ${your_project_path}/extensions/web-zip-bundle`
|
||||
|
||||
* 安装扩展依赖包 `npm install`
|
||||
|
||||
* 构建扩展 `npm run build`
|
||||
|
||||
4. 到 Editor 菜单 Extension -> Extension Manager -> Installed 启用 `web-easy-obfus`。
|
||||
|
||||
>(*注:安装方法也可参考官方文档 [【扩展 安装与分享】](https://docs.cocos.com/creator/3.8/manual/zh/editor/extension/install.html) 。*)
|
||||
|
||||
|
||||
## 如何使用
|
||||
|
||||
1. 到 Build Setting 新增 New Build Task 并选择平台 WebMobile/WebDesktop。到 Panel 中下拉找到 web-easy-obfus 选项。
|
||||
|
||||
* Enable:启用或关闭功能。
|
||||
|
||||
* Include All Bundle: 包含所有Bundle
|
||||
|
||||
* 启用后,所有 Bundle 内的 JS 档案将进行混淆,否则只有 `assets/main/bundle.js` 下的JS档案将进行混淆。
|
||||
|
||||
* Select Obfus Level:混淆分为五个等级,等级越高,混淆程度越彻底,但文件体积会增大,执行性能可能略受影响。
|
||||
|
||||
* 基础 (Minimal),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Disables converting code into a more complex control flow structure.
|
||||
"controlFlowFlattening": false,
|
||||
// Disables adding redundant dead code blocks.
|
||||
"deadCodeInjection": false,
|
||||
// Keeps global variable names unchanged.
|
||||
"renameGlobals": false,
|
||||
// Avoids extracting strings into a separate array for simplicity.
|
||||
"stringArray": false
|
||||
}
|
||||
```
|
||||
|
||||
* 标准 (Standard),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 75% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.75,
|
||||
// Avoids injecting unnecessary dead code.
|
||||
"deadCodeInjection": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Applies string array obfuscation to 75% of strings.
|
||||
"stringArrayThreshold": 0.75
|
||||
}
|
||||
```
|
||||
|
||||
* 增强 (Enhanced),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to 90% of the code.
|
||||
"controlFlowFlatteningThreshold": 0.9,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 40% of places.
|
||||
"deadCodeInjectionThreshold": 0.4,
|
||||
// Keeps global variable names unchanged for compatibility.
|
||||
"renameGlobals": false,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using Base64.
|
||||
"stringArrayEncoding": ["base64"],
|
||||
// Applies string array obfuscation to 90% of strings.
|
||||
"stringArrayThreshold": 0.9,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* 安全 (Secure),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in 50% of places.
|
||||
"deadCodeInjectionThreshold": 0.5,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings in the array using RC4 encryption.
|
||||
"stringArrayEncoding": ["rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true
|
||||
}
|
||||
```
|
||||
|
||||
* 极致 (Ultimate),對 javascript-obfuscator 設定分別為:
|
||||
|
||||
```javascript
|
||||
{
|
||||
// Minifies the output code to reduce file size.
|
||||
"compact": true,
|
||||
// Enables control flow flattening for added complexity.
|
||||
"controlFlowFlattening": true,
|
||||
// Applies control flow flattening to all code.
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
// Adds dead code to make reverse engineering harder.
|
||||
"deadCodeInjection": true,
|
||||
// Inserts dead code in all possible places.
|
||||
"deadCodeInjectionThreshold": 1,
|
||||
// Renames global variables for better obfuscation.
|
||||
"renameGlobals": true,
|
||||
// Moves strings into a separate array for obfuscation.
|
||||
"stringArray": true,
|
||||
// Encodes strings using both Base64 and RC4 encryption.
|
||||
"stringArrayEncoding": ["base64", "rc4"],
|
||||
// Applies string array obfuscation to all strings.
|
||||
"stringArrayThreshold": 1,
|
||||
// Obfuscates object keys for added security.
|
||||
"transformObjectKeys": true,
|
||||
// Converts characters to Unicode escape sequences for obfuscation.
|
||||
"unicodeEscapeSequence": true,
|
||||
// Replaces console output calls with empty functions to hide debugging messages.
|
||||
"disableConsoleOutput": true
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## CI/CD
|
||||
|
||||
本插件天然支持 CI/CD,只需從 Build Panel 导出当前平台的构建选项配置为 json 文件,用于[命令行构建](https://docs.cocos.com/creator/3.8/manual/zh/editor/publish/publish-in-command-line.html)。
|
||||
|
||||
|
||||
## 参考文献
|
||||
|
||||
* [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator)
|
||||
|
||||
* [Cocos Creator 官方的 UI 範例 GitHub:Cocos UI Example](https://github.com/cocos/cocos-example-ui)
|
||||
52
extensions/web-easy-obfus/dist/asset-handlers.js
vendored
Normal file
52
extensions/web-easy-obfus/dist/asset-handlers.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.compressTextures = void 0;
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const compressTextures = (tasks) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
console.debug(`Execute compress task ${tasks}`);
|
||||
for (let i = 0; i < tasks.length; i++) {
|
||||
const task = tasks[i];
|
||||
if (task.format !== 'jpg') {
|
||||
continue;
|
||||
}
|
||||
// task.dest should change suffix before compress
|
||||
task.dest = task.dest.replace('.png', '.jpg');
|
||||
yield pngToJPG(task.src, task.dest, task.quality);
|
||||
// The compress task have done needs to be removed from the original tasks
|
||||
tasks.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
});
|
||||
exports.compressTextures = compressTextures;
|
||||
function pngToJPG(src, dest, quality) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const img = yield getImage(src);
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
const imageData = canvas.toDataURL('image/jpeg', quality / 100);
|
||||
yield (0, fs_extra_1.outputFile)(dest, imageData);
|
||||
console.debug('pngToJPG', dest);
|
||||
});
|
||||
}
|
||||
function getImage(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = function () {
|
||||
resolve(img);
|
||||
};
|
||||
img.onerror = function (err) {
|
||||
reject(err);
|
||||
};
|
||||
img.src = path.replace('#', '%23');
|
||||
});
|
||||
}
|
||||
68
extensions/web-easy-obfus/dist/builder.js
vendored
Normal file
68
extensions/web-easy-obfus/dist/builder.js
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.assetHandlers = exports.configs = exports.unload = exports.load = void 0;
|
||||
const global_1 = require("./global");
|
||||
const load = function () {
|
||||
console.debug(`${global_1.PACKAGE_NAME} load`);
|
||||
};
|
||||
exports.load = load;
|
||||
const unload = function () {
|
||||
console.debug(`${global_1.PACKAGE_NAME} unload`);
|
||||
};
|
||||
exports.unload = unload;
|
||||
const webEasyObfusConfig = {
|
||||
hooks: './hooks',
|
||||
options: {
|
||||
enable: {
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.enable`,
|
||||
description: `i18n:${global_1.PACKAGE_NAME}.options.enable`,
|
||||
default: true,
|
||||
render: {
|
||||
ui: 'ui-checkbox',
|
||||
}
|
||||
},
|
||||
includeAllBundle: {
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.includeAllBundle`,
|
||||
description: `i18n:${global_1.PACKAGE_NAME}.options.includeAllBundle`,
|
||||
default: true,
|
||||
render: {
|
||||
ui: 'ui-checkbox',
|
||||
}
|
||||
},
|
||||
selectObfusLevel: {
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevel`,
|
||||
description: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevelDescription`,
|
||||
default: 'option2',
|
||||
render: {
|
||||
ui: 'ui-select',
|
||||
items: [
|
||||
{
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevelOptions.option0`,
|
||||
value: 'option0',
|
||||
},
|
||||
{
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevelOptions.option1`,
|
||||
value: 'option1',
|
||||
},
|
||||
{
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevelOptions.option2`,
|
||||
value: 'option2',
|
||||
},
|
||||
{
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevelOptions.option3`,
|
||||
value: 'option3',
|
||||
},
|
||||
{
|
||||
label: `i18n:${global_1.PACKAGE_NAME}.options.selectObfusLevelOptions.option4`,
|
||||
value: 'option4',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
exports.configs = {
|
||||
'web-mobile': webEasyObfusConfig,
|
||||
'web-desktop': webEasyObfusConfig
|
||||
};
|
||||
exports.assetHandlers = './asset-handlers';
|
||||
4
extensions/web-easy-obfus/dist/global.js
vendored
Normal file
4
extensions/web-easy-obfus/dist/global.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PACKAGE_NAME = void 0;
|
||||
exports.PACKAGE_NAME = 'web-easy-obfus';
|
||||
190
extensions/web-easy-obfus/dist/hooks.js
vendored
Normal file
190
extensions/web-easy-obfus/dist/hooks.js
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.onAfterMake = exports.onBeforeMake = exports.onError = exports.unload = exports.onAfterBuild = exports.onAfterCompressSettings = exports.onBeforeCompressSettings = exports.onBeforeBuild = exports.load = exports.throwError = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const global_1 = require("./global");
|
||||
const fs = __importStar(require("fs-extra"));
|
||||
const javascript_obfuscator_1 = __importDefault(require("javascript-obfuscator"));
|
||||
exports.throwError = true;
|
||||
const load = function () {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.load = load;
|
||||
const onBeforeBuild = function (options, result) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.onBeforeBuild = onBeforeBuild;
|
||||
const onBeforeCompressSettings = function (options, result) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.onBeforeCompressSettings = onBeforeCompressSettings;
|
||||
const onAfterCompressSettings = function (options, result) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.onAfterCompressSettings = onAfterCompressSettings;
|
||||
const onAfterBuild = function (options, result) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const pkgOptions = options.packages[global_1.PACKAGE_NAME];
|
||||
if (pkgOptions.enable) {
|
||||
let obfuscationOptions = {};
|
||||
if (pkgOptions.selectObfusLevel === 'option1') {
|
||||
obfuscationOptions = {
|
||||
"compact": true,
|
||||
"controlFlowFlattening": true,
|
||||
"controlFlowFlatteningThreshold": 0.75,
|
||||
"deadCodeInjection": false,
|
||||
"stringArray": true,
|
||||
"stringArrayThreshold": 0.75 // Applies string array obfuscation to 75% of strings.
|
||||
};
|
||||
}
|
||||
else if (pkgOptions.selectObfusLevel === 'option2') {
|
||||
obfuscationOptions = {
|
||||
"compact": true,
|
||||
"controlFlowFlattening": true,
|
||||
"controlFlowFlatteningThreshold": 0.9,
|
||||
"deadCodeInjection": true,
|
||||
"deadCodeInjectionThreshold": 0.4,
|
||||
"renameGlobals": false,
|
||||
"stringArray": true,
|
||||
"stringArrayEncoding": ["base64"],
|
||||
"stringArrayThreshold": 0.9,
|
||||
"transformObjectKeys": true // Obfuscates object keys for added security.
|
||||
};
|
||||
}
|
||||
else if (pkgOptions.selectObfusLevel === 'option3') {
|
||||
obfuscationOptions = {
|
||||
"compact": true,
|
||||
"controlFlowFlattening": true,
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
"deadCodeInjection": true,
|
||||
"deadCodeInjectionThreshold": 0.5,
|
||||
"renameGlobals": true,
|
||||
"stringArray": true,
|
||||
"stringArrayEncoding": ["rc4"],
|
||||
"stringArrayThreshold": 1,
|
||||
"transformObjectKeys": true // Obfuscates object keys for added security.
|
||||
};
|
||||
}
|
||||
else if (pkgOptions.selectObfusLevel === 'option4') {
|
||||
obfuscationOptions = {
|
||||
"compact": true,
|
||||
"controlFlowFlattening": true,
|
||||
"controlFlowFlatteningThreshold": 1,
|
||||
"deadCodeInjection": true,
|
||||
"deadCodeInjectionThreshold": 1,
|
||||
"renameGlobals": true,
|
||||
"stringArray": true,
|
||||
"stringArrayEncoding": ["base64", "rc4"],
|
||||
"stringArrayThreshold": 1,
|
||||
"transformObjectKeys": true,
|
||||
"unicodeEscapeSequence": true,
|
||||
"disableConsoleOutput": true // Replaces console output calls with empty functions to hide debugging messages.
|
||||
};
|
||||
}
|
||||
else {
|
||||
obfuscationOptions = {
|
||||
"compact": true,
|
||||
"controlFlowFlattening": false,
|
||||
"deadCodeInjection": false,
|
||||
"renameGlobals": false,
|
||||
"stringArray": false // Avoids extracting strings into a separate array for simplicity.
|
||||
};
|
||||
}
|
||||
const BUILD_DEST_DIR = result.dest;
|
||||
if (pkgOptions.includeAllBundle) {
|
||||
findAndObfusJSFile(path_1.default.join(BUILD_DEST_DIR, 'assets'), obfuscationOptions);
|
||||
}
|
||||
else {
|
||||
findAndObfusJSFile(path_1.default.join(BUILD_DEST_DIR, 'assets', 'main'), obfuscationOptions);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.onAfterBuild = onAfterBuild;
|
||||
const unload = function () {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.unload = unload;
|
||||
const onError = function (options, result) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.onError = onError;
|
||||
const onBeforeMake = function (root, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.onBeforeMake = onBeforeMake;
|
||||
const onAfterMake = function (root, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
});
|
||||
};
|
||||
exports.onAfterMake = onAfterMake;
|
||||
function findAndObfusJSFile(dir, options) {
|
||||
const items = fs.readdirSync(dir);
|
||||
for (const item of items) {
|
||||
const fullPath = path_1.default.join(dir, item);
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
findAndObfusJSFile(fullPath, options);
|
||||
}
|
||||
else if (item.endsWith('.js')) {
|
||||
console.log('Found js-file:', fullPath);
|
||||
fs.readFile(fullPath, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
const obfuscatedData = javascript_obfuscator_1.default.obfuscate(data, options).getObfuscatedCode();
|
||||
fs.writeFile(fullPath, obfuscatedData, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
console.log('Obfuscated:', fullPath);
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
78
extensions/web-easy-obfus/dist/panel.js
vendored
Normal file
78
extensions/web-easy-obfus/dist/panel.js
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.close = exports.ready = exports.update = exports.$ = exports.template = exports.style = void 0;
|
||||
const global_1 = require("./global");
|
||||
let panel;
|
||||
exports.style = ``;
|
||||
exports.template = `
|
||||
<div class="build-plugin">
|
||||
<ui-prop>
|
||||
<ui-label slot="label" value="Hide Link"></ui-label>
|
||||
<ui-checkbox slot="content"></ui-checkbox>
|
||||
</ui-prop>
|
||||
<ui-prop id="link">
|
||||
<ui-label slot="label" value="Docs"></ui-label>
|
||||
<ui-link slot="content" value=${Editor.Utils.Url.getDocUrl('editor/publish/custom-build-plugin.html')}></ui-link>
|
||||
</ui-prop>
|
||||
</div>
|
||||
`;
|
||||
exports.$ = {
|
||||
root: '.build-plugin',
|
||||
hideLink: 'ui-checkbox',
|
||||
link: '#link',
|
||||
};
|
||||
/**
|
||||
* all change of options dispatched will enter here
|
||||
* @param options
|
||||
* @param key
|
||||
* @returns
|
||||
*/
|
||||
function update(options, key) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (key) {
|
||||
return;
|
||||
}
|
||||
// when import build options, key will bey ''
|
||||
init();
|
||||
});
|
||||
}
|
||||
exports.update = update;
|
||||
function ready(options) {
|
||||
// @ts-ignore
|
||||
panel = this;
|
||||
panel.options = options;
|
||||
init();
|
||||
}
|
||||
exports.ready = ready;
|
||||
function close() {
|
||||
panel.$.hideLink.removeEventListener('change', onHideLinkChange);
|
||||
}
|
||||
exports.close = close;
|
||||
function init() {
|
||||
panel.$.hideLink.value = panel.options.hideLink;
|
||||
updateLink();
|
||||
panel.$.hideLink.addEventListener('change', onHideLinkChange);
|
||||
}
|
||||
function onHideLinkChange(event) {
|
||||
panel.options.hideLink = event.target.value;
|
||||
// Note: dispatch the change to build panel
|
||||
panel.dispatch('update', `packages.${global_1.PACKAGE_NAME}.hideLink`, panel.options.hideLink);
|
||||
updateLink();
|
||||
}
|
||||
function updateLink() {
|
||||
if (panel.options.hideLink) {
|
||||
panel.$.link.style.display = 'none';
|
||||
}
|
||||
else {
|
||||
panel.$.link.style.display = 'block';
|
||||
}
|
||||
}
|
||||
BIN
extensions/web-easy-obfus/doc/img/build_panel_export.png
Normal file
BIN
extensions/web-easy-obfus/doc/img/build_panel_export.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
extensions/web-easy-obfus/doc/img/extension_manager.png
Normal file
BIN
extensions/web-easy-obfus/doc/img/extension_manager.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
extensions/web-easy-obfus/doc/img/store_banner.png
Normal file
BIN
extensions/web-easy-obfus/doc/img/store_banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
BIN
extensions/web-easy-obfus/doc/img/store_console_log.png
Normal file
BIN
extensions/web-easy-obfus/doc/img/store_console_log.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 906 KiB |
17
extensions/web-easy-obfus/i18n/en.js
Normal file
17
extensions/web-easy-obfus/i18n/en.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
title: "Web Easy Obfus",
|
||||
description: "Easily obfuscate the project codebase!",
|
||||
options: {
|
||||
enable: "Enable",
|
||||
includeAllBundle: "Include All Bundle",
|
||||
selectObfusLevel: "Select Obfus Level",
|
||||
selectObfusLevelDescription: "",
|
||||
selectObfusLevelOptions: {
|
||||
option0: "Minimal",
|
||||
option1: "Standard",
|
||||
option2: "Enhanced",
|
||||
option3: "Secure",
|
||||
option4: "Ultimate",
|
||||
}
|
||||
},
|
||||
};
|
||||
17
extensions/web-easy-obfus/i18n/zh.js
Normal file
17
extensions/web-easy-obfus/i18n/zh.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
title: "Web Easy Obfus",
|
||||
description: "混淆項目代码就这样简单!",
|
||||
options: {
|
||||
enable: "启用",
|
||||
includeAllBundle: "包含所有Bundle",
|
||||
selectObfusLevel: "选择混淆等级",
|
||||
selectObfusLevelDescription: "",
|
||||
selectObfusLevelOptions: {
|
||||
option0: "基础",
|
||||
option1: "标准",
|
||||
option2: "增强",
|
||||
option3: "安全",
|
||||
option4: "极致",
|
||||
}
|
||||
},
|
||||
};
|
||||
BIN
extensions/web-easy-obfus/logo.jpg
Normal file
BIN
extensions/web-easy-obfus/logo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
28
extensions/web-easy-obfus/package.json
Normal file
28
extensions/web-easy-obfus/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "./@types/schema/package/index.json",
|
||||
"package_version": 2,
|
||||
"name": "web-easy-obfus",
|
||||
"version": "1.0.4",
|
||||
"author": "ericlin09@gmail.com",
|
||||
"editor": ">=3.7.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"preinstall": "node ./scripts/preinstall.js",
|
||||
"build": "tsc"
|
||||
},
|
||||
"title": "i18n:web-easy-obfus.title",
|
||||
"description": "i18n:web-easy-obfus.description",
|
||||
"contributions": {
|
||||
"builder": "./dist/builder.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.0.0",
|
||||
"typescript": "^4.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cocos/creator-types": "^3.8.3",
|
||||
"@types/fs-extra": "^5.0.4",
|
||||
"@types/node": "^18.17.1",
|
||||
"javascript-obfuscator": "^4.1.1"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user