Skip to content

Commit 4a497ec

Browse files
committed
Support using <script> tags directly.
Fixes #23. Some tools such as `next/head` rely on a script tag existing directly under the `<Head>` component. Allowing a react-schemaorg user just pass the props opaquely to a `<script>` tag gives us both encapsulation while getting the library to work. Our public API surface area is now effectivley 3 pieces: the original JSON-LD component, a function generating Helmet-style props, and this function, which generates plain JSX-style props for `<script>`.
1 parent 94e4245 commit 4a497ec

3 files changed

Lines changed: 66 additions & 13 deletions

File tree

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,39 @@ export function GraceHopper() {
5050
}
5151
```
5252

53+
### Directly creating `<script>` tags (for `next/head` and elsewhere)
54+
55+
Certain `<head>` management libraries require `<script>` tags to be directly
56+
included, rather than wrapped in a component. This includes NextJS's
57+
`next/head`, and `react-helmet`. With these, we can use the `jsonLdScriptProps`
58+
export to do the same thing:
59+
60+
```tsx
61+
import { Person } from "schema-dts";
62+
import { helmetJsonLdProp } from "react-schemaorg";
63+
import Head from "next/head";
64+
65+
export default function MyPage() {
66+
return (
67+
<Head>
68+
<script
69+
{...jsonLdScriptProps<Person>({
70+
"@context": "https://schema.org",
71+
"@type": "Person",
72+
name: "Grace Hopper",
73+
alternateName: "Grace Brewster Murray Hopper",
74+
alumniOf: {
75+
"@type": "CollegeOrUniversity",
76+
name: ["Yale University", "Vassar College"],
77+
},
78+
knowsAbout: ["Compilers", "Computer Science"],
79+
})}
80+
/>
81+
</Head>
82+
);
83+
}
84+
```
85+
5386
### [React Helmet](https://github.com/nfl/react-helmet) Usage
5487

5588
To set JSON-LD in React Helmet, you need to pass it to the `script={[...]}` prop

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
* limitations under the License.
1515
*/
1616

17-
export { helmetJsonLdProp, JsonLd } from "./json-ld";
17+
export { helmetJsonLdProp, JsonLd, jsonLdScriptProps } from "./json-ld";

src/json-ld.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,41 @@ export class JsonLd<T extends Thing> extends React.Component<
5050
}
5151
> {
5252
render() {
53-
return (
54-
<script
55-
type="application/ld+json"
56-
dangerouslySetInnerHTML={{
57-
__html: JSON.stringify(
58-
this.props.item,
59-
safeJsonLdReplacer,
60-
this.props.space
61-
),
62-
}}
63-
/>
64-
);
53+
return <script {...jsonLdScriptProps<T>(this.props.item, this.props)} />;
6554
}
6655
}
6756

57+
/**
58+
* Produces necessary props for a JSX <script> tag that includes JSON-LD.
59+
*
60+
* Can be used by spreading the props into a <script> JSX tag:
61+
*
62+
* ```tsx
63+
* <script {...jsonLdScriptProps<Person>({
64+
* "@context": "https://schema.org",
65+
* "@type": "Person",
66+
* name: "Grace Hopper",
67+
* alternateName: "Grace Brewster Murray Hopper",
68+
* alumniOf: {
69+
* "@type": "CollegeOrUniversity",
70+
* name: ["Yale University", "Vassar College"]
71+
* },
72+
* knowsAbout: ["Compilers", "Computer Science"]
73+
* })} />
74+
* ```
75+
*/
76+
export function jsonLdScriptProps<T extends Thing>(
77+
item: WithContext<T>,
78+
options: JsonLdOptions = {}
79+
): JSX.IntrinsicElements["script"] {
80+
return {
81+
type: "application/ld+json",
82+
dangerouslySetInnerHTML: {
83+
__html: JSON.stringify(item, safeJsonLdReplacer, options.space),
84+
},
85+
};
86+
}
87+
6888
/**
6989
* Produces a Helmet-style <script> prop for a given JSON-LD datum.
7090
*

0 commit comments

Comments
 (0)