步骤
- 用 boostnote 创建、编辑、更新、整理、搜索笔记
- 用 Dropbox 在多台机器同步笔记
- 用脚本将 boostnote 的 cson 格式笔记内容转换成 markdown 格式
- 用脚本生成 markdown 文件的目录文件
README.md
- 用 docsify 展示 markdown 格式的笔记
- 用 nginx 提供静态文件内容服务,可以通过 https://note.drink.cafe 访问我的笔记
scripts (updated at 2020-02-10)
file: generate-readme-for-docsify
#!/usr/bin/env python3
# coding: utf-8
"""
Author : weaming
Created Time : 2018-05-04 09:53:22
Requirement :
python2.x
pip install filetree
Description :
generate README.md files to prepare for https://github.com/QingWei-Li/docsify
"""
import os, sys
from filetree import File
target = sys.argv[1] if len(sys.argv) > 1 else '.'
def is_markdown_article(x):
return x.ext == 'md' and x.name.lower() != 'readme' and x.basename[0] != '.'
def conditional_title(text):
if text[0] in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
return text
return text.title()
def gen(d, h2_prefix=''):
fp = os.path.join(os.path.abspath(d.path), 'README.md')
# print(dir(d))
# gen recursively
for dd in sorted(d.dirs, key=lambda x: x.mtime, reverse=True):
if dd.basename[0] == '.':
continue
gen(dd, h2_prefix=os.path.join(h2_prefix, dd.basename))
if os.path.isfile(fp):
print('existed {}'.format(fp))
return
print(fp)
with open(fp, 'w') as me:
def genDir(d, prefix="", pre_hook=None):
"""
scan markdown files,
and write entries in README.md
"""
mds = [x for x in d.files if is_markdown_article(x)]
if pre_hook and mds:
pre_hook()
for f in sorted(mds, key=lambda x: x.mtime, reverse=True):
relpath = os.path.relpath(d.path, target)
me.write('{}- [{}]({})\n'.format(
prefix,
conditional_title(f.name.replace('-', ' ').replace('_', ' ')),
os.path.join('' if relpath == '.' else relpath, f.relpath),
))
# use direcotry name as h1 title
me.write('# {}\n'.format(conditional_title(d.basename)))
# generate for next level sub directories
for dd in sorted(d.dirs, key=lambda x: x.mtime, reverse=True):
if dd.basename[0] == '.':
continue
me.write('\n## [{}]({}{}/)\n\n'.format(
conditional_title(dd.basename),
(h2_prefix + '/') if h2_prefix else '',
dd.basename,
))
genDir(dd, prefix="")
genDir(d, pre_hook=lambda: me.write('\n## Articles\n'))
gen(File(target))
file: boostnote2md
#!/usr/bin/env python3
# coding: utf-8
"""
Author : weaming
Created Time : 2018-05-26 21:32:59
Prerequisite:
python3 -m pip install cson arrow
"""
import json
import os
import sys
import datetime
import cson
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"""
try:
return cson.loads(text)
except:
pass
try:
return json.loads(text)
except:
pass
raise Exception("text should be in cson or json format")
def read_folder_names(fp):
data = text_to_dict(read_file(fp))
return {x["key"]: x["name"] for x in data["folders"]}
def get_reverse_in():
exclude = os.getenv("BOOSTNOTE_EXCLUDE", "")
excludes = exclude.split(",") if exclude else []
def _in(title):
for e in excludes:
if e in title.lower():
return True
return False
return _in
contains_keyswords = get_reverse_in()
def red(text):
return "\033[{}m{}\033[0m".format(31, text)
def write_boostnote_markdown(data, output, folder_map):
"""write boostnote dict to markdown"""
title = data["title"]
folder = folder_map[data["folder"]]
# ignore blank title
if not title.strip():
print(red("warning: ignore article with blank title"))
return
# ignore article whose title contains keyword
if contains_keyswords(title):
print(red("warning: ignore article with title: {}".format(title)))
return
# ignore article whose folder contains keyword
if contains_keyswords(folder):
print(red("warning: ignore article in folder: {}".format(folder)))
return
# ignore trashed article
if data["isTrashed"]:
print(red("warning: ignore trashed article: {}".format(title)))
return
target_dir = os.path.join(output, folder)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
target_file = os.path.join(
target_dir, "{}.md".format(title.replace("/", "-").replace(" ", "-"))
)
with open(target_file, "w") as f:
f.write(data["content"])
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)
def process_file(source, output, folder_map):
data = text_to_dict(read_file(source))
write_boostnote_markdown(data, output, folder_map)
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)
process_file(source, output, folder_map)
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)