From a1921e23f5a8b65541f9dfd4ddb6fed4744691cf Mon Sep 17 00:00:00 2001 From: spring-raining Date: Wed, 17 Jan 2024 23:54:23 +0900 Subject: [PATCH] fix: Improve file selector not to include unnecessary files into Webpub/EPUB fix #461 --- src/output/webbook.ts | 36 ++++++++++++---------- src/processor/compile.ts | 65 ++++++++++++++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/src/output/webbook.ts b/src/output/webbook.ts index 1552ad22..775504b6 100644 --- a/src/output/webbook.ts +++ b/src/output/webbook.ts @@ -2,7 +2,12 @@ import fs from 'node:fs'; import MIMEType from 'whatwg-mimetype'; import { MANIFEST_FILENAME } from '../const.js'; import { MergedConfig, WebbookEntryConfig } from '../input/config.js'; -import { generateManifest, globAssetFiles } from '../processor/compile.js'; +import { + generateManifest, + getAutoGeneratedAssetPatterns, + getDefaultIgnorePatterns, + globAssetFiles, +} from '../processor/compile.js'; import { ResourceLoader, fetchLinkedPublicationManifest, @@ -18,7 +23,6 @@ import { debug, logError, logUpdate, - pathContains, pathEquals, remove, safeGlob, @@ -247,10 +251,14 @@ export async function copyWebPublicationAssets({ exportAliases, outputs, copyAsset, + themesDir, manifestPath, input, outputDir, -}: Pick & { +}: Pick< + MergedConfig, + 'exportAliases' | 'outputs' | 'copyAsset' | 'themesDir' +> & { input: string; outputDir: string; manifestPath: string; @@ -261,21 +269,12 @@ export async function copyWebPublicationAssets({ target: upath.relative(input, target), })) .filter(({ source }) => !source.startsWith('..')); - const ignore = [ - // don't copy auto-generated assets - ...outputs.flatMap(({ format, path: p }) => - !pathContains(input, p) - ? [] - : format === 'webpub' - ? upath.join(upath.relative(input, p), '**') - : upath.relative(input, p), - ), - ]; const allFiles = new Set([ ...(await globAssetFiles({ copyAsset, cwd: input, - ignore, + outputs, + themesDir, })), ...(await safeGlob( [ @@ -285,7 +284,14 @@ export async function copyWebPublicationAssets({ { cwd: input, ignore: [ - ...ignore, + ...getAutoGeneratedAssetPatterns({ + cwd: input, + outputs, + }), + ...getDefaultIgnorePatterns({ + cwd: input, + themesDir, + }), // only include dotfiles starting with `.vs-` '**/.!(vs-*)/**', ], diff --git a/src/processor/compile.ts b/src/processor/compile.ts index 5c14ae40..6d0df03e 100644 --- a/src/processor/compile.ts +++ b/src/processor/compile.ts @@ -362,22 +362,68 @@ export async function compile({ } } +export function getDefaultIgnorePatterns({ + themesDir, + cwd, +}: Pick & { + cwd: string; +}): string[] { + const ignorePatterns = [ + // ignore node_modules directory + '**/node_modules', + ]; + if (pathContains(cwd, themesDir)) { + // ignore example files of theme packages + ignorePatterns.push( + `${upath.relative(cwd, themesDir)}/packages/*/example`, + `${upath.relative(cwd, themesDir)}/packages/*/*/example`, + ); + } + return ignorePatterns; +} + +export function getAutoGeneratedAssetPatterns({ + outputs, + cwd, +}: Pick & { + cwd: string; +}): string[] { + return outputs.flatMap(({ format, path: p }) => + !pathContains(cwd, p) + ? [] + : format === 'webpub' + ? upath.join(upath.relative(cwd, p), '**') + : upath.relative(cwd, p), + ); +} + export async function globAssetFiles({ copyAsset: { fileExtensions, includes, excludes }, + outputs, + themesDir, cwd, ignore = [], -}: Pick & { +}: Pick & { cwd: string; ignore?: string[]; }): Promise> { + const ignorePatterns = [ + ...ignore, + ...excludes, + ...getAutoGeneratedAssetPatterns({ outputs, cwd }), + ]; + const weakIgnorePatterns = getDefaultIgnorePatterns({ themesDir, cwd }); + debug('globAssetFiles > ignorePatterns', ignorePatterns); + debug('globAssetFiles > weakIgnorePatterns', weakIgnorePatterns); + const assets = new Set([ // Step 1: Glob files with an extension in `fileExtension` - // Ignore files in node_modules directory and files matched `excludes` + // Ignore files in node_modules directory, theme example files and files matched `excludes` ...(await safeGlob( fileExtensions.map((ext) => `**/*.${ext}`), { cwd, - ignore: [...ignore, ...excludes, '**/node_modules'], + ignore: [...ignorePatterns, ...weakIgnorePatterns], followSymbolicLinks: true, gitignore: false, }, @@ -386,7 +432,7 @@ export async function globAssetFiles({ // Ignore only files matched `excludes` ...(await safeGlob(includes, { cwd, - ignore: [...ignore, ...excludes], + ignore: ignorePatterns, followSymbolicLinks: true, gitignore: false, })), @@ -399,6 +445,7 @@ export async function copyAssets({ workspaceDir, copyAsset, outputs, + themesDir, }: MergedConfig): Promise { if (pathEquals(entryContextDir, workspaceDir)) { return; @@ -407,15 +454,9 @@ export async function copyAssets({ const assets = await globAssetFiles({ copyAsset, cwd: entryContextDir, + outputs, + themesDir, ignore: [ - // don't copy auto-generated assets - ...outputs.flatMap(({ format, path: p }) => - !pathContains(entryContextDir, p) - ? [] - : format === 'webpub' - ? upath.join(upath.relative(entryContextDir, p), '**') - : upath.relative(entryContextDir, p), - ), // don't copy workspace itself ...(relWorkspaceDir ? [upath.join(relWorkspaceDir, '**')] : []), ],