Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,10 @@ private void handleAsset(String npmModule, String npmAsset) {
File npmModuleDir = new File(options.getNodeModulesFolder(), npmModule);

List<Path> paths = collectFiles(npmModuleDir.toPath(), rule.copyRule);
Path basePath = getBasePath(npmModuleDir.toPath(), rule.copyRule);

paths.stream().map(Path::toFile).forEach(file -> {
copyFileToTarget(file, new File(staticOutput, rule.targetFolder));
copyFileToTarget(file, rule, basePath);
});
}

Expand All @@ -144,8 +145,13 @@ private Rule getRule(String npmAsset, String npmModule) {
return rule;
}

private void copyFileToTarget(File file, File targetFolder) {
File destFile = new File(targetFolder, file.getName());
private void copyFileToTarget(File file, Rule copyRule, Path basePath) {
File baseDestinationFolder = new File(staticOutput,
copyRule.targetFolder);

Path relativePath = basePath.relativize(file.toPath());
File destFile = new File(baseDestinationFolder,
relativePath.toString());
// Copy file to a target path, if target file doesn't exist
// or if file to copy is newer.
if (!destFile.exists()
Expand All @@ -162,6 +168,36 @@ private void copyFileToTarget(File file, File targetFolder) {
}
}

private Path getBasePath(Path npmModuleDir, String copyRule) {
// Extract the static part of the copy rule (before any wildcards)
String basePathStr = copyRule;

// Remove leading slashes
if (basePathStr.startsWith("/")) {
basePathStr = basePathStr.substring(1);
}

int wildcardIndex = -1;
if (basePathStr.contains("*")) {
wildcardIndex = basePathStr.indexOf('*');
} else if (basePathStr.contains("?")) {
wildcardIndex = basePathStr.indexOf('?');
}

if (wildcardIndex != -1) {
basePathStr = basePathStr.substring(0, wildcardIndex);
// Remove trailing slash or incomplete path segment
int lastSlash = basePathStr.lastIndexOf('/');
if (lastSlash != -1) {
// Resolve the base path relative to npmModuleDir
return npmModuleDir
.resolve(basePathStr.substring(0, lastSlash));
}
}

return npmModuleDir;
}

private List<Path> collectFiles(Path basePath, String matcherPattern) {
final List<Path> filePaths = new ArrayList<>();
if (!basePath.toFile().exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,29 @@ public void assertFolderIsCopied() throws IOException {
.contains("VAADIN/static/assets/button/image.gif"));
}

@Test
public void copiedFolderStructureIsKept() throws IOException {
Mockito.when(scanner.getAssets())
.thenReturn(Map.of("test-button", List.of("**:button")));

TaskCopyNpmAssetsFiles taskCopyNpmAssetsFiles = new TaskCopyNpmAssetsFiles(
options);
taskCopyNpmAssetsFiles.execute();

Set<String> filesInDirectory = getFilesInDirectory(
webappResourcesDirectory);
Assert.assertEquals(3, filesInDirectory.size());
Assert.assertTrue("Could not find file images/image.jpg",
filesInDirectory.contains(
"VAADIN/static/assets/button/images/image.jpg"));
Assert.assertTrue("Could not find file images/image.gif",
filesInDirectory.contains(
"VAADIN/static/assets/button/images/image.gif"));
Assert.assertTrue("Could not find file templates/button.template",
filesInDirectory.contains(
"VAADIN/static/assets/button/templates/button.template"));
}

@Test
public void singleAssertFromFolderIsCopied() throws IOException {
Mockito.when(scanner.getAssets()).thenReturn(
Expand Down
Loading