xml-disassembler
Version:
Disassemble XML files into smaller, more manageable files and reassemble the XML when needed.
3 lines (2 loc) • 10.8 kB
JavaScript
;var e=require("log4js"),t=require("node:fs/promises"),n=require("node:path/posix"),i=require("yaml"),r=require("json5"),s=require("smol-toml"),o=require("ini"),l=require("node:fs"),d=require("node:path"),a=require("ignore"),c=require("node:crypto"),u=require("fast-xml-parser");function f(e,t,n,i){return new(n||(n=Promise))((function(r,s){function o(e){try{d(i.next(e))}catch(e){s(e)}}function l(e){try{d(i.throw(e))}catch(e){s(e)}}function d(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,l)}d((i=i.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const m=" ",p={commentPropName:"!---",ignoreAttributes:!1,ignoreNameSpace:!1,parseTagValue:!1,parseNodeValue:!1,parseAttributeValue:!1,trimValues:!0,processEntities:!1,cdataPropName:"![CDATA["},y=Object.assign(Object.assign({},p),{format:!0,indentBy:m,suppressBooleanAttributes:!1,suppressEmptyNode:!1});function h(e,t=0){return new u.XMLBuilder(y).build(e).split("\n").map((e=>`${" ".repeat(4*t)}${e}`)).join("\n").trimEnd()}function $(e){return f(this,void 0,void 0,(function*(){const n=new u.XMLParser(p),i=yield t.readFile(e,"utf-8");let r;try{return r=n.parse(i,!0),r}catch(t){return void W.error(`${e} was unabled to be parsed and will not be processed. Confirm formatting and try again.`)}}))}function g(e,t){let n=`<${t}`;for(const[t,i]of Object.entries(e))if(t.startsWith("@")){n+=` ${t.slice(2)}="${String(i)}"`}return n+=">",n}function b(e){let t='<?xml version="1.0" encoding="UTF-8"?>';if(e["?xml"]){const n=e["?xml"];t=`<?xml ${Object.entries(n).map((([e,t])=>`${e.replace("@_","")}="${t}"`)).join(" ")}?>`}return t}function v(e){return f(this,void 0,void 0,(function*(){const t=b(e),n=Object.keys(e)[1];return[n,g(e[n],n),t]}))}function x(e,t){if(void 0===t)return j(e);const n=t.split(",");for(const t of n)if(void 0!==e[t]&&"string"==typeof e[t])return e[t];for(const n in e)if("object"==typeof e[n]&&null!==e[n]){const i=x(e[n],t);if(void 0!==i)return i}return j(e)}function j(e){const t=c.createHash("sha256");t.update(JSON.stringify(e));return t.digest("hex").slice(0,8)}function E(e){return f(this,void 0,void 0,(function*(){const n=yield $(e),r=i.stringify(n),s=e.replace(/\.xml$/,".yaml");yield t.writeFile(s,r),W.debug(`${e} has been transformed into ${s}`)}))}function w(e){return f(this,void 0,void 0,(function*(){const n=yield $(e),i=r.stringify(n,null,2),s=e.replace(/\.xml$/,".json5");yield t.writeFile(s,i),W.debug(`${e} has been transformed into ${s}`)}))}function P(e){return f(this,void 0,void 0,(function*(){const n=yield $(e),i=JSON.stringify(n,null,2),r=e.replace(/\.xml$/,".json");yield t.writeFile(r,i),W.debug(`${e} has been transformed into ${r}`)}))}function C(e){return f(this,void 0,void 0,(function*(){const n=yield $(e),i=s.stringify(n),r=e.replace(/\.xml$/,".toml");yield t.writeFile(r,i),W.debug(`${e} has been transformed into ${r}`)}))}function F(e){return f(this,void 0,void 0,(function*(){const n=yield $(e),i=o.stringify(n),r=e.replace(/\.xml$/,".ini");yield t.writeFile(r,i),W.debug(`${e} has been transformed into ${r}`)}))}function q(e){switch(e){case"yaml":return E;case"json5":return w;case"json":return P;case"toml":return C;case"ini":return F;default:return}}function N(e,i,r,s,o,l,d,a,c){return f(this,void 0,void 0,(function*(){let u="";const f=x(e,r),m=n.join(i,l),p=`${f}.${l}-meta.xml`,y=n.join(m,p);yield t.mkdir(m,{recursive:!0});const $=g(e,l);u=h(e,2);let b=`${a}\n`;b+=`${o}\n`,b+=`${d}${$}\n`,b+=`${u}\n`,b+=`${d}</${l}>\n`,b+=`</${s}>`,yield t.writeFile(y,b),W.debug(`Created disassembled file: ${y}`);const v=q(c);v&&(yield v(y),yield t.rm(y))}))}function O(e){return f(this,void 0,void 0,(function*(){const{element:t,disassembledPath:n,uniqueIdElements:i,rootElementName:r,rootElementHeader:s,key:o,indent:l,leafContent:d,leafCount:a,hasNestedElements:c,xmlDeclarationStr:u,format:f}=e;if("object"==typeof t)return yield N(t,n,i,r,s,o,l,u,f),[d,a,!0];return[`${d}${l}<${o}>${String(t)}</${o}>\n`,a+1,c]}))}function S(e,i,r,s,o,l,d){return f(this,void 0,void 0,(function*(){let a=`${l}\n`;a+=`${o}\n`,a+=e,a+=`</${s}>`;const c=n.join(i,`${r}.xml`);yield t.writeFile(c,a),W.debug(`Created disassembled file: ${c}`);const u=q(d);u&&(yield u(c),yield t.rm(c))}))}function L(e){return f(this,void 0,void 0,(function*(){const{element:t,key:n,indent:i,leafContent:r,leafCount:s,hasNestedElements:o}=e,l={};if("object"==typeof t)return l[n]||(l[n]=[]),l[n].push(t),{leafContent:r,leafCount:s,hasNestedElements:!0,nestedGroups:l};return{leafContent:`${r}${i}<${n}>${String(t)}</${n}>\n`,leafCount:s+1,hasNestedElements:o,nestedGroups:l}}))}function k(e,i,r,s,o,l,d,a){return f(this,void 0,void 0,(function*(){const c=n.join(r,`${e}.xml`);yield t.mkdir(r,{recursive:!0});let u=`${l}\n${o}\n`;for(const t of i){const n=Object.entries(t).filter((([e,t])=>A(e,t))).map((([e,t])=>` ${e.replace(/^@_/,"")}="${t}"`)).join(""),i=Object.fromEntries(Object.entries(t).filter((([e])=>!e.startsWith("@_"))));u+=`${d}<${e}${n}>\n`,u+=h(i,2),u+=`\n${d}</${e}>\n`}u+=`</${s}>`,yield t.writeFile(c,u),W.debug(`Created grouped nested file: ${c}`);const f=q(a);f&&(yield f(c),yield t.rm(c))}))}function A(e,t){return e.startsWith("@_")&&("string"==typeof t||"number"==typeof t)}const W=e.getLogger();e.configure({appenders:{disassemble:{type:"file",filename:"disassemble.log"}},categories:{default:{appenders:["disassemble"],level:"error"}}}),exports.DisassembleXMLFileHandler=class{constructor(){this.ign=a()}disassemble(e){return f(this,void 0,void 0,(function*(){const{filePath:n,uniqueIdElements:i,strategy:r="unique-id",prePurge:s=!1,postPurge:o=!1,ignorePath:a=".xmldisassemblerignore",format:c="xml"}=e,u=d.resolve(a);if(l.existsSync(u)){const e=yield t.readFile(u);this.ign.add(e.toString())}const f=yield t.stat(n),m=this.posixPath(d.relative(process.cwd(),n));if(f.isFile()){const e=d.resolve(n);if(!e.endsWith(".xml"))return void W.error(`The file path provided is not an XML file: ${e}`);if(this.ign.ignores(m))return void W.warn(`File ignored by ${a}: ${e}`);const t=d.dirname(e);yield this.processFile({dirPath:t,strategy:r,filePath:e,uniqueIdElements:i,prePurge:s,postPurge:o,format:c})}else if(f.isDirectory()){const e=yield t.readdir(n);for(const t of e){const e=d.join(n,t),l=this.posixPath(d.relative(process.cwd(),e));e.endsWith(".xml")&&!this.ign.ignores(l)?yield this.processFile({dirPath:n,strategy:r,filePath:e,uniqueIdElements:i,prePurge:s,postPurge:o,format:c}):this.ign.ignores(l)&&W.warn(`File ignored by ${a}: ${e}`)}}}))}processFile(e){return f(this,void 0,void 0,(function*(){const{dirPath:n,strategy:i,filePath:r,uniqueIdElements:s,prePurge:o,postPurge:a,format:c}=e;W.debug(`Parsing file to disassemble: ${r}`);const u=d.basename(r,d.extname(r)),p=u.split(".")[0];let y;y=d.join(n,p),o&&l.existsSync(y)&&(yield t.rm(y,{recursive:!0})),"grouped-by-tag"===i?yield function(e,n,i,r,s,o){return f(this,void 0,void 0,(function*(){const l=yield $(e);if(void 0===l)return;const d=Object.keys(l)[1],a=b(l),c=l[d],u=g(c,d);let f="",m=0,p=!1;const y={};for(const e of Object.keys(c).filter((e=>!e.startsWith("@")))){const t=Array.isArray(c[e])?c[e]:[c[e]];for(const n of t){const t=yield L({element:n,key:e,indent:r,leafContent:f,leafCount:m,hasNestedElements:p});f=t.leafContent,m=t.leafCount,p=t.hasNestedElements;for(const e in t.nestedGroups)y[e]||(y[e]=[]),y[e].push(...t.nestedGroups[e])}}if(p){for(const e in y)yield k(e,y[e],n,d,u,a,r,o);m>0&&(yield S(f,n,i,d,u,a,o)),s&&(yield t.unlink(e))}else W.error(`The XML file ${e} only has leaf elements. This file will not be disassembled.`)}))}(r,y,u,m,a,c):yield function(e,n,i,r,s,o,l){return f(this,void 0,void 0,(function*(){const d=yield $(e);if(void 0===d)return;const a=Object.keys(d)[1],c=b(d),u=d[a],f=g(u,a);let m="",p=0,y=!1;for(const e of Object.keys(u).filter((e=>!e.startsWith("@"))))if(Array.isArray(u[e]))for(const t of u[e]){const[r,o,d]=yield O({element:t,disassembledPath:n,uniqueIdElements:i,rootElementName:a,rootElementHeader:f,key:e,indent:s,leafContent:m,leafCount:p,hasNestedElements:y,xmlDeclarationStr:c,format:l});m=r,p=o,y=d}else{const[t,r,o]=yield O({element:u[e],disassembledPath:n,uniqueIdElements:i,rootElementName:a,rootElementHeader:f,key:e,indent:s,leafContent:m,leafCount:p,hasNestedElements:y,xmlDeclarationStr:c,format:l});m=t,p=r,y=o}y?(p>0&&(yield S(m,n,r,a,f,c,l)),o&&t.unlink(e)):W.error(`The XML file ${e} only has leaf elements. This file will not be disassembled.`)}))}(r,y,s,u,m,a,c)}))}posixPath(e){return e.replace(/\\+/g,"/")}},exports.ReassembleXMLFileHandler=class{processFilesInDirectory(e){return f(this,void 0,void 0,(function*(){const i=[];let r;const s=yield t.readdir(e);s.sort(((e,t)=>{const n=e.split(".")[0].toLowerCase(),i=t.split(".")[0].toLowerCase();return n.localeCompare(i)}));for(const o of s){const s=n.join(e,o),l=yield t.stat(s);if(l.isFile()){if(/\.(xml|json|json5|ya?ml|toml|ini)$/.test(o)){const e=yield this.parseToXmlObject(s);if(void 0===e)continue;r=yield v(e);const t=h(e);i.push(t)}}else if(l.isDirectory()){const[e,t]=yield this.processFilesInDirectory(s);i.push(...e),r=t}}return[i,r]}))}reassemble(e){return f(this,void 0,void 0,(function*(){const{filePath:i,fileExtension:r,postPurge:s=!1}=e;let o=[];if(!(yield t.stat(i)).isDirectory())return void W.error(`The provided path to reassemble is not a directory: ${i}`);W.debug(`Parsing directory to reassemble: ${i}`);const[l,d]=yield this.processFilesInDirectory(i);o=l;const a=n.dirname(i),c=n.basename(i),u=r?`${c}.${r}`:`${c}.xml`,p=n.join(a,u);if(void 0!==d){const[e,n,r]=d;yield function(e,n,i,r,s){return f(this,void 0,void 0,(function*(){let o=e.join("\n");const l=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),d=new RegExp(`^\\s*${l}\\s*$`,"gm");o=o.replace(d,""),o=o.replace(new RegExp(`<${i}\\s*[^>]*>`,"g"),""),o=o.replace(new RegExp(`</${i}>`,"g"),""),o=o.replace(/<!\[CDATA\[\s*([\s\S]*?)\s*]]>/g,(function(e,t){const n=t.trim().split("\n").map((function(e){return e.replace(/^\s*/,"")}));return"<![CDATA[\n"+m+n.join("\n"+m)+"\n]]>"})),o=o.replace(/(\n\s*){2,}/g,`\n${m}`);const a=`</${i}>`;yield t.writeFile(n,`${s}\n${r}${o}${a}`),W.debug(`Created reassembled file: ${n}`)}))}(o,p,e,n,r),s&&(yield t.rm(i,{recursive:!0}))}else W.error(`No files under ${i} were parsed successfully. A reassembled XML file was not created.`)}))}parseToXmlObject(e){return f(this,void 0,void 0,(function*(){if(e.endsWith(".xml"))return yield $(e);const n=yield t.readFile(e,"utf-8");let l;return e.endsWith(".yaml")||e.endsWith(".yml")?l=i.parse(n):e.endsWith(".json5")?l=r.parse(n):e.endsWith(".json")?l=JSON.parse(n):e.endsWith(".toml")?l=s.parse(n):e.endsWith(".ini")&&(l=o.parse(n)),l}))}},exports.buildXMLString=h,exports.logger=W,exports.parseXML=$,exports.setLogLevel=function(t){e.getLogger().level=t};
//# sourceMappingURL=index.min.cjs.map