# Text highlighting via script-function

**URL:** <https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925>\
**Category:** Automation\
**Created:** [October 2, 2021, 6:14pm UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925 "2021-10-02T18:14:20Z")\
**Posts on this page:** 6\
**Page:** 2

<div class="post-metadata">

**Author:** ![chrillek](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/chrillek/32/29340_2.png) [@chrillek](https://discourse.devontechnologies.com/u/chrillek)\
**Post date:** [May 9, 2022, 11:44am UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925/21 "2022-05-09T11:44:20Z")

</div>

Definitely. Personally, I’d also get rid of all these these, those, this, that, the etc. Never got the point of them (wow, never saw a “them” actually in AS code).

---

<div class="post-metadata">

**Author:** ![cgrunenberg](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/cgrunenberg/32/7172_2.png) [@cgrunenberg](https://discourse.devontechnologies.com/u/cgrunenberg)\
**Post date:** [May 9, 2022, 12:27pm UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925/22 "2022-05-09T12:27:47Z")

</div>

Yes, that’s correct.

---

<div class="post-metadata">

**Author:** ![mdbraber](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/mdbraber/32/5802_2.png) [@mdbraber](https://discourse.devontechnologies.com/u/mdbraber)\
**Post date:** [May 9, 2022, 2:50pm UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925/24 "2022-05-09T14:50:31Z")

</div>

I love this script @pete31 - it feels like proper magic 😉 I’ve updated the script so you can give it a list containing search terms and a comment and it will add it back to the PDF like such:

```applescript
property theHighlightColorIndex : 1 -- set a color, Preferences > Colors > Highlighting

tell application id "DNtp"
	set thePath to path of first item of (selection as list)
	set itemA to {"Something very important", "Check out these references"}
	set itemB to {"A sentence to highlight", "Don't forget this"}
	set theHighlightItems to {itemA, itemB}
	my addHighlightAnnotations(thePath, theHighlightItems, theHighlightColorIndex)
end tell

```

There might be some tweaking needed at some point removing some `current application` references as well as juggling lists and arrays, but it works exactly like expected for now.

> **Updated script**
>
> ```applescript
> use AppleScript version "2.4"
> use framework "Foundation"
> use framework "Quartz"
> use scripting additions
> 
> on addHighlightAnnotations(thePath, theItems, theHighlightColorIndex)
> try
> set thePDF to current application's PDFDocument's alloc()'s initWithURL:(current application's |NSURL|'s fileURLWithPath:thePath)
> set theItems to (current application's NSArray's arrayWithArray:theItems)
> set theSelectionsArray to current application's NSMutableArray's new()
> 		
> repeat with i from 0 to ((theItems's |count|()) - 1)
> set thisItem to (theItems's objectAtIndex:i)
> set thisSearchTerm to ((current application's NSArray's arrayWithArray:thisItem)'s objectAtIndex:0)
> set thisComment to ((current application's NSArray's arrayWithArray:thisItem)'s objectAtIndex:1)
> 			
> set theResultSelections to (thePDF's findString:thisSearchTerm withOptions:0)
> if theResultSelections's |count|() ≠ 0 then
> set theSelectionsArray to my addSelectionToSelectionsArray(thisSearchTerm, theResultSelections, thisComment, theSelectionsArray)
> else
> set thisSearchTerm_Components to (thisSearchTerm's componentsSeparatedByString:space)
> repeat with j from 0 to ((thisSearchTerm_Components's |count|()) - 1)
> set theseSearchTerm_Components_1 to (thisSearchTerm_Components's subarrayWithRange:{0, (thisSearchTerm_Components's |count|()) - j})
> set thisSearchTerm_Part_1 to (theseSearchTerm_Components_1's componentsJoinedByString:space)
> set theResultSelections to (thePDF's findString:thisSearchTerm_Part_1 withOptions:0)
> if theResultSelections's |count|() ≠ 0 then
> set theSelectionsArray to my addSelectionToSelectionsArray(thisSearchTerm_Part_1, theResultSelections, thisComment, theSelectionsArray)
> set thisLocation to (theseSearchTerm_Components_1's |count|())
> set thisLength to (thisSearchTerm_Components's |count|()) - thisLocation
> set theseSearchTerm_Components_2 to (thisSearchTerm_Components's subarrayWithRange:{thisLocation, thisLength})
> set thisSearchTerm_Part_2 to (theseSearchTerm_Components_2's componentsJoinedByString:space)
> set theResultSelections to (thePDF's findString:thisSearchTerm_Part_2 withOptions:0)
> if theResultSelections's |count|() ≠ 0 then
> set theSelectionsArray to my addSelectionToSelectionsArray(thisSearchTerm_Part_2, theResultSelections, thisComment, theSelectionsArray)
> end if
> exit repeat
> end if
> end repeat
> end if
> end repeat
> 		
> set theDeeperLookArray to current application's NSMutableArray's new()
> 		
> repeat with i from 0 to ((theItems's |count|()) - 1)
> set thisSearchTerm to ((current application's NSArray's arrayWithArray:(theItems's objectAtIndex:i))'s objectAtIndex:0)
> repeat with j from 0 to ((theItems's |count|()) - 1)
> set thatSearchTerm to ((current application's NSArray's arrayWithArray:(theItems's objectAtIndex:j))'s objectAtIndex:0)
> if (thisSearchTerm's containsString:thatSearchTerm) and not (thisSearchTerm's isEqualTo:thatSearchTerm) then
> (theDeeperLookArray's addObject:thatSearchTerm)
> end if
> end repeat
> end repeat
> 		
> if theHighlightColorIndex < 1 or theHighlightColorIndex > 7 then error "No valid HighlightColor index. Valid: 1-7"
> if current application's id = "com.devon-technologies.think3" then
> set theDefaults to current application's NSUserDefaults's standardUserDefaults()
> else
> set theDefaults to current application's NSUserDefaults's alloc()'s initWithSuiteName:"com.devon-technologies.think3"
> end if
> set theDictionary to (theDefaults's dictionaryRepresentation())'s dictionaryWithValuesForKeys:{"HighlightColor-0", "HighlightColor-1", "HighlightColor-2", "HighlightColor-3", "HighlightColor-4", "HighlightColor-5", "HighlightColor-6"}
> set theColorDictionary to theDictionary's objectForKey:("HighlightColor-" & ((theHighlightColorIndex - 1) as string))
> set theRed to current application's NSNumber's numberWithDouble:((theColorDictionary's valueForKey:"red"))
> set theGreen to current application's NSNumber's numberWithDouble:((theColorDictionary's valueForKey:"green"))
> set theBlue to current application's NSNumber's numberWithDouble:((theColorDictionary's valueForKey:"blue"))
> set theAlpha to current application's NSNumber's numberWithDouble:((theColorDictionary's valueForKey:"alpha"))
> set theHighlightColor to current application's NSColor's colorWithCalibratedRed:theRed green:theGreen blue:theBlue alpha:theAlpha
> set theDocumentAuthor to (theDefaults's dictionaryRepresentation())'s stringForKey:"DocumentAuthor"
> set theAnnotationSubtype to current application's PDFAnnotationSubtypeHighlight
> set theAnnotationProperties to current application's NSMutableDictionary's new()
> (theAnnotationProperties's setObject:theHighlightColor forKey:(current application's PDFAnnotationKeyColor))
> 		
> repeat with i from 0 to ((theSelectionsArray's |count|()) - 1)
> set thisItem to (theSelectionsArray's objectAtIndex:i)
> set thisSearchTerm to (thisItem's valueForKey:"SearchTerm")
> set thisComment to (thisItem's valueForKey:"Comment")
> set thisResultSelection_BoundsForPage to (thisItem's valueForKey:"Selection_BoundsForPage")
> set thisResultSelection_Lines_QuadPointsArray to (thisItem's valueForKey:"Selection_Lines_QuadPoints")
> set createAnnotation to true
> 			
> if (theDeeperLookArray's containsObject:thisSearchTerm) then
> set thisResultSelection_Page_Label to (thisItem's valueForKey:"Selection_Page_Label")
> set thisSelectionsArray_filtered to (theSelectionsArray's filteredArrayUsingPredicate:(current application's NSPredicate's predicateWithFormat:("self.Selection_Page_Label = " & quoted form of (thisResultSelection_Page_Label as string) & " AND " & "self.SearchTerm CONTAINS " & quoted form of (thisSearchTerm as string) & " AND " & "!self.SearchTerm = " & quoted form of (thisSearchTerm as string))))
> repeat with j from 0 to ((thisSelectionsArray_filtered's |count|()) - 1)
> set thatItem to (thisSelectionsArray_filtered's objectAtIndex:j)
> set thatResultSelection_BoundsForPage to (thatItem's valueForKey:"Selection_BoundsForPage")
> set thatResultSelection_Lines_QuadPointsArray to (thatItem's valueForKey:"Selection_Lines_QuadPoints")
> set intersectsBoundsForPage to current application's NSIntersectsRect(thisResultSelection_BoundsForPage, thatResultSelection_BoundsForPage)
> if intersectsBoundsForPage then
> repeat with k from 0 to ((thisResultSelection_Lines_QuadPointsArray's |count|()) - 1) by 4
> set thisResultSelection_Line_QuadPoints to (thisResultSelection_Lines_QuadPointsArray's subarrayWithRange:{k, 4})
> set thisResultSelection_Line_Bounds to my makeRect(thisResultSelection_Line_QuadPoints)
> repeat with l from 0 to ((thatResultSelection_Lines_QuadPointsArray's |count|()) - 1) by 4
> set thatResultSelection_Line_QuadPoints to (thatResultSelection_Lines_QuadPointsArray's subarrayWithRange:{l, 4})
> set thatResultSelection_Line_Bounds to my makeRect(thatResultSelection_Line_QuadPoints)
> set intersectsBoundsForLine to current application's NSIntersectsRect(thisResultSelection_Line_Bounds, thatResultSelection_Line_Bounds)
> if intersectsBoundsForLine then
> set createAnnotation to false
> exit repeat
> end if
> end repeat
> if intersectsBoundsForLine then exit repeat
> end repeat
> if intersectsBoundsForLine then exit repeat
> end if
> end repeat
> end if
> 			
> if createAnnotation then
> set thisDate to (current application's NSDate's |date|())
> (theAnnotationProperties's setObject:thisDate forKey:(current application's PDFAnnotationKeyDate))
> set thisAnnotation to (current application's PDFAnnotation's alloc()'s initWithBounds:(thisResultSelection_BoundsForPage) forType:theAnnotationSubtype withProperties:theAnnotationProperties)
> 				
> set thisAnnotation_QuadPoints to current application's NSMutableArray's new()
> repeat with i from 0 to ((thisResultSelection_Lines_QuadPointsArray's |count|()) - 1)
> (thisAnnotation_QuadPoints's addObject:(current application's NSValue's valueWithPoint:(thisResultSelection_Lines_QuadPointsArray's objectAtIndex:i)))
> end repeat
> (thisAnnotation's setValue:(thisAnnotation_QuadPoints) forAnnotationKey:(current application's PDFAnnotationKeyQuadPoints))
> if not (theDocumentAuthor's isEqualTo:"") then (thisAnnotation's setUserName:theDocumentAuthor)
> set thisResultSelection_Page to (thisItem's valueForKey:"Selection_Page")
> 				
> -- add popup	
> set popupAnnotationSubtype to current application's PDFAnnotationSubtypePopup
> set popupAnnotation to (current application's PDFAnnotation's alloc()'s initWithBounds:(thisResultSelection_BoundsForPage) forType:popupAnnotationSubtype withProperties:theAnnotationProperties)
> 				
> (thisAnnotation's setValue:thisComment forAnnotationKey:(current application's PDFAnnotationKeyContents))
> (thisAnnotation's setValue:popupAnnotation forAnnotationKey:(current application's PDFAnnotationKeyPopup))
> 				
> (thisResultSelection_Page's addAnnotation:thisAnnotation)
> end if
> end repeat
> 		
> thePDF's writeToFile:thePath
> 		
> on error error_message number error_number
> activate
> if the error_number is not -128 then display alert "Error: Handler \"addHighlightAnnotations\"" message error_message as warning
> error number -128
> end try
> end addHighlightAnnotations
> 
> on addSelectionToSelectionsArray(thisSearchTerm, theResultSelections, theComment, theSelectionsArray)
> try
> repeat with i from 0 to ((theResultSelections's |count|()) - 1)
> set thisResultSelection to (theResultSelections's objectAtIndex:i)
> set thisResultSelection_Pages to thisResultSelection's pages()
> repeat with j from 0 to ((thisResultSelection_Pages's |count|()) - 1)
> set thisResultSelection_Page to (thisResultSelection_Pages's objectAtIndex:j)
> set thisResultSelection_BoundsForPage to (thisResultSelection's boundsForPage:thisResultSelection_Page)
> set thisResultSelection_Lines to thisResultSelection's selectionsByLine
> set thisResultSelection_Lines_QuadPointsArray to current application's NSMutableArray's new()
> repeat with k from 0 to ((thisResultSelection_Lines's |count|()) - 1)
> set thisResultSelection_Line to (thisResultSelection_Lines's objectAtIndex:k)
> set thisResultSelection_Line_Page to (thisResultSelection_Line's pages())'s firstObject()
> if (thisResultSelection_Line_Page's isEqualTo:thisResultSelection_Page) then
> set thisResultSelection_Line_BoundsForPage to (thisResultSelection_Line's boundsForPage:thisResultSelection_Line_Page)
> set thisResultSelection_Line_BoundsForPage to current application's NSRect's NSInsetRect(thisResultSelection_Line_BoundsForPage, -1, -1) -- DEVONthink recognizes text more reliably
> set MinX to current application's NSRect's NSMinX(thisResultSelection_Line_BoundsForPage)
> set MinY to current application's NSRect's NSMinY(thisResultSelection_Line_BoundsForPage)
> set MaxX to current application's NSRect's NSMaxX(thisResultSelection_Line_BoundsForPage)
> set MaxY to current application's NSRect's NSMaxY(thisResultSelection_Line_BoundsForPage)
> (thisResultSelection_Lines_QuadPointsArray's addObject:{MinX, MaxY})
> (thisResultSelection_Lines_QuadPointsArray's addObject:{MaxX, MaxY})
> (thisResultSelection_Lines_QuadPointsArray's addObject:{MinX, MinY})
> (thisResultSelection_Lines_QuadPointsArray's addObject:{MaxX, MinY})
> end if
> end repeat
> set thisResultSelection_Page_Label to thisResultSelection_Page's label()
> (theSelectionsArray's addObject:{Selection_Page:thisResultSelection_Page, Selection_Page_Label:thisResultSelection_Page_Label, Selection_BoundsForPage:thisResultSelection_BoundsForPage, Selection_Lines_QuadPoints:thisResultSelection_Lines_QuadPointsArray, SearchTerm:thisSearchTerm, Comment:theComment})
> end repeat
> end repeat
> return theSelectionsArray
> on error error_message number error_number
> activate
> if the error_number is not -128 then display alert "Error: Handler \"addSelectionToSelectionsArray\"" message error_message as warning
> error number -128
> end try
> end addSelectionToSelectionsArray
> 
> on makeRect(theSelection_QuadPoints)
> try
> set theSelection_QuadPoints to (theSelection_QuadPoints as list)
> set MinX to theSelection_QuadPoints's item 1's item 1
> set MinY to theSelection_QuadPoints's item 3's item 2
> set theWidth to (theSelection_QuadPoints's item 2's item 1) - MinX
> set theHeight to (theSelection_QuadPoints's item 1's item 2) - MinY
> set theRect to current application's NSRect's NSMakeRect(MinX, MinY, theWidth, theHeight)
> on error error_message number error_number
> activate
> if the error_number is not -128 then display alert "Error: Handler \"makeRect\"" message error_message as warning
> error number -128
> end try
> end makeRect
> 
> on tid(theInput, theDelimiter)
> set d to AppleScript's text item delimiters
> set AppleScript's text item delimiters to theDelimiter
> if class of theInput = text then
> set theOutput to text items of theInput
> else if class of theInput = list then
> set theOutput to theInput as text
> end if
> set AppleScript's text item delimiters to d
> return theOutput
> end tid
> 
> ```

---

<div class="post-metadata">

**Author:** ![pete31](https://discourse.devontechnologies.com/letter_avatar_proxy/v4/letter/p/d26b3c/32.png) [@pete31](https://discourse.devontechnologies.com/u/pete31)\
**Post date:** [May 9, 2022, 6:23pm UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925/25 "2022-05-09T18:23:14Z")

</div>

Glad it’s useful. You wrote

> [@mdbraber](#):
>
> I’m trying to ‘reverse’ a Sheet (TSV) back into a PDF.

and I’m wondering in what situation that would be necessary. Does it perhaps have something to do with PDFs that got corrupted by PDFKit (i.e. applying annotations of a corrupted PDF to a new PDF)?

---

<div class="post-metadata">

**Author:** ![BLUEFROG](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/bluefrog/32/135_2.png) [@BLUEFROG](https://discourse.devontechnologies.com/u/BLUEFROG)\
**Post date:** [May 9, 2022, 6:36pm UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925/26 "2022-05-09T18:36:19Z")

</div>

I’m wondering as well, especially since you can already convert a sheet into a PDF. 🤔

---

<div class="post-metadata">

**Author:** ![mdbraber](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/mdbraber/32/5802_2.png) [@mdbraber](https://discourse.devontechnologies.com/u/mdbraber)\
**Post date:** [May 9, 2022, 6:45pm UTC](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925/27 "2022-05-09T18:45:28Z")

</div>

> [@mdbraber](#):
>
> I’m trying to ‘reverse’ a Sheet (TSV) back into a PDF.

Sorry this might be a bit confusing, I mean applying the individual items of the TSV (the highlights and notes) as highlights and notes back to the accompanying PDF.

> [@pete31](#):
>
> and I’m wondering in what situation that would be necessary. Does it perhaps have something to do with PDFs that got corrupted by PDFKit (i.e. applying annotations of a corrupted PDF to a new PDF)?

No - it’s a different workflow altogether. I’m clipping everything I find for reference to PDF and automatically create annotations in Markdown. After that I most times read the PDF and highlight + take notes (in DT or on other devices). Highlights and notes get extracted to the annotation file again. That works well.

But there’s also another type of reading where after clipping I continue reading the webpage and going through it I add selection of the webpage to the annotation file (by appending them). Those annotations obviously are not present in the PDF. I’m using this script to add them afterwards as highlights so I’m keeping my annotation file and highlights in sync. Also this means PDF become portable and have all the relevant content, even without the annotation file.

[Previous page](https://discourse.devontechnologies.com/t/text-highlighting-via-script-function/66925.md?page=1)
