From c9056b27d83cb2aab14ecc35d0916e8fe8853069 Mon Sep 17 00:00:00 2001 From: Chauncey McAskill Date: Tue, 8 Feb 2022 14:46:34 -0500 Subject: [PATCH] Add support for removing duplicates in concats.js Added: - Argument `concatOptions` to `concatFiles()` function to customize concatenation. - Option 'removeDuplicates' to `concatOptions` to remove duplicate paths from the array of globbed paths. Defaults to `true`. The 'removeDuplicates' is useful for customizing the order of files to concatenate, in which globbing will usually sort paths alphabetically. This option is convenient when the installed glob library does not support removing duplicates on their own (feature supported in 'fast-glob' and 'glob'). Example: ``` /assets/scripts/vendors/a.js /assets/scripts/vendors/b.js /assets/scripts/vendors/c.js /assets/scripts/vendors/d.js ``` ```json "concats": [ { "includes": [ "{% paths.scripts.src %}/vendors/c.js", "{% paths.scripts.src %}/vendors/*.js" ], "outfile": "{% paths.scripts.dest %}/vendors.js" } ] ``` --- build/tasks/concats.js | 45 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/build/tasks/concats.js b/build/tasks/concats.js index a7e4811..f21b116 100644 --- a/build/tasks/concats.js +++ b/build/tasks/concats.js @@ -4,7 +4,10 @@ import message from '../utils/message.js'; import notification from '../utils/notification.js'; import template from '../utils/template.js'; import concat from 'concat'; -import { basename } from 'node:path'; +import { + basename, + normalize, +} from 'node:path'; /** * @const {object} defaultGlobOptions - The default shared glob options. @@ -16,15 +19,35 @@ export const defaultGlobOptions = { export const developmentGlobOptions = Object.assign({}, defaultGlobOptions); export const productionGlobOptions = Object.assign({}, defaultGlobOptions); +/** + * @typedef {object} ConcatOptions + * @property {boolean} removeDuplicates - Removes duplicate paths from + * the array of matching files and folders. + * Only the first occurrence of each path is kept. + */ + +/** + * @const {ConcatOptions} defaultConcatOptions - The default shared concatenation options. + * @const {ConcatOptions} developmentConcatOptions - The predefined concatenation options for development. + * @const {ConcatOptions} productionConcatOptions - The predefined concatenation options for production. + */ +export const defaultConcatOptions = { + removeDuplicates: true, +}; +export const developmentConcatOptions = Object.assign({}, defaultConcatOptions); +export const productionConcatOptions = Object.assign({}, defaultConcatOptions); + /** * @const {object} developmentConcatFilesArgs - The predefined `concatFiles()` options for development. * @const {object} productionConcatFilesArgs - The predefined `concatFiles()` options for production. */ export const developmentConcatFilesArgs = [ developmentGlobOptions, + developmentConcatOptions, ]; export const productionConcatFilesArgs = [ productionGlobOptions, + productionConcatOptions, ]; /** @@ -35,9 +58,11 @@ export const productionConcatFilesArgs = [ * @async * @param {object} [globOptions=null] - Customize the glob options. * If `null`, default production options are used. + * @param {object} [concatOptions=null] - Customize the concatenation options. + * If `null`, default production options are used. * @return {Promise} */ -export default async function concatFiles(globOptions = null) { +export default async function concatFiles(globOptions = null, concatOptions = null) { if (globOptions == null) { globOptions = productionGlobOptions; } else if ( @@ -47,6 +72,15 @@ export default async function concatFiles(globOptions = null) { globOptions = Object.assign({}, defaultGlobOptions, globOptions); } + if (concatOptions == null) { + concatOptions = productionConcatOptions; + } else if ( + concatOptions !== developmentConcatOptions && + concatOptions !== productionConcatOptions + ) { + concatOptions = Object.assign({}, defaultConcatOptions, concatOptions); + } + loconfig.tasks.concats.forEach(async ({ includes, outfile, @@ -63,7 +97,12 @@ export default async function concatFiles(globOptions = null) { includes = includes.map((path) => template(path)); outfile = template(outfile); - const files = await glob(includes, globOptions); + let files = await glob(includes, globOptions); + + if (concatOptions.removeDuplicates) { + files = files.map((path) => normalize(path)); + files = [ ...new Set(files) ]; + } await concat(files, outfile);