Files
mnote/wolai-frontend/temp-import-check.js
T

61 lines
3.2 KiB
JavaScript

const fs=require("fs");
const JSZip=require("jszip");
const {XMLParser}=require("fast-xml-parser");
const arrify=(v)=>Array.isArray(v)?v:(v==null?[]:[v]);
const safeText=(v)=>typeof v==='string'&&v.trim()?v.trim():(v&&typeof v==='object'&&v.PlainText?String(v.PlainText).trim():"未命名节点");
const pickUid=(obj)=>Object.entries(obj||{}).find(([k,v])=>['OId','Guid','ID','Id','uid'].includes(k)&&typeof v==='string'&&v.trim())?.[1]||`node_${Math.random().toString(16).slice(2)}`;
const parseUri=(input)=>{if(typeof input==='string') return input.trim(); if(input && typeof input==='object' && '#text' in input && typeof input['#text']==='string') return input['#text'].trim(); return null;};
async function parse(buf){
const zip=await JSZip.loadAsync(buf);
const xml=await zip.file('Document.xml').async('text');
const parser=new XMLParser({ignoreAttributes:false,removeNSPrefix:true,attributeNamePrefix:''});
const parsed=parser.parse(xml);
const rootTopic=(parsed.Map?.OneTopic?.Topic)||parsed.OneTopic?.Topic||parsed.Topic;
const root=Array.isArray(rootTopic)?rootTopic[0]:rootTopic;
const uriSet=new Set();
(function collect(node){
if(!node||typeof node!=='object') return;
const images=[...arrify(node.OneImage), ...arrify(node.Image)];
images.forEach(img=>{
const uri=parseUri(img?.Image?.ImageData?.Uri ?? img?.ImageData?.Uri ?? img?.Uri);
if(uri) uriSet.add(uri);
});
const children=(arrify(node.SubTopics?.Topic)||arrify(node.Topics?.Topic)||arrify(node.Topic));
children.forEach(collect);
})(root);
const uriData=new Map();
const detectMime=(b)=> b.slice(0,8).equals(Buffer.from([0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a]))?'image/png':b.slice(0,3).equals(Buffer.from([0xff,0xd8,0xff]))?'image/jpeg':b.slice(0,2).equals(Buffer.from([0x42,0x4d]))?'image/bmp':'application/octet-stream';
for(const uri of uriSet){
const path=uri.startsWith('mmarch://')?uri.replace('mmarch://',''):uri;
const file=zip.file(path);
if(!file) continue;
const bin=await file.async('nodebuffer');
const mime=detectMime(bin);
uriData.set(uri,{url:`data:${mime};base64,${bin.toString('base64')}`});
}
const conv=(node)=>{
const data={text:safeText(node?.Text??node?.text)};
const images=[...arrify(node?.OneImage), ...arrify(node?.Image)];
if(images.length){
const first=images[0];
const uri=parseUri(first?.Image?.ImageData?.Uri ?? first?.ImageData?.Uri ?? first?.Uri);
const size=first?.Image?.ImageSize||first?.ImageSize;
if(uri && uriData.has(uri)){
data.image=uriData.get(uri).url;
if(size?.Width||size?.Height){
data.imageSize={width:Number(size.Width)||0,height:Number(size.Height)||0,custom:true};
}
}
}
const kids=(arrify(node?.SubTopics?.Topic)||arrify(node?.Topics?.Topic)||arrify(node?.Topic)).map(conv);
return {uid:pickUid(node||{}), data, children:kids};
};
return conv(root);
}
(async()=>{
const root=await parse(fs.readFileSync('..\\design\\导图1.mmap'));
const imgs=[];const walk=(n)=>{if(n.data.image) imgs.push(n.data.image.slice(0,40));(n.children||[]).forEach(walk)};walk(root);
console.log('image count', imgs.length);
console.log('sample', imgs[0]?.slice(0,80));
})();