Count cell values only if another condition is met

I currently use the below function to count the occurances of the same value in a column.

function countRecords() {

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  const last = sheet.getLastRow();
  const range = 'B2:B' + last ;
  const data = sheet.getRange(range).getValues();
  
  const counts = {};

  data.forEach(function (x) { counts[x] = (counts[x] || 0) + 1; });
  var result = Object.entries(counts);
  return result; 
  
}

This results in an array with each unique value and a count of how many times it appears in the column.
I now have a requirement to only count the value if another value on the row exists.

For Example

COL A COL B
Val1
Val1
Val1 Something
Val1 something

I would expect the output to be [Va1, 2], it should only count the rows where COLB is empty.

I have tried nesting loops but I am getting more confused as I go and would appreciate some help.

Solana Swap Error with Jupiter/Raydium SDK – “Unable to Swap Tokens”

I am unable to have proper swap transaction. i tried raydium & orca api both throwed poolInfo undefined.

can you please go through my code and let me know the reason. i just want to loop over my wallets and want to swap sol to kalki token.
I am new to this so please help

thanks

const BigNumber = require('bignumber.js');
const { Connection, PublicKey, Keypair } = require('@solana/web3.js');
const { getMint } = require('@solana/spl-token');
const { Jupiter, SwapMode } = require('@jup-ag/api');
require('dotenv').config();
console.log(Jupiter, SwapMode)
// --- Configuration ---
const RPC_URL = process.env.RPC_URL || 'https://api.mainnet-beta.solana.com';
const connection = new Connection(RPC_URL, 'confirmed');

const SOURCE_TOKEN_MINT = new PublicKey('So11111111111111111111111111111111111111112'); // Token A (e.g., SOL)
const TARGET_TOKEN_MINT = new PublicKey('8rKrd91nu6uRJa8hntaft5YDwmwkMhSGkTuRitRNdJKE'); // Replace with actual Kalki token mint address

// Load wallets from environment variables
const wallets = [
  process.env.WALLET_PRIVATE_KEY1,
  process.env.WALLET_PRIVATE_KEY2,
  process.env.WALLET_PRIVATE_KEY3,
  process.env.WALLET_PRIVATE_KEY4,
  // Add more wallets here
].map((key) => Keypair.fromSecretKey(Uint8Array.from(JSON.parse(key))));

// --- Helper Function: Initialize Jupiter ---
async function initializeJupiter(connection) {
  const jupiter = await Jupiter.load({
    connection,
    cluster: 'mainnet-beta', // Use 'mainnet-beta' or 'devnet'
  });
  return jupiter;
}

// --- Helper Function: Check Wallet Balance ---
async function checkWalletBalance(wallet) {
  const balance = await connection.getBalance(wallet.publicKey);
  console.log(`Wallet ${wallet.publicKey.toBase58()} balance: ${(balance / 10 ** 9).toFixed(5)} SOL`);
  return balance;
}

// --- Helper Function: Fetch Token Decimals ---
const tokenDecimals = async (mintAddress) => {
  const mintInfo = await getMint(connection, new PublicKey(mintAddress));
  return mintInfo.decimals;
};

// --- Execute the Swap using Jupiter ---
async function executeSwap(wallet, amountInLamports, jupiter) {
  try {
    const swapAmount = new BigNumber(amountInLamports).toString(); // Amount in lamports
    console.log('Executing swap with amount (in SOL):', swapAmount / 10 ** 9);

    // Find the best route for the swap
    const routes = await jupiter.computeRoutes({
      inputMint: SOURCE_TOKEN_MINT,
      outputMint: TARGET_TOKEN_MINT,
      amount: amountInLamports, // Amount in lamports
      slippage: 1, // Slippage tolerance in percentage
    });

    if (!routes.routesInfos || routes.routesInfos.length === 0) {
      throw new Error('No routes found for the swap.');
    }

    const bestRoute = routes.routesInfos[0]; // Take the best route
    console.log('Best route:', bestRoute);

    // Execute the swap
    const { swapTransaction } = await jupiter.executeSwap({
      routeInfo: bestRoute,
      swapMode: SwapMode.ExactIn, // Swap exact input amount
    });

    if (!swapTransaction) {
      throw new Error('Failed to create a swap transaction.');
    }

    // Sign and send the transaction
    const latestBlockhash = await connection.getLatestBlockhash();
    swapTransaction.recentBlockhash = latestBlockhash.blockhash;
    swapTransaction.feePayer = wallet.publicKey;
    swapTransaction.sign(wallet);

    const signature = await connection.sendRawTransaction(swapTransaction.serialize());
    await connection.confirmTransaction(signature, 'confirmed');

    console.log(`Swap executed successfully! View on Explorer: https://explorer.solana.com/tx/${signature}?cluster=mainnet`);
  } catch (error) {
    console.error('Error during swap execution:', error.message);
    throw error;
  }
}

// --- Main Function ---
(async () => {
  try {
    console.log('Connecting to Solana...');
    const version = await connection.getVersion();
    console.log('Connected to Solana cluster:', version);

    const jupiter = await initializeJupiter(connection);

    for (const [index, wallet] of wallets.entries()) {
      console.log(`n--- Processing Wallet ${index + 1} ---`);
      const balance = await checkWalletBalance(wallet);

      // Check if balance is sufficient
      const lamports = balance; // Balance in lamports
      const halfBalance = lamports / 2; // Half of wallet balance
      const transactionFee = 0.000005 * 10 ** 9; // Fee in lamports

      if (lamports < transactionFee) {
        console.error('Insufficient SOL balance for transaction fees. Skipping wallet.');
        continue;
      }

      const availableForSwap = halfBalance - transactionFee; // Deduct transaction fees
      if (availableForSwap <= 0) {
        console.error('Not enough SOL to perform the swap after deducting fees. Skipping wallet.');
        continue;
      }

      console.log(`Swapping half of the wallet balance: ${availableForSwap / 10 ** 9} SOL`);

      const swapAmount = new BigNumber(availableForSwap); // Amount to swap in lamports
      await executeSwap(wallet, swapAmount, jupiter); // Execute swap
    }

    console.log('nAll transactions completed!');
  } catch (error) {
    console.error('Error during token swap process:', error.message);
  }
})();

errors:

bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)
undefined { ExactIn: 'ExactIn', ExactOut: 'ExactOut' }
Connecting to Solana...
Connected to Solana cluster: { 'feature-set': 3039680930, 'solana-core': '2.1.8' }     
Error during token swap process: Cannot read properties of undefined (reading 'load')

i tried with raydium too.

const {
    Connection,
    PublicKey,
    Keypair,
    Transaction,
    SystemProgram,
    sendAndConfirmTransaction,
} = require("@solana/web3.js");
const {
    Amm,
    LIQUIDITY_POOLS,
    createAssociatedTokenAccountInstruction,
} = require("@raydium-io/raydium-sdk");
const { TOKEN_PROGRAM_ID, getOrCreateAssociatedTokenAccount, createSyncNativeInstruction } = require("@solana/spl-token");
const bs58 = require("bs58");
require("dotenv").config();

// --- Configuration ---
const RPC_URL = process.env.RPC_URL || "https://api.mainnet-beta.solana.com";
const connection = new Connection(RPC_URL, "confirmed");

// Replace with your private key (use environment variables for security)
const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY1;
const userWallet = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(WALLET_PRIVATE_KEY)));

// Replace with the Raydium pool ID for SOL-to-KALKI swaps
const RAYDIUM_POOL_ID = ""; // Example Pool ID

// --- Fetch Pool Details ---
async function getPoolDetails() {
    try {
        const response = await connection.getParsedAccountInfo(new PublicKey(RAYDIUM_POOL_ID));
        const poolInfo = response.value.data;
        if (!poolInfo) {
            throw new Error("Failed to fetch pool details. Pool data not found.");
        }
        console.log("Fetched Pool Info:", poolInfo);
        return poolInfo;
    } catch (error) {
        console.error("Error fetching pool details:", error.message);
        throw error;
    }
}

async function wrapSol(amount) {
    try {
      // Check wallet balance
      const balance = await connection.getBalance(userWallet.publicKey);
      console.log("Wallet Balance:", balance / 10 ** 9, "SOL");
  
      if (balance < amount + 0.000005 * 10 ** 9) {
        throw new Error("Insufficient SOL balance for wrapping and transaction fees.");
      }
  
      // WSOL mint address
      const wsolMintAddress = new PublicKey("So11111111111111111111111111111111111111112");
  
      // Create or get associated WSOL account
      const wsolAccount = await getOrCreateAssociatedTokenAccount(
        connection,
        userWallet,
        wsolMintAddress,
        userWallet.publicKey
      );
  
      console.log("WSOL Account Address:", wsolAccount.address.toBase58());
  
      // Transfer SOL to WSOL account
      const transaction = new Transaction().add(
        SystemProgram.transfer({
          fromPubkey: userWallet.publicKey,
          toPubkey: wsolAccount.address,
          lamports: amount,
        }),
        createSyncNativeInstruction(wsolAccount.address)
      );
  
      const signature = await sendAndConfirmTransaction(connection, transaction, [userWallet]);
      console.log(`Wrapped ${amount / 10 ** 9} SOL to WSOL. Transaction: https://explorer.solana.com/tx/${signature}?cluster=mainnet`);
  
      return wsolAccount.address;
    } catch (error) {
      console.error("Error wrapping SOL:", error.message);
      throw error;
    }
  }
  

// --- Perform Token Swap ---
async function executeSwap(poolData, solAmount) {
    try {
        console.log("Executing swap with", solAmount, "lamports...");

        // Fetch the Kalki token mint address from the pool data
        const destinationVault = new PublicKey(poolData[0].mintB.address);

        // Create or fetch the associated token account for Kalki tokens
        const destinationTokenAccount = await getOrCreateAssociatedTokenAccount(
            connection,
            userWallet,
            destinationVault,
            userWallet.publicKey
        );

        console.log("Destination Token Account:", destinationTokenAccount.address.toBase58());

        // Construct the swap instruction
        const swapInstruction = AmmV3.makeSwapInstruction({
            poolInfo: poolData,
            userWallet: userWallet.publicKey,
            inputTokenAccount: userWallet.publicKey, // For SOL, inputTokenAccount is the wallet
            outputTokenAccount: destinationTokenAccount.address,
            amountIn: solAmount, // Amount of SOL to swap (in lamports)
            minAmountOut: 1, // Minimum acceptable Kalki tokens (adjust for slippage)
        });

        const transaction = new Transaction().add(swapInstruction);

        // Sign and send the transaction
        const signature = await connection.sendTransaction(transaction, [userWallet]);
        console.log(`Swap executed! View on Explorer: https://explorer.solana.com/tx/${signature}?cluster=mainnet`);
    } catch (error) {
        console.error("Error during swap execution:", error.message);
        throw error;
    }
}


// --- Main Function ---
(async () => {
    try {
        console.log("Connecting to Solana...");
        const version = await connection.getVersion();
        console.log("Connected to Solana cluster:", version);

        console.log("Fetching pool details...");
        const poolData = await getPoolDetails();

        console.log("Wrapping SOL...");
        const solAmount = 0.001 * 10 ** 9; // 0.002 SOL in lamports
        const kalkiAmount = solAmount / poolData[0].price; // SOL to Kalki conversion
        console.log(`You will receive approximately ${kalkiAmount} Kalki tokens.`);
        
        const wsolAccount = await wrapSol(solAmount);

        console.log("Swapping SOL for Kalki tokens...");
        await executeSwap(poolData, wsolAccount, solAmount);

        console.log("Swap completed!");
    } catch (error) {
        console.error("Error during token swap process:", error.message);
    }
})();

error :

bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)      

Connecting to Solana...
Connected to Solana cluster: { 'feature-set': 3039680930, 'solana-core': '2.1.8' }

Fetching pool details...
Fetched Pool Info: <Buffer f7 ed e3 f5 d7 c3 de 46 b3 21 3f ba 8b f9 c8 7f a9 1e 47 81 96 28 c3 83 e0 0b ea 7e 98 c7 a0 3e 03 ba 10 69 cf c3 f6 f3 88 f0 27 32 a4 b0 59 75 61 71 ... 587 more bytes>
Wrapping SOL...
You will receive approximately NaN Kalki tokens.
Wallet Balance: 0.007096975 SOL
WSOL Account Address: 6CajUsnhEEvr2YiBaUyDjPUXYJfTTxcPEancJNucPv4Z
Error wrapping SOL: Signature QgyMVa5nW4UmaLKBKh62sfW1EEdv2CEcCzJY1ikQqzVU4V28RGPCC6U8z8UUUAPUoM8vzLjX5jXwJDMHRDrrMEB has expired: block height exceeded.
Error during token swap process: Signature QgyMVa5nW4UmaLKBKh62sfW1EEdv2CEcCzJY1ikQqzVU4V28RGPCC6U8z8UUUAPUoM8vzLjX5jXwJDMHRDrrMEB has expired: block height exceeded.

I am doing something wrong when trying to decode this Base64 text into a file?

I am currently trying to create a web app using Vue.js in the Front-End and a Flask server on the Back-End to process videos.

The idea is that I upload a video from the Vue client-side code send a POST request for the Flask server, which will process the video (converting from any format to .mp4 and running a ML model) and return a JSON containing all the necessary information. The problem is that
when I try to decode my video into a URL, I get a video.js error:

Video.js error code

The crazy part is also that a jpg image that comes in THE SAME JSON can be decoded perfectly.

The graph below the black part is the image. Ignore the HTML positioning.

Here’s the VUE code make a POST for the video:


    async handleFileUpload($evt) {
      const file = $evt.target.files[0];

      if (file) {
        // VIDEO REQUEST
        const urlServer = "http://localhost:5000/analysis";
        const formData = new FormData();
        formData.append("file", file); // 'file' is the key used for the file on the server

        (async () => {
          try {
            const result = await axios.post(urlServer, formData, {
              headers: { "Content-Type": "multipart/form-data" },
            });
            console.log(`RESULT`, result);
            const resultJSON = result.data;
            const strResult = resultJSON.string;
            const grafico_base64 = resultJSON.grafico;
            let video_base64 = resultJSON.video;
            console.log("RECEIVED VIDEO: ", video_base64, typeof video_base64);
            const extension = resultJSON.extVideo;

            const mimeVar = mime.lookup(extension);

            await db.open();
            const videoData = {
              string: strResult,
              video: video_base64,
              grafico: grafico_base64,
              mimeVideo: mimeVar,
            };
            console.log(videoData);
            let constId = await db.add(videoData);
            console.log(constId + " " + typeof constId);

            alert(constId);
            console.log("VIDEO PROCESSADO");
            this.$router.push({
              name: "analiseVideo",
              query: { idVideoAnalise: constId },
            });
          } catch (error) {
            console.error(error + "An error occurred while uploading the file.");
          }
        })();
      }
    },

And the Vue code for decoding the video:

<script>
import db from "../db.js";
import videojs from "video.js";
import "video.js/dist/video-js.css";
import { Buffer } from "node:buffer";


export default {
  name: "Player_de_Video",
  components: {},
  data() {
    return {
      videoSource: "",
    };
  },
  async mounted() {
    console.log("MOUNTED VIDEOPLAYER:");
    const res = await this.pegarVideo();
    this.videoSource = res.videoURL;

    const mimeVideo = res.mime;
    this.graficoURL = res.graficoURL;
    this.$refs.imgGraf.src = this.graficoURL;
    this.strResult = res.strResult;

    const sources = [{ src: this.videoSource, type: `${mimeVideo}` }];
    this.setupPlayer(sources);
  },

  methods: {
    setupPlayer(sources) {
      //Initial videoplayer setup using data from VideoPlayer.vue
      this.player = videojs(this.$refs.videoplayer, {
        sources: sources,
      });
    },

    onVoltar() {
      this.$router.push("/");
    },
    async pegarVideo() {
      try {
        

        const resultData = {
              string: strResult,
              video: video_base64,
              grafico: grafico_base64,
              mimeVideo: mimeVar,
            };
        const mime = resultData.mimeVideo;

        const videoURL = this.base64ToURL(resultData.video, mime, "video.mp4");
        console.log(`VIDEO URL: ${videoURL}`);
        const graficoURL = this.base64ToURL(resultData.grafico, "image/jpg");
        const strResult = resultData.string;

        return { strResult, graficoURL, mime, videoURL };
      } catch (error) {
        console.error("ERROR! " + error);
      }
    },
    base64ToURL(base64String, mimeType) {
      // Decode the Base64 string
      try {
        const binaryString = Buffer.from(base64String, "base64").toString("binary");
        console.log("base64 STRING: ", base64String);
        const len = binaryString.length;
        const bytes = new Uint8Array(len);
        for (let i = 0; i < len; i++) {
          bytes[i] = binaryString.charCodeAt(i);
        }
        const blob = new Blob([bytes], { type: String(mimeType) }); // Adjust the MIME type as needed
        
        // Generate a URL for the Blob and set it as the video source
        const url = URL.createObjectURL(blob);
        return url;
      } catch (error) {
        console.error("Error decoding Base64 string:", error);
        return null;
      }
    },

Anyways, thanks for taking the time to read this! Any help is welcome.

How to fix Lambda function timeout when interacting with DynamoDB using AWS SDK v3 in Node.js?

I’m building a serverless API with Node.js using AWS Lambda, and my function interacts with DynamoDB to retrieve data. However, every time I try to interact with DynamoDB, the Lambda function times out before the request completes.

I have correctly configured my Lambda function’s execution role with the necessary permissions, and I’ve ensured that the AWS SDK v3 (@aws-sdk/client-dynamodb) is properly installed and initialized. Despite this, the Lambda function times out without successfully querying DynamoDB.

Here’s what I’ve done so far:

  • Configured the Lambda function timeout to 30 seconds, but it still times out.

  • I verified the permissions for the Lambda role, which includes access to DynamoDB.

  • I used async/await for handling asynchronous requests.

I expect the Lambda function to complete successfully and return data from DynamoDB without any timeouts.

  • I tried increasing the Lambda function’s timeout to 30 seconds.

  • I tried adjusting the read/write capacity of the DynamoDB table, but it didn’t solve the issue.

  • I expected the Lambda function to run without hitting the timeout and successfully retrieve the data from DynamoDB.

Task timed out after 30.01 seconds

const { DynamoDBClient, GetItemCommand } = require("@aws-sdk/client-dynamodb");

const client = new DynamoDBClient({ region: "us-east-1" });

const params = {
  TableName: "MyTable",
  Key: { "id": { S: "123" } }
};

exports.handler = async (event) => {
  try {
    const data = await client.send(new GetItemCommand(params));
    return {
      statusCode: 200,
      body: JSON.stringify(data),
    };
  } catch (err) {
    console.error("Error", err);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: "Could not retrieve data" }),
    };
  }
};

I’ve verified that the DynamoDB table exists and contains data for the provided id, but the Lambda function still times out.

Relationship between main thread and worker threads in Node.js: Context isolation and message exchange

I have tried implementing a test in my NodeJS service using Jest.
I’ve leveraged the auto mocks feature from Jest when mocking node_modules.

Since my application uses workers, I’ve noticed that the context of the workers knows nothing about the Jest environment and with it nothing about the mocked modules. Hence, my first question was:

  1. Is there a way to share mocks from the main thread with workers?

That question sparked my interest further, as I wanted to understand better how the workers are created and how the main thread and workers in NodeJS bound together. I’ve read a couple of articles, but some things are still not clear for me.

  1. How does the exchange of messages happen between the main thread and workers?
  2. If I understood correctly, main thread and the workers are part of the same process and share the memory. Why do they have different context?

I’ve seen this thread, and from there I drew the conclusion that context sharing won’t be possible.

There is a possibility to share the mocks via worker_data parameter when creating a worker thread. This is not a solution to my problem, but it looks to me that Jest and its mocks just won’t work with the worker threads the way they work in the main thread.

const worker = new Worker('./worker.js', { workerData: mockData });

worker.js:

const { workerData } = require('worker_threads'); 
const { produce, startConsumer } = workerData;

So I believe this answers the first question.

It still leaves me with a gap on the relationship between main and worker threads that I’ve asked about in points 2. and 3.

How to trim the content of the current editor state in Lexical.js based on height?

I am working with Lexical.js to implement a content editor. I want to trim the content of the current editor state if the rendered content’s height exceeds a specified height (rootelement).

Here’s the approach I’ve taken so far:

I’ve registered an update listener on the editor to monitor changes in the editor state.
I’m checking the height of the rendered content (innerHtml.height) against a predefined value (rootelement).
If the height exceeds the limit, I want to update the editor state to trim the content and make it visible within the height limit.

   editor.registerUpdateListener(({ editorState }) => {
     // Read the editorState and maybe get some value.
       editorState.read(() => {
       const innerHtmlHeight = // logic to get the height of the rendered content
       const rootElementHeight = // predefined height limit

       if (innerHtmlHeight > rootElementHeight) {
          // Schedule another update to trim the content
           editor.update(() => {
           // Here, I want to trim the content of the current editor state
           // How can I achieve this effectively?
           });
        }
     });
   });

What I Need Help With:
How can I trim or modify the current editor state to ensure the visible content stays within the height limit?
What’s the best way to calculate and adjust content in Lexical.js while maintaining proper editor functionality?
Any examples or guidance would be greatly appreciated. Thanks!

Tab Characters Align Correctly in Firefox but Misaligned in Chrome – Why?

I’m encountering inconsistent tab alignment between Chrome and Firefox. In the provided example, Firefox aligns tabs properly, while Chrome breaks the vertical alignment. I need help understanding why this happens and how to fix it.

Reproduction Steps:

Open this JSFiddle in Firefox: https://jsfiddle.net/hpft9581/4/

Open the same JSFiddle in Chrome.

Observe the alignment of the text after the tags.

Expected Behavior (Firefox):

Tabs (t) align vertically, creating consistent indentation:

enter image description here

Actual Behavior (Chrome):

Tabs are misaligned, causing uneven spacing:enter image description here

HTML:

<div class="container">
  <div class="justify-font">
    <p>
      <speaker><span id="1"></span></speaker> In publishing an
    </p>
    <p>
      <speaker><span id="2"></span></speaker> In publishing anqweqweqweqweqweqweqweqweqweqweqwe
    </p>
  </div>
</div>

CSS:


.justify-font {
  text-align: justify;
  text-align-last: left;
  tab-size: 12; /* Explicit tab size */
  font-size: 23px;
  white-space: pre-wrap; /* Preserve whitespace */
  word-wrap: break-word;
}

.container {
  width: 700px;
  max-width: 700px;
  margin: auto;
}

JavaScript:

document.getElementById("1").innerText = 't' + "John Snow";
document.getElementById("2").innerText = 't' + "John Snowssssss";

Questions:

Why does Chrome misalign tab characters compared to Firefox?

How can I achieve consistent cross-browser tab alignment without relying on browser-specific quirks?

How to split a DOM node around a selection?

I have a contenteditable div, and I want to split a node around a selection. Using execCommand(), I can toggle “bold” on or off for a selection, so if I have:

<b>ABCDEFGHI</b>

and select DEF, toggling “bold” gives me

<b>ABC</b>DEF<b>GHI</b>

where the <b> node has been split into two <b> nodes with a text node in between.

I want to be able to do the same with other elements not supported by execCommand(), for example <bdi>. In other words, if I start with

<bdi>ABCDEFGHI</bdi>

and select DEF, I want to end up with

<bdi>ABC</bdi>DEF<bdi>GHI</bdi>

I can test if the selection is contained in a surrounding <bdi> tag using range.commonAncestorContainer() and if not wrap the range in a <bdi> tag, but if there is an enclosing <bdi> node, how can I split it into (a) a well-formed <bdi> node before the selection, (b) a well-formed selection with no enclosing <bdi>, and (c) another well-formed <bdi> node after the selection, and then reassemble them?

How to insert the value-based if-condition in an array of objects [duplicate]

How can I insert the values in array of objects based on one value condition?

opayloadchild = [];

for (let i = 0; i < j; i++) {

     opayloadchild.push({
                            "A": "123456",
                            "B": data[i].x,
                            "C": data[i].y,
                            "D": data[i].z.toUpperCase(),
                            "E": data[i].d.toUpperCase(),
                            "F": data[i].e.toUpperCase()
                        })

}

In the above code I want to check inside the for-loop like if data[i].x is null or not.

If data[i].x = null then insert "" else the value.

How can I achieved this?

Prettier Custom Plugin

Using React, Typescript, Vite, Prettier.

I’m trying to customize some formatting options in Prettier, specifically have the opening curly bracket { in functions one line below their signature like so:

function myFunc()
{

}

instead of

function myFunc() {

}

I got the following:

import { doc } from 'prettier';
import parserBabel from 'prettier/parser-babel';

function printFunctionDeclaration(path, options, print) {
  const node = path.getValue();

  if (node.type === "FunctionDeclaration" || node.type === "ArrowFunctionExpression") {
    const parts = [
        print(path.get("id")), // Print the function name
        "(",
        print(path.get("params")),
        ")",
    ];

    // Add the opening curly brace on a new line
    parts.push([doc.builders.line, "{"]);
    
    // Print the body of the function
    parts.push(print(path.get("body")));

    return doc.builders.indent(parts);
  }

  return null;
}

export default {
    parsers: {
        astFormat: "babel",
        babel: {
          parse: (text, parsers, options) => {
            const ast = parserBabel.parsers.babel.parse(text, parsers, options);
            return ast;
          },
        },
      },
  printers: {
    astFormat: "babel",
    babel: {
        print(path, options, print) {
            const node = path.getValue();
            
            // Check for function declaration or arrow function expression
            if (node.type === "FunctionDeclaration" || node.type === "ArrowFunctionExpression") {
              return printFunctionDeclaration(path, options, print);
            }
      
            // Default printing for other nodes
            return print(path);
          },
    }
  },
};

But after linking it to my .prettierrc file and trying it, it gives me the following error: Error: astFormat is required.

IIS won’t handle the static file properly for nodejs-express and vite-react app. No static file found (index…. .js and index…. cs -> 404.0)

I have created frontend using react-vite and backend using nodejs-express.js. Done npm run build for production build of frontend and served the static build using express.static()

Whenever I host my app on IIS using iisnode and url-rewrite. The app can fetch index.html correctly but as soon as index.html being loaded the IIS can route the static files needed but index.html

<configuration> 
    <system.webServer>
  
     <handlers>
       <add name="iisnode" path="server.js" verb="*" modules="iisnode" />
     </handlers>
  
     <rewrite>
       <rules>
       
         <rule name="nodejs">
           <match url="(.*)" />
           <conditions>
             <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
           </conditions>
           <action type="Rewrite" url="server.js" />
         </rule>

        <rule name="ReactRouter Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          </conditions>
          <action type="Rewrite" url="/frontend/dist/index.html" />
        </rule>

       </rules>
     </rewrite>
  
     <security>
       <requestFiltering>
         <hiddenSegments>
           <add segment="node_modules" />
           <add segment="iisnode" />
         </hiddenSegments>
       </requestFiltering>
     </security>
     </system.webServer> 
 </configuration>

server.js:

import path from "path";
import express from "express";
import dotenv from "dotenv";
import cookieParser from "cookie-parser";

import authRoutes from './backend/routes/auth.routes.js'
import messageRoutes from "./backend/routes/message.routes.js";
import userRoutes from './backend/routes/user.routes.js';

import connectToMongoDB from "./backend/db/connectToMongoDB.js";
import { app, server } from "./backend/socket/socket.js";

dotenv.config();


// Initialize express application

const PORT = process.env.PORT || 5000;
const __dirname =  path.resolve();

// Load environment variables from .env file

/*
        MIDDLEWARE SECTION
*/
app.use(express.json()); //to parse the incoming requests with JSON payloads (from: req.body)
app.use(cookieParser());


// app.use->(  Middleware to handle routes starting with /api/auth/)
app.use("/api/auth", authRoutes);  //authentication routes
app.use("/api/messages", messageRoutes); //get & send:id message
app.use("/api/users", userRoutes);  //get users

app.use(express.static(path.join(__dirname, "/frontend/dist")));

app.get("*", (req, res) => {
        res.sendFile(path.join(__dirname, "/frontend", "dist", "index.html"));
})



/*
        SERVER SECTION
*/

// Start the server and listen on the specified port
server.listen(PORT, '0.0.0.0',() => {
    connectToMongoDB();
    console.log(`Server is running on PORT: http://localhost:${PORT}`)

});

I have hosted the app as subsite under default website and the error I always get is:
No .js and .css file found. I tried making changes in web.config still no reaults.


localhost/chat

http://localhost/assets/index-qBCe9vKe.js

JavaScript shuffle elements but track original index or use modulus to insert them into parent markup

I have the following markup:

<div class="">
  <div class="tiled-gallery__gallery">
    <div class="tiled-gallery__row columns-1">
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/our-team-dan/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-dan-1024x1024.jpeg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-dan-1024x1024.jpeg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-dan-1024x1024.jpeg?resize=1200%2C1200&amp;strip=info&amp;ssl=1 1200w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-dan-1024x1024.jpeg?resize=1500%2C1500&amp;strip=info&amp;ssl=1 1500w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-dan-1024x1024.jpeg?resize=1800%2C1800&amp;strip=info&amp;ssl=1 1800w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-dan-1024x1024.jpeg?resize=2000%2C2000&amp;strip=info&amp;ssl=1 2000w"
            />
          </a>
        </figure>
      </div>
    </div>
    <div class="tiled-gallery__row columns-2">
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/our-team-jessica/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-jessica-1024x1024.jpg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-jessica-1024x1024.jpg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-jessica-1024x1024.jpg?resize=1132%2C1132&amp;strip=info&amp;ssl=1 1132w"
            />
          </a>
        </figure>
      </div>
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/rebecca-2/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/Rebecca-1-1024x1024.jpg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/Rebecca-1-1024x1024.jpg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/Rebecca-1-1024x1024.jpg?resize=1200%2C1200&amp;strip=info&amp;ssl=1 1200w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/Rebecca-1-1024x1024.jpg?resize=1333%2C1333&amp;strip=info&amp;ssl=1 1333w"
            />
          </a>
        </figure>
      </div>
    </div>
    <div class="tiled-gallery__row columns-2">
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/our-team-test-2/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-2-1024x768.jpeg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-2-1024x768.jpeg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-2-1024x768.jpeg?resize=1200%2C1200&amp;strip=info&amp;ssl=1 1200w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-2-1024x768.jpeg?resize=1500%2C1500&amp;strip=info&amp;ssl=1 1500w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-2-1024x768.jpeg?resize=1800%2C1800&amp;strip=info&amp;ssl=1 1800w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-2-1024x768.jpeg?resize=2000%2C2000&amp;strip=info&amp;ssl=1 2000w"
            />
          </a>
        </figure>
      </div>
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/our-team-test-4/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-4-733x1024.jpeg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-4-733x1024.jpeg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-4-733x1024.jpeg?resize=1200%2C1200&amp;strip=info&amp;ssl=1 1200w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-4-733x1024.jpeg?resize=1500%2C1500&amp;strip=info&amp;ssl=1 1500w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-4-733x1024.jpeg?resize=1800%2C1800&amp;strip=info&amp;ssl=1 1800w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-4-733x1024.jpeg?resize=2000%2C2000&amp;strip=info&amp;ssl=1 2000w"
            />
          </a>
        </figure>
      </div>
    </div>
    <div class="tiled-gallery__row columns-2">
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/our-teram-test-3/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-teram-test-3-1024x718.jpg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-teram-test-3-1024x718.jpg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-teram-test-3-1024x718.jpg?resize=1200%2C1200&amp;strip=info&amp;ssl=1 1200w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-teram-test-3-1024x718.jpg?resize=1500%2C1500&amp;strip=info&amp;ssl=1 1500w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-teram-test-3-1024x718.jpg?resize=1800%2C1800&amp;strip=info&amp;ssl=1 1800w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-teram-test-3-1024x718.jpg?resize=2000%2C2000&amp;strip=info&amp;ssl=1 2000w"
            />
          </a>
        </figure>
      </div>
      <div class="tiled-gallery__col">
        <figure class="tiled-gallery__item">
          <a href="https://staging-7578-youthlandscapers.wpcomstaging.com/2024/12/11/our-team/our-team-test-1/">
            <img
              srcset="https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-1-768x1024.jpg?resize=600%2C600&amp;strip=info&amp;ssl=1 600w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-1-768x1024.jpg?resize=900%2C900&amp;strip=info&amp;ssl=1 900w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-1-768x1024.jpg?resize=1200%2C1200&amp;strip=info&amp;ssl=1 1200w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-1-768x1024.jpg?resize=1500%2C1500&amp;strip=info&amp;ssl=1 1500w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-1-768x1024.jpg?resize=1800%2C1800&amp;strip=info&amp;ssl=1 1800w,https://i0.wp.com/staging-7578-youthlandscapers.wpcomstaging.com/wp-content/uploads/2024/12/our-team-test-1-768x1024.jpg?resize=2000%2C2000&amp;strip=info&amp;ssl=1 2000w"
            />
          </a>
        </figure>
      </div>
    </div>
  </div>
</div>

I want to be able to shuffle each item: <div class="tiled-gallery__item"> into a random position, however the issue I have is that the first item has a parent container which specifies 1 column columns-1 although most of the markup uses the 2 column layout class columns-2.

I have written a basic shuffle using this javascript:

const shuffleElems = () => {
  const wrapper = document.querySelector(".tiled-gallery__gallery");
  const items = wrapper.querySelectorAll(
    ".tiled-gallery__row .tiled-gallery__col"
  );

  for (var i = items.length; i >= 0; i--) {
    wrapper.appendChild(items[(Math.random() * i) | 0]);
  }
};

shuffleElems();

This works in that it will rearrange the items, but it could add a single item into a column that should take two. So I assume I need some way of tracking the original index and the new one, and either using a modulus, or checking the parent class. Or possibly shuffling everything in the column-2 classes and then just swap the single row at the very end?

I hope this makes sense, all of the code is in codesandbox.

I will add a screenshot shortly.

How to use sendBeacon for tracking checkout status before page redirect in JavaScript?

I have a function submitOrderRequestForm that submits form data via an AJAX call and redirects the user to another page upon a successful response. I want to track the status “REQUEST_FLOW” using the sendBeacon API before the page redirects.

Here is my current code:

function submitOrderRequestForm() {
            $('#mobile_number').val($("#phone-number").intlTelInput("getNumber"));
            $('#contact_number').val($("#phone-number").intlTelInput("getNumber"));
            $('#orderType').val('order_request');
            // $('#consentEmailValue').val($("#consentEmail").is(":checked") ? 1 : 0);
            // $('#consentSMSValue').val($("#consentSMS").is(":checked") ? 1 : 0);
            $('#consentBothValue').val($("#consentBoth").is(":checked") ? 1 : 0);

            getToken();
            // $("#continueBtn").prop("disabled",true);
            $.ajax({
                url: "{{URL::route('item.borrow-post',$shoppingCart->id)}}",
                type: "post",
                async: false,
                data: $("#reservationForm").serialize(),
                success: function (data) {
                    if (data.type=='success') {
                        window.location.href = "{{URL::route('submit-order-request')}}";
                        checkout_tracking_status = "REQUEST_FLOW";
                    }
                },
}

I want to use the sendBeacon API to send tracking data to the server for the checkout_tracking_status = “REQUEST_FLOW” event. However, I’m not sure how to implement this correctly to ensure the beacon sends the data reliably before the page redirects.

Where should I place the sendBeacon call to ensure it executes before the redirect?
How can I structure the data payload for sendBeacon?

Any guidance or examples would be greatly appreciated.

SVG Sprite not working in the consuming app

I implemented an SVG sprite file generation for all my SVG icons. It works and I have a fully working file within components/icons/sprites/icons.svg. Then inside my Index.tsx file I have:

import { SvgIcon } from '@mui/material';

<SvgIcon
  viewBox={viewBox}
  sx={sx}
  aria-label={label}
  data-test={dataTest}
  {...rest}
>
  <use xlinkHref={`${sprite}#${iconName}`} />
</SvgIcon>'

It all works fine in my Storybook, so I’m sure that this implementation should be fine. If I inspect the element in the storybook it is:

<use xlink:href="static/media/icons.svg#text-aa"></use>

The issue starts to exist when I’m building my package. It struggles in the consuming app to get the icon. In my webpack config for the package I have:

{
  test: /components/icons/sprites/icons.svg$/,
  type: 'asset/resource',
  generator: {
    filename: 'sprites/icons.svg',
    publicPath: '/',
  },
},

I also have publicPath: '/', within the webpack output object.

This ends with such selector in the consuming app:

<use xlink:href="/assets/icons.svg#warning"></use>

It renders nothing

If I expect node_modules, the file is there – node_modules/@company/packageName/dist/assets/icons.svg

I can see in the Chrome network tab that it’s trying to reach /assets/icons.svg but ends up with 404 Not Found.

When I remove the publicPath: '/', from the webpack output object, and just keep:

{
  test: /components/icons/sprites/icons.svg$/,
  type: 'asset/resource',
},

for the rules object, I end up with some svg generated file in the main dist folder in the consuming app node modules: node_modules/@company/packageName/dist/db6b1fc5dea1759a88ef.svg

And then within the app running in the browser:

<use xlink:href="file:///Users/marcus/Desktop/repos/sso-playground/node_modules/@company/packageName/dist/components/badge/../../db6b1fc5dea1759a88ef.svg#warning"></use>

This time it is

Not allowed to load local resource:

Basically I’ve already experimented a lot with publicPath or filename and the build bundle in the consuming app follow all the settings, however then the import does not work. I’m a bit surprised, because there is another package running in my app, also design system with icons sprite from it, there’s no special config in the app for that and the icons just work out of the box with such tag:

<use xlink:href="/images/vendor/@company/anotherPackage/components/icons/icons.svg?16c5895e4b93fe53247be390dfbb7ba1#alert-circle"></use>

What am I missing, what could be done to get the icons working in my consuming app?

How to print in italic using Docxtemplater libary

I’m trying to generate a Microsoft Word Document using docxtemplater library https://www.npmjs.com/package/docxtemplater. Here is how my code would look like (using in browser):

<script src="https://cdnjs.cloudflare.com/ajax/libs/docxtemplater/3.49.0/docxtemplater.js"></script>
<script src="https://unpkg.com/[email protected]/dist/pizzip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
<script src="https://unpkg.com/[email protected]/dist/pizzip-utils.js"></script>

    <script>
        function loadFile(url, callback) {
            PizZipUtils.getBinaryContent(url, callback);
        }

        window.onload = function generate() {
        const data = "<i>some text with italic</i>";

        const file = "http://file-url";

        loadFile(file, function (error, content) {
            if (error) {
                throw error;
            }
            const zip = new PizZip(content);
            const doc = new window.docxtemplater(zip, {
                paragraphLoop: true,
                linebreaks: true,
            });

            doc.render({
                "data":data
            });

            const blob = doc.getZip().generate({
                type: "blob",
                mimeType:
                    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                compression: "DEFLATE",
            });
 
            saveAs(blob, "output.docx");

        });
    }
    </script>

When i look at the word output, i expect it to look like “some text with italic”, instead of

<i>some text with italic</i>

How can i make text in the word output italic using docxtemplater library?