Cannot create route’s draggabe line in leaflet routing

I’m creating a method for map class which responsible for plotting route on map and later be edited by dragging it. L.Routing.Control I do not consider as an option since it treats path’s coordinates as waypoints (both waypoints and plan option) and if disable waypoints we won’t be able to create new later when dragging the route. Now I’m trying to use L.Routing.Line since in docs it says Displays a route on the map, and allows adding new waypoints by dragging the line. which looks like what I need, but when I try to create on using following code

public addRoute(pathCoordinates: [number, number][]): void {
    const latLngPath = pathCoordinates.map(coord => new L.LatLng(coord[0], coord[1]));

    const routeLine = L.Routing.line({
        coordinates: latLngPath,
        waypoints: [latLngPath[0], latLngPath[latLngPath.length - 1]],
    }).addTo(this.map); 
}

I always got this error

Uncaught TypeError: wps is undefined
_findWaypointIndices leaflet-routing-machine.js:16984
_getWaypointIndices leaflet-routing-machine.js:17061
_extendToWaypoints leaflet-routing-machine.js:17011
initialize leaflet-routing-machine.js:16967
NewClass Class.js:24
line leaflet-routing-machine.js:16595
debugger eval code:1
addRoute mapService.ts:215

My guess that wps stands for waypoints, but even if I send waypoints: [] I’m still getting same error.
So the question is how to fix this creation problem or what another alternative for setting the route on the map and then changing it by dragging it.

Execute JSP containing JavaScript in background

I have a logic to generate pdf written in js in my JSP.

AutoDownloadPDF.jsp:

setInterval(function() {
        $.ajax({
        type: "POST",
        url: "GetInvoicesNo.jsp?EntityID=40&MappingID=<%=getMappingID%>",
        async: false,
        success: function(data){    
        var splitData =data.trim().split(',');
                $.each(splitData, function(index, value){
                if(value.trim()!=''){
                var url="GeneratePDF.jsp?EntityCode=<%=getEntityCode%>&InvoiceNo="+value;
        var printWindow = window.open(url,"_blank");
                 }
                        
            });     
                    
    }
    }); 
}, 90000);          

Current Setup:

I’m triggering AutoDownloadPDF.jsp through a Windows batch script like this:

msedge --app=http://localhost:8088/APP/AutoDownloadPDF.jsp 

The process works as intended; however, this method is unsuitable for my server environment because the server may log off, which causes Microsoft Edge to close and interrupts the process.

I tried tools like HTMLUnit and Playwright but didn’t work for me. It seems the problem is that the JSP depends heavily on browser-based JavaScript. Are there any tools or approaches that can handle this effectively?

Running jest in nest js project is taking a lot of heap memory

I am trying to run unit test on my project which is written with nest js framework. Irrespective of unit tests it is taking almost 4 gb of heap memory which is unexpected.

This is my jest.config.ts:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  testMatch: ['**/*-test.ts', '**/**spec.ts', '.*\.spec\.ts$'],
  globalSetup: './spec/jest.setup.ts',
  globalTeardown: './spec/teardown.js',
  reporters: ['default', 'jest-junit'],
  moduleNameMapper: {
    '^apps/(.*)$': '<rootDir>/apps/$1',
    '^common/(.*)$': '<rootDir>/common/$1'
  },
  setupFilesAfterEnv: ['<rootDir>/spec/jest.setup.redis-mock.ts', '<rootDir>/apps/events/jest.setup.ts'],
  moduleFileExtensions: ['js', 'json', 'ts'],
  modulePaths: ['<rootDir>'],
  rootDir: '.',
  transform: {
    '^.+\.(t|j)s$': [
      'ts-jest',
      {
        diagnostics: false
      }
    ]
  },
  collectCoverageFrom: ['**/*.(t|j)s'],
  coverageDirectory: './coverage',
  roots: ['<rootDir>', '<rootDir>/apps/'],
  testPathIgnorePatterns: [
    '/node_modules/',
    '/dist/'
  ]
}

While running with node --no-compilation-cache --inspect-brk -r node_modules/.bin/jest --runInBand apps/events/src/events.controller.spec.ts command, I saw it has already occupied 4gb memory even before my globalSetup is initialized. Not sure why!

This is my tsconfig.json:

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2020",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "paths": {
      "apps/*": [
        "./apps/*"
      ],
      "common/*": [
        "./common/*"
      ]
    },
    "resolveJsonModule": true
  }
}

This is my apps/events/events.controller.spec.ts:

// import { Test, TestingModule } from '@nestjs/testing'
// import { EventsController } from './events.controller'

describe('EventsController', () => {

  describe('root', () => {
    it('should return "Hello World!"', () => {
      expect(true).toBe(true)
    })
  })
})

which is a very basic test case and should not require to load this much memory.

I am not sure if during initialization of test cases the libraries (my node_modules size is 2.2 gb) are loaded or not, if so what can I do. This is my package.json dependencies:

"dependencies": {
        "@analytics/google-analytics": "^0.5.3",
        "@azure/msal-node": "^2.16.2",
        "@babel/parser": "^7.24.6",
        "@clickhouse/client": "^1.6.0",
        "@dqbd/tiktoken": "^1.0.7",
        "@google-cloud/bigquery": "^5.12.0",
        "@google-cloud/dialogflow": "^5.8.0",
        "@google-cloud/logging-winston": "^4.0.4",
        "@google-cloud/monitoring": "^3.0.3",
        "@google-cloud/pubsub": "^2.15.1",
        "@google-cloud/pubsub_v3": "npm:@google-cloud/[email protected]",
        "@google-cloud/pubsub_v4": "npm:@google-cloud/[email protected]",
        "@google-cloud/secret-manager": "^5.0.1",
        "@google-cloud/storage": "^5.13.1",
        "@google-cloud/storage_v2": "npm:@google-cloud/[email protected]",
        "@google-cloud/tasks": "0.4.0",
        "@google-cloud/tasks_v3": "npm:@google-cloud/[email protected]",
        "@mhoc/axios-digest-auth": "^0.8.0",
        "@microsoft/microsoft-graph-client": "^3.0.5",
        "@mozilla/readability": "^0.4.4",
        "@nestjs/axios": "^3.0.2",
        "@nestjs/common": "^10.3.7",
        "@nestjs/config": "^3.2.2",
        "@nestjs/core": "^10.3.7",
        "@nestjs/mongoose": "^7.2.4",
        "@nestjs/platform-express": "^10.3.7",
        "@nestjs/swagger": "^7.3.1",
        "@types/bcrypt": "^3.0.0",
        "@types/bunyan": "^1.8.6",
        "@types/facebook-js-sdk": "^3.3.5",
        "@types/fluent-ffmpeg": "^2.1.20",
        "@types/google-libphonenumber": "^7.4.20",
        "@types/handlebars": "^4.0.37",
        "@types/json2csv": "^5.0.3",
        "@types/jsonwebtoken": "^8.5.1",
        "@types/lodash": "^4.14.168",
        "@types/mailgun-js": "^0.22.12",
        "@types/moment-timezone": "^0.5.30",
        "@types/multer": "^1.4.7",
        "@types/passport-local-mongoose": "^6.1.0",
        "@types/shortid": "^0.0.29",
        "@types/simple-oauth2": "^4.1.1",
        "@types/valid-url": "^1.0.3",
        "analytics": "^0.7.5",
        "atob": "^2.1.2",
        "authorizenet": "^1.0.8",
        "await-to-js": "^3.0.0",
        "aws-sdk": "^2.906.0",
        "axios": "^0.21.1",
        "basic-auth": "2.0.1",
        "bcrypt": "^5.0.1",
        "class-transformer": "0.4.0",
        "class-validator": "^0.13.1",
        "compression": "^1.7.4",
        "convert-array-to-csv": "^2.0.0",
        "cookie-parser": "^1.4.5",
        "crypto-js": "^3.1.9-1",
        "csvtojson": "^2.0.10",
        "currency.js": "^2.0.4",
        "date-fns": "2",
        "date-fns-tz": "2",
        "dialogflow": "^0.8.0",
        "dotenv-safe": "^8.2.0",
        "elasticsearch": "^16.7.2",
        "emoji-regex": "^10.3.0",
        "eslint-plugin-import": "^2.29.1",
        "fast-xml-parser": "^4.1.2",
        "fb": "^2.0.0",
        "firebase-admin": "12.1.0",
        "fluent-ffmpeg": "^2.1.2",
        "form-data": "^4.0.0",
        "fs": "^0.0.1-security",
        "geoip-country": "^4.1.9",
        "google-auth-library": "^7.10.1",
        "google-libphonenumber": "3.2.34",
        "google-spreadsheet": "^4.1.2",
        "googleapis": "^92.0.0",
        "handlebars": "^4.7.8",
        "handlebars-intl": "^1.1.2",
        "heapdump": "^0.3.15",
        "html-to-text": "^8.0.0",
        "ics": "^2.35.0",
        "id-shorter": "^0.1.2",
        "intuit-oauth": "^4.0.0",
        "ioredis": "^4.16.0",
        "isbot": "^5.1.6",
        "isomorphic-fetch": "^3.0.0",
        "javascript-obfuscator": "^4.1.0",
        "jest-junit": "^13.0.0",
        "jimp": "^0.22.10",
        "joi": "^17.4.0",
        "jsdom": "^19.0.0",
        "json-bigint": "^1.0.0",
        "json2csv": "^6.0.0-alpha.2",
        "jsonwebtoken": "^8.5.1",
        "jstoxml": "^3.2.6",
        "langfuse": "^3.24.0",
        "lodash": "4.17.19",
        "luxon": "^3.4.4",
        "mailgun-js": "^0.22.0",
        "mailgun.js": "^7.0.1",
        "marked": "^13.0.2",
        "md5": "^2.3.0",
        "metadata-scraper": "^0.2.61",
        "migrate-mongo": "^8.2.2",
        "mime-types": "^2.1.35",
        "mjml": "^4.10.4",
        "moment": "^2.29.4",
        "moment-timezone": "^0.5.43",
        "mongo-escape": "^2.0.6",
        "mongoose": "5.12.13",
        "mongoose-extend-schema": "^1.0.0",
        "mongoose-long": "^0.5.1",
        "mongoose6": "npm:mongoose@^6.8.2",
        "mysql2": "^2.3.3",
        "node-forge": "^1.3.1",
        "node-ical": "^0.16.1",
        "parse-reply": "^0.0.4",
        "passport-local-mongoose": "^6.1.0",
        "path": "^0.12.7",
        "path-to-regexp": "^7.1.0",
        "pdf-lib": "^1.17.1",
        "prom-client": "^14.0.1",
        "promisify-any": "2.0.1",
        "psl": "^1.8.0",
        "puppeteer": "^22.7.1",
        "qs": "^6.10.1",
        "sanitize-html": "^2.13.0",
        "sequelize": "^6.37.3",
        "sharp": "^0.33.5",
        "simple-oauth2": "1.5.0",
        "ts-loader": "^9.2.3",
        "ts-node": "^9.1.1",
        "tsconfig-paths": "^3.9.0",
        "type-is": "1.6.18",
        "typescript": "^5.4.4",
        "ulid": "^2.3.0",
        "url": "^0.11.0",
        "uuid": "^8.3.2",
        "uuid-mongodb": "^2.5.1",
        "uuidv4": "^6.2.7",
        "vm2": "^3.9.17",
        "webpack": "^5.93.0",
        "winston": "^3.3.3",
    },
    "devDependencies": {
        "@nestjs/cli": "^10.3.2",
        "@nestjs/schematics": "^10.1.1",
        "@nestjs/testing": "^10.3.7",
        "@types/authorizenet": "^1.0.0",
        "@types/bcrypt": "^3.0.0",
        "@types/bunyan": "^1.8.6",
        "@types/cookie-parser": "^1.4.2",
        "@types/cron": "^2.0.0",
        "@types/express": "^4.17.11",
        "@types/facebook-nodejs-business-sdk": "^15.0.5",
        "@types/google-libphonenumber": "^7.4.20",
        "@types/ioredis": "^4.28.10",
        "@types/ioredis-mock": "^8.2.2",
        "@types/isomorphic-fetch": "^0.0.36",
        "@types/jest": "^26.0.20",
        "@types/jsonwebtoken": "^8.5.1",
        "@types/lodash": "^4.14.168",
        "@types/mailgun-js": "^0.22.12",
        "@types/mjml-core": "^4.7.1",
        "@types/moment-timezone": "^0.5.30",
        "@types/multer": "^1.4.7",
        "@types/node": "^18.11.18",
        "@types/psl": "^1.1.0",
        "@types/request-ip": "^0.0.37",
        "@types/ssh2-sftp-client": "^9.0.1",
        "@types/supertest": "^2.0.10",
        "@typescript-eslint/eslint-plugin": "^7.6.0",
        "@typescript-eslint/parser": "^7.5.0",
        "eslint": "^8.0.0",
        "eslint-config-prettier": "^8.1.0",
        "eslint-import-resolver-typescript": "^3.6.1",
        "eslint-plugin-prettier": "^3.3.1",
        "firestore-jest-mock": "^0.17.0",
        "husky": "^7.0.4",
        "ioredis-mock": "^6.13.0",
        "jest": "^29.7.0",
        "lint-staged": "^11.0.0",
        "mongodb-memory-server": "^8.8.0",
        "prettier": "^2.2.1",
        "pretty-quick": "^3.1.1",
        "rimraf": "^3.0.2",
        "supertest": "^6.1.3",
        "ts-jest": "^29.1.3",
        "ts-loader": "^8.0.17",
        "tsconfig-paths": "^3.9.0",
        "tslint": "^6.1.3"
    }
    ```

Will appreciate if someone can help!

How to to find CPU hot spot functions in bun.js?

My JS program is slow, I want to find functions that consume most CPU time.

How can I do that? No precise timing or advanced charting needed, just a rough estimate to find names of couple most time consuming functions.

Example – the script contains a problematic function c the profiler should help to find it:

function a() {
  const r: string[] = []
  for (let i = 0; i < 500; i++) r.push(b(i))
  return r
}

function b(n: number): string {
  return c(n)
}

const letters = 'abcdefghijklmnopqrstuvwxyz'
function c(n: number): string {
  const b: string[] = []
  for (let i = 0; i < n; i++) {
    b.push(letters[i % letters.length])
    b.sort() // <= Problem
  }
  return b.join('')
}

function run () { a() }

;(globalThis as any).run = run

P.S. I tried using built-in bun.js debugger, but it has no CPU hotspot information. I tried bun --inspect main.ts and then switching to “Timelines” and clicking on ‘Record’ button and then executed run() in the console, and when it finished clicked ‘Stop recording’. It created the dump with statistics, but I have not found any CPU timing information.

Why are numbers not enclosed in quotation marks when NormalizeText ؟

I am trying to make NormalizeText But there is a part in the output, which is the numbers, which are not enclosed in quotation marks, and they are the last lines in the code. this is my code

 public static string SerializeAndNormalizeReceipt(object receipt)
 {
     if (receipt == null)
         return string.Empty;

     string serializedData = JsonConvert.SerializeObject(receipt, Formatting.None);

     string normalizedData = NormalizeText(serializedData);

     return normalizedData;
 }

 public static string NormalizeText(string text)
 {
     if (string.IsNullOrEmpty(text))
         return string.Empty;

     string cleanedText = Regex.Replace(text, @"[:,]", "");

     string normalizedText = Regex.Replace(cleanedText, @"[a-z]", m => m.Value.ToUpper());

     normalizedText = Regex.Replace(normalizedText, @"[u0600-u06FF]+", m => m.Value);

     normalizedText = Regex.Replace(normalizedText, @"[{}[]]", "");

     normalizedText = Regex.Replace(normalizedText, @"s+(?=[a-zA-Z0-9])", "");

     return normalizedText;
 }

and this is my output

"HEADER""DATETIMEISSUED""2024-12-30T173749""RECEIPTNUMBER""HAZ002""UUID""""PREVIOUSUUID""""REFERENCEOLDUUID""""CURRENCY""EGP""EXCHANGERATE"0"DOCUMENTTYPE""RECEIPTTYPE""S""TYPEVERSION""1.2""SELLER""RIN""332460843""COMPANYTRADENAME""سعاد محمد صالح حسن""BRANCHCODE""ABC""DEVICESERIALNUMBER""CWX02618""ACTIVITYCODE""8620""BRANCHADDRESS""COUNTRY""EG""GOVERNATE""CAIRO""REGIONCITY""CITYCENTER""STREET""16STREET""BUILDINGNUMBER""14BN""BUYER""TYPE""F""ID""313717919""NAME""TAXPAYER1""MOBILENUMBER""+201020567462""PAYMENTNUMBER""987654""ITEMDATA""INTERNALCODE""NA""DESCRIPTION""MEDICALCAREFORTHEELDERLY""ITEMTYPE""EGS""ITEMCODE""EG-332460843-M3""UNITTYPE""EA""QUANTITY"1"UNITPRICE"200"NETSALE"200"TOTALSALE"200"TOTAL"200"COMMERCIALDISCOUNTDATA""AMOUNT"0"DESCRIPTION""NODISCOUNT""RATE"0"ITEMDISCOUNTDATA""AMOUNT"0"DESCRIPTION""NODISCOUNT""RATE"0"TAXABLEITEMS""TAXTYPE""T1""AMOUNT"28"SUBTYPE""V009""RATE"14"TOTALSALES"200"TOTALCOMMERCIALDISCOUNT"0"TOTALITEMSDISCOUNT"0"EXTRARECEIPTDISCOUNTDATA""AMOUNT"0"DESCRIPTION""NODISCOUNT""RATE"0"NETAMOUNT"200"FEESAMOUNT"0"TOTALAMOUNT"228"TAXTOTALS""TAXTYPE""T1""AMOUNT"28"PAYMENTMETHOD""C""ADJUSTMENT"0"CONTRACTOR""NAME""CONTRACTOR1""AMOUNT"0"RATE"0

CSS Keyframe Continuous Horizontal Scroll buffering on loop start

I have programmed a continuous horizontal text scroll using CSS @keyframes and two identical div tags.

The issue I am facing is when the loop starts again, there is a small, but noticeable, pause before the text scrolls again. I would like the scroll to be continuous with no pause, even whether that means to not use CSS @keyframes and instead javascript/jQuery.

My code is below.

HTML

<div id="scrolling-header-parent-container">
   <div id="scrolling-header-container">
      <div class="scrolling-header-container-item">
         AUTHENTIC VIETNAMESE FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;INDIAN CUISINE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHURROS & COFFEE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;BUBBLE TEA&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;ESCAPE ROOM EXPERIENCE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;SOUFFLE PANCAKE & DESSERT CAFE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;COCKTAIL BAR&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;TAIWANESE FRIED CHICKEN&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHINESE HOTPOT&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;POLISH STREET FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;KOREAN BBQ&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;
      </div>
      <div class="scrolling-header-container-item">
         AUTHENTIC VIETNAMESE FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;INDIAN CUISINE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHURROS & COFFEE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;BUBBLE TEA&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;ESCAPE ROOM EXPERIENCE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;SOUFFLE PANCAKE & DESSERT CAFE&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;COCKTAIL BAR&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;TAIWANESE FRIED CHICKEN&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;CHINESE HOTPOT&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;POLISH STREET FOOD&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;KOREAN BBQ&nbsp;&nbsp;&nbsp;•&nbsp;&nbsp;&nbsp;
      </div>
   </div>
</div>

CSS (using SASS)

@keyframes infiniteScroll {
   from {  transform: translateX(0) }
   to {    transform: translateX(calc(0px - 50%)); }
}

#scrolling-header-parent-container {
   width: 100%;
   background-color: black;
   overflow-x: hidden;
    
   #scrolling-header-container {
      display: flex;
      width: fit-content;
      height: 8vh;
      font-size: 30px;
      align-items: center;
      overflow-x: hidden;
    
      animation-name: infiniteScroll;
      animation-duration: 20s;
      animation-iteration-count: infinite;
      animation-timing-function: linear;
    
      .scrolling-header-container-item {
         white-space: nowrap;
         color: white;
      }
   }
}

Why my button isnt in scrollview in code ( but it show it in phone ?)

<ScreenWapper bg="white">
            <Vie<ScreenWapper bg="white">
    <View styles={styles.container}>
        <Header title="Create Post" />
        <ScrollView contentContainerStyle={{gap: 20}} >
            
            {/* avatar */}
            <View style={styles.header}>
                <Avatar
                    uri={user?.image}
                    size={hp(6.5)}
                    rounded={theme.radius.xl}
                />
                <View styles={{gap: 2}}>
                    <Text style={styles.username}>
                        {
                            user && user.name
                        }
                    </Text>
                    <Text style={styles.publicText}>
                        Public
                    </Text>
                </View>
            </View>

            <View style={styles.textEditor}>
                <RichTextEditor editorRef={editorRef} onChange={body=> bodyRef.current = body}/>
            </View>
            {
                file && (
                    <View style={styles.file}>
                        {
                            getFileType(file) == 'video'? (
                                <Video
                                style={{flex: 1}}
                                source={{
                                    uri: getFileUri(file)
                                }}
                                useNativeControls
                                resizeMode='cover'
                                isLooping
                                />
                            ):(
                                <Image srouce={{uri: getFileUri(file)}} resizeMode='cover' style={{flex: 1}} />
                            )
                        }
                        <Pressable style={styles.closeIcon} onPress={()=>setFile(null)}>
                            <Icon name="delete" size={20} color="white" />
                        </Pressable>
                    </View>
                )
            }
            <View style={styles.media}>
                <Text style={styles.addImageText}>Add to your post</Text>
                <View style={styles.mediaIcons}>
                    <TouchableOpacity onPress={()=>onPick(true)}>
                        <Icon name="image" size={30} color={theme.colors.dark} />
                    </TouchableOpacity>
                    <TouchableOpacity onPress={()=>onPick(false)}>
                        <Icon name="video" size={33} color={theme.colors.dark} />
                    </TouchableOpacity>
                </View>
            </View> 
        </ScrollView>
        <Button
            buttonStyle={{height: hp(6.2)}}
            title="Post"
            loading={loading}
            hasShadow={false}
            onPress={onSubmit}
        />   
    </View>
</ScreenWapper>

I follow this tutorial: https://www.youtube.com/watch?v=YvODxoOTCGw in 25:33-26:03 his button is on the bottom of the screen. But for me, it show on the bottom of the add to your post. And the screen cant scrolling. enter image description here

This is the style of View.container

    container: {
        flex: 1,
        backgroundColor: 'red',
        marginBottom: 30,
        paddingHorizontal: wp(4), //FIX_HERE nhap lai
        gap: 15,
    },
  1. I have tried put this code in scroll View to make the content inside is bigger

     {Array.from({ length: 20 }).map((_, index) => (
        <Text key={index}>Dòng {index + 1}</Text>
      ))}
    

    And the post button got push down enter image description here

  2. I have tried keyboardShouldPersistTaps=”handled”but the result is the same

Issue with SHA mismatch despite matching Base64 content in JavaScript program

I’m working on a JavaScript app in NodeJs v22.11.0 with @octokit/rest 21.0.2 and crypto-js 4.2.0 and I’m encountering an issue where the text content of a file with accents (e.g., in Spanish) gets corrupted when pushed and pulled via the GitHub API. Specifically, if I push a file with the string "Quedar con la tía María", (“meet up with aunt María” in Spanish if you are curious), and then pull it back, I end up with incorrect characters in the decoded output. Depending on the decoding method used, I get one of these results:

"Quedar con la t�a Mar�a"
"Quedar con la tía MarÃa"
This issue occurs whether I use Buffer.from(repoFile.base64content, ‘base64’).toString(‘utf-8’) or atob(repoFile.base64content).

Additionally, the SHA hash calculated for the file after decoding is different from the original GitHub SHA. The SHA calculation works fine when there are no accented characters.

Here’s a minimal example to reproduce the issue:

import { Octokit } from "@octokit/rest";
import CryptoJS from 'crypto-js';

const octokit = new Octokit({ auth: 'personal-access-token' });

// Local file content with accented characters
const localFileContentString = 'Quedar con la tía María';
const localFile = { 
  path: 'Recordar.md', 
  sha: getSha(localFileContentString), 
  content: localFileContentString, 
  base64Content: btoa(localFileContentString) 
};

// Function to calculate SHA1 of file content
function getSha(fileContents) {
    const size = fileContents.length;
    const blobString = `blob ${size}${fileContents}`;
    return CryptoJS.SHA1(blobString).toString(CryptoJS.enc.Hex);
}

// Fetch the file content from GitHub repo
async function getRepoFile() {
    const existingFileResponse = await octokit.repos.getContent({
        owner: 'github-username',
        repo: 'vault-name',
        path: localFile.path
    });
    return { sha: existingFileResponse.data.sha, base64content: existingFileResponse.data.content.replace(/n/g, '') };
}

const repoFile = await getRepoFile();

console.log('EncodedRepoFile', repoFile, "n");
console.log('EncodedLocalFile', localFile, "n");

// Decode the base64 content from both the repo and local file
console.log('DecodedRepoFile', Buffer.from(repoFile.base64content, 'base64').toString());
console.log('DecodedLocalFile', Buffer.from(localFile.base64Content, 'base64').toString());

And the code output:

EncodedRepoFile {
  sha: '9fe35536cd6188e428ee04dcb559d69ecfb4d5d9',
  base64content: 'UXVlZGFyIGNvbiBsYSB0w61hIE1hcsOtYQoK'
} 

EncodedLocalFile {
  path: 'Recordar.md',
  sha: '9860966172762a56f5b3dec12d51d4b1fb1034e8',
  content: 'Quedar con la tía María',
  base64Content: 'UXVlZGFyIGNvbiBsYSB07WEgTWFy7WE='
} 

DecodedRepoFile Quedar con la tía María


DecodedLocalFile Quedar con la t�a Mar�a

I think the problem relies on how GitHub itself handles this special characters and I don’t know how to work my way around it. I’m using UFT-8 and I’ve tried changing the encoding to ISO-8859-1, getting the SHA of the corrupted string to at least check if I got the same SHA and checked through all the code that the encoding is consistent with libs like iconv-lite and chardet but none of that works.

Render range of pages of a PDF with PDF.JS

Is it possible to render a specific range of pages in a pdf using pdf.js?
I currently have a PHP + Javascript project that classifies a pdf by ranges, so when the user chooses a range, I can only send the viewer the start page and it is responsible for initially displaying that page ignoring the range.

The problem arises when the complete pdf has more than 80 pages because the viewer will load all the pages even though the user only requires a specific range, for example, from page 5 to 10.

In case pdf.js does not allow me to do this, what library can I use to achieve this, thank you very much.

I can only send the viewer the start page and it is responsible for initially displaying that page ignoring the range.

This is my code in PHP.

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Visor de PDF Integrado con PDF.js</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            margin: 20px;
        }

        iframe {
            width: 90%;
            height: 800px;
            border: 1px solid #ccc;
            margin-top: 20px;
        }

        input[type="file"] {
            margin-top: 20px;
        }
    </style>
</head>

<body>
    <h1>Visor de PDF Integrado</h1>
    <input type="file" id="pdfFileInput" accept="application/pdf" />
    <iframe id="pdfViewer" src=""></iframe>

    <script>
        const pdfFileInput = document.getElementById('pdfFileInput');
        const pdfViewer = document.getElementById('pdfViewer');

        let currentURL = null;

        pdfFileInput.addEventListener('change', (event) => {
            const file = event.target.files[0];
            if (file && file.type === 'application/pdf') {
                // Liberar URL anterior si existe
                if (currentURL) {
                    URL.revokeObjectURL(currentURL);
                }
                // Crear una URL para el archivo PDF
                currentURL = URL.createObjectURL(file);
                // Establecer la fuente del iframe al visor de PDF.js con el archivo PDF
                pdfViewer.src = `pdf.js/web/viewer.html?file=${encodeURIComponent(currentURL)}#page=2`;
            } else {
                alert("Por favor, selecciona un archivo PDF válido.");
            }
        });
    </script>
</body>

</html>

I have already downloaded PDF.js and it works, but I don’t know how to configure a page range.

Jest code coverage not picking up JS files from parent directory even if within rootDir

I have a specific project setup where the Jest tests live in a folder but are testing code from two different source folders located in a parent directory. When trying to setup code coverage, I read on other posts that setting the rootDir to the common parent and adding the other folders as roots should solve it. However, my JS files in the source folders are still not being picked up. I’ve tried moving a JS file around to test and sure enough only files located within the same folder of the Jest config are being picked up for coverage.

Here’s my jest config file:

{
  "testEnvironment": "jsdom",
  "testMatch": [
    "**/jest/**/*.test.js"
  ],
  "rootDir": "../../",
  "transform": {
    "^.+\.[t|j]sx?$": [
      "babel-jest",
      {
        "configFile": "./babel.config.json"
      }
    ]
  },
  "transformIgnorePatterns": [
    "node_modules/(?!(parsel-js|cheerio|uuid)/)"
  ],
  "roots": [
    "<rootDir>/mu-plugins/tests",
    "<rootDir>/mu-plugins/core/assets/src/js",
    "<rootDir>/themes/theme/assets/ts"
  ],
  "setupFilesAfterEnv": [
    "<rootDir>/mu-plugins/tests/jest.setup.js"
  ],
  "moduleDirectories": [
    "<rootDir>/mu-plugins/tests/node_modules"
  ],
  "globals": {
    "CSS": {}
  },
  "collectCoverageFrom": [
    "**/*.js"
  ],
  "coveragePathIgnorePatterns": [
    "/node_modules/",
    "/coverage/"
  ],
  "coverageDirectory": "<rootDir>/mu-plugins/tests/coverage"
}

I am using Jest 29.7 in case it matters.

My rootDir used to be on the same level as the Jest config so I changed it to the common parent, and added all relevant directories to the roots array. This didn’t solve the issue. I’m certain the paths are right though as when putting a wrong folder on purpose, Jest would throw an error.

I’ve tried clearing the Jest cache, but it didn’t solve it either.

I’ve tried various formatting for collectCoverageFrom but none worked.

I’ve also tried changing the value of forceCoverageMatch, no luck there too.

When running jest --coverage I then see:

> jest --coverage

 PASS  jest/theme/components/shared/info.test.js
 PASS  jest/core/variant/variant.test.js
----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |
----------|---------|----------|---------|---------|-------------------

Test Suites: 2 passed, 2 total
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        5.112 s
Ran all test suites.

angular jest test fails when using js object from shared library

I have an angular 18 app in a NX workspace and I am trying to run a test in isolation. But I am getting an error:

 FAIL   shared-ui  libs/web/shared/ui/src/lib/shared-ui/form-controls/exercise-selector-input/data-access/exercise-input.service.spec.ts
  ● Test suite failed to run
    ReferenceError: fetch is not defined
 .....
  at Object.<anonymous> (src/lib/shared-ui/form-controls/exercise-selector-input/data-access/exercise-input.service.spec.ts:4:1)
 Test Suites: 1 failed, 1 total
 Tests:       0 total

The line referenced is the import line FormatOptionData

I am using the following command to run jus the single file in question:

nx run shared-ui:test --testFile=exercise-input.service.spec.ts

Here is my test file simplified:

    import { TestBed } from '@angular/core/testing';
    
    import { ExerciseInputService } from './exercise-input.service';
    import { Format, FormatOptionData } from '@t3a/shared-data-access';
    
    describe('ExerciseRecordService', () => {
      let service: ExerciseInputService;
      const format: Format[] = FormatOptionData;
    
      beforeEach(() => {
        TestBed.configureTestingModule({});
        service = TestBed.inject(ExerciseInputService);
      });
      
      // tests go here

    });

I know the error occurs on the FormatDataOptions assignemnt because if that is the ONLY thing I remove then there is no error.

FormatDataOptions is a js object that is imported from another shared lib inside the NX workspace. It looks like this:

export const FormatOptionData: Format[] = [
  {
    dataType: DataTypeListEnum.Enum.format,
    name: "Sets x Reps",
    code: "NSETS_XREPS",
    description: "A number of sets of reps",
    useValue: true,
    valueType: FormatValueTypeEnum.enum.set_reps,
    valueLabel: "Sets",
    prefixValue: false,
    public: true,
  },
  {
    dataType: DataTypeListEnum.Enum.format,
    name: "Rep Max",
    code: "NRM",
    description: "Maximum weight for a specific number of reps",
    useValue: true,
    valueType: FormatValueTypeEnum.enum.number,
    valueLabel: "Reps",
    prefixValue: true,
    public: true,
  },
]

I don’t want to mock this because I need to do this with multiple objects like the one above and I don’t want to maintain the data in two places

Can someone help me import this JavaScript object into my angular test

thanks

How can I fix the error where the game goes to game over logic immediately?

I am trying to build a simple game with JS and HTML, but I found it difficult to fix an error where my code immediately goes to the “game over” block at the time of running the program.

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas Graphics</title>
  <style>
    .btn {
      margin-right: 65px;
      margin-top: 50px;
    }
  </style>
</head>

<body onload="startGame()">
  <h1>Canvas Graphics</h1>

  <script>
    // Game variables

    let comp1, block, blockArray = [];

    let xSpeed = 0,
      ySpeed = 0,
      blockSpeed = 0;

    let myInterval;

    // Game area setup
    const gameArea = {
      canvas: document.createElement("canvas"),
      start: function() {
        this.canvas.width = 400;
        this.canvas.height = 400;
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, document.body.childNodes[3]);
      }
    };

    // Movement functions
    function right() {
      xSpeed += 1;
      ySpeed = 0;
      blockSpeed = 1;
    }

    function up() {
      ySpeed -= 1;
      xSpeed = 0;
      blockSpeed = 1;
    }

    function left() {
      xSpeed -= 1;
      ySpeed = 0;
      blockSpeed = 1;
    }

    function down() {
      ySpeed += 1;
      xSpeed = 0;
      blockSpeed = 1;
    }

    // Update game components
    function updateComponent() {
      gameArea.context.clearRect(0, 0, gameArea.canvas.width, gameArea.canvas.height);
      let overlap = false;

      // Define boundaries for comp1
      const myRight = comp1.x + comp1.width,
        myLeft = comp1.x,
        myTop = comp1.y,
        myBottom = comp1.y + comp1.height;

      // Check for collisions with blocks
      for (let blocks of blockArray) {
        const blockLeft = blocks.x,
          blockRight = blocks.x + blocks.width,
          blockTop = blocks.y,
          blockBottom = blocks.y + blocks.height;

        // Collision detection
        if (myRight > blockLeft && myLeft < blockRight &&
          myBottom > blockTop && myTop < blockBottom) {
          overlap = true;
          break; // Exit loop on collision
        }
      }

      // If no overlap, update positions and create new blocks
      if (!overlap) {
        if (blockSpeed == 1) {
          gameArea.createBlockInterval += 50;

          // Create a new block every 3 seconds
          if (gameArea.createBlockInterval >= 3000) {
            let newBlock = new Component(gameArea.canvas.width,
              Math.random() * (gameArea.canvas.height - block.height),
              15,
              130,
              block.color);
            blockArray.push(newBlock);
            gameArea.createBlockInterval = 0; // Reset interval
          }

          // Update position of comp1
          comp1.x += xSpeed;
          comp1.y += ySpeed;

          // Draw player component
          gameArea.context.fillStyle = comp1.color;
          gameArea.context.fillRect(comp1.x, comp1.y, comp1.width, comp1.height);

          // Draw all blocks in the array
          for (let block of blockArray) {
            block.x -= blockSpeed; // Move blocks left
            gameArea.context.fillStyle = block.color;
            gameArea.context.fillRect(block.x, block.y, block.width, block.height);
          }
        } else {
          clearInterval(myInterval); // Stop the game loop
          prompt("Game Over"); // Notify player of game over
        }
      }
    }

    // Component constructor
    function Component(x, y, width, height, color) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
      this.color = color;

      // Draw the component on the canvas
      this.draw = function() {
        const ctx = gameArea.context;
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.width, this.height);
      };
    }


    // Start the game function
    function startGame() {
      gameArea.start();
      comp1 = new Component(20, 300, 50, 10, "red"); // Player component
      block = new Component(380, 100, 15, 130, "yellow"); // Initial block
      blockArray.push(block);
      myInterval = setInterval(updateComponent, 50); // Update loop every 50 ms
    }
  </script>

  <!-- Control buttons -->

  <button onclick="left()" class="btn">Left</button>
  <button onclick="right()" class="btn">Right</button><br>
  <button onclick="down()" class="btn">Down</button>
  <button onclick="up()" class="btn">Up</button><br>

Tawk.to Widget Stops Working After Livewire Component Change in Laravel

I’m using Laravel Livewire with app.blade.php as the main layout for all pages. The app.blade.php file includes dynamic content using {{$slot}}. I’ve created a separate Livewire component for the Tawk.to widget (TawkWidget) and included it in the layout.

app.blade.php:

<!DOCTYPE html>
<html lang="en">
<head>
    @livewireStyles
</head>
<body>
    <livewire:header />
    {{ $slot }}
    <livewire:footer />
    <livewire:tawk-widget />
    @livewireScripts
</body>
</html>

tawk-widget.blade.php:

<div id="tawk-widget-container" wire:ignore>
    <!--Start of Tawk.to Script-->
    <script type="text/javascript">
        var Tawk_API = Tawk_API || {}, Tawk_LoadStart = new Date();
        (function () {
            var s1 = document.createElement("script"), s0 = document.getElementsByTagName("script")[0];
            s1.async = true;
            s1.src = 'https://embed.tawk.to/id-provided/some-id';
            s1.charset = 'UTF-8';
            s1.setAttribute('crossorigin', '*');
            s0.parentNode.insertBefore(s1, s0);
        })();
    </script>
    <!--End of Tawk.to Script-->
</div>

How I change component:

return cache()->remember('about-us-v10', 31536000, function () {
    return view('livewire.about-us')->layout('app')->render();
});

Issues:

  • On the initial page load, the Tawk.to widget works perfectly, and its is injected into the DOM.
  • After switching Livewire components (updating the {{$slot}}), the widget disappears, and the is not re-injected.

What I Tried:

  • Used wire:ignore in the widget component to prevent Livewire from interfering with the widget’s container.
  • Triggered reinitialization of the script on livewire:update and livewire:load events.
  • Moved the script directly into app.blade.php.
  • Tried @script and @endscript

Expected:
The Tawk.to widget should remain visible and functional across Livewire component changes, or it should reinitialize if needed.
How can I ensure the Tawk.to widget persists or reloads correctly after Livewire component changes? Any advice on handling third-party scripts with Livewire?

How to programmatically draw using DGM.js

I can’t seem to figure out the right combinations of methods/properties/values to draw a simple rectangle into the Editor (I guess onto the canvas) of the DGM.js package.

Is anyone able to provide some example code that will show how to programmatically draw a rectangle (or any shape), that I can use as a starting point?

If it matters, I’d rather the rectangle not be user select-able once it’s drawn, unlike rectangles that a user will draw using their cursor