Skip to content

Instantly share code, notes, and snippets.

@vszakats
Last active December 10, 2022 19:41
Show Gist options
  • Save vszakats/f24e7700428c1e694e20cee0b1cc542b to your computer and use it in GitHub Desktop.
Save vszakats/f24e7700428c1e694e20cee0b1cc542b to your computer and use it in GitHub Desktop.
Export Apple Notes to HTML (with formatting/pics)
#!/usr/bin/env osascript
// Export all Apple Notes.app notes to the current directory, each note
// into a HTML file that includes formatting and embedded documents, with
// creation/modification timestamps set according to Notes metadata.
// To the extent possible under law, Viktor Szakats
// has waived all copyright and related or neighboring rights to this
// script.
// CC0 - https://creativecommons.org/publicdomain/zero/1.0/
// SPDX-License-Identifier: CC0-1.0
// THIS 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 NON-INFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS 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.
// Ref:
// https://github.com/abruneau/apple-notes-jxa
// https://gist.github.com/sudocode/ae26950f1dac9c2f6a81
// https://bru6.de/jxa/automating-applications/notes/
'use strict'
ObjC.import('stdlib')
ObjC.import('Foundation')
function run() {
const app = Application.currentApplication();
app.includeStandardAdditions = true;
const na = Application("Notes")
na.includeStandardAdditions = true
const acclist = na.accounts
for (let a = 0; a < acclist.length; ++a) {
const acc = acclist[a]
for (let f = 0; f < acc.folders.length; ++f) {
const folder = acc.folders[f]
for (let n = 0; n < folder.notes.length; ++n) {
const note = folder.notes[n]
let fn = acc.name() + "-" + folder.name() + "-" + (n + 1).toString().padStart(3, "0") + "-" + note.name() + ".html"
fn = fn.replace(/[\/\\\?\*|:•]/g, "_")
// https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
const c = note.creationDate().toLocaleString("sv", {timeZone: "UTC"}) + "Z"
const m = note.modificationDate().toLocaleString("sv", {timeZone: "UTC"}) + "Z"
const str = $.NSString.alloc.initWithUTF8String("---\n" + "updated: " + m + "\n" + "created: " + c + "\n---\n" + note.body())
str.writeToFileAtomically(fn, true)
// "mm/dd/yyyy [hh:mm:[:ss] [AM | PM]]"
const cx = note.creationDate().toLocaleString("en-us", {timeZone: "UTC"})
const mx = note.modificationDate().toLocaleString("en-us", {timeZone: "UTC"})
const fnx = fn.replace("'", "'\\''")
// SetFile requires Developer Tools apparently
app.doShellScript(`TZ= /usr/bin/SetFile -d '${cx}' -m '${mx}' '${fnx}'`)
console.log(fn)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment