Safari scroll jump after unloading element innerHTML

This issue is isolated to Safari on macOS and iOS. All other browsers don’t have this problem.

I have an Intersection Observer that handles loading/unloading chapters in a vertical scrolling book.

This function unloads chapters that aren’t in view:

function unloadChapter(chapterId) {

  const chapterElement = document.querySelector('.chapter[data-chapter-id="' + chapterId + '"] .chapter-content');

  if (chapterElement) {
    chapterElement.innerHTML = '';
  }
}

When unloading a chapter below the current position, there’s no scroll jank.

But when unloading a chapter above the current chapter, the scroll position jumps due to the sudden unload of content, but only on Safari.

I have a temporary work around by adding back in the difference of lost content height, then scrolling back to the new relative position:

function unloadChapter(chapterId) {

    const chapterElement = document.querySelector('.chapter[data-chapter-id="' + chapterId + '"] .chapter-content');

    if (chapterElement) {
        // Measure the current scroll height
        const previousScrollHeight = document.documentElement.scrollHeight;
        
        // Measure the current scroll position
        const previousScrollTop = window.scrollY || document.documentElement.scrollTop;
    
        // Unload the chapter content
        chapterElement.innerHTML = '';

        // Measure the new scroll height after unloading the content
        const newScrollHeight = document.documentElement.scrollHeight;

        // Calculate the difference in scroll height
        const scrollHeightDifference = previousScrollHeight - newScrollHeight;

        // Adjust the scroll position based on the difference in height
        window.scrollTo(0, previousScrollTop - scrollHeightDifference);
    }
}

But this causes a noticeable flicker when scrolling.

Replace backlash with 2 backslashes in JavaScript [duplicate]

I want to display strings exactly as they are, without special characters (i.e. d, n, s) being recognized.

For example, say I have this string with a newline character:

let someString = 'hellonthere';

I need to escape the newline character, so I need to replace the backslash with 2 backslashes to get hello\nthere.

Solution Attempt 1:

let replacedString = someString.replace(/\/g, "\\"), 

but replacedString still recognizes the newline character:

hello
there

when what I want to see for replacedString is hello\nthere.

Solution Attempt 2:

let rawString = String.raw`hellonworld`.replace(/\/g,"\\");

This works well, because rawString is hello\nworld. However, the template literal part should be a variable (someString) and when I include someString like so:

let rawString = String.raw`${someString}`.replace(/\/g,"\\");

I get this for rawString:

hello
there

How do I simply replace a backslash with 2 backslashes? I’ve already scoured several posts on Stack Overflow and can’t seem to find a solution to this problem.

Thanks in advance!

CSS scroll-snap on overlapping divs not working in Firefox

I was messing around with CSS and tried to make a scroll snap effect in some divs that overlap each other on scroll, like cards coming up and down over each other. When i scroll up they disapear leaving allways 1 div in the viewport.

I tried to add a snap effect when i scroll into an out of a div. The snap effect works fine on Edge and Chrome but when i try it on firefox, sometimes divs just don’t scroll totally or don’t let me use scroll on mouse wheel.

To keep the “overlapping divs” effect i used:

position: sticky

top: 0

Here is a codepen link: https://codepen.io/MoreiraJorge/pen/ZEdvzmG

PS: I didn’t test it in Safari.

String.replace Error: Maximum call stack size exceeded [closed]

error image
I am new to nextjs and working on stack overflow clone by following a tutorial, my webpage was running fine but as soon as i started implementing server side things , it started to show this error.
enter image description here enter image description here

  • I tried to search it everywhere on Chatgpt, tutorial, github copilot but didn’t got the result, first it also showed error image, but somehow got it fixed , but the above error is not fixable by any means. I am a newbie to this, i am really looking forward for your help, if required i can share more codes and files which may be breaking my webpage.
    thank you

Integrating tailwind into storybook7 using webpack

Been struggling with this problem for hours πŸ™
I have a separate project with a component that uses shadcn and tailwind.css. And I want to move this component to another project that uses storybook7 version, and then I will implement other components there. Also this project is monorepo. I have almost everything worked out, but tailwind styles don’t work for all components.

storybook (7 version) details

/apps/design-system/.storybook/main.js

const path = require('path');

module.exports = {
  stories: [
    '../../../packages/*/src/**/*.stories.@(js|jsx|ts|tsx)',
    '../../../apps/*/src/**/*.stories.@(js|jsx|ts|tsx)',
    '../../../packages/*/*/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  staticDirs: ['../../../packages/component-library/public'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-onboarding',
    '@storybook/addon-interactions',
    '@storybook/preset-scss',
  ],
  framework: '@storybook/react-webpack5',
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /.css$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            postcssOptions: {
              plugins: [
                require('tailwindcss'),
                require('autoprefixer'),
              ],
            },
          },
        },
      ],
      include: path.resolve(__dirname, '../../../packages/component-library/uikit'),
    });

    config.resolve.alias = {
      '@': path.resolve(__dirname, '../../../packages/component-library/uikit'),
      '@ui': path.resolve(__dirname, '../../../packages/component-library/uikit/ui'),
      '@components': path.resolve(__dirname, '../../../packages/component-library/uikit/components'),
    };

    return config;
  },
};

/apps/design-system/.storybook/preview.js

import 'shared/src/index.css'
import '../../../packages/component-library/uikit/global.css'

/** @type { import('@storybook/react').Preview } */
const preview = {
  parameters: {
    actions: { argTypesRegex: "^on[A-Z].*" },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
};

export default preview;

tailwind details

/packages/component-library/uikit/global.css

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 240 10% 3.9%;
    --card: 0 0% 100%;
    --card-foreground: 240 10% 3.9%;
    --popover: 0 0% 100%;
    --popover-foreground: 240 10% 3.9%;
    --primary: 142 86% 28%;
    --primary-foreground: 356 29% 98%;
    --secondary: 240 4.8% 95.9%;
    --secondary-foreground: 240 5.9% 10%;
    --muted: 240 4.8% 95.9%;
    --muted-foreground: 240 3.8% 45%;
    --accent: 240 4.8% 95.9%;
    --accent-foreground: 240 5.9% 10%;
    --destructive: 0 72% 51%;
    --destructive-foreground: 0 0% 98%;
    --border: 240 5.9% 90%;
    --input: 240 5.9% 90%;
    --ring: 142 86% 28%;
    --radius: 0.5rem;
  }
}

@layer base {
  * {
    @apply border-border;
  }

  body {
    @apply bg-background text-foreground font-body;
  }

  h1, h2, h3, h4, h5, h6 {
    @apply font-heading;
  }
}

/packages/component-library/uikit/postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

/packages/component-library/uikit/tailwind.config.js

/** @type {import('tailwindcss').Config} */

import { fontFamily } from 'tailwindcss/defaultTheme';
import tailwindAnimate from 'tailwindcss-animate';

export default {
  content: ['./components/**/*.{js,jsx}', './ui/**/*.{js,jsx}'],
  prefix: '',
  theme: {
    extend: {
      fontFamily: {
        heading: ['var(--font-heading)', ...fontFamily.sans],
        body: ['var(--font-body)', ...fontFamily.sans],
      },
      colors: {
        border: 'hsl(var(--border))',
        input: 'hsl(var(--input))',
        ring: 'hsl(var(--ring))',
        background: 'hsl(var(--background))',
        foreground: 'hsl(var(--foreground))',
        primary: {
          DEFAULT: 'hsl(var(--primary))',
          foreground: 'hsl(var(--primary-foreground))',
        },
        secondary: {
          DEFAULT: 'hsl(var(--secondary))',
          foreground: 'hsl(var(--secondary-foreground))',
        },
        destructive: {
          DEFAULT: 'hsl(var(--destructive))',
          foreground: 'hsl(var(--destructive-foreground))',
        },
        muted: {
          DEFAULT: 'hsl(var(--muted))',
          foreground: 'hsl(var(--muted-foreground))',
        },
        accent: {
          DEFAULT: 'hsl(var(--accent))',
          foreground: 'hsl(var(--accent-foreground))',
        },
        popover: {
          DEFAULT: 'hsl(var(--popover))',
          foreground: 'hsl(var(--popover-foreground))',
        },
        card: {
          DEFAULT: 'hsl(var(--card))',
          foreground: 'hsl(var(--card-foreground))',
        },
      },
      borderRadius: {
        xl: `calc(var(--radius) + 4px)`,
        lg: `var(--radius)`,
        md: `calc(var(--radius) - 2px)`,
        sm: `calc(var(--radius) - 4px)`,
      },
      keyframes: {
        'accordion-down': {
          from: { height: 0 },
          to: { height: 'var(--radix-accordion-content-height)' },
        },
        'accordion-up': {
          from: { height: 'var(--radix-accordion-content-height)' },
          to: { height: 0 },
        },
      },
      animation: {
        'accordion-down': 'accordion-down 0.2s ease-out',
        'accordion-up': 'accordion-up 0.2s ease-out',
      },
    },
  },
  plugins: [tailwindAnimate],
};

But I get an error as a result

Module build failed (from ../../node_modules/@storybook/builder-webpack5/node_modules/css-loader/dist/cjs.js):

SyntaxError

(2:7) /Users/yurii/projects/datarama_frontend/packages/component-library/uikit/global.css Unknown word

1 |

2 | import API from “!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js”;
| ^
3 | import domAPI from “!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js”;
4 | import insertFn from “!../../../node_modules/style-loader/dist/runtime/insertBySelector.js”;

ERROR in ../../node_modules/@storybook/builder-webpack5/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[9].use[1]!../../node_modules/style-loader/dist/cjs.js!../../node_modules/css-loader/dist/cjs.js!../../node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[16].use[2]!../../packages/component-library/uikit/global.css
Module build failed (from ../../node_modules/@storybook/builder-webpack5/node_modules/css-loader/dist/cjs.js):

SyntaxError

(2:7) /Users/yurii/projects/datarama_frontend/packages/component-library/uikit/global.css Unknown word

1 |

2 | import API from “!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js”;
| ^
3 | import domAPI from “!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js”;
4 | import insertFn from “!../../../node_modules/style-loader/dist/runtime/insertBySelector.js”;

I realize it’s because my webpack is trying to parse the css as a js file. But I don’t understand why? What am I doing wrong? Please help me fix it!

Passing URLs as video paths in @google/generative AI and Next.js

I’m looking for a solution to upload videos from a URL when using @google/generative-ai in Next.js. I have figured out how to use videos that are stored on my machine, but not on external sources.

This is my current function to upload videos to @google/generative-ai:

"use server"

const { GoogleGenerativeAI } = require("@google/generative-ai");
import { GoogleAIFileManager, FileState } from "@google/generative-ai/server";
import { redirect } from "next/navigation";
import fetchVideoById from "./fetchVideoById";

// Initialize GoogleAIFileManager with your API_KEY.
const fileManager = new GoogleAIFileManager(process.env.API_KEY);


// Access your API key as an environment variable (see "Set up your API key" above)
const genAI = new GoogleGenerativeAI(process.env.API_KEY);

// Choose a Gemini model.
const model = genAI.getGenerativeModel({
  model: "gemini-1.5-pro",
});

export async function generateSummary(formData) {
  const rows = await fetchVideoById(formData.get("id"))
  const url = rows["url"]
  // by the way, this returns the URL for the video that is stored in my database, so assume that      the URL is valid.

  console.log("Uploading file...")
    const fileManager = new GoogleAIFileManager(process.env.API_KEY);

    // Upload the file and specify a display name.
    const uploadResponse = await fileManager.uploadFile(url, {
      mimeType: "video/mp4",
      displayName: rows["title"],
    });

    // View the response.
    console.log(`Uploaded file ${uploadResponse.file.displayName} as: ${uploadResponse.file.uri}`);
    const name = uploadResponse.file.name;

    // Poll getFile() on a set interval (10 seconds here) to check file state.
    let file = await fileManager.getFile(name);
    while (file.state === FileState.PROCESSING) {
      process.stdout.write(".")
      // Fetch the file from the API again
      file = await fileManager.getFile(name)
    }

    if (file.state === FileState.FAILED) {
      throw new Error("Video processing failed.");
    }

    // When file.state is ACTIVE, the file is ready to be used for inference.
    console.log(`File ${file.displayName} is ready for inference as ${file.uri}`);

    const result = await model.generateContent([
      {
        fileData: {
          mimeType: uploadResponse.file.mimeType,
          fileUri: uploadResponse.file.uri
        }
      },
      { text: "Summarize this video." },
    ]);

  // Handle the response of generated text
  console.log(result.response.text())

  return result.response.text()

  console.log("Deleting file...")

  await fileManager.deleteFile(file.name);

  console.log("Deleted file.")
  
}

This is the error that I get:

Error: ENOENT: no such file or directory, open 'C:Usersn_macDesktopCodingsummafront-endhttps:m9x5emw6q3oaze3r.public.blob.vercel-storage.commonkeyman646999DBC5-2D93-4220-BC43-3C16C9A5D9C6-IZzFC1THZXPSgeAK1NPo3uCVxA091l.mp4'

As you can see, it’s searching on my machine for the file, when the files are stored in Vercel Blob.

Any help is appreciated.

vscode extension for auto complete inside html script tag

I’m creating a vscode extension that adds some custom autofill capabilities to the script tags inside an html file. It’s based on this example from vscodes extension tutorial page.

I took that example and changed it to look at script tags. So overall the flow of the extension is something like:

  1. A user goes to an .html file, the extension starts
  2. When the user starts typing and vscode generates autocomplete items, it calls provideCompletionItem from my extension
  3. My extension checks if the document is currently located inside a script tag before continuing
  4. Create a virtual document which replaces everything in the file with spaces except for script tag content
  5. Append ;class ExampleClass{method1(){}}; to the end of the virtual document string
  6. Run the default behavior for getting the autocompletion list in the virtual document

The current result of this is when you go to a script tag and start typing, ExampleClass will show up like I want. However when you type ExampleClass.| (‘|’ represents where the cursor is) it only displays the default completion elements. It also produces an error:

[Extension Host] Unexpected resource embedded-content://js/path/to/file.html.js

Before this error pops up it isn’t running the registerTextDocumentContentProvider which returns the virtual content when given a virtual URI. Presumably this means I’m missing some special case for when some path saved in the CompletionItem is accessed but I can’t figure out exactly what that is.

Here is some of the relevant code:

the function that creates virtual file content:

    // the above code is unchanged from the vscode example

    let content = documentText
        .split('n')
        .map(line => {
            return ' '.repeat(line.length);
        }).join('n');

    regions.forEach(r => {
        if (r.languageId === languageId) { // languageId == javascript
            content = content.slice(0, r.start) + documentText.slice(r.start, r.end) + content.slice(r.end);
        }
    });

    let inject = ';class ExampleClass{method1(){}};';

    return content + inject; // does not run on error
}

serves up the virtual documents:

const virtualDocumentContents = new Map<string, string>();

workspace.registerTextDocumentContentProvider('embedded-content', {
    provideTextDocumentContent: uri => {
        console.log('get virt file'); // in the case of the error this never logs
        // Remove leading `/` and ending `.js` to get original URI
        const originalUri = uri.path.slice(1).slice(0, -3);
        const decodedUri = decodeURIComponent(originalUri);
        if (!virtualDocumentContents.has(decodedUri)) console.warn(`no such virtual file ${decodedUri}`); // this warning never goes off
        return virtualDocumentContents.get(decodedUri);
    }
});

Provide CompletionItems

const clientOptions: LanguageClientOptions = {
    documentSelector: [{ scheme: 'file', language: 'html' }],
    middleware: {
        provideCompletionItem: async (document, position, context, token, next) => {
            console.log('auto completion...'); // does not run on error

            if (!isInsideScriptRegion(htmlLanguageService, document.getText(), document.offsetAt(position))) {
                return await next(document, position, context, token);
            }

            const originalUri = document.uri.toString(true);
            
            const virtContent = getVirtualContent(htmlLanguageService, document.getText(), 'javascript');
            virtualDocumentContents.set(originalUri, virtContent);

            const vdocUriString = `embedded-content://js/${encodeURIComponent(
                originalUri
            )}.js`;
            const vdocUri = Uri.parse(vdocUriString);

            const compArr = await commands.executeCommand<CompletionList>(
                'vscode.executeCompletionItemProvider',
                vdocUri,
                position,
                context.triggerCharacter
            );

            env.clipboard.writeText(virtContent); // for debugging, this of course also does not run when the error occurs
            console.log('write board');

            return compArr;
        }
    }
}

Preline component library JavaScript not working when used in browser via CDN

I am having problems with what should be a very simple task. I would like to use Preline’s Tailwind CSS component library. To be exact, I would like to use this basic modal sample found in the documentation:

<button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-basic-modal" data-hs-overlay="#hs-basic-modal">
  Open modal
</button>

<div id="hs-basic-modal" class="hs-overlay hs-overlay-open:opacity-100 hs-overlay-open:duration-500 hidden size-full fixed top-0 start-0 z-[80] opacity-0 overflow-x-hidden transition-all overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-basic-modal-label">
  <div class="sm:max-w-lg sm:w-full m-3 sm:mx-auto">
    <div class="flex flex-col bg-white border shadow-sm rounded-xl pointer-events-auto">
      <div class="flex justify-between items-center py-3 px-4 border-b">
        <h3 id="hs-basic-modal-label" class="font-bold text-gray-800">
          Modal title
        </h3>
        <button type="button" class="size-8 inline-flex justify-center items-center gap-x-2 rounded-full border border-transparent bg-gray-100 text-gray-800 hover:bg-gray-200 focus:outline-none focus:bg-gray-200 disabled:opacity-50 disabled:pointer-events-none" aria-label="Close" data-hs-overlay="#hs-basic-modal">
          <span class="sr-only">Close</span>
          <svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M18 6 6 18"></path>
            <path d="m6 6 12 12"></path>
          </svg>
        </button>
      </div>
      <div class="p-4 overflow-y-auto">
        <p class="mt-1 text-gray-800">
          This is a wider card with supporting text below as a natural lead-in to additional content.
        </p>
      </div>
      <div class="flex justify-end items-center gap-x-2 py-3 px-4 border-t">
        <button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#hs-basic-modal">
          Close
        </button>
        <button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
          Save changes
        </button>
      </div>
    </div>
  </div>
</div>

The tricky part is that this project does not use a Node JS server. This is why searched for its JavaScript library CDN and included it to my HTML file:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/preline.min.js"></script>

However, when trying to test the modal window, the window just goes dark (as if there modal was opened) but nothing happens. I have tried with multiple browsers and even to upload the preline.min.js file to my server and link it locally but it does not work either. I have checked and the code of the CDN’s preline.min.js file seems to be identical to what you when you install it via NPM. Other preline components seem to be partially working.

Screenshot of the problem

This is the full code of my HTML page:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Sample</title>

    <script src="https://cdn.tailwindcss.com"></script>
</head>

<body>
  <button type="button" class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-basic-modal" data-hs-overlay="#hs-basic-modal">
    Open modal
  </button>
  
  <div id="hs-basic-modal" class="hs-overlay hs-overlay-open:opacity-100 hs-overlay-open:duration-500 hidden size-full fixed top-0 start-0 z-[80] opacity-0 overflow-x-hidden transition-all overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-basic-modal-label">
    <div class="sm:max-w-lg sm:w-full m-3 sm:mx-auto">
      <div class="flex flex-col bg-white border shadow-sm rounded-xl pointer-events-auto">
        <div class="flex justify-between items-center py-3 px-4 border-b">
          <h3 id="hs-basic-modal-label" class="font-bold text-gray-800">
            Modal title
          </h3>
          <button type="button" class="size-8 inline-flex justify-center items-center gap-x-2 rounded-full border border-transparent bg-gray-100 text-gray-800 hover:bg-gray-200 focus:outline-none focus:bg-gray-200 disabled:opacity-50 disabled:pointer-events-none" aria-label="Close" data-hs-overlay="#hs-basic-modal">
            <span class="sr-only">Close</span>
            <svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
              <path d="M18 6 6 18"></path>
              <path d="m6 6 12 12"></path>
            </svg>
          </button>
        </div>
        <div class="p-4 overflow-y-auto">
          <p class="mt-1 text-gray-800">
            This is a wider card with supporting text below as a natural lead-in to additional content.
          </p>
        </div>
        <div class="flex justify-end items-center gap-x-2 py-3 px-4 border-t">
          <button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#hs-basic-modal">
            Close
          </button>
          <button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
            Save changes
          </button>
        </div>
      </div>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/preline.min.js"></script>
</body>

</html>

I would be very grateful for any suggestions to get this working.

create-jest-runner throwing “cannot read properties of undefined” error

I am creating a custom runner for jest with create-jest-runner

I am following the examples, but I keep receiving the error

TypeError: Cannot read properties of undefined (reading 'startsWith')
    at new Worker (/Users/redacted/git/redacted/redacted/redacted/node_modules/create-jest-runner/node_modules/jest-worker/build/index.js:120:20)
    at BaseTestRunner._createParallelTestRun (/Users/redacted/git/redacted/redacted/redacted/node_modules/create-jest-runner/build/createJestRunner.js:63:22)
    at BaseTestRunner.runTests (/Users/redacted/git/redacted/redacted/redacted/node_modules/create-jest-runner/build/createJestRunner.js:40:119)
    at TestScheduler.scheduleTests (/Users/redacted/git/redacted/redacted/redacted/node_modules/@jest/core/build/TestScheduler.js:331:30)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async runJest (/Users/redacted/git/redacted/redacted/redacted/node_modules/@jest/core/build/runJest.js:376:19)
    at async _run10000 (/Users/redacted/git/redacted/redacted/redacted/node_modules/@jest/core/build/cli/index.js:416:7)
    at async runCLI (/Users/redacted/git/redacted/redacted/redacted/node_modules/@jest/core/build/cli/index.js:271:3)
    at async Object.run (/Users/redacted/git/redacted/redacted/redacted/node_modules/jest-cli/build/cli/index.js:163:37)

I am very confused. It doesn’t even get to the runner before it throws the error. I haven’t seen any documentation on how to fix this. I must be missing something.

Here is the setup I have:

"jest": "^26.6.3",
"create-jest-runner": "^0.12.3",

custom-runner.js

const { createJestRunner } = require("create-jest-runner");

const runner = async ({ testPath }) => {
    // Do Something
};

module.exports = createJestRunner(runner);

jest.config.js

module.exports = {
    ...regularSettings,
    runner: "./custom-runner.js",
};

When do we need to use a dot prefix when doing lit attribute property assignments?

The lit documentation has the following example showing how to set attribute values:

<!-- attribute values -->
<div label=${label}></div>
<button ?disabled=${isDisabled}>Click me!</button>
<input .value=${currentValue}>
<button @click=${this.handleClick()}>

So in the above example label is set without a dot prefix, but value uses a dot prefix (.value).

When do we need to include a dot . prefix. Is it only for value property assignments?

How can I display Plop generators based on choice?

I’m trying to configure Plop so that when the command is run, a sort of menu is first displayed prompting to select what group of generators you’d want to run. For example, you have generators for frontend files and generators for backend files. When you run plop, you should first be prompted with what group of generators you want to proceed with, then from that choice, the correspoding generators will be revealed to pick from.

Here’s what I have so far:

const controllerGenerator = require('./generators/server/controller');

module.exports = function (plop) {
  plop.setGenerator('menu', {
    description: 'Choose between client and server generators',
    prompts: [
      {
        type: 'list',
        name: 'workspace',
        message: 'Choose your workspace generator: ',
        choices: ['Client', 'Server'],
      },
    ],
    actions: (data) => {
      if (data.workspace === 'Client') {
        return [];
      } else if (data.workspace === 'Server') {
        return [controllerGenerator(plop)];
      }
    },
  });
};

I get this error when I run plop and select the server option

> plop

? Choose your workspace generator: Server
 - [ERROR] Cannot read properties of undefined (reading 'type')

Here is my controller generator:

module.exports = function (plop) {
  plop.setGenerator('controller', {
    description: 'generate controller',
    prompts: [
      {
        type: 'input',
        name: 'name',
        message: 'controller name: ',
      },
    ],
    actions: [
      {
        type: 'add',
        path: 'apps/server/src/controllers/{{kebabCase name}}-controller.js',
        templateFile: './templates/server/controller.js.hbs',
      },
    ],
  });
};

I’m assuming this has to do with the actions part of the controller generator, but I’m not sure as to what would make it not work. I’ve tried using the plop.load() function, but it just creates a no action error. Not sure how else to proceed to achieve my desired effect, which is that if I had selected the server option, then there would be the various server related generators displayed (ex: controller, router, etc.). Something like below:

> plop

? Choose your workspace generator:  Server

- controller generator
- router generator
...

and when you chose the specified generator (ex: controller generator), you would then be prompted to provide the details for it, like the name for example.

Is this feasible with plop?

Error output when trying to add data to the database using ajax in opencart

This is the error that appears
Warning: Undefined array key “name” in C:OSPanelhomehikmetpubliccatalogcontrollerdemotest.php on line 13Warning: Undefined array key “tel” in C:OSPanelhomehikmetpubliccatalogcontrollerdemotest.php on line 14{“success”:0}

HTML

<form action="/" method="post" class="main-hero-form">
                <div class="form-row">
                  <input class="form-control" type="text" name="name" placeholder="Π’Π°ΡˆΠ΅ имя" autocomplete="name" required="" id="name">
                  <input class="form-control" type="tel" name="tel" placeholder="Π’Π΅Π»Π΅Ρ„ΠΎΠ½" autocomplete="phone" required="" id="tel">
                  <input class="d-none" type="text" name="service" value="Π’Π΅ΠΏΠ»ΠΎΠ²Ρ‹Π΅ Ρ†Π΅Π½Ρ‚Ρ€Ρ‹ Π½Π° ΠΆΠΈΠ΄ΠΊΠΎΠΌ ΠΈ Π³Π°Π·ΠΎΠ²ΠΎΠΌ Ρ‚ΠΎΠΏΠ»ΠΈΠ²Π΅ с Π°Π²Ρ‚ΠΎΠ½ΠΎΠΌΠ½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚ΠΎΠΉ">
                </div>
                <input type="submit"value="Π—Π°ΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ, условия ΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ поставки" class="main-hero-form-send">
                <p class="main-hero-text">Π’ Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠΈ <span>15 ΠΌΠΈΠ½ΡƒΡ‚</span> Π²Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ Π·Π²ΠΎΠ½ΠΎΠΊ ΠΎΡ‚ нашСго ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставит ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΡƒΡŽ ΠΊΠΎΠ½ΡΡƒΠ»ΡŒΡ‚Π°Ρ†ΠΈΡŽ.</p>
              </form>

jQuery

$(document).ready(function() {
    $('.main-hero-form-send').on('click', function() { //активация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΡ€ΠΈ Π½Π°ΠΆΠ°Ρ‚ΠΈΠΈ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ с class='main-hero-form-send'
        $.ajax({
            url: 'index.php?route=demo/test&language=ru-ru', 
            type: 'post',
            dataType: 'json', // Π½ΡƒΠΆΠ½ΠΎ Π»ΠΈ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΠΌΠ΅Π½Π½ΠΎ json?
            data: {'name': $('#name').val(), 'tel': $('#tel').val()}, // записываСм Π² массив Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· ΠΈΠ½ΠΏΡƒΡ‚Π°
            success: function(data){
                if (data.success){
                    alert('Π—Π°ΠΌΠ΅Ρ‚ΠΊΠ° Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π°');
                } else {  
                    alert('Ошибка записи'); 
                }
            }
        });
    });
});

PHP

$json = array();

        $name = $this->request->post['name']; // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΎΠ±Π΅ эти ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈΠ· посланных Π² аяксС Ρ‡Π΅Ρ€Π΅Π· POST Π΄Π°Π½Π½Ρ‹Ρ…
        $tel = $this->request->post['tel'];
    
        try {
            $this->db->query("INSERT INTO " . DB_PREFIX . "customer (firstname, telephone) VALUES ($name, $tel)");
            $json['success'] = 1; // всС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ
        } catch (Exception $e) {
            $json['success'] = 0; // Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ
        }
        $this->response->addHeader('Content-Type: application/json'); // Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ ΠΈ отправляСм Π΄Π°Π½Π½Ρ‹Π΅ Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ json (ΠΊΠ°ΠΊ ΠΈ Π±Ρ‹Π»ΠΎ ΡƒΠΊΠ°Π·Π°Π½ΠΎ Π² аяксС )
        $this->response->setOutput(json_encode($json));

Automated Flask Interface Querying After Form Submission

I’m creating a basic Flask app to showcase my silly mini projects that I’ve done for fun in python (originally created for CLI). One of these is a program to visualize John Conway’s Game Of Life (GOL). If you don’t know what that is, you don’t need to, just know that it’s a continuously changing binary matrix.

After the user submits a form that specifies an integer for the size of the grid and a float between 0 and 1 to auto-generate the density of living cells in the initial state, I want the grid to display below the form and switch to its next state every 0.1 seconds (without refreshing the page).

I have a fairly decent knowledge of Vanilla Python and HTML, but I’m new to Flask and know nothing about JavaScript. I ChatGPTed a little JS that I thought would work, but nothing displays below the form after it is submitted. As a side note, if possible, I’d like to not start querying Flask until after the form is submitted, which ChatGPT’s JS does not do. Here’s the code relevant to the GOL piece of the app:

In app.py:

import game_of_life
from markupsafe import Markup

game = None
@app.route("/create_GOL", methods=['post'])
def create_game():
    density, size = request.form['density'], request.form['size']
    global game
    # initializes game in GameOfLife class
    game = game_of_life.GameOfLife(int(size), float(density))
    return render_template("index.html")

@app.route("/next_state", methods=['get'])
def next_state():
    # runs method to update "game" to the next state in-place
    game.find_next_state()
    # returns the HTML-friendly version of the matrix
    return Markup('<br>'.join(''.join(('  ', 'β–ˆβ–ˆ')[j] for j in i) for i in game.m))

In index.html:

<form action="create_GOL", method="post">
    <label for="density">Density (0-1): </label>
    <input type="number" name="density", step="any", min=0, max=1>
    <label for="size">Size: </label>
    <input type="number" name="size", min=1, max=100>
    <input type="submit" value="Submit">
</form><br>
<div id="game-state"></div>
<script>
    function updateGameState() {
        fetch('/next_state')
            .then(response => response.json())
            .then(data => document.getElementById('game-state').innerText = data.state)
    }
    setInterval(updateGameState, 100);
</script>

How should I modify my code to:
1. Actually display something
2. Not waste queries on nothing until the form is actually submitted

Or, should I use a different approach?

Substitute synchronous (Webpack) bundled ESM client code on the server side (Node) based on feature flag

Given:

moduleA.mjs,
moduleA_FeatureFlag1.mjs,
moduleA_FeatureFlag2.mjs,

Where:
no modules expose an async export

I’d like to substitute moduleA.mjs from my node server at runtime (or at least at pod startup time) based on a feature flag stored in an environment variable. For example, I would switch moduleA.mjs for moduleA_FeatureFlag1.mjs on the server side if environment variable GLOBAL_FEATURE_FLAGS=FeatureFlag1

In webpack, you can easily do this if you have async code by using a const module = await import(<name of module>); in your code base.

However, the idea here is to allow developers to quickly and arbitrarily substitute new feature flag specific code in the application by copying existing modules (which might have synchronous interfaces) and renaming the copy with the feature flag (maintaining the same exports obviously). I don’t want people to have to add redirection logic in the existing modules to do this. The whole idea here is to keep the existing, tested logic unchanged so there are fewer opportunities to introduce regressions in the non-feature flag code.

This copying and renaming happens before the code is webpack bundled for production, so I could use webpack to do this. I just don’t know how (without using async import();).

Because this is going to be happening all the time (there may be dozens of feature flags at a time), it will be too much ceremony to separate the code into its own bundled library for every feature flag – unless there is some way to make this transparent to the developer by automating the process at bundle time.

Also, this is a large code base (i.e. slow to build) and there may be any number of these files with feature flag substitutions, so building every possible combination of them is probably a bad idea.