Check if a DOM Element is ; why can’t I use instanceof HTMLNoScriptElement?

I need to process the DOM children of a container element (to achieve some fancy layout magic) and leave non-rendered elements alone.

I was surprised to find that I can’t use an instanceof HTMLNoScriptElement check for <noscript> elements; which was my go-to solution for <style>, <script>, etc.

const shouldIgnoreElement = (element: Element) =>
  element instanceof HTMLStyleElement ||
  element instanceof HTMLScriptElement ||
  element instanceof HTMLDialogElement ||
  element instanceof HTMLTemplateElement ||
  element.tagName === 'NOSCRIPT'

const shouldProcessElement = (element: Element) => !shouldIgnoreElement(element)
[...root.children].filter(shouldProcessElement).forEach(...)

As you can see I ended up using element.tagName === 'NOSCRIPT' for the check. But I still want to get a deeper understanding of this curious situation. And wonder whether I did something wrong or harbor a misunderstanding.

My research on mdn turned up:

So it seems there simply is no class to represent <noscript> elements.

Why is there no corresponding class?

Is noscript the only HTML element type with this curious gap in the Web API?

AWS elemental media convert service audio and subtitle track missing

async createVideoJob(
    movieId: string,
    mainVideoPath: string,  // HLS Video Input
    audioPaths: any[] = [],
    subtitlePaths: any[] = [],
    outputFileName: string,
    resolution: any
  ): Promise<string> {
    // Verify main video file exists.
    const videoExists = await this.checkFileExists(awsDetail.bucket, mainVideoPath);
    if (!videoExists) throw new Error(`Main video file does not exist: ${mainVideoPath}`);
  
    // Verify audio files.
    for (const audioPath of audioPaths) {
      const audioExists = await this.checkFileExists(awsDetail.bucket, audioPath.file);
      if (!audioExists) throw new Error(`Audio file does not exist: ${audioPath.file}`);
    }
  
    // Verify caption files.
    for (const subtitlePath of subtitlePaths) {
      const captionExists = await this.checkFileExists(awsDetail.bucket, subtitlePath.file);
      if (!captionExists) throw new Error(`Caption file does not exist: ${subtitlePath.file}`);
    }
  
    const outputBasePath = `MOVIEZU/PROCESSED/${outputFileName}`;
    const hlsDestination = `s3://${awsDetail.bucket}/${outputBasePath}/HLS/`;
  
    const { width, height } = resolution;
    const aspectRatio = width / height;
    const presets = [
      { height: 2160, name: "4K", bitrate: 12000000 },
      { height: 1440, name: "2K", bitrate: 8000000 },
      { height: 1080, name: "1080p", bitrate: 6000000 },
      { height: 720, name: "720p", bitrate: 4000000 },
      { height: 480, name: "480p", bitrate: 2500000 },
      { height: 360, name: "360p", bitrate: 1500000 },
      { height: 240, name: "240p", bitrate: 1000000 },
      { height: 144, name: "144p", bitrate: 500000 },
    ].filter(preset => preset.height <= height);
    const resolutions = presets.map(preset => {
      let computedWidth = Math.floor(preset.height * aspectRatio);
      if (computedWidth % 2 !== 0) computedWidth--;
      return { width: computedWidth, height: preset.height, name: preset.name, bitrate: preset.bitrate };
    });
  
    // ---- Audio Setup ----
    const audioSelectors: Record<string, any> = {
      "Audio Selector 1": { DefaultSelection: "DEFAULT" },
    };
    const hlsAudioDescriptions: any[] = [
      {
        AudioSourceName: "Audio Selector 1",
        CodecSettings: {
          Codec: "AAC",
          AacSettings: { Bitrate: 96000, CodingMode: "CODING_MODE_2_0", SampleRate: 48000 },
        },
        StreamName: "Original Audio",
        AudioGroupId: "program_audio",
        LanguageCode: "ENG",
      },
    ];
    let audioInputIndex = 2;
    for (const audioPath of audioPaths) {
      const selectorName = `Audio Selector ${audioInputIndex}`;
      audioSelectors[selectorName] = {
        ExternalAudioFileInput: `s3://${awsDetail.bucket}/${audioPath.file}`,
      };
      hlsAudioDescriptions.push({
        AudioSourceName: selectorName,
        CodecSettings: {
          Codec: "AAC",
          AacSettings: { Bitrate: 96000, CodingMode: "CODING_MODE_2_0", SampleRate: 48000 },
        },
        StreamName: audioPath.name || `Audio ${audioInputIndex}`,
        AudioGroupId: "program_audio",
        LanguageCode: audioPath.language || "ENG",
      });
      audioInputIndex++;
    }
  
    // ---- Video Outputs with Embedded Captions ----
    // Each output rendition includes a CaptionDescription referencing a CaptionSelector defined in Inputs.
    const videoOutputs = resolutions.map(res => ({
      VideoDescription: {
        Width: res.width,
        Height: res.height,
        CodecSettings: {
          Codec: "H_264",
          H264Settings: {
            RateControlMode: "QVBR",
            QualityTuningLevel: "SINGLE_PASS_HQ",
            QvbrSettings: { QvbrQualityLevel: 7 },
            MaxBitrate: res.bitrate,
          },
        },
      },
      AudioDescriptions: hlsAudioDescriptions,
      CaptionDescriptions: subtitlePaths.length
        ? subtitlePaths.map((subtitle, idx) => ({
            // Must match the CaptionSelector name defined in Inputs.
            CaptionSelectorName: `Caption Selector ${idx + 1}`,
            DestinationSettings: {
              // Use EMBEDDED so that captions appear as selectable tracks.
              DestinationType: "EMBEDDED"
            },
            LanguageCode: subtitle.language || "ENG",
            LanguageDescription: subtitle.name || "English",
          }))
        : undefined,
      ContainerSettings: { Container: "M3U8" },
      NameModifier: `/${res.name}`,
    }));
  
    // ---- Job Settings ----
    // Include CaptionSelectors in Inputs so that embedded captions can be processed.
    const jobSettings: JobSettings | any = {
      Inputs: [
        {
          FileInput: `s3://${awsDetail.bucket}/${mainVideoPath}`,
          AudioSelectors: audioSelectors,
          CaptionSelectors: subtitlePaths.length
            ? Object.fromEntries(
                subtitlePaths.map((subtitle, idx) => [
                  `Caption Selector ${idx + 1}`,
                  {
                    // For selectable (embedded) captions, use a supported SourceType (EIA608).
                    SourceSettings: {
                      SourceType: "EIA608",
                      FileSourceSettings: {
                        SourceFile: `s3://${awsDetail.bucket}/${subtitle.file}`,
                      },
                    },
                  },
                ])
              )
            : {},
        },
      ],
      OutputGroups: [
        {
          Name: "HLS Output Group",
          OutputGroupSettings: {
            Type: "HLS_GROUP_SETTINGS",
            HlsGroupSettings: {
              Destination: hlsDestination,
              SegmentLength: 6,
              MinSegmentLength: 6,
              OutputSelection: "MANIFESTS_AND_SEGMENTS",
              AudioGroupId: "program_audio",
              AudioRenditionSets: "program_audio",
              // Enable insertion of closed-caption manifest tags.
              CaptionLanguageSetting: "INSERT",
              // Provide caption language mappings for each caption selector.
              CaptionLanguageMappings: subtitlePaths.length
                ? subtitlePaths.map((subtitle, idx) => ({
                    CaptionSelectorName: `Caption Selector ${idx + 1}`,
                    CustomLanguageCode: subtitle.language || "ENG",
                    LanguageDescription: subtitle.name || "English"
                  }))
                : [],
            } as any,
          },
          Outputs: videoOutputs,
        } as any,
      ],
      TimecodeConfig: { Source: "ZEROBASED" },
    };
  
    const command = new CreateJobCommand({
      Role: awsDetail.mediaConvertRoleArn,
      Settings: jobSettings,
      AccelerationSettings: { Mode: "DISABLED" },
      StatusUpdateInterval: "SECONDS_60",
    });
  
    const movieName = mainVideoPath.split("/").pop()?.replace(/.w+$/, "") || "movie";
    const path = `${outputBasePath}/HLS/${movieName}.m3u8`;
  
    try {
      const data = await this.mediaConvertClient.send(command);
      await MovieZu.findOneAndUpdate(
        { _id: movieId },
        { jobId: data.Job.Id, processedVideoUrl: path },
        { new: true }
      );
      return `${outputBasePath}/`;
    } catch (error) {
      console.error("MediaConvertService error:", error);
      throw new Error("Failed to create video job");
    }
  }

audio and subtitle track are missing on master.m3u8, only HLS video quality track.
Track missing

m3u8 response data

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=6908373,AVERAGE-BANDWIDTH=2249342,CODECS="avc1.640028",RESOLUTION=1920x1080,FRAME-RATE=24.000
Fateh.2025.1080p.JHS.WEB.DL.Hindi.DDPA5.1.ESub.x264-Vegamovies.is/1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=4868448,AVERAGE-BANDWIDTH=1105432,CODECS="avc1.64001f",RESOLUTION=1280x720,FRAME-RATE=24.000
Fateh.2025.1080p.JHS.WEB.DL.Hindi.DDPA5.1.ESub.x264-Vegamovies.is/720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3016272,AVERAGE-BANDWIDTH=665885,CODECS="avc1.64001e",RESOLUTION=852x480,FRAME-RATE=24.000
Fateh.2025.1080p.JHS.WEB.DL.Hindi.DDPA5.1.ESub.x264-Vegamovies.is/480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1825354,AVERAGE-BANDWIDTH=415826,CODECS="avc1.64001e",RESOLUTION=640x360,FRAME-RATE=24.000
Fateh.2025.1080p.JHS.WEB.DL.Hindi.DDPA5.1.ESub.x264-Vegamovies.is/360p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1116720,AVERAGE-BANDWIDTH=254112,CODECS="avc1.640015",RESOLUTION=426x240,FRAME-RATE=24.000
Fateh.2025.1080p.JHS.WEB.DL.Hindi.DDPA5.1.ESub.x264-Vegamovies.is/240p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=506848,AVERAGE-BANDWIDTH=130283,CODECS="avc1.64000c",RESOLUTION=256x144,FRAME-RATE=24.000
Fateh.2025.1080p.JHS.WEB.DL.Hindi.DDPA5.1.ESub.x264-Vegamovies.is/144p.m3u8

When working with AWS Elemental MediaConvert to transcode media files using Node.js, a common issue developers face is that audio tracks or subtitle tracks are missing in the output files. This note aims to explain why this happens and how to properly configure your Node.js MediaConvert job to include audio and subtitle tracks.

When in development mode, unable to GET bundle.js file, fails with 404 Not Found

While trying to run the application locally, browser is not able to load bundle.js
enter image description here

This is the setup to load up bundle.js inside index.html

<script type="text/javascript" src="/static/js/bundle.js"></script>

But when hitting directly to this request URL: http://localhost:3000/static/js/bundle.js, bundled js code is visible
enter image description here

If webpack failed to generate the bundle.js file then this should also fail I assume. I can also see this assets report
enter image description here

Below is my output config inside webpack.config

 output: {
    pathinfo: true,
    filename: 'static/js/bundle.js',
    chunkFilename: 'static/js/[name].chunk.js',
    publicPath: "/",
    devtoolModuleFilenameTemplate: (info) => path.resolve(info.absoluteResourcePath).replace(/\/g, '/'),
  },

This is how I server static files using Express

  app.use(favicon(path.join(__dirname, '../build', 'favicon.ico')));
  app.use('/static', express.static(path.join(__dirname, '../build/static/'), { maxAge: '30d' }));

My build folder structure is:

-build
--static
---css
----main.123sf.css
---js
----main.123124.js
----main.123124.js.LICENSE.txt
---media
----mygif.gif
--favicon.ico
--index.html
--login.html

When in development mode, I believe if everything goes well bundle.js can be located at below structure inside Sources.

-top
--localhost:3000
---static/js
----bundle.js

this are the package versions I am using currently using

"express": "^4.21.2",
"webpack": "^5.96.1",
"webpack-dev-server": "^4.15.2",

what am I doing wrong here? Any help is appreciated, thanks in advance.

How to implemet slide search with Ivory Search in WordPress?

I am using the Ivory Search plugin on my WordPress site, and I would like to implement a “slide search” feature.

Currently, the whole search form is showing (search bar and search icon). I want the search icon to be visible only at first. When the user clicks the search icon, I want the search bar to appear by sliding out to the left (as the search icon is placed to the right). I also want to make sure that when the user first clicks the search icon, it shows the search bar and doesn’t toggle the search functionality (I want it to search a term on second click).

I haven’t written any custom code yet, but I am open to using JavaScript, CSS, or PHP if necessary. Could someone guide me on how to achieve this?

<div class="ast-search-menu-icon slide-search">
        <form class="is-search-form is-form-style is-form-style-3 is-form-id-9231 " action="https://embroidla.com/" method="get" role="search"><label for="is-search-input-9231"><span class="is-screen-reader-text">Search for:</span><input type="search" id="is-search-input-9231" name="s" value="" class="is-search-input" placeholder="Search..." autocomplete="off"></label><button type="submit" class="is-search-submit"><span class="is-screen-reader-text">Search Button</span><span class="is-search-icon"><svg focusable="false" aria-label="Search" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></svg></span></button></form>         <div class="ast-search-icon">
                <a class="slide-search astra-search-icon" aria-label="Search icon link" href="#">
                    <span class="screen-reader-text">Search</span>
                    <span class="ast-icon icon-search"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="-893 477 142 142" enable-background="new -888 480 142 142" xml:space="preserve">
                          <path d="M-787.4,568.7h-6.3l-2.4-2.4c7.9-8.7,12.6-20.5,12.6-33.1c0-28.4-22.9-51.3-51.3-51.3  c-28.4,0-51.3,22.9-51.3,51.3c0,28.4,22.9,51.3,51.3,51.3c12.6,0,24.4-4.7,33.1-12.6l2.4,2.4v6.3l39.4,39.4l11.8-11.8L-787.4,568.7  L-787.4,568.7z M-834.7,568.7c-19.7,0-35.5-15.8-35.5-35.5c0-19.7,15.8-35.5,35.5-35.5c19.7,0,35.5,15.8,35.5,35.5  C-799.3,553-815,568.7-834.7,568.7L-834.7,568.7z"></path>
                          </svg></span>             </a>
            </div>
        </div>

Rollup Package Error: TypeError: Unable to determine current node version

I have built an npm package using Rollup, but after publishing and installing it in another project, I get the following error when running the project:

TypeError: Unable to determine current node version

My Rollup Configuration:
Here is my rollup.config.js:

import babel from "@rollup/plugin-babel";
import commonjs from "@rollup/plugin-commonjs";
import json from "@rollup/plugin-json";
import resolve from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import url from "@rollup/plugin-url";
import svgr from "@svgr/rollup";
import jsx from "acorn-jsx";
import dts from "rollup-plugin-dts";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import { terser } from "rollup-plugin-terser";
import { visualizer } from "rollup-plugin-visualizer";

const packageJson = require("./package.json");

export default [
  {
    input: packageJson.source,
    output: [
      {
        file: packageJson.main,
        format: "cjs",
        exports: "named",
        inlineDynamicImports: true,
      },
      {
        file: packageJson.module,
        format: "esm",
        inlineDynamicImports: true,
      },
    ],
    acornInjectPlugins: [jsx()],
    plugins: [
      peerDepsExternal(),
      json(),
      url({
        include: ["**/*.svg", "**/*.png"],
        limit: 8192,
        emitFiles: true,
        fileName: "[dirname][hash][extname]",
      }),
      svgr(),
      resolve({
        extensions: [".js", ".jsx", ".ts", ".tsx"],
        mainFields: ["module", "main"],
        preferBuiltins: false,
        browser: true,
      }),
      babel({
        exclude: "node_modules/**",
        babelHelpers: "runtime",
        extensions: [".js", ".ts", ".jsx", ".tsx"],
        presets: ["@babel/preset-react", "@babel/preset-typescript"],
        plugins: ["@babel/plugin-transform-runtime"],
      }),
      commonjs({
        include: "node_modules/**",
        exclude: [
          "node_modules/process-es6/**",
          "node_modules/@mui/**",
          "node_modules/three/**",
        ],
      }),
      typescript({
        tsconfig: "./tsconfig.json",
        exclude: ["**/*.stories.tsx", "**/*.test.tsx"],
      }),
      postcss({
        extract: true,
        minimize: true,
        modules: true,
        plugins: [require("cssnano")], // Add CSS minification
      }),
      terser({
        format: {
          comments: false,
        },
        compress: {
          drop_console: true,
          ecma: 2015,
        },
      }),
      visualizer({
        filename: "bundle-analysis.html",
        open: true,
      }),
    ],
    external: [
      /^react($|/)/,
      /^react-dom($|/)/,
      /^three($|/)/,
      /^@mui/.*/,
      /^@react-three/.*/,
      "axios",
      "jszip",
      "i18next",
      "react-i18next",
      "lucide-react",
      "moment",
      "process",
    ],
  },
  {
    input: "build/types/index.d.ts",
    output: [{ file: "build/index.d.ts", format: "esm" }],
    plugins: [dts.default()],
    external: [/.css$/, /.scss$/],
  },
];

Package.json
My package.json includes:

{
  "name": "@solarhub-3d-viewer",
  "version": "0.0.10",
  "main": "build/index.js",
  "module": "build/index.es.js",
  "types": "dist/index.d.ts",
  "source": "index.ts",
  "dependencies": {
    "@babel/preset-flow": "^7.25.9",
    "@cometchat-pro/chat": "^3.0.6",
    "@emotion/react": "^11.10.0",
    "@emotion/styled": "^11.10.0",
    "@mui/icons-material": "^5.5.1",
    "@mui/material": "^5.14.17",
    "@mui/styles": "^5.5.3",
    "@mui/types": "^7.1.3",
    "@react-google-maps/api": "^2.19.2",
    "@react-oauth/google": "^0.10.0",
    "@react-pdf/renderer": "^3.4.4",
    "@react-three/drei": "^9.109.5",
    "@react-three/fiber": "^8.17.5",
    "@rollup/plugin-babel": "^6.0.4",
    "@sentry/react": "^7.27.0",
    "@sentry/tracing": "^7.27.0",
    "@stripe/react-stripe-js": "^1.7.0",
    "@stripe/stripe-js": "^1.24.0",
    "@testing-library/jest-dom": "^5.16.2",
    "@testing-library/react": "^12.1.4",
    "@testing-library/user-event": "^13.5.0",
    "@turf/turf": "^6.5.0",
    "@types/antd": "^1.0.0",
    "@types/axios": "^0.14.0",
    "@types/jest": "^27.4.1",
    "@types/mapbox__mapbox-gl-geocoder": "^4.7.2",
    "@types/mixpanel-browser": "^2.38.0",
    "@types/node": "^16.11.26",
    "@types/react-dom": "^17.0.13",
    "@types/react-dropzone": "^5.1.0",
    "@types/react-share": "^4.0.0",
    "@types/styled-components": "^5.1.24",
    "@types/uuid": "^8.3.4",
    "antd": "^4.19.2",
    "apexcharts": "^3.36.0",
    "axios": "^0.26.1",
    "buffer": "^6.0.3",
    "chart.js": "^3.9.1",
    "dateformat": "^4.6.3",
    "earcut": "^2.2.4",
    "emoji-mart": "^3.0.1",
    "env-cmd": "^10.1.0",
    "firebase": "^8.4.2",
    "firebase-admin": "^10.0.0",
    "geofire-common": "^5.2.0",
    "geotiff": "^2.1.3",
    "geotiff-geokeys-to-proj4": "^2024.4.13",
    "html-react-parser": "^1.4.5",
    "html-to-image": "^1.11.11",
    "html2canvas": "^1.4.1",
    "http": "0.0.1-security",
    "https": "^1.0.0",
    "https-browserify": "^1.0.0",
    "i": "^0.3.7",
    "i18next": "^21.8.16",
    "install": "^0.13.0",
    "jodit-react": "^4.1.2",
    "jszip": "^3.10.1",
    "jwt-decode": "^4.0.0",
    "load-bmfont": "^1.4.1",
    "lodash": "^4.17.21",
    "lucide-react": "^0.469.0",
    "mapbox-gl": "^2.7.1",
    "mixpanel-browser": "^2.45.0",
    "ndarray": "^1.0.19",
    "ndarray-gemm": "^1.0.0",
    "npm": "^8.7.0",
    "pdf-lib": "^1.17.1",
    "plotty": "^0.4.9",
    "proj4": "^2.11.0",
    "prop-types": "^15.8.1",
    "querystring": "^0.2.1",
    "react": "^18.3.1",
    "react-3d-viewer": "^1.0.12",
    "react-apexcharts": "^1.4.0",
    "react-app-rewired": "^2.2.1",
    "react-calendly": "^2.2.2",
    "react-chartjs-2": "^4.3.1",
    "react-colorful": "^5.6.1",
    "react-dom": "^18.3.1",
    "react-draggable": "^4.4.6",
    "react-dropzone": "^14.2.2",
    "react-full-screen": "^1.1.1",
    "react-html-parser": "^2.0.2",
    "react-i18next": "^11.18.6",
    "react-image-gallery": "^1.2.7",
    "react-map-gl": "^6.1.16",
    "react-map-gl-geocoder": "^2.1.7",
    "react-mapbox-gl-geocoder": "^1.1.0",
    "react-multi-date-picker": "^3.3.0",
    "react-pdf": "^9.1.0",
    "react-query": "^3.34.16",
    "react-quick-pinch-zoom": "^4.9.0",
    "react-redux": "^7.2.6",
    "react-router": "^6.18.0",
    "react-router-dom": "^6.2.2",
    "react-scripts": "^5.0.0",
    "react-share": "^4.4.0",
    "react-signature-canvas": "^1.0.6",
    "react-slick": "^0.28.1",
    "react-spinners": "^0.11.0",
    "react-timezone-select": "^1.2.0",
    "react-to-print": "^2.15.1",
    "react-toastify": "^8.2.0",
    "redux": "^4.1.2",
    "redux-saga": "^1.1.3",
    "redux-thunk": "^2.4.1",
    "reselect": "^4.1.8",
    "rollup-plugin-copy": "^3.5.0",
    "rollup-plugin-dts": "^6.1.1",
    "slick-carousel": "^1.8.1",
    "stream-http": "^3.2.0",
    "suncalc": "^1.9.0",
    "swiper": "^6.8.4",
    "three": "^0.167.1",
    "three-bmfont-text": "^3.0.1",
    "twemoji": "^13.1.0",
    "url": "^0.11.0",
    "uuid": "^8.3.2",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "env-cmd -f .env.stage react-app-rewired start",
    "prebuild": "tsc --noEmit",
    "build": "env-cmd -f .env.stage react-app-rewired build",
    "deploy": "firebase deploy --only hosting:solarhub-redesign",
    "start:prod": "env-cmd -f .env.prod react-app-rewired start",
    "prebuild:prod": "tsc --noEmit",
    "build:prod": "env-cmd -f .env.prod react-app-rewired build",
    "predeploy:prod": "npm run build:prod",
    "deploy:prod": "firebase deploy --only hosting:solarhub-44450",
    "lint": "eslint src/**/*.{js,jsx,ts,tsx,json}",
    "lint:fix": "eslint --fix 'src/**/*.{js,jsx,ts,tsx,json}'",
    "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc",
    "rollup": "rollup -c --bundleConfigAsCjs"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/plugin-transform-runtime": "^7.26.9",
    "@babel/preset-react": "^7.26.3",
    "@babel/runtime": "^7.26.9",
    "@rollup/plugin-commonjs": "^28.0.2",
    "@rollup/plugin-json": "^6.1.0",
    "@rollup/plugin-node-resolve": "^16.0.0",
    "@rollup/plugin-typescript": "^12.1.2",
    "@rollup/plugin-url": "^8.0.2",
    "@svgr/rollup": "^8.1.0",
    "@types/earcut": "^2.1.4",
    "@types/lodash": "^4.14.182",
    "@types/mapbox-gl": "^2.6.3",
    "@types/ndarray": "^1.0.11",
    "@types/proj4": "^2.5.5",
    "@types/react": "^17.0.19",
    "@types/react-html-parser": "^2.0.2",
    "@types/react-signature-canvas": "^1.0.5",
    "@types/react-slick": "^0.23.8",
    "@types/suncalc": "^1.9.2",
    "@types/three": "^0.158.3",
    "@typescript-eslint/eslint-plugin": "^5.47.1",
    "ajv": "^7.2.4",
    "autoprefixer": "^10.4.2",
    "cssnano": "^7.0.6",
    "eslint": "^8.31.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-config-standard-with-typescript": "^24.0.0",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-import-resolver-typescript": "^3.5.2",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-n": "^15.6.0",
    "eslint-plugin-only-warn": "^1.1.0",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-promise": "^6.1.1",
    "eslint-plugin-react": "^7.31.11",
    "eslint-plugin-react-hooks": "^4.6.0",
    "i18next-scanner": "^4.3.0",
    "postcss": "^8.4.8",
    "prettier": "^2.8.1",
    "process": "^0.11.10",
    "readline-sync": "^1.4.10",
    "rollup": "^4.34.9",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "rollup-plugin-postcss": "^4.0.2",
    "rollup-plugin-terser": "^7.0.2",
    "rollup-plugin-visualizer": "^5.14.0",
    "styled-components": "^5.3.3",
    "tailwindcss": "^3.0.23",
    "ts-node": "^10.9.2",
    "typescript": "^5.8.2"
  }
}

My config.overrides.js:

const webpack = require("webpack");

module.exports = function override(config, env) {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    http: require.resolve("stream-http"),
    https: require.resolve("https-browserify"),
    buffer: require.resolve("buffer"),
    assert: require.resolve("assert/"),
    tty: require.resolve("tty-browserify"),
    util: require.resolve("util/"),
    os: require.resolve("os-browserify/browser"),
    path: require.resolve("path-browserify"),
    "process": require.resolve("process/browser"),
    fs: false, // fs is not available in browsers
    module: false, // module should not be included
  };
  config.resolve.extensions = [...config.resolve.extensions, ".ts", ".js"];
  config.plugins = [
    ...config.plugins,
    new webpack.ProvidePlugin({
      process: "process/browser",
      Buffer: ["buffer", "Buffer"],
    }),
  ];
  config.module.rules.push({
    test: /.(js|mjs|jsx)$/,
    enforce: "pre",
    loader: require.resolve("source-map-loader"),
    resolve: {
      fullySpecified: false,
    },
  });

  return config;
};

What I Have Tried:

  • Ensured the package.json correctly specifies source, main, and
    module.
  • Checked if babelHelpers: “runtime” is correctly configured.
  • Added preferBuiltins: false in @rollup/plugin-node-resolve.
  • Verified that external dependencies are properly marked in external.

Additional Info:

  • Node.js Version: v16.14.0
  • Project Type: React + TypeScript
  • Error Appears When: Running the installed package inside another project

Question:

What could be causing this error, and how can I fix it? Any help would be greatly appreciated! Let me know if you have any questions!

amCharts4 – How to stretch the visible data range to see last value of a DateAxisRangeSelector?

I have an XYChart developed with amCharts4 in Javascript. I have a DateAxis on the x-axis and a ValueAxis on the y-axis. To control the visible data range, I use a DateAxisRangeSelector and an XYChartScrollbar. When I select two dates, my chart displays data from the first date at 00:00:00 to the second date at 00:00:00. As a result, I can’t see the data corresponding to the last date.

Is there any way of stretching the visible data range to see the last date, without modifying the dates in the selector?

Cypress Studio Does Not Handle Multiple Matching Elements – How to Fix?

I’m using Cypress Studio to generate test scripts, and I noticed an issue with how it selects elements. Consider the following line generated by Cypress Studio:

cy.get('[data-cy="kam.customer.basic-details.customer-name-input"] input').clear().type('test_1');

The problem is that there are multiple elements matching this selector, but Cypress Studio does not add any indexing. So, when I run the test again, it sometimes fails because it selects the wrong element (or multiple elements).

For example, if I manually add indexing like this:

`cy.get('[data-cy="kam.customer.basic-details.customer-name-input"]').find('input').eq(0).clear().type('test_1');

It works, but I want to know:
Why doesn’t Cypress Studio automatically handle multiple matching elements?
Is there a way to configure Cypress Studio to generate more reliable selectors?
What are the best practices to avoid this issue when using Cypress Studio for test recording?

How can I get a ACS ID for initiating a 1:1 voice all using Azure Communication Service?

I am using the sample code from Azure to trying the JS SDK of the Azure Communication Service. Now I am trying to initiate an outgoing call. But the API needs the ACS ID for the outgoing call and I am unable to find this ID.

I have already created a resource in azure portal and got the Connection String. A user token with VOIP is also generated. The SDK initialisation has worked with the connection string. But I could only initiate a voice call to the azure echo bot using 8:echo123 successfully.

Hide a highchart sankey diagram node on double click

I have created a Sankey diagram from Highcharts.

I want to hide all the nodes which start from a particular node when i double click it.

So far, i am able to remove the path from clicked node to target node, but could not remove target node itself.

Here is the example, if you double click on “Shopping” node ( and remove the mouse from the chart ) it hides the path, but i want to remove both “Online” and “Offline” node also.

Highcharts.chart("container", {
  title: {
    text: "Cash flow"
  },
  chart: {
    events: {
      load: function() {
        let chart = this;

        chart.series[0].points.forEach((point) => {
          point.graphic.element.addEventListener("dblclick", function() {
            point.toNode.linksFrom.forEach((node) => {
              node.update({color: 'transparent', weight: 0 }, false);
            });
          });
        });
      }
    }
  },

  accessibility: {
    point: {
      valueDescriptionFormat: "{index}. {point.from} to {point.to}, " + "{point.weight}."
    }
  },
  tooltip: {
    headerFormat: null,
    pointFormat: "{point.fromNode.name} u2192 {point.toNode.name}: {point.weight:.2f} ",
    nodeFormat: "{point.name}: {point.sum:.2f}"
  },
  series: [{
    keys: ["from", "to", "weight"],
    data: [
      ["Salary", "Income", 5],
      ["Dividend", "Income", 2],
      ["Bonus", "Income", 3],

      ["Income", "Tax", 1],
      ["Income", "Shopping", 3],
      ["Income", "Invest", 6],

      ["Shopping", "Online", 1],
      ["Shopping", "Offline", 2]
    ],
    type: "sankey",
    name: "Sankey demo series"
  }]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/sankey.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

<figure class="highcharts-figure">
  <div id="container"></div>
</figure>

Issue when yarn install inside docker, but works outside docker

I get this error

Yarn - There appears to be trouble with your network connection. Retrying

and then timeout as error An unexpected error occurred: 'https://registry.yarnpkg.com/<package name>.tgz: ESOCKETTIMEDOUT’.

I have tried adding network timeout via yarn install --network-timeout 240000 , still same issue

if have any suggestions for this then please let me know. Thankyou

How to limit new Google Maps Autocomplete suggestions to only return street addresses

Problem Description

I’m having an issue with the new Google Autocomplete API not returning street addresses as in earlier versions:

  • Previous Behavior: The API accepted a type: [“address”] parameter
    which returned only full addresses
  • Current Behavior: When I type “V”,
    I get countries like “Vietnam” instead of street addresses starting
    with “V”
  • Desired Outcome: I want to list only full street addresses
    to users

What I’ve Tried

Looking at Google’s documentation, there’s a property called includedPrimaryTypes which accepts values like “street_address” or “street_number”, but this doesn’t seem to be working correctly it returns only specific street addresses not all that Google offers.

My Current Code

     const { AutocompleteSuggestion } = await google.maps.importLibrary("places");

     const { suggestions: fetchedSuggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions({
          input,
          sessionToken: token.value,
          // includedPrimaryTypes: ["street_address", "street_number", "premise"],
        });
    
    suggestions.value = await Promise.all(
      fetchedSuggestions.map(
        async (suggestion: google.maps.places.AutocompleteSuggestion) => {
          const place = suggestion.placePrediction.toPlace();
    
          await place.fetchFields({
            fields: ["formattedAddress"],
          });
    
          return {
            placePrediction: suggestion.placePrediction,
            formattedAddress: place.formattedAddress,
          };
        },
      ),
    );
  1. How can I filter results to only include street addresses?
  2. Is there a replacement for the previous type: [“address”] parameter?
  3. What’s the correct way to use includedPrimaryTypes if that’s the right approach?

How to get custom variable price if bought in bulk (2x, 3x)

I want to have option to buy 2x or 3x product with discount (custom) price.
If chosen 2x or 3x all the attributes have same price.

The issue is that the custom price (e.g., 19.9) is not being applied to the cart item, and the base prices (price: “22.90”, regular_price: “34.90”) are still being used. This indicates that the custom price is not being properly passed to the server or applied to the cart item.

  1. Custom Price Not Applied:
    The custom price is sent to the server, but it is not being applied to the cart item.
    The base prices (price, regular_price, sale_price) are still being used.

  2. WooCommerce REST API Not Handling Custom Price:
    The WooCommerce REST API (/wp-json/wc/store/v1/batch) does not natively support custom prices. You need to handle this on the server side.

  3. JavaScript and PHP Integration:
    The JavaScript code sends the custom price to the server, but the PHP code is not properly applying it to the cart item.

To solve this problem, i need to:

  1. Ensure the Custom Price is Passed to the Server:
    The JavaScript code must send the custom price to the server when adding items to the cart.

  2. Apply the Custom Price to the Cart Item:
    Use WooCommerce hooks to override the product price when it is added to the cart.

  3. Retain the Custom Price in the Cart Session:
    Ensure the custom price is retained in the cart session after page refresh.

  4. Display the Custom Price in the Mini-Cart and Cart Page:
    Ensure the custom price is displayed correctly in the mini-cart and cart page.

My functions code:

function custom_pricing_options_html() {
    if (!is_product()) return;

    global $product;

    // Check if the product is simple or variable
    if (!$product->is_type('simple') && !$product->is_type('variable')) return;

    $product_id = $product->get_id();
    $currency = get_woocommerce_currency_symbol();

    // Get base prices
    $regular_price = $product->is_type('variable') 
        ? floatval($product->get_variation_regular_price('min')) 
        : floatval($product->get_regular_price());
    $sale_price = $product->is_type('variable') 
        ? floatval($product->get_variation_sale_price('min')) 
        : floatval($product->get_sale_price());

    // Get custom pricing options from ACF fields
    $price_option_2 = floatval(get_field('pricing_option_2', $product_id)) ?: 0;
    $price_option_3 = floatval(get_field('pricing_option_3', $product_id)) ?: 0;

    // Pricing options for 1x, 2x, and 3x
    $pricing_options = [
        1 => ['price' => $sale_price],
        2 => ['price' => $price_option_2],
        3 => ['price' => $price_option_3],
    ];

    ob_start();
    ?>

    <div class="pricing-container">
        <?php foreach ($pricing_options as $qty => $option) :
            if ($option['price'] <= 0) continue; // Skip empty values
        ?>
        <div class="pricing-option <?php echo $qty === 1 ? 'selected' : ''; ?>" 
            data-qty="<?php echo esc_attr($qty); ?>" 
            data-price="<?php echo esc_attr($option['price']); ?>" 
            data-currency-symbol="<?php echo esc_attr($currency); ?>">
    
            <div class="qty-discount-qty"><?php echo esc_html($qty); ?>x</div>
            <span class="qty-discount-price">
                <strong><?php echo esc_html($option['price'] . ' ' . $currency); ?></strong>
            </span>
            <div class="qty-discount-kos">per pair</div>
        </div>
        <?php endforeach; ?>
    </div>

    <!-- Hidden field to store the selected price -->
    <input type="hidden" id="custom_selected_price" name="custom_selected_price" value="<?php echo esc_attr($sale_price); ?>">
    
   
    <?php
    echo ob_get_clean();
}
add_action('woocommerce_before_add_to_cart_form', 'custom_pricing_options_html');

// Save the selected price in cart item data
add_filter('woocommerce_add_cart_item_data', 'update_sale_price_in_cart', 10, 2);
function update_sale_price_in_cart($cart_item_data, $product_id) {
    if (isset($_POST['custom_selected_price'])) {
        $selected_price = floatval($_POST['custom_selected_price']);
        error_log('Selected Price in Cart: ' . $selected_price); // Debug
        $cart_item_data['custom_price'] = $selected_price;
    }
    return $cart_item_data;
}

// Apply the custom price to the cart item
add_action('woocommerce_before_calculate_totals', 'apply_custom_price_to_cart', 20);
function apply_custom_price_to_cart($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;

    foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
        if (isset($cart_item['custom_price'])) {
            $custom_price = floatval($cart_item['custom_price']);
            $cart_item['data']->set_price($custom_price); // Override base price
        }
    }
}

// Retain the custom price in the cart after page refresh
add_filter('woocommerce_get_cart_item_from_session', 'retain_custom_price_in_cart', 10, 2);
function retain_custom_price_in_cart($cart_item, $values) {
    if (isset($values['custom_price'])) {
        error_log('Retaining Custom Price: ' . $values['custom_price']); // Debug
        $cart_item['custom_price'] = $values['custom_price'];
    }
    return $cart_item;
}

// Display custom price in mini-cart and cart page
function display_custom_price_in_cart($price, $cart_item, $cart_item_key) {
    if (isset($cart_item['custom_price'])) {
        $price = wc_price($cart_item['custom_price']);
    }
    return $price;
}
add_filter('woocommerce_cart_item_price', 'display_custom_price_in_cart', 10, 3);
add_filter('woocommerce_cart_item_subtotal', 'display_custom_price_in_cart', 10, 3);

// AJAX Handler for Adding to Cart with Custom Price
add_action('wp_ajax_add_to_cart_with_custom_price', 'add_to_cart_with_custom_price');
add_action('wp_ajax_nopriv_add_to_cart_with_custom_price', 'add_to_cart_with_custom_price');
function add_to_cart_with_custom_price() {
    if (!isset($_POST['product_id']) || !isset($_POST['custom_price'])) {
        wp_send_json_error('Invalid request.');
    }

    $product_id = intval($_POST['product_id']);
    $quantity = intval($_POST['quantity']);
    $custom_price = floatval($_POST['custom_price']);

    // Add product to cart
    $cart_item_key = WC()->cart->add_to_cart($product_id, $quantity);

    if ($cart_item_key) {
        // Set custom price in cart item data
        WC()->cart->cart_contents[$cart_item_key]['custom_price'] = $custom_price;
        WC()->cart->set_session();

        // Recalculate totals to apply the custom price
        WC()->cart->calculate_totals();

        wp_send_json_success('Product added to cart.');
    } else {
        wp_send_json_error('Failed to add product to cart.');
    }
}

My javascript:


jQuery(document).ready(function ($) {
    const $body = $('body');
    const $pricingOptions = $('.pricing-option');
    const $customSelectedPrice = $('#custom_selected_price');
    const $addToCartButton = $('.single_add_to_cart_button');

    // Event delegation for pricing options
    $body
        .on('click', '.pricing-option', function () {
            $pricingOptions.removeClass('selected');
            $(this).addClass('selected');

            const qty = $(this).data('qty');
            const price = $(this).data('price');

            // Debug: Log the selected price
            console.log('Selected Price:', price);

            // Update the hidden input field
            $customSelectedPrice.val(price);

            duplicateVariationSelection(qty);
            updatePriceTotal();
            updateSimpleQuantity(qty);
            maybeDisableVariableAddToCartButton();
        })
        .on('click', '.qty-appended .filter-item-list li', function () {
            $(this).parents('.qty-appended').find('.filter-item-list li').removeClass('active');
            $(this).addClass('active');
            maybeDisableVariableAddToCartButton();
        })
        .on('click', '.product-type-variable .single_add_to_cart_button', function (e) {
            e.preventDefault();

            const selectedPrice = $customSelectedPrice.val();
            console.log('Price sent to server:', selectedPrice);

            if ($(this).hasClass('wc-variation-selection-needed') && $('.qty-appended').length > 0) {
                alert('Please select all variations before adding to cart.');
                return;
            }

            addAppendedItemsToCart(selectedPrice);
        });

    // Duplicate variations based on selected quantity
    function duplicateVariationSelection(qty) {
        if ($('.product-type-variable').length <= 0) return;

        const label = $('.variations .label label').first().text();
        const list = $('.variations .value ul.filter-item-list').clone().html().replace(/active/g, '');

        $('.qty-appended').remove(); // Remove previous appended rows

        for (let i = 2; i <= qty; i++) {
            $('.variations tbody').append(`
                <tr class="qty-appended qty-${i}">
                    <th class="label"><label>${label} ${i}</label></th>
                    <td><ul class="filter-item-list">${list}</ul></td>
                </tr>`);
        }

        maybeDisableVariableAddToCartButton();
    }

    // Enable/disable the "Add to Cart" button based on selected variations
    function maybeDisableVariableAddToCartButton() {
        const totalAppended = $('.qty-appended').length;
        const totalSelected = $('.filter-item-list li.active').length;

        $addToCartButton.prop('disabled', totalAppended + 1 !== totalSelected);
    }

    // Add items to the cart
    function addAppendedItemsToCart() {
        const attributeName = $('[data-attribute_name]').data('attribute_name');
        const variationData = $('[data-product_variations]').data('product_variations');
        const totalAppended = $('.qty-appended').length;
        const selectedPrice = $('.pricing-option.selected').data('price'); // Get selected price
        let cartData = [];
    
        let itemAttributeOriginal = $('table.variations tr:not(.qty-appended) li.active a').data('value');
    
        // Original selected variation.
        $.each(variationData, function (key, value) {
            if (value['attributes'][attributeName] === itemAttributeOriginal) {
                cartData.push({
                    path: '/wc/store/v1/cart/add-item',
                    method: 'POST',
                    headers: {
                        'Nonce': product_js_vars.woononce
                    },
                    body: {
                        id: value.variation_id,
                        quantity: 1,
                        custom_price: selectedPrice // Include custom price
                    }
                });
            }
        });
    
        // If multiple appended
        if ($('.qty-appended').length > 0) {
            for (let i = 1; i < totalAppended + 1; i++) {
                let counter = i + 1;
                const itemAttribute = $(`.qty-${counter} .filter-item-list li.active a`).data('value');
    
                $.each(variationData, function (key, value) {
                    if (value['attributes'][attributeName] === itemAttribute) {
                        cartData.push({
                            path: '/wc/store/v1/cart/add-item',
                            method: 'POST',
                            headers: {
                                'Nonce': product_js_vars.woononce
                            },
                            body: {
                                id: value.variation_id,
                                quantity: 1,
                                custom_price: selectedPrice // Include custom price
                            }
                        });
                    }
                });
            }
        }
    
        $.ajax({
            url: '/wp-json/wc/store/v1/batch',
            method: 'POST',
            dataType: 'json',
            headers: {
                'Nonce': product_js_vars.woononce
            },
            data: {
                requests: cartData
            },
            success: function (response) {
                console.log("Items added to cart:", response);
            },
            error: function (xhr) {
                console.error('Error adding item to cart:', xhr.responseJSON);
            }
        });
    }

    // Update the displayed price
    function updatePriceTotal() {
        const selectedOption = $('.pricing-option.selected');
        const price = selectedOption.data('price');
        const qty = selectedOption.data('qty');
        const percent = selectedOption.data('percent');
        const regular = selectedOption.data('regular');
        const currency = selectedOption.data('currency-symbol');

        const totalRegular = (regular * qty).toFixed(2);
        const totalPrice = (price * qty).toFixed(2);

        $('.price-placeholder').html(`
            <div class="variable-price-box">
                <div class="left-price-wrapper">
                    <div class="limited-offer-label">Quantity: ${qty}</div>
                    <div class="discount-badge-price">-${percent}% discount</div>
                </div>
                <div>
                    <del>${totalRegular} ${currency}</del>
                    <ins>${totalPrice} ${currency}</ins>
                </div>
            </div>`);
    }

    // Update quantity for simple products
    function updateSimpleQuantity(qty) {
        if ($('.product-type-variable').length > 0) return;
        $('form.cart .quantity input.qty').val(qty).trigger('change');
    }
});

Ghostscript “gs” breaks imagick readImage for PDF

When everything is installed and setup regarding magick and if the Environment Variables path is also set, you should look at the installation folder which is usually located in C:Program Filesgsgs10.x .0bin. If there is no gs.exe and only gswin64.c.exe, copy that executable and change its name to gs.exe and readImage() will run the script.

With Laravel and php i have tried to convert pdf to png so i could use it for converting png image to zpl extension. Installing ghostscript for windows system didn’t help because file that are installed do not have proper name that class Imagick call and that name of executabel is “gs” and not “gswin64c”. Changing name help to solve problem and run ghostscript.

How to test and share PHP and MySQL code together [closed]

I’m looking for an open-source online development environment or fiddle, similar to JSFiddle, that allows me to create and share small PHP and MySQL code snippets. My goal is to build proof-of-concept examples that I can share in Stack Overflow answers, where viewers can test the code live without needing to set up their own server environments.

Ideally, the tool should support both PHP scripts and MySQL queries, providing a quick and easy way to demonstrate server-side code and database interactions directly in the browser.

Does anyone know of a platform or tool that fits this use case, where I can generate and share these kinds of live demos without any server configuration?