Exclude empty attributes from .md export

I have a basic template (because I’m a basic Tinderbox user) to export notes in Markdown. The template includes the Displayed Attributes I have by default at the head of my notes, which export as MD frontmatter:

---

Title: ^value($Title)^

Authors: ^value($Authors)^

Source: ^value($Source)^

SourceURL: ^value($SourceURL)^

ClipDate: ^value($ClipDate.format(L))

DTRef: ^value($DTRef)^

Tags: ^value($Tags)^

Created: ^value($Created.format(L))^

---

^value($Text)^

This works well for my purposes. However, many of my notes only carry data for some, or none, of the displayed attributes. I’d like to exclude empty attributes from export, so that the resulting .md notes only carry frontmatter that actually has data.

Is this possible? I looked through aTbRef, but I didn’t see any obvious resolution.

Yes, you need the ^if()^ conditional export operator.

Explanation in next post.

For your purposes you don’t need an ^else^ branch for your ^if^ test. For most data types, you just need:

^if($SomeAttribute)^^value($SomeAttribute)^^endIf^

If a String type holds "", a Number 0, or a Date "never", or a Boolean false, the above test evaluates as false and no value is emitted. If the attribute has a non-type-default default value, e.g. the current default for $Width is 4 (as opposed to a Number-type default of 0) then you need a more precise test. For instance,

^if($MyString!="")^...
^if($MyOtherString!="foobar")^... // assumes attribute's default is 'foobar'
^if($MyNumver>0)^...
^if($Width!=4)^...

and so on. So, for your template, I’ll assume the following types for user attributes:

  • $Source is a String.
  • $Source is a URL.
  • $ClipDate is a Date.
  • $DTRef is a a URL

Note: as $URL type is essentially a special type of String, we can test as for a string.

My suggested edit to your template:
[edited to add missing opening parentheses, as spotted in a later post]

---

^if($Title)^Title: ^value($Title)^

^endIf^^if($Authors)^Authors: ^value($Authors.format(", "))^

^endIf^^if($Source)^Source: ^value($Source)^

^endIf^^if($SourceURL)^SourceURL: ^value($SourceURL)^

^endIf^^if($ClipDate)^ClipDate: ^value($ClipDate.format(L))

^endIf^^if($DTRef)^DTRef: ^value($DTRef)^

^endIf^^if($DTRef)^Tags: ^value($Tags.format(", "))^

^endIf^^if($Created)^Created: ^value($Created.format(L))^

^endIf^---

^value($Text)^

Notes:

HTH

That’s both helpful and instructive as per, thank you Mark. Also, it works! Thank you for taking the time and care to help this stumbling user reach a new plateau of understanding. (Although ‘plateau’ might be overdoing it. More of a shaky finger hold.)

There is a missing parenthesis in the Source line. That’s corrected below, in case some future user has a similar question.

---

^if($Title)^Title: ^value($Title)^

^endIf^^if($Authors)^Authors: ^value($Authors.format(", "))^

^endIf^^if($Source)^Source: ^value($Source)^

^endIf^^if($SourceURL)^SourceURL: ^value($SourceURL)^

^endIf^^if($ClipDate)^ClipDate: ^value($ClipDate.format(L))

^endIf^^if($DTRef)^DTRef: ^value($DTRef)^

^endIf^^if($DTRef)^Tags: ^value($Tags.format(", "))^

^endIf^^if($Created)^Created: ^value($Created.format(L))^

^endIf^
---

^value($Text)^
2 Likes

BTW, the above approach is very good, there is also an alternative, you could put this in the template:

^action(
   var:string vStr=;
   var:string vBeg="<p>";
   var:string vEnd="</p>";
   if($Name!=""){vStr+=vBeg+"Title: "+$Name+vEnd+"\n";};
   if($Authors!=""){vStr+=vBeg+"Authors: "+$Authors+vEnd+"\n";};
   if($Source!=""){vStr+=vBeg+"Source: "+$Source+vEnd+"\n";};
   if($SourceURL!=""){vStr+=vBeg+"SourceURL: "+$SourceURL+vEnd+"\n";};
   if($ClipDate!=""){vStr+=vBeg+"ClipDate: "+$ClipDate.format(L)+vEnd+"\n";};
   if($DTRef!=""){vStr+=vBeg+"DTRef: "+$DTRef+vEnd+"\n";};
   if($Tags!=""){vStr+=vBeg+"Tags: "+$Tags.format(", ")+vEnd+"\n";};
   if($Created!=""){vStr+=vBeg+"Created: "+$Created.format("L")+vEnd+"\n";};
)^

<html>
<head>
</head>
<body>
^value(vStr)^
</body>

With this method, you could easily add additional code and have more control on the output, e.g., number of bullet list, format the URL, etc.

Thanks, Michael. I have no idea how or why this template works, but I’ll tinker with aTbRef in hand and hopefully learn something.

Sorry, saw an error, I’d forgotten to string the variable with +=. Fixed.

It works because the export code ^action)^ lets you write action code in in a template. You can populate a variable, e.g., vStr, and then display the results with the ^value()^ export code.

Thanks - that’s a good basis for exploration.

I note the html code at the end of the template. As mentioned up front, I’m working with Markdown. Do these patterns work with markdown, and is the html code necessary with markdown export?

[As I’ve edit access, I’ve fixed the missing parenthesis you spotted in my earlier reply. Sorry!]

As @satikusala notes, the ^action()^ export operator can be used like any other ^export^ code. To implement his HTML template approach as Markdown, use:

^action(
   var:string vStr=;
   if($Name!=""){vStr+="Title: "+$Name+"\n\n";};
   if($Authors!=""){vStr+="Authors: "+$Authors+"\n\n";};
   if($Source!=""){vStr+="Source: "+$Source+"\n\n";};
   if($SourceURL!=""){vStr+="SourceURL: "+$SourceURL+"\n\n";};
   if($ClipDate!=""){vStr+="ClipDate: "+$ClipDate.format(L)+"\n\n";};
   if($DTRef!=""){vStr+="DTRef: "+$DTRef+"\n\n";};
   if($Tags!=""){vStr+="Tags: "+$Tags.format(", ")+"\n\n";};
   if($Created!=""){vStr+=Created+"Created: "+$Created.format(L)+"\n\n";};
)^
---

^value(vStr)^

---

^value($Text)^

HTH :slight_smile:

Yes, they do. Remember, markdown is just a shorthand for HTML. There are lots of ways to skin this effort—all depends on what you’re trying to do, why, and how. The details matter as you build out your personal workflow.

Could we have an example-TBX-file of the version you are going to use now, @amc

thanks

For now I’m just using the version offered by @mwra, undiluted. I’ll look into @satikusala template down the track. I have a pleasant but intermittent relationship with Tinderbox, due to much going on in my wild and precious life, so I don’t have nearly the time to explore its functionality as I would like. But even at my fairly basic usage, it helps me order my thoughts in ways that nothing else can match.

nice. then maybe – if you don’t mind – you might share just that (maybe @mwra can support) … so we beginners can learn how those fruitful conversations here in the forum eventually translate into a working tbx-file, a template (so to speak), that showcases the question and the answer.

thanks

Can you clarify what those are, as it makes it easier to write a clear demo file. the more options, the more complex the file (and less easy to learn from).

The original request was simply asking for optional inclusion of a fixed number of system/user attributes (derived from Displayed Attributes). Then the thread branched to variations on exporting put Markdown (.md) files vs. complete HTML files which seems a different problem.

Processing the current note’s Displayed Attributes (a Set-type list) is perfectly possible in an ^action()^ to process $DisplayedAttributes to emit per item labels/values. But as you’ll see from above, you also need to allow for each items attribute data type as the ^value()^ call differs slightly. The sensible way to do the latter is to make a library not with a function and takes an attribute names and returns the correct-for-type output. Of course, for the starter learner, using functions is likely too complex (too much abstraction in terms of construction).

The general break down is:

  • read $DisplayedAttributes and iterate the list using list.each()
  • for each item, test for a non-default value. If such is found:
    • set a boolean outside the loop indicating there with be Displayed Attributes data to export
    • save a string with the attribute name, a colon, a space, the attribute value (correctly formatted for the attribute’s data type) followed by two line breaks (\n x 2)
      • Note: ensure you format the attribute data appropriately for the attribute data type.
  • if the boolean set in the above loop is true (i.e. there is data to export):
    • make a string of 3 consecutive hyphens and a line line break
    • add the the above to both the beginning and end of the Displayed Attributes data output string to the end of the string above
    • insert that value into the template replacing the section enclosing/including the lines with --- in the original example.

That isn’t the only way—there rarely is only one way—but it should suffice. Best is in the eye of the beholder and their prior expertise. But the above rubric can suffice.

Suggest exercise for the learner, try using the description above to make code for yourself. It’'s Ok to leave out the per-data-type formatting in the first pass. The main point is to prove to yourself that the template outputs title/value lines for only those Displayed Attributes with a non-default value.

If that exercise is too complex for the learner, then a complete demo file will be too complex as a leaning resource, which is why I ask what the real aim is here. Making (effective) demos is time-consuming and it is demotivating to build one only to find the brief was wrong, as all the time put into the demo is wasted. :slight_smile:

†. The --- on discrete lines mark the beginning and end of the Markdown frontmatter. I think this idea comes over from YAML.

1 Like

Here is an example.

TBX 5Cs Exclude Emtpy Attributes.tbx (173.1 KB)

1 Like

Thank you, @satikusala. That’s exactly what i was looking for.

Question:
What would you have to set differently or additionally to get all data for Note1 in the preview pane displayed one below the other instead of next to each other - just like in Note2 and Note3?

Thank you Mark @mwra for your detailed explanation. While I appreciate your breakdown of the process, I still find it a bit challenging to understand without a concrete example. I’m more of a visual learner, which is why I asked for an example file.

That’s why I’m particularly grateful to Michael @satikusala for providing the TBX file - seeing the implementation in action helps me understand the concepts much better than theoretical explanations alone.

I’ll study both your explanation and the example file to improve my understanding of Tinderbox templates.

1 Like

Note 1 uses the tExpordCode template as is in the examples above.

What I’d do differently is add in paragaph and linebreak tags, see example:
TBX 5Cs Exclude Emtpy Attributes_R2.tbx (226.7 KB)

Remember: Tinderbox will output whatever you tell it to.

1 Like

Again: To get inside baseball … and hit a home run … you need this BAT

Thank you for the “R2” @satikusala.






ɯǝpuɐʇ-uosɹǝpu∀-ɹǝʞɔǝq

1 Like