Skip to content

Instantly share code, notes, and snippets.

@rordaz
Forked from weaming/boostnote2md.py
Last active January 16, 2023 14:50
Show Gist options
  • Save rordaz/1acb3e324846c40095a9f16cf5e22d9b to your computer and use it in GitHub Desktop.
Save rordaz/1acb3e324846c40095a9f16cf5e22d9b to your computer and use it in GitHub Desktop.
Convert boostnote cson format data to markdown
#!/usr/bin/env python3
# coding: utf-8
"""
Author : weaming
updated by : rordaz
Created Time : 2018-05-26 21:32:59
updated Time : 2022-11-21
Prerequisite:
python3 -m pip install cson arrow
python.exe -m pip install cson arrow (Microsoft Install)
"""
import json
import os
import sys
import datetime
import cson
import shutil
import re
try:
import arrow
time_aware = True
except ImportError:
print(
'warning: datetime information will be discarded unless you install arrow'
)
time_aware = False
def read_file(fp):
with open(fp) as f:
return f.read()
def text_to_dict(text):
"""convert json or cson to dict"""
# Exclude Snippets
if(text.find("SNIPPET_NOTE") == -1):
try:
return cson.loads(text)
except:
pass
try:
return json.loads(text)
except:
pass
raise Exception("text should be in cson or json format")
else:
return "EMPTY"
def read_folder_names(fp):
data = text_to_dict(read_file(fp))
return {x['key']: x['name'] for x in data['folders']}
def copy_boostnote_attachments(base_dir,output,noteHex):
target_dir = os.path.join(output,'attachments')
attachmentFolder = getAttachmentFolder(noteHex)
file_source_dir = os.path.join(base_dir,'attachments',attachmentFolder)
print("source",file_source_dir)
if os.path.exists(file_source_dir):
for filePNG in os.listdir(file_source_dir):
if not filePNG.endswith('.png'):
continue
print("copying attachament: ", filePNG)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
pngFullPath = os.path.join(file_source_dir,filePNG)
shutil.copy(pngFullPath,target_dir)
def updateImagePath(content):
pattern = '(:storage\\\\){1}(\w){8}-{1}(\w){4}-{1}(\w){4}-{1}(\w){4}-{1}(\w){12}(\\\\){1}'
return re.sub(pattern,'',content)
def getAttachmentFolder(filePath):
attachmentFolder = ""
if filePath.endswith('.cson'):
attachmentFolder = (filePath[filePath.find('.cson')-36:filePath.find('.cson')])
return attachmentFolder
def write_boostnote_markdown(data, output, folder_map,source):
"""write boostnote dict to markdown"""
if(data != "EMPTY"):
folderName = folder_map[data['folder']]
fileTitle = data['title'].replace('/', '-')
# Exclusions, the following BoostNote Folder will be excluder
foldersToExclude = ['folderName1','folderName2','folderName3']
# Boostnote Tags, also use the folder name as tag
tags = data['tags']
if (len(tags)) == 0 :
print("Note: [" + fileTitle + "] does not contain any tags")
print("Loc:" + source)
print("--------------------------")
# Move this folder to the company folder
if foldersToExclude.count(folderName.lower()) > 0 :
folderName = os.path.join('EMR',folderName)
# Create tags based on folder name
#tags.append((folderName).lower().replace(" ", ""))
for t in tags:
if foldersToExclude.count(t.lower()) > 0 :
folderName = os.path.join('EMR',folderName)
break
target_dir = os.path.join(output, folderName)
contenTag = ""
for tag in tags:
contenTag = contenTag +"#"+ tag.lower().replace(" ", "") + " "
content = data.get('content', '')
# Update Image Path
content = updateImagePath(content)
tagBreak = content.find("\n")+1
contentTagged = content[:tagBreak] +"\n"+ contenTag +"\n"+ content[tagBreak:]
#eof
if not os.path.exists(target_dir):
os.makedirs(target_dir)
target_file = os.path.join(target_dir, '{}.md'.format(data['title'].replace('/', '-')))
with open(target_file, 'w') as f:
f.write(contentTagged)
# print(">>> ",target_file)
if time_aware:
update_at = arrow.get(data['updatedAt'])
update_at_epoch = int(update_at.strftime('%S'))
os.utime(target_file, (update_at_epoch, update_at_epoch))
stat = os.stat(target_file)
#copy_boostnote_attachments(source)
def process_file(source, output, folder_map):
data = text_to_dict(read_file(source))
write_boostnote_markdown(data, output, folder_map, source)
def main(boostnote_dir, output):
"""
:input: input folder path
:output: output folder path
"""
folder_map = read_folder_names(os.path.join(boostnote_dir, 'boostnote.json'))
notes_dir = os.path.join(boostnote_dir, 'notes')
for name in os.listdir(notes_dir):
if not name.endswith('.cson'):
continue
source = os.path.join(notes_dir, name)
print("Source:", source)
process_file(source, output, folder_map)
copy_boostnote_attachments(boostnote_dir,output,source)
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(
description="convert boostnote cson format data to markdown")
parser.add_argument(
'-s',
'--source',
type=str,
help="directory store the cson files",
default=".")
parser.add_argument(
'-o', '--output', type=str, help="output directory", default="output")
args = parser.parse_args()
main(args.source, args.output)
@rordaz
Copy link
Author

rordaz commented Jan 16, 2023

Adding folder organization based on tagging

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment