66 lines
4.2 KiB
Python
66 lines
4.2 KiB
Python
import json,zipfile,pathlib,collections,re,posixpath,hashlib
|
|
repo=pathlib.Path(__file__).resolve().parents[1];b=repo/'tools/demo-source';out=repo/'release';out.mkdir(exist_ok=True)
|
|
z=zipfile.ZipFile(b/'original-demo.zip');meta=json.loads(z.read('!!!meta.json'));old=json.loads((b/'scoped/notes.json').read_text(encoding='utf-8'));edges=json.loads((b/'demo-edges.json').read_text());byold={n['noteId']:n for n in old};parents=collections.defaultdict(set)
|
|
for n,p in edges:parents[n].add(p)
|
|
root='lq5FhqEInunb';archive={};apaths=collections.defaultdict(set);afiles={}
|
|
def walk(nodes,parent='',titles=()):
|
|
for n in nodes:
|
|
if 'title' not in n:continue
|
|
ident=n['noteId'];seq=titles+(n['title'],)
|
|
if not n.get('isClone'):
|
|
archive[ident]=n
|
|
if n.get('dataFileName'):afiles[ident]=posixpath.join(parent,n['dataFileName'])
|
|
apaths[ident].add(seq)
|
|
walk(n.get('children',[]),posixpath.join(parent,n.get('dirFileName','')),seq)
|
|
walk(meta['files'])
|
|
def sourcepaths(n,seen=frozenset()):
|
|
if n==root:return {('root','Trilium Demo')}
|
|
if n in seen:return set()
|
|
return {p+(byold[n]['title'],) for parent in parents[n] for p in sourcepaths(parent,seen|{n})}
|
|
mapping={};ambiguities=[]
|
|
for n in old:
|
|
candidates=[i for i,a in archive.items() if (a.get('title'),a.get('type'),a.get('mime'))==(n['title'],n['type'],n['mime'])]
|
|
if n['noteId']==root:candidates=[i for i,a in archive.items() if a.get('title')=='Trilium Demo']
|
|
if len(candidates)>1:candidates=[i for i in candidates if apaths[i]&sourcepaths(n['noteId'])]
|
|
if len(candidates)!=1:ambiguities.append((n['noteId'],n['title'],candidates))
|
|
else:mapping[n['noteId']]=candidates[0]
|
|
assert not ambiguities,ambiguities
|
|
assert len(set(mapping.values()))==170
|
|
changes={c['noteId']:c for c in json.loads((b/'release/demo-migration.json').read_text(encoding='utf-8'))['changes']}
|
|
for c in json.loads((b/'phase4/korean-phase4-pending.json').read_text(encoding='utf-8'))['changes']:changes[c['noteId']]={**changes.get(c['noteId'],{}),**c}
|
|
files={n:z.read(n) for n in z.namelist() if not n.endswith('/')};count=0
|
|
for oldid,newid in mapping.items():
|
|
a=archive[newid];n=byold[oldid];c=changes.get(oldid)
|
|
if not c:continue
|
|
a['title']=c['title'];count+=1
|
|
if 'content' not in c:continue
|
|
content=c['content'];filename=afiles[newid]
|
|
if a.get('type')=='text' or a.get('mime')=='text/html':
|
|
original=files[filename].decode('utf-8');oldsrc=re.findall(r'\bsrc="([^"]+)"',n.get('content') or '');newsrc=re.findall(r'\bsrc="([^"]+)"',original)
|
|
if oldsrc and len(oldsrc)==len(newsrc):
|
|
for x,y in zip(oldsrc,newsrc):content=content.replace('src="'+x+'"','src="'+y+'"')
|
|
def link(m):
|
|
target=m.group(1).split('/')[-1]
|
|
if target in mapping and mapping[target] in afiles:return 'href="'+posixpath.relpath(afiles[mapping[target]],posixpath.dirname(filename))+'"'
|
|
return m.group(0)
|
|
content=re.sub(r'href="#root/([^"#?]+)"',link,content)
|
|
for x,y in mapping.items():content=content.replace(x,y)
|
|
files[filename]=content.encode('utf-8')
|
|
phase4=json.loads((b/'phase4/korean-phase4-pending.json').read_text(encoding='utf-8'))
|
|
for c in phase4['attributes']:
|
|
for a in archive[mapping[c['noteId']]].get('attributes',[]):
|
|
if a['name']==c['name']:a['value']=c['value']
|
|
def prefixes(nodes):
|
|
for n in nodes:
|
|
if n.get('prefix') in ['TODO','DONE','28. 11. 2017']:n['prefix']={'TODO':'할 일','DONE':'완료','28. 11. 2017':'2017년 11월 28일'}[n['prefix']]
|
|
prefixes(n.get('children',[]))
|
|
prefixes(meta['files'])
|
|
for a in archive.values():
|
|
if a.get('title')=='root':a['title']='내 노트'
|
|
if a.get('title')=='Journal':a['title']='일지'
|
|
pdfid=mapping['swKGGdlek7o6'];files[afiles[pdfid]]=(b/'phase5/마지막-질문-한국어.pdf').read_bytes() if (b/'phase5/마지막-질문-한국어.pdf').exists() else next((b/'phase5').glob('*.pdf')).read_bytes()
|
|
files['!!!meta.json']=json.dumps(meta,ensure_ascii=False,indent=2).encode('utf-8')
|
|
with zipfile.ZipFile(out/'demo-ko.zip','w',zipfile.ZIP_DEFLATED) as dest:
|
|
for info in z.infolist():dest.writestr(info,b'' if info.is_dir() else files[info.filename])
|
|
(out/'demo-map.json').write_text(json.dumps(mapping,indent=2),encoding='utf-8');print(json.dumps({'mappedNotes':len(mapping),'translatedNotes':count,'archiveFiles':len(files),'sha256':hashlib.sha256((out/'demo-ko.zip').read_bytes()).hexdigest()}))
|