Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Spaces is a macro are being replaced by %20

I have several handouts containing macros that send text to the chat window. Last night, when using one of these the macro failed: instead of sending text to the chat window like this: it instead popped up this window: Which, when I clicking "Continue" sent me to a new browser window displaying a "Page Not Found" error. We continued play with me just verbally describing what the link was supposed to display, so game play wasn't really effected. Later, when I went back to analyse what went wrong, I see that the link definition in the handout had been changed to this: <a href="https://app.roll20.net/editor/%60/emas%20A%20cloud%20of%20fine%20brown%20powder%20sprays%20from%20around%20the%20lock.%20Everyone%20within%205%20ft.%20must%20make%20a%20DC%2013%20Constitution%20saving%20throw%20or%20take%20[[3d6]]%20Poison%20damage.%20If%20the%20saving%20throw%20is%20failed,%20then%20that%20person%20or%20creature%20must%20make%20another%20DC%2013%20Constitution%20saving%20throw%20each%20round%20or%20take%20an%20additional%201d6%20poison%20damage.%20The%20effect%20ends%20after%20the%20person%20or%20creature%20makes%20three%20successful%20saving%20throws" rel="nofollow">https://app.roll20.net/editor/%60/emas%20A%20cloud%20of%20fine%20brown%20powder%20sprays%20from%20around%20the%20lock.%20Everyone%20within%205%20ft.%20must%20make%20a%20DC%2013%20Constitution%20saving%20throw%20or%20take%20[[3d6]]%20Poison%20damage.%20If%20the%20saving%20throw%20is%20failed,%20then%20that%20person%20or%20creature%20must%20make%20another%20DC%2013%20Constitution%20saving%20throw%20each%20round%20or%20take%20an%20additional%201d6%20poison%20damage.%20The%20effect%20ends%20after%20the%20person%20or%20creature%20makes%20three%20successful%20saving%20throws</a>. Instead of this, as I originally wrote it: `/emas A cloud of fine brown powder sprays from around the lock. Everyone within 5 ft. must make a DC 13 Constitution saving throw or take [[3d6]] Poison damage. If the saving throw is failed, then that person or creature must make another DC 13 Constitution saving throw eac round or take an additional 1d6 poison damage. The effect ends after the person or creature makes three successful saving throws. What caused the link definition to change?&nbsp;
1699899835
GiGs
Pro
Sheet Author
API Scripter
I can't say what specifically happened here, but I know that roll20 does parse and change external links. It's best not to use them unless you have tested them before hand. The %20 are html substitutions for spaces: roll20 is parsing the link, trying to make it safe for browser user by changing the spaces to %20. Unfortunately its parsing does sometimes break completely valid links.
1699904311

Edited 1699904349
Weird, because I didn't think that using the backtick ( ` ) to create output to the journal was&nbsp; creating an external link. My bad for not understanding how that worked. Now I'm worried about all my other handouts where I created links using `\emas,&nbsp; `\desc, etc.
1699905033

Edited 1699905057
GiGs
Pro
Sheet Author
API Scripter
Anything which links to an external website will be processed. It doesn't matter if you use a backtick or not.
I didn't think that I was linking to an external web site. Doesn't the backtick ( ` ) just send command to the chat window, and isn't "\emas" just a chat command? Is using double brackets [[ ]] to send die rolls to the chat considered an external link? GiGs said: Anything which links to an external website will be processed. It doesn't matter if you use a backtick or not.
1699908572
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
This is a known (and reported) bug. A back-ticked macro linked in handout text works just fine. Unless the text that includes the link is copied and pasted. Then it will internally parse as if a URL, replacing non-URL characters with html entities and prepending with the domain.
Well, that's an obscure error. That didn't come up when I searched for past occurences of this type of thing, but that's not so surprising. I almost always compose macros (and most handout text for that matter) in an offline text editor then copy/paste when it's ready.&nbsp; keithcurtis said: This is a known (and reported) bug. A back-ticked macro linked in handout text works just fine. Unless the text that includes the link is copied and pasted. Then it will internally parse as if a URL, replacing non-URL characters with html entities and prepending with the domain.
1699915954
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Yeah, I don't know if it is that publicly reported, but I have filed reports on it. The powers that be are aware.
1699917652

Edited 1699996992
The Aaron
Roll20 Production Team
API Scripter
Here's a quick script for fixing this issue, hopefully.&nbsp; Note : When this changes the handout text, you will need to close the handout and open it again to have the changes take effect. You can have it parse all handouts using: !fix-all-handout-urls Here's the script, it will automatically apply the fix to handouts that get saved: on('ready',()=&gt;{ const JournalCommandDecoder = (t) =&gt; { const fixStart = t =&gt; t.replace(/^"https:\/\/app.roll20.net\/editor\/%60/,'"`'); const percentOut = t =&gt; t.replace(/%{/g,'::PERCENT_OPEN_CURLY::'); const percentIn = t =&gt; t.replace(/::PERCENT_OPEN_CURLY::/g,'%{'); return percentIn(decodeURIComponent(percentOut(fixStart(t)))); }; const fixHandoutURLs = (data) =&gt; { const re = new RegExp(`"<a href="https://app.roll20.net/editor/%60[^&quot;]*&quot;`,'g" rel="nofollow">https://app.roll20.net/editor/%60[^"]*"`,'g</a>'); return data.replace(re,JournalCommandDecoder); }; const alterHandout = (obj)=&gt;obj.get('notes',(notesPrime)=&gt;obj.get('gmnotes',(gmnotesPrime)=&gt;{ let notes = fixHandoutURLs(notesPrime); let gmnotes = fixHandoutURLs(gmnotesPrime); if(notes !== notesPrime){ setTimeout(()=&gt;obj.set('notes',notes), 1000); } if(gmnotes !== gmnotesPrime){ setTimeout(()=&gt;obj.set('gmnotes',gmnotes), 2000); } })); on('chat:message',msg=&gt;{ if('api'===msg.type &amp;&amp; /^!fix-all-handout-urls(\b\s|$)/i.test(msg.content) &amp;&amp; playerIsGM(msg.playerid)){ const who = (getObj('player',msg.playerid)||{get:()=&gt;'API'}).get('_displayname'); let handouts=findObjs({type:'handout'}); let c = handouts.length; sendChat('',`/w "${who}" processing ${c} handout(s)"`); const burndown = () =&gt; { let h = handouts.shift(); if(h) { alterHandout(h); setTimeout(burndown,0); } else { sendChat('',`/w "${who}" examined ${c} handout(s)"`); } }; burndown(); } }); on('change:handout',alterHandout); });
Wow! Thanks! And you call that a "quick script"? Your reputation is again reinforced. :) I came looking for an explanation and am walking away with a fix. I'm chalking up today as a win.
1699980560
The Aaron
Roll20 Production Team
API Scripter
Well, it's quick because it's not well tested yet.&nbsp; =D Keith found one edge case that breaks it, using %{...} references causes a decoding error.&nbsp; I've adjusted the script above to account for that.&nbsp; If you get any other crashes, be sure to let me know!
1699997002
The Aaron
Roll20 Production Team
API Scripter
(Updated again to fix a bug... =D)
1699998906
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Super useful! I no longer need to fear editing my journals with lots of command buttons! Thanks, Aaron!
1700027339
vÍnce
Pro
Sheet Author
Aaron's "patches" should automatically be implemented into Roll20. Please hire The Aaron