{"id":29150322,"url":"https://github.com/humanmade/react-oembed-container","last_synced_at":"2025-06-30T23:10:18.701Z","repository":{"id":29571771,"uuid":"121773792","full_name":"humanmade/react-oembed-container","owner":"humanmade","description":"React container for rendering oembed scripts within HTML string content.","archived":false,"fork":false,"pushed_at":"2022-01-31T17:02:36.000Z","size":1424,"stargazers_count":43,"open_issues_count":5,"forks_count":13,"subscribers_count":18,"default_branch":"main","last_synced_at":"2025-06-04T10:07:19.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/humanmade.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-16T16:34:04.000Z","updated_at":"2023-01-21T19:07:30.000Z","dependencies_parsed_at":"2022-08-07T14:30:23.526Z","dependency_job_id":null,"html_url":"https://github.com/humanmade/react-oembed-container","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/humanmade/react-oembed-container","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanmade%2Freact-oembed-container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanmade%2Freact-oembed-container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanmade%2Freact-oembed-container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanmade%2Freact-oembed-container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/humanmade","download_url":"https://codeload.github.com/humanmade/react-oembed-container/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanmade%2Freact-oembed-container/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260677203,"owners_count":23045127,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-30T23:10:17.710Z","updated_at":"2025-06-30T23:10:18.673Z","avatar_url":"https://github.com/humanmade.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# oEmbedContainer\n\nThis package provides a React component wrapper to handle detecting and injecting script tags within HTML string content.\n\n[![Build Status](https://travis-ci.org/humanmade/react-oembed-container.svg?branch=master)](https://travis-ci.org/humanmade/react-oembed-container)\n\n## Background\n\nContent management system API endpoints like those in WordPress often return editorial content as HTML strings rather than structured data. `dangerouslySetInnerHTML` is required to properly render this HTML content within a React application, or else any markup embedded in that string will not display properly.\n\nPost content however may _also_ include `\u003cscript\u003e` tags, which have no effect when injected via `innerHTML` [per the HTML5 specification](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML). Scripts are nullified on `innerHTML` to prevent cross-site scripting attacks, but this means that any content which contains a valid script as part of its HTML content will not properly render.\n\nThis issue is particularly noticeable when dealing with [**oEmbed**](https://oembed.com/)ded content, such as embedded Twitter or Facebook posts. Because many of these social media providers return `\u003cscript\u003e` tags as part of their oEmbed response, WordPress will produce post content HTML which works fine when loaded from an application backend but which will not properly display embedded social content when rendered from React.\n\nFor example, WordPress will let you paste in a URL like `https://twitter.com/reactjs/status/964689022747475968` to the editor, then via an oEmbed request will convert it to the following rendered markup:\n\n```html\n\u003cblockquote class=\"twitter-tweet\" data-width=\"525\" data-dnt=\"true\"\u003e\n\u003cp lang=\"en\" dir=\"ltr\"\u003eWe\u0026#39;re relicensing React Native (including Fresco, Metro, and Yoga) under the MIT license to match React. \u003ca href=\"https://t.co/Ypg7ozX958\"\u003ehttps://t.co/Ypg7ozX958\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u0026mdash; React (@reactjs) \u003ca href=\"https://twitter.com/reactjs/status/964689022747475968?ref_src=twsrc%5Etfw\"\u003eFebruary 17, 2018\u003c/a\u003e\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003e\u003cscript async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"\u003e\u003c/script\u003e\u003c/p\u003e\n```\n\nThese oEmbed HTML responses may not contain any scripts. If so, great! React can render that easily. But if they do, they will either contain script tags with `src` attributes pointing at an external JavaScript file (as in the twitter example above), or else an inline `\u003cscript\u003e` tag with code that will create \u0026 inject a script into the DOM of the page as in Facebook's example:\n\n```html\n\u003cdiv id=\"fb-root\"\u003e\u003c/div\u003e\n\u003cp\u003e\u003cscript\u003e\n(function(d, s, id) {\n  var js, fjs = d.getElementsByTagName(s)[0];\n  if (d.getElementById(id)) return;\n  js = d.createElement(s); js.id = id;\n  js.src = 'https://connect.facebook.net/en_US/sdk.js#xfbml=1\u0026version=v2.12';\n  fjs.parentNode.insertBefore(js, fjs);\n}(document, 'script', 'facebook-jssdk'));\n\u003c/script\u003e\u003c/p\u003e\n```\n\nIn order to properly display inlined oEmbed content, we need to detect and inject both types of scripts.\n\n## A Note on Security\n\nTechnically what we're doing here is permitting arbitrary scripts injected into API responses to be rendered on the front-end of your site: under certain circumstances this can pose a security risk. However, these scripts would be rendered normally when loading this same markup from the server in a more traditional CMS-driven webpage rendering context.\n\nIt is up to the CMS to ensure that any scripts which make it far enough to be output on the page (or in API responses) are properly whitelisted or sanitized as necessary. Using WordPress as an example, only the responses from whitelisted oEmbed providers or content from highly authorized users may contain scripts at all; we therefore assume that any scripts inlined within the returned content are integral to the rendering of that content and should be loaded accordingly.\n\n## Installation\n\n```\nnpm install --save react-oembed-container\n```\n\nThis library has peerdependencies on `react-dom` and `react` v16. If you do not already have these in your project, run\n\n```\nnpm install --save react react-dom\n```\n\n## Usage\n\nImport the container element into your React component:\n\n```js\nimport EmbedContainer from 'react-oembed-container';\n```\n\nThen use this container to wrap whatever JSX you would normally use to render the content:\n\n```js\nrender() {\n  const { post } = this.props;\n  return (\n    \u003cEmbedContainer markup={post.content.rendered}\u003e\n\n      {/* for example, */}\n      \u003carticle id={`post-${post.id}`}\u003e\n        \u003ch2\u003e{ post.title.rendered }\u003c/h2\u003e\n        \u003cdiv dangerouslySetInnerHTML={{ __html: post.content.rendered }} /\u003e\n      \u003c/article\u003e\n\n    \u003c/EmbedContainer\u003e\n  );\n}\n```\n\nIf you set a `className` on the `EmbedContainer` component, that class will be passed through to the rendered `\u003cdiv\u003e` container:\n\n```js\nrender() {\n  const { post } = this.props;\n  return (\n    \u003cEmbedContainer\n      className=\"article-content\"\n      markup={post.content.rendered}\n    \u003e\n      \u003cp\u003eArticle text here\u003c/p\u003e\n    \u003c/EmbedContainer\u003e\n  );\n}\n```\nyields\n```html\n\u003cdiv class=\"article-content\"\u003e\u003cp\u003eArticle text here\u003c/p\u003e\u003c/div\u003e\n```\n\n## Local Development\n\nRun `npm install` to pull down the dependencies for local development. Linting with ESLint is handled through `npm run lint`, and the Jest tests are run with `npm test`.\n\nTo work on this component, either use [`npm link`](https://docs.npmjs.com/cli/link) to bring it into another project for testing or else run `npm run storybook` within this repository to spin up a [Storybook](https://storybook.js.org/) UI development environment. This environment should be available locally at [localhost:6006](http://localhost:6006).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanmade%2Freact-oembed-container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhumanmade%2Freact-oembed-container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanmade%2Freact-oembed-container/lists"}