From 0f03dc75dc3f75dca6f53257376bd2440c07218f Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Mon, 25 Dec 2023 18:20:21 +0100 Subject: [PATCH 1/2] feat: support for images --- CHANGELOG.md | 4 ++ .../render/ImageTreeprocessor.java | 43 ++++++++++++++++++ .../refinedsites/render/PageInfo.java | 4 +- .../refinedsites/render/Renderer.java | 44 ++++++++++++++----- 4 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/refinedmods/refinedsites/render/ImageTreeprocessor.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f8931bf..5c6ae32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Support for images. + ## [0.2.3] - 2023-12-24 ### Fixed diff --git a/src/main/java/com/refinedmods/refinedsites/render/ImageTreeprocessor.java b/src/main/java/com/refinedmods/refinedsites/render/ImageTreeprocessor.java new file mode 100644 index 0000000..35c6123 --- /dev/null +++ b/src/main/java/com/refinedmods/refinedsites/render/ImageTreeprocessor.java @@ -0,0 +1,43 @@ +package com.refinedmods.refinedsites.render; + +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import lombok.RequiredArgsConstructor; +import org.asciidoctor.ast.Document; +import org.asciidoctor.ast.StructuralNode; +import org.asciidoctor.extension.Treeprocessor; + +@RequiredArgsConstructor +public class ImageTreeprocessor extends Treeprocessor { + private final Path currentPageSourcePath; + private final Path currentPageOutputPath; + private final Map sourceToDestinationAssets; + + @Override + public Document process(final Document document) { + processBlock(document); + return document; + } + + private void processBlock(final StructuralNode block) { + final List blocks = block.getBlocks(); + for (int i = 0; i < blocks.size(); i++) { + final StructuralNode currentBlock = blocks.get(i); + if ("image".equals(currentBlock.getContext())) { + final Path sourcePath = currentPageSourcePath.getParent().resolve( + (String) currentBlock.getAttribute("target") + ).normalize(); + final Path destinationPath = sourceToDestinationAssets.get(sourcePath); + if (destinationPath == null) { + throw new RuntimeException("Asset " + sourcePath + " not found"); + } + final Path relativePath = currentPageOutputPath.getParent().relativize(destinationPath); + currentBlock.setAttribute("target", relativePath.toString(), true); + } else { + processBlock(currentBlock); + } + } + } +} diff --git a/src/main/java/com/refinedmods/refinedsites/render/PageInfo.java b/src/main/java/com/refinedmods/refinedsites/render/PageInfo.java index f1184b4..ab353e6 100644 --- a/src/main/java/com/refinedmods/refinedsites/render/PageInfo.java +++ b/src/main/java/com/refinedmods/refinedsites/render/PageInfo.java @@ -1,5 +1,6 @@ package com.refinedmods.refinedsites.render; +import java.nio.file.Path; import java.util.List; import lombok.Builder; @@ -10,5 +11,6 @@ record PageInfo(String title, String relativePath, String icon, IconReferences iconReferences, - List tableOfContents) { + List tableOfContents, + Path pageOutputPath) { } diff --git a/src/main/java/com/refinedmods/refinedsites/render/Renderer.java b/src/main/java/com/refinedmods/refinedsites/render/Renderer.java index 695614c..2873929 100644 --- a/src/main/java/com/refinedmods/refinedsites/render/Renderer.java +++ b/src/main/java/com/refinedmods/refinedsites/render/Renderer.java @@ -150,8 +150,11 @@ private void renderComponent(final Component component, sitemapBaseUrl, componentOutputPath ); + final Map sourceToDestinationAssets; if (component.getAssetsPath() != null) { - copyComponentAssets(component, assetsOutputPath); + sourceToDestinationAssets = copyComponentAssets(component, assetsOutputPath); + } else { + sourceToDestinationAssets = Collections.emptyMap(); } final Releases releases = site.getReleases(component); if (component.isLatest() && releases != null) { @@ -165,7 +168,13 @@ private void renderComponent(final Component component, final PageAttributeCache pageAttributeCache = new PageAttributeCache(); final Map pageInfo = new HashMap<>(); for (final Path pagePath : component.getPages()) { - pageInfo.put(pagePath, renderPagePre(pagePath, component, pageAttributeCache)); + pageInfo.put(pagePath, renderPagePre( + pagePath, + component, + pageAttributeCache, + sourceToDestinationAssets, + componentOutputPath + )); } prepareNavigationItems(component.getNavigationItems(), pageInfo); for (final Path pagePath : component.getPages()) { @@ -300,31 +309,37 @@ private void prepareNavigationItems(final List navigationItems, }); } - private void copyComponentAssets(final Component component, - final Path assetsOutputPath) throws IOException { + private Map copyComponentAssets(final Component component, + final Path assetsOutputPath) throws IOException { if (!Files.exists(component.getAssetsPath())) { - return; + return Collections.emptyMap(); } final Path componentAssetsPath = assetsOutputPath.resolve( component.getAssetsOutputPath() + "/" ); + final Map sourceToDestinationAssets = new HashMap<>(); Files.walk(component.getAssetsPath()).forEach(path -> { final Path relativePath = component.getAssetsPath().relativize(path); final Path targetPath = componentAssetsPath.resolve(relativePath); try { Files.createDirectories(targetPath.getParent()); Files.copy(path, targetPath); + sourceToDestinationAssets.put(path.normalize(), targetPath); } catch (final IOException e) { throw new RuntimeException(e); } }); + return sourceToDestinationAssets; } private PageInfo renderPagePre(final Path pagePath, final Component component, - final PageAttributeCache attributeCache) { + final PageAttributeCache attributeCache, + final Map sourceToDestinationAssets, + final Path componentOutputPath) { log.info("Parsing Asciidoc for page {}", pagePath); final String relativePath = component.getRelativePagePath(component.getPagesPath(), pagePath); + final Path pageOutputPath = componentOutputPath.resolve(relativePath); final IconReferences icons = new IconReferences(); try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) { final PageAttributeCache.PageAttributes pageAttributes = attributeCache.getAttributes( @@ -332,6 +347,11 @@ private PageInfo renderPagePre(final Path pagePath, pagePath ); asciidoctor.javaExtensionRegistry().includeProcessor(new IncludeProcessorImpl()); + asciidoctor.javaExtensionRegistry().treeprocessor(new ImageTreeprocessor( + pagePath, + pageOutputPath, + sourceToDestinationAssets + )); asciidoctor.javaExtensionRegistry().inlineMacro(new XRefInlineMacroProcessor( component, pagePath, @@ -353,6 +373,7 @@ private PageInfo renderPagePre(final Path pagePath, .replace(" Date: Mon, 25 Dec 2023 17:22:34 +0000 Subject: [PATCH 2/2] chore: prepare release v0.3.0 --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c6ae32..0e8253c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.3.0] - 2023-12-25 + ### Added -- Support for images. +- Support for images. ## [0.2.3] - 2023-12-24 @@ -53,7 +55,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Initial release. -[Unreleased]: https://github.com/refinedmods/refinedsites/compare/v0.2.3...HEAD +[Unreleased]: https://github.com/refinedmods/refinedsites/compare/v0.3.0...HEAD + +[0.3.0]: https://github.com/refinedmods/refinedsites/compare/v0.2.3...v0.3.0 [0.2.3]: https://github.com/refinedmods/refinedsites/compare/v0.2.2...v0.2.3