mirror of
https://github.com/SynologyOpenSource/pkgscripts-ng.git
synced 2025-07-29 12:49:21 +00:00
feat: provide toolkit tools
This commit is contained in:
248
tool/GenerateJSDepend.php
Executable file
248
tool/GenerateJSDepend.php
Executable file
@ -0,0 +1,248 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
/* Decode json file to php object */
|
||||
function DecodeJsonFile($file)
|
||||
{
|
||||
$content = @file_get_contents($file);
|
||||
if (FALSE === $content) {
|
||||
echo $file . ": Read error.\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$result = json_decode($content, true);
|
||||
if (!is_array($result)) {
|
||||
echo $file . ": Json parse failed.\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/* Get all dependency from one js file. e.g. */
|
||||
/*
|
||||
fn = "js/abc.js": {
|
||||
"SYNO.AAA": {
|
||||
"depend" : [
|
||||
"SYNO.Parent"
|
||||
]
|
||||
},
|
||||
"SYNO.BBB" : {
|
||||
"depend" : [
|
||||
"SYNO.Father"
|
||||
]
|
||||
}
|
||||
}
|
||||
input -->
|
||||
fn["js/abc.js"]
|
||||
output -->
|
||||
["SYNO.Parent", "SYNO.Father"]
|
||||
*/
|
||||
function MergeDependency($fnList)
|
||||
{
|
||||
$depend = array();
|
||||
foreach ($fnList as $fnName => $fnConfig) {
|
||||
if (is_array($fnConfig['depend'])) {
|
||||
$depend = array_merge($depend, $fnConfig['depend']);
|
||||
}
|
||||
}
|
||||
return array_unique($depend);
|
||||
}
|
||||
|
||||
function FindSrcFileForFn($fnName)
|
||||
{
|
||||
global $ConfigDebug;
|
||||
foreach ($ConfigDebug as $srcFile => $fileConfig) {
|
||||
if (isSet($fileConfig[$fnName])) {
|
||||
return $srcFile;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
function PostTraversalDependency($file, $depend, &$queue)
|
||||
{
|
||||
if (FALSE !== array_search($file, $queue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_array($depend[$file])) {
|
||||
foreach ($depend[$file] as $depFn) {
|
||||
$depFile = FindSrcFileForFn($depFn);
|
||||
if (FALSE === $depFile || $file === $depFile) {
|
||||
continue;
|
||||
}
|
||||
PostTraversalDependency($depFile, $depend, $queue);
|
||||
}
|
||||
}
|
||||
|
||||
if (isSet($depend[$file])) {
|
||||
$queue[] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
function Usage()
|
||||
{
|
||||
global $argv;
|
||||
|
||||
echo <<<EOD
|
||||
Usage: {$argv[0]} module_dir
|
||||
|
||||
EOD;
|
||||
}
|
||||
|
||||
/* ----------------------- */
|
||||
/* ----------------------- */
|
||||
/* main access entry point */
|
||||
/* ----------------------- */
|
||||
/* ----------------------- */
|
||||
|
||||
|
||||
if (!is_dir($argv[1])) {
|
||||
echo "Error: {$argv[1]} is not a directory.\n";
|
||||
Usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$CWD = getcwd();
|
||||
chdir($argv[1]);
|
||||
|
||||
$InputFiles = array(
|
||||
'debug' => 'config.debug',
|
||||
'define' => 'config.define',
|
||||
'auto_debug' => 'auto_config.debug'
|
||||
);
|
||||
|
||||
$OutputFiles = array(
|
||||
'config' => 'config',
|
||||
'depend' => 'config.depends'
|
||||
);
|
||||
|
||||
$JSInfo = array();
|
||||
$Config = array();
|
||||
|
||||
$define_path = $InputFiles['define'];
|
||||
|
||||
if (file_exists($define_path)) {
|
||||
$ConfigDefine = DecodeJsonFile($define_path);
|
||||
} else {
|
||||
echo "Skip parsing: config.define not exist in config.depends\n";
|
||||
$ConfigDefine = array();
|
||||
}
|
||||
|
||||
/* try to read from auto config path */
|
||||
if (file_exists($InputFiles['debug'])) {
|
||||
$ConfigDebug = DecodeJsonFile($InputFiles['debug']);
|
||||
} else if (file_exists($InputFiles['auto_debug'])) {
|
||||
$ConfigDebug = DecodeJsonFile($InputFiles['auto_debug']);
|
||||
} else {
|
||||
echo "Skip parsing: config.debug and auto_config.debug not exist\n";
|
||||
$ConfigDebug = array();
|
||||
}
|
||||
|
||||
if (!is_array($ConfigDebug) || !is_array($ConfigDefine)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* merge config, parse fn and dependency info */
|
||||
foreach ($ConfigDefine as $dstFile => $srcFiles) {
|
||||
$Config[$dstFile] = array();
|
||||
$JSInfo[$dstFile] = array('jsFiles' => array(), 'fnList' => array(), 'params' => null);
|
||||
|
||||
$srcJsFiles = array();
|
||||
if (isSet($srcFiles['JSfiles'])) { /* with parameters */
|
||||
$srcJsFiles = $srcFiles['JSfiles'];
|
||||
} else {
|
||||
$srcJsFiles = $srcFiles;
|
||||
}
|
||||
|
||||
foreach ($srcJsFiles as $files) {
|
||||
foreach(glob($files) as $file) {
|
||||
if (!isSet($ConfigDebug[$file])) {
|
||||
$ConfigDebug[$file] = array();
|
||||
}
|
||||
$Config[$dstFile] = array_merge($Config[$dstFile], $ConfigDebug[$file]);
|
||||
$JSInfo[$dstFile]['jsFiles'][$file] = MergeDependency($ConfigDebug[$file]);
|
||||
$JSInfo[$dstFile]['fnList'] = array_merge($JSInfo[$dstFile]['fnList'], array_keys($ConfigDebug[$file]));
|
||||
if (isSet($srcFiles['params'])) {
|
||||
$JSInfo[$dstFile]['params'] = $srcFiles['params'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* copy virtual config */
|
||||
if (isSet($ConfigDebug['.url'])) {
|
||||
$Config['.url'] = $ConfigDebug['.url'];
|
||||
}
|
||||
|
||||
/* Resolve JS compress dependency */
|
||||
foreach ($JSInfo as $dstFile => &$dstConfig) {
|
||||
$queue = array();
|
||||
foreach (array_keys($dstConfig['jsFiles']) as $file) {
|
||||
PostTraversalDependency($file, $dstConfig['jsFiles'], $queue);
|
||||
}
|
||||
|
||||
if(isSet($JSInfo[$dstFile]['params'])) {
|
||||
$JSInfo[$dstFile] = array('files' => $queue, 'params' => $JSInfo[$dstFile]['params']);
|
||||
} else {
|
||||
$JSInfo[$dstFile] = $queue;
|
||||
}
|
||||
}
|
||||
|
||||
function getFlattenDepList($dstConfig, $comp) {
|
||||
$dependList = array();
|
||||
if (array_key_exists('depend', $comp)) {
|
||||
foreach ($comp['depend'] as $item) {
|
||||
if (array_key_exists($item, $dstConfig)) {
|
||||
// internal depend => get its depend list
|
||||
$flatDep = getFlattenDepList($dstConfig, $dstConfig[$item]);
|
||||
$dependList = array_merge($flatDep, $dependList);
|
||||
$dependList = array_values(array_unique($dependList));
|
||||
} else {
|
||||
$dependList[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dependList;
|
||||
}
|
||||
|
||||
/* flatten dependency */
|
||||
if ($argv[2] != "") {
|
||||
echo "Flatten Dependency...\n";
|
||||
foreach ($Config as $dstFile => &$dstConfig) {
|
||||
foreach ($dstConfig as $comp => &$compConfig) {
|
||||
if (array_key_exists('depend', $compConfig)) {
|
||||
$dependList = getFlattenDepList($dstConfig, $compConfig);
|
||||
|
||||
if (count($dependList) === 0) {
|
||||
unset($compConfig['depend']);
|
||||
} else {
|
||||
$compConfig['depend'] = $dependList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "Flatten Dependency Done...\n";
|
||||
}
|
||||
|
||||
function GenerateConfig()
|
||||
{
|
||||
global $Config;
|
||||
|
||||
$result = json_encode($Config);
|
||||
if( (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) ||
|
||||
(ini_get('magic_quotes_sybase') && (strtolower(ini_get('magic_quotes_sybase')) != "off" )) ) {
|
||||
$result = stripslashes($result);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
file_put_contents($OutputFiles['depend'], json_encode($JSInfo));
|
||||
|
||||
if (count($Config) > 0) {
|
||||
file_put_contents($OutputFiles['config'], GenerateConfig());
|
||||
}
|
||||
|
||||
exit(0);
|
||||
?>
|
||||
|
340
tool/GenerateModuleFiles.php
Executable file
340
tool/GenerateModuleFiles.php
Executable file
@ -0,0 +1,340 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
/* Decode json file to php object */
|
||||
function DecodeJsonFile($file)
|
||||
{
|
||||
$content = @file_get_contents($file);
|
||||
if (FALSE === $content) {
|
||||
echo $file . ": Read error.\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$result = json_decode($content, true);
|
||||
if (!is_array($result)) {
|
||||
echo $file . ": Json parse failed.\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function HasExternalDepend(&$dstConfig, &$comp)
|
||||
{
|
||||
if (array_key_exists($comp, $dstConfig)) {
|
||||
$compConfig = $dstConfig[$comp];
|
||||
|
||||
if (array_key_exists('depend', $compConfig)) {
|
||||
foreach ($compConfig['depend'] as $item) {
|
||||
if (HasExternalDepend($dstConfig, $item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function GenerateCompassConfig()
|
||||
{
|
||||
|
||||
$compassConfig = <<<EOD
|
||||
# Get the directory that this configuration file exists in
|
||||
dir = File.dirname(__FILE__)
|
||||
|
||||
load File.join(dir, '../../../resources/scss/src')
|
||||
|
||||
ext_dir = "/usr/syno/synoman/scripts/ext-3.4/ux/scss/src"
|
||||
# compatibility with 6.0
|
||||
ext_dir = "/source/synojslib/ext-3.4/ux/scss/src" unless File.directory?(ext_dir)
|
||||
add_import_path ext_dir
|
||||
|
||||
syno_ext_dir = "/usr/syno/synoman/synoSDSjslib/scss"
|
||||
# compatibility with 6.0
|
||||
syno_ext_dir="/source/synoSDSjslib/scss" unless File.directory?(syno_ext_dir)
|
||||
add_import_path syno_ext_dir
|
||||
|
||||
# Compass configurations
|
||||
sass_path = dir
|
||||
css_path = File.join(dir, "..")
|
||||
images_path = "/usr/syno/synoman/scripts/ext-3.4/ux"
|
||||
# compatibility with 6.0
|
||||
images_path = "/source/synojslib/ext-3.4/ux" unless File.directory?(images_path)
|
||||
environment = :production
|
||||
output_style = :compressed
|
||||
sprite_load_path = File.join(dir, "../images")
|
||||
http_path = "./"
|
||||
generated_images_dir = "../images"
|
||||
|
||||
module Sass::Script::Functions
|
||||
|
||||
def real_path(image_file)
|
||||
if Compass.configuration.images_path
|
||||
File.join(Compass.configuration.images_path, image_file)
|
||||
else
|
||||
File.join(Compass.configuration.project_path, image_file)
|
||||
end
|
||||
end
|
||||
|
||||
def md5(filename)
|
||||
if filename && File.exist?(filename)
|
||||
digest = Digest::MD5.new()
|
||||
digest << File.read(filename)
|
||||
unquoted_string(digest.hexdigest)
|
||||
else
|
||||
Compass::Util.compass_warn(
|
||||
"File not found: #{filename}, cannot do prevent cache signature."
|
||||
)
|
||||
unquoted_string('no_image_found')
|
||||
end
|
||||
end
|
||||
def syno_md5(image_file)
|
||||
image_file = image_file.respond_to?(:value) ? image_file.value : image_file
|
||||
if File.exists?(image_file)
|
||||
md5(image_file)
|
||||
else
|
||||
md5(real_path(image_file))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
EOD;
|
||||
|
||||
return $compassConfig;
|
||||
}
|
||||
|
||||
function GenerateMakefile($compress)
|
||||
{
|
||||
global $ConfigDefine;
|
||||
|
||||
if (true === $compress) {
|
||||
echo "Compress to Gzip: [{$compress}]\n";
|
||||
}
|
||||
|
||||
$JSTarget = array();
|
||||
foreach ($ConfigDefine as $dstFile => $srcFiles) {
|
||||
array_push($JSTarget, $dstFile);
|
||||
}
|
||||
|
||||
$CompressedFiles = implode(' ', array_keys($ConfigDefine));
|
||||
$Makefile = <<<EOD
|
||||
include /env.mak
|
||||
|
||||
JS_COMPILER=/usr/local/tool/shrinksafe.php $(JS_COMPILER_ARGV)
|
||||
SASS_COMPILER=/usr/bin/compass $(SASS_COMPILER_ARGV)
|
||||
CONFIG_PARSER=/usr/syno/bin/GenerateModuleFiles.php
|
||||
JS_DEPENDER=/usr/syno/bin/GenerateJSDepend.php
|
||||
AUTO_CONFIG_TOOL=/usr/local/tool/parse_requires.py
|
||||
|
||||
CONFIGFILE=config
|
||||
STYLEFILE=style.css
|
||||
SCSS_FILE=scss/style.scss
|
||||
SASS_CACHE=scss/.sass-cache
|
||||
COMPASS_CONFIG=scss/config.rb
|
||||
JSFILES={$CompressedFiles}
|
||||
JS_INPUT=$(shell /usr/bin/find $(JS_DIR) -name "*.js")
|
||||
|
||||
TARGET_JSCompress=CSSCompress config.depends \$(JSFILES)
|
||||
TARGET_install=install_CSSCompress
|
||||
TARGET_clean=clean_CSSCompress
|
||||
|
||||
ifneq ("$(wildcard app.config)","")
|
||||
DEBUGFILE:=auto_config.debug
|
||||
else
|
||||
DEBUGFILE:=config.debug
|
||||
endif
|
||||
|
||||
USE_COMPRESS_GZIP={$compress}
|
||||
ifeq ("\$(SYNOCOMPRESS)", "")
|
||||
USE_COMPRESS_GZIP=no
|
||||
endif
|
||||
|
||||
ifeq ("\$(USE_COMPRESS_GZIP)", "yes")
|
||||
STYLEFILE_GZIP:=$(addsuffix .gz, $(STYLEFILE))
|
||||
JSFILES_GZIP:=$(addsuffix .gz, $(JSFILES))
|
||||
TARGET_install+=install_GzipCompress
|
||||
TARGET_clean+=clean_GzipCompress
|
||||
endif
|
||||
|
||||
JSCompress: $(TARGET_JSCompress)
|
||||
JSCompress_AutoConfig: $(TARGET_JSCompress)
|
||||
|
||||
CSSCompress:
|
||||
if [ -f \$(SCSS_FILE) ]; then \$(SASS_COMPILER) compile scss; fi
|
||||
|
||||
clean_JSCompress: $(TARGET_clean)
|
||||
if [ -n "\$(JSFILES)" ]; then rm -f \$(JSFILES); fi
|
||||
if [ -n "auto_config.debug" ]; then rm -f auto_config.debug; fi
|
||||
if [ -n "config.depends" ]; then rm -f config.depends; fi
|
||||
if [ -n "config" ]; then rm -f config; fi
|
||||
|
||||
clean_CSSCompress:
|
||||
if [ -f \$(SCSS_FILE) ]; then rm -f \$(STYLEFILE); fi
|
||||
if [ -d \$(SASS_CACHE) ]; then rm -rf \$(SASS_CACHE); fi
|
||||
|
||||
clean_GzipCompress:
|
||||
if [ -n "\$(JSFILES_GZIP)" ]; then rm -f \$(JSFILES_GZIP); fi
|
||||
if [ -f "\$(STYLEFILE_GZIP)" ]; then rm -f \$(STYLEFILE_GZIP); fi
|
||||
|
||||
install_JSCompress: $(TARGET_install)
|
||||
[ -d \$(INSTALLDIR) ] || install -d \$(INSTALLDIR)
|
||||
if [ -f \$(CONFIGFILE) ]; then cp \$(CONFIGFILE) \$(INSTALLDIR); fi
|
||||
if [ -n "\$(JSFILES)" ]; then cp \$(JSFILES) \$(INSTALLDIR); fi
|
||||
if [ -f \$(STYLEFILE) ]; then cp -f \$(STYLEFILE) \$(INSTALLDIR); fi
|
||||
|
||||
install_CSSCompress:
|
||||
# already install style.css install_JSCompress
|
||||
|
||||
install_GzipCompress: \$(JSFILES) CSSCompress
|
||||
if [ -f "\$(STYLEFILE)" ] && [ -s "\$(STYLEFILE)" ]; then \$(SYNOCOMPRESS) \$(STYLEFILE); fi
|
||||
if [ -n "\$(JSFILES)" ]; then \$(SYNOCOMPRESS) \$(JSFILES); fi
|
||||
[ -d "\$(INSTALLDIR)" ] || install -d \$(INSTALLDIR)
|
||||
if [ -f "\$(STYLEFILE_GZIP)" ]; then cp -f \$(STYLEFILE_GZIP) \$(INSTALLDIR); fi
|
||||
for JSFILE in $(JSFILES_GZIP); do \
|
||||
if [ -f "\$\$JSFILE" ]; then cp -f \$\$JSFILE $(INSTALLDIR); fi \
|
||||
done
|
||||
|
||||
auto_config.debug: app.config config.define \$(JS_INPUT)
|
||||
\$(AUTO_CONFIG_TOOL) --makegoal=\$(MAKECMDGOALS) \$(JS_DIR) \$(JS_NAMESPACE)
|
||||
|
||||
config.depends: $(DEBUGFILE) config.define
|
||||
\$(JS_DEPENDER) \$(shell pwd)
|
||||
|
||||
|
||||
EOD;
|
||||
|
||||
foreach ($ConfigDefine as $dstFile => $dstConfig) {
|
||||
if(isSet($ConfigDefine[$dstFile]['JSfiles']) && isSet($ConfigDefine[$dstFile]['params'])) {
|
||||
$Makefile .= $dstFile . ': config.depends ' . implode(' ', $ConfigDefine[$dstFile]['JSfiles']) . "\n";
|
||||
$Makefile .= "\t$(JS_COMPILER) " . $ConfigDefine[$dstFile]['params'] . " -d ". $dstFile ." \"\$(shell pwd)/config.depends\"\n\n";
|
||||
} else {
|
||||
$Makefile .= $dstFile . ': config.depends ' . implode(' ', $dstConfig) . "\n";
|
||||
$Makefile .= "\t$(JS_COMPILER) -d ". $dstFile ." \$(shell pwd)/config.depends\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $Makefile;
|
||||
}
|
||||
|
||||
function Usage()
|
||||
{
|
||||
global $argv;
|
||||
|
||||
echo <<<EOD
|
||||
Usage: {$argv[0]} [-c yes|no] moduleDir
|
||||
-c yes|no:
|
||||
yes: Compress .css and .js to .gz
|
||||
no: Don't compress to .gz
|
||||
|
||||
EOD;
|
||||
}
|
||||
|
||||
/* ----------------------- */
|
||||
/* ----------------------- */
|
||||
/* main access entry point */
|
||||
/* ----------------------- */
|
||||
/* ----------------------- */
|
||||
|
||||
function GetOptions()
|
||||
{
|
||||
global $argv, $argc;
|
||||
|
||||
$options = "c:";
|
||||
$opts = getopt($options);
|
||||
foreach( $opts as $o => $a )
|
||||
{
|
||||
while ( $k = array_search( "-" . $o, $argv ) ) {
|
||||
if ( $k ) {
|
||||
unset( $argv[$k] );
|
||||
$argc--;
|
||||
}
|
||||
if ( preg_match( "/^.*".$o.":.*$/i", $options ) ) {
|
||||
unset( $argv[$k+1] );
|
||||
$argc--;
|
||||
}
|
||||
}
|
||||
}
|
||||
$argv = array_merge( $argv );
|
||||
return $opts;
|
||||
}
|
||||
|
||||
$opts = GetOptions();
|
||||
|
||||
if (FALSE === $opts || $argc < 2 || $argc > 3) {
|
||||
Usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Compress package's js, css to gzip */
|
||||
$UseCompressGzip="yes";
|
||||
if (file_exists("/lnxscripts")) {
|
||||
$UseCompressGzip = "no";
|
||||
} else if (isSet($opts['c'])) {
|
||||
switch ($opts['c']) {
|
||||
case "yes":
|
||||
$UseCompressGzip = "yes";
|
||||
break;
|
||||
case "no":
|
||||
$UseCompressGzip = "no";
|
||||
break;
|
||||
default:
|
||||
echo "Error: Invalid Transpiler Option.\n";
|
||||
Usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_dir($argv[1])) {
|
||||
echo "Error: {$argv[1]} is not a directory.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$CWD = getcwd();
|
||||
chdir($argv[1]);
|
||||
|
||||
$InputFiles = array(
|
||||
'debug' => 'config.debug',
|
||||
'define' => 'config.define',
|
||||
'auto_debug'=> 'auto_config.debug',
|
||||
'depend' => 'config.depends'
|
||||
);
|
||||
|
||||
$OutputFiles = array(
|
||||
'config' => 'config',
|
||||
'makefile' => 'Makefile.js.inc',
|
||||
'style' => 'style.css',
|
||||
'scss' => 'scss/style.scss',
|
||||
'compass_config' => 'scss/config.rb'
|
||||
);
|
||||
|
||||
if (file_exists("app.config") && file_exists("config.debug")) {
|
||||
echo "Error > app.config and config.debug should not both exist\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$define_path = $InputFiles['define'];
|
||||
|
||||
if (file_exists($define_path)) {
|
||||
$ConfigDefine = DecodeJsonFile($define_path);
|
||||
} else {
|
||||
echo "Skip parsing: config.define not exist\n";
|
||||
$ConfigDefine = array();
|
||||
}
|
||||
|
||||
if (!is_array($ConfigDefine)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Generate files */
|
||||
file_put_contents($OutputFiles['makefile'], GenerateMakefile($UseCompressGzip));
|
||||
|
||||
// generate config.rb for compass if scss file exists
|
||||
if (file_exists($OutputFiles['scss'])) {
|
||||
file_put_contents($OutputFiles['compass_config'], GenerateCompassConfig());
|
||||
}
|
||||
|
||||
chdir($CWD);
|
||||
|
||||
?>
|
||||
|
10
tool/_babel.config.js
Normal file
10
tool/_babel.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
"presets": [
|
||||
[
|
||||
"/usr/lib/node_modules/@babel/preset-env",
|
||||
{
|
||||
modules: false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
39
tool/_eslintrc.json
Executable file
39
tool/_eslintrc.json
Executable file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": ["off", {
|
||||
"vars": "all",
|
||||
"args": "none"
|
||||
}],
|
||||
"no-mixed-spaces-and-tabs": "off",
|
||||
"no-empty": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"yoda": "off"
|
||||
},
|
||||
"globals": {
|
||||
"SYNO": true,
|
||||
"Ext": true,
|
||||
"Vue": true,
|
||||
"_S": true,
|
||||
"_D": true,
|
||||
"_JSLIBSTR": true,
|
||||
"_WFT": false,
|
||||
"_AST": true,
|
||||
"_VCT": true,
|
||||
"_VST": true,
|
||||
"PhotoStation": true,
|
||||
"Main": true,
|
||||
"_PST": true,
|
||||
"_T": true,
|
||||
"_TT": true,
|
||||
"Promise": true,
|
||||
"synowebapi": true
|
||||
}
|
||||
}
|
142
tool/parse_requires.py
Executable file
142
tool/parse_requires.py
Executable file
@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env python
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import copy
|
||||
from argparse import ArgumentParser
|
||||
|
||||
class Parser:
|
||||
def __init__ (self, jsPath, makeGoal, appPrefix):
|
||||
self.jsPath = jsPath
|
||||
self.makeGoal = makeGoal
|
||||
appPrefixOr = re.sub(r'\s+', '|', appPrefix)
|
||||
print(appPrefixOr)
|
||||
rePatterns = [
|
||||
'(?://\s*@require\s*:\s*([\w\-_.]+))', # require
|
||||
'(?:Ext\.define\s*\(\s*[\'\"]([\w\-_.]+))', # define
|
||||
'(?:extend\s*:\s*\(*[\'\"]([\w\-_.]+))', # extend
|
||||
'(?:([\w\-_.]+)\s*=\s*Ext.extend\s*\(\s*([\w\-_.]+))', # define2, extend2
|
||||
'(?:((?:{})[\w\-_.]+)\s*=[^=])'.format(appPrefixOr), # define3
|
||||
'(?://\s*@define\s*:\s*([\w\-_.]+))' # define4
|
||||
]
|
||||
self.matchRe = re.compile('|'.join(rePatterns))
|
||||
self.replaceRe = re.compile('\/([^\/]+)$')
|
||||
prefixNames = appPrefix.split(" ")
|
||||
|
||||
self.ourRe = re.compile('^({})'.format(appPrefixOr))
|
||||
|
||||
def run (self):
|
||||
if len(self.makeGoal) == 0 or self.makeGoal == 'all' or self.makeGoal == 'JSCompress' or self.makeGoal == 'JSCompress_AutoConfig':
|
||||
self.make()
|
||||
if self.makeGoal == 'clean':
|
||||
self.clean()
|
||||
|
||||
def make (self):
|
||||
self.clean()
|
||||
jsFiles = self.getJSFiles()
|
||||
print("Auto config js files:")
|
||||
print(jsFiles)
|
||||
self.parseRequire(jsFiles)
|
||||
|
||||
def clean (self):
|
||||
return os.system('/usr/bin/find -L ' + self.jsPath + ' -name auto_config.debug -exec rm -f {} \\;')
|
||||
|
||||
def getJSFiles (self):
|
||||
return os.popen('/usr/bin/find -L {} -name "*.js"'.format(self.jsPath)).read().strip().split('\n')
|
||||
|
||||
def parseRequire (self, jsFiles):
|
||||
generatedPath = 'auto_config.debug'
|
||||
debugConfig = {}
|
||||
|
||||
for jsFile in jsFiles:
|
||||
with open(jsFile) as file:
|
||||
fnDefs = self.getFnDefs(file.read())
|
||||
debugConfig[jsFile] = self.mixAppConfig(jsFile, fnDefs)
|
||||
|
||||
self.jsonToFile(debugConfig, generatedPath)
|
||||
|
||||
def getMatchResult(self, js):
|
||||
matchRec = self.matchRe.findall(js)
|
||||
result = []
|
||||
|
||||
for require, define, extend, define2, extend2, define3, define4 in matchRec:
|
||||
if len(require) > 0:
|
||||
result.append(('require', None, require))
|
||||
elif len(define) > 0:
|
||||
result.append(('define', define, None))
|
||||
elif len(extend) > 0:
|
||||
last = result.pop()
|
||||
result.append(('define', last[1], extend))
|
||||
elif len(define2) > 0:
|
||||
result.append(('define', define2, extend2))
|
||||
elif len(define3) > 0:
|
||||
result.append(('define', define3, None))
|
||||
elif len(define4) > 0:
|
||||
result.append(('define', define4, None))
|
||||
|
||||
return result
|
||||
|
||||
def getFnDefs (self, js):
|
||||
matches = self.getMatchResult(js)
|
||||
fnDefs = {}
|
||||
requires = []
|
||||
|
||||
for rule, fn, depend in matches:
|
||||
if rule == 'require':
|
||||
requires.append(depend)
|
||||
elif rule == 'define':
|
||||
fnDefs[fn] = requires
|
||||
requires = []
|
||||
if (depend):
|
||||
self.prependExtends(fnDefs[fn], depend)
|
||||
|
||||
return fnDefs
|
||||
|
||||
def prependExtends (self, requires, extends):
|
||||
if self.isOurExtends(extends):
|
||||
requires.insert(0, extends)
|
||||
|
||||
def isOurExtends (self, extends):
|
||||
return self.ourRe.search(extends)
|
||||
|
||||
def mixAppConfig (self, jsFile, fnDefs):
|
||||
appConfPath = 'app.config'
|
||||
conf = {}
|
||||
|
||||
try:
|
||||
appConf = self.fileToJson(appConfPath)
|
||||
except:
|
||||
print('[Warning] no {} file or failed to parse into json'.format(appConfPath))
|
||||
appConf = {}
|
||||
|
||||
for fnName, dependencies in fnDefs.iteritems():
|
||||
conf[fnName] = {}
|
||||
if fnName in appConf:
|
||||
conf[fnName] = copy.deepcopy(appConf[fnName])
|
||||
|
||||
conf[fnName]['depend'] = dependencies
|
||||
|
||||
return conf;
|
||||
|
||||
def fileToJson (self, path):
|
||||
with open(path) as file:
|
||||
return json.load(file)
|
||||
|
||||
def jsonToFile (self, js, path):
|
||||
with open(path, 'w') as file:
|
||||
json.dump(js, file, indent=2)
|
||||
|
||||
def Main ():
|
||||
parser = ArgumentParser(description='Chat @require to Config debug tool')
|
||||
parser.add_argument('--makegoal', metavar='makegoals', type=str, help='your MAKECMDGOALS')
|
||||
parser.add_argument('jspath', metavar='js-path', type=str, help='yout js path')
|
||||
parser.add_argument('appprefix', metavar='app-prefix', type=str, help='application prefix (e.g. SYNO.SDS.Chat)')
|
||||
options = parser.parse_args()
|
||||
|
||||
parser = Parser(jsPath=options.jspath, makeGoal=options.makegoal, appPrefix=options.appprefix)
|
||||
parser.run()
|
||||
|
||||
Main()
|
||||
|
449
tool/shrinksafe.php
Executable file
449
tool/shrinksafe.php
Executable file
@ -0,0 +1,449 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
$JRE = "/usr/lib/jvm/java-6-jdk/bin/java";
|
||||
$JSLINT = "/usr/local/tool/jslint+rhino.jar";
|
||||
$RhinoCompressor = "/usr/local/tool/custom_rhino.jar";
|
||||
$ClosureCompiler = "/usr/local/tool/closurecompiler.jar";
|
||||
$YUICompressor = "/usr/local/tool/yuicompressor-2.4.2.jar";
|
||||
$VerboseMsg = false;
|
||||
|
||||
$COPYRIGHT = "/* Copyright (c) " . date("Y") . " Synology Inc. All rights reserved. */\n\n";
|
||||
|
||||
$JSLINT_IGNORE = array("/variable .* declared in a block/",
|
||||
"/.* is better written in dot notation/",
|
||||
"/Use .* to compare with/",
|
||||
"/Line breaking error/",
|
||||
"/A constructor name should start with an uppercase letter/",
|
||||
"/Missing 'new' prefix when invoking a constructor/",
|
||||
"/Use the array literal notation*/",
|
||||
"/JavaScript URL./",
|
||||
"/document.write/",
|
||||
"/eval/");
|
||||
|
||||
|
||||
function ShouldIgnoreJSLintError($desc)
|
||||
{
|
||||
global $JSLINT_IGNORE;
|
||||
foreach($JSLINT_IGNORE as $pattern) {
|
||||
if (preg_match($pattern, $desc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function FindJSHintComments($fileList) {
|
||||
echo "== begin of JSHint comments ==\n";
|
||||
|
||||
$cmd = "grep -n ' jshint ' $fileList";
|
||||
system($cmd);
|
||||
$cmd = "grep -n ' global ' $fileList";
|
||||
system($cmd);
|
||||
echo "== end of JSHint comments ==\n";
|
||||
}
|
||||
|
||||
function ValidateJSFiles($linter, $jsFiles) {
|
||||
global $JRE, $JSLINT, $VerboseMsg;
|
||||
|
||||
$errors = 0;
|
||||
$fileList = implode(' ', $jsFiles);
|
||||
|
||||
if ($linter === "rhino-jslint") {
|
||||
$cmd = sprintf("%s -jar %s %s", $JRE, $JSLINT, $fileList);
|
||||
} elseif ($linter === "jslint") {
|
||||
$cmd = sprintf("/usr/bin/jslint --white --terse %s", $fileList);
|
||||
} elseif ($linter === "jshint") {
|
||||
$cmd = sprintf("/usr/bin/jshint %s", $fileList);
|
||||
|
||||
if ($VerboseMsg) {
|
||||
FindJSHintComments($fileList);
|
||||
}
|
||||
} elseif ($linter === "eslint") {
|
||||
$cmd = sprintf("/usr/bin/eslint --color %s", $fileList);
|
||||
}
|
||||
|
||||
$handle = popen($cmd, "r");
|
||||
if (false === $handle) {
|
||||
echo "Failed to execute [".$cmd."]\n";
|
||||
return 1;
|
||||
}
|
||||
while (!feof($handle)) {
|
||||
$line = fgets($handle);
|
||||
$line = trim($line);
|
||||
if (!$line) {
|
||||
continue;
|
||||
}
|
||||
if ($linter === "rhino-jslint") {
|
||||
list($prog, $file, $lineno, $err, $desc) = explode(":", $line);
|
||||
$invalidLine = !ShouldIgnoreJSLintError($desc);
|
||||
} else {
|
||||
$invalidLine = true;
|
||||
}
|
||||
if ($invalidLine) {
|
||||
$errors++;
|
||||
}
|
||||
if ($invalidLine || $VerboseMsg) {
|
||||
echo $line ."\n";
|
||||
}
|
||||
}
|
||||
pclose($handle);
|
||||
return $errors;
|
||||
}
|
||||
|
||||
function CombineJSFiles($outFile, $jsFiles)
|
||||
{
|
||||
foreach ($jsFiles as $file) {
|
||||
$fileContent = file_get_contents($file);
|
||||
/* append newline to end of file in case last line is comment */
|
||||
if ($fileContent !== false && substr($fileContent, -1) !== "\n") {
|
||||
$fileContent .= "\n";
|
||||
}
|
||||
file_put_contents($outFile, $fileContent, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
function RhinoCompress($outFile, $jsFile)
|
||||
{
|
||||
global $JRE, $RhinoCompressor;
|
||||
$cmd = sprintf("%s -jar %s -c %s",
|
||||
escapeshellcmd($JRE), escapeshellarg($RhinoCompressor),
|
||||
escapeshellarg($jsFile));
|
||||
$handle = popen($cmd, "r");
|
||||
|
||||
/* custom_rhino.jar won't trim line-break */
|
||||
$fp = fopen($outFile, "a");
|
||||
while (!feof($handle)) {
|
||||
fwrite($fp, trim(fgets($handle)));
|
||||
}
|
||||
fclose($fp);
|
||||
|
||||
pclose($handle);
|
||||
}
|
||||
|
||||
/* Transpiler */
|
||||
|
||||
function TranspileJSFiles($transpiler, $outFile, $jsFiles)
|
||||
{
|
||||
$retCode = -1;
|
||||
|
||||
$tmpFile = getcwd()."/.jsTmp_" . strtr($outFile, "/", "_") . ".js";
|
||||
CombineJSFiles($tmpFile, $jsFiles);
|
||||
$retCode = $transpiler($outFile, $tmpFile);
|
||||
@unlink($tmpFile);
|
||||
|
||||
return $retCode;
|
||||
}
|
||||
|
||||
function BabelTranspile($outFile, $jsFile)
|
||||
{
|
||||
$retCode = -1;
|
||||
|
||||
$cmd = sprintf("babel %s -o %s", escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
system($cmd, $retCode);
|
||||
|
||||
return $retCode;
|
||||
}
|
||||
|
||||
function SkipTranspile($outFile, $jsFile)
|
||||
{
|
||||
$retCode = -1;
|
||||
|
||||
$cmd = sprintf("mv %s %s", escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
system($cmd, $retCode);
|
||||
|
||||
return $retCode;
|
||||
}
|
||||
|
||||
/* Compressor */
|
||||
|
||||
function ClosureCompile($outFile, $jsFile)
|
||||
{
|
||||
global $JRE, $ClosureCompiler;
|
||||
$cmd = sprintf("%s -jar %s --warning_level QUIET --js %s >>%s",
|
||||
escapeshellcmd($JRE), escapeshellarg($ClosureCompiler),
|
||||
escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
function YUICompress($outFile, $jsFile)
|
||||
{
|
||||
global $JRE, $YUICompressor;
|
||||
$cmd = sprintf("%s -jar %s %s >>%s",
|
||||
escapeshellcmd($JRE), escapeshellarg($YUICompressor),
|
||||
escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
function UglifyjsCompress($outFile, $jsFile)
|
||||
{
|
||||
$cmd = sprintf("/usr/bin/uglifyjs --comments '/license/i' -m -c drop_console,warnings=false %s >> %s",
|
||||
escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
function TerserCompress($outFile, $jsFile)
|
||||
{
|
||||
$cmd = sprintf("/usr/bin/terser --comments '/license/i' -m -c drop_console,warnings=false %s >> %s",
|
||||
escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
function SkipCompress($outFile, $jsFile)
|
||||
{
|
||||
$cmd = sprintf("mv %s %s",
|
||||
escapeshellarg($jsFile), escapeshellarg($outFile));
|
||||
|
||||
system($cmd);
|
||||
}
|
||||
|
||||
function CompressJSFiles($compressor, $outFile, $transpiledFile)
|
||||
{
|
||||
global $COPYRIGHT;
|
||||
|
||||
file_put_contents($outFile, $COPYRIGHT);
|
||||
|
||||
$compressor($outFile, $transpiledFile);
|
||||
@unlink($transpiledFile);
|
||||
}
|
||||
|
||||
function GetOptions()
|
||||
{
|
||||
global $argv;
|
||||
|
||||
$options = "svdc:l:t:";
|
||||
$opts = getopt($options);
|
||||
foreach( $opts as $o => $a )
|
||||
{
|
||||
while ( $k = array_search( "-" . $o, $argv ) ) {
|
||||
if ( $k )
|
||||
unset( $argv[$k] );
|
||||
if ( preg_match( "/^.*".$o.":.*$/i", $options ) )
|
||||
unset( $argv[$k+1] );
|
||||
}
|
||||
}
|
||||
$argv = array_merge( $argv );
|
||||
return $opts;
|
||||
}
|
||||
|
||||
function ShowMessage($msg)
|
||||
{
|
||||
global $VerboseMsg;
|
||||
|
||||
if (!$VerboseMsg) {
|
||||
return;
|
||||
}
|
||||
echo $msg . "\n";
|
||||
}
|
||||
|
||||
function Usage()
|
||||
{
|
||||
global $argv;
|
||||
|
||||
echo <<<EOD
|
||||
USAGE:
|
||||
{$argv[0]} [-d] output config.depends
|
||||
{$argv[0]} [-s|-l] [-tc] [-v] output input [...]
|
||||
|
||||
OPTIONS:
|
||||
-d: Read JS dependency from config depend file
|
||||
-s: Skip JavaScript Validation (will ignore -l)
|
||||
-t Transpiler:
|
||||
babel: Convert ES6+ code into a backwards compatible version
|
||||
skip: Don't do any transpile (default)
|
||||
-c Compressor:
|
||||
rhino: old compressor
|
||||
closure: Google Closure Compiler
|
||||
uglifyjs: UglifyJs Compressor
|
||||
yui: Yahoo YUI Compressor (default)
|
||||
terser: JavaScript parser, mangler, optimizer and beautifier toolkit for ES6+
|
||||
skip: do not use any compressor
|
||||
-l Linter:
|
||||
rhino-jslint: old linter
|
||||
jslint: node-jslint
|
||||
jshint: node-jshint (default)
|
||||
eslint: eslint for ES6/JSX syntax
|
||||
skip: skip JavaScript validation
|
||||
-v:
|
||||
show verbose message, including full JSLint messages.
|
||||
|
||||
EOD;
|
||||
}
|
||||
|
||||
/* Decode json file to php object */
|
||||
function DecodeJsonFile($file)
|
||||
{
|
||||
print($file."\n");
|
||||
$content = @file_get_contents($file);
|
||||
if (FALSE === $content) {
|
||||
echo $file . ": Read error.\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$result = json_decode($content, true);
|
||||
if (!is_array($result)) {
|
||||
echo $file . ": Json parse failed.\n";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function SetTranspiler($opts)
|
||||
{
|
||||
$transpiler = SkipTranspile;
|
||||
|
||||
if (isSet($opts['t'])) {
|
||||
switch ($opts['t']) {
|
||||
case 'babel':
|
||||
if (!file_exists("/usr/bin/babel")) {
|
||||
echo "Error: Babel not found, available after DSM6.2\n";
|
||||
exit(1);
|
||||
}
|
||||
$transpiler = BabelTranspile;
|
||||
break;
|
||||
case 'skip':
|
||||
$transpiler = SkipTranspile;
|
||||
break;
|
||||
default:
|
||||
echo "Error: Invalid Transpiler Option.\n";
|
||||
Usage();
|
||||
exit(1);
|
||||
}
|
||||
if ('skip' != $opts['t']) {
|
||||
echo "Transpile using [".$opts['t']."]\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $transpiler;
|
||||
}
|
||||
|
||||
function SetCompressor($opts)
|
||||
{
|
||||
$compressor = YUICompress;
|
||||
if (isSet($opts['c'])) {
|
||||
switch ($opts['c']) {
|
||||
case 'rhino':
|
||||
$compressor = RhinoCompress;
|
||||
break;
|
||||
case 'closure':
|
||||
$compressor = ClosureCompile;
|
||||
break;
|
||||
case 'yui':
|
||||
$compressor = YUICompress;
|
||||
break;
|
||||
case 'uglifyjs':
|
||||
$compressor = UglifyjsCompress;
|
||||
break;
|
||||
case 'terser':
|
||||
$compressor = TerserCompress;
|
||||
break;
|
||||
case 'skip':
|
||||
$compressor = SkipCompress;
|
||||
break;
|
||||
default:
|
||||
echo "Error: Invalid Compressor Option.\n";
|
||||
Usage();
|
||||
exit(1);
|
||||
}
|
||||
if ('skip' != $opts['c']) {
|
||||
echo "Compress using [".$opts['c']."]\n";
|
||||
}
|
||||
} else {
|
||||
echo "Compress using [yui]\n";
|
||||
}
|
||||
return $compressor;
|
||||
}
|
||||
|
||||
function SetLinter($opts)
|
||||
{
|
||||
$linter = 'jshint';
|
||||
if (isset($opts['l'])) {
|
||||
$linter = $opts['l'];
|
||||
}
|
||||
return $linter;
|
||||
}
|
||||
|
||||
function RunLinter($opts, $linter, $jsFiles)
|
||||
{
|
||||
if (!isSet($opts['s']) && "skip" != $linter) {
|
||||
echo "Validating JS using [$linter]...\n";
|
||||
if ($linter === "eslint" && !file_exists("/usr/bin/eslint")) {
|
||||
echo "Error: Compressor [eslint] only avaliable since DSM7.0\n";
|
||||
exit(1);
|
||||
}
|
||||
if (ValidateJSFiles($linter, $jsFiles) > 0) {
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
echo "Skip JavaScript Validation\n";
|
||||
}
|
||||
}
|
||||
|
||||
function RunTranspiler($transpiler, $jsFiles, $transpiledOutFile)
|
||||
{
|
||||
$retCode = TranspileJSFiles($transpiler, $transpiledOutFile, $jsFiles);
|
||||
if (0 != retCode) {
|
||||
throw new Exception("ERROR >> Failed to transpile [".$transpiledOutFile."]\n");
|
||||
}
|
||||
}
|
||||
|
||||
function RunCompressor($compressor, $outFile, $transpiledOutFile)
|
||||
{
|
||||
CompressJSFiles($compressor, $outFile, $transpiledOutFile);
|
||||
}
|
||||
|
||||
/* main process */
|
||||
|
||||
$opts = GetOptions();
|
||||
|
||||
if (FALSE === $opts || count($argv) < 3) {
|
||||
Usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$VerboseMsg = isSet($opts['v']);
|
||||
$transpiler = SetTranspiler($opts);
|
||||
$compressor = SetCompressor($opts);
|
||||
$linter = SetLinter($opts);
|
||||
|
||||
/* read depend js file */
|
||||
|
||||
$outFile = $argv[1];
|
||||
|
||||
if(isSet($opts['d'])) {
|
||||
$jsDepCfg = DecodeJsonFile($argv[2]);
|
||||
|
||||
if (!is_array($jsDepCfg)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!is_array($jsDepCfg[$outFile])) {
|
||||
echo "Error > ".$outFile." is not in config.depends\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(isSet($jsDepCfg[$outFile]['files'])) {
|
||||
$jsFiles = $jsDepCfg[$outFile]['files'];
|
||||
} else {
|
||||
$jsFiles = $jsDepCfg[$outFile];
|
||||
}
|
||||
} else {
|
||||
$jsFiles = array_slice($argv, 2);
|
||||
}
|
||||
|
||||
$transpiledOutFileOrig = tempnam("/tmp/", basename($outFile)."_transpiled_");
|
||||
$transpiledOutFile = $transpiledOutFileOrig.'.js';
|
||||
|
||||
try {
|
||||
RunLinter($opts, $linter, $jsFiles);
|
||||
RunTranspiler($transpiler, $jsFiles, $transpiledOutFile);
|
||||
RunCompressor($compressor, $outFile, $transpiledOutFile);
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
@unlink($transpiledOutFileOrig);
|
||||
@unlink($transpiledOutFile);
|
||||
?>
|
||||
|
62
tool/snpm
Executable file
62
tool/snpm
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
toolchain = {
|
||||
"babel": "/usr/bin/babel",
|
||||
"uglifyjs": "/usr/bin/uglifyjs",
|
||||
"terser": "/usr/bin/terser",
|
||||
"jslint": "/usr/bin/jslint",
|
||||
"jshint": "/usr/bin/jshint",
|
||||
"eslint": "/usr/bin/eslint"
|
||||
}
|
||||
|
||||
|
||||
CSI = '\033['
|
||||
FAIL = '91m'
|
||||
OSC = '\033]'
|
||||
|
||||
def print_fail(line):
|
||||
if sys.stderr is None:
|
||||
return
|
||||
if sys.stderr.isatty():
|
||||
print(CSI + FAIL + line.decode('utf-8') + OSC, end='', file=sys.stderr)
|
||||
else:
|
||||
print(line.decode('utf-8'), end='', file=sys.stderr)
|
||||
|
||||
def print_succ(line):
|
||||
if sys.stdout is None:
|
||||
return
|
||||
print(line.decode('utf-8'), end='', file=sys.stdout)
|
||||
|
||||
def find_toolchain(tool):
|
||||
if tool in toolchain:
|
||||
return toolchain[tool]
|
||||
return tool
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
args = sys.argv[1:] if len(sys.argv) > 1 else []
|
||||
if len(args) >= 1 and args[0] == 'chroot':
|
||||
tool = []
|
||||
if len(args) >= 2:
|
||||
tool = [find_toolchain(args[1])]
|
||||
args = args[2:]
|
||||
cmd_list = ['/usr/bin/node'] + tool + args
|
||||
else:
|
||||
cmd_list = ['/usr/bin/pnpm'] + args
|
||||
proc = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
|
||||
for line in iter(proc.stdout.readline, b''):
|
||||
print_succ(line)
|
||||
for line in iter(proc.stderr.readline, b''):
|
||||
print_fail(line)
|
||||
proc.wait()
|
||||
except subprocess.CalledProcessError as err:
|
||||
print("""Failed with %s.""" % str(err), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Reference in New Issue
Block a user