3

The problem can be seen here

I built a site using Sanity headless CMS and GatsbyJS on the frontend.

I'm querying URLs dynamically so that it can be rendered inside the src attribute of an </iframe> The problem is when the user adds an URL containing &amp, pretty common for Google Calendar's embed code.

With &amp The link no longer works and the calendar breaks (goes blank). Unless I hardcode it directly in the src which is exactly what we want to avoid.

How can I mitigate/escape this issue and have it so I can render the URL accordingly?

I've looked into encodeURI , encodeURIComponent, even tried this custom function:

function htmlEntities(str) {
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

No dice...

  • Looking for a client-side JS solution or backend solution, if possible to do so, inside Sanity's ecosystem

My current implementation

// sanity schema
export default {
  type: 'document',
  title: 'Google Calendar',
  name: 'calendar',
  fields: [
    {
      type: 'string',
      name: 'Title',
    },
    {
      type: 'url',
      name: 'URL',
      validation: (Rule) => Rule.required(),
    },
  ],
};

//gastby 
export default function GoogleCalendar() {
  const { calendar } = useStaticQuery(graphql`
    query {
      calendar: allSanityCalendar {
        nodes {
          URL
          Title
        }
      }
    }
  `);

  if (!calendar.nodes.length) return null;
  return (
    <>
      <div>
        {calendar.nodes.map((node) => (
          <iframe
            src={node.URL}
            id="test"
            title={node.Title}
            width="100%"
            height="1000px"
            async
          />
        ))}
      </div>
    </>
  );
}

Here's a sandbox illustrating the issue: https://stackblitz.com/edit/iframe-dynamic-src

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
Null isTrue
  • 1,882
  • 6
  • 26
  • 46

1 Answers1

1

Here you have your sandbox working: https://iframe-dynamic-src-pmxqbb.stackblitz.io

I've fixed it by:

  <iframe
    src={decodeURIComponent(
      encodeURIComponent(brokeUrl.replace(/&amp;/g, "&"))
    )}
    width="800"
    height="600"
    frameborder="0"
    scrolling="no"
    content
  />

Decoding an encoded URL that replaces globally the ampersands (&amp;) by &.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
  • 1
    brillant! thank you so very much - any concerns w/ doing this on client-side as opposed to server-side? – Null isTrue Dec 24 '20 at 16:31
  • 1
    Well, any computation effort that you can save to the client is performance earnt but it always depends on your setup, the use-cases (especially)/needs, and capabilities – Ferran Buireu Dec 24 '20 at 17:45