Pdfmake – Generated file displays text correctly but text is not searchable in Chrome (but works in Safari and Edge)

I’m using pdfMake in a Next.js project to generate PDFs with Japanese text using NotoSansJP fonts. The fonts are loaded via fetch, encoded in Base64, and assigned to the virtual file system (vfs). The generated PDF renders Japanese characters correctly in all browsers visually.

However:
In Chrome, the Japanese text is not searchable, and When copying the text, it becomes garbled (e.g., 89:;, rst}~).
In Safari and Edge, everything works as expected — text is copyable and searchable.
Curiously, “支援等記録” is searchable in Chrome only if bold: true is set.

What I’ve tried
Embedding .ttf and .otf versions of NotoSansJP.
Setting the font using font style at both defaultStyle and per text level.
Verified fonts are correctly fetched, base64-encoded, and loaded in vfs.

Has anyone resolved this issue with pdfMake and Japanese fonts in Chrome?
Is there a way to fix text encoding so it’s searchable?
Does this require specific font format settings?
Or is this a limitation of Chrome’s PDF renderer?

        let isPdfMakeReady = false;
        
        async function fetchFontBase64(url: string): Promise<string> {
          const res = await fetch(url);
          const blob = await res.blob();
        
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => {
              const result = reader.result as string;
              resolve(result.split(',')[1]); // remove "data:application/x-font-otf;base64,"
            };
            reader.onerror = reject;
            reader.readAsDataURL(blob);
          });
        }
        
        export async function initFonts() {
          if (isPdfMakeReady || typeof window === 'undefined') return pdfMake;
        
          const [regular, bold] = await Promise.all([
            fetchFontBase64('/fonts/NotoSansJP-Regular.ttf'),
            fetchFontBase64('/fonts/NotoSansJP-Bold.ttf'),
          ]);
        
          pdfMake.vfs = {
            'NotoSansJP-Regular.otf': regular,
            'NotoSansJP-Bold.otf': bold,
          };
        
          pdfMake.fonts = {
            NotoSansJP: {
              normal: 'NotoSansJP-Regular.otf',
              bold: 'NotoSansJP-Bold.otf',
              italics: 'NotoSansJP-Regular.otf',
              bolditalics: 'NotoSansJP-Bold.otf',
            }
          };
        
          isPdfMakeReady = true;
        }
        
        initFonts();
    
      let definition: TDocumentDefinitions = {
        pageSize: "A4",
        pageOrientation: pageOrientation,
        pageMargins: pageOrientation === "portrait" ? [0, 20, 0, 90] : [30, 20, 30, 90],
        content:     {
      text: '支援等記録', style: {
        font: "NotoSansJP",
        fontSize: 18,
        bold: false,
      }
    },
    {
      marginLeft: 20,
      marginRight: 28,
      columns: [
        {
          width: "*",
          stack: [
            {
              table: {
                widths: ["*", "*", '*'],
                body: [
                  [
                    { text: groupHome.name, bold: true },
                    "",
                    { text: '', alignment: "right", bold: true }
                  ],
                  [
                    { text: `${customer.name} 様`, style: "text" },
                    "",
                    { text: "", alignment: "right" }
                  ]
                ]
              },
              layout: 'noBorders'
            },
            {
              marginTop: 10,
              table: {
                widths: [100, 100],
                body: [
                  ['日付', getDisplayDate(date)],
                  ['水分合計量', getWaterAmountTotal(dailyRecordGroup.records).toString() + "ml"]
                ]
              },
            },
          ]
        },
        {
          width: 50,
          table: {
            widths: [50],
            heights: [10, 50],
            body: [
              [{ text: '利用者確認印', alignment: "center" }],
              [(stampSetting && stampSetting[RECORD_PDF_STAMP_TYPES.CUSTOMER as keyof RecordPdfStampSetting] && stampImage) ? {
                image: stampImage,
                width: 50,
                height: 50
              } : ""]
            ]
          },
        }
      ]
    }
],
        footer: function (currentPage, pageCount) {
          return [
            {
              text: `${currentPage.toString()} / ${pageCount}`,
              marginLeft: 560,
              marginTop: 60
            }
          ];
        },
        defaultStyle: {
          font: 'NotoSansJP',
          fontSize: 8,
          lineHeight: 0.9
        },
        styles: {
          title: {
            fontSize: 18,
            bold: true,
            alignment: "center",
            marginBottom: 20
          },
          subheader: {
            fontSize: 12,
            bold: true,
            margin: [0, 10, 0, 5]
          },
          text: {
            fontSize: 8,
            bold: false,
          },
          tableExample: {
            margin: [0, 5, 0, 15]
          }
        },
      };

How to open Safari with JavaScript

For versions prior to iOS18,it can open Safari with the following code:

var a = document.createElement('a');
a.href = "http://www.test.com";
document.body.appendChild(a);
a.click();

But for versions after iOS18,the code above is not effective.

So Is there any way to open Safari with JavaScript?

How can I persist Firebase user login session using Expo and JavaScript in React Native? Still redirects to Start screen after app refresh

I’m building a React Native app using Expo and JavaScript (no TypeScript) and integrating Firebase for authentication. After a user logs in successfully, I want them to stay logged in even after closing and reopening the app.

However, after an app refresh or restart, the user is redirected to the Start screen again and the user is set to NULL — even though they had just logged in before and outputting their values in the console. Here’s what I’ve tried and my current setup:

What I’ve Verified / Tried:

  • onAuthStateChanged() works — it returns the correct user after login
  • After refresh, it fires with null, meaning session wasn’t persisted
  • Made sure setPersistence() is called right after getAuth(app)
  • No other call to getAuth() anywhere before persistence is set
  • Confirmed AsyncStorage is installed and working
  • Read all related Firebase docs and Expo persistence guides

I feel like everything is wired correctly, but the session doesn’t persist — is there something I’m missing with setPersistence() or a race condition with how Firebase initializes?

App.js

import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import Start from './screens/Start'
import Home from './screens/Home'
import Register from './screens/Register'
import Login from './screens/Login'
import TermsAndConditions from './screens/TermsAndConditions'
import useAuth from './hooks/useAuth';

const Stack = createStackNavigator()

export default function App() {
  const { user } = useAuth();
  console.log('User:', user);

  if (user) {
    return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName = 'Home'>
          <Stack.Screen
            name='Home'
            component={Home}
            options={{ headerShown: false }}
          />
          <Stack.Screen
            name='TermsAndConditions'
            component={TermsAndConditions}
            options={{ headerShown: false }}
          />
      </Stack.Navigator>
    </NavigationContainer>
  );
  } else {
    return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName = 'Start'>
          <Stack.Screen
            name='Start'
            component={Start}
            options={{ headerShown: false }}
          />
          <Stack.Screen
            name='Register'
            component={Register}
            options={{ headerShown: false }}
          />
          <Stack.Screen
            name='Login'
            component={Login}
            options={{ headerShown: false }}
          />
          <Stack.Screen
            name='Home'
            component={Home}
            options={{ headerShown: false }}
          />
          <Stack.Screen
            name='TermsAndConditions'
            component={TermsAndConditions}
            options={{ headerShown: false }}
          />
      </Stack.Navigator>
    </NavigationContainer>
  );
  }
}

firebase.js:

import { initializeApp } from 'firebase/app';
import { initializeAuth, getReactNativePersistence } from 'firebase/auth';
import AsyncStorage from "@react-native-async-storage/async-storage"

const firebaseConfig = {
.... my config here ....
};

export const app = initializeApp(firebaseConfig);

export const auth = initializeAuth(app, { 
  persistence: getReactNativePersistence(AsyncStorage) 
});

useAuth.js:

import { useEffect, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../config/firebase';
 
export default function useAuth() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const unsub = onAuthStateChanged(auth, (user) => {
      console.log("Got User:", user);
      if (user) {
        setUser(user)
      } else {
        setUser(null)
      }
    });
    return unsub
  }, []);
  return { user };
}

Let me know if you need Login.js or my Register.js for more context

Express default route crashing app – Missing parameter name at path-to-regexp

please I need help.

My default route in Express is causing the app to crash instead of handling unmatched routes. Below is the error I’m getting:

    C:UsersJohn Doewilliampioneer_students_backendnode_modulespath-to-regexpdistindex.js:73
    throw new TypeError(`Missing parameter name at ${i}: ${DEBUG_URL}`);
    ^

TypeError: Missing parameter name at 1: https://git.new/pathToRegexpError
    at name (C:UsersJohn Doewilliampioneer_students_backendnode_modulespath-to-regexpdistindex.js:73:19)
    at lexer (C:UsersJohn Doewilliampioneer_students_backendnode_modulespath-to-regexpdistindex.js:91:27)
    ...
[nodemon] app crashed - waiting for file changes before starting...

here is my code

const express = require("express");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const rateLimit = require("express-rate-limit");
const helmet = require("helmet");

const memberRouter = require("./router/memberRouter");
const stateRouter = require("./router/stateRouter");
const adminRouter = require("./router/adminRouter");
const customError = require("./utils/customError");
const globalErrorHandler = require("./controller/errorController");

const app = express();

const loginLimiter = rateLimit({
  max: 10,
  windowMs: 60 * 60 * 1000,
  message:
    "We have received too many request from this IP. Please try again after one hour.",
});

const generalLimiter = rateLimit({
  max: 100,
  windowMs: 60 * 60 * 1000,
  message:
    "We have received too many request from this IP. Please try again after one hour.",
});

app.use(
  cors({
    // origin: "https://pioneer-students-of-st-marks-sec-sch.netlify.app",
    origin: "http://localhost:5173",
    credentials: true,
  })
);
app.use(cookieParser());
app.use(express.json({ limit: "10kb" }));
app.use(helmet());

app.use("/api/v1/register", generalLimiter, memberRouter);
app.use("/api/v1/states", generalLimiter, stateRouter);
app.use("/api/v1/admin", loginLimiter, adminRouter);

app.all("*", (req, res, next) => {
  const err = new customError(
    `Can't find the url ${req.originalUrl} on this server`,
    404
  );

  next(err);
});

app.use(globalErrorHandler);
module.exports = app;



const express = require("express");
const multer = require("multer");
const { storage } = require("./../config/cloudinaryConfig");
const upload = multer({ storage });

const {
  getUsers,
  createUser,
  updateUser,
  deleteUser,
  getUser,
  getSearchedUsers,
} = require("./../controller/memberController");
const { protect } = require("./../controller/adminController");

const router = express.Router();

// routes

router.route("/search").get(getSearchedUsers);
router
  .route("/")
  .get(getUsers)
  .post(protect, upload.single("profilePic"), createUser);

router
  .route("/:id")
  .get(getUser)
  .patch(upload.single("profilePic"), updateUser)
  .delete(protect, deleteUser);

module.exports = router;


const express = require("express");
const {
  getAllAdmins,
  signup,
  updateAdmin,
  deleteAdmin,
  login,
  logout,
  protect,
  verified,
} = require("../controller/adminController");

const router = express.Router();

router.route("/").get(getAllAdmins);
router.route("/protected").get(protect, (req, res) => {
  res.json({
    id: req.admin.id,
    firstName: req.admin.firstName,
  });
});
router.route("/signup").post(signup);
router.route("/login").post(login);
router.route("/logout").post(logout);
router.route("/verify").get(protect, verified);
router.route("/:id").patch(updateAdmin).delete(deleteAdmin);

module.exports = router;


const express = require("express");

const {
  CreateStates,
  getAllStates,
  updateState,
  deleteState,
} = require("../controller/stateController");

const router = express.Router();

router.route("/").get(getAllStates).post(CreateStates);
router.route("/:id").patch(updateState).delete(deleteState);

module.exports = router;


const { cloudinary } = require("../config/cloudinaryConfig");
const Members = require("../modal/memberModel");
const CustomError = require("../utils/customError");
const asyncErrorHandler = require("./../utils/asyncErrorHandler");

exports.getUsers = asyncErrorHandler(async (req, res, next) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 2;

  const members = await Members.find(
    {},
    "firstName lastName email phone profilePic"
  )
    .skip((page - 1) * limit)
    .limit(limit);

  const total = await Members.countDocuments();
  res.status(200).json({
    status: "success",
    count: members.length,
    data: {
      members,
      total,
      page,
      totalPages: Math.ceil(total / limit),
    },
  });
});

exports.createUser = asyncErrorHandler(async (req, res, next) => {
  let profilePicUrl = null;

  if (req.file) {
    const result = await cloudinary.uploader.upload(req.file.path, {
      folder: "profilePics",
    });

    profilePicUrl = { url: result.secure_url, public_id: result.public_id };
  }
  const memberData = { ...req.body, profilePic: profilePicUrl };

  const newMember = await Members.create(memberData);

  res.status(201).json({
    status: "success",
    message: "Member successfully created",
    data: {
      newMember,
    },
  });
});

exports.updateUser = asyncErrorHandler(async (req, res, next) => {
  let updatedData = { ...req.body };

  const updateMember = await Members.findById(req.params.id);

  if (!updateMember) {
    return next(
      new CustomError("Member not found. Please provide a valid ID", 404)
    );
  }

  if (req.file) {
    if (updateMember.profilePic && updateMember.profilePic.public_id) {
      await cloudinary.uploader.destroy(updateMember.profilePic.public_id);
    }

    const uploadResult = await new Promise((resolve, reject) => {
      cloudinary.uploader
        .upload_stream(
          {
            folder: "profile_pics",
          },
          (error, result) => {
            if (error) reject(error);
            else resolve(result);
          }
        )
        .end(req.file.buffer);
    });
    updatedData.profilePic = {
      url: uploadResult.secure_url,
      public_id: uploadResult.public_id,
    };
  }

  const updatedMember = await Members.findByIdAndUpdate(
    req.params.id,
    updatedData,
    {
      new: true,
      runValidators: true,
    }
  );

  res.status(200).json({
    status: "success",
    data: {
      updatedMember,
    },
  });
});

exports.deleteUser = asyncErrorHandler(async (req, res, next) => {
  const deleteMember = await Members.findById(req.params.id);
  if (!deleteMember) {
    return next(
      new CustomError("Member not found. Please provide a valid ID", 400)
    );
  }
  if (deleteMember.profilePic) {
    const parts = deleteMember.profilePic.split("/");
    const fileName = parts[parts.length - 1];
    const publicId = fileName.split(".")[0];
    await cloudinary.uploader.destroy(publicId);
  }
  await Members.findByIdAndDelete(req.params.id);
  res.status(201).json({
    message: "Member deleted successfully",
  });
});

exports.getSearchedUsers = asyncErrorHandler(async (req, res, next) => {
  const { lastName } = req.query;

  const searchedMembers = await Members.find(
    { lastName },
    "firstName lastName email phone profilePic"
  );
  if (searchedMembers.length === 0) {
    return next(
      new CustomError(
        "No member with the given surname was found. Please provide the correct surname",
        400
      )
    );
  }
  res.status(200).json({
    status: "Success",
    data: {
      searchedMembers,
    },
  });
});

exports.getUser = asyncErrorHandler(async (req, res, next) => {
  const member = await Members.findById(req.params.id);
  if (!member) {
    return next(
      new CustomError("User not found. Please provide a valid ID", 400)
    );
  }
  res.status(200).json({
    status: "Success",
    data: {
      member,
    },
  });
});


const CustomError = require("../utils/customError");
const States = require("./../modal/stateModel");
const asyncErrorHandler = require("./../utils/asyncErrorHandler");

exports.CreateStates = asyncErrorHandler(async (req, res, next) => {
  const createdStates = await States.create(req.body);
  res.status(201).json({
    status: "success",
    data: {
      states: createdStates,
    },
  });
});

exports.getAllStates = asyncErrorHandler(async (req, res, next) => {
  const getStates = await States.find({ isActive: true })
    .select("state value localGovernments")
    .sort({ state: 1 });
  res.status(200).json({
    data: {
      getStates,
    },
  });
});

exports.updateState = asyncErrorHandler(async (req, res, next) => {
  const UpdatedState = await States.findByIdAndUpdate(req.params.id, req.body, {
    new: true,
    runValidators: true,
  });
  if (!UpdatedState) {
    return next(new CustomError("State not found", 404));
  }
  res.status(200).json({
    status: "success",
    data: {
      UpdatedState,
    },
  });
});

exports.deleteState = asyncErrorHandler(async (req, res, next) => {
  const id = req.params.id;
  const deleteState = await States.findByIdAndUpdate(
    id,
    { isActive: false },
    { new: true, runValidators: true }
  );

  if (!deleteState) {
    return next(new CustomError("State not found", 404));
  }

  res.status(200).json({
    status: "success",
  });
});


const Admin = require("./../modal/adminModel");
const jwt = require("jsonwebtoken");
const util = require("util");
const asyncErrorHandler = require("./../utils/asyncErrorHandler");
const CustomError = require("../utils/customError");

// console.log(require("crypto").randomBytes(64).toString("hex"));

const signToken = (id, res) => {
  const token = jwt.sign({ id }, process.env.SECRET_WORD, {
    expiresIn: process.env.LOGIN_EXPIRES,
  });

  res.cookie("jwt", token, {
    httpOnly: true,
    sameSite: "strict",
    maxAge: 24 * 60 * 60 * 1000,
    secure: process.env.NODE_ENV !== "development",
  });
};

exports.getAllAdmins = asyncErrorHandler(async (req, res, next) => {
  const allAdmins = await Admin.find();
  res.status(200).json({
    status: "success",
    count: allAdmins.length,
    data: {
      allAdmins,
    },
  });
});

exports.signup = asyncErrorHandler(async (req, res, next) => {
  const newAdmin = await Admin.create(req.body);

  const token = signToken(newAdmin._id, res);

  res.status(200).json({
    status: "success",
    token,
    data: {
      newAdmin,
    },
  });
});

exports.updateAdmin = asyncErrorHandler(async (req, res, next) => {
  const updateAdminData = await Admin.findByIdAndUpdate(
    req.params.id,
    req.body,
    {
      new: true,
      runValidators: true,
    }
  );

  if (!updateAdminData) {
    return next(
      new CustomError("Admin not found. please provide a valid ID", 400)
    );
  }

  res.status(200).json({
    status: "Success",
    data: {
      updateAdminData,
    },
  });
});

exports.deleteAdmin = asyncErrorHandler(async (req, res, next) => {
  const deleteAdminData = await Admin.findByIdAndDelete(req.params.id);
  if (!deleteAdminData) {
    return next(
      new CustomError("Admin not found. Please provide a valid ID", 400)
    );
  }

  res.status(201).json({
    status: "success",
  });
});

exports.login = asyncErrorHandler(async (req, res, next) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return next(new CustomError("Please provide Email and Password", 400));
  }

  const adminLogin = await Admin.findOne({ email }).select("+password");

  const isMatch = await adminLogin.comparePassword(
    password,
    adminLogin.password
  );

  if (!adminLogin || !isMatch) {
    return next(
      new CustomError(
        "Password does not match. please provide a correct password",
        400
      )
    );
  }

  const token = signToken(adminLogin._id, res);

  res.status(200).json({
    status: "success",
    token,
    data: {
      name: adminLogin.firstName,
    },
  });
});

exports.protect = asyncErrorHandler(async (req, res, next) => {
  const token = req.cookies.jwt;

  if (!token) {
    return next(new CustomError("You are not loggedIn. Please login", 401));
  }

  const decodedToken = await util.promisify(jwt.verify)(
    token,
    process.env.SECRET_WORD
  );

  const currentUser = await Admin.findById(decodedToken.id);
  if (!currentUser) {
    return next(new CustomError("Admin with given token does not exit", 401));
  }

  req.admin = currentUser;
  next();
});

exports.logout = (req, res) => {
  res.cookie("jwt", "", {
    httpOnly: true,
    sameSite: "strict",
    secure: process.env.NODE_ENV !== "development",
    expires: new Date(0),
  });

  res.status(200).json({
    status: "success",
    message: "Logout successful",
  });
};

exports.verified = (req, res) => {
  res.status(200).json({
    status: "success",
    data: {
      username: req.admin.firstName,
    },
  });
};


function dev(res, error) {
  res.status(error.statusCode).json({
    status: error.status,
    message: error.message,
    stackTrace: error.stack,
    
  });
}

function prod(res, error) {
  if (isOperational) {
    res.status(error.statusCode).json({
      status: error.status,
      message: error.message,
    });
  } else {
    res.status(error.statusCode).json({
      status: "error",
      message: "Something went wrong. Please try again later",
    });
  }
}

module.exports = (error, req, res, next) => {
  error.statusCode = error.statusCode || 500;
  error.status = error.status || "fail";

  if (process.env.NODE_ENV === "development") {
    dev(res, error);
  }

  if (process.env.NODE_ENV === "production") {
    prod(res, error);
  }
};

Observation

The crash happens only when a route is not matched (i.e., hits app.all(“*”)).

The error refers to path-to-regexp, which is used internally by Express.

I don’t use any malformed dynamic route like /: anywhere as far as I can tell.

What I’ve Tried
Commented out app.all(“*”) and the app doesn’t crash anymore.

Checked my routers for malformed paths like /:, but I couldn’t find any.

Question

Why is my app.all(“*”) causing the Missing parameter name error?

Is there something wrong with how my routes are defined?

How do I properly define a catch-all route without causing this crash?

Thank You

How can I use Tone.js to analyze uploaded audio files more effectively?

I’m working on a web project that involves uploading audio files and analyzing them using Tone.js. Right now, I can play the uploaded audio without issues, but I’m not sure how to perform deeper analysis, like getting frequency data, amplitude levels or pitch detection.
I’d also like to eventually visualize this data.
Any advice, examples or direction would be apreciated

MUI X Datagrid Resets on Row Selection

I’m using MUI X Datagrid in my application, where a list of files and folders are displayed. I have enabled row selection for files, but whenever a row is being selected the datagrid resets and it scrolls back to the top. For example if I select 100th row for each selection it scrolls back to the very top i.e 1st row. I have to scroll back again all the way down to make the next selection. Im adding the code below. I searched the docs, they have the exact same code. Doesnt seem to be of any help. How do I fix this?

const [selectedFilter, setSelectedFilter] = useState({
      type: 'include',
      ids: new Set(),
    }); // has files selected for export in grid


<CustomDataGrid
                        showToolbar
                        disableColumnMenu={true}
                          rows={Array.isArray(folderContents.folderData) && Array.isArray(folderContents.fileData)
                            ? [...folderContents.folderData, ...folderContents.fileData]
                            : []}
                          columns={fileColumns}
                          slots={{
                            toolbar: CustomToolbar,
                            noRowsOverlay: (() => {
                              return (
                                <Box
                                  sx={{
                                    display: 'flex',
                                    flexDirection: 'column',
                                    alignItems: 'center',
                                    justifyContent: 'center',
                                    height: '100%',
                                    '& .no-rows-primary': {
                                      fill: '#3D4751',
                                    },
                                    '& .no-rows-secondary': {
                                      fill: '#1D2126',
                                    },
                                    '& .MuiDataGrid-virtualScroller': {
                                      overflowY: 'auto',
                                      scrollBehavior: 'smooth',
                                      maxHeight: '20rem',
                                      paddingRight: '0.5rem',

                                      
                                    },
                                  }}
                                > No folders or files</Box>)
                            }),
                          }}
                          pagination
                          initialState={{
                            pagination: {
                                paginationModel: {
                                pageSize: 20,
                                },
                            },
                          }}
                          pageSizeOptions={[5,10,20,50,100]}
                          checkboxSelection
                          onRowClick={(params) => {
                            setSelectedFiles([])
                            setSelectedFilter({
                              type: 'include',
                              ids: new Set(),
                            })
                            if(params.row.type === 'Folder'){
                              setIsClickedFromBreadcrumbs(false)
                              setFolderBreadcrumbs((currState) => {
                                return [...currState, {id:params.row.id, name: params.row.name}]
                              })
                            }
                          }}
                          isRowSelectable={(params) => params.row.type !== 'Folder'}
                          getRowClassName={(params) => {
                            return params.row.type === 'Folder' ? 'hide-checkbox' : '';
                          }}
                          onRowSelectionModelChange={
                            (newSelectionModel) => {
                              console.log(newSelectionModel)
                              const currSelectedFilter = [...folderContents.folderData, ...folderContents.fileData].filter((file) => Array.from(newSelectionModel.ids).includes(file.id));
                              setSelectedFilter(newSelectionModel);
                              const selected = currSelectedFilter.map((ele)=> 
                                [ele.name, ele.url,ele.type, `${moment(ele.createdAt.split('+')[0]).utc().format('L LT')} PDT`, folderBreadcrumbs[folderBreadcrumbs.length -1].name ] 
                              );                            
                              setSelectedFiles(selected);
                            }
                          }
                          rowSelectionModel={selectedFilter}
    
                          sx={{
                            height: '100%',
                            cursor: 'pointer',
                            borderRadius: '8px',
                           
                          }}
                          
                      />

Title: 404 Error for main.tsx When Deploying Vite React App to GitHub Pages

Body:

I’m trying to deploy a Vite React application to GitHub Pages at https://elgendy-store.github.io/Store/, but I’m encountering a persistent 404 error for main.tsx in the browser console. The site loads a blank page, and the network tab shows the server can’t find main.tsx, even though the compiled assets (e.g., assets/index-C3ZZHLQ7.js) exist in the dist/ folder locally after building.

Details:
Project Setup: Vite + React, with base: ‘/Store/’ set in vite.config.ts.
Build Process: Running npm run build generates a dist/ folder containing index.html, 404.html, and an assets/ folder with compiled JS and CSS files (e.g., index-C3ZZHLQ7.js, index-bAlYlLZN.css).
Deployment: I’ve tried:
npx gh-pages -d dist (default deployment).
npx gh-pages -d dist –dest docs with GitHub Pages source set to main branch /docs.
Updated package.json with “homepage”: “https://elgendy-store.github.io/Store” and “deploy”: “gh-pages -d dist”.
GitHub Pages Settings: Source is set to main branch / (root) or /docs, depending on the deployment method.
Console Error: Failed to load resource: the server responded with a status of 404 () for main.tsx.
Local Test: Opening dist/index.html locally works fine, loading the assets without 404s.
Repository: https://github.com/Elgendy-Store/Store
What I’ve Tried:
Rebuilt the project with rm -rf node_modules/.vite dist and npm install followed by npm run build.
Ensured vite.config.ts has base: ‘/Store/’.
Added a public/ folder with vite.svg to match the favicon reference.
Committed all changes and pushed to the repo.
Expected Behavior:
The site should load at https://elgendy-store.github.io/Store/, with the React app rendering and assets (e.g., assets/index-C3ZZHLQ7.js) loading correctly.

Actual Behavior:
Blank page with a 404 error for main.tsx in the console, and the Network tab shows it’s looking for the source file instead of the compiled asset.

Question:
Why is GitHub Pages serving a 404 for main.tsx instead of the compiled assets/index-C3ZZHLQ7.js, and how can I fix this deployment issue?

Any help or suggestions would be greatly appreciated!

Trying to make an updating timeseries with working show/hide functions from legend with Apexcharts.js

I was looking for it in the documentation, but there didn’t seem to be anything on it: how would I make it so the built in legend buttons toggle and highlight functions work for an updating timeseries? How it seems to be happening on default is that the function will work but then update to the default show on the next tick. I was considering just making a whole other button system with hideSeries() and showSeries(), but it would be convenient to just use the built in legend…

Also, how could I make an appending timeseries that’s at a set width but the tickmarks on the x-axis just get smaller as necessary? (maybe just use appendSeries?)

Why is javascript not running code from VS Code to the console in Google Chrome?

I’m currently having trouble completing an entry level Javascript course. Javascript is not running from Visual Studio Code to my Google Chrome console.

I don’t have any extensions downloaded and all my software is updated. Maybe my computer model is outdated. Any help would be appreciated.

Thank You,

-Nate

I tried rebooting the programs that were suggested. What I expected is for the console to receive the code. The console should’ve had javascript noted on the right hand side. The code didn’t transfer over as it should have.

is there a way to code customization page for shirts [closed]

i want to create a page on a website where that allows the users to choose any color from the color wheel and when they choose it . Im coding a customization page for shirts where they can choose a color and and the shirt color will change but i having fault where the background color is changing im still very new in this field and want to learn is there anyone who can help me im using html and css

How to create a JS event for a button in a modularized app?

I wanted to insert buttons into a DataTable and found this very helpful code. Just copy pasting it in the simplest case works like a charm, however, I cannot adapt it to my modularized situation. I am attaching my code with some very minor adaptations to keep everything shorter. None of this should lead the code to break though, as I have tested the same adaptations on the non-modularized variant (no intermediate data frame, simpler data retrieval process, no abstracted button generator function).

library(shiny)
library(DT)
library(tibble)

uiModuleImpl <- function(id) {
  ns <- NS(id)
  
  tabPanel(
    title = "Dummy title",
    DTOutput(ns("dummyDT")),
    textOutput(ns("myText")),

    value = id
  )
}

serverModuleImpl <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    
    output$dummyDT <- renderDT({
      dummyData <- tibble(
        "Col A" = c(2000, 1994),
        "Col B" = c(2019, 2023),
      )

      dummyData$Calculate <- vapply(X=1:2, function(i) {
        as.character(
          actionButton(
            inputId = ns(paste0("actionButton_", i)),
            label = "Calculate",
            onclick = 'Shiny.setInputValue("idxToProcess", i, {priority: "event"})')) # does not work
            # onClick = sprintf('Shiny.setInputValue("%s", i, {priority: "event"})', ns("idxToProcess")))) # tried some variants of accessing the namespace, also does not work
      }, character(1))
      
      dummyData
    },
    
      escape = F,
      selection = "none"
    )
    
    observe({
      print(paste("idx =", input$idxToProcess))
    })

    output$myText <- renderText({
      req(input$idxToProcess)
      paste("idx =", input$idxToProcess)
    })
  })
}

ui <- fluidPage(
  uiModuleImpl("someNamespace")
)

server <- function(input, output, session) {
  serverModuleImpl("someNamespace")
}

shinyApp(ui = ui, server = server)

The solution is probably simply that the onClick event writes into the wrong namespace. I am a very inexperienced JS developer though and have not managed to find just where exactly I would find this variable, though.

Real-world examples of using an Abstract Factory in Javascript? [closed]

I know that we can encounter Abstract Factory in OOP languages like Java, C#, but it’s hard to imagine the real-world usage in Frontend. Nevertheless, countless guides and recommendations suggest that a JavaScript developer might still need this. Speaking of factories, we could use a factory method that creates an API instance with interceptors (e.g. authentication):

const apiInstance = API.withInterceptors(AUTH_INTERCEPTOR, LOG_INTERCEPTOR);

// ...
class API {
// ...

  static withInterceptors(...interceptors) {
    const instance = axios.create();

    // here we can add the interceptors

    return instance;
  }
}

We could theoretically create an abstract factory on Node.js for an abstract DB connection and ORM library, but this is not the case for frontend. Is there anything suitable for the UI part?

Weather hourly forecast with React and TypeScript

I try to only display the next 5 hours based on the current time in my weather app, but I don’t know how do this.

This is my code:

   <div className="hour_forecast_container">
        {weatherData.forecast.forecastday[0].hour.map((i) => (
              <div>
              <div className="hour_container">
                <div>
                <p key={i.temp_c}>{i.temp_c}°C</p>
                <img src={i.condition.icon} height={"28px"} width={"28px"}/>
                <p key={i.time}>{convertDate(i.time)}</p>
                </div>
           </div>
           </div>
        ))}
        </div>

(the time is a type string).

`import.meta.dirname` and `import.meta.filename` are `undefined` when using `ts-jest`

I’m trying to move a TypeScript project from CJS to ESM and, along with that, our tests. They’re using ts-jest to run, and used to use __dirname and __filename, but in line with the change to ESM, I’ve changed them to use import.meta.dirname and import.meta.filename.

The problem seems to be that, when I run this with ts-jest, it’s always undefined. I’ve checked and import.meta.url is defined, but this would mean that I’d have to use fileURLToPath(new URL(".", import.meta.url)) everywhere to get the __dirname.

I’ve run the same files with ts-node and they are defined, which confuses me further. I’ve also checked this in the examples folder of the official repository of ts-jest, and it’s also not defined or available when running with a "module": "nodenext" setting.

Here is the important part of the tsconfig.json of my project:

{
  "compilerOptions": {
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "target": "esnext",
    "isolatedModules": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
  },
}

Is this because of a setting I’ve missed, or is this a bug with ts-jest that I should report?