4242import io .yupiik .asciidoc .parser .Parser ;
4343import io .yupiik .asciidoc .parser .internal .LocalContextResolver ;
4444import io .yupiik .asciidoc .parser .internal .Reader ;
45+ import io .yupiik .asciidoc .parser .resolver .ContentResolver ;
4546import io .yupiik .asciidoc .renderer .Visitor ;
4647import io .yupiik .asciidoc .renderer .a2s .YupiikA2s ;
4748import io .yupiik .asciidoc .renderer .uri .DataResolver ;
@@ -88,6 +89,8 @@ public class AsciidoctorLikeHtmlRenderer implements Visitor<String> {
8889 protected final boolean dataUri ;
8990 protected final DataResolver resolver ;
9091 protected final State state = new State (); // this is why we are not thread safe
92+ protected final Parser subParser ;
93+ protected final ContentResolver subResolver ;
9194
9295 public AsciidoctorLikeHtmlRenderer () {
9396 this (new Configuration ().setAttributes (Map .of ()));
@@ -101,6 +104,8 @@ public AsciidoctorLikeHtmlRenderer(final Configuration configuration) {
101104 this .resolver = dataUri ?
102105 (configuration .getResolver () == null ? new DataResolver (assetsDir (configuration , "imagesdir" )) : configuration .getResolver ()) :
103106 null ;
107+ this .subParser = new Parser (configuration .getAttributes () == null ? Map .of () : configuration .getAttributes ());
108+ this .subResolver = new LocalContextResolver (configuration .getAssetsBase ());
104109 }
105110
106111 private Path assetsDir (final Configuration configuration , final String attribute ) {
@@ -815,25 +820,11 @@ public void visitMacro(final Macro element) {
815820 final var label = element .options ().getOrDefault ("" , element .label ());
816821 if (label .contains ("image:" )) { // FIXME: ...we don't want options to be parsed but this looks required
817822 try {
818- final var parser = new Parser (configuration .getAttributes () == null ? Map .of () : configuration .getAttributes ());
819- final var body = parser .parseBody (new Reader (List .of (label )), new LocalContextResolver (configuration .getAssetsBase ()));
823+ final var body = subParser .parseBody (new Reader (List .of (label )), subResolver );
820824 if (body .children ().size () == 1 && body .children ().get (0 ) instanceof Text t && t .style ().isEmpty ()) {
821825 visitLink (new Link (element .label (), new Text (List .of (), t .value (), Map .of ()), element .options ()));
822826 } else {
823- final var nested = new AsciidoctorLikeHtmlRenderer (configuration );
824- nested .state .sawPreamble = true ;
825- (body .children ().size () == 1 && body .children ().get (0 ) instanceof Paragraph p ?
826- p .children () :
827- body .children ()).stream ()
828- .map (e -> e instanceof Text t ?
829- new Text (t .style (), t .value (), Stream .concat (
830- t .options ().entrySet ().stream (),
831- Stream .of (entry ("nowrap" , "true" )))
832- .collect (toMap (Map .Entry ::getKey , Map .Entry ::getValue , (a , b ) -> b ))) :
833- e )
834- .forEach (nested ::visitElement );
835-
836- final var html = nested .result ();
827+ final var html = render (body ).result ();
837828 visitLink (new Link (element .label (), new Text (List .of (), html , Map .of ()), Stream .concat (element .options ().entrySet ().stream (), Stream .of (entry ("unsafeHtml" , "true" )))
838829 .collect (toMap (Map .Entry ::getKey , Map .Entry ::getValue , (a , b ) -> b ))));
839830 }
@@ -896,7 +887,36 @@ protected void visitXref(final Macro element) {
896887 target = relFilePrefix + target .substring (0 , target .length () - ".adoc" .length ()) + relFileSuffix ;
897888 }
898889 final var label = element .options ().get ("" );
899- builder .append (" <a href=\" " ).append (target ).append ("\" >" ).append (label == null ? element .label () : label ).append ("</a>\n " );
890+ builder .append (" <a href=\" " ).append (target ).append ("\" >" ).append (label == null ? element .label () : parseLabel (label )).append ("</a>\n " );
891+ }
892+
893+ // FIXME: should it be done in Parser? but macro label isn't supposed to be interpreted in parser....
894+ private String parseLabel (final String label ) {
895+ try {
896+ final var body = subParser .parseBody (new Reader (List .of (label )), subResolver );
897+ if (body .children ().size () == 1 && body .children ().get (0 ) instanceof Text t && t .style ().isEmpty ()) {
898+ return label ;
899+ }
900+ return render (body ).result ();
901+ } catch (final RuntimeException re ) {
902+ return label ;
903+ }
904+ }
905+
906+ private AsciidoctorLikeHtmlRenderer render (final Body body ) {
907+ final var nested = new AsciidoctorLikeHtmlRenderer (configuration );
908+ nested .state .sawPreamble = true ;
909+ (body .children ().size () == 1 && body .children ().get (0 ) instanceof Paragraph p ?
910+ p .children () :
911+ body .children ()).stream ()
912+ .map (e -> e instanceof Text t ?
913+ new Text (t .style (), t .value (), Stream .concat (
914+ t .options ().entrySet ().stream (),
915+ Stream .of (entry ("nowrap" , "true" )))
916+ .collect (toMap (Map .Entry ::getKey , Map .Entry ::getValue , (a , b ) -> b ))) :
917+ e )
918+ .forEach (nested ::visitElement );
919+ return nested ;
900920 }
901921
902922 // todo: enhance
0 commit comments