How Can I Optimize Recursive Function Calls to Prevent Stack Overflow in Deeply Nested Data Structures?

I’m working on a recursive function to traverse and process deeply nested JSON structures. However, when the depth exceeds a certain limit (e.g., 10,000+ levels), my program crashes with a “Maximum call stack size exceeded” error.

I need a way to handle deep recursion without exceeding the call stack limit while maintaining performance.

  • Tried a regular recursive function → Works for small depths but fails at deep levels due to stack overflow.
  • Tried increasing Node.js stack size (–stack-size=8192) → Helps, but not a real solution for extreme depths.
  • Tried iterative approaches using loops → Hard to implement for deeply nested structures.
  • Tried asynchronous recursion with setImmediate() → Slows down performance significantly.

I expected a solution that allows me to traverse extremely deep structures without crashing the program.

How to correctly get transaction status via tonapi.io webhooks?

I’m integrating TON API and trying to set up receiving transaction notifications via webhooks. However, I’m facing an issue where TON API returns 401 Unauthorized or illegal base32 data at input byte 2.

Here is an example of the webhook request body I receive:

{
   "event_type": "account_tx",
   "account_id": "0:add4bfa3b10899fe5a53f8f5585705156feac70ee25df9b08de867596cbd7fab",
   "lt": 53812960000003,
   "tx_hash": "6ddd3abd23caacc8186c075a9e69a942a206caaf532f90f6e0cca5b52029609d"
}

I am passing account_id as a query parameter, but the API returns an illegal base32 data error.
I am also passing my API key in the “Authorization”: “Bearer <TON_API_KEY>” header.

How should I correctly process this webhook and fetch the transaction status? Should I convert account_id to another format?

I have tried the following approaches:

Passing account_id as HEX (as received in the webhook) → API returns 401 Unauthorized or illegal base32 data.
Converting account_id to base64url before making a request to TON API → API still returns 401.
Sending account_id without the 0: prefix → Error still persists.
I expect the API to correctly return the transaction status, but I can’t figure out the correct format for account_id.
I would appreciate any help or a working example!

Here is my current webhook handler code:

import { checkTransactionStatus } from "../utils/ton.js"; 

export default async function handler(req, res) {
    if (req.method !== "POST") {
    return res.status(405).json({ error: "Method not allowed" });
    }

    try {
    const { tx_hash, account_id } = req.body;

    if (!tx_hash || !account_id) {
      return res.status(400).json({ error: "Invalid request body: missing tx_hash or        account_id" });
     }

    // API key in the Authorization header
    const authHeader = req.headers.authorization || `Bearer ${process.env.TON_API_KEY}`;

    // Check transaction status
    const status = await checkTransactionStatus(tx_hash, account_id, authHeader);

    return res.status(200).json({ status, transaction: tx_hash, account: account_id });
  } catch (error) {
    return res.status(500).json({ error: "Internal server error", details: error.message });
  }
}

Quill HTML editor

I’m trying to add the ability to paste HTML into the Quill editor so that users can insert HTML tags inside the editor. However, following the instructions causes the editor to crash. I’m not sure how to properly add an HTML block to the Quill editor. After adding my code, Quill works correctly, but the actual HTML element is not being added to the editor.

My code

((exports) => {
  // Define HTMLElement Blot
  const Inline = Quill.import('blots/inline');

  class HTMLElement extends Inline {
    static create(value) {
      const node = super.create();
      const { tag, ...attributes } = value;
      node.tagName = tag.toUpperCase();
      
      Object.keys(attributes).forEach(attr => {
        node.setAttribute(attr, attributes[attr]);
      });
      
      return node;
    }

    static formats(node) {
      const attributes = {};
      if (node.hasAttributes()) {
        const attrs = node.attributes;
        for (let i = 0; i < attrs.length; i++) {
          attributes[attrs[i].name] = attrs[i].value;
        }
      }
      return {
        tag: node.tagName.toLowerCase(),
        ...attributes
      };
    }
  }

  // Register HTMLElement format
  Quill.register('formats/html-element', HTMLElement);

  const quillFormats = [
    "bold",
    "italic",
    "link",
    "underline",
    "header",
    "list",
    "video",
    "image",
    "alt",
    "break",
    "html-element"  // Added HTML element format
  ];

  const createQuillEditor = (container) => {
    const toolbar = $(container).data("toolbar");
    const disabled = $(container).data("disabled");

    const styles = {
      "Wyróżniony śródtytuł": "area-color-headline",
      "Podstawa prawna": "legal-basis",
    };

    let quillToolbar = [
      ["bold", "italic", "underline", "linebreak"],
      ["undo", "redo"],
      [{ list: "ordered" }, { list: "bullet" }],
      ["link", "button", "video", "clean", "html"]  // Added HTML button
    ];

    if (toolbar === "full") {
      quillToolbar = [
        [{ header: [2, 3, 4, 5, 6, false] }],
        ["bold", "italic", "underline", "strike"],
        ["undo", "redo"],
        ["style"],
        [{ align: [] }],
        [{ list: "ordered" }, { list: "bullet" }],
        [{ script: "sub" }, { script: "super" }],
        [{ indent: "-1" }, { indent: "+1" }],
        [{ direction: "rtl" }],
        ["blockquote"],
        ["link", "button", "image", "repository-image", "video", "html"],  // Added HTML button
        ["clean"],
        ["divider"],
      ];
    } else if (toolbar === "basic") {
      quillToolbar = [...quillToolbar, ["video"]];
    }

    var icons = Quill.import("ui/icons");

    icons["undo"] = `<svg viewbox="0 0 18 18">
                      <polygon class="ql-fill ql-stroke" points="6 10 4 12 2 10 6 10"></polygon>
                      <path class="ql-stroke" d="M8.09,13.91A4.6,4.6,0,0,0,9,14,5,5,0,1,0,4,9"></path>
                    </svg>`;

    icons["redo"] = `<svg viewbox="0 0 18 18">
                      <polygon class="ql-fill ql-stroke" points="12 10 14 12 16 10 12 10"></polygon>
                      <path class="ql-stroke" d="M9.91,13.91A4.6,4.6,0,0,1,9,14a5,5,0,1,1,5-5"></path>
                    </svg>`;

    icons["divider"] = `<svg viewbox="0 0 18 18">
                          <line x1="0" y1="9" x2="18" y2="9" stroke="currentColor" />
                        </svg>`;

    icons["button"] = `<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 32 32">
                        <g><g><path d="M28.8,0H3.2A3.2,3.2,0,0,0,0,3.2V28.8A3.2,3.2,0,0,0,3.2,32H28.8A3.2,3.2,0,0,0,32,28.8V3.2A3.2,3.2,0,0,0,28.8,0Zm-.64,28.16H3.84V3.84H28.16Z"/>
                        <path d="M11.16,8.72h4.37a9,9,0,0,1,4.24.79,2.88,2.88,0,0,1,1.44,2.77,3.49,3.49,0,0,1-.56,2,2.3,2.3,0,0,1-1.6,1v.1a4.26,4.26,0,0,1,1.27.5,2.36,2.36,0,0,1,.91,1,3.9,3.9,0,0,1,.34,1.77,3.56,3.56,0,0,1-1.39,3,5.91,5.91,0,0,1-3.77,1.09H11.16Zm3,5.57h1.73a2.94,2.94,0,0,0,1.8-.41,1.44,1.44,0,0,0,.5-1.21,1.25,1.25,0,0,0-.59-1.16,3.8,3.8,0,0,0-1.86-.35H14.13Zm0,2.36v3.66h1.95A2.7,2.7,0,0,0,18,19.79a1.88,1.88,0,0,0,.53-1.39,1.61,1.61,0,0,0-.54-1.27,3,3,0,0,0-2-.48Z"/></g></g></svg>`;

    icons["html"] = `<svg viewbox="0 0 18 18">
                      <text x="9" y="12" text-anchor="middle" fill="currentColor" style="font-size: 14px;">&lt;&gt;</text>
                    </svg>`;

    registerQuillStyleToolbarTool();

    Quill.register({
      "formats/extended-image": ExtendedImage,
      "formats/extended-video": ExtendedVideo,
      "formats/divider": Divider,
      "formats/link": Link,
      "formats/button": Button,
    });

    const $input = $(container).siblings('input[type="hidden"]');
    container.innerHTML = $input.val() || "";

    const quill = new Quill(container, {
      modules: {
        history: {
          userOnly: true,
        },
        toolbar: {
          container: quillToolbar,
          handlers: {
            image: createImageToolbarToolHandler({
              uploadEndpointUrl: "//" + location.host + "/admin/files",
            }),

            "repository-image": createRepositoryImageToolbarToolHandler({
              iframeSourceUrl: "/admin/files/editor_images",
            }),

            divider: function() {
              var range = quill.getSelection();
              if (range) {
                quill.insertEmbed(range.index, "divider", "null");
              }
            },

            html: function() {
              const range = this.quill.getSelection();
              if (range) {
                const tag = prompt('Enter HTML tag (e.g., span, div):', 'span');
                const className = prompt('Enter class name (optional):', '');
                
                if (tag) {
                  const value = {
                    tag: tag,
                    ...(className && { class: className })
                  };
                  
                  this.quill.format('html-element', value);
                }
              }
            }
          },
        },
      },
      formats: quillFormats,
      theme: "snow",
    });

    initializeQuillStyleToolbarTool(quill, styles);

    $(".ql-undo").on("click", function(e) {
      quill.history.undo();
    });

    $(".ql-redo").on("click", function(e) {
      quill.history.redo();
    });

    if (disabled) {
      quill.disable();
    }

    quill.on("text-change", () => {
      const text = quill.getText();

      let event = new CustomEvent("quill-position", {
        detail: quill.getSelection(),
      });
      container.dispatchEvent(event);

      $input.val(quill.root.innerHTML.replace(/(<p><br></p>)+$/, ""));
    });

    const length = quill.getLength();
    const text = quill.getText(length - 1, 1);

    if (text === "nn") {
      quill.deleteText(quill.getLength() - 1, 1);
    }

    return quill;
  };

  const quillEditor = () => {
    $(".editor-container").each((_idx, container) => {
      createQuillEditor(container);
    });
  };

  exports.Decidim = exports.Decidim || {};
  exports.Decidim.quillEditor = quillEditor;
  exports.Decidim.createQuillEditor = createQuillEditor;
})(window);

Editor code below

editor.js.es6

((exports) => {
  const quillFormats = [
    "bold",
    "italic",
    "link",
    "underline",
    "header",
    "list",
    "video",
    "image",
    "alt",
    "break",
  ];

  const createQuillEditor = (container) => {
    const toolbar = $(container).data("toolbar");
    const disabled = $(container).data("disabled");

    const styles = {
      // Custom Classes
      // Label => Custom Class without prefix
      "Wyróżniony śródtytuł": "area-color-headline",
      "Podstawa prawna": "legal-basis",
    };

    let quillToolbar = [
      ["bold", "italic", "underline", "linebreak"],
      ["undo", "redo"],
      [{ list: "ordered" }, { list: "bullet" }],
      ["link", "button", "video", "clean"],
    ];

    if (toolbar === "full") {
      quillToolbar = [
        [{ header: [2, 3, 4, 5, 6, false] }],
        ["bold", "italic", "underline", "strike"],
        ["undo", "redo"],
        ["style"],
        [{ align: [] }],
        [{ list: "ordered" }, { list: "bullet" }],
        [{ script: "sub" }, { script: "super" }],
        [{ indent: "-1" }, { indent: "+1" }],
        [{ direction: "rtl" }],
        ["blockquote"],
        ["link", "button", "image", "repository-image", "video"],
        ["clean"],
        ["divider"],
      ];
    } else if (toolbar === "basic") {
      quillToolbar = [...quillToolbar, ["video"]];
    }

    var icons = Quill.import("ui/icons");

    icons["undo"] = `<svg viewbox="0 0 18 18">
                      <polygon class="ql-fill ql-stroke" points="6 10 4 12 2 10 6 10"></polygon>
                      <path class="ql-stroke" d="M8.09,13.91A4.6,4.6,0,0,0,9,14,5,5,0,1,0,4,9"></path>
                    </svg>`;

    icons["redo"] = `<svg viewbox="0 0 18 18">
                      <polygon class="ql-fill ql-stroke" points="12 10 14 12 16 10 12 10"></polygon>
                      <path class="ql-stroke" d="M9.91,13.91A4.6,4.6,0,0,1,9,14a5,5,0,1,1,5-5"></path>
                    </svg>`;

    icons["divider"] = `<svg viewbox="0 0 18 18">
                          <line x1="0" y1="9" x2="18" y2="9" stroke="currentColor" />
                        </svg>`;

    icons[
      "button"
    ] = `<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 32 32"><g><g><path d="M28.8,0H3.2A3.2,3.2,0,0,0,0,3.2V28.8A3.2,3.2,0,0,0,3.2,32H28.8A3.2,3.2,0,0,0,32,28.8V3.2A3.2,3.2,0,0,0,28.8,0Zm-.64,28.16H3.84V3.84H28.16Z"/><path d="M11.16,8.72h4.37a9,9,0,0,1,4.24.79,2.88,2.88,0,0,1,1.44,2.77,3.49,3.49,0,0,1-.56,2,2.3,2.3,0,0,1-1.6,1v.1a4.26,4.26,0,0,1,1.27.5,2.36,2.36,0,0,1,.91,1,3.9,3.9,0,0,1,.34,1.77,3.56,3.56,0,0,1-1.39,3,5.91,5.91,0,0,1-3.77,1.09H11.16Zm3,5.57h1.73a2.94,2.94,0,0,0,1.8-.41,1.44,1.44,0,0,0,.5-1.21,1.25,1.25,0,0,0-.59-1.16,3.8,3.8,0,0,0-1.86-.35H14.13Zm0,2.36v3.66h1.95A2.7,2.7,0,0,0,18,19.79a1.88,1.88,0,0,0,.53-1.39,1.61,1.61,0,0,0-.54-1.27,3,3,0,0,0-2-.48Z"/></g></g></svg>`;

    registerQuillStyleToolbarTool();

    Quill.register({
      "formats/extended-image": ExtendedImage,
      "formats/extended-video": ExtendedVideo,
      "formats/divider": Divider,
      "formats/link": Link,
      "formats/button": Button,
    });

    const $input = $(container).siblings('input[type="hidden"]');
    container.innerHTML = $input.val() || "";

    const quill = new Quill(container, {
      modules: {
        history: {
          userOnly: true,
        },
        // linebreak: {},
        toolbar: {
          container: quillToolbar,
          handlers: {
            // "linebreak": exports.Decidim.Editor.lineBreakButtonHandler

            image: createImageToolbarToolHandler({
              uploadEndpointUrl:
                //"https://ks.beta-um.warszawa.pl/admin/files",
                "//" + location.host + "/admin/files",
            }),

            "repository-image": createRepositoryImageToolbarToolHandler({
              iframeSourceUrl: "/admin/files/editor_images",
            }),

            divider: function () {
              var range = quill.getSelection();
              if (range) {
                quill.insertEmbed(range.index, "divider", "null");
              }
            },
          },
        },
      },
      // formats: quillFormats,
      theme: "snow",
    });

    initializeQuillStyleToolbarTool(quill, styles);

    $(".ql-undo").on("click", function (e) {
      quill.history.undo();
    });

    $(".ql-redo").on("click", function (e) {
      quill.history.redo();
    });

    if (disabled) {
      quill.disable();
    }

    quill.on("text-change", () => {
      const text = quill.getText();

      // Triggers CustomEvent with the cursor position
      // It is required in input_mentions.js
      let event = new CustomEvent("quill-position", {
        detail: quill.getSelection(),
      });
      container.dispatchEvent(event);

      $input.val(quill.root.innerHTML.replace(/(<p><br></p>)+$/, ""));
    });

    const length = quill.getLength();
    const text = quill.getText(length - 1, 1);

    // Remove extraneous new lines
    if (text === "nn") {
      quill.deleteText(quill.getLength() - 1, 1);
    }

    return quill;
  };

  const quillEditor = () => {
    $(".editor-container").each((_idx, container) => {
      createQuillEditor(container);
    });
  };

  exports.Decidim = exports.Decidim || {};
  exports.Decidim.quillEditor = quillEditor;
  exports.Decidim.createQuillEditor = createQuillEditor;
})(window);

node-gdal-async docker failed when deployed in lambda

I recently need to make a docker image on node-async-lambda to deploy it on ECS. At the next step, I will use it as the base image to build lambda.
I have tested the simple PoC image locally, and it outputs normally. I successfully tagged it and uploaded it to ECS, and when I use it to build lambda, “Runtime exited without providing a reason” has been thrown. Anyone who has similar experience and solution?

Context:
Typescript as programming language so integrate “node-gdal-async” but not geolambda(python).
Example project is so simple, just a .mjs file as lambda standards, and some sample code as below, example.tif
is at the same folder – root folder of project.

import gdal from 'gdal-async';
export const handler = async (event) => {
  // TODO implement
  const dataset = gdal.open("example.tif")
  console.log("number of bands: " + dataset.bands.count())
  const response = {
    statusCode: 200,
    body: JSON.stringify(dataset.bands.count()),
  };
  return response;
};

And dockerfile is as below:

FROM node:18

WORKDIR /app
COPY ./index.mjs ./package.json ./package-lock.json ./example.tif ./
RUN npm install

COPY . .
CMD ["node", "index.mjs"]

I change the “async (event)” to “()” for local docker test, not complying with lambda’s event standards, it works well.
Then I change it back to “async (event)” to make it run in lambda and docker it, tag it and push it to the ecr, succceed. However, when I run the lambda based on the ecr image, throws
“{
“errorType”: “Runtime.ExitError”,
“errorMessage”: “RequestId: be5f8e0e-6c24-403e-99ed-cf474e9edef1 Error: Runtime exited without providing a reason”
}”
I have configured the memory to 1G and time limits to 1 min, it still fails after only 6 seconds.
Anyone have some idea about this?

How to change the navbar’s color on request?

I want to change the navbar color when my specific div is hitting the top of the page. It only does it on my second request and not on my first, even though the console says it is working.

I can’t find the reason it only works on the second ‘box’ of the forEach. Maybe it has something to do with that, but I also wrote it separately and it doesn’t work.

const boxes = document.querySelectorAll('.Boxes');
const navContainer = document.querySelector('.nav-container');
const navItems = document.querySelectorAll('.nav-item');
const lines = document.querySelectorAll('.line');

window.addEventListener('scroll', function() {
  boxes.forEach((box) => {
    let boxRect = box.getBoundingClientRect();

    if (boxRect.top <= 100 && boxRect.bottom >= 100) {
      navContainer.style.backgroundColor = "#6a994e";
      //console.log(navContainer.style.backgroundColor);
      navItems.forEach((item) => {
        item.style.color = "white";
      })
      lines.forEach((line) => {
        line.style.backgroundColor = "white";
      })
    } else {
      navContainer.style.backgroundColor = "white";
      navItems.forEach((item) => {
        item.style.color = "#6a994e";
      })
      lines.forEach((line) => {
        line.style.backgroundColor = "#6a994e";
      })
    }
  })
});
body{
    margin: 0;
    padding: 0;
    font-family: Arial;
    overflow-x: clip;
}

.nav-container{
    width: 100%;
    height: 75px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: 75px;
    padding: 10px 50px;
    background-color: white;
    color: black;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 5;
    transition: all 0.5s linear;
}



.menu-container{
    display: inline-grid;
    justify-items: end;
    align-items: center;
}

.icon{
    position: relative;
    width: 40px;
    height: 40px;
    border: none;
    background-color: transparent;
    z-index: 2;
}

.menu-container .icon .line{
    width: 80%;
    height: 2px;
    background-color: #6a994e;
    position: absolute;
    transition: transform 0.6s linear;
}

.menu-container .icon .line1{
    top: 15px;
    left: 5px;
}
.menu-container .icon .line2{
    bottom: 15px;
    left: 5px;
}

.boxes{
    background-color: #6a994e;
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    overflow-x: hidden;
    animation: theater;
    animation-timeline: view();
    
}


@keyframes theater{
    0%{
        transform: scale(1);
    } 50% {
        transform: scale(2);
    }
}
<nav>
        <div class="nav-container">
            <a href=""><i class="fa-solid fa-paw nav-item"></i></a>
            <h1 class="nav-item">LOGO</h1>
            <div class ="menu-container">
                <button class="icon" id="toggle">
                    <div class="line line1"></div>
                    <div class="line line2"></div>
                </button>
                <ul class="nav-list">
                    <li><a href="">Home</a></li>
                    <li><a href="">Gallerij</a></li>
                    <li><a href="">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

<section>
        <div class="boxes">
            <h1>text</h1>
        </div>
    </section>
  
  
<section>
        <div class="boxes">
            <h1>text</h1>
        </div>
    </section>

Page scroll is broken when dropdown is open

When I scroll the page, it works normally. But when I open the dropdown, I cannot seem to scroll, or it does “scroll” but it is very buggy, like it’s displayed in the gif in URL. I work in brite.js with .tmpl and .js files. I am also using 3rdparty files like select2.min.js and select2.min.css. When I go to devTools I see that this dropdown is not actually dropdown but unordered list.

Here is some of the code related to selecting that span:

$('#tags12').select2({
            tags: true,
            multiple: 'multiple',
            tokenSeparators: [], //Here we choose delimiters
            dropdownParent: $('#cat2'),
            data: d
          });

          $('.select2-container').addClass('tags-styling');
          $('.select2-selection').addClass('tags-styling');

          //When tag is selected, added new, pressed space or enter
          $('#tags12').on('select2:select', function (e) {
            var data = e.params.data;

            //ajax call to add tags to database
            $('#tags12').empty();
            $.ajax({
              method: 'POST',
              url: main.config.dataBase,
              data: {
                tag_name: data.text,
                user_id: sessionStorage.getItem('user_id'),
                action: 'addTags'
              }
            }).done(function (resp) {
              var json = JSON.parse(resp);

              var tagToDbObj = {
                catId: catalog_id,
                tagId: json.id,
                tagName: data.text,
                user_id: sessionStorage.getItem('user_id')
              };

              //Ajax call to add tag to catalog
              $.ajax({
                method: 'POST',
                url: main.config.dataBase,
                data: {
                  Object: tagToDbObj,
                  action: 'bondTagtoCat'
                }
              }).done(function () {
                utils.messeage('Tag added!', 'success');
                historyTable.draw();
              });

              //Checks if tag is already selected
              if ($('#' + json.id).length) {
                utils.messeage('Tag already chosen', 'danger');
              } else {
                //if not appends new tag
                $('.tags-container').append(
                  '<div title="' +
                    json.description +
                    '" id="' +
                    json.id +
                    '" class="tag col-xs-6" style="background-color:' +
                    json.color +
                    ';"><div name="deleteTag"><div class="tagText">' +
                    data.text +
                    '</div><i class="fas fa-times"></i></div></div>'
                );
                $('#tags12').empty();
              }

I have tried all sorts of combinations with css and in js files, but I cannot seem to find the fix. Any tip or help would be apriciated. Thank you.

What devTools selection is on the page

in DevTools

gif what the problem is

I expected that by adding overflows in .less and .css files, something would change, but it stayed the same.

Prevent Slick Slider Classes from Being Added to HTML After Content Edit and download html in jQuery

I’m working on edit content functionality with js where I’ve dynamically added contenteditable="true" to some HTML elements on click on “Edit text”. When i click on “save” after editing any content, I capture the updated content from the DOM and save it to a html file.

Here’s the relevant working HTML file with all neccessory css and js code:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="description" content="Extracted Page">
      <title>Home</title>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
         integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous">
      <style>
         .partner-block .partner-list {
         overflow: hidden;
         margin: 0;
         }
         .partner-block .partner-list li {
         float: left;
         margin: 0 auto;
         }
         .partner-block .partner-list li a:before {
         pointer-events: none;
         width: 0;
         height: 3px;
         z-index: 1;
         opacity: 0;
         visibility: hidden;
         }
         .partner-block .partner-list li a:hover:before {
         width: 100%;
         opacity: 1;
         visibility: visible;
         }
         .partner-block .partner-list .slick-arrow {
         position: absolute;
         display: -webkit-box;
         display: -ms-flexbox;
         display: flex;
         -webkit-box-align: center;
         -ms-flex-align: center;
         align-items: center;
         -webkit-box-pack: center;
         -ms-flex-pack: center;
         justify-content: center;
         color: var(--background-primary-color);
         border: 1px solid #e8e8e8;
         font-size: 14px;
         right: 17px;
         bottom: 100%;
         margin-bottom: 33px;
         width: 34px;
         height: 34px;
         }
         .partner-block .partner-list .slick-arrow.slick-disabled {
         pointer-events: none;
         color: var(--text-color-default);
         }
         .partner-block .partner-list .slick-arrow:hover {
         background-color: var(--secondary-border-color);
         color: var(--text-color-default);
         border-color: var(--secondary-border-color);
         }
         .partner-block .partner-list .slick-prev {
         margin-right: 41px;
         }
         [contenteditable="true"] :hover {
         border: 1px solid red;
         outline: none;
         }
      </style>
   </head>
   <body>
      <div class="editor-section">
         <button id="editText">Edit text</button>
         <button id="savePage">Save</button>
      </div>
      <div id="wrapper" class="editableSection">
         <div id="about-7" class="">
            <section class="partner-block">
               <div class="container">
                  <div class="row">
                     <header class="col-xs-12 popular-posts-head">
                        <h2 class="popular-head-heading">Trusted Partners</h2>
                     </header>
                  </div>
                  <div class="row">
                     <div class="col-xs-12 dynamic-slider-wrapper">
                        <ul class="list-unstyled partner-list">
                           <li>
                              <a href="#">
                                 <p>Test1</p>
                              </a>
                           </li>
                           <li>
                              <a href="#">
                                 <p>Test2</p>
                              </a>
                           </li>
                        </ul>
                     </div>
                  </div>
               </div>
            </section>
         </div>
      </div>
      <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
      <script>
         $(document).ready(function () {
           initSlickCarousel();
         
           // Function to enable content editing
           $('#editText').click(function () {
               $("body *").attr("contenteditable", "true");
         
           });
         
           // Function to save the edited content and generate a downloadable file
           $('#savePage').click(function () {
               $("body *").removeAttr("contenteditable");
         
               $(".editor-section").remove();
         
               // Generate the edited HTML content
               var htmlContent = $('html').html();
               var blob = new Blob([htmlContent], { type: 'text/html' });
               var url = URL.createObjectURL(blob);
               var a = document.createElement('a');
               a.href = url;
               a.download = 'edited_page.html';
               a.click();
               URL.revokeObjectURL(url); // Clean up the URL object
           });
         
           // slick init
           function initSlickCarousel() {
               "use strict";
               jQuery('.partner-list').slick({
                   slidesToScroll: 1,
                   rows: 0,
                   slidesToShow: 1,
                   prevArrow: '<a href="#" class="slick-prev fas fa-chevron-left"><span class="sr-only">Previous</span></a>',
                   nextArrow: '<a href="#" class="slick-next fas fa-chevron-right"><span class="sr-only">Next</span></a>',
                   infinite: false,
                   adaptiveHeight: true,
                   responsive: [{
                       breakpoint: 1025,
                       settings: {
                           slidesToShow: 5
                       }
                   }, {
                       breakpoint: 991,
                       settings: {
                           slidesToShow: 4
                       }
                   }, {
                       breakpoint: 577,
                       settings: {
                           slidesToShow: 3
                       }
                   }, {
                       breakpoint: 481,
                       settings: {
                           slidesToShow: 2
                       }
                   }]
               });
           }
         });
      </script>
   </body>
</html>

So after click on “edit” if we change any text on the page, for example “Test1” to “NewTest1” and saved the file then the text updates in the downloaded file but there’s an issue:when the HTML code of a slider loads, jQuery (jquery.min.js) is adding Slick slider classes (slick-slide, slick-initialized, etc.) to the content inside the ul with the class list-unstyled partner-list. the content inside class=”dynamic-slider-wrapper” looks something like this in the downloaded html file:

<div class="col-xs-12 dynamic-slider-wrapper">
   <ul class="list-unstyled partner-list slick-initialized slick-slider">
      <a href="#"
         class="slick-prev fas fa-chevron-left slick-arrow slick-disabled"
         aria-disabled="true" style=""><span class="sr-only">Previous</span></a>
      <div class="slick-list draggable" style="height: 30px;">
         <div class="slick-track"
            style="opacity: 1; width: 2280px; transform: translate3d(0px, 0px, 0px);">
            <li class="slick-slide slick-current slick-active" data-slick-index="0"
               aria-hidden="false" tabindex="0" style="width: 1140px;">
               <a href="#"
                  tabindex="0">
                  <p>NewTest1</p>
               </a>
            </li>
            <li class="slick-slide" data-slick-index="1" aria-hidden="true" tabindex="-1"
               style="width: 1140px;">
               <a href="#" tabindex="-1">
                  <p>Test2</p>
               </a>
            </li>
         </div>
      </div>
      <a href="#" class="slick-next fas fa-chevron-right slick-arrow" aria-disabled="false"
         style=""><span class="sr-only">Next</span></a>
   </ul>
</div>

So, how can we avoid the Slick slider classes in the downloaded HTML file while keeping the updated changes? I want to download the file with the original HTML code, including the updated content changes on save. For example, if we change ‘Test1’ to ‘NewTest1’, the output in the downloaded file should look like this:

<div class="col-xs-12 dynamic-slider-wrapper">
   <ul class="list-unstyled partner-list">
      <li>
         <a href="#">
            <p>NewTest1</p>
         </a>
      </li>
      <li>
         <a href="#">
            <p>Test2</p>
         </a>
      </li>
   </ul>
</div>

Svelte Maplibre Popup open issues

I am having a problem with a Popup opening on hovering over an area on a map

<script>
   let showPopup = false;

    const setPopup = (e: any) => {
       showPopup = true;
    }
 
</script>
<GeoJSON bind:data={info}>
  <Popup open={showPopup} lngLat={popupLngLat}>
    {#if popupData}
      <p class="govuk-body-s popup">
        {popupData}
      </p>
    {/if}
  </Popup>
</GeoJson>

I have tried adding an openOn='manual' option to the pop but that doesn’t seem to help. The popup only opens when the area is clicked on instead of when hovered over.

I’m using Svelte 4 and svelte-maplibre: 0.9.8

Selenium 4 (Node.js): How to Capture Network Requests? (getDevTools, createCDPConnection)

Selenium 4 (Node.js) – TypeError: driver.manage(…).getDevTools is not a function

I’m trying to capture network requests and responses in Selenium 4 using Node.js and Chrome. I’m encountering the error: TypeError: driver.manage(...).getDevTools is not a function.

My environment details:

  • Selenium WebDriver: 4.28.1
  • ChromeDriver: 133.0.0
  • Chrome: 133.0.6943.60

Here’s my code:

const { Builder, Browser, Capabilities } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

async function captureNetworkRequests() {
    const capabilities = new Capabilities();
    capabilities.set('goog:chromeOptions', {
        'args': [
            // other chrome options if needed
        ]
    });

    const driver = await new Builder()
        .withCapabilities(capabilities)
        .forBrowser(Browser.CHROME)
        .build();

    const devTools = await driver.manage().getDevTools(); // Error occurs here

    await devTools.send('Network.enable', {});

    devTools.on('Network.requestWillBeSent', (event) => {
        const request = event.request;
        console.log('Request URL:', request.url);
    });

    devTools.on('Network.responseReceived', async (event) => {
        const response = event.response;
        const requestId = event.requestId;
        const url = response.url;
        const status = response.status;

        if (url.includes('ws_api.php?')) {
            console.log(`${status} ${url}`);
            try {
                const responseBody = await devTools.send('Network.getResponseBody', { requestId });
                console.error(responseBody.body);

                const assert = require('assert');
                assert.strictEqual(status, 200, `Expected status 200 for ${url}, but got ${status}`);

            } catch (error) {
                console.error("Error getting response body:", error);
            }
        }
    });

    try {
        await driver.get('[https://weatherstack.com/](https://weatherstack.com/)');
        await new Promise(resolve => setTimeout(resolve, 10000));

    } finally {
        await driver.quit();
        await devTools.close();
    }
}

captureNetworkRequests();

I’m trying to use Chrome DevTools (via driver.manage().getDevTools()) to capture network requests/responses in Selenium 4 with Node.js. However, I’m encountering errors, and createCDPConnection is also not working. I cannot use driver.executeScript due to CSRF vulnerabilities. A working example or help with DevTools/CDP configuration would be very helpful.

group-hover does not work when hover is manually added with JS

I’m attempting to have the nav anchor tag go in the hover state based on the user’s section in the viewport. The Tailwind CSS is working when I manually hover over these nav items but does not work when I add the hover class using Javascript.

I looked into variants but from the docs this should be supported out of the box.

I also added this into my style sheet and again it only changes the background color to red when I manually hover over the element, not when the hover class is added with JS

      .nav-indicator:hover {
         background-color: red;
      }

Is there a way to add the hover force element state with Tailwind?

<li>
   <a id="about" class="nav-indicator group" href="#about-screen" data-ref="about-screen">
   <span class="group-hover:w-16 group-hover:bg-red-200 group-focus-visible:w-16 group-focus-visible:bg-red-200"></span>
   <span class="group-hover:text-red-200 group-focus-visible:text-red-200">About</span></a>
</li>

Here is the whole tailwind code: https://play.tailwindcss.com/rzNXqvfcln?layout=horizontal

Below is my JS that currently correctly adds the hover class depending on the viewport:

  const sections = document.querySelectorAll('section');
  const config = {
    rootMargin: '-50px 0px -55%'
  };

  let observer = new IntersectionObserver(function (entries, self) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        intersectionHandler(entry); 
      }
    });
  }, config);

  sections.forEach(section => {
    observer.observe(section);
  });

  function intersectionHandler(entry) {
    const id = entry.target.id;

    const currentlyActive = document.querySelector('nav ul li a');
    const shouldBeActive = document.querySelector('nav ul li a[data-ref=' + id + ']');

    if (currentlyActive) {
      currentlyActive.classList.remove('hover');
      // console.log("removed");
      // console.log(currentlyActive);

    }
    if (shouldBeActive) {
      shouldBeActive.classList.add('hover');
      console.log("added");
      console.log(shouldBeActive);

    }
  }

Pixel image blurs on rotation, JS Canvas

When drawing an image with rotation on a JS canvas the image is blurring. See attached images.

Blurred, with rotation:
blurred

No blur, not rotated:
not blurred

I have set imageSmoothingEnabled to false and image-rendering to pixelated.

Render code:

fg.save();
fg.translate(gun.x - gun.frame.w / 2, gun.y - gun.frame.h / 2);
fg.rotate(gun.a);
if(mouse.x < (player.x + player.width / 2)) {
    fg.scale(1, -1);
}
fg.drawImage(spriteSheet, gun.frame.x, gun.frame.y, gun.frame.w, gun.frame.h, 0, 0, gun.frame.w, gun.frame.h);
fg.restore();

Please no answers saying it isn’t possible. It would be much more helpful having an alternative rendering method suggested.

Javascript puppeteer code works in debug mode, but not when running using node js

const puppeteer = require('puppeteer');

(async () => {
  // Launch a new browser instance
  const browser = await puppeteer.launch({ headless: false }); // Set headless to false to see the browser
  const page = await browser.newPage();
  
  // URL of the page to load
  const url = 'https://www.bestbuy.com/site/xfx-mercury-amd-radeon-rx-7900-xtx-magnetic-air-24gb-gddr6-pci-express-4-0-gaming-graphics-card-black-red/6588232.p?skuId=6588232';

  // Open the page
  await page.goto(url, { waitUntil: 'domcontentloaded' });

  // Define the selector for the button you are looking for
  const buttonSelector = '.c-button.c-button-primary.c-button-lg.c-button-block.c-button-icon.c-button-icon-leading.add-to-cart-button '; // Replace with your button's selector
  
  // Wait for the button to appear or reload the page
  while (true) {
    try {
      // Try to find the button
      await page.waitForSelector(buttonSelector, { visible: true, timeout: 50000 });
      console.log('Button found!');
      break; // Exit the loop once the button is found
    } catch (error) {
      console.log('Button not found, reloading the page...');
      
      // Reload the page if the button is not found
      await page.reload({ waitUntil: 'domcontentloaded' });
    }
  }
  
  // Close the browser
  await browser.close();
})();

I am trying to reload a webpage until a button is found present on the screen. This code works fine when in debug mode on vscode, but when I try running it using node js it gives me an error.

This is the output when running in node js, the first being my program console output which is expected, but then also a thrown error.

$ node test.js Button not found, reloading the page...
C:UsersstudentDesktopBestBuyTrackerBestBuyTrackernode_modulespuppeteer-corelibcjspuppeteercdpCDPSession.js:67return Promise.reject(new Errors_js_1.TargetCloseError(Protocol error (${method}): Session closed. Most likely the ${this.#targetType} has been closed.));^ TargetCloseError: Protocol error (Page.reload): Session closed. Most likely the page has been closed.at CdpCDPSession.send (C:UsersstudentDesktopBestBuyTrackerBestBuyTrackernode_modulespuppeteer-corelibcjspuppeteercdpCDPSession.js:67:35) at CdpPage.reload (C:UsersstudentDesktopBestBuyTrackerBestBuyTrackernode_modulespuppeteer-coreli bcjspuppeteercdpPage.js:667:39) at C:UsersstudentDesktopBestBuyTrackerBestBuyTrackertest.js:28:18 at process.processTicksAndRejections (node:internal/process/task_queues:105:5)  Node.js v22.13.1

Race Condition in Strapi Prevents Relation Field from Being Filled in User Cart

I am working on an e-shop using Strapi as the backend and Next.js as the frontend. I encountered an issue where, if multiple users add products to their basket simultaneously (simulated using two different browsers), a race condition occurs. The user who loses the race ends up with an empty basket.

Current Implementation:

  1. Fetching Products:
    I retrieve the product collection from Strapi to display all products on the webpage:

    {
      "kind": "collectionType",
      "collectionName": "products",
      "info": {
        "singularName": "product",
        "pluralName": "products",
        "displayName": "Product"
      },
      "attributes": {
        "title": { "type": "string", "required": true },
        "price": { "type": "decimal", "required": true },
        "user_cart": { "type": "relation", "relation": "manyToOne", "target": "api::user-cart.user-cart", "inversedBy": "product" }
      }
    }
    
  2. Adding Product to User Cart:

    {
      "kind": "collectionType",
      "collectionName": "user_carts",
      "info": {
        "singularName": "user-cart",
        "pluralName": "user-carts",
        "displayName": "User Cart"
      },
      "attributes": {
        "product": { "type": "relation", "relation": "oneToMany", "target": "api::product.product", "mappedBy": "user_cart" }
      }
    }
    

Problem:

When I check the user who lost the race, their product array is empty, while the winning user gets the relation data correctly.

Why am I not receiving the related product information (e.g., product title) for the losing user?