dolanmiu / docx

Easily generate and modify .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.
https://docx.js.org/
MIT License
4.42k stars 486 forks source link

docx@5.0.0-rc5 DOMException [InvalidCharacterError] #2047

Closed parparpoundski closed 1 year ago

parparpoundski commented 1 year ago

I'm having an issue with "docx@5.0.0-rc5" after upgrading from NodeJS version 16.17.0 to v18.15.0:

POST /inventoryViewOrderPaging 200 7.604 ms - 33786

C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\protocol\Parser.js:437
      throw err; // Rethrow non-MySQL errors
      ^
DOMException [InvalidCharacterError]: Invalid character
    at new DOMException (node:internal/per_context/domexception:53:5)
    at __node_internal_ (node:internal/util:520:10)
    at atob (node:buffer:1315:11)
    at Media.convertDataURIToBinary (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\docx\build\index.js:18481:35)
    at Media.createMedia (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\docx\build\index.js:18451:57)
    at Media.addMedia (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\docx\build\index.js:18445:21)
    at Media.addImage (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\docx\build\index.js:18422:38)
    at buildLogo (C:\wamp64\www\MightyQuote\v4.3.1\routes\inventoryOrder.js:2253:21)
    at C:\wamp64\www\MightyQuote\v4.3.1\routes\inventoryOrder.js:2311:31
    at Query.<anonymous> (C:\wamp64\www\MightyQuote\v4.3.1\database.js:82:13)

Node.js v18.15.0
Press any key to continue . . .

When I try using the latest Docx version ("5.5.0" via npm install --save docx), I get the following:

POST /inventoryViewOrderPaging 200 7.038 ms - 33786
C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\protocol\Parser.js:437
      throw err; // Rethrow non-MySQL errors
      ^

TypeError: rows.map is not a function
    at new Table (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\docx\build\index.js:15092:70)
    at build<_REDACTED CLIENT INFORMATION_>FormDocx (C:\wamp64\www\MightyQuote\v4.3.1\routes\inventoryOrder.js:2494:18)
    at C:\wamp64\www\MightyQuote\v4.3.1\routes\inventoryOrder.js:2286:26
    at Query.<anonymous> (C:\wamp64\www\MightyQuote\v4.3.1\database.js:82:13)
    at Query.<anonymous> (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\Connection.js:526:10)
    at Query._callback (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\Connection.js:488:16)
    at Sequence.end (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
    at Query._handleFinalResultPacket (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\protocol\sequences\Query.js:149:8)
    at Query.EofPacket (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\protocol\sequences\Query.js:133:8)
    at Protocol._parsePacket (C:\wamp64\www\MightyQuote\v4.3.1\node_modules\mysql\lib\protocol\Protocol.js:291:23)

Node.js v18.15.0
Press any key to continue . . .

This is the caller function (see the comment '// LN # 2493 - Potentially the call that causes the crash?'):

/******************
 * build<_REDACTED CLIENT INFORMATION_>FormDocx
 * 
 * Custom form for <_REDACTED CLIENT INFORMATION_> used to display pallet, case, and carton counts.
 * Displays the individual carton counts if pallet or case and uses sqft as a measurment
 * 
 * 
 * @param lineItems
 * @returns table format for docx
 */
function build<_REDACTED CLIENT INFORMATION_>FormDocx(lineItems){
    var AlignmentType = docx.AlignmentType;
    var Table = docx.Table;
    var WidthType = docx.WidthType;
    var BorderStyle = docx.BorderStyle;
    var ShadingType = docx.ShadingType;

    function bottomBorder(cell,color,size){
        setBorderToNone(cell);
        cell.Borders.addBottomBorder(BorderStyle.SINGLE,size,color);
    }

    function setBackground(cell,pos){
        var mod = pos % 2;
        if( mod == 0){
            cell.setShading({
                fill: "white",
                val: ShadingType.PERCENT_100,
                color: "auto"
            });
        } else {
            cell.setShading({
                fill: "#e6e6e6",
                val: ShadingType.PERCENT_100,
                color: "auto"
            });
        }
    }

    var usePlts = false;
    var useCS = false;
    var useCtns = false;
    var totalCols = 5;
    var totalPallets = 0;
    var totalCartons = 0;
    var totalCases = 0;
    var grandTotal = 0;

    var headerFontSize = 24;
    var fontSize = 24;

    var cellWidth = [];

    for(var i = 0; i < lineItems.length; i++){
        if(lineItems[i].package_type == 1 && lineItems[i].product_type == 1 ){
            usePlts = true;
            useCtns = true
        } else if(lineItems[i].package_type == 2 && lineItems[i].product_type == 1){
            useCS = true;
            useCtns = true;
        } else {
            if( lineItems[i].package_type == 1 ){
                usePlts = true;
            } else if( lineItems[i].package_type == 2){
                useCS = true;
                totalCols++;
            }
        }
        //If all are found stop
        if( usePlts && useCtns && useCS){
            i = lineItems.length;
        }
    }

    if( usePlts ){
        totalCols++;
    }

    if( useCS ){
        totalCols++;
    }

    if( useCtns ){
        totalCols++;
    }

    switch( totalCols ){
        case 6:
            cellWidth = ['10%', '5%','10%', '40%','15%','20%'];
        break;

        case 7:
            cellWidth = ['10%', '5%','5%','5%','53%','10%','12%'];
        break;

        case 8:
            cellWidth = ['7%', '4%','10%','10%','10%','33%','13%','13%'];
        break;

        default:
            cellWidth = ['15%', '5%','40%', '20%','20%'];
    }

        // LN # 2493 - Potentially the call that causes the crash?
    var infoTable = new Table({
        rows: lineItems.length + 2,
        columns: totalCols,
        width: 100,
        widthUnitType: WidthType.PERCENTAGE,
    });

    //Build Headers
    var colPos = 0;

    var cell = infoTable.getCell(0,0);
    cell.add( quickParagraph("QTY",true,headerFontSize,"Calibri",AlignmentType.LEFT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    bottomBorder(cell,"black",20);
    setBackground(cell,colPos);
    colPos++;

    cell = infoTable.getCell(0,colPos);
    cell.add( quickParagraph("UOM",true,headerFontSize,"Calibri",AlignmentType.LEFT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    bottomBorder(cell,"black",20);
    setBackground(cell,colPos);
    colPos++;

    if( usePlts ){
        cell = infoTable.getCell(0,colPos);
        cell.add( quickParagraph("PLTS",true,headerFontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"black",20);
        setBackground(cell,colPos);
        colPos++;
    }

    if( useCS ){
        cell = infoTable.getCell(0,colPos);
        cell.add( quickParagraph("# CS",true,headerFontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"black",20);
        setBackground(cell,colPos);
        colPos++;
    }

    if( useCtns ){
        cell = infoTable.getCell(0,colPos);
        cell.add( quickParagraph("CTNS",true,headerFontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"black",20);
        setBackground(cell,colPos);
        colPos++;
    }

    cell = infoTable.getCell(0,colPos);
    cell.add( quickParagraph("Description",true,headerFontSize,"Calibri",AlignmentType.LEFT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    bottomBorder(cell,"black",20);
    setBackground(cell,colPos);
    colPos++;

    cell = infoTable.getCell(0,colPos);
    cell.add( quickParagraph("Price",true,headerFontSize,"Calibri",AlignmentType.RIGHT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    bottomBorder(cell,"black",20);
    setBackground(cell,colPos);
    colPos++;

    cell = infoTable.getCell(0,colPos);
    cell.add( quickParagraph("Total",true,headerFontSize,"Calibri",AlignmentType.RIGHT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    bottomBorder(cell,"black",20);
    setBackground(cell,colPos);

    for(var i = 0 ; i < lineItems.length; i++){

        var qty = 0,//holds the qty or the sqft depending on the product type
            productType = lineItems[i].package_type,
            uom = '',
            desc = lineItems[i].product_sku + ' - ' + lineItems[i].product_name,
            units = parseInt(lineItems[i].units),
            cost =  parseFloat(lineItems[i].cost),
            price = Math.round(  parseFloat(lineItems[i].cost) * 100 ) /100,
            productType = parseInt( lineItems[i].product_type, 10 ),
            packageType = parseInt( lineItems[i].package_type, 10),
            conversion = parseFloat( lineItems[i].conversion),
            amount = parseInt(lineItems[i].qty,10), //same as qty
            total = 0,
            cartons = 0;

        c = 0;
        grandTotal += total;

        if(productType == 1){
            uom = 'SQFT';
        } else if( productType == 2){
            uom = 'EA';
        } else if( productType == 3) {
            uom = 'QT';
        }

        row = [];
        //pallet && sqft
        if(packageType == 1 && productType == 1 ){
            qty = convertQty( conversion * amount * units );
            cartons = amount * units;
            total = Math.round(amount * units * cost * 100) / 100;
            totalPallets += amount;
            totalCartons += amount * units;
        } else if(packageType == 1  ){
            qty = convertQty(  amount * units );
            total = Math.round(amount * units * cost * 100) / 100;
            totalPallets += amount;
        } else if( packageType == 2 && productType == 1 ) {
            qty = convertQty( conversion * amount * units);
            cartons = amount * units;
            total = Math.round(amount * units * cost * 100) / 100;
            totalCases += amount;
            totalCartons += amount * units;
        } else if( packageType == 2) {
            qty = convertQty( amount * units);
            total = Math.round(amount * units * cost * 100) / 100;
            totalCases += amount;
        } else {
            if( productType == 1 ){
                qty = convertQty(conversion * amount * units  );
                total =  Math.round(cost * amount * 100) / 100;
                totalCartons += amount * units;
            } else if( productType == 2){
                qty = convertQty(amount * units );
                total =  Math.round(cost * amount * 100) / 100;
            } else {
                qty = convertQty( amount * units );
                total =  Math.round(cost * amount * 100) / 100;
            }
        }

        grandTotal += total;

        colPos = 0;
        cell = infoTable.getCell(i + 1,0);
        cell.add( quickParagraph(qty.toString(),false,fontSize,"Calibri",AlignmentType.LEFT) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"gray",15);
        setBackground(cell,colPos);
        colPos++;

        cell = infoTable.getCell(i + 1,colPos);
        cell.add( quickParagraph(uom,false,fontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"gray",15);
        setBackground(cell,colPos);
        colPos++;

        if( usePlts ){
            cell = infoTable.getCell(i + 1,colPos);
            cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
            bottomBorder(cell,"gray",15);
            setBackground(cell,colPos);
            if( packageType == 1 ){
                cell.add( quickParagraph(amount.toString(),false,fontSize,"Calibri",AlignmentType.CENTER) );
            } else {
                cell.add( quickParagraph("",true,fontSize,"Calibri",AlignmentType.CENTER) );
            }

            colPos++;
        }

        if( useCS ){
            cell = infoTable.getCell(i + 1,colPos);
            cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
            bottomBorder(cell,"gray",15);
            setBackground(cell,colPos);
            if( packageType == 2  ){
                cell.add( quickParagraph(amount.toString(),false,fontSize,"Calibri",AlignmentType.CENTER) );
            } else {
                cell.add( quickParagraph("",false,fontSize,"Calibri",AlignmentType.CENTER) );
            }

            colPos++;
        }

        if( useCtns ){
            cell = infoTable.getCell(i + 1,colPos);
            cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
            bottomBorder(cell,"gray",15);
            setBackground(cell,colPos);
            if( productType == 1 && (packageType == 1 || packageType == 2) ){
                cell.add( quickParagraph(cartons.toString(),false,fontSize,"Calibri",AlignmentType.CENTER) );
            } else if(productType== 1){
                cell.add( quickParagraph(amount.toString(),false,fontSize,"Calibri",AlignmentType.CENTER) );
            } else {
                cell.add( quickParagraph("",false,fontSize,"Calibri",AlignmentType.CENTER) );
            }

            colPos++;
        }

        cell = infoTable.getCell(i + 1,colPos);
        cell.add( quickParagraph(desc,false,fontSize,"Calibri",AlignmentType.LEFT) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"gray",15);
        setBackground(cell,colPos);
        colPos++;

        cell = infoTable.getCell(i + 1,colPos);
        cell.add( quickParagraph('$'+price.toFixed(2).toString(),false,fontSize,"Calibri",AlignmentType.RIGHT) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"gray",15);
        setBackground(cell,colPos);
        colPos++;

        cell = infoTable.getCell(i + 1,colPos);
        cell.add( quickParagraph('$'+total.toFixed(2).toString(),false,fontSize,"Calibri",AlignmentType.RIGHT) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        bottomBorder(cell,"gray",15);
        setBackground(cell,colPos);
    }

    colPos = 0;

    cell = infoTable.getCell(lineItems.length + 1,colPos);
    setBorderToNone(cell);
    setBackground(cell,colPos);
    colPos++;

    cell = infoTable.getCell(lineItems.length + 1,colPos);
    setBorderToNone(cell);
    setBackground(cell,colPos);
    colPos++;

    if( usePlts ){
        cell = infoTable.getCell(lineItems.length + 1,colPos);
        cell.add( quickParagraph(totalPallets.toString(),true,fontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        setBorderToNone(cell);
        setBackground(cell,colPos);
        colPos++;
    }

    if( useCS ){
        cell = infoTable.getCell(lineItems.length + 1,colPos);
        cell.add( quickParagraph(totalCases.toString(),true,fontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        setBorderToNone(cell);
        setBackground(cell,colPos);
        colPos++;
    }

    if( useCtns ){
        cell = infoTable.getCell(lineItems.length + 1,colPos);
        cell.add( quickParagraph(totalCartons.toString(),true,fontSize,"Calibri",AlignmentType.CENTER) );
        cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
        setBorderToNone(cell);
        setBackground(cell,colPos);
        colPos++;
    }

    cell = infoTable.getCell(lineItems.length + 1,colPos);
    setBorderToNone(cell);
    setBackground(cell,colPos);
    colPos++;

    cell = infoTable.getCell(lineItems.length + 1,colPos);
    cell.add( quickParagraph('Total:',true,fontSize,"Calibri",AlignmentType.RIGHT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    setBorderToNone(cell);
    setBackground(cell,colPos);
    colPos++;

    cell = infoTable.getCell(lineItems.length + 1,colPos);
    cell.add( quickParagraph('$'+grandTotal.toFixed(2).toString(),true,fontSize,"Calibri",AlignmentType.RIGHT) );
    cell.Properties.setWidth(cellWidth[colPos],WidthType.PCT);
    setBorderToNone(cell);
    setBackground(cell,colPos);

    return infoTable;
};

Can anyone please explain how to resolve this?

dolanmiu commented 1 year ago

Your problem is here:

        // LN # 2493 - Potentially the call that causes the crash?
    var infoTable = new Table({
        rows: lineItems.length + 2,
        columns: totalCols,
        width: 100,
        widthUnitType: WidthType.PERCENTAGE,
    });

rows is an array, not a number. I suggest you use TypeScript to get type information:

https://github.com/dolanmiu/docx/blob/5.5.0/src/file/table/table.ts#L22

https://github.com/dolanmiu/docx/blob/5.5.0/src/file/table/table.ts#L45-L47

Also, upgrade docx to a newer version, docx@5 is old and deprecated for the most part.