From 58e51e9b8c57ec3926795232f1f09f654b423400 Mon Sep 17 00:00:00 2001 From: David Bielik Date: Mon, 25 Nov 2019 02:35:01 +0100 Subject: [PATCH] Initial commit --- .gitignore | 5 ++ README.md | 62 +++++++++++++++++ date_converter.py | 31 +++++++++ notability_pdf_export.scpt | 137 +++++++++++++++++++++++++++++++++++++ 4 files changed, 235 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 date_converter.py create mode 100644 notability_pdf_export.scpt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..393736b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# macOS +.DS_Store + +# Don't include the generated pdfs +out/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca7b2fb --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# πŸ“Œ Notability Notes Converter πŸ“Œ + +This repository contains the necessary code to convert all of your notes to `.pdf` format. After running the script, all notes from the Notability app on your Mac will be exported as pdf to an `out` folder. + +### ⚠️ Requirements ⚠️ +1. macOS +2. [Notability.app](https://www.gingerlabs.com) for macOS + +## Running the script + +1. Append a pin emoji (πŸ“Œ) to each note file that you wan't to have exported. +2. (Optional if editing notes from another Apple device) Wait for iCloud to sync. +3. Then run from terminal + +``` +$ osascript notability_pdf_export.scpt +``` + +Or just run the file directly via Script Editor. + +### Example + +Structure of notes in Notability +``` +subject_1/note1πŸ“Œ.note +subject_1/note2πŸ“Œ.note +subject_1/note3πŸ“Œ.note +subject_1/note4.note +subject_2/example_noteπŸ“Œ.note +subject_3/private_note.note +``` + +``` +$ osascript notability_pdf_export.scpt +Success +$ +``` + +After running the script a new directory containing all the required pdfs is created. + +``` +# Structure of out folder +out/subject_1/note1.pdf +out/subject_1/note2.pdf +out/subject_1/note3.pdf +out/subject_2/example_note.pdf +``` + +## Features + + * Creates a `.pdf` file for each note that ends with the pin emoji (πŸ“Œ) + * Each pdf file will be correctly categorized by a folder that represents the Note subject + * The script doesn't export the same note twice. (i.e. the pdf files are overwritten only when the modification time of the Notability note is greater than the pdfs that were generated beforehand) +### Todo + +- [ ] Add flags for including the Paper πŸ“œ / Page Margin πŸ“„ in the pdf export settings. Currently each pdf is exported without the paper and page margins. +- [ ] Add the option to flag (πŸ“Œ) an entire subject. + - [ ] Add exclusion tag for notes that you don't want to be exported from tagged subjects. + +## License + +MIT diff --git a/date_converter.py b/date_converter.py new file mode 100755 index 0000000..13f02dd --- /dev/null +++ b/date_converter.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import argparse +from datetime import datetime, timedelta + +def arguments(): + parser = argparse.ArgumentParser() + parser.add_argument("datestring") + return parser.parse_args() + +def create_expected_datestring(datestr): + time_format = "%H:%M" + date_format = "%d %b %Y" + datetime_format = "{} {}".format(date_format, time_format) + today = datetime.today() + yesterday = today - timedelta(days=1) + date_to_day_nr = lambda d: d.strftime(date_format) + clean_datestr = datestr.replace( + "at", "" + ).replace( + "Today", date_to_day_nr(today) + ).replace( + "Yesterday", date_to_day_nr(yesterday) + ) + + correct_datetime = datetime.strptime(clean_datestr, datetime_format) + return correct_datetime.strftime("%A, %d %B %Y at %H:%M:%S") + +if __name__ == "__main__": + args = arguments() + print(create_expected_datestring(args.datestring)) diff --git a/notability_pdf_export.scpt b/notability_pdf_export.scpt new file mode 100644 index 0000000..3c969a3 --- /dev/null +++ b/notability_pdf_export.scpt @@ -0,0 +1,137 @@ +#!/usr/bin/osascript + +property exportFileExtension : ".pdf" +property noteExportFlag : "πŸ“Œ" +property notabilityName : "Notability" + +# Create the out folder +tell application "Finder" + set outFolder to my FilepathToThisFolderAsString() & "out" +end tell + +# Launch Notability +tell application notabilityName + quit + delay 1 + launch + delay 2 + activate +end tell + +tell application "System Events" + my WaitUntilExists(window 1 of application process notabilityName) + # Save notability main window for later + set notabilityWindow to window 1 of application process notabilityName + tell process notabilityName + # This selects the All Notes tab + select (row 1 of outline 1 of scroll area 2 of window 1) + + # For each note in All notes + repeat with aRow in (every row of table 1 of scroll area 3 of notabilityWindow) + repeat 1 times + # Variables + set currentNoteCategory to name of static text 1 of UI element 1 of aRow + set currentNoteName to name of static text 2 of UI element 1 of aRow + set currentNoteModDate to name of static text 3 of UI element of aRow + set currentNoteModDate to my CreateDateFromDatestring(currentNoteModDate as text) + + # if current row contains export flag + if (currentNoteName contains noteExportFlag) then + # create a new name for the note without the export flag + set noteNameWithoutEmoji to text 1 thru -2 of currentNoteName + # create the out filename for our note + set outNoteFilename to noteNameWithoutEmoji & exportFileExtension + set outFolder to outFolder & "/" & currentNoteCategory + set outNoteFilepath to outFolder & "/" & outNoteFilename + # create dir if needed + do shell script "mkdir -p " & quoted form of outFolder + + + # check if note already exists + set noteFileExists to my FileExists(outNoteFilepath) + if noteFileExists then + # check if the current date is newer + tell application "System Events" to set lastLocalModDate to modification date of file outNoteFilepath + if lastLocalModDate β‰₯ currentNoteModDate then + # continue the loop, we don't have to export this + exit repeat -- continue + end if + end if + + # select it, so the export knows what to export + select aRow + + # export + click menu item "PDF..." of menu 1 of menu item "Export As" of menu 1 of menu bar item "File" of menu bar 1 + + set exportDialogWindow to window "Export" + my WaitUntilExists(exportDialogWindow) + + # handle Export dialog + tell (exportDialogWindow) + # set focus on the text field + set focused of text field 1 to true + + # Change the output folder + keystroke "g" using {command down, shift down} + delay 0.1 + my WaitUntilExists(sheet 1) + tell sheet 1 + set value of combo box 1 to outFolder + click button "Go" + end tell + + # set the new filename without emojis + set value of text field 1 to outNoteFilename + + # we don't want page margins or the paper to be included in the final pdf (uncheck all checkboxes) + repeat with aCheckbox in (every checkbox) + tell aCheckbox to if value is 1 then click + end repeat + + # finally, export + click button "Export" + + # if the file exists + if noteFileExists then + # wait for the action sheet + my WaitUntilExists(sheet 1) + # click the button + click button "Replace" of sheet 1 + end if + end tell + end if + end repeat + end repeat + end tell +end tell + +tell application notabilityName to quit + +return "Success" + + +# Sub-routines +on FileExists(theFile) -- (String) as Boolean + tell application "System Events" + return (exists file theFile) + end tell +end FileExists + +on CreateDateFromDatestring(theString) + return date (do shell script "python3 " & my FilepathToThisFolderAsString() & "date_converter.py " & quoted form of theString) +end CreateDateFromDatestring + +on FilepathToThisFolderAsString() + tell application "Finder" + return POSIX path of (parent of (path to me) as string) + end tell +end FilepathToThisFolderAsString + +on WaitUntilExists(theElement) + tell current application + repeat until (exists theElement) + delay 1 + end repeat + end tell +end WaitUntilExists