import React from "react"; import { OPTIMIZED_FONT_PROVIDERS, NEXT_BUILTIN_DOCUMENT } from "../shared/lib/constants"; import { getPageFiles } from "../server/get-page-files"; import { htmlEscapeJsonString } from "../server/htmlescape"; import isError from "../lib/is-error"; import { HtmlContext, useHtmlContext } from "../shared/lib/html-context.shared-runtime"; /** Set of pages that have triggered a large data warning on production mode. */ const largePageDataWarnings = new Set(); function getDocumentFiles(buildManifest, pathname, inAmpMode) { const sharedFiles = getPageFiles(buildManifest, "/_app"); const pageFiles = process.env.NEXT_RUNTIME !== "edge" && inAmpMode ? [] : getPageFiles(buildManifest, pathname); return { sharedFiles, pageFiles, allFiles: [ ...new Set([ ...sharedFiles, ...pageFiles ]) ] }; } function getPolyfillScripts(context, props) { // polyfills.js has to be rendered as nomodule without async // It also has to be the first script to load const { assetPrefix, buildManifest, assetQueryString, disableOptimizedLoading, crossOrigin } = context; return buildManifest.polyfillFiles.filter((polyfill)=>polyfill.endsWith(".js") && !polyfill.endsWith(".module.js")).map((polyfill)=>/*#__PURE__*/ React.createElement("script", { key: polyfill, defer: !disableOptimizedLoading, nonce: props.nonce, crossOrigin: props.crossOrigin || crossOrigin, noModule: true, src: `${assetPrefix}/_next/${polyfill}${assetQueryString}` })); } function hasComponentProps(child) { return !!child && !!child.props; } function AmpStyles({ styles }) { if (!styles) return null; // try to parse styles from fragment for backwards compat const curStyles = Array.isArray(styles) ? styles : []; if (// @ts-ignore Property 'props' does not exist on type ReactElement styles.props && // @ts-ignore Property 'props' does not exist on type ReactElement Array.isArray(styles.props.children)) { const hasStyles = (el)=>{ var _el_props_dangerouslySetInnerHTML, _el_props; return el == null ? void 0 : (_el_props = el.props) == null ? void 0 : (_el_props_dangerouslySetInnerHTML = _el_props.dangerouslySetInnerHTML) == null ? void 0 : _el_props_dangerouslySetInnerHTML.__html; }; // @ts-ignore Property 'props' does not exist on type ReactElement styles.props.children.forEach((child)=>{ if (Array.isArray(child)) { child.forEach((el)=>hasStyles(el) && curStyles.push(el)); } else if (hasStyles(child)) { curStyles.push(child); } }); } /* Add custom styles before AMP styles to prevent accidental overrides */ return /*#__PURE__*/ React.createElement("style", { "amp-custom": "", dangerouslySetInnerHTML: { __html: curStyles.map((style)=>style.props.dangerouslySetInnerHTML.__html).join("").replace(/\/\*# sourceMappingURL=.*\*\//g, "").replace(/\/\*@ sourceURL=.*?\*\//g, "") } }); } function getDynamicChunks(context, props, files) { const { dynamicImports, assetPrefix, isDevelopment, assetQueryString, disableOptimizedLoading, crossOrigin } = context; return dynamicImports.map((file)=>{ if (!file.endsWith(".js") || files.allFiles.includes(file)) return null; return /*#__PURE__*/ React.createElement("script", { async: !isDevelopment && disableOptimizedLoading, defer: !disableOptimizedLoading, key: file, src: `${assetPrefix}/_next/${encodeURI(file)}${assetQueryString}`, nonce: props.nonce, crossOrigin: props.crossOrigin || crossOrigin }); }); } function getScripts(context, props, files) { var _buildManifest_lowPriorityFiles; const { assetPrefix, buildManifest, isDevelopment, assetQueryString, disableOptimizedLoading, crossOrigin } = context; const normalScripts = files.allFiles.filter((file)=>file.endsWith(".js")); const lowPriorityScripts = (_buildManifest_lowPriorityFiles = buildManifest.lowPriorityFiles) == null ? void 0 : _buildManifest_lowPriorityFiles.filter((file)=>file.endsWith(".js")); return [ ...normalScripts, ...lowPriorityScripts ].map((file)=>{ return /*#__PURE__*/ React.createElement("script", { key: file, src: `${assetPrefix}/_next/${encodeURI(file)}${assetQueryString}`, nonce: props.nonce, async: !isDevelopment && disableOptimizedLoading, defer: !disableOptimizedLoading, crossOrigin: props.crossOrigin || crossOrigin }); }); } function getPreNextWorkerScripts(context, props) { const { assetPrefix, scriptLoader, crossOrigin, nextScriptWorkers } = context; // disable `nextScriptWorkers` in edge runtime if (!nextScriptWorkers || process.env.NEXT_RUNTIME === "edge") return null; try { let { partytownSnippet } = __non_webpack_require__("@builder.io/partytown/integration"); const children = Array.isArray(props.children) ? props.children : [ props.children ]; // Check to see if the user has defined their own Partytown configuration const userDefinedConfig = children.find((child)=>{ var _child_props_dangerouslySetInnerHTML, _child_props; return hasComponentProps(child) && (child == null ? void 0 : (_child_props = child.props) == null ? void 0 : (_child_props_dangerouslySetInnerHTML = _child_props.dangerouslySetInnerHTML) == null ? void 0 : _child_props_dangerouslySetInnerHTML.__html.length) && "data-partytown-config" in child.props; }); return /*#__PURE__*/ React.createElement(React.Fragment, null, !userDefinedConfig && /*#__PURE__*/ React.createElement("script", { "data-partytown-config": "", dangerouslySetInnerHTML: { __html: ` partytown = { lib: "${assetPrefix}/_next/static/~partytown/" }; ` } }), /*#__PURE__*/ React.createElement("script", { "data-partytown": "", dangerouslySetInnerHTML: { __html: partytownSnippet() } }), (scriptLoader.worker || []).map((file, index)=>{ const { strategy, src, children: scriptChildren, dangerouslySetInnerHTML, ...scriptProps } = file; let srcProps = {}; if (src) { // Use external src if provided srcProps.src = src; } else if (dangerouslySetInnerHTML && dangerouslySetInnerHTML.__html) { // Embed inline script if provided with dangerouslySetInnerHTML srcProps.dangerouslySetInnerHTML = { __html: dangerouslySetInnerHTML.__html }; } else if (scriptChildren) { // Embed inline script if provided with children srcProps.dangerouslySetInnerHTML = { __html: typeof scriptChildren === "string" ? scriptChildren : Array.isArray(scriptChildren) ? scriptChildren.join("") : "" }; } else { throw new Error("Invalid usage of next/script. Did you forget to include a src attribute or an inline script? https://nextjs.org/docs/messages/invalid-script"); } return /*#__PURE__*/ React.createElement("script", { ...srcProps, ...scriptProps, type: "text/partytown", key: src || index, nonce: props.nonce, "data-nscript": "worker", crossOrigin: props.crossOrigin || crossOrigin }); })); } catch (err) { if (isError(err) && err.code !== "MODULE_NOT_FOUND") { console.warn(`Warning: ${err.message}`); } return null; } } function getPreNextScripts(context, props) { const { scriptLoader, disableOptimizedLoading, crossOrigin } = context; const webWorkerScripts = getPreNextWorkerScripts(context, props); const beforeInteractiveScripts = (scriptLoader.beforeInteractive || []).filter((script)=>script.src).map((file, index)=>{ const { strategy, ...scriptProps } = file; return /*#__PURE__*/ React.createElement("script", { ...scriptProps, key: scriptProps.src || index, defer: scriptProps.defer ?? !disableOptimizedLoading, nonce: props.nonce, "data-nscript": "beforeInteractive", crossOrigin: props.crossOrigin || crossOrigin }); }); return /*#__PURE__*/ React.createElement(React.Fragment, null, webWorkerScripts, beforeInteractiveScripts); } function getHeadHTMLProps(props) { const { crossOrigin, nonce, ...restProps } = props; // This assignment is necessary for additional type checking to avoid unsupported attributes in
const headProps = restProps; return headProps; } function getAmpPath(ampPath, asPath) { return ampPath || `${asPath}${asPath.includes("?") ? "&" : "?"}amp=1`; } function getNextFontLinkTags(nextFontManifest, dangerousAsPath, assetPrefix = "") { if (!nextFontManifest) { return { preconnect: null, preload: null }; } const appFontsEntry = nextFontManifest.pages["/_app"]; const pageFontsEntry = nextFontManifest.pages[dangerousAsPath]; const preloadedFontFiles = [ ...appFontsEntry ?? [], ...pageFontsEntry ?? [] ]; // If no font files should preload but there's an entry for the path, add a preconnect tag. const preconnectToSelf = !!(preloadedFontFiles.length === 0 && (appFontsEntry || pageFontsEntry)); return { preconnect: preconnectToSelf ? /*#__PURE__*/ React.createElement("link", { "data-next-font": nextFontManifest.pagesUsingSizeAdjust ? "size-adjust" : "", rel: "preconnect", href: "/", crossOrigin: "anonymous" }) : null, preload: preloadedFontFiles ? preloadedFontFiles.map((fontFile)=>{ const ext = /\.(woff|woff2|eot|ttf|otf)$/.exec(fontFile)[1]; return /*#__PURE__*/ React.createElement("link", { key: fontFile, rel: "preload", href: `${assetPrefix}/_next/${encodeURI(fontFile)}`, as: "font", type: `font/${ext}`, crossOrigin: "anonymous", "data-next-font": fontFile.includes("-s") ? "size-adjust" : "" }); }) : null }; } // Use `React.Component` to avoid errors from the RSC checks because // it can't be imported directly in Server Components: // // import { Component } from 'react' // // More info: https://github.com/vercel/next.js/pull/40686 export class Head extends React.Component { static #_ = this.contextType = HtmlContext; getCssLinks(files) { const { assetPrefix, assetQueryString, dynamicImports, crossOrigin, optimizeCss, optimizeFonts } = this.context; const cssFiles = files.allFiles.filter((f)=>f.endsWith(".css")); const sharedFiles = new Set(files.sharedFiles); // Unmanaged files are CSS files that will be handled directly by the // webpack runtime (`mini-css-extract-plugin`). let unmangedFiles = new Set([]); let dynamicCssFiles = Array.from(new Set(dynamicImports.filter((file)=>file.endsWith(".css")))); if (dynamicCssFiles.length) { const existing = new Set(cssFiles); dynamicCssFiles = dynamicCssFiles.filter((f)=>!(existing.has(f) || sharedFiles.has(f))); unmangedFiles = new Set(dynamicCssFiles); cssFiles.push(...dynamicCssFiles); } let cssLinkElements = []; cssFiles.forEach((file)=>{ const isSharedFile = sharedFiles.has(file); if (!optimizeCss) { cssLinkElements.push(/*#__PURE__*/ React.createElement("link", { key: `${file}-preload`, nonce: this.props.nonce, rel: "preload", href: `${assetPrefix}/_next/${encodeURI(file)}${assetQueryString}`, as: "style", crossOrigin: this.props.crossOrigin || crossOrigin })); } const isUnmanagedFile = unmangedFiles.has(file); cssLinkElements.push(/*#__PURE__*/ React.createElement("link", { key: file, nonce: this.props.nonce, rel: "stylesheet", href: `${assetPrefix}/_next/${encodeURI(file)}${assetQueryString}`, crossOrigin: this.props.crossOrigin || crossOrigin, "data-n-g": isUnmanagedFile ? undefined : isSharedFile ? "" : undefined, "data-n-p": isUnmanagedFile ? undefined : isSharedFile ? undefined : "" })); }); if (process.env.NODE_ENV !== "development" && optimizeFonts) { cssLinkElements = this.makeStylesheetInert(cssLinkElements); } return cssLinkElements.length === 0 ? null : cssLinkElements; } getPreloadDynamicChunks() { const { dynamicImports, assetPrefix, assetQueryString, crossOrigin } = this.context; return dynamicImports.map((file)=>{ if (!file.endsWith(".js")) { return null; } return /*#__PURE__*/ React.createElement("link", { rel: "preload", key: file, href: `${assetPrefix}/_next/${encodeURI(file)}${assetQueryString}`, as: "script", nonce: this.props.nonce, crossOrigin: this.props.crossOrigin || crossOrigin }); })// Filter out nulled scripts .filter(Boolean); } getPreloadMainLinks(files) { const { assetPrefix, assetQueryString, scriptLoader, crossOrigin } = this.context; const preloadFiles = files.allFiles.filter((file)=>{ return file.endsWith(".js"); }); return [ ...(scriptLoader.beforeInteractive || []).map((file)=>/*#__PURE__*/ React.createElement("link", { key: file.src, nonce: this.props.nonce, rel: "preload", href: file.src, as: "script", crossOrigin: this.props.crossOrigin || crossOrigin })), ...preloadFiles.map((file)=>/*#__PURE__*/ React.createElement("link", { key: file, nonce: this.props.nonce, rel: "preload", href: `${assetPrefix}/_next/${encodeURI(file)}${assetQueryString}`, as: "script", crossOrigin: this.props.crossOrigin || crossOrigin })) ]; } getBeforeInteractiveInlineScripts() { const { scriptLoader } = this.context; const { nonce, crossOrigin } = this.props; return (scriptLoader.beforeInteractive || []).filter((script)=>!script.src && (script.dangerouslySetInnerHTML || script.children)).map((file, index)=>{ const { strategy, children, dangerouslySetInnerHTML, src, ...scriptProps } = file; let html = ""; if (dangerouslySetInnerHTML && dangerouslySetInnerHTML.__html) { html = dangerouslySetInnerHTML.__html; } else if (children) { html = typeof children === "string" ? children : Array.isArray(children) ? children.join("") : ""; } return /*#__PURE__*/ React.createElement("script", { ...scriptProps, dangerouslySetInnerHTML: { __html: html }, key: scriptProps.id || index, nonce: nonce, "data-nscript": "beforeInteractive", crossOrigin: crossOrigin || process.env.__NEXT_CROSS_ORIGIN }); }); } getDynamicChunks(files) { return getDynamicChunks(this.context, this.props, files); } getPreNextScripts() { return getPreNextScripts(this.context, this.props); } getScripts(files) { return getScripts(this.context, this.props, files); } getPolyfillScripts() { return getPolyfillScripts(this.context, this.props); } makeStylesheetInert(node) { return React.Children.map(node, (c)=>{ var _c_props, _c_props1; if ((c == null ? void 0 : c.type) === "link" && (c == null ? void 0 : (_c_props = c.props) == null ? void 0 : _c_props.href) && OPTIMIZED_FONT_PROVIDERS.some(({ url })=>{ var _c_props_href, _c_props; return c == null ? void 0 : (_c_props = c.props) == null ? void 0 : (_c_props_href = _c_props.href) == null ? void 0 : _c_props_href.startsWith(url); })) { const newProps = { ...c.props || {}, "data-href": c.props.href, href: undefined }; return /*#__PURE__*/ React.cloneElement(c, newProps); } else if (c == null ? void 0 : (_c_props1 = c.props) == null ? void 0 : _c_props1.children) { const newProps = { ...c.props || {}, children: this.makeStylesheetInert(c.props.children) }; return /*#__PURE__*/ React.cloneElement(c, newProps); } return c; // @types/react bug. Returned value from .map will not be `null` if you pass in `[null]` }).filter(Boolean); } render() { const { styles, ampPath, inAmpMode, hybridAmp, canonicalBase, __NEXT_DATA__, dangerousAsPath, headTags, unstable_runtimeJS, unstable_JsPreload, disableOptimizedLoading, optimizeCss, optimizeFonts, assetPrefix, nextFontManifest } = this.context; const disableRuntimeJS = unstable_runtimeJS === false; const disableJsPreload = unstable_JsPreload === false || !disableOptimizedLoading; this.context.docComponentsRendered.Head = true; let { head } = this.context; let cssPreloads = []; let otherHeadElements = []; if (head) { head.forEach((c)=>{ let metaTag; if (this.context.strictNextHead) { metaTag = /*#__PURE__*/ React.createElement("meta", { name: "next-head", content: "1" }); } if (c && c.type === "link" && c.props["rel"] === "preload" && c.props["as"] === "style") { metaTag && cssPreloads.push(metaTag); cssPreloads.push(c); } else { if (c) { if (metaTag && (c.type !== "meta" || !c.props["charSet"])) { otherHeadElements.push(metaTag); } otherHeadElements.push(c); } } }); head = cssPreloads.concat(otherHeadElements); } let children = React.Children.toArray(this.props.children).filter(Boolean); // show a warning if Head contains