ligger inde i en
, hvis
# starttag tømmer linjen før den — så første linje er tom, og
# sammenligningen så på ingenting.
# Titlen kan være delt over flere overskrifter.
#
# Noter kalder noten det, der står på de første linjer, sat sammen med
# mellemrum — så en note, hvis to første linjer er "CPU" og "CAN", hedder
# "CPU CAN". Sammenlignede man kun med den første linje, gik det fri, og
# titlen stod bagefter to gange: én gang som overskrift og én gang som de
# stumper, den var lavet af. Fjorten noter ud af tolv hundrede.
#
# Overskrifterne øverst tages derfor med, så længe de tilsammen stadig er
# begyndelsen på titlen, og fjernes kun, hvis de til sidst er hele titlen.
lines = text.split("\n")
while lines and not lines[0].strip():
lines.pop(0)
taken, joined = 0, ""
for line in lines:
if not line.strip():
taken += 1
continue
if not line.lstrip().startswith("#"):
break
candidate = (joined + " " + line.lstrip("# ").strip()).strip()
if not title.strip().startswith(candidate):
break
joined, taken = candidate, taken + 1
if joined == title.strip():
break
if joined == title.strip():
lines = lines[taken:]
while lines and not lines[0].strip():
lines.pop(0)
text = "\n".join(lines)
name = safe_name(title, f"note-{i}")
used[name] = used.get(name, 0) + 1
path = os.path.join(out_dir, name if used[name] == 1 else f"{name} ({used[name]})") + ".md"
# Datoerne i et hoved, som enhver anden Markdown-læser kender.
#
# Uden dem er en flytning af tolv hundrede noter en bunke, der alle er
# skrevet samme aften: rækkefølgen, som er halvdelen af hvad et arkiv er,
# findes ikke længere. Obsidian, Bear og alt andet læser den her blok, og
# verdandes egen import gør nu også.
created, modified = iso(row["created"]), iso(row["modified"])
head = ""
if created or modified:
head = "---\n"
if created:
head += f"created: {created}\n"
if modified:
head += f"modified: {modified}\n"
head += "---\n\n"
with open(path, "w", encoding="utf-8") as f:
f.write(f"{head}# {title}\n\n{text}\n")
# Billeder og bilag. En note fra Noter er ofte fuld af fotografier, og en
# note, der kommer over som ord alene, er ikke den note.
# Antallet kom med i klumpen. Det var ét kald pr. note, og da kun hver
# tiende note har et bilag, var de ni af dem en proces startet for at få
# svaret nul.
if row["files"] > 0:
os.makedirs(attachments_dir, exist_ok=True)
with open(path, "a", encoding="utf-8") as f:
for j in range(1, row["files"] + 1):
a_name = osascript(
f'tell application "Notes" to return name of attachment {j} '
f'of note id "{note_id}"'
) or f"bilag-{i}-{j}"
a_file = f"{i}-{j}-" + safe_name(a_name, f"bilag-{i}-{j}")
target = os.path.join(attachments_dir, a_file)
# Nogle vedhæftninger — links til websider, kort — har ingen
# fil bag sig og fejler her. De springes over.
osascript(
f'tell application "Notes" to save attachment {j} '
f'of note id "{note_id}" in POSIX file "{target}"'
)
if os.path.exists(target):
f.write(f"\n})\n")
if i % 25 == 0:
print(f" {i} / {total}")
print(f"\nFærdig. {total} noter ligger i:\n {out_dir}\n")
print("Pak dem og importér zip'en under Indstillinger → Data:")
print(f' cd "{os.path.dirname(out_dir)}" && zip -r "{os.path.basename(out_dir)}.zip" "{os.path.basename(out_dir)}"')
return 0
if __name__ == "__main__":
sys.exit(main())