Automatically generating DT annotation document from PDF annotations

@BLUEFROG would you be able to share how you made the smart rule? Currently, I am able to search for PDF’s in annotations, but I cannot find a way to invoke the Tools>Summarize Highlights>Markdown. Thanks in advance.

Welcome @dawob

It actually involves a bit of AppleScript.

(Smart rule removed and updated below - 09.28.2022)

I’d recommend to use the record’s location group instead of the current group as smart rules shouldn’t depend on the user interface.

:+1:t2:

summarize highlights of records {theRecord} to rich in (location group)

If I do this and run from a smart rule nothing seems to be happening.

Otherwise, using current group seems to be creating summarized highlights in the top level of my database.

The in parameter is actually invalid as location group is a property of records, not a global one.

Not totally following. My use case is I’d like to use this smart rule to create summarized output alongside the original file.

I tried omitting the in as well and it is still creating in the top level of the DB. I’m assuming this is because it’s being run from a smart rule?

I removed the old smart rule above.
Here is an updated version…
Summarize On Import.dtSmartRule.zip (1.5 KB)

Ahh super useful, thank you!!

Quoting the relevant part here (for me to remember and if it’s of use to anybody else)

	repeat with theRecord in theRecords
	     summarize highlights of records {theRecord} to markdown in (location group of theRecord) # saves the annotation alongside the Record when running from a smart rule
	end repeat
1 Like

You’re welcome :slight_smile:

So, I’ve taken your Smart Rule with the Applescript and tried to move it to Javascript. The code is at the bottom, and I get the error:

10/24/22, 5:18:39 PM: Summarize On Demand on performSmartRule (Error: Error: Parameter is missing.)

Here is my code:

function performsmartrule(records) {
	var app = Application("DEVONthink 3");
	app.includeStandardAdditions = true;
	app.displayAlert(records.length);
	records.forEach(r => {
		app.summarizeHighlightsOf(r,"markdown")
	})
}

Any insight is appreciated.

The syntax of this command is not the right one, see description of DEVONthink’s script suite in Script Editor after switching the language to JavaScript:

You might have a look at @chrillek’s great introduction to JXA:

The correct syntax for summarizeHighlightsOfwould be

app.summarizeHighlightsOf({records: [r], to: "markdown"});

Which you could in part deduce from the scripting dictionary quoted above by @cgrunenberg: The first parameter is a list of records, which translates to an Array in JavaScript. And since you have to pass an Array, using a forEach loop for every single record is a futile.

Less obvious is how to pass these parameters. As you can see (again, from the scripting dictionary, but also from @BLUEFROG’s AppleScript), the parameters are named. This is translated into JavaScript by using an object whose properties are the parameter names and their values are the value you want to pass for the corresponding parameter. Hence:

function performsmartrule(records) {
	const app = Application("DEVONthink 3");
	app.summarizeHighlightsOf({records: records,to: "markdown"})
}

Note includeStandardAdditions is only needed in some cases, notably when executing shell commands or for user interaction methods. And you should use const for all program variables that are not variable to avoid involuntary modifications.

@chrillek,
Thank you for your response. It was your guide that led me to this point. Your opening statements on DEVONthink in your JXA guide led me to the forEach loop. I did look at the AppleScript from @BLUEFROG, but was not able to deduce how it treated an Array. I tried to reference Array notation to no avail. Thank you for bridging the gap in my understanding. When looking at the dictionary, which I did, how do you know the difference between a named parameter and one that can be passed as an argument to the function/method?

Dawob

E.g. have a look at this command:

The URL is a direct & unnamed parameter, all the others are named and optional. A required parameter looks like this…

name: Type : Description

…and optional ones like this:

[name: Type] : Description

1 Like

I feel your pain. The dictionary format is very old (very), and it has probably been developed with AppleScript in mind. Which has some weird (in my opinion) ideas about parameter passing with named and unnamed (positional) parameters which can be required or optional, too. So, the dictionary requires some getting used to if you are using JavaScript. As @cgrunenberg pointed out, there might be

  • an unnamed parameter, which is always the first one
  • an object of named parameters, some of which might be required
  • optional parameters are always written in brackets

Parameter types mostly translate directly from AppleScript to JavaScript. There’s a slight difference in AS between Text and String, afaik, but in JS both are simply strings. An AppleScript record is an object in JavaScript, and an AS list is a JS Array. AS dates are internally mapped to JS Dates and vice versa.

Note that DT uses the term record for its own objects, they are not to be confused with AS’s records!

@chrillek
I have used:

function performsmartrule(records) {
	const app = Application("DEVONthink 3");
	app.summarizeHighlightsOf({records: records,to: "markdown"})
}

Still, I did not get a document or documents with the summarized highlights. The tags update, but I get nothing else.

I’m not sure how summarizeHighlightsOf works and I do not use highlights myself. The method returns a record, so it might be worthwhile to do something like
const result=app.summarize...; console.log(result.name());
and then search for the name in DT.

Edit I had a look at @BLUEFROG’s script. It does in fact loop over all the records, so your original approach was closer to the original version. So, another version would look like this

function performsmartrule(records) {
  const app = Application("DEVONthink 3");
  records.forEach( r => {
    app.summarizeHighlightsOf({records: [r],to: "markdown", in: r.locationGroup()})
  })
}

That is a verbatim translation of the AppleScript code (as far as I can see, that is) and it should produce the summarized highlights for every record in its location group.

@chrillek,
Thanks for the help, but there must be something wrong with implementing Javascript and Devonthink. It will not make individual summary documents. There are no errors, and it does apply the summarized tags. The script is running but not actually creating the summary files. The Applescript works fine, so I am using that for now. I would like to change to Javascript at some point, but I’ve spent enough time on this little project. Thank you, and I look forward to the future growth of JXA.

@BLUEFROG, how do you direct the summaries into a specific group of a database with Applescript? I cannot seem to find the syntax for making that happen. Thanks in advance.

Hi @dawob, it looks like we’re trying to do something similar and I’ve opened a related thread at Script Summarize Highlights from Javascript

We may have identified a bug in JXA but not sure yet