feat: printTemplate (#1338)
Co-authored-by: root <root@huan.daoyoucloud.com> Co-authored-by: sealday <zhanglin@daoyoucloud.com> Reviewed-on: daoyoucloud/tachybase#1338 Reviewed-by: sealday <zhanglin@daoyoucloud.com> Co-authored-by: yoona <1486343814@qq.com> Co-committed-by: yoona <1486343814@qq.com>
This commit is contained in:
		
							parent
							
								
									6a151a136c
								
							
						
					
					
						commit
						49a8e2e534
					
				| @ -0,0 +1,2 @@ | |||||||
|  | /node_modules | ||||||
|  | /src | ||||||
| @ -0,0 +1 @@ | |||||||
|  | # @tachybase/plugin-print-template | ||||||
							
								
								
									
										2
									
								
								packages/plugins/@tachybase/plugin-print-template/client.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/plugins/@tachybase/plugin-print-template/client.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | export * from './dist/client'; | ||||||
|  | export { default } from './dist/client'; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | module.exports = require('./dist/client/index.js'); | ||||||
| @ -0,0 +1,15 @@ | |||||||
|  | { | ||||||
|  |   "name": "@tachybase/plugin-print-template", | ||||||
|  |   "version": "0.21.73", | ||||||
|  |   "main": "dist/server/index.js", | ||||||
|  |   "dependencies": { | ||||||
|  |     "docxtemplater": "^3.48.0", | ||||||
|  |     "pizzip": "^3.1.7", | ||||||
|  |     "xml2js": "^0.6.2" | ||||||
|  |   }, | ||||||
|  |   "peerDependencies": { | ||||||
|  |     "@tachybase/client": "workspace:*", | ||||||
|  |     "@tachybase/server": "workspace:*", | ||||||
|  |     "@tachybase/test": "workspace:*" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								packages/plugins/@tachybase/plugin-print-template/server.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								packages/plugins/@tachybase/plugin-print-template/server.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | export * from './dist/server'; | ||||||
|  | export { default } from './dist/server'; | ||||||
| @ -0,0 +1 @@ | |||||||
|  | module.exports = require('./dist/server/index.js'); | ||||||
| @ -0,0 +1,21 @@ | |||||||
|  | import { Plugin } from '@tachybase/client'; | ||||||
|  | 
 | ||||||
|  | export class PluginPrintTemplateClient extends Plugin { | ||||||
|  |   async afterAdd() { | ||||||
|  |     // await this.app.pm.add()
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async beforeLoad() {} | ||||||
|  | 
 | ||||||
|  |   // You can get and modify the app instance here
 | ||||||
|  |   async load() { | ||||||
|  |     console.log(this.app); | ||||||
|  |     // this.app.addComponents({})
 | ||||||
|  |     // this.app.addScopes({})
 | ||||||
|  |     // this.app.addProvider()
 | ||||||
|  |     // this.app.addProviders()
 | ||||||
|  |     // this.app.router.add()
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default PluginPrintTemplateClient; | ||||||
| @ -0,0 +1,2 @@ | |||||||
|  | export * from './server'; | ||||||
|  | export { default } from './server'; | ||||||
| @ -0,0 +1,93 @@ | |||||||
|  | import fs from 'fs'; | ||||||
|  | import path from 'path'; | ||||||
|  | import { PassThrough, Readable } from 'stream'; | ||||||
|  | import { Context } from '@tachybase/actions'; | ||||||
|  | import { Model } from '@tachybase/database'; | ||||||
|  | 
 | ||||||
|  | import Docxtemplater from 'docxtemplater'; | ||||||
|  | import PizZip from 'pizzip'; | ||||||
|  | 
 | ||||||
|  | import { getTemplateParams } from './template-params'; // 导入 getTemplateParams
 | ||||||
|  | 
 | ||||||
|  | export const generate = async (ctx: Context) => { | ||||||
|  |   const id = ctx.action.params.id; | ||||||
|  |   const repo = ctx.db.getRepository('templateManage'); | ||||||
|  |   const template: Model = await repo.findOne({ | ||||||
|  |     filter: { | ||||||
|  |       id, | ||||||
|  |     }, | ||||||
|  |     appends: ['template'], | ||||||
|  |   }); | ||||||
|  |   console.log(template.get()); | ||||||
|  | 
 | ||||||
|  |   const rawTemplate = template.get(); | ||||||
|  |   const templatePath = path.join(process.env.PWD, rawTemplate.template[0].get().url); | ||||||
|  | 
 | ||||||
|  |   const data = rawTemplate.testData; | ||||||
|  | 
 | ||||||
|  |   const outputPath = path.join(__dirname, './output.docx'); | ||||||
|  | 
 | ||||||
|  |   try { | ||||||
|  |     // 获取模板中的占位符
 | ||||||
|  |     const tags = (await getTemplateParams(templatePath)) as any; | ||||||
|  |     console.log('Template tags:', tags); | ||||||
|  | 
 | ||||||
|  |     // 验证数据是否包含所有占位符
 | ||||||
|  |     const missingTags = tags.filter((tag) => !data.prototype.hasOwnProperty.call(tag.replace(/[{}]/g, ''))); | ||||||
|  |     if (missingTags.length > 0) { | ||||||
|  |       // throw new Error(`Missing data for tags: ${missingTags.join(',')}`);
 | ||||||
|  |       console.log('Missing data for tags'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // 生成定制的 docx 文件
 | ||||||
|  |     const buffer = generateDocxFromTemplate(templatePath, data); | ||||||
|  | 
 | ||||||
|  |     // 创建一个可读流
 | ||||||
|  |     const readableStream = new Readable({ | ||||||
|  |       read(size) { | ||||||
|  |         // 将Buffer数据push到可读流中
 | ||||||
|  |         this.push(buffer); | ||||||
|  |         // 标记流的末尾
 | ||||||
|  |         this.push(null); | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     ctx.withoutDataWrapping = true; | ||||||
|  |     // 设置响应类型为二进制流
 | ||||||
|  |     ctx.set('Content-Type', 'application/octet-stream'); | ||||||
|  |     // 将可读流设置为响应体
 | ||||||
|  |     ctx.body = readableStream; | ||||||
|  | 
 | ||||||
|  |     // // 确保生成的 docx 文件存在
 | ||||||
|  |     // if (!fs.existsSync(outputPath)) {
 | ||||||
|  |     //     throw new Error('Generated DOCX file not found');
 | ||||||
|  |     // }
 | ||||||
|  |     // ctx.body = 'Word and PDF files generated';
 | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Error:', error); | ||||||
|  |     ctx.status = 500; | ||||||
|  |     ctx.body = 'Error generating files: ' + error.message; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | function generateDocxFromTemplate(templatePath, data): Buffer { | ||||||
|  |   try { | ||||||
|  |     const content = fs.readFileSync(templatePath, 'binary'); | ||||||
|  |     const zip = new PizZip(content); | ||||||
|  |     const doc = new Docxtemplater(zip); | ||||||
|  | 
 | ||||||
|  |     doc.setData(data); | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |       doc.render(); | ||||||
|  |     } catch (error) { | ||||||
|  |       console.error('Error rendering template:', error); | ||||||
|  |       throw error; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return doc.getZip().generate({ type: 'nodebuffer' }); | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Error generating DOCX from template:', error); | ||||||
|  |     throw error; // Ensure errors are propagated correctly
 | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1,54 @@ | |||||||
|  | import fs from 'fs'; | ||||||
|  | 
 | ||||||
|  | import PizZip from 'pizzip'; | ||||||
|  | import { parseStringPromise } from 'xml2js'; | ||||||
|  | 
 | ||||||
|  | export async function getTemplateParams(templatePath) { | ||||||
|  |   try { | ||||||
|  |     const content = fs.readFileSync(templatePath, 'binary'); | ||||||
|  |     const zip = new PizZip(content); | ||||||
|  | 
 | ||||||
|  |     const getXmlContent = (fileName) => { | ||||||
|  |       const file = zip.file(fileName); | ||||||
|  |       return file ? file.asText() : ''; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const docXml = getXmlContent('word/document.xml'); | ||||||
|  | 
 | ||||||
|  |     const parseXml = async (xml) => { | ||||||
|  |       try { | ||||||
|  |         const result = await parseStringPromise(xml, { explicitArray: false, ignoreAttrs: true }); | ||||||
|  |         const body = result['w:document']['w:body']; | ||||||
|  |         return Array.isArray(body['w:p']) ? body['w:p'] : [body['w:p']]; | ||||||
|  |       } catch (error) { | ||||||
|  |         console.error('Error parsing XML:', error); | ||||||
|  |         throw error; | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const xmlContent = await parseXml(docXml); | ||||||
|  | 
 | ||||||
|  |     const extractTags = (nodes) => { | ||||||
|  |       const tags = new Set(); | ||||||
|  |       nodes.forEach((node) => { | ||||||
|  |         if (node['w:r'] && Array.isArray(node['w:r'])) { | ||||||
|  |           node['w:r'].forEach((r) => { | ||||||
|  |             if (r['w:t'] && r['w:t']['#']) { | ||||||
|  |               const matches = r['w:t']['#'].match(/\{[\w-]+\.}/g); | ||||||
|  |               if (matches) { | ||||||
|  |                 matches.forEach((tag) => tags.add(tag)); | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |       return tags; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const tags = extractTags(xmlContent); | ||||||
|  |     return Array.from(tags); // Ensure the return value is an array
 | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Error in getTemplateParams:', error); | ||||||
|  |     throw error; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -0,0 +1 @@ | |||||||
|  | export { default } from './plugin'; | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | import { Plugin } from '@tachybase/server'; | ||||||
|  | 
 | ||||||
|  | import { generate } from './actions/printTemplates'; | ||||||
|  | 
 | ||||||
|  | export class PluginPrintTemplateServer extends Plugin { | ||||||
|  |   async afterAdd() {} | ||||||
|  | 
 | ||||||
|  |   async beforeLoad() {} | ||||||
|  | 
 | ||||||
|  |   async load() { | ||||||
|  |     // localhost:3000/api/printTemplates:generate
 | ||||||
|  |     this.app.resourcer.define({ | ||||||
|  |       name: 'printTemplates', | ||||||
|  |       actions: { | ||||||
|  |         generate, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async install() {} | ||||||
|  | 
 | ||||||
|  |   async afterEnable() {} | ||||||
|  | 
 | ||||||
|  |   async afterDisable() {} | ||||||
|  | 
 | ||||||
|  |   async remove() {} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default PluginPrintTemplateServer; | ||||||
| @ -3483,6 +3483,27 @@ importers: | |||||||
|         specifier: ^6.11.2 |         specifier: ^6.11.2 | ||||||
|         version: 6.21.0(react-dom@18.3.1)(react@18.3.1) |         version: 6.21.0(react-dom@18.3.1)(react@18.3.1) | ||||||
| 
 | 
 | ||||||
|  |   packages/plugins/@tachybase/plugin-print-template: | ||||||
|  |     dependencies: | ||||||
|  |       '@tachybase/client': | ||||||
|  |         specifier: workspace:* | ||||||
|  |         version: link:../../../core/client | ||||||
|  |       '@tachybase/server': | ||||||
|  |         specifier: workspace:* | ||||||
|  |         version: link:../../../core/server | ||||||
|  |       '@tachybase/test': | ||||||
|  |         specifier: workspace:* | ||||||
|  |         version: link:../../../core/test | ||||||
|  |       docxtemplater: | ||||||
|  |         specifier: ^3.48.0 | ||||||
|  |         version: 3.48.0 | ||||||
|  |       pizzip: | ||||||
|  |         specifier: ^3.1.7 | ||||||
|  |         version: 3.1.7 | ||||||
|  |       xml2js: | ||||||
|  |         specifier: ^0.6.2 | ||||||
|  |         version: 0.6.2 | ||||||
|  | 
 | ||||||
|   packages/plugins/@tachybase/plugin-saml: |   packages/plugins/@tachybase/plugin-saml: | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@tachybase/actions': |       '@tachybase/actions': | ||||||
| @ -13928,7 +13949,6 @@ packages: | |||||||
|   /@xmldom/xmldom@0.8.10: |   /@xmldom/xmldom@0.8.10: | ||||||
|     resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} |     resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} | ||||||
|     engines: {node: '>=10.0.0'} |     engines: {node: '>=10.0.0'} | ||||||
|     dev: true |  | ||||||
| 
 | 
 | ||||||
|   /@xtuc/ieee754@1.2.0: |   /@xtuc/ieee754@1.2.0: | ||||||
|     resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} |     resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} | ||||||
| @ -17432,6 +17452,13 @@ packages: | |||||||
|     dependencies: |     dependencies: | ||||||
|       esutils: 2.0.3 |       esutils: 2.0.3 | ||||||
| 
 | 
 | ||||||
|  |   /docxtemplater@3.48.0: | ||||||
|  |     resolution: {integrity: sha512-eM/sSUIVZND/GeY7FCC8kL2QV9oEQZ/RNxfY9cC07JutpVMFC9EEBOk4ajs3mcN72gqzOUqrsdwXPmKTD9TyHA==} | ||||||
|  |     engines: {node: '>=0.10'} | ||||||
|  |     dependencies: | ||||||
|  |       '@xmldom/xmldom': 0.8.10 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /dom-accessibility-api@0.5.16: |   /dom-accessibility-api@0.5.16: | ||||||
|     resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} |     resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} | ||||||
| 
 | 
 | ||||||
| @ -22634,7 +22661,7 @@ packages: | |||||||
|     dependencies: |     dependencies: | ||||||
|       debug: 3.2.7 |       debug: 3.2.7 | ||||||
|       iconv-lite: 0.4.24 |       iconv-lite: 0.4.24 | ||||||
|       sax: 1.3.0 |       sax: 1.4.1 | ||||||
|     transitivePeerDependencies: |     transitivePeerDependencies: | ||||||
|       - supports-color |       - supports-color | ||||||
|     dev: false |     dev: false | ||||||
| @ -23330,6 +23357,10 @@ packages: | |||||||
|   /pako@1.0.11: |   /pako@1.0.11: | ||||||
|     resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} |     resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} | ||||||
| 
 | 
 | ||||||
|  |   /pako@2.1.0: | ||||||
|  |     resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /param-case@3.0.4: |   /param-case@3.0.4: | ||||||
|     resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} |     resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} | ||||||
|     dependencies: |     dependencies: | ||||||
| @ -23710,6 +23741,12 @@ packages: | |||||||
|     optionalDependencies: |     optionalDependencies: | ||||||
|       nice-napi: 1.0.2 |       nice-napi: 1.0.2 | ||||||
| 
 | 
 | ||||||
|  |   /pizzip@3.1.7: | ||||||
|  |     resolution: {integrity: sha512-VemVeAQtdIA74AN1Fsd5OmbMbEeS4YOwwlcudgzvmUrOIOPrk1idYC5Tw5FUFq/I0c26ziNOw9z//iPmGfp1jA==} | ||||||
|  |     dependencies: | ||||||
|  |       pako: 2.1.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /pkg-dir@4.2.0: |   /pkg-dir@4.2.0: | ||||||
|     resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} |     resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} | ||||||
|     engines: {node: '>=8'} |     engines: {node: '>=8'} | ||||||
| @ -26886,13 +26923,9 @@ packages: | |||||||
|       immutable: 4.3.5 |       immutable: 4.3.5 | ||||||
|       source-map-js: 1.2.0 |       source-map-js: 1.2.0 | ||||||
| 
 | 
 | ||||||
|   /sax@1.3.0: |  | ||||||
|     resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} |  | ||||||
| 
 |  | ||||||
|   /sax@1.4.1: |   /sax@1.4.1: | ||||||
|     resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} |     resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} | ||||||
|     requiresBuild: true |     requiresBuild: true | ||||||
|     optional: true |  | ||||||
| 
 | 
 | ||||||
|   /saxes@5.0.1: |   /saxes@5.0.1: | ||||||
|     resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} |     resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} | ||||||
| @ -30356,7 +30389,7 @@ packages: | |||||||
|     resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} |     resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} | ||||||
|     engines: {node: '>=4.0.0'} |     engines: {node: '>=4.0.0'} | ||||||
|     dependencies: |     dependencies: | ||||||
|       sax: 1.3.0 |       sax: 1.4.1 | ||||||
|       xmlbuilder: 11.0.1 |       xmlbuilder: 11.0.1 | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
| @ -30364,7 +30397,7 @@ packages: | |||||||
|     resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} |     resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} | ||||||
|     engines: {node: '>=4.0.0'} |     engines: {node: '>=4.0.0'} | ||||||
|     dependencies: |     dependencies: | ||||||
|       sax: 1.3.0 |       sax: 1.4.1 | ||||||
|       xmlbuilder: 11.0.1 |       xmlbuilder: 11.0.1 | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
| @ -30372,14 +30405,12 @@ packages: | |||||||
|     resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} |     resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} | ||||||
|     engines: {node: '>=4.0.0'} |     engines: {node: '>=4.0.0'} | ||||||
|     dependencies: |     dependencies: | ||||||
|       sax: 1.3.0 |       sax: 1.4.1 | ||||||
|       xmlbuilder: 11.0.1 |       xmlbuilder: 11.0.1 | ||||||
|     dev: true |  | ||||||
| 
 | 
 | ||||||
|   /xmlbuilder@11.0.1: |   /xmlbuilder@11.0.1: | ||||||
|     resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} |     resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} | ||||||
|     engines: {node: '>=4.0'} |     engines: {node: '>=4.0'} | ||||||
|     dev: true |  | ||||||
| 
 | 
 | ||||||
|   /xmlbuilder@15.1.1: |   /xmlbuilder@15.1.1: | ||||||
|     resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} |     resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user