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()}))