Perhaps the place for this is really a Github collection of notes and examples on moving attributes between TaskPaper and Tinderbox, but lets start here, and then move elsewhere if it grows too much.
Let’s assume:
- we are drafting things in TaskPaper, and then adding them to some part of a growing Tinderbox document.
- Taskpaper @tags and @key(value) pairs will map onto Tinderbox Attributes.
- and that we are going to place things in Tinderbox via JavaScript.
(an alternative is to create an XML-defined clipboard from which we can paste items with attributes into Tinderbox. Let me know if you would prefer a copy as Tinderbox
script for TaskPaper)
Let’s also assume that it may be more helpful to step through the basics, rather than just hand over a clump of slightly over-specialised scripts and script-fragments.
The first thing to get right is the set of data types at each end.
A few basics:
-
Case: While TaskPaper @tags and @key(value) pairs tend to have lower-case names, the Tinderbox convention is for attributes whose names start with a Capital.
-
Available attributes: TaskPaper gives us the freedom to create any new @tag or @key(value) combination on the fly, but Tinderbox needs an Attribute to be named, and given a data type, and a default value, before we can create a note that has such an attribute.
That means that to use a TaskPaper tag (renamed to start with a capital) as an attribute in a Tinderbox document, we will need to:
- see if such an Attribute already exists in the target Tinderbox document,
- and if it doesn’t, create it, and give it a specific type (and default value).
A function to find or create a Tinderbox Attribute of a given name and type:
click to expand code
// tbxAttribFoundOrCreated ::
// TBX App -> TBX Attributes ->
// String -> String -> TBX Attribute
const tbxAttribFoundOrCreated = tbx =>
// Either a reference to an existing attribute, if found,
// or to a new attribute of the given name and type,
// where type is a string drawn from:
// {boolean,color,date,file,interval,
// list,number,set,string,url}
attribs => strTypeName => attribName => {
const maybeAttrib = attribs.byName(attribName);
return maybeAttrib.exists() ? (
maybeAttrib
) : (() => {
const newAttrib = tbx.Attribute({
name: attribName,
type: strTypeName
});
return (
attribs.push(newAttrib),
newAttrib
);
})();
};
TaskPaper and Tinderbox value types
The Tinderbox attribute type names are:
- boolean
- color
- date
- file
- interval
- list
- number
- set
- string
- url
And the obvious TaskPaper mappings to a sub-set of these might be:
boolean:
The presence or absence of simple TaskPaper tag
date:
@somedate(2020-06-07)
@somedate(2020-06-07 14:00)
list:
@participants(london, paris, tokyo)
number:
@priority(3)
string:
@any(other)
Tinderbox default values:
Tinderbox attribute values are stored as strings, but interpreted in the light of their data type name. Each of these data types is associated with a special string which defines their default value:
- boolean –
'false'
- date –
'never'
- list –
''
- number –
'0'
- string –
''
Creating a Tinderbox note.
Once all the attributes needed have been found or created (see above), we can start to create notes in Tinderbox, using our TaskPaper data.
Note creation via JavaScript for Automation is a three-step process:
- The new note object is defined,
- it is ‘pushed’ into the notes collection of its parent (either another note, or the document itself),
- and its various attribute-value pairs are specified.
Defining the new note object:
const newNote = tbx.Note({
name: "a task, note or project string from TaskPaper"
});
Pushing it into the notes collection of its parent object:
parent.notes.push(newNote)
and specifying any attribute values assuming that we have obtaining a key-value dictionary object of Attribute names, and their values for this note from TaskPaper:
Object.keys(dict).reduce(
(a, k) => 'Name' !== k ? (
a.byName(k).value = dict[k],
a
) : a,
newNote.attributes
)
I’m not sure how much JS scripting you have done so far. So perhaps I can pause there and let you direct what we clarify or show code for next ?
Or if you prefer, we can restart with an XML approach ?
Rob