Linking back to Bookends?

A couple of other things worth noting:

  • When reference type is Article, what is on the Bookends URL field will get imported. When reference type is Book, it won’t.
  • The translator field (aka User3) never makes the trip over. (It would be nice if it did).

Lastly, what have I done wrong for all those prototypes to show up? (I only have one of each type, of course).

My impression is that the coding decisions about what is transferred (and under what key) are made by the Bookends team rather than at the Tinderbox end.

It should, however, be possible to write a customisable ‘Copy As Tinderbox’ macro for Bookends selections (in JavaScript for Automation or AppleScript) to give the user a little more control.

(I’ll take a look at the weekend, if there is any interest in something like that)

1 Like

It looks to me like you’ve set $IsPrototype for lots of notes — perhaps because you’re creating them inside the Prototypes container?

1 Like

Thanks for the suggestion, Mark. It was hidden inside a separator.

I have a couple of scripts for exporting metadata out of Bookends. If you tell me the basic syntax for creating a note on Tinderbox with such and such attributes, I would have it in no time (and would be more than happy to post it here afterwards).

The trick of a Copy As script is to place something in the clipboard in the same format that Tinderbox uses for copying and pasting notes.

As you know, the clipboard can simultaneously hold its data in several formats, and the format eventually used is decided at paste-time, depending on the capacities and preferences of the receiving app.

When you copy a note in Tinderbox 8, a clipboard object (labelled with the type com.eastgate.tinderbox.scrap) is created in a .tbx XML format.

A sample might look like this:

Sample clipboard XML
<?xml version="1.0" encoding="UTF-8" ?>
<tinderbox version="2" revision="12" savedBy="version 8.1.0 b405" uuid="CDCDD0A2-9B80-49EA-B2B6-22973D1A60F3" >
<item ID="1571687918" Creator="Robin Trew" proto="Reference" >
<attribute name="Abstract" >abstract :: The publication’s abstract as plain text.</attribute>
<attribute name="ArticleTitle" >Sample of :: Journal article</attribute>
<attribute name="Associates" ></attribute>
<attribute name="Authors" >LF., authors :: The publication’s authors. Separate names with</attribute>
<attribute name="Created" >2019-10-21T20:56:56+01:00</attribute>
<attribute name="DominantLanguage" >en</attribute>
<attribute name="ISBN" >isbn :: The publication’s ISBN.</attribute>
<attribute name="IsComposite" >false</attribute>
<attribute name="Issue" >optionally followed by the issue number in parentheses</attribute>
<attribute name="Journal" >journal :: The publication’s journal.</attribute>
<attribute name="Modified" >2019-10-21T20:57:17+01:00</attribute>
<attribute name="Name" >Sample of :: Journal article</attribute>
<attribute name="Pages" >pages :: The page range in the hosting publication (e.g., a book or periodical) this publication was published in.</attribute>
<attribute name="PublicationYear" >1971</attribute>
<attribute name="RefKeywords" >keywords :: The publication’s keywords. Separate keywords with LF.</attribute>
<attribute name="RefType" >JOUR</attribute>
<attribute name="ReferenceRIS" >TY  - JOUR
AU  - LF., authors :: The publication’s authors. Separate names with 
T1  - Sample of :: Journal article 
KW  - keywords :: The publication’s keywords. Separate keywords with LF. 
PY  - 1971 
JA  - journal :: The publication’s journal. 
SP  - pages :: The page range in the hosting publication (e.g., a book or periodical) this publication was published in. 
VL  - volume :: The volume number of a journal article 
IS  - optionally followed by the issue number in parentheses
SN  - isbn :: The publication’s ISBN. 
AB  - abstract :: The publication’s abstract as plain text. 
N1  - notes :: The publication’s notes. Separate paragraphs with LF. Separate notecards with LFLF. 
UR  - url :: The publication’s default URL (Uniform Resource Locator). 
ER  - 

</attribute>
<attribute name="ReferenceURL" >url :: The publication’s default URL (Uniform Resource Locator).</attribute>
<attribute name="SelectionCount" >9</attribute>
<attribute name="URL" >bookends://sonnysoftware.com/38460</attribute>
<attribute name="Volume" >volume :: The volume number of a journal article</attribute>
<attribute name="Xpos" >0.09521484375</attribute>
<attribute name="Ypos" >-0.4613037109</attribute>
<text >authors :: The publication’s authors. Separate names with LF., ‘Sample of :: Journal Article’, journal :: The publication’s journal., volume :: The volume number of a journal article (1971), pages :: The page range in the hosting publication (e.g., a book or periodical) this publication was published in.
</text>
</item>
<links >
</links>
</tinderbox>

So there are two things to do:

  1. Build your XML string, with the AttributeName::Value pairs that you need.
  2. Place that XML in the clipboard, not as public.utf8-plain-text but as com.eastgate.tinderbox.scrap

We can put things in the clipboard, labelled with their type, by writing JavaScript for Automation code like:

ObjC.import('AppKit');


// setClipOfTextType :: String -> String -> IO Bool
const setClipOfTextType = utiOrBundleID => txt => {
    const pb = $.NSPasteboard.generalPasteboard;
    return (
        pb.clearContents,
        pb.setStringForType(
            $(txt),
            utiOrBundleID
        )
    );
};

setClipOfType('com.eastgate.tinderbox.scrap')(strXML)

(where the AppKit import is needed to get access to the $.NSPasteboard object)

PS You should be able to skip any potentially irrelevant XML tags, like those which specify creation or access date.

2 Likes

Or if you prefer to write in AppleScript, I think something equivalent, like the snippet below, should work:

AppleScript example
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions

on run
    set strXML to "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<tinderbox version=\"2\" revision=\"12\" savedBy=\"version 8.1.0 b405\" uuid=\"CDCDD0A2-9B80-49EA-B2B6-22973D1A60F3\" >\n<item ID=\"1571687918\" Creator=\"Robin Trew\" proto=\"Reference\" >\n<attribute name=\"Abstract\" >abstract :: The publication’s abstract as plain text.</attribute>\n<attribute name=\"ArticleTitle\" >Sample of :: Journal article</attribute>\n<attribute name=\"Associates\" ></attribute>\n<attribute name=\"Authors\" >LF., authors :: The publication’s authors. Separate names with</attribute>\n<attribute name=\"Created\" >2019-10-21T20:56:56+01:00</attribute>\n<attribute name=\"DominantLanguage\" >en</attribute>\n<attribute name=\"ISBN\" >isbn :: The publication’s ISBN.</attribute>\n<attribute name=\"IsComposite\" >false</attribute>\n<attribute name=\"Issue\" >optionally followed by the issue number in parentheses</attribute>\n<attribute name=\"Journal\" >journal :: The publication’s journal.</attribute>\n<attribute name=\"Modified\" >2019-10-21T20:57:17+01:00</attribute>\n<attribute name=\"Name\" >Sample of :: Journal article</attribute>\n<attribute name=\"Pages\" >pages :: The page range in the hosting publication (e.g., a book or periodical) this publication was published in.</attribute>\n<attribute name=\"PublicationYear\" >1971</attribute>\n<attribute name=\"RefKeywords\" >keywords :: The publication’s keywords. Separate keywords with LF.</attribute>\n<attribute name=\"RefType\" >JOUR</attribute>\n<attribute name=\"ReferenceRIS\" >TY  - JOUR\nAU  - LF., authors :: The publication’s authors. Separate names with \nT1  - Sample of :: Journal article \nKW  - keywords :: The publication’s keywords. Separate keywords with LF. \nPY  - 1971 \nJA  - journal :: The publication’s journal. \nSP  - pages :: The page range in the hosting publication (e.g., a book or periodical) this publication was published in. \nVL  - volume :: The volume number of a journal article \nIS  - optionally followed by the issue number in parentheses\nSN  - isbn :: The publication’s ISBN. \nAB  - abstract :: The publication’s abstract as plain text. \nN1  - notes :: The publication’s notes. Separate paragraphs with LF. Separate notecards with LFLF. \nUR  - url :: The publication’s default URL (Uniform Resource Locator). \nER  - \n\n</attribute>\n<attribute name=\"ReferenceURL\" >url :: The publication’s default URL (Uniform Resource Locator).</attribute>\n<attribute name=\"SelectionCount\" >9</attribute>\n<attribute name=\"URL\" >bookends://sonnysoftware.com/38460</attribute>\n<attribute name=\"Volume\" >volume :: The volume number of a journal article</attribute>\n<attribute name=\"Xpos\" >0.09521484375</attribute>\n<attribute name=\"Ypos\" >-0.4613037109</attribute>\n<text >authors :: The publication’s authors. Separate names with LF., ‘Sample of :: Journal Article’, journal :: The publication’s journal., volume :: The volume number of a journal article (1971), pages :: The page range in the hosting publication (e.g., a book or periodical) this publication was published in.\n</text>\n</item>\n<links >\n</links>\n</tinderbox>"
    
    setClipOfTextType("com.eastgate.tinderbox.scrap", strXML)
end run


-- setClipOfTextType :: String -> String -> IO Bool
on setClipOfTextType(utiOrBundleID, txt)
    tell generalPasteboard of NSPasteboard of current application
        its clearContents()
        its setString:(txt) forType:(utiOrBundleID)
    end tell
end setClipOfTextType

[Notice that in AppleScript, which can only work with double quotes (in JS we can use single or double, enclosing either within the other) we have to escape every double quote in any literally included XML with a preceding backslash.]

(and of course, you will need to reproduce the two use framework incantations at the top of the snippet)

1 Like

For testing purposes, here is a Keyboard Maestro macro which you can use to copy the XML version of selected Tinderbox notes (as pasteable UTF8 plain XML text) so that you can paste it into a text editor and study it more closely:

Copy selected Tinderbox note(s) as XML.kmmacros.zip (11.7 KB)

1 Like

Thank you, you help is much appreciated. Still, I was thinking about approaching this from a different angle.

Here is what I came up with:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions


tell application "Bookends"
	tell front library window
		
		-- Get selected publication 
		set theRefs to selected publication items
		set theRefsNo to count of theRefs
		set theRef to first item of theRefs
		
		-- Error messages	
		if theRefsNo is greater than 1 then error "Select only one item"
		if theRefs is {} then error "Nothing selected in Bookends"
		
		-- Get properties of selected reference
		set theType to type of theRef
		set theID to id of theRef
		set theAbstract to abstract of theRef
		set theAuthor to authors of theRef
		set theEditor to editors of theRef
		set theTitle to title of theRef
		set theAbstract to abstract of theRef
		set theLocation to location of theRef
		set thePublisher to publisher of theRef
		set theDate2 to publication date string of theRef
		set theURL2 to url of theRef
		set theISBN to isbn of theRef
		set theDOI to doi of theRef
		set theTranslator to user3 of theRef
		set theCitation to user1 of theRef
		set thePages to pages of theRef
		set theIssue to volume of theRef
		set theNotes to notes of theRef
		set theLanguage to language of theRef
		set theAttachments to attachments of theRef
		set theJournal to journal of theRef
		set theShortTitle to short title of theRef
		
		try
			set {od, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ", "}
			set theTags to keyword names of theRef
			set theTags to (theTags as string)
		end try
		
			set theFormattedReference to format theRef using "ABNT.fmt"
	end tell
end tell

tell application "Tinderbox 8"
	tell front document
		if not (exists) then error "No Tinderbox document open."
		
		set newNote to make new note
		
		tell newNote
			
			set value of attribute "Prototype" to "Reference"
			set value of attribute "Name" to theShortTitle
			set value of attribute "Text" to theFormattedReference & theAbstract
			set value of attribute "Authors" to theAuthor
			set value of attribute "Editor" to theEditor
			set value of attribute "Translator" to theTranslator
			set value of attribute "PublicationCity" to theLocation
			set value of attribute "Publisher" to thePublisher
			set value of attribute "PublicationYear" to theDate2
			set value of attribute "Journal" to theJournal
			set value of attribute "RefKeywords" to theTags
			set value of attribute "URL" to "bookends://sonnysoftware.com/" & theID
			
			if theType is "2" then set value of attribute "BookTitle" to theTitle
			if theType is "6" then set value of attribute "BookTitle" to theTitle
			if theType is "9" then set value of attribute "ArticleTitle" to theTitle
			if theType is "15" then set value of attribute "ArticleTitle" to theTitle
			if theType is "3" then set value of attribute "ArticleTitle" to theTitle
			
			set NoteURL to value of attribute "NoteURL"
			
		end tell
		
		
	end tell
end tell

tell application "Bookends"
	tell front library window
		set user8 of publication item id theID to NoteURL
	end tell
end tell

For what I need, it will be enough for me.

EDITED:
In case someone else is reading this: read the script before you use it.
What it will do is essentially what the usual method does, with the following minor differences:

  • It will copy the fields “Translator” (aka user3), “Editor”, “URL” (in some cases the usual method does not copy the URL field from the Bookends reference)(by this I do not mean the url with the format bookends://sonnysoftware.com. I mean the field that appears in Bookends with the title URL.)
  • The formatted reference to be added is set to ABNT, but it can easily be changed.
  • It will copy the Note URL and post it back to the Bookends reference in the field user8
2 Likes

JS is still on my to do list :wink:

Out of interest, you are entering your Bookends keyword names delimited with ", " ?

(The scripting dictionary doc strings seems to expect each keyword on a new line)

If we enter keywords delimited by linefeeds:
28

then Bookends does some parsing for use, and makes that parse accessible to the scripting interface as keyword names
(the raw string is exposed as keywords)

(possibly not the right forum, but in defense it goes to the assumption made by import scripts :slight_smile: )

I am entering them delimited by linefeeds. If I am not mistaken, the script takes them as keyword names and transforms them into a comma separated string. (Not sure if this is what Tinderbox would expect and make best use of.) Did you notice something off somewhere?

Got it – thanks – I was reading too fast.

FWIW JS dictionaries are a bit more flexible than their AS (record) counterparts – one approach would be to define a conversion table in the form of a dict, and write a script around that.

const conversionTable = {
    'abstract': {
        attribute: 'Text',
        translation: ref => x => bookends.format(
            ref, {
                using: formatName
            }
        ) + x
    },
    'attachments': {},
    'authors': {
        attribute: 'Authors'
    },
    'authorNames': {},
    'citekey': {},
    'doi': {},
    'editors': {
        attribute: 'Editor'
    },
    'editorNames': {},
    'id': {
        attribute: 'URL',
        translation: ref => x => "bookends://sonnysoftware.com/" + x
    },
    'isbn': {},
    'journal': {
        attribute: 'Journal'
    },
    'keywords': {},
    'keywordNames': {
        attribute: 'RefKeywords',
        translation: ref => x => x.join(', ')
    },
    'labelColor': {},
    'language': {},
    'location': {
        attribute: 'PublicationCity'
    },
    'notes': {},
    'pages': {},
    'pmid': {},
    'publisher': {
        attribute: 'Publisher'
    },
    'publicationDateString': {
        attribute: 'PublicationYear'
    },
    'rating': {},
    'shortTitle': {
        attribute: 'Name'
    },
    'title': {
        attribute: ref => x => [2, 6].includes(ref['type']) ? (
            'BookTitle'
        ) : 'ArticleTitle'
    },
    'type': {},
    'url': {},
    'user1': {},
    'user3': {
        attribute: 'Translator'
    },
    'volume': {}
};
1 Like

Sorry to revive an old thread, but this looks a great script though it makes me realise that I don’t know how to find a list of the codes corresponding to different reference types in Bookends. I have not changed the standard reference types in Bookends, so I hope yours will work for that, but I also use a User-defined type and probably some others, and would need to find the code for that. I feel that would be more elegant than inserting a default value for theTitle.

One advantage of this would presumably be that you can change the script to use a different user-defined Prototype rather than the built in one, which I do not like to edit in case I mess it up and cannot get it back. The inconvenience, as I see it, is that user8 in bookends is not clickable. Or is it? Having two or three fields in Bookends that could be used for clickable URLs would be useful (one for the original URL, if there is one, one for a link to Tinderbox, and one for a link to DevonThink).

PS What is ABNT and does a normal user need to know?

ABNT is one of the bibliography formats. If you go to the formats manager in Bookends you will find it in the list.

Might I suggest that you temporarily make all the attributes in the Reference prototype into Key Attributes (you can change it back later) and make the Key Attributes visible for your notes. It will give you a better idea of what is going on. When you drag in items from Bookends you get more than you can normally see, because any stuff that is not a Key Attribute is hidden. But it is still there (unless things have changed since I last did it).

Edit: you can find Attributes here: https://www.acrobatfaq.com/atbref8/index/Attributes/AttributeGroupswithinTin/ReferencesAttributes.html

Thank you. I had not thought of that method: importing a reference of each type and see how Tinderbox identifies them. I shall try it.

I should have noticed where the format was in the macro, and its function. It could presumably be changed to anything else.

Like Tinderbox, Bookends has wonderful depth (and has been going long enough to know where/how some weirdnesses have arises. IME, Jon—its dev, has been wonderfully responsive via forum and Support. The answers, whilst not always what I hoped (due to now-known constraints) are always explanatory. This is the joy of more artisanal software, coming to a better understanding of what’s possible, rather than what might be if only Venture gets behind that next round of funding in a world where fashion changes with the turn of the tide.

My experience with Bookends has been excellent.

3 Likes