Skip to content

Commit 8e37e95

Browse files
Allow copying entire directories from node_modules
1 parent f6cfa87 commit 8e37e95

File tree

3 files changed

+61
-30
lines changed

3 files changed

+61
-30
lines changed

StatiqPipelines.Tests/CopyFromNPMTests.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,27 @@ public async Task NodeModulesAreTranslated()
1616
context.FileSystem.GetInputFile("/node_modules/y/2.js").OpenWrite();
1717

1818
var pipeline = new CopyFromNPM(new[] { "x/1.js", "y/2.js" }, "assets/js");
19-
var input = pipeline.InputModules.First(m => m is ReadFiles);
19+
var input = pipeline.InputModules.Where(m => m is ReadFiles);
2020

2121
//act
22-
var output = await input.ExecuteAsync(context);
22+
var tasks = input.Select(async i => await i.ExecuteAsync(context));
23+
var output = await Task.WhenAll(tasks);
2324

2425
//assert
25-
var files = output.Select(d => d.Source.FileName.ToString()).ToArray();
26+
var files = output.SelectMany(d => d).Select(d => d.Source.FileName.ToString()).ToArray();
2627
Assert.Equal(2, files.Length);
2728
Assert.Contains("1.js", files);
2829
Assert.Contains("2.js", files);
2930
}
3031

3132
[Fact]
32-
public async Task CopyToFlattensOutputPath()
33+
public async Task CopyToFlattensOutputPathForFiles()
3334
{
3435
//arrange
3536
var docs = new List<IDocument>
3637
{
37-
new TestDocument(new NormalizedPath("x/1.js")),
38-
new TestDocument(new NormalizedPath("y/2.js"))
38+
new TestDocument(new NormalizedPath("/node_modules/x/1.js")),
39+
new TestDocument(new NormalizedPath("/node_modules/y/2.js"))
3940
};
4041
var context = new TestExecutionContext();
4142
context.SetInputs(docs);
@@ -51,4 +52,28 @@ public async Task CopyToFlattensOutputPath()
5152
Assert.Equal("assets/js/1.js", outputDocs[0].Destination);
5253
Assert.Equal("assets/js/2.js", outputDocs[1].Destination);
5354
}
55+
56+
[Fact]
57+
public async Task CopyToDoesNotFlattenOutputPathForDirectories()
58+
{
59+
//arrange
60+
var docs = new List<IDocument>
61+
{
62+
new TestDocument(new NormalizedPath("/node_modules/x/1.js")),
63+
new TestDocument(new NormalizedPath("/node_modules/x/y/2.js"))
64+
};
65+
var context = new TestExecutionContext();
66+
context.SetInputs(docs);
67+
68+
var pipeline = new CopyFromNPM(new[] { "x" }, "assets/js");
69+
var copy = pipeline.ProcessModules.First(m => m is SetDestination);
70+
71+
//act
72+
var output = await copy.ExecuteAsync(context);
73+
74+
//assert
75+
var outputDocs = output.ToArray();
76+
Assert.Equal("assets/js/x/1.js", outputDocs[0].Destination);
77+
Assert.Equal("assets/js/x/y/2.js", outputDocs[1].Destination);
78+
}
5479
}

StatiqPipelines/CopyFromNPM.cs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,50 @@ namespace ecoAPM.StatiqPipelines;
55

66
public class CopyFromNPM : Pipeline
77
{
8+
private const string NodeModulesDirectory = "node_modules/";
9+
private Dictionary<string, ReadFiles> _files;
10+
811
/// <summary>
912
/// Copies specific files from a `node_modules` directory to the output
1013
/// </summary>
1114
/// <param name="paths">The file paths (relative to `node_modules`) to copy</param>
1215
/// <param name="output">The path (relative to the output root) where the files will be copied</param>
16+
/// <param name="flatten">Flatten all files into the <see cref="output">output</see> directory</param>
1317
public CopyFromNPM(IEnumerable<string> paths, string output = "lib")
1418
{
19+
_files = paths.ToDictionary(p => p, p => new ReadFiles(npmPath(p)));
20+
1521
Isolated = true;
16-
InputModules = new ModuleList
17-
{
18-
new NodeRestore(),
19-
new ReadFiles(npmPath(paths))
20-
};
21-
ProcessModules = new ModuleList
22-
{
23-
CopyTo(output)
24-
};
25-
OutputModules = new ModuleList
26-
{
27-
new WriteFiles()
28-
};
22+
InputModules = new ModuleList { new NodeRestore() };
23+
InputModules.AddRange(_files.Values);
24+
25+
ProcessModules = new ModuleList { CopyTo(output) };
26+
27+
OutputModules = new ModuleList { new WriteFiles() };
2928
}
3029

31-
private static IReadOnlyList<string> npmPath(IEnumerable<string> paths)
32-
=> paths.Select(p => IExecutionContext.Current.FileSystem
33-
.GetRootDirectory("node_modules").GetFile(p)
34-
.Path.FullPath.Replace("\\", "/"))
35-
.ToArray();
30+
private static string npmPath(string path)
31+
=> IExecutionContext.Current.FileSystem
32+
.GetRootDirectory(NodeModulesDirectory).GetFile(path)
33+
.Path.FullPath.Replace("\\", "/");
3634

37-
private static SetDestination CopyTo(string output)
35+
private SetDestination CopyTo(string output)
3836
=> new(SetPath(output));
3937

40-
private static Config<NormalizedPath> SetPath(string output)
38+
private Config<NormalizedPath> SetPath(string output)
4139
=> Config.FromDocument(d => NewPath(output, d));
4240

43-
private static NormalizedPath NewPath(string output, IDocument d)
41+
private NormalizedPath NewPath(string output, IDocument d)
4442
=> new(OutputPath(output, d));
4543

46-
private static string OutputPath(string output, IDocument d)
47-
=> Path.Combine(output, d.Source.FileName.ToString());
44+
private string OutputPath(string output, IDocument d)
45+
=> Path.Combine(output, RelativeOutputPath(d));
46+
47+
private string RelativeOutputPath(IDocument d)
48+
=> _files.ContainsKey(RelativePath(d))
49+
? d.Source.FileName.ToString()
50+
: RelativePath(d);
51+
52+
private static string RelativePath(IDocument d)
53+
=> d.Source.RootRelative.ToString().RemoveStart(NodeModulesDirectory);
4854
}

StatiqPipelines/StatiqPipelines.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
5-
<Version>1.0.0</Version>
5+
<Version>1.1.0</Version>
66
<PackageId>ecoAPM.StatiqPipelines</PackageId>
77
<RootNamespace>ecoAPM.StatiqPipelines</RootNamespace>
88
<Description>Pipelines and helpers used in ecoAPM's static sites</Description>

0 commit comments

Comments
 (0)