Last active
February 18, 2025 23:12
-
-
Save kzaremski/830f2bbe5a6a97829b49901833af2f51 to your computer and use it in GitHub Desktop.
Apple Notes Exporter Script (AppleScript)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | |
-- ** AppleNotesExporter ** | |
-- -- Easily export Apple notes to standard encoding HTML preserving directory structure | |
-- | |
-- Copyright 2022 Konstantin Zaremski | |
-- | |
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | |
-- documentation files (the "Software"), to deal in the Software without restriction, including without limitation | |
-- the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, | |
-- and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
-- | |
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions | |
-- of the Software. | |
-- | |
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | |
-- TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
-- CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
-- DEALINGS IN THE SOFTWARE. | |
-- | |
-- Replace text | |
on replaceText(this_text, search_string, replacement_string) | |
set AppleScript's text item delimiters to the search_string | |
set the item_list to every text item of this_text | |
set AppleScript's text item delimiters to the replacement_string | |
set this_text to the item_list as string | |
set AppleScript's text item delimiters to "" | |
return this_text | |
end replaceText | |
tell application "Notes" | |
activate | |
-- Build list of account human readable names | |
set theAccountNames to {} | |
repeat with theAccount in accounts | |
copy name of theAccount as string to end of theAccountNames | |
end repeat | |
-- Select the desired account from the list of human readable names | |
set chosenAccountName to choose from list theAccountNames with prompt "Select the Apple Notes account to export from:" | |
-- Quit if cancel | |
if chosenAccountName is false then | |
return | |
end if | |
-- Set the desired account object to the account that has that human readable name | |
repeat with theAccount in accounts | |
-- display dialog ("\"" & name of theAccount as string) & "\" \"" & chosenAccountName & "\"" | |
-- Dont even ask me why the above line was here >:( | |
if name of theAccount as string = chosenAccountName as string then | |
set chosenAccount to theAccount | |
end if | |
end repeat | |
-- Get output folder | |
set outputFolder to (choose folder with prompt "Choose an output location. Note: Note folder organization structure will be preserved. It is best to use an empty directory." as string) | |
-- Quit if cancel | |
if outputFolder is false then | |
return | |
end if | |
-- For every note in the account | |
repeat with theNote in notes of chosenAccount | |
set noteLocked to password protected of theNote as boolean | |
set modDate to modification date of theNote as date | |
set creDate to creation date of theNote as date | |
set noteID to id of theNote as string | |
set oldDelimiters to AppleScript's text item delimiters | |
set AppleScript's text item delimiters to "/" | |
set theArray to every text item of noteID | |
set AppleScript's text item delimiters to oldDelimiters | |
if length of theArray > 4 then | |
set noteID to item 5 of theArray | |
else | |
set noteID to "" | |
end if | |
if not noteLocked then | |
set theText to body of theNote as string | |
set currentContainer to container of theNote | |
set internalPath to name of currentContainer | |
-- Path | |
repeat until name of currentContainer as string = name of default account as string | |
set currentContainer to container of currentContainer | |
if name of currentContainer as string ≠ name of default account then | |
set internalPath to (name of currentContainer & "/" & internalPath) | |
end if | |
end repeat | |
-- Create dir | |
do shell script "mkdir -p '" & (POSIX path of outputFolder as string) & internalPath & "'" | |
-- Filename | |
set fileName to ("[" & my replaceText(noteID as string, "p", "") & "] " & (name of theNote as string)) as string | |
if length of fileName > 250 then | |
set fileName to text 1 thru 250 of fileName | |
end if | |
global outputFolder | |
-- Sanitize filename | |
set fileNameClean to my replaceText(fileName, ":", "-") | |
set fileNameClean to my replaceText(fileNameClean, "/", "-") | |
set fileNameClean to my replaceText(fileNameClean, "$", "") | |
set fileNameClean to my replaceText(fileNameClean, "\"", "-") | |
set fileNameClean to my replaceText(fileNameClean, "\\", "-") | |
set filepath to ((POSIX path of outputFolder as string) & internalPath as string) & "/" & fileNameClean & ".html" | |
set theFile to open for access filepath with write permission | |
set eof of the theFile to 0 | |
write theText to theFile starting at eof as «class utf8» | |
close access theFile | |
-- Convert to UTF-8 proper | |
-- do shell script "sync; iconv --from-code UTF-8 --to-code=UTF-8 \"" & filepath & "\" > \"" & filepath & "UTF8\"; sync; mv \"" & filepath & "UTF8\" \"" & filepath & "\"" | |
end if | |
end repeat | |
-- Display within the Notes application so we are not jumping around | |
display dialog "Done! | |
Thanks for using AppleNotesExporter. | |
https://www.github.com/kzaremski" buttons {"Nice 🔥"} default button "Nice 🔥" | |
end tell | |
-- I really don't like AppleScript :( | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
August 7, 2022: Added the ability to select the note account instead of using the default