Skip to content

Commit

Permalink
fix: make Site.copy support multiple destinations
Browse files Browse the repository at this point in the history
Site.copy previously didn't support multiple destinations:

   site.copy("foo", "bar1")
   site.copy("foo", "bar2")

Previously resulted in `foo` being only copied once to `bar2`.

   site.copy("static")
   site.copy("static/foo", "bar")

Previously didn't copy `static/foo` to `bar`.

This commit fixes both of these bugs. Fixes #428.
  • Loading branch information
not-my-profile committed Jun 5, 2023
1 parent 29db4a3 commit b50cda9
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 40 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Any BREAKING CHANGE between minor versions will be documented here in upper case
### Fixed

- `Site.copy` now supports trailing slashes in the source path. [#426]
- Multiple `Site.copy` calls can now be used to copy one file to multiple destinations. [#429]

## [1.17.4] - 2023-05-25
### Added
Expand Down Expand Up @@ -2261,6 +2262,7 @@ The first version.
[#418]: https://github.com/lumeland/lume/issues/418
[#419]: https://github.com/lumeland/lume/issues/419
[#426]: https://github.com/lumeland/lume/pull/426
[#429]: https://github.com/lumeland/lume/pull/429

[1.17.4]: https://github.com/lumeland/lume/compare/v1.17.3...v1.17.4
[1.17.3]: https://github.com/lumeland/lume/compare/v1.17.2...v1.17.3
Expand Down
74 changes: 46 additions & 28 deletions core/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ export default class Source {
prettyUrls: boolean;

/** List of static files and folders to copy */
staticPaths = new Map<
string,
{ dest: string | ((path: string) => string) | undefined; dirOnly: boolean }
>();
staticPaths: {
from: string;
to: string | ((path: string) => string) | undefined;
dirOnly: boolean;
}[] = [];

/** List of static files and folders to copy */
copyRemainingFiles?: (path: string) => string | boolean;
Expand Down Expand Up @@ -102,10 +103,10 @@ export default class Source {
}

addStaticPath(from: string, to?: string | ((path: string) => string)) {
this.staticPaths.set(
normalizePath(from.replace(/\/$/, "")),
this.staticPaths.push(
{
dest: typeof to === "string" ? normalizePath(to) : to,
from: normalizePath(from.replace(/\/$/, "")),
to: typeof to === "string" ? normalizePath(to) : to,
dirOnly: from.endsWith("/"),
},
);
Expand All @@ -118,12 +119,42 @@ export default class Source {
const pages: Page[] = [];
const staticFiles: StaticFile[] = [];

// Resolve staticPaths to staticFiles
for (const instruction of this.staticPaths) {
const entry = this.fs.entries.get(instruction.from);
if (entry) {
const path = posix.dirname(entry.path);

if (entry.type == "file") {
if (instruction.dirOnly) {
continue;
}
staticFiles.push({
entry,
outputPath: getOutputPath(
entry,
path,
instruction.to,
),
});
} else {
const dest = instruction.to;
staticFiles.push(...this.#getStaticFiles(
entry,
typeof dest === "string" ? dest : posix.join(path, entry.name),
typeof dest === "function" ? dest : undefined,
));
}
}
}

await this.#build(
buildFilters,
this.fs.entries.get("/")!,
"/",
globalComponents,
{},
new Set(this.staticPaths.map(p => p.from)),
pages,
staticFiles,
);
Expand All @@ -140,6 +171,7 @@ export default class Source {
path: string,
parentComponents: Components,
parentData: Data,
staticPaths: Set<string>,
pages: Page[],
staticFiles: StaticFile[],
) {
Expand Down Expand Up @@ -191,26 +223,8 @@ export default class Source {
continue;
}

// Static files
if (this.staticPaths.has(entry.path)) {
const { dest, dirOnly } = this.staticPaths.get(entry.path)!;

if (entry.type === "file") {
if (dirOnly) {
continue;
}
staticFiles.push({
entry,
outputPath: getOutputPath(entry, path, dest),
});
continue;
}

staticFiles.push(...this.#getStaticFiles(
entry,
typeof dest === "string" ? dest : posix.join(path, entry.name),
typeof dest === "function" ? dest : undefined,
));
if (staticPaths.has(entry.path)) {
// The static file has already been resolved.
continue;
}

Expand Down Expand Up @@ -311,6 +325,7 @@ export default class Source {
path,
parentComponents,
dirData,
staticPaths,
pages,
staticFiles,
);
Expand Down Expand Up @@ -695,7 +710,10 @@ export function getOutputPath(
return dest;
}

const outputPath = posix.join(path, entry.name);
const outputPath = posix.join(
path.split("/").map((comp) => parseDate(comp)[0]).join("/"),
entry.name,
);

if (typeof dest === "function") {
return dest(outputPath);
Expand Down
4 changes: 2 additions & 2 deletions core/writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ export default class Writer {
async copyFile(file: StaticFile): Promise<boolean> {
const { entry } = file;

if (entry.flags.has("saved")) {
if (entry.flags.has("saved-" + file.outputPath)) {
return false;
}

entry.flags.add("saved");
entry.flags.add("saved-" + file.outputPath);

const pathTo = posix.join(this.dest, file.outputPath);

Expand Down
15 changes: 15 additions & 0 deletions tests/__snapshots__/static_files.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ snapshot[`Copy static files 2`] = `
flags: [],
outputPath: "/_headers",
},
{
entry: "/one.yes",
flags: [],
outputPath: "/one.yes",
},
{
entry: "/one.yes",
flags: [],
outputPath: "/one-again.yes",
},
{
entry: "/other/one",
flags: [],
Expand Down Expand Up @@ -166,6 +176,11 @@ snapshot[`Copy static files 2`] = `
flags: [],
outputPath: "/script/app/main.js",
},
{
entry: "/static/_redirects",
flags: [],
outputPath: "/_redirects",
},
{
entry: "/static/one.yes",
flags: [],
Expand Down
19 changes: 9 additions & 10 deletions tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,19 @@ Deno.test("static files configuration", () => {
const { staticPaths } = site.source;

site.copy("img");
equals(staticPaths.size, 1);
equals(staticPaths.has("/img"), true);
equals(staticPaths.get("/img")!.dest, undefined);
equals(staticPaths.length, 1);
equals(staticPaths[0].from, "/img");
equals(staticPaths[0].to, undefined);

site.copy("statics/favicon.ico", "favicon.ico");
equals(staticPaths.size, 2);
equals(
staticPaths.get("/statics/favicon.ico")!.dest,
"/favicon.ico",
);
equals(staticPaths.length, 2);
equals(staticPaths[1].from, "/statics/favicon.ico");
equals(staticPaths[1].to, "/favicon.ico");

site.copy("css", ".");
equals(staticPaths.size, 3);
equals(staticPaths.get("/css")!.dest, "/");
equals(staticPaths.length, 3);
equals(staticPaths[2].from, "/css");
equals(staticPaths[2].to, "/");
});

Deno.test("ignored files configuration", () => {
Expand Down
4 changes: 4 additions & 0 deletions tests/static_files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Deno.test("Copy static files", async (t) => {
(file) => "/subdir" + file.replace(/\.copy2/, ".copy3"),
);

// a single file can be copied multiple times
site.copy("one.yes")
site.copy("one.yes", "one-again.yes")

// copied with the trailing slash
site.copy("other2/");

Expand Down

0 comments on commit b50cda9

Please sign in to comment.