diff --git a/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLContent.java b/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLContent.java index 0ba0913ff0..d796ab08e8 100644 --- a/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLContent.java +++ b/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLContent.java @@ -313,23 +313,23 @@ public HTMLContent fetchContent() throws IOException { if (!(content instanceof UrlContent urlContent)) { throw new IllegalStateException("HTMLContent is not a URL"); } + var url = urlContent.url(); try { - Optional libraryOpt = new LibraryManager().getLibrary(urlContent.url()).get(); + Optional libraryOpt = new LibraryManager().getLibrary(url).get(); if (libraryOpt.isEmpty()) { - throw new IOException( - I18N.getText("msg.error.html.loadingURL", urlContent.url().toExternalForm())); + throw new IOException(I18N.getText("msg.error.html.loadingURL", url.toExternalForm())); } var library = libraryOpt.get(); - var assetKey = library.getAssetKey(urlContent.url()).get().orElse(null); + var assetKey = library.getAssetKey(url).get().orElse(null); // Check if the asset key is null, if so try reading the resource as a string from the // library if (assetKey == null) { - String html = library.readAsString(urlContent.url()).get(); + String html = library.readAsString(url).get(); if (html != null) { - var mediaType = Asset.getMediaType("", html.getBytes(StandardCharsets.UTF_8)); - var assetType = Asset.Type.fromMediaType(mediaType); + var mediaType = Asset.getMediaType(url.getPath(), html.getBytes(StandardCharsets.UTF_8)); + var assetType = Asset.Type.fromMediaType(mediaType, url.getPath()); if (assetType == Asset.Type.HTML) { return new HTMLContent(new HtmlDocumentContent(html)); @@ -352,8 +352,7 @@ public HTMLContent fetchContent() throws IOException { } catch (InterruptedException | ExecutionException e) { throw new IOException(e); } - throw new IOException( - I18N.getText("msg.error.html.loadingURL", urlContent.url().toExternalForm())); + throw new IOException(I18N.getText("msg.error.html.loadingURL", url.toExternalForm())); } /** diff --git a/src/main/java/net/rptools/maptool/model/Asset.java b/src/main/java/net/rptools/maptool/model/Asset.java index 7b6781b167..d628935491 100644 --- a/src/main/java/net/rptools/maptool/model/Asset.java +++ b/src/main/java/net/rptools/maptool/model/Asset.java @@ -44,6 +44,7 @@ import net.rptools.maptool.model.library.addon.AddOnLibraryImporter; import net.rptools.maptool.server.proto.AssetDto; import net.rptools.maptool.server.proto.AssetDtoType; +import net.rptools.maptool.util.HandlebarsUtil; import org.apache.commons.io.FilenameUtils; import org.apache.tika.config.TikaConfig; import org.apache.tika.exception.TikaException; @@ -61,6 +62,8 @@ public enum Type { IMAGE(false, "", Asset::createImageAsset), // extension is determined from format. /** The {@code Asset} is an audio file. */ AUDIO(false, "", Asset::createAudioAsset), // extension is determined from format. + /** The {@code Asset} is a Handlebars template. */ + HANDLEBARS(true, "hbs", Asset::createHandlebarsAsset), /** The {@code Asset} is an HTML string. */ HTML(true, "html", Asset::createHTMLAsset), /** The {@code Asset} is some generic data. */ @@ -161,7 +164,12 @@ public static Type fromMediaType(MediaType mediaType, String filename) { case "image" -> Type.IMAGE; case "text" -> switch (subType) { - case "html" -> Type.HTML; + case "html" -> { + if (HandlebarsUtil.isAssetFileHandlebars(filename)) { + yield Type.HANDLEBARS; + } + yield Type.HTML; + } case "markdown", "x-web-markdown" -> Type.MARKDOWN; case "javascript" -> Type.JAVASCRIPT; case "css" -> Type.CSS; @@ -419,6 +427,18 @@ public static Asset createAssetDetectType(String name, byte[] data, File file) return factory.apply(name, data); } + /** + * Creates a Handlebars {@code Asset}. + * + * @param name The name of the {@code Asset}. + * @param data The data for the {@code Asset}. + * @return the Handlebars {@code Asset}. + */ + public static Asset createHandlebarsAsset(String name, byte[] data) { + return new Asset( + null, name, data, Type.HANDLEBARS, Type.HANDLEBARS.getDefaultExtension(), false); + } + /** * Creates a HTML {@code Asset}. * diff --git a/src/main/java/net/rptools/maptool/model/library/addon/AddOnLibraryImporter.java b/src/main/java/net/rptools/maptool/model/library/addon/AddOnLibraryImporter.java index e0b66d3cb4..76c7159e42 100644 --- a/src/main/java/net/rptools/maptool/model/library/addon/AddOnLibraryImporter.java +++ b/src/main/java/net/rptools/maptool/model/library/addon/AddOnLibraryImporter.java @@ -248,9 +248,9 @@ private void addMetaData( String path = METADATA_DIR + entry.getName(); try (InputStream inputStream = zip.getInputStream(entry)) { byte[] bytes = inputStream.readAllBytes(); - MediaType mediaType = Asset.getMediaType(entry.getName(), bytes); - Asset asset = - Type.fromMediaType(mediaType).getFactory().apply(namespace + "/" + path, bytes); + var assetName = namespace + "/" + path; + MediaType mediaType = Asset.getMediaType(assetName, bytes); + Asset asset = Type.fromMediaType(mediaType, assetName).getFactory().apply(assetName, bytes); addAsset(asset); pathAssetMap.put(path, Pair.with(asset.getMD5Key(), asset.getType())); } @@ -277,9 +277,9 @@ private Map> processAssets(String namespace, ZipFile String path = entry.getName().substring(CONTENT_DIRECTORY.length()); try (InputStream inputStream = zip.getInputStream(entry)) { byte[] bytes = inputStream.readAllBytes(); - MediaType mediaType = Asset.getMediaType(entry.getName(), bytes); - Asset asset = - Type.fromMediaType(mediaType).getFactory().apply(namespace + "/" + path, bytes); + var assetName = namespace + "/" + path; + MediaType mediaType = Asset.getMediaType(assetName, bytes); + Asset asset = Type.fromMediaType(mediaType, assetName).getFactory().apply(assetName, bytes); addAsset(asset); pathAssetMap.put(path, Pair.with(asset.getMD5Key(), asset.getType())); } diff --git a/src/main/java/net/rptools/maptool/util/HandlebarsUtil.java b/src/main/java/net/rptools/maptool/util/HandlebarsUtil.java index ff17e8310d..18d1ab83b2 100644 --- a/src/main/java/net/rptools/maptool/util/HandlebarsUtil.java +++ b/src/main/java/net/rptools/maptool/util/HandlebarsUtil.java @@ -52,6 +52,12 @@ * @param The type of the bean to apply the template to. */ public class HandlebarsUtil { + public static boolean isAssetFileHandlebars(String filename) { + if (filename == null) { + return false; + } + return filename.toLowerCase().endsWith(".hbs"); + } /** The compiled template. */ private final Template template;