mirror of
https://github.com/joomla/joomla-cms.git
synced 2024-06-25 23:02:55 +00:00
[4.0] Build Tools code cleanup (#32300)
This commit is contained in:
parent
399cf4c66c
commit
52fc4b86a8
|
@ -1,9 +1,8 @@
|
|||
const Fs = require('fs');
|
||||
const FsExtra = require('fs-extra');
|
||||
const Path = require('path');
|
||||
const Recurs = require('recursive-readdir');
|
||||
const UglyCss = require('uglifycss');
|
||||
const CompileScss = require('./stylesheets/scss-transform.es6.js');
|
||||
const { stat } = require('fs-extra');
|
||||
const { sep } = require('path');
|
||||
const recursive = require('recursive-readdir');
|
||||
const { handleScssFile } = require('./stylesheets/handle-scss.es6.js');
|
||||
const { handleCssFile } = require('./stylesheets/handle-css.es6.js');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
|
@ -20,96 +19,70 @@ const RootPath = process.cwd();
|
|||
* @param {object} options The options
|
||||
* @param {string} path The folder that needs to be compiled, optional
|
||||
*/
|
||||
module.exports.compile = (options, path) => {
|
||||
Promise.resolve()
|
||||
// Compile the scss files
|
||||
.then(() => {
|
||||
const files = [];
|
||||
let folders = [];
|
||||
module.exports.stylesheets = async (options, path) => {
|
||||
const files = [];
|
||||
let folders = [];
|
||||
|
||||
if (path) {
|
||||
const stats = Fs.lstatSync(`${RootPath}/${path}`);
|
||||
if (path) {
|
||||
const stats = await stat(`${RootPath}/${path}`);
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
folders.push(`${RootPath}/${path}`);
|
||||
} else if (stats.isFile()) {
|
||||
files.push(`${RootPath}/${path}`);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Unknown path ${path}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
folders = [
|
||||
`${RootPath}/build/media_source`,
|
||||
`${RootPath}/templates`,
|
||||
`${RootPath}/installation/template`,
|
||||
`${RootPath}/administrator/templates`,
|
||||
];
|
||||
if (stats.isDirectory()) {
|
||||
folders.push(`${RootPath}/${path}`);
|
||||
} else if (stats.isFile()) {
|
||||
files.push(`${RootPath}/${path}`);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Unknown path ${path}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
folders = [
|
||||
`${RootPath}/build/media_source`,
|
||||
`${RootPath}/templates`,
|
||||
`${RootPath}/administrator/templates`,
|
||||
`${RootPath}/installation/template`,
|
||||
`${RootPath}/media/vendor/debugbar`,
|
||||
];
|
||||
}
|
||||
|
||||
const folderPromises = [];
|
||||
|
||||
// Loop to get the files that should be compiled via parameter
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const folder of folders) {
|
||||
folderPromises.push(recursive(folder, ['!*.+(scss|css)']));
|
||||
}
|
||||
|
||||
const computedFiles = await Promise.all(folderPromises);
|
||||
|
||||
const cssFilesPromises = [];
|
||||
const scssFilesPromises = [];
|
||||
|
||||
// Loop to get the files that should be compiled via parameter
|
||||
[].concat(...computedFiles).forEach((file) => {
|
||||
if (file.endsWith('.css') && !file.endsWith('.min.css')) {
|
||||
cssFilesPromises.push(handleCssFile(file));
|
||||
}
|
||||
|
||||
// Don't take files with "_" but "file" has the full path, so check via match
|
||||
if (file.endsWith('.scss') && !file.match(/(\/|\\)_[^/\\]+$/)) {
|
||||
// Bail out for non Joomla convention folders, eg: scss
|
||||
if (!(file.match(/\/scss\//) || file.match(/\\scss\\/))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop to get the files that should be compiled via parameter
|
||||
folders.forEach((folder) => {
|
||||
Recurs(folder, ['*.js', '*.map', '*.svg', '*.png', '*.gif', '*.swf', '*.html', '*.json']).then(
|
||||
(filesRc) => {
|
||||
filesRc.forEach(
|
||||
(file) => {
|
||||
// Don't take files with "_" but "file" has the full path, so check via match
|
||||
if (file.match(/\.scss$/)) {
|
||||
// Bail out for non Joomla convention folders, eg: scss
|
||||
if (!(file.match(/\/scss\//) || file.match(/\\scss\\/))) {
|
||||
return;
|
||||
}
|
||||
// Ignore files starting with _
|
||||
if (!file.match(/(\/|\\)_[^/\\]+$/)) {
|
||||
files.push(file);
|
||||
}
|
||||
files.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Update the scss in the media folder
|
||||
if (file.match(/build\/media_source\//)) {
|
||||
FsExtra.mkdirsSync(Path.dirname(file).replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\'), {});
|
||||
Fs.copyFileSync(file, file.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\'));
|
||||
}
|
||||
}
|
||||
if (file.match(/\.css/) && !(file.match(/\/template(s)?\//) || file.match(/\\template(s)?\\/))) {
|
||||
// CSS file, we will copy the file and then minify it in place
|
||||
// Ensure that the directories exist or create them
|
||||
FsExtra.mkdirsSync(Path.dirname(file).replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\'), {});
|
||||
Fs.copyFileSync(file, file.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\'));
|
||||
Fs.writeFileSync(
|
||||
file.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.css', '.min.css'),
|
||||
UglyCss.processFiles([file], { expandVars: false }),
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const file of files) {
|
||||
const outputFile = file.replace(`${sep}scss${sep}`, `${sep}css${sep}`)
|
||||
.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`)
|
||||
.replace('.scss', '.css');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`CSS file copied/minified: ${file}`);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error.formatted);
|
||||
},
|
||||
);
|
||||
scssFilesPromises.push(handleScssFile(file, outputFile));
|
||||
}
|
||||
|
||||
return files;
|
||||
},
|
||||
).then(
|
||||
(scssFiles) => {
|
||||
scssFiles.forEach(
|
||||
(inputFile) => {
|
||||
CompileScss.compile(inputFile);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
})
|
||||
|
||||
// Handle errors
|
||||
.catch((error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
});
|
||||
await Promise.all([...cssFilesPromises, ...scssFilesPromises]);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
const Fs = require('fs');
|
||||
const { stat } = require('fs-extra');
|
||||
const { sep } = require('path');
|
||||
const Recurs = require('recursive-readdir');
|
||||
const HandleFile = require('./javascript/handle-file.es6.js');
|
||||
const recursive = require('recursive-readdir');
|
||||
const { handleES5File } = require('./javascript/handle-es5.es6.js');
|
||||
const { handleESMFile } = require('./javascript/compile-es6.es6.js');
|
||||
const { handleWCFile } = require('./javascript/compile-w-c.es6.js');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
|
@ -19,50 +21,58 @@ const RootPath = process.cwd();
|
|||
* @param { object } options The options from settings.json
|
||||
* @param { string } path The folder that needs to be compiled, optional
|
||||
*/
|
||||
module.exports.compileJS = (options, path) => {
|
||||
Promise.resolve(options, path)
|
||||
// Compile the scss files
|
||||
.then(() => {
|
||||
let folders = [];
|
||||
if (path) {
|
||||
const stats = Fs.lstatSync(`${RootPath}/${path}`);
|
||||
module.exports.scripts = async (options, path) => {
|
||||
const files = [];
|
||||
let folders = [];
|
||||
|
||||
if (!stats.isDirectory()) {
|
||||
// @todo: allow to compile single file
|
||||
throw new Error(`Path should be a directory: ${path}`);
|
||||
}
|
||||
if (path) {
|
||||
const stats = await stat(`${RootPath}/${path}`);
|
||||
|
||||
folders.push(`${RootPath}/${path}`);
|
||||
} else {
|
||||
folders = [
|
||||
`${RootPath}/build/media_source`,
|
||||
`${RootPath}/templates/cassiopeia/js`,
|
||||
];
|
||||
}
|
||||
if (stats.isDirectory()) {
|
||||
folders.push(`${RootPath}/${path}`);
|
||||
} else if (stats.isFile()) {
|
||||
files.push(`${RootPath}/${path}`);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Unknown path ${path}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
folders = [
|
||||
`${RootPath}/build/media_source`,
|
||||
`${RootPath}/templates/cassiopeia`,
|
||||
];
|
||||
}
|
||||
|
||||
// Loop to get some text for the packgage.json
|
||||
folders.forEach((folder) => {
|
||||
Recurs(folder, ['*.min.js', '*.map', '*.scss', '*.css', '*.svg', '*.png', '*.swf', '*.gif', '*.json']).then(
|
||||
(files) => {
|
||||
files.forEach(
|
||||
(file) => {
|
||||
if (file.includes(`build${sep}media_source${sep}vendor${sep}bootstrap${sep}js`)) {
|
||||
return;
|
||||
}
|
||||
HandleFile.run(file);
|
||||
},
|
||||
(error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error.formatted);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
})
|
||||
const folderPromises = [];
|
||||
|
||||
// Handle errors
|
||||
.catch((error) => {
|
||||
throw new Error(`${error}`);
|
||||
});
|
||||
// Loop to get the files that should be compiled via parameter
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const folder of folders) {
|
||||
folderPromises.push(recursive(folder, ['!*.+(js)']));
|
||||
}
|
||||
|
||||
const computedFiles = await Promise.all(folderPromises);
|
||||
const computedFilesFlat = [].concat(...computedFiles);
|
||||
|
||||
const jsFilesPromises = [];
|
||||
const wcFilesPromises = [];
|
||||
const esmFilesPromises = [];
|
||||
|
||||
// Loop to get the files that should be compiled via parameter
|
||||
computedFilesFlat.forEach((file) => {
|
||||
if (file.includes(`build${sep}media_source${sep}vendor${sep}bootstrap${sep}js`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.match(/\.es5\.js$/)) {
|
||||
jsFilesPromises.push(handleES5File(file));
|
||||
} else if (file.match(/\.w-c\.es6\.js$/)) {
|
||||
wcFilesPromises.push(handleWCFile(file));
|
||||
} else if (file.match(/\.es6\.js$/)) {
|
||||
esmFilesPromises.push(handleESMFile(file));
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all([...jsFilesPromises, ...wcFilesPromises, ...esmFilesPromises]);
|
||||
};
|
||||
|
|
26
build/build-modules-js/compress.es6.js
Normal file
26
build/build-modules-js/compress.es6.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const { getFiles } = require('@dgrammatiko/compress/src/getFiles.js');
|
||||
const { compressFile } = require('@dgrammatiko/compress/src/compressFile.js');
|
||||
|
||||
/**
|
||||
* Method that will pre compress (gzip) all .css/.js files
|
||||
* in the templates and in the media folder
|
||||
*/
|
||||
module.exports.compressFiles = async (enableBrotli = false) => {
|
||||
const paths = [
|
||||
`${process.cwd()}/media`,
|
||||
`${process.cwd()}/installation/template`,
|
||||
`${process.cwd()}/templates`,
|
||||
`${process.cwd()}/administrator/templates`,
|
||||
];
|
||||
|
||||
const tasks = [];
|
||||
const compressTasks = [];
|
||||
paths.map((path) => tasks.push(getFiles(`${path}/`)));
|
||||
|
||||
const files = await Promise.all(tasks);
|
||||
[].concat(...files).map((file) => compressTasks.push(compressFile(file, enableBrotli)));
|
||||
|
||||
await Promise.all(compressTasks);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Done 👍');
|
||||
};
|
|
@ -1,20 +1,20 @@
|
|||
const Fs = require('fs');
|
||||
const {
|
||||
access, mkdir, readFile, writeFile,
|
||||
} = require('fs').promises;
|
||||
const Ini = require('ini');
|
||||
const Path = require('path');
|
||||
const { dirname } = require('path');
|
||||
const Recurs = require('recursive-readdir');
|
||||
const UglifyCss = require('uglifycss');
|
||||
const UglifyJs = require('uglify-es');
|
||||
const Postcss = require('postcss');
|
||||
const Autoprefixer = require('autoprefixer');
|
||||
const CssNano = require('cssnano');
|
||||
const { minify } = require('terser');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
const dir = `${RootPath}/installation/language`;
|
||||
const srcPath = `${RootPath}/build/warning_page`;
|
||||
|
||||
// Set the initial template
|
||||
let incomplete = 'window.errorLocale = {';
|
||||
let unsupported = 'window.errorLocale = {';
|
||||
|
||||
/**
|
||||
* Will produce 2 .html files
|
||||
* Will produce as many .html files as defined in settings.json
|
||||
* Expects three files:
|
||||
* build/warning_page/template.css
|
||||
* build/warning_page/template.html
|
||||
|
@ -23,80 +23,141 @@ let unsupported = 'window.errorLocale = {';
|
|||
* And also specific strings in the languages in the installation folder!
|
||||
* Also the base strings are held in build/build-modules-js/settings.json
|
||||
*/
|
||||
module.exports.run = (options) => {
|
||||
const initTemplate = Fs.readFileSync(`${srcPath}/template.html`, 'utf-8');
|
||||
let cssContent = Fs.readFileSync(`${srcPath}/template.css`, 'utf-8');
|
||||
let jsContent = Fs.readFileSync(`${srcPath}/template.js`, 'utf-8');
|
||||
module.exports.createErrorPages = async (options) => {
|
||||
const iniFilesProcess = [];
|
||||
const processPages = [];
|
||||
this.incompleteObj = {};
|
||||
this.unsupportedObj = {};
|
||||
this.fatalObj = {};
|
||||
this.noxmlObj = {};
|
||||
|
||||
cssContent = UglifyCss.processString(cssContent, { expandVars: false });
|
||||
jsContent = UglifyJs.minify(jsContent);
|
||||
const initTemplate = await readFile(`${srcPath}/template.html`, { encoding: 'utf8' });
|
||||
let cssContent = await readFile(`${srcPath}/template.css`, { encoding: 'utf8' });
|
||||
let jsContent = await readFile(`${srcPath}/template.js`, { encoding: 'utf8' });
|
||||
|
||||
Recurs(dir).then(
|
||||
(files) => {
|
||||
files.sort().forEach((file) => {
|
||||
const languageStrings = Ini.parse(Fs.readFileSync(file, 'UTF-8'));
|
||||
const cssMin = await Postcss([Autoprefixer, CssNano]).process(cssContent, { from: undefined });
|
||||
///
|
||||
cssContent = cssMin.css;
|
||||
jsContent = await minify(jsContent);
|
||||
|
||||
// Build the variables into json for the unsupported page
|
||||
if (languageStrings.MIN_PHP_ERROR_LANGUAGE) {
|
||||
const name = Path.dirname(file).replace(/.+\//, '').replace(/.+\\/, '');
|
||||
unsupported += `"${name}":{"language":"${languageStrings.MIN_PHP_ERROR_LANGUAGE}",`
|
||||
+ `"header":"${languageStrings.MIN_PHP_ERROR_HEADER}",`
|
||||
+ `"text1":"${languageStrings.MIN_PHP_ERROR_TEXT}",`
|
||||
+ `"help-url-text":"${languageStrings.MIN_PHP_ERROR_URL_TEXT}"},`;
|
||||
}
|
||||
const processIni = async (file) => {
|
||||
const languageStrings = Ini.parse(await readFile(file, { encoding: 'utf8' }));
|
||||
|
||||
// Build the variables into json for the unsupported page
|
||||
if (languageStrings.BUILD_INCOMPLETE_LANGUAGE) {
|
||||
const name = Path.dirname(file).replace(/.+\//, '').replace(/.+\\/, '');
|
||||
incomplete += `"${name}":{"language":"${languageStrings.BUILD_INCOMPLETE_LANGUAGE}",`
|
||||
+ `"header":"${languageStrings.BUILD_INCOMPLETE_HEADER}",`
|
||||
+ `"text1":"${languageStrings.BUILD_INCOMPLETE_TEXT}",`
|
||||
+ `"help-url-text":"${languageStrings.BUILD_INCOMPLETE_URL_TEXT}"},`;
|
||||
}
|
||||
});
|
||||
// Build the variables into json for the unsupported page
|
||||
if (languageStrings.MIN_PHP_ERROR_LANGUAGE) {
|
||||
const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, '');
|
||||
this.unsupportedObj = {
|
||||
...this.unsupportedObj,
|
||||
[name]: {
|
||||
language: languageStrings.MIN_PHP_ERROR_LANGUAGE,
|
||||
header: languageStrings.MIN_PHP_ERROR_HEADER,
|
||||
text1: languageStrings.MIN_PHP_ERROR_TEXT,
|
||||
'help-url-text': languageStrings.MIN_PHP_ERROR_URL_TEXT,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
unsupported = `${unsupported}}`;
|
||||
incomplete = `${incomplete}}`;
|
||||
// Build the variables into json for the build incomplete page
|
||||
if (languageStrings.BUILD_INCOMPLETE_LANGUAGE) {
|
||||
const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, '');
|
||||
this.incompleteObj = {
|
||||
...this.incompleteObj,
|
||||
[name]: {
|
||||
language: languageStrings.BUILD_INCOMPLETE_LANGUAGE,
|
||||
header: languageStrings.BUILD_INCOMPLETE_HEADER,
|
||||
text1: languageStrings.BUILD_INCOMPLETE_TEXT,
|
||||
'help-url-text': languageStrings.BUILD_INCOMPLETE_URL_TEXT,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Object.keys(options.settings.errorPages).sort().forEach((name) => {
|
||||
let checkContent = initTemplate;
|
||||
checkContent = checkContent.replace('{{jsonContents}}', name === 'incomplete' ? incomplete : unsupported);
|
||||
checkContent = checkContent.replace('{{PHP_VERSION}}', '');
|
||||
checkContent = checkContent.replace('{{Title}}', options.settings.errorPages[name].title);
|
||||
checkContent = checkContent.replace('{{Header}}', options.settings.errorPages[name].header);
|
||||
checkContent = checkContent.replace('{{Description}}', options.settings.errorPages[name].text);
|
||||
checkContent = checkContent.replace('{{Link}}', options.settings.errorPages[name].link);
|
||||
checkContent = checkContent.replace('{{LinkText}}', options.settings.errorPages[name].linkText);
|
||||
// Build the variables into json for the fatal error page
|
||||
if (languageStrings.BUILD_FATAL_LANGUAGE) {
|
||||
const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, '');
|
||||
this.fatalObj = {
|
||||
...this.fatalObj,
|
||||
[name]: {
|
||||
language: languageStrings.BUILD_FATAL_LANGUAGE,
|
||||
header: languageStrings.BUILD_FATAL_HEADER,
|
||||
text1: languageStrings.BUILD_FATAL_TEXT,
|
||||
'help-url-text': languageStrings.BUILD_FATAL_URL_TEXT,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (cssContent) {
|
||||
checkContent = checkContent.replace('{{cssContents}}', cssContent);
|
||||
}
|
||||
// Build the variables into json for the missing XML error page
|
||||
if (languageStrings.BUILD_NOXML_LANGUAGE) {
|
||||
const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, '');
|
||||
this.noxmlObj = {
|
||||
...this.noxmlObj,
|
||||
[name]: {
|
||||
language: languageStrings.BUILD_NOXML_LANGUAGE,
|
||||
header: languageStrings.BUILD_NOXML_HEADER,
|
||||
text1: languageStrings.BUILD_NOXML_TEXT,
|
||||
'help-url-text': languageStrings.BUILD_NOXML_URL_TEXT,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
if (jsContent) {
|
||||
checkContent = checkContent.replace('{{jsContents}}', jsContent.code);
|
||||
}
|
||||
const files = await Recurs(dir);
|
||||
files.sort().forEach((file) => {
|
||||
iniFilesProcess.push(processIni(file));
|
||||
});
|
||||
|
||||
Fs.writeFile(
|
||||
`${RootPath}${options.settings.errorPages[name].destFile}`,
|
||||
checkContent,
|
||||
{ encoding: 'utf8' },
|
||||
(err) => {
|
||||
if (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
await Promise.all(iniFilesProcess).catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(-1);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`The ${options.settings.errorPages[name].destFile} page was created successfully!`);
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
},
|
||||
);
|
||||
const processPage = async (name) => {
|
||||
const jsonContent = `window.errorLocale=${JSON.stringify(this[`${name}Obj`])};`;
|
||||
|
||||
let template = initTemplate;
|
||||
|
||||
template = template.replace('{{jsonContents}}', jsonContent);
|
||||
template = template.replace('{{Title}}', options.settings.errorPages[name].title);
|
||||
template = template.replace('{{Header}}', options.settings.errorPages[name].header);
|
||||
template = template.replace('{{Description}}', options.settings.errorPages[name].text);
|
||||
template = template.replace('{{Link}}', options.settings.errorPages[name].link);
|
||||
template = template.replace('{{LinkText}}', options.settings.errorPages[name].linkText);
|
||||
|
||||
if (cssContent) {
|
||||
template = template.replace('{{cssContents}}', cssContent);
|
||||
}
|
||||
|
||||
if (jsContent) {
|
||||
template = template.replace('{{jsContents}}', jsContent.code);
|
||||
}
|
||||
|
||||
let mediaExists = false;
|
||||
try {
|
||||
await access(dirname(`${RootPath}${options.settings.errorPages[name].destFile}`));
|
||||
mediaExists = true;
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
if (!mediaExists) {
|
||||
await mkdir(dirname(`${RootPath}${options.settings.errorPages[name].destFile}`), { recursive: true });
|
||||
}
|
||||
|
||||
await writeFile(
|
||||
`${RootPath}${options.settings.errorPages[name].destFile}`,
|
||||
template,
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Created the file: ${options.settings.errorPages[name].destFile}`);
|
||||
};
|
||||
|
||||
Object.keys(options.settings.errorPages).forEach((name) => processPages.push(processPage(name)));
|
||||
|
||||
await Promise.all(processPages).catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(-1);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
/**
|
||||
* For creating Brotli files you need to install iltorb
|
||||
* and import it like:
|
||||
* const { compressStream } = require('iltorb');
|
||||
*/
|
||||
const Fs = require('fs');
|
||||
const { gzip } = require('@gfx/zopfli');
|
||||
const walkSync = require('walk-sync');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
const compressStream = '';
|
||||
const options = {
|
||||
verbose: false,
|
||||
verbose_more: false,
|
||||
numiterations: 15,
|
||||
blocksplitting: true,
|
||||
blocksplittingmax: 15,
|
||||
};
|
||||
|
||||
/**
|
||||
* Method that will create a gzipped vestion of the given file
|
||||
*
|
||||
* @param { string } file The path of the file
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const handleFile = (file, enableBrotli) => {
|
||||
if (file.match('/images') || file.match('\\images')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file.match(/\.min\.js/) && !file.match(/\.min\.js\.gz/) && !file.match(/\.min\.js\.br/) && !file.toLowerCase().match(/json/) && !file.toLowerCase().match(/license/)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Processing: ${file}`);
|
||||
|
||||
if (enableBrotli && compressStream) {
|
||||
// Brotli file
|
||||
Fs.createReadStream(file)
|
||||
.pipe(compressStream())
|
||||
.pipe(Fs.createWriteStream(file.replace(/\.js$/, '.js.br')));
|
||||
} else {
|
||||
// Gzip the file
|
||||
Fs.readFile(file, (err, data) => {
|
||||
if (err) throw err;
|
||||
gzip(data, options, (error, output) => {
|
||||
if (error) throw err;
|
||||
// Save the gzipped file
|
||||
Fs.writeFileSync(
|
||||
file.replace(/\.js$/, '.js.gz'),
|
||||
output,
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (file.match(/\.min\.css/) && !file.match(/\.min\.css\.gz/) && !file.match(/\.min\.css\.br/) && !file.match(/\.css\.map/) && !file.toLowerCase().match(/license/)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Processing: ${file}`);
|
||||
|
||||
if (enableBrotli && compressStream) {
|
||||
// Brotli file
|
||||
Fs.createReadStream(file)
|
||||
.pipe(compressStream())
|
||||
.pipe(Fs.createWriteStream(file.replace(/\.css$/, '.css.br')));
|
||||
} else {
|
||||
// Gzip the file
|
||||
Fs.readFile(file, (err, data) => {
|
||||
if (err) throw err;
|
||||
gzip(data, options, (error, output) => {
|
||||
if (error) throw err;
|
||||
// Save the gzipped file
|
||||
Fs.writeFileSync(
|
||||
file.replace(/\.css$/, '.css.gz'),
|
||||
output,
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Method to gzip the script and stylesheet files
|
||||
*
|
||||
* @param brotliParam {string} The CLI argument
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const gzipFiles = (brotliParam) => {
|
||||
let enableBrotli = false;
|
||||
if (brotliParam === 'brotli') {
|
||||
enableBrotli = true;
|
||||
}
|
||||
// Minify the legacy files
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Gziping stylesheets and scripts...');
|
||||
|
||||
const templatesFiles = walkSync(`${RootPath}/templates`, {
|
||||
globs: ['**/*.{js,css}'],
|
||||
includeBasePath: true,
|
||||
ignore: [],
|
||||
directories: false,
|
||||
});
|
||||
const adminTemplatesFiles = walkSync(`${RootPath}/administrator/templates`, {
|
||||
globs: ['**/*.{js,css}'],
|
||||
includeBasePath: true,
|
||||
ignore: [],
|
||||
directories: false,
|
||||
});
|
||||
const mediaFiles = walkSync(`${RootPath}/media`, {
|
||||
globs: ['**/*.{js,css}'],
|
||||
includeBasePath: true,
|
||||
ignore: [],
|
||||
directories: false,
|
||||
});
|
||||
|
||||
if (templatesFiles.length) {
|
||||
templatesFiles.forEach((file) => handleFile(file, enableBrotli));
|
||||
}
|
||||
if (adminTemplatesFiles.length) {
|
||||
adminTemplatesFiles.forEach((file) => handleFile(file, enableBrotli));
|
||||
}
|
||||
if (mediaFiles.length) {
|
||||
mediaFiles.forEach((file) => handleFile(file, enableBrotli));
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.gzipFiles = gzipFiles;
|
|
@ -1,363 +0,0 @@
|
|||
const Copydir = require('copy-dir');
|
||||
const Fs = require('fs');
|
||||
const FsExtra = require('fs-extra');
|
||||
const Path = require('path');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
const xmlVersionStr = /(<version>)(.+)(<\/version>)/;
|
||||
|
||||
/**
|
||||
* Method that will erase the media/vendor folder
|
||||
* and populate the debugbar assets
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const cleanVendors = () => {
|
||||
if (Fs.existsSync(Path.join(RootPath, 'libraries/vendor/maximebf/debugbar/src/DebugBar/Resources'))) {
|
||||
// Remove the vendor folder
|
||||
FsExtra.removeSync(Path.join(RootPath, 'media/vendor'));
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('/media/vendor has been removed.');
|
||||
|
||||
// Copy some assets from a PHP package
|
||||
FsExtra.copySync(Path.join(RootPath, 'libraries/vendor/maximebf/debugbar/src/DebugBar/Resources'), Path.join(RootPath, 'media/vendor/debugbar'));
|
||||
// Do some cleanup
|
||||
FsExtra.removeSync(Path.join(RootPath, 'media/vendor/debugbar/vendor/font-awesome'));
|
||||
FsExtra.removeSync(Path.join(RootPath, 'media/vendor/debugbar/vendor/jquery'));
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('You need to run `npm install` AFTER the command `composer install`!!!. The debug plugin HASN\'T installed all its front end assets');
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies all the files from a directory
|
||||
*
|
||||
* @param {string} dirName the name of the source folder
|
||||
* @param {string} name the name of the destination folder
|
||||
* @param {string} type the type of the folder, eg: js, css, fonts, images
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const copyAll = (dirName, name, type) => {
|
||||
const folderName = dirName === '/' ? '/' : `/${dirName}`;
|
||||
FsExtra.copySync(Path.join(RootPath, `node_modules/${name}/${folderName}`),
|
||||
Path.join(RootPath, `media/vendor/${name.replace(/.+\//, '')}/${type}`));
|
||||
};
|
||||
|
||||
/**
|
||||
* Copies an array of files from a directory
|
||||
*
|
||||
* @param {string} dirName the name of the source folder
|
||||
* @param {array} files the array of files to be be copied
|
||||
* @param {string} name the name of the destination folder
|
||||
* @param {string} type the type of the folder, eg: js, css, fonts, images
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const copyArrayFiles = (dirName, files, name, type) => {
|
||||
files.forEach((file) => {
|
||||
const folderName = dirName === '/' ? '/' : `/${dirName}/`;
|
||||
if (FsExtra.existsSync(`node_modules/${name}${folderName}${file}`)) {
|
||||
FsExtra.copySync(`node_modules/${name}${folderName}${file}`, `media/vendor/${name.replace(/.+\//, '')}${type ? `/${type}` : ''}/${file}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} files the object of files map, eg {"src.js": "js/src.js"}
|
||||
* @param {string} srcDir the name of the package root dir
|
||||
* @param {string} destDir the name of the Vendor destination dir
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const copyFilesTo = (files, srcDir, destDir) => {
|
||||
const filesResult = [];
|
||||
|
||||
// Copy each file
|
||||
// eslint-disable-next-line guard-for-in, no-restricted-syntax
|
||||
for (const srcFile in files) {
|
||||
const destFile = files[srcFile];
|
||||
const srcPath = Path.join(srcDir, srcFile);
|
||||
const destPath = Path.join(destDir, destFile);
|
||||
|
||||
FsExtra.copySync(srcPath, destPath);
|
||||
filesResult.push(destPath);
|
||||
}
|
||||
|
||||
return filesResult;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method to concatenate some files
|
||||
*
|
||||
* @param {array} files the array of files to be be concatenated
|
||||
* @param {string} output the name of the output file
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const concatFiles = (files, output) => {
|
||||
let tempMem = '';
|
||||
files.forEach((file) => {
|
||||
if (FsExtra.existsSync(`${RootPath}/${file}`)) {
|
||||
tempMem += Fs.readFileSync(`${RootPath}/${file}`);
|
||||
}
|
||||
});
|
||||
|
||||
Fs.writeFileSync(`${RootPath}/${output}`, tempMem);
|
||||
};
|
||||
|
||||
/**
|
||||
* Main method that will copy all vendor files according to Joomla's specs
|
||||
*
|
||||
* @param options The options from setting.json
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
const copyFiles = (options) => {
|
||||
const mediaVendorPath = Path.join(RootPath, 'media/vendor');
|
||||
const registry = {
|
||||
$schema: 'https://developer.joomla.org/schemas/json-schema/web_assets.json',
|
||||
name: options.name,
|
||||
version: options.version,
|
||||
description: options.description,
|
||||
license: options.license,
|
||||
assets: [],
|
||||
};
|
||||
|
||||
if (!FsExtra.existsSync(mediaVendorPath)) {
|
||||
FsExtra.mkdirSync(mediaVendorPath);
|
||||
}
|
||||
|
||||
// Loop to get some text for the packgage.json
|
||||
// eslint-disable-next-line guard-for-in, no-restricted-syntax
|
||||
for (const packageName in options.settings.vendors) {
|
||||
const vendor = options.settings.vendors[packageName];
|
||||
const vendorName = vendor.name || packageName;
|
||||
const modulePathJson = require.resolve(`${packageName}/package.json`);
|
||||
const modulePathRoot = Path.dirname(modulePathJson);
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
const moduleOptions = require(modulePathJson);
|
||||
|
||||
if (packageName === 'codemirror') {
|
||||
const itemvendorPath = Path.join(RootPath, `media/vendor/${packageName}`);
|
||||
if (!FsExtra.existsSync(itemvendorPath)) {
|
||||
FsExtra.mkdirSync(itemvendorPath);
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'addon'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'lib'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'mode'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'keymap'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'theme'));
|
||||
}
|
||||
|
||||
copyAll('addon', 'codemirror', 'addon');
|
||||
copyAll('lib', 'codemirror', 'lib');
|
||||
copyAll('mode', 'codemirror', 'mode');
|
||||
copyAll('keymap', 'codemirror', 'keymap');
|
||||
copyAll('theme', 'codemirror', 'theme');
|
||||
|
||||
concatFiles(
|
||||
[
|
||||
'media/vendor/codemirror/addon/display/autorefresh.js',
|
||||
'media/vendor/codemirror/addon/display/fullscreen.js',
|
||||
'media/vendor/codemirror/addon/display/panel.js',
|
||||
'media/vendor/codemirror/addon/edit/closebrackets.js',
|
||||
'media/vendor/codemirror/addon/edit/closetag.js',
|
||||
'media/vendor/codemirror/addon/edit/matchbrackets.js',
|
||||
'media/vendor/codemirror/addon/edit/matchtags.js',
|
||||
'media/vendor/codemirror/addon/fold/brace-fold.js',
|
||||
'media/vendor/codemirror/addon/fold/foldcode.js',
|
||||
'media/vendor/codemirror/addon/fold/foldgutter.js',
|
||||
'media/vendor/codemirror/addon/fold/xml-fold.js',
|
||||
'media/vendor/codemirror/addon/mode/loadmode.js',
|
||||
'media/vendor/codemirror/addon/mode/multiplex.js',
|
||||
'media/vendor/codemirror/addon/scroll/annotatescrollbar.js',
|
||||
'media/vendor/codemirror/addon/scroll/simplescrollbars.js',
|
||||
'media/vendor/codemirror/addon/scroll/matchesonscrollbar.js',
|
||||
'media/vendor/codemirror/addon/scroll/match-highlighter.js',
|
||||
'media/vendor/codemirror/addon/scroll/searchcursor.js',
|
||||
'media/vendor/codemirror/addon/selection/active-line.js',
|
||||
'media/vendor/codemirror/mode/meta.js',
|
||||
],
|
||||
'media/vendor/codemirror/lib/addons.js',
|
||||
);
|
||||
|
||||
concatFiles(
|
||||
[
|
||||
'media/vendor/codemirror/lib/codemirror.js',
|
||||
'media/vendor/codemirror/lib/addons.js',
|
||||
|
||||
],
|
||||
'media/vendor/codemirror/lib/codemirror-ce.js',
|
||||
);
|
||||
|
||||
concatFiles([
|
||||
'media/vendor/codemirror/addon/display/fullscreen.css',
|
||||
'media/vendor/codemirror/addon/fold/foldgutter.css',
|
||||
'media/vendor/codemirror/addon/search/matchesonscrollbar.css',
|
||||
'media/vendor/codemirror/addon/scroll/simplescrollbars.css',
|
||||
], 'media/vendor/codemirror/lib/addons.css');
|
||||
|
||||
// Update the XML file for Codemirror
|
||||
let codemirrorXml = Fs.readFileSync(`${RootPath}/plugins/editors/codemirror/codemirror.xml`, { encoding: 'UTF-8' });
|
||||
codemirrorXml = codemirrorXml.replace(xmlVersionStr, `$1${moduleOptions.version}$3`);
|
||||
Fs.writeFileSync(`${RootPath}/plugins/editors/codemirror/codemirror.xml`, codemirrorXml, { encoding: 'UTF-8' });
|
||||
} else if (packageName === 'tinymce') {
|
||||
const itemvendorPath = Path.join(RootPath, `media/vendor/${packageName}`);
|
||||
|
||||
if (!FsExtra.existsSync(itemvendorPath)) {
|
||||
FsExtra.mkdirSync(itemvendorPath);
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'icons'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'plugins'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'langs'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'skins'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'themes'));
|
||||
FsExtra.mkdirSync(Path.join(itemvendorPath, 'templates'));
|
||||
}
|
||||
|
||||
copyAll('icons', 'tinymce', 'icons');
|
||||
copyAll('plugins', 'tinymce', 'plugins');
|
||||
copyAll('skins', 'tinymce', 'skins');
|
||||
copyAll('themes', 'tinymce', 'themes');
|
||||
|
||||
copyArrayFiles('', ['tinymce.js', 'tinymce.min.js', 'changelog.txt', 'license.txt'], 'tinymce', '');
|
||||
|
||||
// Update the XML file for tinyMCE
|
||||
let tinyXml = Fs.readFileSync(`${RootPath}/plugins/editors/tinymce/tinymce.xml`, { encoding: 'UTF-8' });
|
||||
tinyXml = tinyXml.replace(xmlVersionStr, `$1${moduleOptions.version}$3`);
|
||||
Fs.writeFileSync(`${RootPath}/plugins/editors/tinymce/tinymce.xml`, tinyXml, { encoding: 'UTF-8' });
|
||||
|
||||
// Remove that sourcemap...
|
||||
let tinyWrongMap = Fs.readFileSync(`${RootPath}/media/vendor/tinymce/skins/ui/oxide/skin.min.css`, { encoding: 'UTF-8' });
|
||||
tinyWrongMap = tinyWrongMap.replace('/*# sourceMappingURL=skin.min.css.map */', '');
|
||||
Fs.writeFileSync(`${RootPath}/media/vendor/tinymce/skins/ui/oxide/skin.min.css`, tinyWrongMap, { encoding: 'UTF-8' });
|
||||
} else {
|
||||
['js', 'css', 'filesExtra'].forEach((type) => {
|
||||
if (!vendor[type]) return;
|
||||
|
||||
const dest = Path.join(mediaVendorPath, vendorName);
|
||||
copyFilesTo(vendor[type], modulePathRoot, dest, type);
|
||||
});
|
||||
|
||||
// Copy the license if exists
|
||||
if (options.settings.vendors[packageName].licenseFilename
|
||||
&& Fs.existsSync(`${Path.join(RootPath, `node_modules/${packageName}`)}/${options.settings.vendors[packageName].licenseFilename}`)
|
||||
) {
|
||||
const dest = Path.join(mediaVendorPath, vendorName);
|
||||
FsExtra.copySync(`${Path.join(RootPath, `node_modules/${packageName}`)}/${options.settings.vendors[packageName].licenseFilename}`, `${dest}/${options.settings.vendors[packageName].licenseFilename}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Joomla's hack to expose the chosen base classes so we can extend it ourselves
|
||||
// (it was better than the many hacks we had before. But I'm still ashamed of myself).
|
||||
if (packageName === 'chosen-js') {
|
||||
const dest = Path.join(mediaVendorPath, vendorName);
|
||||
const chosenPath = `${dest}/${options.settings.vendors[packageName].js['chosen.jquery.js']}`;
|
||||
let ChosenJs = Fs.readFileSync(chosenPath, { encoding: 'UTF-8' });
|
||||
ChosenJs = ChosenJs.replace('}).call(this);', ' document.AbstractChosen = AbstractChosen;\n'
|
||||
+ ' document.Chosen = Chosen;\n'
|
||||
+ '}).call(this);');
|
||||
Fs.writeFileSync(chosenPath, ChosenJs, { encoding: 'UTF-8' });
|
||||
}
|
||||
|
||||
// Append initialising code to the end of the Short-and-Sweet javascript
|
||||
if (packageName === 'short-and-sweet') {
|
||||
const dest = Path.join(mediaVendorPath, vendorName);
|
||||
const shortandsweetPath = `${dest}/${options.settings.vendors[packageName].js['dist/short-and-sweet.min.js']}`;
|
||||
let ShortandsweetJs = Fs.readFileSync(shortandsweetPath, { encoding: 'UTF-8' });
|
||||
ShortandsweetJs = ShortandsweetJs.concat('document.addEventListener(\'DOMContentLoaded\', function()'
|
||||
+ '{shortAndSweet(\'textarea.charcount\', {counterClassName: \'small text-muted\'}); });');
|
||||
Fs.writeFileSync(shortandsweetPath, ShortandsweetJs, { encoding: 'UTF-8' });
|
||||
}
|
||||
|
||||
// Add provided Assets to a registry, if any
|
||||
if (vendor.provideAssets && vendor.provideAssets.length) {
|
||||
vendor.provideAssets.forEach((assetInfo) => {
|
||||
const registryItemBase = {
|
||||
package: packageName,
|
||||
name: assetInfo.name || vendorName,
|
||||
version: moduleOptions.version,
|
||||
type: assetInfo.type,
|
||||
};
|
||||
|
||||
const registryItem = Object.assign(assetInfo, registryItemBase);
|
||||
|
||||
// Update path to file
|
||||
if (assetInfo.uri && (assetInfo.type === 'script' || assetInfo.type === 'style' || assetInfo.type === 'webcomponent')) {
|
||||
let itemPath = assetInfo.uri;
|
||||
|
||||
// Check for external path
|
||||
if (itemPath.indexOf('http://') !== 0 && itemPath.indexOf('https://') !== 0 && itemPath.indexOf('//') !== 0) {
|
||||
itemPath = `vendor/${vendorName}/${itemPath}`;
|
||||
}
|
||||
|
||||
registryItem.uri = itemPath;
|
||||
}
|
||||
|
||||
registry.assets.push(registryItem);
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${packageName} was updated.`);
|
||||
}
|
||||
|
||||
// Write assets registry
|
||||
Fs.writeFileSync(
|
||||
Path.join(mediaVendorPath, 'joomla.asset.json'),
|
||||
JSON.stringify(registry, null, 2),
|
||||
{ encoding: 'UTF-8' },
|
||||
);
|
||||
|
||||
// Restore our code on the vendor folders
|
||||
FsExtra.copySync(Path.join(RootPath, 'build/media_source/vendor/tinymce/templates'), Path.join(RootPath, 'media/vendor/tinymce/templates'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Method to recreate the basic media folder structure
|
||||
* After execution the media folder is populated with empty js and css subdirectories
|
||||
* images subfolders with the relative files
|
||||
* any other files except .js, .css, .scss
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const recreateMediaFolder = () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Recreating the media folder...');
|
||||
|
||||
Copydir.sync(Path.join(RootPath, 'build/media_source'), Path.join(RootPath, 'media'), (stat, filepath, filename) => {
|
||||
if (stat === 'file' && filename.match(/\.(es6\.js|es5\.js|scss)$/)) {
|
||||
return false;
|
||||
}
|
||||
if (stat === 'directory' && filename.match(/^(core\.es6|scss)$/)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, (err) => {
|
||||
if (!err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Legacy media files restored');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.copyAssets = (options) => {
|
||||
Promise.resolve()
|
||||
// Copy a fresh version of the files
|
||||
.then(cleanVendors())
|
||||
|
||||
// Copy a fresh version of the files
|
||||
.then(recreateMediaFolder())
|
||||
|
||||
// Copy a fresh version of the files
|
||||
.then(copyFiles(options))
|
||||
|
||||
// Handle errors
|
||||
.catch((error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
38
build/build-modules-js/init/cleanup-media.es6.js
Normal file
38
build/build-modules-js/init/cleanup-media.es6.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
const {
|
||||
stat, mkdir, copy, remove,
|
||||
} = require('fs-extra');
|
||||
const { join } = require('path');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
* Method that will erase the media/vendor folder
|
||||
* and populate the debugbar assets
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.cleanVendors = async () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Cleanup the Vendor ');
|
||||
|
||||
const mediaFolder = await stat(join(RootPath, 'libraries/vendor/maximebf/debugbar/src/DebugBar/Resources'));
|
||||
|
||||
if (await mediaFolder.isDirectory()) {
|
||||
// Remove the vendor folder
|
||||
// await remove(join(RootPath, 'media'));
|
||||
// eslint-disable-next-line no-console
|
||||
// console.error('/media has been removed.');
|
||||
|
||||
// Recreate the media folder
|
||||
await mkdir(join(RootPath, 'media/vendor/debugbar'), { recursive: true });
|
||||
|
||||
// Copy some assets from a PHP package
|
||||
await copy(join(RootPath, 'libraries/vendor/maximebf/debugbar/src/DebugBar/Resources'), join(RootPath, 'media/vendor/debugbar'));
|
||||
await remove(join(RootPath, 'media/vendor/debugbar/vendor/font-awesome'));
|
||||
await remove(join(RootPath, 'media/vendor/debugbar/vendor/jquery'));
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('You need to run `npm install` AFTER the command `composer install`!!!. The debug plugin HASN\'T installed all its front end assets');
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
26
build/build-modules-js/init/common/concat-files.es6.js
Normal file
26
build/build-modules-js/init/common/concat-files.es6.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
const { readFile, writeFile, existsSync } = require('fs-extra');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
* Method to concatenate some files
|
||||
*
|
||||
* @param {array} files the array of files to be be concatenated
|
||||
* @param {string} output the name of the output file
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.concatFiles = async (files, output) => {
|
||||
const promises = [];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const file of files) {
|
||||
if (existsSync(`${RootPath}/${file}`)) {
|
||||
promises.push(readFile(`${RootPath}/${file}`, { encoding: 'utf8' }));
|
||||
}
|
||||
}
|
||||
|
||||
const res = await Promise.all(promises);
|
||||
|
||||
await writeFile(`${RootPath}/${output}`, res.join(' '));
|
||||
};
|
19
build/build-modules-js/init/common/copy-all-files.es6.js
Normal file
19
build/build-modules-js/init/common/copy-all-files.es6.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
const { copy } = require('fs-extra');
|
||||
const { join } = require('path');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
* Copies all the files from a directory
|
||||
*
|
||||
* @param {string} dirName the name of the source folder
|
||||
* @param {string} name the name of the destination folder
|
||||
* @param {string} type the type of the folder, eg: js, css, fonts, images
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
module.exports.copyAllFiles = async (dirName, name, type) => {
|
||||
const folderName = dirName === '/' ? '/' : `/${dirName}`;
|
||||
await copy(join(RootPath, `node_modules/${name}/${folderName}`),
|
||||
join(RootPath, `media/vendor/${name.replace(/.+\//, '')}/${type}`));
|
||||
};
|
78
build/build-modules-js/init/exemptions/codemirror.es6.js
Normal file
78
build/build-modules-js/init/exemptions/codemirror.es6.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
const {
|
||||
existsSync, readFile, writeFile, mkdir,
|
||||
} = require('fs-extra');
|
||||
const { join } = require('path');
|
||||
|
||||
const { concatFiles } = require('../common/concat-files.es6.js');
|
||||
const { copyAllFiles } = require('../common/copy-all-files.es6.js');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
const xmlVersionStr = /(<version>)(.+)(<\/version>)/;
|
||||
|
||||
/**
|
||||
* Codemirror needs special treatment
|
||||
*/
|
||||
module.exports.codeMirror = async (packageName, version) => {
|
||||
const itemvendorPath = join(RootPath, `media/vendor/${packageName}`);
|
||||
if (!await existsSync(itemvendorPath)) {
|
||||
await mkdir(itemvendorPath, { recursive: true });
|
||||
await mkdir(join(itemvendorPath, 'addon'));
|
||||
await mkdir(join(itemvendorPath, 'lib'));
|
||||
await mkdir(join(itemvendorPath, 'mode'));
|
||||
await mkdir(join(itemvendorPath, 'keymap'));
|
||||
await mkdir(join(itemvendorPath, 'theme'));
|
||||
}
|
||||
|
||||
await copyAllFiles('addon', 'codemirror', 'addon');
|
||||
await copyAllFiles('lib', 'codemirror', 'lib');
|
||||
await copyAllFiles('mode', 'codemirror', 'mode');
|
||||
await copyAllFiles('keymap', 'codemirror', 'keymap');
|
||||
await copyAllFiles('theme', 'codemirror', 'theme');
|
||||
|
||||
await concatFiles(
|
||||
[
|
||||
'media/vendor/codemirror/addon/display/fullscreen.js',
|
||||
'media/vendor/codemirror/addon/display/panel.js',
|
||||
'media/vendor/codemirror/addon/edit/closebrackets.js',
|
||||
'media/vendor/codemirror/addon/edit/closetag.js',
|
||||
'media/vendor/codemirror/addon/edit/matchbrackets.js',
|
||||
'media/vendor/codemirror/addon/edit/matchtags.js',
|
||||
'media/vendor/codemirror/addon/fold/brace-fold.js',
|
||||
'media/vendor/codemirror/addon/fold/foldcode.js',
|
||||
'media/vendor/codemirror/addon/fold/foldgutter.js',
|
||||
'media/vendor/codemirror/addon/fold/xml-fold.js',
|
||||
'media/vendor/codemirror/addon/mode/loadmode.js',
|
||||
'media/vendor/codemirror/addon/mode/multiplex.js',
|
||||
'media/vendor/codemirror/addon/scroll/annotatescrollbar.js',
|
||||
'media/vendor/codemirror/addon/scroll/simplescrollbars.js',
|
||||
'media/vendor/codemirror/addon/scroll/matchesonscrollbar.js',
|
||||
'media/vendor/codemirror/addon/scroll/match-highlighter.js',
|
||||
'media/vendor/codemirror/addon/scroll/searchcursor.js',
|
||||
'media/vendor/codemirror/addon/selection/active-line.js',
|
||||
'media/vendor/codemirror/mode/meta.js',
|
||||
],
|
||||
'media/vendor/codemirror/lib/addons.js',
|
||||
);
|
||||
|
||||
await concatFiles(
|
||||
[
|
||||
'media/vendor/codemirror/lib/codemirror.js',
|
||||
'media/vendor/codemirror/lib/addons.js',
|
||||
],
|
||||
|
||||
'media/vendor/codemirror/lib/codemirror-ce.js',
|
||||
);
|
||||
|
||||
await concatFiles([
|
||||
'media/vendor/codemirror/addon/display/fullscreen.css',
|
||||
'media/vendor/codemirror/addon/fold/foldgutter.css',
|
||||
'media/vendor/codemirror/addon/search/matchesonscrollbar.css',
|
||||
'media/vendor/codemirror/addon/scroll/simplescrollbars.css',
|
||||
],
|
||||
'media/vendor/codemirror/lib/addons.css');
|
||||
|
||||
// Update the XML file for Codemirror
|
||||
let codemirrorXml = await readFile(`${RootPath}/plugins/editors/codemirror/codemirror.xml`, { encoding: 'utf8' });
|
||||
codemirrorXml = codemirrorXml.replace(xmlVersionStr, `$1${version}$3`);
|
||||
await writeFile(`${RootPath}/plugins/editors/codemirror/codemirror.xml`, codemirrorXml, { encoding: 'utf8' });
|
||||
};
|
70
build/build-modules-js/init/exemptions/tinymce.es6.js
Normal file
70
build/build-modules-js/init/exemptions/tinymce.es6.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
const {
|
||||
existsSync, copy, readFile, writeFile, mkdir,
|
||||
} = require('fs-extra');
|
||||
const { join } = require('path');
|
||||
|
||||
const { copyAllFiles } = require('../common/copy-all-files.es6.js');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
const xmlVersionStr = /(<version>)(.+)(<\/version>)/;
|
||||
|
||||
/**
|
||||
* Copies an array of files from a directory
|
||||
*
|
||||
* @param {string} dirName the name of the source folder
|
||||
* @param {array} files the array of files to be be copied
|
||||
* @param {string} name the name of the destination folder
|
||||
* @param {string} type the type of the folder, eg: js, css, fonts, images
|
||||
*
|
||||
* @returns { void }
|
||||
*/
|
||||
const copyArrayFiles = async (dirName, files, name, type) => {
|
||||
const promises = [];
|
||||
// eslint-disable-next-line guard-for-in,no-restricted-syntax
|
||||
for (const file of files) {
|
||||
const folderName = dirName === '/' ? '/' : `/${dirName}/`;
|
||||
|
||||
if (existsSync(`node_modules/${name}${folderName}${file}`)) {
|
||||
promises.push(copy(`node_modules/${name}${folderName}${file}`, `media/vendor/${name.replace(/.+\//, '')}${type ? `/${type}` : ''}/${file}`));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
};
|
||||
|
||||
/**
|
||||
* tinyMCE needs special treatment
|
||||
*/
|
||||
module.exports.tinyMCE = async (packageName, version) => {
|
||||
const itemvendorPath = join(RootPath, `media/vendor/${packageName}`);
|
||||
|
||||
if (!await existsSync(itemvendorPath)) {
|
||||
await mkdir(itemvendorPath);
|
||||
await mkdir(join(itemvendorPath, 'icons'));
|
||||
await mkdir(join(itemvendorPath, 'plugins'));
|
||||
await mkdir(join(itemvendorPath, 'langs'));
|
||||
await mkdir(join(itemvendorPath, 'skins'));
|
||||
await mkdir(join(itemvendorPath, 'themes'));
|
||||
await mkdir(join(itemvendorPath, 'templates'));
|
||||
}
|
||||
|
||||
await copyAllFiles('icons', 'tinymce', 'icons');
|
||||
await copyAllFiles('plugins', 'tinymce', 'plugins');
|
||||
await copyAllFiles('skins', 'tinymce', 'skins');
|
||||
await copyAllFiles('themes', 'tinymce', 'themes');
|
||||
|
||||
await copyArrayFiles('', ['tinymce.js', 'tinymce.min.js', 'changelog.txt', 'license.txt'], 'tinymce', '');
|
||||
|
||||
// Update the XML file for tinyMCE
|
||||
let tinyXml = await readFile(`${RootPath}/plugins/editors/tinymce/tinymce.xml`, { encoding: 'utf8' });
|
||||
tinyXml = tinyXml.replace(xmlVersionStr, `$1${version}$3`);
|
||||
await writeFile(`${RootPath}/plugins/editors/tinymce/tinymce.xml`, tinyXml, { encoding: 'utf8' });
|
||||
|
||||
// Remove that sourcemap...
|
||||
let tinyWrongMap = await readFile(`${RootPath}/media/vendor/tinymce/skins/ui/oxide/skin.min.css`, { encoding: 'utf8' });
|
||||
tinyWrongMap = tinyWrongMap.replace('/*# sourceMappingURL=skin.min.css.map */', '');
|
||||
await writeFile(`${RootPath}/media/vendor/tinymce/skins/ui/oxide/skin.min.css`, tinyWrongMap, { encoding: 'utf8' });
|
||||
|
||||
// Restore our code on the vendor folders
|
||||
await copy(join(RootPath, 'build/media_source/vendor/tinymce/templates'), join(RootPath, 'media/vendor/tinymce/templates'));
|
||||
};
|
149
build/build-modules-js/init/localise-packages.es6.js
Normal file
149
build/build-modules-js/init/localise-packages.es6.js
Normal file
|
@ -0,0 +1,149 @@
|
|||
const {
|
||||
existsSync, copy, writeFile, mkdir, mkdirs, ensureDir,
|
||||
} = require('fs-extra');
|
||||
const { dirname, join } = require('path');
|
||||
const { codeMirror } = require('./exemptions/codemirror.es6.js');
|
||||
const { tinyMCE } = require('./exemptions/tinymce.es6.js');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} files the object of files map, eg {"src.js": "js/src.js"}
|
||||
* @param {string} srcDir the name of the package root dir
|
||||
* @param {string} destDir the name of the Vendor destination dir
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const copyFilesTo = async (files, srcDir, destDir) => {
|
||||
const copyPromises = [];
|
||||
|
||||
async function doTheCopy(source, dest) {
|
||||
await ensureDir(dirname(dest));
|
||||
await copy(source, dest);
|
||||
}
|
||||
|
||||
// Copy each file
|
||||
// eslint-disable-next-line no-restricted-syntax,guard-for-in
|
||||
for (const srcFile in files) {
|
||||
copyPromises.push(doTheCopy(join(srcDir, srcFile), join(destDir, files[srcFile])));
|
||||
}
|
||||
|
||||
return Promise.all(copyPromises);
|
||||
};
|
||||
|
||||
/**
|
||||
* Main method that will resolve each vendor package
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const resolvePackage = async (vendor, packageName, mediaVendorPath, options, registry) => {
|
||||
const vendorName = vendor.name || packageName;
|
||||
const modulePathJson = require.resolve(`${packageName}/package.json`);
|
||||
const modulePathRoot = dirname(modulePathJson);
|
||||
// eslint-disable-next-line global-require, import/no-dynamic-require
|
||||
const moduleOptions = require(modulePathJson);
|
||||
|
||||
const promises = [];
|
||||
|
||||
if (packageName === 'codemirror') {
|
||||
promises.push(codeMirror(packageName, moduleOptions.version));
|
||||
} else if (packageName === 'tinymce') {
|
||||
promises.push(tinyMCE(packageName, moduleOptions.version));
|
||||
} else {
|
||||
await mkdirs(join(mediaVendorPath, vendorName));
|
||||
|
||||
['js', 'css', 'filesExtra'].forEach((type) => {
|
||||
if (!vendor[type]) return;
|
||||
|
||||
promises.push(
|
||||
copyFilesTo(vendor[type], modulePathRoot, join(mediaVendorPath, vendorName), type),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Copy the license if existsSync
|
||||
if (options.settings.vendors[packageName].licenseFilename
|
||||
&& await existsSync(`${join(RootPath, `node_modules/${packageName}`)}/${options.settings.vendors[packageName].licenseFilename}`)
|
||||
) {
|
||||
const dest = join(mediaVendorPath, vendorName);
|
||||
await copy(
|
||||
`${join(RootPath, `node_modules/${packageName}`)}/${options.settings.vendors[packageName].licenseFilename}`,
|
||||
`${dest}/${options.settings.vendors[packageName].licenseFilename}`,
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
// Add provided Assets to a registry, if any
|
||||
if (vendor.provideAssets && vendor.provideAssets.length) {
|
||||
vendor.provideAssets.forEach((assetInfo) => {
|
||||
const registryItemBase = {
|
||||
package: packageName,
|
||||
name: assetInfo.name || vendorName,
|
||||
version: moduleOptions.version,
|
||||
type: assetInfo.type,
|
||||
};
|
||||
|
||||
const registryItem = Object.assign(assetInfo, registryItemBase);
|
||||
|
||||
// Update path to file
|
||||
if (assetInfo.uri && (assetInfo.type === 'script' || assetInfo.type === 'style' || assetInfo.type === 'webcomponent')) {
|
||||
let itemPath = assetInfo.uri;
|
||||
|
||||
// Check for external path
|
||||
if (itemPath.indexOf('http://') !== 0 && itemPath.indexOf('https://') !== 0 && itemPath.indexOf('//') !== 0) {
|
||||
itemPath = `vendor/${vendorName}/${itemPath}`;
|
||||
}
|
||||
|
||||
registryItem.uri = itemPath;
|
||||
}
|
||||
|
||||
registry.assets.push(registryItem);
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`${packageName} was updated.`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Main method that will copy all vendor files according to Joomla's specs
|
||||
*
|
||||
* @param options The options from setting.json
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.localisePackages = async (options) => {
|
||||
const mediaVendorPath = join(RootPath, 'media/vendor');
|
||||
const registry = {
|
||||
$schema: 'https://developer.joomla.org/schemas/json-schema/web_assets.json',
|
||||
name: options.name,
|
||||
version: options.version,
|
||||
description: options.description,
|
||||
license: options.license,
|
||||
assets: [],
|
||||
};
|
||||
const promises = [];
|
||||
|
||||
if (!await existsSync(mediaVendorPath)) {
|
||||
await mkdir(mediaVendorPath, { recursive: true });
|
||||
}
|
||||
|
||||
// Loop to get some text for the packgage.json
|
||||
// eslint-disable-next-line guard-for-in, no-restricted-syntax
|
||||
for (const packageName in options.settings.vendors) {
|
||||
const vendor = options.settings.vendors[packageName];
|
||||
|
||||
promises.push(resolvePackage(vendor, packageName, mediaVendorPath, options, registry));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
// Write assets registry
|
||||
await writeFile(
|
||||
join(mediaVendorPath, 'joomla.asset.json'),
|
||||
JSON.stringify(registry, null, 2),
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
};
|
103
build/build-modules-js/init/minify-vendor.es6.js
Normal file
103
build/build-modules-js/init/minify-vendor.es6.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
const { lstat, readFile, writeFile } = require('fs-extra');
|
||||
const { sep } = require('path');
|
||||
const recursive = require('recursive-readdir');
|
||||
const { minify } = require('terser');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
const folders = [
|
||||
'media/vendor/accessibility/js',
|
||||
'media/vendor/chosen/js',
|
||||
'media/vendor/codemirror',
|
||||
'media/vendor/debugbar',
|
||||
'media/vendor/punycode/js',
|
||||
'media/vendor/qrcode/js',
|
||||
'media/vendor/short-and-sweet/js',
|
||||
'media/vendor/webcomponentsjs/js',
|
||||
];
|
||||
|
||||
let allFiles = [];
|
||||
|
||||
const noMinified = [
|
||||
'media/vendor/accessibility/js/accessibility.min.js',
|
||||
'media/vendor/short-and-sweet/js/short-and-sweet.min.js',
|
||||
];
|
||||
|
||||
const alreadyMinified = [
|
||||
'media/vendor/webcomponentsjs/js/webcomponents-ce.js',
|
||||
'media/vendor/webcomponentsjs/js/webcomponents-sd.js',
|
||||
'media/vendor/webcomponentsjs/js/webcomponents-sd-ce.js',
|
||||
'media/vendor/webcomponentsjs/js/webcomponents-sd-ce-pf.js',
|
||||
];
|
||||
|
||||
/**
|
||||
* Check if a file exists
|
||||
*
|
||||
* @param file
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
const minifiedExists = async (file) => {
|
||||
try {
|
||||
return (await lstat(file)).isFile();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} file
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const minifyJS = async (file) => {
|
||||
const needsDotJS = noMinified.includes(file.replace(`${RootPath}${sep}`, ''));
|
||||
if (file.endsWith('.min.js') && !needsDotJS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Processing Vendor file: ${file}`);
|
||||
|
||||
let minified;
|
||||
const fileExists = await minifiedExists(file);
|
||||
if (!fileExists) {
|
||||
return;
|
||||
}
|
||||
|
||||
const content = await readFile(file, { encoding: 'utf8' });
|
||||
|
||||
const isMinified = alreadyMinified.includes(file.replace(`${RootPath}${sep}`, ''));
|
||||
if (isMinified || needsDotJS) {
|
||||
minified = content;
|
||||
} else {
|
||||
minified = (await minify(content, { sourceMap: false, format: { comments: false } })).code;
|
||||
}
|
||||
|
||||
const newFile = needsDotJS ? file.replace('.min.js', '.js') : file.replace('.js', '.min.js');
|
||||
// Write the file
|
||||
await writeFile(
|
||||
newFile,
|
||||
minified,
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Method that will minify a set of vendor javascript files
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.minifyVendor = async () => {
|
||||
// return;
|
||||
const folderPromises = [];
|
||||
const filesPromises = [];
|
||||
|
||||
folders.map((folder) => folderPromises.push(recursive(folder, ['!*.+(js)'])));
|
||||
|
||||
const computedFiles = await Promise.all(folderPromises);
|
||||
allFiles = [...allFiles, ...[].concat(...computedFiles)];
|
||||
allFiles.map((file) => filesPromises.push(minifyJS(file)));
|
||||
|
||||
return Promise.all(filesPromises);
|
||||
};
|
33
build/build-modules-js/init/patches.es6.js
Normal file
33
build/build-modules-js/init/patches.es6.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
const { readFile, writeFile } = require('fs-extra');
|
||||
const { join } = require('path');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
* Main method that will patch files...
|
||||
*
|
||||
* @param options The options from setting.json
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.patchPackages = async (options) => {
|
||||
const mediaVendorPath = join(RootPath, 'media/vendor');
|
||||
|
||||
// Joomla's hack to expose the chosen base classes so we can extend it ourselves
|
||||
// (it was better than the many hacks we had before. But I'm still ashamed of myself).
|
||||
let dest = join(mediaVendorPath, 'chosen');
|
||||
const chosenPath = `${dest}/${options.settings.vendors['chosen-js'].js['chosen.jquery.js']}`;
|
||||
let ChosenJs = await readFile(chosenPath, { encoding: 'utf8' });
|
||||
ChosenJs = ChosenJs.replace('}).call(this);', ` document.AbstractChosen = AbstractChosen;
|
||||
document.Chosen = Chosen;
|
||||
}).call(this);`);
|
||||
await writeFile(chosenPath, ChosenJs, { encoding: 'utf8' });
|
||||
|
||||
// Append initialising code to the end of the Short-and-Sweet javascript
|
||||
dest = join(mediaVendorPath, 'short-and-sweet');
|
||||
const shortandsweetPath = `${dest}/${options.settings.vendors['short-and-sweet'].js['dist/short-and-sweet.min.js']}`;
|
||||
let ShortandsweetJs = await readFile(shortandsweetPath, { encoding: 'utf8' });
|
||||
ShortandsweetJs = ShortandsweetJs.concat('document.addEventListener(\'DOMContentLoaded\', function()'
|
||||
+ '{shortAndSweet(\'textarea.charcount\', {counterClassName: \'small text-muted\'}); });');
|
||||
await writeFile(shortandsweetPath, ShortandsweetJs, { encoding: 'utf8' });
|
||||
};
|
31
build/build-modules-js/init/recreate-media.es6.js
Normal file
31
build/build-modules-js/init/recreate-media.es6.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const { stat, copy } = require('fs-extra');
|
||||
const { join, extname } = require('path');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
* Method to recreate the basic media folder structure
|
||||
* After execution the media folder is populated with empty js and css subdirectories
|
||||
* images subfolders with their relative files and any other files except .js, .css
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
module.exports.recreateMediaFolder = async () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Recreating the media folder...');
|
||||
|
||||
const filterFunc = async (src) => {
|
||||
const fileStat = await stat(src);
|
||||
if (fileStat.isDirectory() && src.endsWith('core.es6')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileStat.isFile() && (extname(src) === '.js' || extname(src) === '.css')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
await copy(join(RootPath, 'build/media_source'), join(RootPath, 'media'), { filter: filterFunc });
|
||||
};
|
|
@ -1,36 +1,53 @@
|
|||
const { writeFile } = require('fs').promises;
|
||||
const Babel = require('@babel/core');
|
||||
const Fs = require('fs');
|
||||
const FsExtra = require('fs-extra');
|
||||
const Path = require('path');
|
||||
const { dirname } = require('path');
|
||||
const { minify } = require('terser');
|
||||
|
||||
/**
|
||||
* Create the minified file as well
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* @param fileName {string}
|
||||
* @param data {string}
|
||||
*/
|
||||
const createMinified = async (fileName, data) => {
|
||||
const mini = await minify(data, { sourceMap: false, format: { comments: false } });
|
||||
await writeFile(fileName, mini.code, { encoding: 'utf8' });
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fileContents the content of the file to be transpiled
|
||||
* @param settings the settings for the transpiler
|
||||
* @param output the full pat + filename + extension of the trnspiled file
|
||||
* @param output the full pat + filename + extension of the transpiled file
|
||||
*/
|
||||
module.exports.run = (fileContents, settings, output) => {
|
||||
Babel.transform(fileContents, settings, (error, result) => {
|
||||
if (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
module.exports.BabelTransform = async (fileContents, settings, output) => {
|
||||
let transformedData;
|
||||
|
||||
// Ensure the folder exists or create it
|
||||
FsExtra.mkdirsSync(Path.dirname(output), {});
|
||||
try {
|
||||
transformedData = await Babel.transform(fileContents, settings);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Fs.writeFile(
|
||||
output,
|
||||
result.code, // + os.EOL
|
||||
{ encoding: 'utf8' },
|
||||
(fsError) => {
|
||||
if (fsError) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${fsError}`);
|
||||
process.exit(1);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
// Ensure the folder exists or create it
|
||||
await FsExtra.ensureDir(dirname(output), {});
|
||||
|
||||
await writeFile(
|
||||
output,
|
||||
transformedData.code, // + os.EOL
|
||||
{ encoding: 'utf8' },
|
||||
(fsError) => {
|
||||
if (fsError) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${fsError}`);
|
||||
process.exit(1);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await createMinified(output.replace('.js', '.min.js'), transformedData.code);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const {
|
||||
readdir, readFile, rename, writeFile, unlink,
|
||||
readdir, readFile, writeFile, unlink,
|
||||
} = require('fs').promises;
|
||||
const { resolve } = require('path');
|
||||
const { minify } = require('terser');
|
||||
|
@ -13,11 +13,13 @@ const tasks = [];
|
|||
const inputFolder = 'build/media_source/vendor/bootstrap/js';
|
||||
const outputFolder = 'media/vendor/bootstrap/js';
|
||||
|
||||
const getCurrentUnixTime = Math.round((new Date()).getTime() / 1000);
|
||||
|
||||
const createMinified = async (file) => {
|
||||
const initial = await readFile(resolve(outputFolder, file), { encoding: 'utf8' });
|
||||
const mini = await minify(initial);
|
||||
await rename(resolve(outputFolder, file), resolve(outputFolder, `${file.split('-')[0]}.es6.js`));
|
||||
await writeFile(resolve(outputFolder, `${file.split('-')[0]}.es6.min.js`), mini.code, { encoding: 'utf8' });
|
||||
const mini = await minify(initial.replace('./popper.js', `./popper.min.js?${getCurrentUnixTime}`).replace('./dom.js', `./dom.min.js?${getCurrentUnixTime}`), { sourceMap: false, format: { comments: false } });
|
||||
await writeFile(resolve(outputFolder, file), initial.replace('./popper.js', `./popper.js?${getCurrentUnixTime}`).replace('./dom.js', `./dom.js?${getCurrentUnixTime}`), { encoding: 'utf8' });
|
||||
await writeFile(resolve(outputFolder, file.replace('.js', '.min.js')), mini.code, { encoding: 'utf8' });
|
||||
};
|
||||
|
||||
const build = async () => {
|
||||
|
@ -67,7 +69,11 @@ const build = async () => {
|
|||
format: 'es',
|
||||
sourcemap: false,
|
||||
dir: outputFolder,
|
||||
chunkFileNames: '[name].js',
|
||||
});
|
||||
|
||||
// closes the bundle
|
||||
await bundle.close();
|
||||
};
|
||||
|
||||
const buildLegacy = async () => {
|
||||
|
@ -110,11 +116,14 @@ const buildLegacy = async () => {
|
|||
format: 'iife',
|
||||
sourcemap: false,
|
||||
name: 'Bootstrap',
|
||||
file: resolve(outputFolder, 'bootstrap.es5.js'),
|
||||
file: resolve(outputFolder, 'bootstrap-es5.js'),
|
||||
});
|
||||
|
||||
// closes the bundle
|
||||
await bundle.close();
|
||||
};
|
||||
|
||||
(async () => {
|
||||
module.exports.bootstrapJs = async () => {
|
||||
rimraf.sync(resolve(outputFolder));
|
||||
|
||||
try {
|
||||
|
@ -142,9 +151,9 @@ const buildLegacy = async () => {
|
|||
|
||||
try {
|
||||
await buildLegacy(inputFolder, 'index.es6.js');
|
||||
const es5File = await readFile(resolve(outputFolder, 'bootstrap.es5.js'), { encoding: 'utf8' });
|
||||
const mini = await minify(es5File);
|
||||
await writeFile(resolve(outputFolder, 'bootstrap.es5.min.js'), mini.code, { encoding: 'utf8' });
|
||||
const es5File = await readFile(resolve(outputFolder, 'bootstrap-es5.js'), { encoding: 'utf8' });
|
||||
const mini = await minify(es5File, { sourceMap: false, format: { comments: false } });
|
||||
await writeFile(resolve(outputFolder, 'bootstrap-es5.min.js'), mini.code, { encoding: 'utf8' });
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Legacy done! ✅');
|
||||
} catch (error) {
|
||||
|
@ -152,4 +161,4 @@ const buildLegacy = async () => {
|
|||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
};
|
|
@ -1,11 +1,25 @@
|
|||
const Fs = require('fs');
|
||||
const Path = require('path');
|
||||
const FsExtra = require('fs-extra');
|
||||
const Babel = require('./babel-transform.es6.js');
|
||||
const { lstat, readdir, readFile } = require('fs').promises;
|
||||
const { dirname, sep } = require('path');
|
||||
const { ensureDir } = require('fs-extra');
|
||||
const { BabelTransform } = require('./babel-transform.es6.js');
|
||||
|
||||
const headerText = `PLEASE DO NOT MODIFY THIS FILE. WORK ON THE ES6 VERSION.
|
||||
OTHERWISE YOUR CHANGES WILL BE REPLACED ON THE NEXT BUILD.`;
|
||||
|
||||
/**
|
||||
* Check if a file exists
|
||||
*
|
||||
* @param file
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
const folderExists = async (folder) => {
|
||||
try {
|
||||
return (await lstat(folder)).isDirectory();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Predefine some settings
|
||||
const settings = [
|
||||
{
|
||||
|
@ -23,21 +37,6 @@ const settings = [
|
|||
],
|
||||
comments: true,
|
||||
},
|
||||
{
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: ['ie 11'],
|
||||
},
|
||||
modules: false,
|
||||
}],
|
||||
['minify', { builtIns: false }],
|
||||
],
|
||||
plugins: [
|
||||
['@babel/plugin-transform-classes'],
|
||||
],
|
||||
comments: false,
|
||||
},
|
||||
{
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
|
@ -52,19 +51,6 @@ const settings = [
|
|||
],
|
||||
comments: true,
|
||||
},
|
||||
{
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: ['> 5%', 'not ie 11'],
|
||||
},
|
||||
modules: false,
|
||||
}],
|
||||
['minify', { builtIns: false }],
|
||||
],
|
||||
plugins: [],
|
||||
comments: false,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -72,48 +58,44 @@ const settings = [
|
|||
*
|
||||
* @param file the full path to the file + filename + extension
|
||||
*/
|
||||
module.exports.compileFile = (file) => {
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
const filePath = file.slice(0, -7);
|
||||
module.exports.handleESMFile = async (file) => {
|
||||
const filePath = file.slice(0, -7);
|
||||
const newPath = filePath.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`);
|
||||
const outputFiles = [
|
||||
`${newPath}.js`,
|
||||
`${newPath}.es6.js`,
|
||||
];
|
||||
|
||||
const outputFiles = [
|
||||
`${filePath.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\')}.js`,
|
||||
`${filePath.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\')}.min.js`,
|
||||
`${filePath.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\')}.es6.js`,
|
||||
`${filePath.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\')}.es6.min.js`,
|
||||
];
|
||||
// Ensure that the directories exist or create them
|
||||
ensureDir(dirname(file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`)));
|
||||
|
||||
// Ensure that the directories exist or create them
|
||||
FsExtra.mkdirsSync(Path.dirname(file).replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\'), {});
|
||||
// Get the contents of the ES-XXXX file
|
||||
let es6File = await readFile(file, { encoding: 'utf8' });
|
||||
const es6FileAsync = [];
|
||||
const es6Subdir = file.replace('es6.js', 'es6');
|
||||
const coreWeirdFolderExists = await folderExists(es6Subdir);
|
||||
|
||||
// Get the contents of the ES-XXXX file
|
||||
let es6File = Fs.readFileSync(file, 'utf8');
|
||||
const es6Subdir = file.replace('es6.js', 'es6');
|
||||
if (coreWeirdFolderExists) {
|
||||
const allCorefilesPromises = [];
|
||||
const concatenateFileContents = async (es6SubFile) => {
|
||||
es6FileAsync.push(await readFile(`${es6Subdir}/${es6SubFile}`, { encoding: 'utf8' }));
|
||||
};
|
||||
const es6SubFiles = await readdir(es6Subdir);
|
||||
es6SubFiles.sort();
|
||||
es6SubFiles.map((es6SubFile) => allCorefilesPromises.push(concatenateFileContents(es6SubFile)));
|
||||
await Promise.all(allCorefilesPromises);
|
||||
}
|
||||
|
||||
if (Fs.existsSync(es6Subdir)) {
|
||||
const stats = Fs.lstatSync(es6Subdir);
|
||||
if (es6FileAsync.length) {
|
||||
es6File += es6FileAsync.join('');
|
||||
}
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
const es6SubFiles = Fs.readdirSync(es6Subdir);
|
||||
es6SubFiles.sort();
|
||||
es6SubFiles.forEach((es6SubFile) => {
|
||||
es6File += Fs.readFileSync(`${es6Subdir}/${es6SubFile}`, 'utf8');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
settings.forEach((setting, index) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`Transpiling ES6 file: ${file}`);
|
||||
Babel.run(es6File, setting, outputFiles[index]);
|
||||
});
|
||||
})
|
||||
|
||||
// Handle errors
|
||||
.catch((error) => {
|
||||
const jobs = [];
|
||||
settings.forEach((setting, index) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
});
|
||||
console.error(`Transpiling ES6 file: ${file}`);
|
||||
jobs.push(BabelTransform(es6File, setting, outputFiles[index]));
|
||||
});
|
||||
|
||||
return Promise.all(jobs);
|
||||
};
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
const Autoprefixer = require('autoprefixer');
|
||||
const CssNano = require('cssnano');
|
||||
const Fs = require('fs');
|
||||
const { sep } = require('path');
|
||||
const Postcss = require('postcss');
|
||||
const Sass = require('sass');
|
||||
const Babel = require('./babel-transform.es6.js');
|
||||
const { BabelTransform } = require('./babel-transform.es6.js');
|
||||
|
||||
const createJsFiles = (inputFile, es6FileContents) => {
|
||||
const createJsFiles = async (inputFile, es6FileContents) => {
|
||||
// Define some settings
|
||||
const settings = [
|
||||
{
|
||||
|
@ -18,17 +19,6 @@ const createJsFiles = (inputFile, es6FileContents) => {
|
|||
],
|
||||
comments: true,
|
||||
},
|
||||
{
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: ['last 1 Chrome version'],
|
||||
},
|
||||
}],
|
||||
['minify', { builtIns: false }],
|
||||
],
|
||||
comments: false,
|
||||
},
|
||||
{
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
|
@ -41,36 +31,21 @@ const createJsFiles = (inputFile, es6FileContents) => {
|
|||
'@babel/plugin-transform-classes',
|
||||
],
|
||||
comments: true,
|
||||
|
||||
},
|
||||
{
|
||||
presets: [
|
||||
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: ['ie 11'],
|
||||
},
|
||||
}],
|
||||
['minify', { builtIns: false }],
|
||||
],
|
||||
plugins: [
|
||||
['@babel/plugin-transform-classes'],
|
||||
],
|
||||
comments: false,
|
||||
|
||||
},
|
||||
];
|
||||
|
||||
const file = inputFile.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`);
|
||||
const outputFiles = [
|
||||
inputFile.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.w-c.es6.js', '.js'),
|
||||
inputFile.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.w-c.es6.js', '.min.js'),
|
||||
inputFile.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.w-c.es6.js', '-es5.js'),
|
||||
inputFile.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.w-c.es6.js', '-es5.min.js'),
|
||||
file.replace('.w-c.es6.js', '.js'),
|
||||
file.replace('.w-c.es6.js', '-es5.js'),
|
||||
];
|
||||
|
||||
const tasks = [];
|
||||
settings.forEach((setting, index) => {
|
||||
Babel.run(es6FileContents, setting, outputFiles[index]);
|
||||
tasks.push(BabelTransform(es6FileContents, setting, outputFiles[index]));
|
||||
});
|
||||
|
||||
await Promise.all(tasks);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -78,7 +53,7 @@ const createJsFiles = (inputFile, es6FileContents) => {
|
|||
*
|
||||
* @param file The full path to the file + filename + extension
|
||||
*/
|
||||
module.exports.compile = (inputFile) => {
|
||||
module.exports.handleWCFile = async (inputFile) => {
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
// Get the contents of the ES-XXXX file
|
||||
|
|
18
build/build-modules-js/javascript/handle-es5.es6.js
Normal file
18
build/build-modules-js/javascript/handle-es5.es6.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
const { readFile, writeFile } = require('fs').promises;
|
||||
const FsExtra = require('fs-extra');
|
||||
const { dirname, sep } = require('path');
|
||||
const { minify } = require('terser');
|
||||
|
||||
module.exports.handleES5File = async (file) => {
|
||||
if (file.match(/\.es5\.js$/)) {
|
||||
// ES5 file, we will copy the file and then minify it in place
|
||||
// Ensure that the directories exist or create them
|
||||
await FsExtra.ensureDir(dirname(file).replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`));
|
||||
await FsExtra.copy(file, file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`).replace('.es5.js', '.js'));
|
||||
const fileContent = await readFile(file, { encoding: 'utf8' });
|
||||
const content = await minify(fileContent, { sourceMap: false, format: { comments: false } });
|
||||
await writeFile(file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`).replace('.es5.js', '.min.js'), content.code, { encoding: 'utf8' });
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Es5 file copied/minified: ${file}`);
|
||||
}
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
const Fs = require('fs');
|
||||
const FsExtra = require('fs-extra');
|
||||
const Path = require('path');
|
||||
const UglifyJS = require('uglify-es');
|
||||
const TranspileJs = require('./compile-es6.es6.js');
|
||||
const TranspileWc = require('./compile-w-c.es6.js');
|
||||
|
||||
module.exports.run = (file) => {
|
||||
if (file.match(/\.js/) && file.match(/\.es6\.js/) && !file.match(/\.w-c\.es6\.js/)) {
|
||||
// ES6 file so we need to transpile it
|
||||
TranspileJs.compileFile(file);
|
||||
} else if (file.match(/\.js/) && file.match(/\.es5\.js/)) {
|
||||
// ES5 file, we will copy the file and then minify it in place
|
||||
// Ensure that the directories exist or create them
|
||||
FsExtra.mkdirsSync(Path.dirname(file).replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\'), {});
|
||||
Fs.copyFileSync(file, file.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.es5.js', '.js'));
|
||||
Fs.writeFileSync(file.replace('/build/media_source/', '/media/').replace('\\build\\media_source\\', '\\media\\').replace('.es5.js', '.min.js'), UglifyJS.minify(Fs.readFileSync(file, 'utf8')).code, { encoding: 'utf8' });
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Es5 file copied/minified: ${file}`);
|
||||
} else if (file.match(/\.js/) && file.match(/\.w-c\.es6\.js/)) {
|
||||
// Web Component, so we need to transpile it
|
||||
TranspileWc.compile(file);
|
||||
}
|
||||
};
|
|
@ -1,54 +0,0 @@
|
|||
const Fs = require('fs');
|
||||
const Path = require('path');
|
||||
const UglifyJS = require('uglify-es');
|
||||
const walkSync = require('walk-sync');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
/**
|
||||
* Method that will minify a set of vendor javascript files
|
||||
*/
|
||||
module.exports.compile = () => {
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
const folders = [
|
||||
Path.join(RootPath, 'media/vendor/codemirror'),
|
||||
Path.join(RootPath, 'media/vendor/punycode/js'),
|
||||
Path.join(RootPath, 'media/vendor/webcomponentsjs'),
|
||||
];
|
||||
|
||||
// Loop to get some text for the package.json
|
||||
folders.forEach((folder) => {
|
||||
const files = walkSync(folder, {
|
||||
globs: ['**/*.js'],
|
||||
includeBasePath: true,
|
||||
ignore: [],
|
||||
directories: false,
|
||||
});
|
||||
|
||||
if (files.length) {
|
||||
files.forEach(
|
||||
(file) => {
|
||||
if (file.match(/\.js/) && !file.match(/LICENSE\.md/)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Processing ES5 file: ${file}`);
|
||||
// Write the file
|
||||
Fs.writeFileSync(
|
||||
file.replace('.js', '.min.js'),
|
||||
UglifyJS.minify(Fs.readFileSync(file, 'utf8')).code,
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// Handle errors
|
||||
.catch((error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(`${error}`);
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
|
@ -76,7 +76,7 @@
|
|||
{
|
||||
"name": "bootstrap.es5",
|
||||
"type": "script",
|
||||
"uri": "bootstrap.es5.min.js",
|
||||
"uri": "bootstrap-es5.min.js",
|
||||
"dependencies": [
|
||||
"core"
|
||||
],
|
||||
|
@ -88,7 +88,7 @@
|
|||
{
|
||||
"name": "bootstrap.alert",
|
||||
"type": "script",
|
||||
"uri": "alert.es6.min.js",
|
||||
"uri": "alert.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -99,7 +99,7 @@
|
|||
{
|
||||
"name": "bootstrap.button",
|
||||
"type": "script",
|
||||
"uri": "button.es6.min.js",
|
||||
"uri": "button.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -110,7 +110,7 @@
|
|||
{
|
||||
"name": "bootstrap.carousel",
|
||||
"type": "script",
|
||||
"uri": "carousel.es6.min.js",
|
||||
"uri": "carousel.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -121,7 +121,7 @@
|
|||
{
|
||||
"name": "bootstrap.collapse",
|
||||
"type": "script",
|
||||
"uri": "collapse.es6.min.js",
|
||||
"uri": "collapse.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -132,7 +132,7 @@
|
|||
{
|
||||
"name": "bootstrap.dropdown",
|
||||
"type": "script",
|
||||
"uri": "dropdown.es6.min.js",
|
||||
"uri": "dropdown.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -143,7 +143,7 @@
|
|||
{
|
||||
"name": "bootstrap.modal",
|
||||
"type": "script",
|
||||
"uri": "modal.es6.min.js",
|
||||
"uri": "modal.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -154,7 +154,7 @@
|
|||
{
|
||||
"name": "bootstrap.popover",
|
||||
"type": "script",
|
||||
"uri": "popover.es6.min.js",
|
||||
"uri": "popover.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -165,7 +165,7 @@
|
|||
{
|
||||
"name": "bootstrap.scrollspy",
|
||||
"type": "script",
|
||||
"uri": "scrollspy.es6.min.js",
|
||||
"uri": "scrollspy.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -176,7 +176,7 @@
|
|||
{
|
||||
"name": "bootstrap.tab",
|
||||
"type": "script",
|
||||
"uri": "tab.es6.min.js",
|
||||
"uri": "tab.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -187,7 +187,7 @@
|
|||
{
|
||||
"name": "bootstrap.toast",
|
||||
"type": "script",
|
||||
"uri": "toast.es6.min.js",
|
||||
"uri": "toast.min.js",
|
||||
"dependencies": [
|
||||
"bootstrap.es5"
|
||||
],
|
||||
|
@ -665,6 +665,7 @@
|
|||
"licenseFilename": "LICENSE",
|
||||
"js": {
|
||||
"dist/metismenujs.js": "js/metismenujs.js",
|
||||
"dist/metismenujs.js.map": "js/metismenujs.js.map",
|
||||
"dist/metismenujs.min.js": "js/metismenujs.min.js",
|
||||
"dist/metismenujs.min.js.map": "js/metismenujs.min.js.map"
|
||||
},
|
||||
|
|
32
build/build-modules-js/stylesheets/handle-css.es6.js
Normal file
32
build/build-modules-js/stylesheets/handle-css.es6.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
const {
|
||||
copy, readFile, writeFile, ensureDir,
|
||||
} = require('fs-extra');
|
||||
const { dirname, sep } = require('path');
|
||||
const Postcss = require('postcss');
|
||||
const Autoprefixer = require('autoprefixer');
|
||||
const CssNano = require('cssnano');
|
||||
|
||||
module.exports.handleCssFile = async (file) => {
|
||||
const outputFile = file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`);
|
||||
try {
|
||||
// CSS file, we will copy the file and then minify it in place
|
||||
// Ensure that the directories exist or create them
|
||||
await ensureDir(dirname(outputFile), { recursive: true, mode: 0o2644 });
|
||||
|
||||
if (file !== outputFile) {
|
||||
await copy(file, outputFile, { overwrite: true });
|
||||
}
|
||||
|
||||
const content = await readFile(file, { encoding: 'utf8' });
|
||||
const cssMin = await Postcss([Autoprefixer, CssNano]).process(content, { from: undefined });
|
||||
|
||||
// Ensure the folder exists or create it
|
||||
await writeFile(outputFile.replace('.css', '.min.css'), cssMin.css.toString(), { encoding: 'utf8', mode: 0o2644 });
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`CSS file copied/minified: ${file}`);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(err);
|
||||
}
|
||||
};
|
47
build/build-modules-js/stylesheets/handle-scss.es6.js
Normal file
47
build/build-modules-js/stylesheets/handle-scss.es6.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
const Autoprefixer = require('autoprefixer');
|
||||
const CssNano = require('cssnano');
|
||||
const { writeFile } = require('fs').promises;
|
||||
const { ensureDir } = require('fs-extra');
|
||||
const { dirname, sep } = require('path');
|
||||
const Postcss = require('postcss');
|
||||
const Sass = require('sass');
|
||||
|
||||
module.exports.handleScssFile = async (file) => {
|
||||
const cssFile = file.replace(`${sep}scss${sep}`, `${sep}css${sep}`)
|
||||
.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`)
|
||||
.replace('.scss', '.css');
|
||||
|
||||
let compiled;
|
||||
try {
|
||||
compiled = Sass.renderSync({ file });
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error.formatted);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Auto prefixing
|
||||
const cleaner = Postcss([Autoprefixer()]);
|
||||
const res = await cleaner.process(compiled.css.toString(), { from: undefined });
|
||||
|
||||
// Ensure the folder exists or create it
|
||||
await ensureDir(dirname(cssFile), {});
|
||||
await writeFile(
|
||||
cssFile,
|
||||
res.css,
|
||||
{ encoding: 'utf8', mode: 0o2644 },
|
||||
);
|
||||
|
||||
const cssMin = await Postcss([CssNano]).process(res.css, { from: undefined });
|
||||
|
||||
// Ensure the folder exists or create it
|
||||
await ensureDir(dirname(cssFile.replace('.css', '.min.css')), {});
|
||||
await writeFile(
|
||||
cssFile.replace('.css', '.min.css'),
|
||||
cssMin.css,
|
||||
{ encoding: 'utf8', mode: 0o2644 },
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`SCSS File compiled: ${cssFile}`);
|
||||
};
|
|
@ -1,15 +1,14 @@
|
|||
const Autoprefixer = require('autoprefixer');
|
||||
const CssNano = require('cssnano');
|
||||
const Fs = require('fs');
|
||||
const Fs = require('fs').promises;
|
||||
const FsExtra = require('fs-extra');
|
||||
const Path = require('path');
|
||||
const { dirname, sep } = require('path');
|
||||
const Postcss = require('postcss');
|
||||
const Sass = require('sass');
|
||||
|
||||
module.exports.compile = (file) => {
|
||||
const cssFile = file.replace('/scss/', '/css/').replace('\\scss\\', '\\css\\')
|
||||
.replace('.scss', '.css').replace('/build/media_source/', '/media/')
|
||||
.replace('\\build\\media_source\\', '\\media\\');
|
||||
module.exports.compile = async (file) => {
|
||||
const cssFile = file.replace(`${sep}scss${sep}`, `${sep}css${sep}`)
|
||||
.replace('.scss', '.css').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`);
|
||||
|
||||
let compiled;
|
||||
try {
|
||||
|
@ -20,34 +19,34 @@ module.exports.compile = (file) => {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
// forked.on('message', async (msg) => {
|
||||
// console.log('Message from child', msg);
|
||||
|
||||
// Auto prefixing
|
||||
const cleaner = Postcss(
|
||||
[
|
||||
Autoprefixer(),
|
||||
],
|
||||
const cleaner = Postcss([Autoprefixer()]);
|
||||
const res = await cleaner.process(compiled.css.toString(), { from: undefined });
|
||||
|
||||
// Ensure the folder exists or create it
|
||||
await FsExtra.mkdirs(dirname(cssFile), {});
|
||||
await Fs.writeFile(
|
||||
cssFile,
|
||||
res.css.toString(),
|
||||
{ encoding: 'utf8', mode: 0o2644 },
|
||||
);
|
||||
cleaner.process(compiled.css.toString(), { from: undefined })
|
||||
.then((res) => {
|
||||
// Ensure the folder exists or create it
|
||||
FsExtra.mkdirsSync(Path.dirname(cssFile), {});
|
||||
|
||||
Fs.writeFileSync(
|
||||
cssFile,
|
||||
res.css.toString(),
|
||||
{ encoding: 'utf8', mode: 0o2644 },
|
||||
);
|
||||
const cssMin = await Postcss([CssNano]).process(res.css.toString(), { from: undefined });
|
||||
|
||||
Postcss([CssNano]).process(res.css.toString(), { from: undefined }).then((cssMin) => {
|
||||
// Ensure the folder exists or create it
|
||||
FsExtra.mkdirsSync(Path.dirname(cssFile.replace('.css', '.min.css')), {});
|
||||
Fs.writeFileSync(
|
||||
cssFile.replace('.css', '.min.css'),
|
||||
cssMin.css.toString(),
|
||||
{ encoding: 'utf8', mode: 0o2644 },
|
||||
);
|
||||
// Ensure the folder exists or create it
|
||||
FsExtra.mkdirs(dirname(cssFile.replace('.css', '.min.css')), {});
|
||||
await Fs.writeFile(
|
||||
cssFile.replace('.css', '.min.css'),
|
||||
cssMin.css.toString(),
|
||||
{ encoding: 'utf8', mode: 0o2644 },
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`SCSS File compiled: ${cssFile}`);
|
||||
});
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`SCSS File compiled: ${cssFile}`);
|
||||
// });
|
||||
|
||||
// forked.send({ file });
|
||||
};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
const watch = require('watch');
|
||||
const Path = require('path');
|
||||
const HandleJsFile = require('./javascript/handle-file.es6.js');
|
||||
const { join, extname } = require('path');
|
||||
const { handleWCFile } = require('./javascript/compile-w-c.es6.js');
|
||||
const { handleESMFile } = require('./javascript/compile-es6.es6.js');
|
||||
const { handleES5File } = require('./javascript/handle-es5.es6.js');
|
||||
|
||||
const RootPath = process.cwd();
|
||||
|
||||
|
@ -15,17 +17,34 @@ const RootPath = process.cwd();
|
|||
// eslint-disable-next-line max-len, no-param-reassign, no-return-assign
|
||||
const debounce = (callback, time = 250, interval) => (...args) => clearTimeout(interval, interval = setTimeout(callback, time, ...args));
|
||||
|
||||
module.exports.run = () => {
|
||||
watch.createMonitor(Path.join(RootPath, 'build/media_source'), (monitor) => {
|
||||
module.exports.watching = () => {
|
||||
watch.createMonitor(join(RootPath, 'build/media_source'), (monitor) => {
|
||||
monitor.on('created', (file) => {
|
||||
if (file.match(/\.js/) && (file.match(/\.es5\.js/) || file.match(/\.es6\.js/) || file.match(/\.w-c\.es6\.js/))) {
|
||||
debounce(HandleJsFile.run(file), 300);
|
||||
if (extname(file) === '.js') {
|
||||
if (file.match(/\.w-c\.es6\.js/)) {
|
||||
debounce(handleWCFile(file), 300);
|
||||
}
|
||||
if (file.match(/\.es6\.js/)) {
|
||||
debounce(handleESMFile(file), 300);
|
||||
}
|
||||
if (file.match(/\.es5\.js/)) {
|
||||
debounce(handleES5File(file), 300);
|
||||
}
|
||||
}
|
||||
|
||||
// @todo css and scss
|
||||
});
|
||||
monitor.on('changed', (file) => {
|
||||
if (file.match(/\.js/) && (file.match(/\.es5\.js/) || file.match(/\.es6\.js/) || file.match(/\.w-c\.es6\.js/))) {
|
||||
debounce(HandleJsFile.run(file), 300);
|
||||
if (extname(file) === '.js') {
|
||||
if (file.match(/\.w-c\.es6\.js/)) {
|
||||
debounce(handleWCFile(file), 300);
|
||||
}
|
||||
if (file.match(/\.es6\.js/)) {
|
||||
debounce(handleESMFile(file), 300);
|
||||
}
|
||||
if (file.match(/\.es5\.js/)) {
|
||||
debounce(handleES5File(file), 300);
|
||||
}
|
||||
}
|
||||
// @todo css and scss
|
||||
});
|
||||
|
|
130
build/build.js
130
build/build.js
|
@ -10,31 +10,61 @@
|
|||
* node build.js --copy-assets === will clean the media/vendor folder and then will populate the folder from node_modules
|
||||
* node build.js --compile-js === will transpile ES6 files and also uglify the ES6,ES5 files
|
||||
* node build.js --compile-css === will compile all the scss defined files and also create a minified version of the css
|
||||
* node build.js --gzip === will create gzip files for all the minified stylesheets and scripts.'
|
||||
* node build.js --compile-bs === will compile all the Bootstrap javascript components
|
||||
* node build.js --gzip === will create gzip files for all the minified stylesheets and scripts.'
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
const Program = require('commander');
|
||||
const semver = require('semver');
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
|
||||
// Joomla Build modules
|
||||
const errorPages = require('./build-modules-js/error-pages.es6.js');
|
||||
const init = require('./build-modules-js/init.es6.js');
|
||||
const compileCSS = require('./build-modules-js/compilecss.es6.js');
|
||||
const compileJS = require('./build-modules-js/compilejs.es6.js');
|
||||
const minifyVendor = require('./build-modules-js/javascript/minify-vendor.es6.js');
|
||||
const watch = require('./build-modules-js/watch.es6.js');
|
||||
const { gzipFiles } = require('./build-modules-js/gzip-assets.es6');
|
||||
const { createErrorPages } = require('./build-modules-js/error-pages.es6.js');
|
||||
const { stylesheets } = require('./build-modules-js/compilecss.es6.js');
|
||||
const { scripts } = require('./build-modules-js/compilejs.es6.js');
|
||||
const { bootstrapJs } = require('./build-modules-js/javascript/build-bootstrap-js.es6.js');
|
||||
const { localisePackages } = require('./build-modules-js/init/localise-packages.es6.js');
|
||||
const { minifyVendor } = require('./build-modules-js/init/minify-vendor.es6.js');
|
||||
const { patchPackages } = require('./build-modules-js/init/patches.es6.js');
|
||||
const { cleanVendors } = require('./build-modules-js/init/cleanup-media.es6.js');
|
||||
const { recreateMediaFolder } = require('./build-modules-js/init/recreate-media.es6');
|
||||
const { watching } = require('./build-modules-js/watch.es6.js');
|
||||
const { compressFiles } = require('./build-modules-js/compress.es6.js');
|
||||
|
||||
// The settings
|
||||
const options = require('../package.json');
|
||||
const settings = require('./build-modules-js/settings.json');
|
||||
|
||||
// Simple timer
|
||||
const timer = (name) => {
|
||||
const start = new Date();
|
||||
return {
|
||||
stop: () => {
|
||||
const end = new Date();
|
||||
const time = end.getTime() - start.getTime();
|
||||
console.log('Timer:', name, 'finished in', time, 'ms');
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// Merge Joomla's specific settings to the main package.json object
|
||||
if ('settings' in settings) {
|
||||
options.settings = settings.settings;
|
||||
}
|
||||
|
||||
const handleError = (err, terminateCode) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(terminateCode);
|
||||
};
|
||||
|
||||
const allowedVersion = () => {
|
||||
if (!semver.satisfies(process.version.substring(1), options.engines.node)) {
|
||||
handleError(`Command line tools require Node Version ${options.engines.node} but found ${process.version}`, -1);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize the CLI
|
||||
Program
|
||||
.version(options.version)
|
||||
|
@ -42,8 +72,10 @@ Program
|
|||
.option('--build-pages', 'Creates the error pages for unsupported PHP version & incomplete environment')
|
||||
.option('--compile-js, --compile-js path', 'Handles ES6, ES5 and web component scripts')
|
||||
.option('--compile-css, --compile-css path', 'Compiles all the scss files to css')
|
||||
.option('--compile-bs', 'Compiles all the Bootstrap component scripts.')
|
||||
.option('--watch', 'Watch file changes and re-compile (ATM only works for the js in the media_source).')
|
||||
.option('--gzip', 'Compress all the minified stylesheets and scripts.')
|
||||
.option('--prepare', 'Run all the needed tasks to initialise the repo')
|
||||
.on('--help', () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Version: ${options.version}`);
|
||||
|
@ -51,61 +83,83 @@ Program
|
|||
})
|
||||
.parse(process.argv);
|
||||
|
||||
|
||||
// Show help by default
|
||||
if (!process.argv.slice(2).length) {
|
||||
Program.outputHelp();
|
||||
process.exit(1);
|
||||
handleError('', 1);
|
||||
}
|
||||
|
||||
// Update the vendor folder
|
||||
if (Program.copyAssets) {
|
||||
Promise.resolve()
|
||||
.then(init.copyAssets(options))
|
||||
.then(minifyVendor.compile(options))
|
||||
|
||||
// Exit with success
|
||||
.then(() => process.exit(0))
|
||||
|
||||
// Handle errors
|
||||
.catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(-1);
|
||||
});
|
||||
allowedVersion();
|
||||
Promise.all([cleanVendors()])
|
||||
.then(() => recreateMediaFolder())
|
||||
.then(() => localisePackages(options))
|
||||
.then(() => patchPackages(options))
|
||||
.then(() => minifyVendor())
|
||||
.then(() => {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => handleError(error, 1));
|
||||
}
|
||||
|
||||
|
||||
// Creates the error pages for unsupported PHP version & incomplete environment
|
||||
if (Program.buildPages) {
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
errorPages.run(options);
|
||||
})
|
||||
// Handle errors
|
||||
.catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(-1);
|
||||
});
|
||||
Promise.all([createErrorPages(options)])
|
||||
.catch((err) => handleError(err, 1));
|
||||
}
|
||||
|
||||
// Convert scss to css
|
||||
if (Program.compileCss) {
|
||||
compileCSS.compile(options, Program.args[0]);
|
||||
Promise.all([stylesheets(options, Program.args[0])])
|
||||
.catch((err) => handleError(err, 1));
|
||||
}
|
||||
|
||||
// Compress/transpile the javascript files
|
||||
if (Program.compileJs) {
|
||||
compileJS.compileJS(options, Program.args[0]);
|
||||
Promise.all([scripts(options, Program.args[0])])
|
||||
.catch((err) => handleError(err, 1));
|
||||
}
|
||||
|
||||
// Compress/transpile the javascript files
|
||||
if (Program.watch) {
|
||||
watch.run();
|
||||
watching();
|
||||
}
|
||||
|
||||
// Gzip js/css files
|
||||
if (Program.compileBs) {
|
||||
bootstrapJs();
|
||||
}
|
||||
|
||||
// Gzip js/css files
|
||||
if (Program.gzip) {
|
||||
gzipFiles();
|
||||
compressFiles();
|
||||
}
|
||||
|
||||
// Prepare the repo for dev work
|
||||
if (Program.prepare) {
|
||||
(async () => {
|
||||
const bench = timer('Build');
|
||||
try {
|
||||
allowedVersion();
|
||||
await cleanVendors();
|
||||
await recreateMediaFolder();
|
||||
await localisePackages(options);
|
||||
await patchPackages(options);
|
||||
await Promise.all([
|
||||
minifyVendor(),
|
||||
createErrorPages(options),
|
||||
stylesheets(options, Program.args[0]),
|
||||
scripts(options, Program.args[0]),
|
||||
bootstrapJs(),
|
||||
]);
|
||||
bench.stop();
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
process.exit(-1);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
|
|
5239
package-lock.json
generated
5239
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
|
@ -14,14 +14,14 @@
|
|||
"scripts": {
|
||||
"build:js": "node build/build.js --compile-js",
|
||||
"build:css": "node build/build.js --compile-css",
|
||||
"build:bs5": "node build/build-modules-js/build-bootstrap-js.es6.js",
|
||||
"build:bs5": "node build/build.js --compile-bs",
|
||||
"watch": "node build/build.js --watch",
|
||||
"lint:js": "eslint --config build/.eslintrc --ignore-pattern '/media/' --ext .es6.js,.es6,.vue .",
|
||||
"lint:css": "stylelint --config build/.stylelintrc.json -s scss \"administrator/components/com_media/resources/**/*.scss\" \"administrator/templates/**/*.scss\" \"build/media_source/**/*.scss\" \"templates/**/*.scss\" \"installation/template/**/*.scss\"",
|
||||
"test": "karma start tests/javascript/karma.conf.js --single-run",
|
||||
"install": "node build/build.js --copy-assets && node build/build.js --build-pages && npm run build:bs5",
|
||||
"postinstall": "node build/build.js --compile-js && node build/build.js --compile-css && npm run build:com_media",
|
||||
"update": "node build/build.js --copy-assets && node build/build.js --build-pages && node build/build.js --compile-js && node build/build.js --compile-css",
|
||||
"install": "node build/build.js --prepare",
|
||||
"postinstall": "npm run build:com_media",
|
||||
"update": "node build/build.js --copy-assets && node build/build.js --build-pages && node build/build.js --compile-js && node build/build.js --compile-css && node build/build.js --compile-bs && npm run build:com_media",
|
||||
"gzip": "node build/build.js --gzip",
|
||||
"watch:com_media": "cross-env NODE_ENV=development webpack --progress --hide-modules --watch --config administrator/components/com_media/webpack.config.js",
|
||||
"dev:com_media": "cross-env NODE_ENV=development webpack --progress --hide-modules --config administrator/components/com_media/webpack.config.js",
|
||||
|
@ -34,6 +34,7 @@
|
|||
"dependencies": {
|
||||
"@claviska/jquery-minicolors": "^2.3.5",
|
||||
"@fortawesome/fontawesome-free": "^5.15.2",
|
||||
"@popperjs/core": "^2.6.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||
"accessibility": "^3.0.10",
|
||||
"awesomplete": "1.1.5",
|
||||
|
@ -51,7 +52,6 @@
|
|||
"jquery-migrate": "^3.3.2",
|
||||
"mediaelement": "^4.2.16",
|
||||
"metismenujs": "^1.2.1",
|
||||
"@popperjs/core": "^2.6.0",
|
||||
"punycode": "1.4.1",
|
||||
"qrcode-generator": "^1.4.4",
|
||||
"roboto-fontface": "^0.10.0",
|
||||
|
@ -68,7 +68,7 @@
|
|||
"@babel/plugin-transform-classes": "^7.12.1",
|
||||
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@gfx/zopfli": "^1.0.15",
|
||||
"@dgrammatiko/compress": "^1.0.4",
|
||||
"@rollup/plugin-babel": "^5.2.2",
|
||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
|
@ -79,7 +79,6 @@
|
|||
"babelify": "^10.0.0",
|
||||
"browserify": "^16.5.2",
|
||||
"commander": "^5.1.0",
|
||||
"copy-dir": "^1.3.0",
|
||||
"core-js": "^3.8.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^3.6.0",
|
||||
|
@ -102,7 +101,6 @@
|
|||
"karma-json-fixtures-preprocessor": "0.0.6",
|
||||
"karma-verbose-reporter": "^0.0.6",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"path": "^0.12.7",
|
||||
"postcss": "^7.0.35",
|
||||
"recursive-readdir": "^2.2.2",
|
||||
"rimraf": "^3.0.2",
|
||||
|
@ -115,11 +113,8 @@
|
|||
"stylelint-order": "^4.1.0",
|
||||
"stylelint-scss": "^3.18.0",
|
||||
"terser": "^5.5.1",
|
||||
"uglify-es": "^3.3.9",
|
||||
"uglifycss": "^0.0.29",
|
||||
"vue-loader": "^15.9.6",
|
||||
"vue-template-compiler": "^2.6.12",
|
||||
"walk-sync": "^2.2.0",
|
||||
"watch": "^1.0.2",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
|
|
Loading…
Reference in New Issue
Block a user