Welcome, Guest. Please Login
Tinderbox
  News:
IMPORTANT MESSAGE! This forum has now been replaced by a new forum at http://forum.eastgate.com and no further posting or member registration is allowed. The forum is still accessible via read-only access for reference purposes. If you wish to discuss content here, please use the new forum. N.B. - posting in the new forum requires a fresh registration in the new forum (sorry - member data can't be ported).
  HomeHelpSearchLogin  
 
Pages: 1
Send Topic Print
Testing the contents of values in macros. (Read 6004 times)
Ioa Petra-ka
Full Member
*
Offline



Posts: 103
Portland, Oregon, USA
Testing the contents of values in macros.
Apr 16th, 2010, 6:38pm
 
I have been attempting to create a macro which reacts to the content that is sent to it via the template. Here is an example what what I would like to in the template:

Code:
^do(image, "src", "alt") 



The template generates HTML intended for e-mail delivery, and thus needs to use absolute URLs. To keep things dynamic and sane, the top level container for the newsletter stores an `NLBaseURL` attribute which all of the templates can use to generate more complete URLs with minimal fuss. However, sometimes the newsletter will link to images not in the newsletter’s base web folder. So what I would like to do is be able to pass absolute URLs to the `src` value and have the macro not prefix the URL with `NLBaseURL`, but if no full URL is given, the macro prefixes the image name appropriately. Using Agent code, something like this could be accomplished with:

Code:
if (Var(http)) {
    $URL = $Var;
} else {
    $URL = $NLBaseURL(parent) + $Var;
} 



It is possible to translate this into template code (Obviously, the indenting and carriage returns are for clarity. Using this code verbatim in a template would make a mess):

Code:
<a href="
    ^if(^not(Var(http))^)^
        ^value($NLBaseURL(parent))^
    ^endif^
    ^value($Var)^
" alt="^value($Alt)^"> 



There however doesn’t seem to be a way to translate these concepts into macros, and I’m guessing the problem has to do with addressing attributes without the `$` when doing regular expressions on them. Since there is no way to address a macro value without the `$` prefixing the numeral, there is hence no way to test them with regular expression. I’d like to be able to do the following (again with spacing for clarity):

Code:
<a href="
    ^if(^not($1(http))^)^
        ^value($NLBaseURL(parent))^
    ^endif^
    $1
" alt="$2"> 



But this just doesn’t work. The value of `$1(http)` is always true, no matter if ‘http’ is found in the string passed to $1 or not. It’s probably trying to look for a note named ‘http’, which is a nonsensical task in this particular context, since $1 does not exist outside of the macro anyway.

And yes, I have tried `^if(1(http))^`.

The only solution that I can think of is:

Code:
^action($TempVar = $1)^
^if(^not(TempVar(http))^)^
    ... 



There’s got to be better way to do this than that! In my experience setting lots of attributes with actions really slows down export, and doing this for every image in the export will result in a lot of that going on.
Back to top
 
 

Av
  IP Logged
Mark Bernstein
YaBB Administrator
*
Offline

designer of
Tinderbox

Posts: 2871
Eastgate Systems, Inc.
Re: Testing the contents of values in macros.
Reply #1 - Apr 16th, 2010, 7:07pm
 
Good conundrum.

This can be made to work -- I've been doing something like this for years in an image macro where, if extra arguments are supplied, you generate markup for captions and a box.  But, as you observe, the template-language ^if^ syntax gets cumbersome.

My suggestions:

a) Nested macros help a lot!
b) Storing intermediate results in an attribute can help break up a complex expression into two or three simpler ones.

c) ^value() lets you use action expressions in templates and macros. I expect ^value() (or maybe ^action() ) will make this much simpler for you.
Back to top
 
 
WWW   IP Logged
Ioa Petra-ka
Full Member
*
Offline



Posts: 103
Portland, Oregon, USA
Re: Testing the contents of values in macros.
Reply #2 - Apr 16th, 2010, 7:38pm
 
I've gone with using actions to set a temporary attribute with the value I wish to perform a regular expression on. Based on my usage of actions in the text part exporter (the text template sets a globally referenced note's attribute to TXT or HTML and all of the macros fork their output based on the output mode), I was expecting things to be *really* slow. There are only a few calls to that action but the text exporter always takes about six or eight seconds to complete. There are many more images than that. However, I found the results to be instantaneous despite the fact that there must be around 30 action calls happening.

The only thing I can speculate on is that there is some slowness in external note set as opposed to setting a notes own attribute. Perhaps there is a degree of time required to search the xml tree for the external note, even though I'm provide a full path. Here are the two action calls:

1. Code:
^action($ExportMode(/Library/ExportMode) = "TXT")^ 



2. Code:
^action($TmpVar = $1)^ 



Why would 10 calls to #1 be noticeably slow while 30+ calls to #2 produce no delay whatsoever? It's not a huge issue because I need to optimise that anyway. There is no need to be setting the mode to TXT over and over during export.

Update: Actually no. I take that back. I've already fixed that problem. The variable is being set only once at the top of the text export template. I have no idea why the text exporter is taking 8 times longer to execute than the HTML exporter. All of the logic forks happen identically. The only difference is that I'm nearly always testing for TXT truth. Does a truth result take longer to resolve than a false result? Well, I'll have to investigate what is happening. Could be something mildly circular in there.

Whatever the case, this problem is effectively solved as it appears to be entirely viable to use temporary attribute for regular expressions on macro values.
Back to top
 
« Last Edit: Apr 16th, 2010, 7:41pm by Ioa Petra-ka »  

Av
  IP Logged
Ioa Petra-ka
Full Member
*
Offline



Posts: 103
Portland, Oregon, USA
Re: Testing the contents of values in macros.
Reply #3 - Apr 16th, 2010, 7:46pm
 
Ah ha. I think I know what it is. When the mode is TXT, the containers temporarily switch their prototypes to an alternate that has very little or no styling. I need markup turned on so that macro code and such is executed, but everything else is stripped. I suspect that

1. Storing the current prototype
2. Switching to a plain-text version of the prototype
3. Executing
4. Switching back to stored prototype

is what is causing the slow-down. Would be nice to have a mode where HTML styling is not used, but template code still executes. Smiley
Back to top
 
 

Av
  IP Logged
Ioa Petra-ka
Full Member
*
Offline



Posts: 103
Portland, Oregon, USA
Re: Testing the contents of values in macros.
Reply #4 - Apr 16th, 2010, 8:13pm
 
The final “recipe” for anyone who comes across this and needs something similar, is to break things out a bit to keep code clean and non-redundant. You’ll need a temporary string attribute, which I’m calling `$TmpVar` in these examples. This will be used to temporarily store the value of what you provide the macro. When applied to this particular case of wishing to add data to an image src, you could set up the helper macro like this:

cleanSRC:

Code:
^action($TmpVar = $1)^^if(^not(TmpVar(http))^)^http://www.yourdomain.com/img/prefix/$1^else^$1^endif^ 



Obviously, you’ll probably want to replace the raw URL prefix with the value of some universal attribute somewhere. Now here is an example image macro which takes the values src and alt in that order:

image:

Code:
<img src="^do(cleanSRC, $1)^" alt="$2" /> 



Of course you could just put the logic in the `cleanSRC()` macro directly into that, but this makes it so you can create many variations of the image macro, all using the same function to clean URLs. If you ever change your mind about how URLs should be presented (like say, changing that raw string into a value), you only need to change one macro and they’ll all be good to go.

The basic concepts here could be used for any number of tasks, and in fact you could create a nice general function with the following macro:

grep:

Code:
^action($TmpVar = $1)
^if(TmpVar($2))^true^else^false^endif^ 



Now you can do general regular expression in other macros like this:

Code:
^if(^equal(^do(grep, $1, "string"), 'true')^)^
    One thing
^else^
    or another.
^endif^ 

Back to top
 
 

Av
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 5689
Southsea, UK
Re: Testing the contents of values in macros.
Reply #5 - Apr 17th, 2010, 11:48am
 
Thanks for sharing this.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v6
(TB consulting - email me)
WWW shoantel   IP Logged
Mark Bernstein
YaBB Administrator
*
Offline

designer of
Tinderbox

Posts: 2871
Eastgate Systems, Inc.
Re: Testing the contents of values in macros.
Reply #6 - Apr 17th, 2010, 12:18pm
 
Remember: if you are exporting an entire document with text export template T, that template is parsed and evaluated for every note in the document.

Also, if you have a large document, evaluating the path expression $MyVar(/path/to/some/note) is indeed somewhat slower than evaluating $MyVar.  But it sounds like you're seeing something *really* slow.  Email me a sample case and I'll try to figure out what's causing the delay.
Back to top
 
 
WWW   IP Logged
Ioa Petra-ka
Full Member
*
Offline



Posts: 103
Portland, Oregon, USA
Re: Testing the contents of values in macros.
Reply #7 - Apr 17th, 2010, 2:26pm
 
Right, the export node uses a single template at the top which does the mode switching. Each of the data nodes have smaller templates built into the Tb file itself, they aren't using the master template. The smaller ones are extremely simple. For the text mode anyway, little more than ^title^ ^text^.

I'm afraid I can no longer provide a working example of the slow-down I was encountering. Somewhere in the course of yesterday's optimisations, it got fixed, and the performance of the document is now uniform with all export modes. Since the prototype switch action is still in place, it wasn't that either. Frankly I'm not sure what it was, but if I come across it again I'll be sure to send you further data.
Back to top
 
 

Av
  IP Logged
Pages: 1
Send Topic Print