Does attributeChangedCallback fire when a property is set programmatically?

If we define a property like this on a color-span custom element:

  static get observedAttributes() {
    return ['bgc'];
  }

And get a reference to an instance like this while also changing the bgc property, should that cause the attributeChangedCallback to fire?

const colorSpan = document.querySelector('color-span');
console.log(colorSpan);
colorSpan.bgc = 'BLUE';

I tried it in this demo, and it does not fire, so I just wanted to confirm my understanding that the attributeChangedCallback will only fire when an attribute is set declaratively like this:

<color-span bgc="RED">Hello From Color Span</color-span>

JS function breaks – ancestor is null

Trying to troubleshoot why this function is failing and my JS is very very rusty. It’s intended to collapse/expand sections on the page and works when expanding, but then breaks when it’s clicked again and is supposed to collapse that section.
browser debug message

Here’s the calling function (screenshot):

calling function screenshot

Here’s the calling function (full code):

NS.run_expansion = function(categorynode) {
    var categorychildren = categorynode.one(SELECTORS.CONTENTNODE),
        self = this,
        ancestor = categorynode.ancestor(SELECTORS.COURSECATEGORYTREE);

    // Add our animation to the categorychildren.
    this.add_animation(categorychildren);


    // If we already have the class, remove it before showing otherwise we perform the
    // animation whilst the node is hidden.
    if (categorynode.hasClass(CSS.SECTIONCOLLAPSED)) {
        // To avoid a jump effect, we need to set the height of the children to 0 here before removing the SECTIONCOLLAPSED class.
        categorychildren.setStyle('height', '0');
        categorynode.removeClass(CSS.SECTIONCOLLAPSED);
        categorynode.setAttribute('aria-expanded', 'true');
        categorychildren.fx.set('reverse', false);
    } else {
        categorychildren.fx.set('reverse', true);
        categorychildren.fx.once('end', function(e, categorynode) {
            categorynode.addClass(CSS.SECTIONCOLLAPSED);
            categorynode.setAttribute('aria-expanded', 'false');
        }, this, categorynode);
    }

    categorychildren.fx.once('end', function(e, categorychildren) {
        // Remove the styles that the animation has set.
        categorychildren.setStyles({
            height: '',
            opacity: ''
        });

        // To avoid memory gobbling, remove the animation. It will be added back if called again.
        this.destroy();
        self.update_collapsible_actions(ancestor);
    }, categorychildren.fx, categorychildren);

    // Now that everything has been set up, run the animation.
    categorychildren.fx.run();
};

And then fails here (screenshot):

failing function screenshot

Failing function (full code):

NS.update_collapsible_actions = function(ancestor) {
    var foundmaximisedchildren = false,
        // Grab the anchor for the collapseexpand all link.
        **togglelink = ancestor.one(SELECTORS.COLLAPSEEXPAND);**

    if (!togglelink) {
        // We should always have a togglelink but ensure.
        return;
    }

    // Search for any visibly expanded children.
    ancestor.all(SELECTORS.CATEGORYWITHMAXIMISEDLOADEDCHILDREN).each(function(n) {
        // If we can find any collapsed ancestors, skip.
        if (n.ancestor(SELECTORS.CATEGORYWITHCOLLAPSEDLOADEDCHILDREN)) {
            return false;
        }
        foundmaximisedchildren = true;
        return true;
    });

    if (foundmaximisedchildren) {
        // At least one maximised child found. Show the collapseall.
        togglelink.setHTML(M.util.get_string('collapseall', 'moodle'))
            .addClass(CSS.COLLAPSEALL)
            .removeClass(CSS.DISABLED);
    } else {
        // No maximised children found but there are collapsed children. Show the expandall.
        togglelink.setHTML(M.util.get_string('expandall', 'moodle'))
            .removeClass(CSS.COLLAPSEALL)
            .removeClass(CSS.DISABLED);
    }
};

I have Googled this and played around with the code a bit, but I’m not making any headway. As I said, my JS is very rusty, so please be kind 🙂

Expo drawer and @react-navigation/material-top-tabs conflict

I’m getting to grips with React Native and have been following the official guide to go the Expo route.

I have implemented the Expo drawer nav, but with one of my routes I am wanting tabs on the top which led me to @react-navigation/material-top-tabs. However, after adding this to my page file, I am facing the error:

Uncaught Error
Looks like you have nested a ‘NavigationContainer’ inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, wrap the container in ‘NavigationIndependentTree’ explicitly. Note that this will make the child navigators disconnected from the parent and you won’t be able to navigate between them.

After looking into the error a bit more it sounds like there will be a NavigationContainer used in both the Expo drawer and the react-navigation components, and anything else I’ve looked into shows examples of using react-navigation’s own drawer nav.

Is there a way in which I can integrate Expo’s drawer with the react-navigation tabs? Or is it worth refactoring to use react-navigation’s drawer instead, given it’s still early stages?

app/_layout.tsx

export default function Layout() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <Drawer>
        {/* other drawer screens */}
        <Drawer.Screen
          name="history" // This is the name of the page and must match the url from root
          options={{
            drawerLabel: 'History',
            title: 'History',
          }}
        />
      </Drawer>
    </GestureHandlerRootView>
  )
}

app/index.tsx

const MyTabs = createMaterialTopTabNavigator({
  screens: {
    Day: HistoryDay, // app/history/day.tsx
    // other screens
  },
});

const TabNavigation = createStaticNavigation(MyTabs);

export default function Index() {
  return (
    <View style={layoutStyles.centeredView}>
      <TabNavigation />
    </View>
  );
}

Identifying issue from character number in compiled node application error logs

I have a node service using express server deployed in production. Internally, it spawns an headless chrome, opens a webpage(developed on react), takes a screenshot of it & returns the screenshot. We are seeing that an issue occurs during rendering of the page causing an exception. We have traced down to the react component where the issue occurs but unable to move forward.

As a last hope, I am trying to see if there is a way to trace back the source(line number in source code maybe?) of failure from the (compiled)application logs using the character number in exception trace logs. They look like as follows,

(Custom-Apollo-Hooks)(] Encountered error) {

errno: 'ECONNRESET',

syscall: 'read',

at /xxxxxx/release_cache/e06cb96d022322dhgs4f5999d4dc5679cf/xx/xx-xxxxxxxx/xxxxxx-service/xxxx/xxxx-server.js:2:57242

at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {

at Logger$F.error (https://127.0.0.1//v1/js/module/app-aafde331.js:1:49395)

at ps (https://cdn.skypack.dev/-/[email protected]/dist=es2020,mode=imports,min/optimized/react-dom.js:9:9574)

at Ja (https://cdn.skypack.dev/-/[email protected]/dist=es2020,mode=imports,min/optimized/react-dom.js:9:864)

at Tt (https://127.0.0.1//v1/js/module/my-react-component-name.container-52c6ce99.js:1:25073)

I have the compiled JS file, the source code from which it is created. Is there a way to get hints from the character number “57242”(or the ones below) to understand which variable is null, or which line has the issue?

The webpage calls on our graphql APIs to render, hence the apollo hook log, I know the failure is likely related to the API call, here the intent is to map it to the source code as precisely as possible.

In Payload CMS, how can I have the defaultValue of a field be assigned as the description, automatically?

I’ve inherited a Payload CMS project and I have a component like this.

I want to get the the defaultValue, which is a global string, and show it as the description value. Then you don’t have to navigate to the global string page to see what it is.

export const CardInstructionTitle: Field = {
  type: "row",
  fields: [
    {
      name: "title",
      type: "group",
      fields: [
        {
          name: "default",
          type: "checkbox",
          label: "Use Default Instruction",
          defaultValue: true,
          admin: {
          description: `The default value is:  ${defaultValue} (it would be great if this worked) `,
           },
        },
        {
          name: "text",
          type: "text",
          admin: {
            components: {
              Field: Component,
            },
          },
          localized: true,
        },
      ],
    },
  ],
};

CardInstructionTitle is used by a few different Block types, so I pass the name of the block like this…

export const SelectThePairsCard: Block = {
  slug: "selectThePairs",
  interfaceName: "SelectThePairsFields",
  fields: [
    CardInstructionTitle("selectThePairs"),
    {
      name: "wordPairs",
      type: "array",
      fields: [
        {
          type: "row",
          fields: [
            {
              name: "firstWord",
              type: "text",
            },
            {
              name: "secondWord",
              type: "text",
            },
          ],
        },
      ],
    },
  ],
};

…and use this string to fetch the defaultValue.

 
const getDefaultValue = async (defaultTitle) => {
  let locale = "fr"
  try {
    const response = await fetch(`/payload/api/globals/cardInstructionTitles?locale=${locale}`);
    
    if (!response.ok) {
      throw new Error(`Failed to fetch: ${response.statusText}`);
    }

    const data = await response.json();
    const value = data[defaultTitle];

    if (typeof value !== 'string') {
      throw new Error(`Invalid default value for ${defaultTitle}`);
    }

    return value;
  } catch (error) {
    console.error(`Error fetching default value: ${error.message}`);
    return `Error fetching value for ${defaultTitle}`;
  }
};

And put it in CardInstructionTitle


export const CardInstructionTitle: (parentName: string) => Field = (parentName: string) => {

  return {
  type: "row",
  fields: [
    {
      name: "title",
      type: "group",
      fields: [
        {
          name: "default",
          type: "checkbox",
          label: "Use Default Instruction",
          defaultValue: true,
          admin: {
            description: getDefaultValue(parentName),
          }
        },
        {
          name: "text",
          type: "text",
          admin: {
            components: {
              Field: Component,
            },
          },
          localized: true,
        },
      ],
    },
  ],
  }
};

Except that it doesn’t seem that the description field is allowed to accept an async value because I keep getting an error saying it’s:

   The types of 'admin.description' are incompatible between these types.
     Type 'Promise<string>' is not assignable to type 'Description | undefined'.
     Type 'Promise<string>' is not assignable to type 'Record<string, string>'.
     Index signature for type 'string' is missing in type 'Promise<string>'.

So, is there a better way to do this? Logically it seems like the defaultValue must be available nearby but how do I assign it to the description, or should I do another approach, like create a new component that just displays defaultValues?

I’m new to Payload and TypeScript so any help would be greatly appreciated, Thanks.

It is Payload version 2

Trying to combine two languages in CodeMirror 6

I’m trying to add a new language that is used in the HTML code in Code Mirror.

I already have the HTML being parsed properly for the syntax coloring, but I can’t find a way to add the language inside the HTML.

It’s Jinja2.

Here’s what I’ve done:

import { StreamLanguage, LanguageSupport} from '@codemirror/language'
import { htmlLanguage } from '@codemirror/lang-html'
import {jinja2} from '@codemirror/legacy-modes/mode/jinja2'

import {EditorView, basicSetup} from 'codemirror'

function jinja2WithHtml () {
  const jinja2Lang = StreamLanguage.define(jinja2)

  return new LanguageSupport(jinja2Lang, [htmlLanguage])
}

let view = new EditorView({
  extensions: [basicSetup, jinja2WithHtml()]
})

This doesn’t work.

Ideally, I’d like to keep syntax coloring for HTML, and also have syntax coloring for Jinja2 along with it.

How can I do?

Thanks !

INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST” When Inserting Value

I have an object Pedido__c with a picklist field named Direccion_entrega__CountryCode__s.
The picklist values are correctly configured in Salesforce (e.g., “Spain”).
I also have an object sl_obj_address__c, from which I am retrieving address information, including the country (sl_fld_core_country__c). Below is my code for inserting a record into the Pedido__c object:

// Retrieve the selected address
sl_obj_address__c direccion = [
    SELECT sl_fld_core_street__c, sl_fld_core_zip_code__c, sl_fld_core_city__c,
           sl_fld_core_state_province_department__c, sl_fld_core_country__c
    FROM sl_obj_address__c
    WHERE Id = :direccionId
    LIMIT 1
];

// Create Pedido
Pedido__c pedido = new Pedido__c();
pedido.Cuenta__c = cuentaId;
pedido.Direccion_entrega__Street__s = direccion.sl_fld_core_street__c;
pedido.Direccion_entrega__PostalCode__s = direccion.sl_fld_core_zip_code__c;
pedido.Direccion_entrega__City__s = direccion.sl_fld_core_city__c;
pedido.Direccion_entrega__StateCode__s = direccion.sl_fld_core_state_province_department__c;
pedido.Direccion_entrega__CountryCode__s = direccion.sl_fld_core_country__c; // This is the picklist field
insert pedido;

Error: When I try to insert the Pedido__c record, I get the following error: “INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST: Delivery Address (Country/Territory): inappropriate value for restricted picklist field: Spain”

I verified that the value being retrieved (direccion.sl_fld_core_country__c) is “Spain” and matches a value in the picklist.
I checked the allowed picklist values, and they are correctly configured in Salesforce.
I tested inserting the same value manually via Salesforce UI, and it works without issues.
What could be causing this error if the value being inserted matches one of the allowed picklist values? Is there anything else I need to configure or consider?

Error message in Salesforce showing INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST for CountryCode field

How to access and existing AWS s3 bucket?

Am I trying to upload an image to my AWS s3 bucket However, I am getting this error

[AccessDenied: User: arn:aws:sts::543216048669:assumed-role/amplify-myproject-dev-125332-unauthRole/CognitoIdentityCredentials is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::myproject-dev/folder/image" because no identity-based policy allows the s3:PutObject action]

500 Internal Server Error in Jest Test for Express App Using Supertest

I’m encountering a 500 Internal Server Error when running a Jest test for my Express app using Supertest, but the app works fine when run normally (e.g., in a browser or Postman). I suspect the issue lies in the test setup, but I’m unable to pinpoint the exact cause.

This is the error message when running npm test

$ npm test

> [email protected] test
> cross-env NODE_OPTIONS=--experimental-vm-modules jest

(node:16440) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
 FAIL  tests/movies.test.js
  Ă— Home page shows list of movies and navigation links (31 ms)

  â—Ź Home page shows list of movies and navigation links

    expected 200 "OK", got 500 "Internal Server Error"

      33 |   );
      34 |
    > 35 |   const response = await request(app).get('/').expect('Content-Type', /html/).expect(200);
         |                                                                               ^
      36 |
      37 |   expect(response.text).toMatch('Pulp Fiction');
      38 |   expect(response.text).toMatch('Fire Walk With Me');

      at Object.expect (tests/movies.test.js:35:79)
      ----
      at Test._assertStatus (node_modules/supertest/lib/test.js:252:14)
      at node_modules/supertest/lib/test.js:308:13
      at Test._assertFunction (node_modules/supertest/lib/test.js:285:13)
      at Test.assert (node_modules/supertest/lib/test.js:164:23)
      at Server.localAssert (node_modules/supertest/lib/test.js:120:14)

Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.617 s, estimated 1 s
Ran all test suites.

I’ll provide some of my code
movies.test.js

import { expect, test } from '@jest/globals';
import request from 'supertest';
import { fetchAllMovies, fetchMovie } from '../src/js/server/fetchMovies.js';
import startApp from '../src/js/server/app.js';

test('Home page shows list of movies and navigation links', async () => {
  const app = startApp(
    {
      fetchMovie: async () => ({
        id: 1,
        title: 'Pulp Fiction',
      }),
      fetchAllMovies: async () => [
        { id: 1, title: 'Pulp Fiction' },
        { id: 2, title: 'Fire Walk With Me' },
        { id: 3, title: 'Isle of Dogs' },
      ],
    },
    {
      navLinks: async () => ({
        headerData: [
          { label: 'BILJETTER', id: 'biljetter', link: '#' },
          { label: 'EVENEMANG', id: 'evenemang', link: '#' },
          { label: 'FILMER', id: 'filmer', link: 'movies' },
        ],
        footerSection1: [
          { label: 'OM KINO', link: 'about' },
          { label: 'FRĂ…GOR SVAR', link: '#' },
          { label: 'KONTAKTA OSS', link: '#' },
        ],
      }),
    }
  );

  const response = await request(app).get('/').expect('Content-Type', /html/).expect(200);

  expect(response.text).toMatch('Pulp Fiction');
  expect(response.text).toMatch('Fire Walk With Me');
  expect(response.text).toMatch('Isle of Dogs');

  expect(response.text).toMatch('BILJETTER');
  expect(response.text).toMatch('EVENEMANG');
  expect(response.text).toMatch('FILMER');
});

server.js

import startApp from './src/js/server/app.js';
import { fetchAllMovies, fetchMovie } from './src/js/server/fetchMovies.js';
import navLinks from './src/js/server/navLinks.js';

const api = {
  fetchMovie,
  fetchAllMovies,
};

const nav = {
  navLinks,
};

const app = startApp(api, nav);

const PORT = process.env.PORT || 5080;
app.listen(5080, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

app.js

import express from 'express';
import ejs from 'ejs';
import { marked } from 'marked';

function startApp(api, nav) {
  const app = express();

  app.locals.formatMarkdown = (text) => marked(text);
  app.set('view engine', 'ejs');

  app.get('/', async (req, res) => {
    const linkData = await nav.navLinks();
    const moviesData = await api.fetchAllMovies();
    res.render('pages/index', { moviesData, ...linkData });
  });

  app.get('/movies', async (req, res) => {
    const linkData = await nav.navLinks();
    const moviesData = await api.fetchAllMovies();
    res.render('pages/allMovies', { moviesData, ...linkData });
  });

  app.get('/movie/:movieId', async (req, res) => {
    const linkData = await nav.navLinks();
    const movieData = await api.fetchMovie(req.params.movieId);
    res.render('pages/movie', { movieData, ...linkData });
  });

  app.use('/static', express.static('./static'));

  app.use((req, res) => {
    const linkData = nav.navLinks();
    res.status(404).render('pages/error', { message: 'Page not found', ...linkData });
  });

  return app;
}

export default startApp;

navLinks.js

const headerData = [
  {
    label: 'BILJETTER',
    id: 'biljetter',
    link: '#',
  },
  {
    label: 'EVENEMANG',
    id: 'evenemang',
    link: '#',
  },
  {
    label: 'FILMER',
    id: 'filmer',
    link: 'movies',
  },
  {
    label: 'MEDLEMSKAP',
    id: 'medlemskap',
    link: '#',
  },
  {
    label: 'OM OSS',
    id: 'omoss',
    link: 'about',
  },
];

const footerSection1 = [
  { label: 'OM KINO', link: 'about' },
  { label: 'FRĂ…GOR SVAR', link: '#' },
  { label: 'KONTAKTA OSS', link: '#' },
];

const footerSection2 = [
  { label: 'PRESENTKORT', link: '#' },
  { label: 'TILLGÄNGLIGHET', link: '#' },
  { label: 'MEDLEMSKAP', link: '#' },
  { label: 'BISTRO-BIO', link: '#' },
  { label: 'EVENEMANG', link: '#' },
];

const footerSection3 = [
  { label: 'FACEBOOK', link: '#' },
  { label: 'INSTAGRAM', link: '#' },
];

export default function navLinks() {
  return {
    headerData,
    footerSection1,
    footerSection2,
    footerSection3,
  };
}
  • Run the app normally: When I start the app and visit http://localhost:5080 in my browser, it works fine. I see the movie list as expected.
  • Added logging: I added a global error handler and logged the error, but the error is not logged in the console during the test.
  • Mock data: I confirmed that the mocked fetchAllMovies is being called and returns the correct data.
  • Simplified test: I replaced the test with a basic request to ‘/’ with no expectations or assertions, but the 500 error persists.

How can I integrate InteractJS with GrapesJS

I’m making a website builder using GrapesJS. I want to use the resize functionality of InteractJS within my project. I have used “component:selected” to initilize the interactJS. But when the element got selected it is not being resizable.

Here is my cod`editor.on(“component:selected”, (model) => {
const el = model.view.el;

    // check for id 
    const id = el.getAttribute("id");


    interact('#' + id)
        .resizable({
            edges: { top: true, left: true, bottom: true, right: true },
            inertia: true,

            listeners: {
                move: function (event) {
                    const target = event.target;

                    // Get current position from data attributes or default to 0
                    let x = (parseFloat(target.getAttribute('data-x')) || 0);
                    let y = (parseFloat(target.getAttribute('data-y')) || 0);

                    // Update the element's width and height
                    target.style.width = event.rect.width + 'px';
                    target.style.height = event.rect.height + 'px';

                    // Update position based on the resize changes
                    x += event.deltaRect.left;
                    y += event.deltaRect.top;

                    // Apply the transform to maintain position
                    target.style.transform = `translate(${x}px, ${y}px)`;

                    // Store the position for future reference
                    target.setAttribute('data-x', x);
                    target.setAttribute('data-y', y);
                }
            }

        });

});`

Why can’t I access the property of an object from a function located in an array of functions [duplicate]

shouldn’t it be able to access the object “something”?

var problem = {
    
    something: {thing:23},
    somethingElse: [function(){return this.something.thing}]
    
};
console.log(problem.somethingElse[0]()); //Gives undefined error

I tried to access an object property from a function located within an array of functions, but it looks like it’s not within the scope of the function. why is this?

converting text annotations to React Component

I need to convert the following text annotations to react component, but this fails in an edge case.

Annotations:

[
  {
    "text": "",
    "stop": [],
    "start": [
      {
        "index": 0,
        "length": 8,
        "name": "bold",
        "value": "true"
      },
      {
        "index": 0,
        "length": 133,
        "name": "italic",
        "value": "true"
      }
    ]
  },
  {
    "text": "Ra",
    "stop": [],
    "start": [
      {
        "index": 2,
        "length": 3,
        "name": "underline",
        "value": "true"
      }
    ]
  },
  {
    "text": "van",
    "stop": [
      {
        "index": 2,
        "length": 3,
        "name": "underline",
        "value": "true"
      }
    ],
    "start": []
  },
  {
    "text": "a: ",
    "stop": [
      {
        "index": 0,
        "length": 133,
        "name": "italic",
        "value": "true"
      },
      {
        "index": 0,
        "length": 8,
        "name": "bold",
        "value": "true"
      }
    ],
    "start": [
      {
        "index": 0,
        "length": 133,
        "name": "italic",
        "value": "true"
      }
    ]
  },
  {
    "text": "Kubera would not allow me to borrow his vimana. When I asked if you could study it for reverse engineering, he refused again.",
    "stop": [
      {
        "index": 0,
        "length": 133,
        "name": "italic",
        "value": "true"
      }
    ],
    "start": []
  },
  {
    "text": "n",
    "stop": [],
    "start": [
      {
        "index": 134,
        "length": 9,
        "name": "bold",
        "value": "true"
      },
      {
        "index": 134,
        "length": 206,
        "name": "italic",
        "value": "true"
      }
    ]
  },
  {
    "text": "Mayasura:",
    "stop": [
      {
        "index": 134,
        "length": 206,
        "name": "italic",
        "value": "true"
      },
      {
        "index": 134,
        "length": 9,
        "name": "bold",
        "value": "true"
      }
    ],
    "start": [
      {
        "index": 134,
        "length": 206,
        "name": "italic",
        "value": "true"
      }
    ]
  },
  {
    "text": " Well, from Kubera’s perspective, he did the right thing. You lost your temper because your wish was rejected. Instead of wasting your energy destroying things, why don’t we channelise it to build?",
    "stop": [
      {
        "index": 134,
        "length": 206,
        "name": "italic",
        "value": "true"
      }
    ],
    "start": []
  }
]

Code for conversion

export interface Annotation {
  index: number;
  length: number;
  name: string;
  value: string;
}

export interface AnnotationExtract {
  text: string;
  stop: Annotation[];
  start: Annotation[];
}

function AnnotateText({ text, tag }: { text: React.ReactNode; tag: string }) {
  const tagMapper: { [key: string]: string } = {
    bold: "b",
    italic: "i",
    underline: "u",
  };

  if (!tagMapper[tag]) {
    return React.Fragment({
      children: text,
    });
  }

  return React.createElement(tagMapper[tag], {}, text);
}

export function applyAnnotations(
  operations: AnnotationExtract[]
): React.ReactNode[] {
  const result: React.ReactNode[] = [];
  let temp_result: React.ReactNode[] = [];
  const tag_stack: string[] = [];

  for (let i = 0; i < operations.length; i++) {
    const op = operations[i];

    if (tag_stack.length == 0) {
      result.push(op.text);
    } else {
      temp_result.push(op.text);
    }

    if (op.stop.length > 0) {
      for (let i = 0; i < op.stop.length; i++) {
        const cur_op = op.stop[i];
        if (
          tag_stack[tag_stack.length - 1] == cur_op.name &&
          temp_result.length > 0
        ) {
          const text = temp_result.pop();
          const t = tag_stack.pop();

          if (t) {
            temp_result.push(
              AnnotateText({
                tag: t,
                text: text,
              })
            );
            temp_result = [
              temp_result.reduce(
                (acc: React.ReactNode, cur: React.ReactNode) => {
                  return React.createElement(React.Fragment, {}, acc, cur);
                },
                React.createElement(React.Fragment)
              ),
            ];
          }
        }
      }

      if (tag_stack.length == 0) {
        result.push(temp_result.pop());
      }
    }

    if (op.start.length > 0) {
      tag_stack.push(...op.start.map((e) => e.name));
    }
  }

  console.log(result);

  return result;
}

Expected result

<bold><italic>Ra<underline>van</underline>a: </italic></bold><italic>Kubera would not allow me to borrow his vimana. When I asked if you could study it for reverse engineering, he refused again.</italic>
<bold><italic>Mayasura:</italic></bold><italic>Well, from Kubera’s perspective, he did the right thing. You lost your temper because your wish was rejected. Instead of wasting your energy destroying things, why don’t we channelise it to build?</italic>

Actual Result

<bold>Ra<underline>van</underline><italic>a: </italic></bold><italic>Kubera would not allow me to borrow his vimana. When I asked if you could study it for reverse engineering, he refused again.</italic>
<bold><italic>Mayasura:</italic></bold><italic> Well, from Kubera’s perspective, he did the right thing. You lost your temper because your wish was rejected. Instead of wasting your energy destroying things, why don’t we channelise it to build?</italic>

Everything works fine, until I encounter an overlapping annotation.

Those bold and italic should be a wrapper like this <bold><italic>Ra<underline>van</underline>a: </italic></bold>

but it is rendered like this <bold>Ra<underline>van</underline><italic>a: </italic></bold>

Could anyone point out what is wrong here?

Cannot use firebaseui when imported as CDN module

I’m trying to get a very basic email/password sign-in working on my firebase website.

I must be importing firebaseui wrong. I’m attempting to import it as a CDN like so:

import * as firebaseui from 'https://www.gstatic.com/firebasejs/ui/6.1.0/firebase-ui-auth.js';

This is because I’m not using a bundler. I’m trying to mimic importing it as a namespace like all the tutorials show (import * as firebaseui from 'firebaseui';). When importing as a cdn like above and then running this code:

// Firebase Config
const firebaseConfig = {
    // ...
};

const app = initializeApp(firebaseConfig);
const authInstance = getAuth();


// FirebaseUI config
const uiConfig = {
    credentialHelper: firebaseui.auth.CredentialHelper.NONE,
    signInOptions: [
        EmailAuthProvider.PROVIDER_ID,
    ],
    callbacks: {
        signInSuccessWithAuthResult: function (authResult, redirectUrl) {
            return false;
        },
    },
};
// Initialize the FirebaseUI widget using Firebase:
const ui = new firebaseui.auth.AuthUI(authInstance);

I get this console error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘CredentialHelper’)

Commenting out the credentialHelper line also results in a similar error, but with the firebaseui.auth.AuthUI(authInstance) line.

However:

If I instead source the firebaseui script and run my script directly in the html file…

<!-- ...head... -->

<link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/6.1.0/firebase-ui-auth.css" />
    <script src="https://www.gstatic.com/firebasejs/ui/6.1.0/firebase-ui-auth.js"></script>

    <script type="module">
        import { initializeApp } from 'https://www.gstatic.com/firebasejs/11.1.0/firebase-app.js';

        import { collection, getDocs, getFirestore } from 'https://www.gstatic.com/firebasejs/11.1.0/firebase-firestore.js';

        import { EmailAuthProvider, getAuth, signOut, onAuthStateChanged } from 'https://www.gstatic.com/firebasejs/11.1.0/firebase-auth.js';

        // Initial variables
        let db, auth;

        // ...

        async function main() {
            // function that runs on page load
            // Firebase Config
            const firebaseConfig = {
                // ...
            };

            // Firebase/Firestore variables
            const app = initializeApp(firebaseConfig);
            const authInstance = getAuth();
            const db = getFirestore(app);


            // FirebaseUI config
            const uiConfig = {
                credentialHelper: firebaseui.auth.CredentialHelper.NONE,
                signInOptions: [
                    // Email / Password Provider.
                    EmailAuthProvider.PROVIDER_ID,
                ],
                callbacks: {
                    signInSuccessWithAuthResult: function (authResult, redirectUrl) {
                        // Handle sign-in.
                        // Return false to avoid redirect.
                        return false;
                    },
                },
            };
            // Initialize the FirebaseUI widget using Firebase:
            const ui = new firebaseui.auth.AuthUI(authInstance);
//...

This works perfectly and I get the email login section.

What am I doing wrong in the first attempt? I’d prefer to keep the script as a separate js file.

Thanks and sorry if I misuse some terms, I’m very new to all of this.

Fetching and displaying images take 5 seconds

I am trying to display pictures on a custom responsive gallery from Imgix. It takes 5 seconds for the images to be displayed.

I am using Next.js and here is the code:

const sourceId: string | undefined = process.env.NEXT_PUBLIC_SOURCE_ID;
const apiKey: string | undefined = process.env.NEXT_PUBLIC_API_KEY;
const domain: string | undefined = process.env.NEXT_PUBLIC_IMGIX_DOMAIN;

interface Image {
    id: string;
    url: string;
    alt: string;
}

const Previews: React.FC = () => {
    const [images, setImages] = useState<Image[]>([]);

    const buildURL = (imagePath: string): string => `https://${domain}/${imagePath}`;

    const fetchImages = async () => {
        const allImages: Image[] = [];
        let cursor: string | null = null;
        let hasMore: boolean = true;
        const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

        do {
            const url = new URL(`https://api.imgix.com/api/v1/sources/${sourceId}/assets`);

            if (cursor) {
                url.searchParams.append("page[cursor]", cursor);
            }

            const response = await fetch(url, {
                headers: {
                    Authorization: `Bearer ${apiKey}`,
                },
            });

            if (!response.ok) {
                if (response.status === 429) {
                    console.log("Rate limit exceeded, waiting before retrying...");
                    await delay(1000);
                    continue;
                } else {
                    throw new Error(`Failed to fetch: ${response.statusText}`);
                }
            }

            const data = await response.json();

            for (const image of data.data) {
                console.log(image);
                if (image.attributes.categories && image.attributes.categories.includes("insects")) {
                    allImages.push({ image });
                    continue;
                }
            }
            console.log(allImages);
            // allImages.push(...data.data);
            cursor = data.meta.cursor.next;

            hasMore = data.meta.cursor.hasMore;
            await delay(500);
        } while (hasMore);

        return allImages;
    };

    useEffect(() => {
        fetchImages().then((images) => {
            console.log(images);
            setImages(images);
        });
    }, []);

    return (
        <div className={styles.container}>
            <DropdownMenu />
            <div className={styles.previewscontainer}>
                {images.map((image, i) => (
                    <Imgix
                        className={styles.preview}
                        key={i}
                        sizes="(min-width: 960px) 33vw, (min-width: 640px) 50vw, 100vw"
                        src={buildURL(image.image.attributes.origin_path)}
                        imgixParams={{
                            fit: "crop",
                            fm: "webp",
                        }}
                        width={250}
                        height={250}
                        alt={image.image.attributes.alt_text}
                    />
                ))}
            </div>
        </div>
    );
};

Maybe it’s for the do while loop? I don’t know. As you can see in the props I’m formatting the images to webp (they are jpgs). If I fetch all images, not only the “insects” category it takes the same amount of time. This component is implemented in a larger page.