laravel reverb broadcast on not chanel not run ever

I have a notification system in Laravel 11, and SPA Nuxt 3 connects in the browser using Laravel Echo and gets status 101. The notification is saved in the database and no errors appear, but the channel never receives anything and does not work at all

Here is the notification file code

<?php

namespace AppNotifications;

use IlluminateBusQueueable;
use IlluminateSupportFacadesLog;
use IlluminateBroadcastingChannel;
use IlluminateNotificationsNotification;
use IlluminateContractsBroadcastingShouldBroadcast;
use IlluminateNotificationsMessagesBroadcastMessage;

class sendContactNotification extends Notification implements ShouldBroadcast
{
    use Queueable;

    public $data;


    public function __construct($data)
    {
        $this->data = $data;
    }

    public function via(object $notifiable): array
    {

        return ["database", "broadcast"];
    }


    public function toArray(object $notifiable): array
    {
        return [
            'text' => $this->data,
        ];
    }

    public function toBroadcast($notifiable)
    {
        Log::info('toBroadcast run.');

        $this->broadcastOn();
        return new BroadcastMessage([
            'message' => $this->data,
        ]);
    }

    public function broadcastOn()
    {
        Log::info('broadcastOn run.');

        return new Channel('admin-notification-channel');
    }
}

Indeed, these words are logged:

toBroadcast run.

broadcastOn run.

I directly call the notification from the controller like this:

$notificationRecipients = Admin::all();
$message = 'contact_us_notifications';
Notification::send($notificationRecipients, new sendContactNotification($message));

This is the channel:

Broadcast::channel('admin-notification-channel', function ($user) {
    Log::info('channel run.');
    return true;
});

I never find this word in the log:
“channel run.”

This is the Laravel Echo code in the front end:


import Echo from 'laravel-echo'
import Pusher from 'pusher-js'

export default defineNuxtPlugin(nuxtApp => {

  const { $coreHttp } = useNuxtApp()
  const config = useRuntimeConfig()

  const pusher_const = Pusher

  console.log("test run")

  const echo_const = new Echo({
    broadcaster: 'reverb',
    key: config.public.REVERB_APP_KEY,
    wsHost: config.public.REVERB_HOST,
    wsPort: config.public.REVERB_PORT,
    wssPort: config.public.REVERB_PORT,
    forceTLS: (config.public.REVERB_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
    auth: {
      headers: {
        Authorization: `Bearer ${localStorage.getItem('authAdmin')}`,
        Accept: 'application/json',
      },
    },
  })

  window.Pusher = pusher_const
  window.Echo = pusher_const

  nuxtApp.provide('pusher', pusher_const)
  nuxtApp.provide('echo', echo_const)

})

The connection runs for the notification using Postman, and each step is saved in the log to check where it reached, as explained. However, the channel never works and is not saved in the log

How to host a webpack-based project with Firebase Hosting while maintaining functionality?

I’m trying to host my social media-like web app on Firebase Hosting. My project uses Webpack for bundling and includes HTML, CSS, and JavaScript(firebase) files. However, I’m facing issues with maintaining the functionality of my app after deploying it to Firebase.

This is my project structure
project structure
project structure

  1. I configured Firebase Hosting and copied my dist/ files into the public/ folder.
  • Result: The website loads, but functionality breaks because the bundled files are not connected to the src/ files.
  1. I considered moving all my dist/ and src/ files into the public/ folder to maintain the directory structure.
  • Problem: It seems unconventional and messy, and I’m unsure if this approach works with Firebase Hosting.

Insert sequence of formatting that can overlap into a string at specific locations

I have this problem, I refactored jQuery Terminal unix_formatting extension (a formatter) that process ANSI escape codes, based on paid work. The task that I was hired for was to only output text, but it should work with any output the terminal can process that you can record into a single file. I’ve got permission to use this code for my Open Source project.

When my code finish parsing the input string, I end up with a structure like this:

var data = [
 {
    text: "                                                       the knight ▄▄▄▄▄ fuel",
    formatting: [
      {start: 55, end: 65, format: '[[b;#555;#000]'},
      {start: 65, end: 66, format: '[[;#000;]'},
      {start: 66, end: 76, format: '[[b;#555;]'}
    ]
}

For the work I was hired, I ignored the formatting and colors and only return text and concatenate the result.

The jQuery Terminal formatting look like this, the opening is the thing in format and then the closing is single closing bracket. The formatting can overlap because I have a formatter that use simple stack to create a flat list.

Now I need to process this code into the final color form using jQuery Terminal formatting. The problem is that the start and end can overlap. I have a function in the library called $.terminal.substring that can return substring of the string and keep the formatting in place. e.g.:

$.terminal.substring('[[;;]hello]', 1, 2);
// '[[;;]e]'

The problem is that this function is slow when text is long, and I use this to test with ANSI Art that sometimes is one big line that need to be split into lines depending on metadata.

So I was thinking of pre-processing the input string somehow and put the markers in palaces where the formatting need to be put. And at the end combine the formatting and input chunks. But I’m not sure how to do this.

I asked ChatGPT It has given me a simple code (way too simple) at first I thought it was working:

function preprocessAndFormat(data) {
    var text = data.text;
    var formatting = data.formatting;

    // Collect all formatting start and end points
    var points = [];
    formatting.forEach(function(item) {
        points.push({ pos: item.start, type: 'start', format: item.format });
        points.push({ pos: item.end, type: 'end', format: item.format });
    });

    // Sort points by position, with 'end' before 'start' if equal
    points.sort(function(a, b) {
        if (a.pos === b.pos) {
            return a.type === 'end' ? -1 : 1;
        }
        return a.pos - b.pos;
    });

    // Process the text and insert formatting placeholders
    var result = '';
    var lastPos = 0;
    var openFormats = [];

    points.forEach(function(point) {
        if (point.pos > lastPos) {
            result += text.slice(lastPos, point.pos);
        }

        if (point.type === 'start') {
            openFormats.push(point.format);
            result += point.format;
        } else if (point.type === 'end') {
            var index = openFormats.lastIndexOf(point.format);
            if (index !== -1) {
                openFormats.splice(index, 1);
                result += ']';
            }
        }

        lastPos = point.pos;
    });

    // Add the remaining text after the last position
    result += text.slice(lastPos);

    return result;
}

But it failed with more complex ANSI Art. As one of unit test I have this Denis Richie ANSI Art.

Denis Richie ANSI Art

This is the output, of the above code:

Denis Richie ANSI Art with visible jQuery Terminal formatting

As you can see, some of the formatting is visible, because the code substring on the output string that already contain the formatting, and the start, end markers are for the original string without the formatting.

So to be complete, here is my question summary:

How to write an algorithm that will process the input string and inject the formatting at specific places, where the formatting can overlap?

Here is a CodePen demo where you can experiment:

https://codepen.io/jcubic/pen/mybEYPV?editors=1010

This is related code:

function format_lines(str, len) {
    str = $.terminal.apply_formatters(str, {
        unixFormatting: {
            format_text: function(line) {
                // return line.text;
                return format_text(line);
            },
            ansiArt: true
        }
    });
    ...
}

format_text function receives a data structure like I showed at the beginning. format_text is invalid function based on ChatGPT.

Problem stopping detecting keys when use “SHIFT”

I was doing tests to detect the keyboard keys, it occurred to me to save it in an array and add the keys in the order in which they are held down. For example, if you keep “w” and “a”, the array would be [“w”, “a”]. The problem occurs when you hold “w” and then “SHIFT”. When you stop holding “w”, the key is not removed from the array.

Note: to replicate the problem, first hold down the “w” and while holding it down then press the “SHIFT”. Then release the “w” while holding down the “SHIFT”.

let keysPressed = [];

document.addEventListener('keydown', (event) => {
  if (!keysPressed.includes(event.key)) {
    keysPressed.push(event.key)
  }
});

document.addEventListener('keyup', (event) => {
  const keyIndex = keysPressed.indexOf(event.key);
  if (keyIndex !== -1) {
    keysPressed.splice(keyIndex, 1)
  }
});

function update() {
  if (keysPressed.length > 0) {
    document.getElementById('status').innerHTML = `Pressed keys: ${keysPressed.join(', ')}<br>Last pressed key: ${keysPressed[keysPressed.length - 1]}`;
  } else {
    document.getElementById('status').textContent = 'No keys pressed'
  }
  requestAnimationFrame(update)
}

requestAnimationFrame(update)
body { 
  font-family: Arial, sans-serif; 
}

.status { 
  font-size: 1.5em; 
  color: green; 
}
<body>
  <h2>Hold a key pressed</h2>
  <p class="status" id="status">No key pressed</p>
</body>

Ajax sending without return due to possible obfuscation in a subsequent sending from the server to an external website

From the client I send an Ajax request to the server expecting a return.

 $.ajax({
        type: "POST",
        url: "RespuestaajaxL.aspx/RespuestaajTask",
        contentType: "application/json; charset=utf-8",
        data: '{"parametro":"funcion","valor":"ActualizarArchivoDrive","tabla":"' + datosserver.nombrearchivo + '","campo":"' + datosserver.extensionarchivo + '","criterio":"' + datosserver.nombrearchivosinext + '","v1":"' + datosserver.extensionarchivoO + '","v2":"' + datosserver.idFile + '","v3":"' + datosserver.idFolder + '","v4":"","v5":"","v6":"","v7":"","v8":""}',
        dataType: "json",
        success: function (devolucion) {
            if (devolucion.d) {
                alert("Actualizado el archivo en Drive");
            }
        },
        error: function (req, status, error) {
            alert("No hubo respuesta desde el método del servidor TroceadoFileBase64_fin. Prueba otra vez.");
        }
    });

The call is successful. In a routine already on the server, an update is performed
ion of a file located in Google Drive. This update is carried out successfully but the response is not returned to the client. The process returns nothing to the client. I have checked the entire process by putting error checking with try catch in the three methods involved and no errors occur.

The method that updates the file in Google Drive is as follows:

 public async Task Ue(string filePath, string fileId, string MIME, Google.Apis.Drive.v3.Data.File updateFileBody, Google.Apis.Drive.v3.DriveService ds)
        {
            try
            {   

                using (var uploadStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))

                {
                    // Update the file id, with new metadata and stream.
                    var updateRequest = ds.Files.Update(updateFileBody, fileId, uploadStream, MIME);
                    var result = await updateRequest.UploadAsync(CancellationToken.None);    
                    
                    uploadStream.Flush();
                    uploadStream.Close();
                    
                }
            } catch (Exception EE)
            {
                string h = EE.Message;
            }
        }

As it seems to me, it may be happening that after the update call is made through the drive.service established with Google Drive with updateRequest the process stops on my site and loses the ability to pick up the thread. But I have no idea why. The update occurs but I need to receive the return on the client because after the thread is lost the application becomes inactive and does not respond to any events.

Is it possible to connect to a SMTP server through proxy?

I’m attempting to connect to SMTP servers through proxies to validate emails.

I’ve looked into http-proxy-agent, but as I understand, proxies cannot be used with a TCP connection?

My current connection setup:

const client = net.createConnection(25, mxServer, () => {
                client.write("HELO @mail.comrn");
                client.write("MAIL FROM:<email_address>rn");
                client.write(`RCPT TO:<${email}>rn`);
            });

Puppeteer Getting Timeout Upon ‘waitForSelector’

I’m using node.js and puppeteer to get some data. However, Puppeteer keeps getting timeout. My code is as followings:

const puppeteer = require("puppeteer");

(async () => {

    const browser = await puppeteer.launch({
        executablePath: '/usr/bin/google-chrome-stable',
    });

    const page = await browser.newPage();

    let url = "https://erecruit.wsib.on.ca/PSHREXTP/start.html";
    let job_selector = "table#tdgbrHRS_CE_JO_EXT_I\$0 tbody tr";

    // works fine for the following webpage
    //let url = "https://career17.sapsf.com/career?company=universitc&career_ns=job_listing_summary&navBarLevel=JOB_SEARCH";
    //let job_selector = "tr.jobResultItem";

    await page.goto(url);
    await page.waitForSelector(job_selector);

    const jobs = await page.evaluate((job_selector) => {
        const quoteList = document.querySelectorAll(job_selector);
        return Array.from(quoteList).map((quote) => quote.outerHTML);
    }, job_selector);

    console.log(JSON.stringify(jobs));

    await browser.close();

})();

I tried to use a longer timeout of 60 seconds. The same error.

I tried to capture the screen before the waitForSelector call, and only the top banner is shown. That indicates the fact that data is not loaded.

As shown in the code, it works fine with another webpage and selector.

What am I missing here?

Infinite Loop on RNEventSource with Server-Sent Events (SSE) – Only Receiving “attempt: 1”

I am working on a React Native expo managed project using RNEventSource to handle Server-Sent Events (SSE). My backend is correctly streaming data (confirmed via Postman), but the frontend gets stuck in an infinite loop of the same response, only receiving:

LOG  Open SSE connection.
LOG  Stream Data: {"attempt": 1, "run_id": "1efb7463-0ff8-60c3-bd10-17ccc210899f"}
WARN  Unexpected Data: {"run_id":"1efb7463-0ff8-60c3-bd10-17ccc210899f","attempt":1}
LOG  Stream Data: {"attempt": 1, "run_id": "1efb7463-0ff8-60c3-bd10-17ccc210899f"}
WARN  Unexpected Data: {"run_id":"1efb7463-0ff8-60c3-bd10-17ccc210899f","attempt":1"}
...

Sent the exact same data I’m attempting on the front in the backend also tried with Postman that worked fine.

  const askDogy = async (request) => {
  const url = `${assitantBaseUrl}/threads/${threadId}/runs/stream`
  const requestBody = JSON.stringify({
    assistant_id: assistantID,
    input: {
      messages: [{ role: 'user', content: request }],
    },
    stream_mode: ['messages'],
  })

  const options = {
    body: requestBody,
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'text/event-stream',
    },
  }

  eventSourceRef.current = new RNEventSource(url, options)

  eventSourceRef.current.addEventListener('open', () => {
    console.log('Open SSE connection.')
  })

  eventSourceRef.current.addEventListener('message', (event) => {
    console.log('Raw Event:', event)
    try {
      const data = JSON.parse(event.data)
      console.log('Parsed Data:', data)

      if (data.content) {
        console.log('AI Reply Content:', data.content)
        setChatResponse('Bot', data.content, true)
      } else {
        console.warn('Unexpected Data:', data)
      }
    } catch (error) {
      console.error('Error parsing event data:', error)
    }
  })

  eventSourceRef.current.addEventListener('error', (error) => {
    console.error('Stream error:', error)

        if (error.status === 409) {
          console.log('Conflict detected, creating a new thread...')
          // Create a new thread and retry
          tempThreadId = await createThread()
          if (!tempThreadId)
            throw new Error('Failed to create a new thread after conflict')
          setThreadId(tempThreadId)

          // Retry the stream with the new thread ID
          console.log('Retrying with new thread ID:', tempThreadId)
          await askDogy(request) // Recursive call with the new thread
        } else {
          handleStopStream()
        }
  })
}

Debugging Observations:

  • I receive the same attempt: 1 data repeatedly with no progress.
  • The backend should send incremental updates, but the frontend logs do not show progress.

Questions:

  • Is there a known issue with RNEventSource or its compatibility with
    React Native?
  • Could there be something specific I need to handle in
    RNEventSource to parse incremental updates?
  • Any other npm package/library I can use to handle server sent events in react native/expo?

Things I’ve tried:

  • Verified backend compliance with the SSE spec.
  • Ensured RNEventSource initialization includes proper headers and method.
  • Added maximum retries and timeout logic in case of backend failures (now removed).
  • Tested backend with Postman and it streams correctly.

How can I access the user’s linkedin post using API

I am currently working on a tool to access logged-in LinkedIn users’ posts, including their likes and comments, along with the commenter and liker profile links.

I have searched the internet and found some API endpoints, but I’m unsure which information and endpoints I need to access.

Additionally, are these permissions available to all users who log in with their LinkedIn accounts to any third-party service, or do I need approval for this specific case?

The content of modal windows is not passed to the Vue.js template

For center-type modal windows, all function arguments are passed correctly.
The issue arises when trying to pass an object from the template to slotContent, as its value becomes null.

In the code, I added debugging for the ModalPlugin in the show() method, and it turns out that the required content is sent there. The problem is that in the Modal.vue template, in this fragment:

<template v-else-if="type === 'bottom'">
    <component v-if="slotContent" :is="slotContent" />
</template>

The slotContent value is null.

Even when sending plain text content (String), the slotContent value is still null.

ModalPlugin.js

import { reactive } from "vue";
import Modal from "@/views/components/Modal.vue";

export default {
  install(app) {
    const state = reactive({
      visible: false,
      type: "center",
      title: "",
      message: "",
      icon: "",
      hasAction: false,
      actionText: "",
      callback: null,
      slotContent: null,
    });

    app.component("Modal", Modal);

    app.config.globalProperties.$modal = {
      show(options) {
        Object.assign(state, options, { visible: true });
      },
      hide() {
        Object.assign(state, {
          visible: false,
          slotContent: null,
          callback: null,
        });
      },
    };

    app.provide("modalState", state);
  },
};

Modal.vue

<template>
    <div
        v-if="visible"
        :class="['modal', type]"
        @click.self="close"
    >
        <div class="modal__content">

            <button class="modal__close" @click="close">
                <img src="~@/assets/images/modal/close.png" alt="">
            </button>

            <template v-if="type === 'center'">
                <div class="modal__image">
                    <img :src="icon" alt="" />
                </div>
                <p class="title">{{ title }}</p>
                <p class="text" v-html="message"></p>

                <button v-if="hasAction" class="btn btn__primary" @click="action">
                    {{ actionText }}
                </button>
            </template>

            <template v-else-if="type === 'bottom'">
                <component v-if="slotContent" :is="slotContent" />
            </template>

        </div>
    </div>
</template>


<script>
import '../../styles/components/Modal.scss';

export default {
    name: "Modal",
    props: {
        visible: { type: Boolean, default: false },
        type: { type: String, default: "center" },
        title: { type: String, default: "" },
        message: { type: String, default: "" },
        icon: { type: String, default: "" },
        hasAction: { type: Boolean, default: false },
        actionText: { type: String, default: "OK" },
        slotContent: { type: [String, Object, Function], default: null },
    },
    emits: ["close", "action"],
    methods: {
        close() {
            this.$emit("close");
        },
        action() {
            this.$emit("action");
        },
    }
};
</script>

ShopView.vue

    <div class="shop">
        <div class="shop__list">
            <button
                class="shop__list__btn glitter"
                @click="openModal('boost', 'Boost')"
            >
                <img src="~@/assets/images/shop/boost.png" alt="">
                <p>Прокачаться</p>
            </button>

            <button
                class="shop__list__btn glitter"
                @click="openModal('exchange', Exchange)"
            >
                <img src="~@/assets/images/shop/exchange.png" alt="">
                <p>Обменник</p>
            </button>

            <button
                class="shop__list__btn glitter"
                @click="openModal('buyDiamonds', BuyDiamond)"
            >
                <img src="~@/assets/images/shop/diamond.png" alt="">
                <p>Купить алмазы</p>
            </button>

            <button
                class="shop__list__btn glitter"
                @click="openModal('withdraw', Withdrawal)"
            >
                <img src="~@/assets/images/shop/withdraw.png" alt="">
                <p>Вывести деньги</p>
            </button>
        </div>
    </div>
</template>

<script>
import '../styles/components/Shop.scss';
import Boost from './components/shop/Boost.vue';
import BuyDiamond from './components/shop/BuyDiamond.vue';
import Exchange from './components/shop/Exchange.vue';
import Withdrawal from './components/shop/Withdrawal.vue';

export default {
    name: "ShopView",
    components: {
        Boost,
        BuyDiamond,
        Exchange,
        Withdrawal
    },
    methods: {
        openModal(type, slotContent) {
            this.$modal.show({
                type: 'bottom',
                slotContent,
            });
        }
    },
};
</script>```


I tried passing a value as a string to slotContent, but it was still null in Modal.vue, even though other arguments were displayed correctly.

slide two divs by clicking one link

I would like to implement this CSS-Only Carousel from this link: https://codepen.io/chriscoyier/pen/XwbNwX. Instead of just one I would like two Carousel that are triggered at the same time by clicking one link. So for example, clicking the link1 would slide both cards with the number1. Example how should look like

I know that with bootstrap is easier but due to css and bootstrap conflicts in WordPress I would like to keep only CSS. I am still a beginner.

     * {
        box-sizing: border-box;
        }

        .slider {
        text-align: left;
        overflow: hidden;
        }

        .slides {
        width: 300px;
        display: flex;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scroll-behavior: smooth;
        -webkit-overflow-scrolling: touch;

        }
        .slides::-webkit-scrollbar {
        width: 10px;
        height: 10px;
        }
        .slides::-webkit-scrollbar-thumb {
        background: black;
        border-radius: 10px;
        }
        .slides::-webkit-scrollbar-track {
        background: transparent;
        }
        .slides > div {
        scroll-snap-align: start;
        flex-shrink: 0;
        width: 300px;
        height: 300px;
        margin-right: 50px;
        border-radius: 10px;
        background: #eee;
        transform-origin: center center;
        transform: scale(1);
        transition: transform 0.5s;
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 100px;
        }
        .slides > div:target {
        /*   transform: scale(0.8); */
        }
        .slider > a {
        display: inline-flex;
        width: 1.5rem;
        height: 1.5rem;
        background: white;
        text-decoration: none;
        align-items: center;
        justify-content: center;
        border-radius: 50%;
        margin: 0 0 0.5rem 0;
        position: relative;
        }
        .slider > a:active {
        top: 1px;
        }
        .slider > a:focus {
        background: #000;
        }

        /* Don't need button navigation */
        @supports (scroll-snap-type) {
        .slider > a {
            display: none;
        }
        }
        .slidecont{
            display: grid;
            grid-template-columns: min-content min-content;
            justify-items: start;
        }
<div class="slider">
    <a href="#slide-1">1</a>
    <a href="#slide-2">2</a>
    <a href="#slide-3">3</a>
    <a href="#slide-4">4</a>
    <a href="#slide-5">5</a>
  <div class="slidecont">
    <div class="slides">
      <div id="slide-1">
        1
      </div>
      <div id="slide-2">
        2
      </div>
      <div id="slide-3">
        3
      </div>
      <div id="slide-4">
        4
      </div>
      <div id="slide-5">
        5
      </div>
    </div>

    <div class="slides">
        <div id="slide-10">
          1
        </div>
        <div id="slide-20">
          2
        </div>
        <div id="slide-30">
          3
        </div>
        <div id="slide-40">
          4
        </div>
        <div id="slide-50">
          5
        </div>
      </div>
    </div>
  </div>

I have tried searching how i can href multiple ids with javascript/jquery but again without success. Is there any way I can achieve this?

Why is my digitally signed PDF invalid in Adobe Acrobat despite correct configuration?

I’m working on a project where I need to digitally sign a PDF using Node.js. My goal is to sign the PDF with a .pfx certificate and include a timestamp (TSA). However, despite following the expected process, Adobe Acrobat reports that the signature is invalid. The certificate itself is valid, and the signed file passes validation on the ITI verifier (Brazilian official digital signature verifier), but not in Acrobat.

What I’ve Done:

1.  Used the @signpdf/signpdf library for signing.
2.  Added a ByteRange placeholder with @signpdf/placeholder-plain.
3.  Configured the TSA using the URL: https://freetsa.org/tsr.
4.  Ensured the .pfx certificate matches the private key.
const fs = require('fs');
const { plainAddPlaceholder } = require('@signpdf/placeholder-plain');
const { SignPdf } = require('@signpdf/signpdf');
const { P12Signer } = require('@signpdf/signer-p12');

// Paths
const pdfPath = '../resources/pdf-entrada.pdf'; // Input PDF
const pfxPath = '../resources/certificado.pfx'; // PFX certificate
const signedPath = '../resources/output-signed.pdf'; // Final signed PDF
const pfxPassword = 'your_password_here'; // Certificate password
const tsaUrl = 'https://freetsa.org/tsr'; // TSA URL

async function signPdfWithTSA() {
  try {
    console.log('--- Start of Signing Process ---');
    console.log('[1] Reading the original PDF...');
    const pdfBuffer = fs.readFileSync(pdfPath);
    console.log(`[1] Original PDF size: ${pdfBuffer.length} bytes`);

    console.log('[2] Adding ByteRange (Placeholder for signature)...');
    const pdfWithPlaceholder = plainAddPlaceholder({
      pdfBuffer,
      reason: 'Digital Signature',
      contactInfo: '[email protected]',
      name: 'Your Name',
      location: 'City / Country',
    });
    console.log(`[2] PDF with Placeholder size: ${pdfWithPlaceholder.length} bytes`);

    console.log('[3] Reading the PFX certificate...');
    const pfxBuffer = fs.readFileSync(pfxPath);
    console.log(`[3] PFX certificate size: ${pfxBuffer.length} bytes`);

    console.log('[4] Configuring signer with TSA...');
    const signer = new P12Signer(pfxBuffer, { passphrase: pfxPassword, tsaUrl });
    const signPdf = new SignPdf();

    console.log('[5] Signing the PDF...');
    const signedPdfBuffer = await signPdf.sign(pdfWithPlaceholder, signer);
    console.log(`[5] Signed PDF size: ${signedPdfBuffer.length} bytes`);

    console.log('[6] Saving the signed PDF...');
    fs.writeFileSync(signedPath, signedPdfBuffer);
    console.log(`[6] Signed PDF saved at: ${signedPath}`);
    console.log('--- End of Signing Process ---');
  } catch (error) {
    console.error('Error while signing the PDF:', error.message || error);
  }
}

signPdfWithTSA();

My console output:

--- Start of Signing Process ---
[1] Reading the original PDF...
[1] Original PDF size: 22368 bytes
[2] Adding ByteRange (Placeholder for signature)...
[2] PDF with Placeholder size: 39989 bytes
[3] Reading the PFX certificate...
[3] PFX certificate size: 9200 bytes
[4] Configuring signer with TSA...
[5] Signing the PDF...
[5] Signed PDF size: 39989 bytes
[6] Saving the signed PDF...
[6] Signed PDF saved at: ../resources/output-signed.pdf
--- End of Signing Process ---
```

Problem:

    •   Adobe Acrobat shows the signature as invalid.
    •   It states that the document was signed using the local time of the computer, despite configuring the TSA.
    •   The signed file passes the ITI verifier, but not Acrobat.

Fileystem API showDirectoryPicker() permanently broken if user doesn’t choose a directory

The following example code uses the Filesystem API’s showDirectoryPicker method to open a directory-picker when a user clicks a button:

async function handleClick() {
    try {
        dirHandle = await window.showDirectoryPicker({startIn: "downloads"});
    } catch (error) {
        console.log(error);
    }
}

However the following circumstances lead to the directory-picker being permanently broken:

  • User is inside Downloads already, so doesn’t think they need to create/choose a subdirectory
  • They click Open without making an explicit choice
  • The directory-picker “closes” with no directory chosen, and dirHandle is null.
  • The user clicks the button to try again
  • This call to showDirectoryPicker() throws an AbortError of NotAllowedError: Failed to execute 'showDirectoryPicker' on 'Window': File picker already active.

Any subsequent clicks to open the directory-picker fail with this same NotAllowedError: Failed to execute 'showDirectoryPicker' on 'Window': File picker already active. error.

So my question is: How can I deactivate, reset, close, delete, resolve, etc., the File Picker, so that it can be opened a second time. I can’t make the dirHandle null since it’s already null. Likewise, the Promise returned by showDirectoryPicker() is already resolved.

Any solution would be very welcome. There has to be some obvious way to resolve this, because otherwise it would be a massive bug in the Filesystem API.

Alternatively, is there any way to make showDirectoryPicker() just actually pick that starting directory (Downloads in this case)?

how can I do the transform first then animation in js?

I want the item1 can be larger and rotate first, and then keep spinning,
however the result shows that it only excutes the animation but transform.
Thank you for your help.

In css

#item1 {
    transition: transform 3s ease-in-out;
    animation: spin 10s linear infinite;
    animation-play-state: paused;
}

@keyframes spin{
    0%{
        transform: rotate(0deg);
    }

    100%{
        transform: rotate(360deg);
    }
}

In js

button.onclick = function () {
  item1.style.transform = "scale(1.2) rotate(360deg)";
  setTimeout(function () {
    item1.style.animationPlayState = "running";
  }, 3000);
};

My pug code is treated as jsx for no reason

Today a problem appeared. I assume something was updated in vscode, vue, or pug plugins. My syntax highlighting is destroyed in one file because something thinks that my javascript file is jsx. I saw something in my package.json about jsx and I removed it with no improvement. My file is a vue single-page-component with .vue suffix that uses pug. My other plain javascript files have no problem. The first few lines in the file are …

<template lang="pug">  
#all(style=`width:100%; height:95dvh; box-sizing: border-box;  

The error that appears in my problem list is JSX expressions must have one parent element..
This puts red underlines in every line of my file. The file still works but it is hard as hell to edit with that ugliness. I tried turning off all syntax checking by putting this in settings.json but the red lines are still there …

  "files.associations": {
    "*.*": "plaintext"
  }

My entire package.json is …

{
"name": "tv-series-client",
"version": "0.1.0",
"private": true,
"scripts": {
"serve-vite": "vite",
"build-vite": "vite build --base=/shows/",
"preview-vite": "vite preview"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/vue-fontawesome": "^3.0.0-5",
"axios": "^0.24.0",
"core-js": "^3.6.5",
"lodash": "^4.17.21",
"sweetalert2": "^11.14.5",
"vue": "^3.0.0"
},
"devDependencies": {
"@originjs/vite-plugin-commonjs": "^1.0.1",
"@vitejs/plugin-vue": "^2.3.2",
"@vitejs/plugin-vue-jsx": "^1.3.2",
"@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0",
"pug": "^3.0.2",
"pug-plain-loader": "^1.1.0",
"vite": "^2.7.2",
"vite-plugin-env-compatible": "^1.1.1",
"vite-plugin-html": "2.1.1"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {
"no-unused-vars": "off",
"no-debugger": "off",
"no-empty": "off"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

Any help would be appreciated.