Resource macros with folder paths

Hey RMS guys (@dan @tpbradley),

I’ve got a question for you about generating resource macros – specifically to resources that are in a folder within the resources folder.

I’m posting this here because it doesn’t really seem like a bug – other parts of RW do the right thing – so I’m guessing I’m just using the API wrong. But it wasn’t obvious what I needed to do to fix the issue – I figured anyone else using resources might have the same question.

OK, here goes:

When I want to publish a resource image I make a <img> tag of course and the src property gets filled in with the RW Resource macro. I generate the macro using RWDocument’s method:

- (NSString *)macroStringForResource:(RWSiteResource *)resource;

It seems to work fine and passes me back a macro like this:

It doesn’t work, obviously. It’s missing the folder info.

But a Styled Text page with the same resource seems to work. So, clearly there’s some way to fetch the correct macro.

And if I Ctrl-Click on the resource and choose Copy Macro then the macro I get is:


And this works! Even on the stacks page I can use this macro in an HTML stack to make an <img> tag and it works great.

So what am I doing wrong? How do I get the folder info? How is the Styled Text plugin doing this? And how does the Copy Macro method differ from the method that I’m calling?


1 Like

Also: I did find a little bug while researching this:

  1. Add a resource using the API method:

NSSiteResource *resource = [nsDocument addResourceForURL:url error:&error];

  1. Now move the image into a folder in the resources window.
  2. Save. Quit. Relaunch.
  3. Now if you call, using the same URL as the image in step #1:

NSSiteResource *resource = [nsDocument resourceForURL:url];


resource => nil

  1. Now if you call, using the same URL as the image in step #1:

NSSiteResource *resource = [nsDocument addResourceForURL:url error:&error];

A new new resource at the top level of the resources is created and the object returned.

I would expect both of these methods to be hierarchical.

Also: the Styled Text plugin again manages to do the right thing. can you explain what methods I should use to search the entire resources folder tree for an existing URL?

Hey @Isaiah,

I think this should be classed as a bug. From looking at the code I can see that - (NSString *)macroStringForResource:(RWSiteResource *)resource; simply returns the filename of the resource wrapped in %resource(). Other areas of RW, like the resource browser will build a full path to the resource.

This looks to be a historic thing where multiple folder levels were introduced at a later point and macroStringForResource wasn’t updated to return a full path. I also have a vague recollection that during export, a resource with the given name will be searched for. I had a quick look in the exporter and couldn’t see anything so it may have been a possible ‘fix’ we thought about at some point.

I don’t see a problem with updating the macroStringForResource method to return a full path but I think a bigger problem is that as soon as you move or rename a resource, all the resource macros break. I’m not sure what the solution is yet, maybe the macro should use the resource identifier which doesn’t change - but it’s an ugly uuid that won’t mean anything to the user.

I’ll check into that resourceForURL: bug, it definitely sounds like one. I’m pretty sure the Styled Text plugin uses a method that compares resource checksums to prevent duplicates. Again, I don’t see a problem updating this method to do the same.


1 Like

Oh also, how did you use a resource macro with Styled Text? Was is just coped using the resource browser?

A fix for macroStringForResource is great :+1:

But if there’s a solution that works in code today I’d love to know it – it would be great to have some conditional code to help be a bit more backward compatible too. You don’t have to be too detailed – just a hint at what API are involved, I"m happy to fill in the details.

Also: the macro thing is an unnecessary detour. I store the resource ID. If there’s some direct way to go from ID to published path it would be even better. I only use the macro today because it’s the only way I know how.

1 Like

Unfortunately, I don’t think there’s a solution for this right now. I mean, there’s private methods that will do it but I can’t find an equivalent in the public API. There is a method for generating a link directly from a resource ID but this doesn’t take into account the current publishing destination and could return the wrong thing.

However, I may have come up with something that’ll do what you want and be backwards compatible. I’ll get something simple working and see what you think.

I’m happy to use private API to fill in support for RW7 or RW8.0. Those old versions aren’t going to change, so private API less fragile – so long as public API is used going forward. Surely better than no-support.

I’m happy to have methods that generates links at that need to be modified for hierarchy. Old-days RW worked that way a lot. I’m pretty sure I still have that code lying around.

Currently I have zero support for RW7 and buggy support for RW8. Anything that I can do to improve that is a win.

1 Like