Can I use export codes in ^value^?

(Pat Maddox) #1

I’m trying to use the return value of ^path^ inside of a ^value^:

^value(^path(/chicken/funky)^.replace('.md', '/'))^

It doesn’t work though… it produces:

chicken/\'.md\', \'/\')

so my workaround is to use an attribute and ^action^

^action($HTMLLinkPath = ^path(/chicken/funky)^)^
^action($HTMLLinkPath = $HTMLLinkPath.replace('.md', '/'))^

which produces:


as expected.

Is there a way to look up ^path^ and call replace on it inside of a ^value^, without using this custom attribute?

(Mark Anderson) #2

See here. ^value()^ is a wrapper for action code expressions. You should be using $Path("/chicken/funky") rather than the export code ^path^.

(Pat Maddox) #3

That works in the simple case that I posted here, but breaks down when I have $HTMLExportFileName set.

Say I have a note called First Parent/First Child, First Parent has $HTMLExportFileName='first-parent' and First Child has $HTMLExportFileName='first-child'

$Path gives me First Parent/First Child, when I really want first-parent/first-child.html (which is what ^path^ gives me).

(Mark Anderson) #4

Might I suggest you post a link to a reference file. This sort of thing is generally hard to do in abstract as generally the solution regards lots of iterations of unstated assumptions that are self-evident if viewed in context.

I sense you want to to set an offset reference (i.e. to some other note that the currently processed one) to ^path^. Have you tried this and found it to fail. note that ^path^ - if it resolves correctly - emits a relative path, but I assume [sic] that’s OK in this setting?

Going back to your first post, you can’t chain action code dot-operators onto export code. The only way to use action code in an export setting is inside an ^action()^ wrapper.

It is probably worth noting that back in 2001(?) when Tinderbox started blogging was one of the uses (@eastgate’s blog is shill written in Tinderbox). Export code was also much less capable then. Export code begun to be used inline in $Text and eventually morphed into action code, with export code relegated to an export role and pruned in scope (see an old baseline of aTbRef to see the change, e.g. here. Throw in 10+ years of incremental improvements I hope this clarifies why there are some dark corners to non-trivial export.

^path(item)^'s optional item argument takes the $Name or $Path (note: non-exported casing) of the desired offset. Duplicate names will fail as >1 match results in the firsts, by $OutlineOrder, being used for the result.

sorry for so much exposition. You can see why a reference doc would help- ideally with in-doc explanatory note’s as to export intent. Indeed, if easier, zip it with specimen HTML output you’d like but can’t (yet) achieve.

(Pat Maddox) #5

Sure, here’s an example file. I took my original file and cut out everything but the most basic example:

broken-link-example.tbx (69.6 KB)

I should clarify that this specific example is a (hopefully) temporary workaround for an export bug: ^linkTo^, ^path^, and ^childLinks^ don’t respect $HTMLLinkExtension (added in 7, so it’s no surprise that there are still kinks to work out).

Still, it serves as an example of a question I have: how do I use the return value of a ^path^ call inside of a ^value^? So far, I’ve identified one way that works (store it in a custom attribute), and one way that doesn’t. I’m asking to see if there’s a way that works that doesn’t require a custom attribute. I have another idea, which I’ll try now…

(Pat Maddox) #6

No dice. I was hoping I could use a variable instead of an attribute:

^action(var link(^path(/chicken/funky)^))^
^action(var linkReplaced(link.replace('.md', '/')))^

but it just emits linkReplaced.

So far it’s looking like I have to use an attribute to pass a ^path^ to a ^value^… of course I’m willing to be pleasantly surprised :slight_smile:

edit: my last final stab was with a macro…

# the macro...
$1.replace('.md', '/');
# calling the marco
do("my macro", ^path^)

but nope. It’s exactly the same as if I just wrote it directly in the note (which makes sense, because I think that’s what macros are).

Look like the rule is simple: no export code inside of export code.

(Mark Anderson) #7

Thanks. Late here so i’ll take a look tomorrow, but one useful clarification is this is a workaround to (an apparent) bug whereby link-creating export codes don’t honour $HTMLLinkExtension. I’ll admit it’s one area of export I’ve not delved into much (only because I’ve never had a personal need - rather than any sense of dislike).

I think your var() calls are trying too do too much in terms of evaluation. As export/action code has grown in ad hoc fashion over time as the need arose, using expressions are inputs is a bit of an unknown. Support for such input is rarely formally documented though where known, I’ve tried to indicate that in aTbRef. Action code isn’t a full programming environment but rather a massively extended macro language. I mean no ill by that statement but the difference does often confuse those with programming expertise who presume behaviours that aren’t implemented in action code.

Further scope for confusion arises over guidance against using export code in action code is because originally there was only export code and then the two were used and long-term users naturally tended to use older code they understood. The deprecation of export code in action code was in part a ‘nudge’ away from use of export code for non-export tasks. As a result, the behaviour of export code in a now much extended action code is … lightly tested. So, that’s the why.

Pending a deeper dive, I’d not use action vars as these are very recent additions. Use an attribute to hold values (for links use a String-type). Not tested:

^action($MyString = ^path(/chicken/funky)^; $MyString.replace(".md","/");)^
^action($MyString=;)^      <!-- optionally reset to avoid saving variable data


edit: fixed stray extra ‘)’ in first expression.

(Mark Anderson) #8

Using your TBX, I created a template ‘url2’ with this code:

^action($MyString = ^path(original)^; $MyString =$MyString.replace("\.md","/");)^^value($MyString)^^action($MyString=;)^

The ‘sitemap’ agent’s test now emits:

I think that’s closer to what you’re after, no?


  • Where is the $MyString be processed? In the child (‘Start here’) alias and not in the Sitemap agent. As $MyString isn’t intrinsic, it’s actually arguably in the note itself, but the point is it’s not the agent. Either way, resetting the ‘variable’ attribute when done is a good idea in terms of garbage collection. In actual code you might want to use a user String attribute $MyVar or $MyStrVar to remind you when revisiting the code a year later.
  • The code is laid out so as note to emit any line breaks purely as a by-product of template code layout.

edit: I’ve reported the issue with the malfunction of $HTMLLinkExtension.

(Pat Maddox) #9

maybe it wasn’t clear, but yes, storing the value in a note-level attribute is the solution I shared in the first post in this thread :slight_smile: I posted in the hopes that I could find a way to do this without temporarily storing a value in an attribute… but as we’ve talked about in this thread, it doesn’t look like there is another way.

(Mark Anderson) #10

Point take. I would note the point about starting assumptions. Export code is a mark-up macro whose internal use subsequently morphed into action code before export code reverted to an export-only role with ^action()^ as a bridge to effect action code during export.line breaks in templates are literal and should be used with care - generally you can’t have a nice layout in both template and output. Way back this mattered little as few looked at (them) HTML code or how it was written. Of course ‘HTML’ export is now used for all sorts of other tasks and pages are more complex. However, I suspect fixing white-space prettiness wouldn’t be a cost-effective enhancement for the app from the vendor’s standpoint.

I think nested evaluations, i.e. within var() within ^value()^, is a degree more than envisaged in design, not least as var() post-dates ^value()^ by some way and because ^action()^ is provided for that general purpose. Way back, attribute values were exported by ^get(AttrName)^ and ^getFor(AttrName, Note name)^. When attribute offset references arrived, e.g. $SomeAttr(some note), putting either that or a direct $SomeAttr in a common ^value()^ operator simplified the syntax for learners and provided better export/action alignment of syntax.

All that said, try this as your ‘url’ template, I think you’ll be pleasantly surprised:^value((^path(original)^).replace("\.md","/"))

The secret is the extra parentheses which causes the output string of ^path^ to be evaluated before a String.replace() operation is attempted. This extra-parentheses approach is worth knowing as a possible syntax shim but doesn’t always work - you just won’t know until you try. Hopefully comment above as to how export/action code got here will help explain why such seemingly inconsistent outputs occur.

Last thought. If you find a code export or action - whose inputs aren’t evaluated and you really need them to be, don’t overlook writing into support and suggesting that as a feature request. Long-term Tinderbox users will attest there are lots of such of fixes that often address just one user’s pressing problems (I’m certainly one of those). Eastgate do listen to well-explained requests. :smiley:

(Pat Maddox) #11


Thanks for sticking with this :slight_smile: That’s a cool trick to know. I don’t really make assumptions about how TB export works, I just try stuff that could maybe work. This is another thing to try :slight_smile:

I do appreciate the background on some of these things. Though I don’t fault Eastgate for the export stuff being a bit… peculiar at times :wink: I am amazed at both how cool Tinderbox is, and how long Eastgate’s been doing it, how the software has evolved.

Yep, I asked for $HTMLLinkExtension… I don’t know if anyone else asked, but I’m glad he added it. Previously I had been doing all link substitution using $HTMLExportCommand to call an outside program and that was slooooow.

The one thing that I DESPERATELY want him to add is to bring back copying & pasting text links. I’ve got a website built from Tinderbox that has 94 content pages right now, and I’m always planning to add more… and I love using text links – but it’s a giant PITA to move text that has text links in it now. If Eastgate brings back this functionality, that will remove the last major obstacle to TB being an absolutely killer website construction platform (for me).

THANK YOU @mwra <3

(Mark Anderson) #12

No problem. Annoyed with myself for not trying the extra parentheses sooner. Anyway, always happy to get a solution. :smiley:

I hear you on the text links side - aTbRef has the same for a site with >1.5k notes. Here’s hoping!