2525import com .github .jknack .handlebars .helper .ext .AssignHelper ;
2626import com .github .jknack .handlebars .helper .ext .IncludeHelper ;
2727import com .github .jknack .handlebars .helper .ext .NumberHelper ;
28+ import com .github .jknack .handlebars .io .AbstractTemplateLoader ;
2829import com .github .jknack .handlebars .io .ClassPathTemplateLoader ;
2930import com .github .jknack .handlebars .io .TemplateLoader ;
30- import com .github .jknack .handlebars .io .URLTemplateLoader ;
31+ import com .github .jknack .handlebars .io .TemplateSource ;
3132import java .io .File ;
3233import java .io .IOException ;
34+ import java .net .URI ;
35+ import java .net .URISyntaxException ;
3336import java .net .URL ;
37+ import java .nio .charset .Charset ;
3438import java .nio .charset .StandardCharsets ;
3539import java .nio .file .Path ;
3640import java .util .Arrays ;
3741import java .util .Base64 ;
42+ import javax .annotation .Nonnull ;
3843import net .rptools .maptool .model .Token ;
44+ import net .rptools .maptool .model .library .Library ;
45+ import net .rptools .maptool .model .library .LibraryManager ;
3946import org .apache .logging .log4j .LogManager ;
4047import org .apache .logging .log4j .Logger ;
4148
@@ -52,50 +59,62 @@ public class HandlebarsUtil<T> {
5259 /** Logging class instance. */
5360 private static final Logger log = LogManager .getLogger (Token .class );
5461
62+ /** Handlebars partial template source that uses Add-On files */
63+ private static record LibraryTemplateSource (@ Nonnull Library library , @ Nonnull String filename )
64+ implements TemplateSource {
65+ @ Override
66+ public long lastModified () {
67+ // No modification time is available.
68+ return -1 ;
69+ }
70+
71+ @ Override
72+ @ Nonnull
73+ public String content (@ Nonnull final Charset charset ) throws IOException {
74+ try {
75+ // The library API requires a URL even if it only uses the path.
76+ var url = new URI ("lib" , library .getNamespace ().join (), filename , null ).toURL ();
77+ try (var is = library .read (url ).join ()) {
78+ return new String (is .readAllBytes (), charset );
79+ }
80+ } catch (URISyntaxException e ) {
81+ throw new AssertionError ("lib URL of namespace and filename should be valid" , e );
82+ }
83+ }
84+ }
85+
5586 /** Handlebars partial template loader that uses Add-On Library URIs */
56- private static class LibraryTemplateLoader extends URLTemplateLoader {
87+ private static class LibraryTemplateLoader extends AbstractTemplateLoader {
5788 /** Path to template being resolved, relative paths are resolved relative to its parent. */
58- Path current ;
89+ @ Nonnull final Path current ;
5990
60- private LibraryTemplateLoader (String current , String prefix , String suffix ) {
91+ @ Nonnull final Library library ;
92+
93+ private LibraryTemplateLoader (@ Nonnull String current , @ Nonnull Library library ) {
6194 if (!current .startsWith ("/" )) {
6295 current = "/" + current ;
6396 }
6497 this .current = new File (current ).toPath ();
65- setPrefix (prefix );
66- setSuffix (suffix );
98+ this .library = library ;
99+ setPrefix (TemplateLoader .DEFAULT_PREFIX );
100+ setSuffix (TemplateLoader .DEFAULT_SUFFIX );
67101 }
68102
69- private LibraryTemplateLoader (String current , String prefix ) {
70- this (current , prefix , DEFAULT_SUFFIX );
71- }
72-
73- private LibraryTemplateLoader (String current ) {
74- this (current , DEFAULT_PREFIX , DEFAULT_SUFFIX );
75- }
76-
77- /** Normalize locations by removing redundant path components */
103+ /** Resolve possibly relative uri to a new location relative to current rooted below prefix */
78104 @ Override
79- protected String normalize (final String location ) {
80- return new File (location ).toPath ().normalize ().toString ();
81- }
82-
83- /** Resolve possibly relative uri relative to current rooted below prefix */
84- @ Override
85- public String resolve (final String uri ) {
86- var location = current .resolveSibling (uri ).normalize ().toString ();
105+ @ Nonnull
106+ public String resolve (@ Nonnull final String path ) {
107+ var location = current .resolveSibling (path ).normalize ().toString ();
87108 if (location .startsWith ("/" )) {
88109 location = location .substring (1 );
89110 }
90111 return getPrefix () + location + getSuffix ();
91112 }
92113
93114 @ Override
94- protected URL getResource (String location ) throws IOException {
95- if (location .startsWith ("/" )) {
96- location = location .substring (1 );
97- }
98- return new URL ("lib://" + location );
115+ @ Nonnull
116+ public LibraryTemplateSource sourceAt (@ Nonnull final String location ) {
117+ return new LibraryTemplateSource (library , resolve (location ));
99118 }
100119 }
101120
@@ -155,7 +174,12 @@ private HandlebarsUtil(String stringTemplate, TemplateLoader loader) throws IOEx
155174 * @throws IOException If there is an error compiling the template.
156175 */
157176 public HandlebarsUtil (String stringTemplate , URL entry ) throws IOException {
158- this (stringTemplate , new LibraryTemplateLoader (entry .getHost () + entry .getPath ()));
177+ this (
178+ stringTemplate ,
179+ new LibraryTemplateLoader (
180+ entry .getPath (),
181+ // Template is defined by AddOn so library should always be present.
182+ new LibraryManager ().getLibrary (entry ).join ().orElseThrow ()));
159183 }
160184
161185 /**
0 commit comments