430 lines
13 KiB
JavaScript
430 lines
13 KiB
JavaScript
/**
|
|
* @file
|
|
* Copy files for JS vendor dependencies from node_modules to the assets/vendor
|
|
* folder.
|
|
*
|
|
* This script handles all dependencies except CKEditor, Modernizr,
|
|
* and jQuery.ui which require a custom build step.
|
|
*/
|
|
|
|
const path = require('path');
|
|
const { copyFile, writeFile, readFile, chmod, rmdir, mkdir, readdir, appendFile } = require('fs').promises;
|
|
|
|
const coreFolder = path.resolve(__dirname, '../../');
|
|
const packageFolder = `${coreFolder}/node_modules`;
|
|
const assetsFolder = `${coreFolder}/assets/vendor`;
|
|
|
|
(async () => {
|
|
const librariesPath = `${coreFolder}/core.libraries.yml`;
|
|
// Open the core.libraries.yml file to update version information
|
|
// automatically.
|
|
const libraries = (await readFile(librariesPath, 'utf-8')).split('\n\n');
|
|
|
|
function updateLibraryVersion(libraryName, { version }) {
|
|
const libraryIndex = libraries.findIndex((lib) =>
|
|
lib.startsWith(libraryName),
|
|
);
|
|
if (libraryIndex > 0) {
|
|
const libraryDeclaration = libraries[libraryIndex];
|
|
// Get the previous package version.
|
|
const currentVersion = libraryDeclaration.match(/version: "(.*)"\n/)[1];
|
|
// Replace the version value and the version in the license URL.
|
|
libraries[libraryIndex] = libraryDeclaration.replace(
|
|
new RegExp(currentVersion, 'g'),
|
|
version,
|
|
);
|
|
}
|
|
}
|
|
|
|
// CKEditor 5 translation files need some special handling. Start by ensuring
|
|
// that an empty /translations directory exists in the
|
|
// /core/assets/vendor/ckeditor5 directory.
|
|
const ckeditor5Path = `${assetsFolder}/ckeditor5`;
|
|
await rmdir(`${ckeditor5Path}/translations`, { recursive: true })
|
|
.catch(() => {
|
|
// Nothing to do if the directory doesn't exist.
|
|
});
|
|
await mkdir(`${ckeditor5Path}/translations`);
|
|
|
|
/**
|
|
* Declare the array that defines what needs to be copied over.
|
|
*
|
|
* @prop {string} pack
|
|
* The name of the npm package (used to get the name of the folder where
|
|
* the files are situated inside of the node_modules folder). Note that we
|
|
* use `pack` and not `package` because `package` is a future reserved word.
|
|
* @prop {string} [folder]
|
|
* The folder under `assets/vendor/` where the files will be copied. If
|
|
* this
|
|
* is not defined the value of `pack` is used.
|
|
* @prop {string} [library]
|
|
* The key under which the library is declared in core.libraries.yml.
|
|
* @prop {Array} files
|
|
* An array of files to be copied over.
|
|
* - A string if the file has the same name and is at the same level in
|
|
* the source and target folder.
|
|
* - An object with a `from` and `to` property if the source and target
|
|
* have a different name or if the folder nesting is different.
|
|
*/
|
|
const process = [
|
|
{
|
|
pack: 'backbone',
|
|
files: ['backbone.js', 'backbone-min.js', 'backbone-min.map'],
|
|
},
|
|
{
|
|
pack: 'css.escape',
|
|
folder: 'css-escape',
|
|
library: 'css.escape',
|
|
files: ['css.escape.js'],
|
|
},
|
|
{
|
|
pack: 'es6-promise',
|
|
files: [
|
|
{ from: 'dist/es6-promise.auto.min.js', to: 'es6-promise.auto.min.js' },
|
|
{
|
|
from: 'dist/es6-promise.auto.min.map',
|
|
to: 'es6-promise.auto.min.map',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
pack: 'farbtastic',
|
|
library: 'jquery.farbtastic',
|
|
files: [
|
|
'marker.png',
|
|
'mask.png',
|
|
'wheel.png',
|
|
'farbtastic.css',
|
|
{ from: 'farbtastic.min.js', to: 'farbtastic.js' },
|
|
],
|
|
},
|
|
{
|
|
pack: 'jquery',
|
|
files: [
|
|
{ from: 'dist/jquery.js', to: 'jquery.js' },
|
|
{ from: 'dist/jquery.min.js', to: 'jquery.min.js' },
|
|
{ from: 'dist/jquery.min.map', to: 'jquery.min.map' },
|
|
],
|
|
},
|
|
{
|
|
pack: 'jquery-form',
|
|
library: 'jquery.form',
|
|
files: [
|
|
{ from: 'dist/jquery.form.min.js', to: 'jquery.form.min.js' },
|
|
{ from: 'dist/jquery.form.min.js.map', to: 'jquery.form.min.js.map' },
|
|
{ from: 'src/jquery.form.js', to: 'src/jquery.form.js' },
|
|
],
|
|
},
|
|
{
|
|
pack: 'joyride',
|
|
folder: 'jquery-joyride',
|
|
library: 'jquery.joyride',
|
|
files: ['jquery.joyride-2.1.js'],
|
|
},
|
|
{
|
|
pack: 'jquery-once',
|
|
library: 'jquery.once',
|
|
files: ['jquery.once.js', 'jquery.once.min.js', 'jquery.once.min.js.map'],
|
|
},
|
|
{
|
|
pack: 'js-cookie',
|
|
files: [{ from: 'dist/js.cookie.min.js', to: 'js.cookie.min.js' }],
|
|
},
|
|
{
|
|
pack: 'normalize.css',
|
|
folder: 'normalize-css',
|
|
library: 'normalize',
|
|
files: ['normalize.css'],
|
|
},
|
|
{
|
|
pack: '@drupal/once',
|
|
folder: 'once',
|
|
files: [
|
|
{ from: 'dist/once.js', to: 'once.js' },
|
|
{ from: 'dist/once.min.js', to: 'once.min.js' },
|
|
{ from: 'dist/once.min.js.map', to: 'once.min.js.map' },
|
|
],
|
|
},
|
|
{
|
|
pack: 'picturefill',
|
|
files: [{ from: 'dist/picturefill.min.js', to: 'picturefill.min.js' }],
|
|
},
|
|
{
|
|
pack: '@popperjs/core',
|
|
folder: 'popperjs',
|
|
files: [
|
|
{ from: 'dist/umd/popper.min.js', to: 'popper.min.js' },
|
|
{ from: 'dist/umd/popper.min.js.map', to: 'popper.min.js.map' },
|
|
],
|
|
},
|
|
{
|
|
pack: 'shepherd.js',
|
|
folder: 'shepherd',
|
|
files: [
|
|
{ from: 'dist/js/shepherd.min.js', to: 'shepherd.min.js' },
|
|
{ from: 'dist/js/shepherd.min.js.map', to: 'shepherd.min.js.map' },
|
|
],
|
|
},
|
|
{ pack: 'sortablejs', folder: 'sortable', files: ['Sortable.min.js'] },
|
|
{
|
|
pack: 'tabbable',
|
|
files: [
|
|
{ from: 'dist/index.umd.min.js', to: 'index.umd.min.js' },
|
|
{ from: 'dist/index.umd.min.js.map', to: 'index.umd.min.js.map' },
|
|
],
|
|
},
|
|
{
|
|
pack: 'underscore',
|
|
files: ['underscore-min.js', 'underscore-min.js.map'],
|
|
},
|
|
{
|
|
pack: 'loadjs',
|
|
files: [{ from: 'dist/loadjs.min.js', to: 'loadjs.min.js' }],
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-alignment',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/alignment.js', to: 'alignment.js' }
|
|
],
|
|
library: 'ckeditor5.alignment',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-basic-styles',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/basic-styles.js', to: 'basic-styles.js' }
|
|
],
|
|
library: 'ckeditor5.basic',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-block-quote',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/block-quote.js', to: 'block-quote.js' }
|
|
],
|
|
library: 'ckeditor5.blockquote',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-editor-classic',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/editor-classic.js', to: 'editor-classic.js' }
|
|
],
|
|
library: 'ckeditor5.editorClassic',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-editor-decoupled',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/editor-decoupled.js', to: 'editor-decoupled.js' }
|
|
],
|
|
library: 'ckeditor5.editorDecoupled',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-essentials',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/essentials.js', to: 'essentials.js' }
|
|
],
|
|
library: 'ckeditor5.internal',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-heading',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/heading.js', to: 'heading.js' }
|
|
],
|
|
library: 'ckeditor5.internal',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-horizontal-line',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/horizontal-line.js', to: 'horizontal-line.js' }
|
|
],
|
|
library: 'ckeditor5.horizontalLine',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-image',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/image.js', to: 'image.js' }
|
|
],
|
|
library: 'ckeditor5.image',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-indent',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/indent.js', to: 'indent.js' }
|
|
],
|
|
library: 'ckeditor5.indent',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-language',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/language.js', to: 'language.js' },
|
|
],
|
|
library: 'ckeditor5.language',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-link',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/link.js', to: 'link.js' }
|
|
],
|
|
library: 'ckeditor5.link',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-list',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/list.js', to: 'list.js' }
|
|
],
|
|
library: 'ckeditor5.list',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-paste-from-office',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/paste-from-office.js', to: 'paste-from-office.js' }
|
|
],
|
|
library: 'ckeditor5.pasteFromOffice',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-remove-format',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/remove-format.js', to: 'remove-format.js' }
|
|
],
|
|
library: 'ckeditor5.removeFormat',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-source-editing',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/source-editing.js', to: 'source-editing.js' }
|
|
],
|
|
library: 'ckeditor5.sourceEditing',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-table',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/table.js', to: 'table.js' }
|
|
],
|
|
library: 'ckeditor5.table',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-html-support',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/html-support.js', to: 'html-support.js' }
|
|
],
|
|
library: 'ckeditor5.htmlSupport',
|
|
},
|
|
{
|
|
pack: '@ckeditor/ckeditor5-special-characters',
|
|
folder: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/special-characters.js', to: 'special-characters.js' }
|
|
],
|
|
library: 'ckeditor5.specialCharacters',
|
|
},
|
|
{
|
|
pack: 'ckeditor5',
|
|
files: [
|
|
{ from: 'build/ckeditor5-dll.js', to: 'ckeditor5-dll.js' }
|
|
],
|
|
}
|
|
];
|
|
|
|
// Use Array.reduce for sequential processing to avoid corrupting the
|
|
// contents of the concatenated CKEditor 5 translation files.
|
|
process.reduce(async (previous, { pack, files = [], folder = false, library = false }) => {
|
|
return previous.then(async () => {
|
|
const sourceFolder = pack;
|
|
const libraryName = library || folder || pack;
|
|
const destFolder = folder || pack;
|
|
|
|
let packageInfo;
|
|
// Take the version info from the package.json file.
|
|
if (!['joyride', 'farbtastic'].includes(pack)) {
|
|
packageInfo = JSON.parse(
|
|
await readFile(`${packageFolder}/${sourceFolder}/package.json`),
|
|
);
|
|
}
|
|
if (packageInfo) {
|
|
updateLibraryVersion(libraryName, packageInfo);
|
|
}
|
|
|
|
// CKEditor 5 packages ship with translation files.
|
|
if (pack.startsWith('@ckeditor') || pack === 'ckeditor5') {
|
|
const packageTranslationPath = `${packageFolder}/${sourceFolder}/build/translations`;
|
|
await readdir(packageTranslationPath, { withFileTypes: true }).then(async (translationFiles) => {
|
|
return translationFiles.map(async (translationFile) => {
|
|
if (!translationFile.isDirectory()) {
|
|
// Translation files are concatenated to a single translation
|
|
// file to avoid having to make multiple network requests to
|
|
// various translation files. As a trade off, this leads into
|
|
// some redundant translations depending on configuration.
|
|
await readFile(`${packageTranslationPath}/${translationFile.name}`).then(async (contents) => {
|
|
return appendFile(`${assetsFolder}/${destFolder}/translations/${translationFile.name}`, contents);
|
|
});
|
|
}
|
|
}, Promise.resolve());
|
|
}).catch(() => {
|
|
// Do nothing as it's expected that not all packages ship translations.
|
|
});
|
|
}
|
|
|
|
return files.forEach(async (file) => {
|
|
let source = file;
|
|
let dest = file;
|
|
if (typeof file === 'object') {
|
|
source = file.from;
|
|
dest = file.to;
|
|
}
|
|
// For map files, make sure the sources files don't leak outside the
|
|
// library folder. In the `sources` member, remove all "../" values at
|
|
// the start of the files names to avoid having the virtual files outside
|
|
// of the library vendor folder in dev tools.
|
|
if (path.extname(source) === '.map') {
|
|
console.log('Process map file', source);
|
|
const map = await readFile(
|
|
`${packageFolder}/${sourceFolder}/${source}`,
|
|
);
|
|
const json = JSON.parse(map);
|
|
json.sources = json.sources.map((source) =>
|
|
source.replace(/^(\.\.\/)+/, ''),
|
|
);
|
|
await writeFile(
|
|
`${assetsFolder}/${destFolder}/${dest}`,
|
|
JSON.stringify(json),
|
|
);
|
|
} else {
|
|
console.log(
|
|
'Copy',
|
|
`${sourceFolder}/${source}`,
|
|
'to',
|
|
`${destFolder}/${dest}`,
|
|
);
|
|
await copyFile(
|
|
`${packageFolder}/${sourceFolder}/${source}`,
|
|
`${assetsFolder}/${destFolder}/${dest}`,
|
|
);
|
|
// These 2 files come from a zip file that hasn't been updated in years
|
|
// hardcode the permission fix to pass the commit checks.
|
|
if (['jquery.joyride-2.1.js', 'marker.png'].includes(dest)) {
|
|
await chmod(`${assetsFolder}/${destFolder}/${dest}`, 0o644);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}, Promise.resolve());
|
|
|
|
await writeFile(librariesPath, libraries.join('\n\n'));
|
|
})();
|