svell_jerry 3 년 전
부모
커밋
f2acfe2d4d
8개의 변경된 파일120개의 추가작업 그리고 13개의 파일을 삭제
  1. 2 0
      .eslintrc.js
  2. 4 0
      build/webpack.dev.js
  3. 4 0
      esbuild/webpack.dev.js
  4. 2 0
      package.json
  5. 5 0
      src/define/global.d.ts
  6. 1 0
      src/internal.ts
  7. 13 0
      src/utils/BrowserUtils.ts
  8. 89 13
      src/xlsx/XLSX.ts

+ 2 - 0
.eslintrc.js

@@ -12,11 +12,13 @@ module.exports = {
         "es2021": true
     },
     "rules": {
+        "no-await-in-loop":"off",
         "no-return-assign": "off",
         "operator-assignment": "off",
         "no-fallthrough": "off",
         "function-call-argument-newline":"off",
         "no-else-return" : "off",
+        "no-empty":"off",
         "no-cond-assign": "off",
         "prefer-regex-literals": "off",
         "@typescript-eslint/no-empty-function": "off",

+ 4 - 0
build/webpack.dev.js

@@ -2,6 +2,7 @@ const merge = require('webpack-merge').merge;
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 const ESLintPlugin = require('eslint-webpack-plugin');
 const ProgressBarWebpackPlugin = require('progress-bar-webpack-plugin');
+const webpack = require('webpack');
 const path = require('path');
 const common = require('./webpack.config.js');
 
@@ -23,6 +24,9 @@ module.exports = merge(common, {
             title: 'luckysheet-io',
             scriptLoading: 'blocking',
         }),
+        new webpack.ProvidePlugin({
+            process: 'process/browser'
+        })
     ],
     output: {
         filename: 'js/[name].[contenthash].js',

+ 4 - 0
esbuild/webpack.dev.js

@@ -3,6 +3,7 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
 const ESLintPlugin = require('eslint-webpack-plugin');
 const ProgressBarWebpackPlugin = require('progress-bar-webpack-plugin');
+const webpack = require('webpack');
 const path = require('path');
 const common = require('./webpack.config.js');
 
@@ -27,6 +28,9 @@ module.exports = merge(common, {
         new MiniCssExtractPlugin({
             filename: 'css/[name].[contenthash].css',
         }),
+        new webpack.ProvidePlugin({
+            process: 'process/browser'
+        })
     ],
     output: {
         filename: 'js/[name].[contenthash].js',

+ 2 - 0
package.json

@@ -48,6 +48,8 @@
     "buffer": "6.0.3",
     "typedoc": "0.22",
 
+    "@types/readable-stream":"2.3.13",
+
     "jest": "27.0.6",
     "@types/jest": "27.0.3",
     "jest-canvas-mock": "2.3.1",

+ 5 - 0
src/define/global.d.ts

@@ -0,0 +1,5 @@
+declare namespace NodeJS {
+  interface Process {
+    browser: boolean;
+  }
+}

+ 1 - 0
src/internal.ts

@@ -1,4 +1,5 @@
 //= ===============================utils
+export * from './utils/BrowserUtils';
 export * from './utils/ExcelUtils';
 
 //= ===============================xlsx

+ 13 - 0
src/utils/BrowserUtils.ts

@@ -0,0 +1,13 @@
+const textDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8');
+
+export class BrowserUtils {
+  public static bufferToString(chunk: string | BufferSource) {
+    if (typeof chunk === 'string') {
+      return chunk;
+    }
+    if (textDecoder) {
+      return textDecoder.decode(chunk);
+    }
+    return chunk.toString();
+  }
+}

+ 89 - 13
src/xlsx/XLSX.ts

@@ -1,33 +1,109 @@
 import JSZip from "jszip";
 
 import {
+  PassThrough,
+  Duplex,
+} from 'readable-stream';
+
+import {
+  BrowserUtils,
   WorkBook,
 } from "../internal";
 
-/**
- * export xlsx
- */
 export class XLSX {
   protected _workbook: WorkBook;
 
-  /**
-     * create xlsx
-     * @param workbook
-     */
   public constructor(workbook: WorkBook) {
     this._workbook = workbook;
   }
 
-  /**
-     * load file buffer
-     * @param buffer
-     */
+  public async read(stream: Duplex): Promise<WorkBook> {
+    if (!stream[Symbol.asyncIterator] && stream.pipe) {
+      stream = stream.pipe(new PassThrough());
+    }
+    const chunks = [];
+    for await (const chunk of stream) {
+      chunks.push(chunk);
+    }
+    return this.load(Buffer.concat(chunks));
+  }
+
   public async load(buffer: Buffer): Promise<WorkBook> {
-    const zip = await JSZip.loadAsync(buffer);
-    const files = Object.values(zip.files);
+    const jszip = await JSZip.loadAsync(buffer);
+    const files = Object.values(jszip.files);
+
     for (const file of files) {
+      if (!file.dir) {
+        let fileName = file.name;
+        if (fileName[0] === '/') {
+          fileName = fileName.substring(1);
+        }
+
+        let stream: PassThrough;
+        if (fileName.match(/xl\/media\//)
+                    || fileName.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/)) {
+          stream = new PassThrough();
+          stream.write(await file.async('nodebuffer'));
+        } else {
+          stream = new PassThrough({
+            writableObjectMode: true,
+            readableObjectMode: true,
+          });
+          let content;
+          if (process.browser) {
+            content = BrowserUtils.bufferToString(await file.async('nodebuffer'));
+          } else {
+            content = await file.async('string');
+          }
+          const chunkSize = 16 * 1024;
+          for (let i = 0; i < content.length; i += chunkSize) {
+            stream.write(content.substring(i, i + chunkSize));
+          }
+        }
+        stream.end();
 
+        switch (fileName) {
+          case 'xl/workbook.xml': {
+            break;
+          }
+          case 'xl/styles.xml': {
+            break;
+          }
+          case 'xl/_rels/workbook.xml.rels': {
+            break;
+          }
+          case '_rels/.rels': {
+            break;
+          }
+          case 'xl/sharedStrings.xml': {
+            break;
+          }
+          case 'docProps/app.xml': {
+            break;
+          }
+          case 'docProps/core.xml': {
+            break;
+          }
+          default: {}
+        }
+      }
     }
     return null;
   }
+
+  public async readFile(filename: string): Promise<WorkBook> {
+    return null;
+  }
+
+  public async write(stream: Duplex): Promise<XLSX> {
+    return null;
+  }
+
+  public async writeBuffer(): Promise<XLSX> {
+    return null;
+  }
+
+  public async writeFile(filename: string): Promise<XLSX> {
+    return null;
+  }
 }