Markdown and store image

This Smart Rule script moves linked images to the record’s new database.

It’s important that you set e.g. /Assets in preferences, see below. It won’t work if there’s no slash.

What

The script checks

  • whether an image is also linked in other records
  • whether there’s already an identical image in the new database’s Assets group
    (“identical image” means an image that would be a duplicate if both images shared a database)

Depending on these checks different things happen:

  • If only 1 record links to the image

    • If there’s no identical image in the new database’s Assets group:
      Move image to new database’s Assets group

    • If there’s an identical image in the new database’s Assets group:
      Replace link URL with identical image’s reference URL and move unnecessary image to trash

  • If more than 1 record links to the image

    • If there’s no identical image in the new database’s Assets group:
      Duplicate image and replace link URL with duplicated record’s reference URL

    • If there’s an identical image in the new database’s Assets group:
      Replace link URL with identical image’s reference URL

Setup

Preferences

  • Go to preferences Files > Markdown
  • Set a location for Import images to group… , e.g. /Assets
    Note the slash at the start.

Script properties

Click

Set property theRecordHistory_Name_End to your Record History records’ name end. If the name is 2022-03-10 My daily record history then set the property to My daily record history.

The script uses the linked image’s incoming references. If you use the “Record History” script and open an image then it’s added to the Record History, which means the Record History record is also added to the image’s incoming references. Because the Record History and the records this script was written for both are Markdown there’s no way to distinguish between them other than filtering by name.

Smart Rule

Create a Smart Rule:

  • Search in: Databases
  • Matching:
    • All
      • Content: ![
      • Content: x-devonthink-item://
      • Kind: Markdown
  • Event: On Moving
  • Action: Execute Script (AppleScript)

2022-03-10_16-29-37

-- Smart Rule script - Move Markdown records' linked images

property theImageDestinationLocation : "/Assets" -- Note the "/" at the start. This script is build for Assets groups that live in databases' root.
property theRecordHistory_Name_End : "Record History" -- If you use the "History Record" script then it's necessary to set this property to the History Record's name end (e.g. "Record History")

on performSmartRule(theRecords)
	tell application id "DNtp"
		try
			repeat with thisRecord in theRecords
				set thisRecord_Text to plain text of thisRecord
				
				--------------------------------------------------- Create Assets group in new database ----------------------------------------------------
				
				set theImageDestinationGroup_NewDatabase to create location theImageDestinationLocation in database of thisRecord
				
				--------------------------------------------------- Get Assets group in old database ----------------------------------------------------
				
				set thisRecord_Text_TextItems to my tid(thisRecord_Text, "![")
				set theImageDestinationGroup_OldDatabase to missing value
				
				repeat with thisTextItem in thisRecord_Text_TextItems
					set thisTextItem to thisTextItem as string
					if thisTextItem contains "](" then
						set thisTextItem_Part to ((characters ((offset of "](" in thisTextItem) + 2) thru -1) in thisTextItem) as string
						set thisLinkURL to ((characters 1 thru ((offset of ")" in thisTextItem_Part) - 1)) in thisTextItem_Part) as string
						if thisLinkURL starts with "x-devonthink-item://" then
							set thisImage to (get record with uuid thisLinkURL)
							set thisImage_LocationGroup to location group of thisImage
							if ("/" & (name of thisImage_LocationGroup)) = theImageDestinationLocation then
								set theImageDestinationGroup_OldDatabase to thisImage_LocationGroup
								exit repeat
							end if
						end if
					end if
				end repeat
				
				if theImageDestinationGroup_OldDatabase ≠ missing value then
					if theImageDestinationGroup_NewDatabase ≠ theImageDestinationGroup_OldDatabase then
						
						set thisRecord_Text_new to thisRecord_Text
						
						----------------------------------- Get images in old database's Assets group that link to record ------------------------------------
						
						set theImages to (children of theImageDestinationGroup_OldDatabase whose incoming references contains thisRecord)
						
						repeat with thisImage in theImages
							
							------------------------------ Check whether there's an identical image in new database's Assets group -------------------------------
							
							set theImageDestinationGroup_NewDatabase_Children to (children of theImageDestinationGroup_NewDatabase whose content hash = content hash of thisImage)
							if theImageDestinationGroup_NewDatabase_Children = {} then
								set theExistingDuplicateImage_ReferenceURL to missing value
							else
								set theExistingDuplicateImage_ReferenceURL to (reference URL of item 1 of theImageDestinationGroup_NewDatabase_Children) as string
							end if
							
							------------------------------------------------ Check how many records link to the image -------------------------------------------------
							
							set thisImage_IncomingReferences to (incoming references of thisImage whose name without extension does not end with theRecordHistory_Name_End)
							set thisImage_IncomingReferences_Count to (count of thisImage_IncomingReferences)
							
							if thisImage_IncomingReferences_Count = 1 then
								
								----------------------------------------------- Move image to new database's Assets group ------------------------------------------------
								
								if theExistingDuplicateImage_ReferenceURL = missing value then
									set thisImage to move record thisImage to theImageDestinationGroup_NewDatabase
									
									-------------------- Replace link URL with identical image's Reference URL and move unnecessary image to trash ---------------------
									
								else if theExistingDuplicateImage_ReferenceURL ≠ missing value then
									set thisRecord_Text_new to my tid(my tid(thisRecord_Text_new, (reference URL of thisImage) as string), theExistingDuplicateImage_ReferenceURL)
									move record thisImage to trash group of database of thisImage
								end if
								
							else if thisImage_IncomingReferences_Count > 1 then
								
								----------------------------- Duplicate image and replace link URL with duplicated record's Reference URL ------------------------------
								
								if theExistingDuplicateImage_ReferenceURL = missing value then
									set thisDuplicatedImage to duplicate record thisImage to theImageDestinationGroup_NewDatabase
									set thisRecord_Text_new to my tid(my tid(thisRecord_Text_new, (reference URL of thisImage) as string), (reference URL of thisDuplicatedImage) as string)
									
									----------------------------------------- Replace link URL with identical image's Reference URL ------------------------------------------
									
								else if theExistingDuplicateImage_ReferenceURL ≠ missing value then
									set thisRecord_Text_new to my tid(my tid(thisRecord_Text_new, (reference URL of thisImage) as string), theExistingDuplicateImage_ReferenceURL)
								end if
								
							end if
						end repeat
						
						if thisRecord_Text_new ≠ thisRecord_Text then set plain text of thisRecord to thisRecord_Text_new
						
					end if
				else
					log message info "Smart Rule: Couldn't find the moved record's old \"Assets\" group" record thisRecord
				end if
			end repeat
			
		on error error_message number error_number
			if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
			return
		end try
	end tell
end performSmartRule

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
2 Likes