@thomas.f/prnext 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +54 -0
  2. package/build/action-exports.mjs +107 -0
  3. package/build/actions.mjs +214 -0
  4. package/build/app-config.mjs +138 -0
  5. package/build/app-routing.mjs +119 -0
  6. package/build/app-static.mjs +158 -0
  7. package/build/app.mjs +536 -0
  8. package/build/cache-components.mjs +91 -0
  9. package/build/cache-handlers.mjs +54 -0
  10. package/build/check.mjs +40 -0
  11. package/build/compiler.mjs +222 -0
  12. package/build/config.mjs +193 -0
  13. package/build/css-modules.mjs +114 -0
  14. package/build/custom-routes.mjs +363 -0
  15. package/build/dev-worker.mjs +18 -0
  16. package/build/dev.mjs +76 -0
  17. package/build/directory-cache.mjs +29 -0
  18. package/build/dynamic.mjs +125 -0
  19. package/build/edge.mjs +141 -0
  20. package/build/font-data.LICENSE.txt +25 -0
  21. package/build/font-data.json +1 -0
  22. package/build/font-files.mjs +221 -0
  23. package/build/fonts.mjs +131 -0
  24. package/build/framework-imports.mjs +17 -0
  25. package/build/i18n.mjs +39 -0
  26. package/build/images-config.mjs +62 -0
  27. package/build/images.mjs +86 -0
  28. package/build/incremental.mjs +76 -0
  29. package/build/index.mjs +356 -0
  30. package/build/loader-cache.mjs +69 -0
  31. package/build/metadata-images.mjs +72 -0
  32. package/build/metadata-routes.mjs +77 -0
  33. package/build/middleware.mjs +231 -0
  34. package/build/migrate.mjs +289 -0
  35. package/build/module-resolution.mjs +78 -0
  36. package/build/native-discovery.mjs +134 -0
  37. package/build/native-packages.mjs +105 -0
  38. package/build/npm-packages.mjs +110 -0
  39. package/build/og.mjs +14 -0
  40. package/build/page-extensions.mjs +12 -0
  41. package/build/passthrough-loader.cjs +4 -0
  42. package/build/precompress.mjs +122 -0
  43. package/build/scan.mjs +178 -0
  44. package/build/script-workers.mjs +25 -0
  45. package/build/server-actions-config.mjs +27 -0
  46. package/build/source-maps.mjs +34 -0
  47. package/build/standalone-config.mjs +19 -0
  48. package/build/standalone-runner.mjs +21 -0
  49. package/build/standalone-worker.mjs +5 -0
  50. package/build/standalone.mjs +240 -0
  51. package/build/static-export.mjs +93 -0
  52. package/build/styles.mjs +174 -0
  53. package/build/transform-cache.mjs +50 -0
  54. package/build/transform.mjs +155 -0
  55. package/build/turbopack-conditions.mjs +59 -0
  56. package/build/webpack-bridge.cjs +3 -0
  57. package/build/webpack-graph.mjs +256 -0
  58. package/build/webpack-loader.cjs +9 -0
  59. package/cli.mjs +210 -0
  60. package/compat/app-client-page.cjs +32 -0
  61. package/compat/app-context.cjs +40 -0
  62. package/compat/app-context.d.cts +20 -0
  63. package/compat/app-dynamic.cjs +34 -0
  64. package/compat/app-error-boundary.cjs +53 -0
  65. package/compat/app-global-error-boundary.cjs +34 -0
  66. package/compat/app-layout-context.cjs +27 -0
  67. package/compat/app-navigation-boundary.cjs +47 -0
  68. package/compat/app.cjs +33 -0
  69. package/compat/app.d.cts +9 -0
  70. package/compat/cache-handlers.cjs +223 -0
  71. package/compat/cache-life.cjs +34 -0
  72. package/compat/cache.cjs +99 -0
  73. package/compat/cache.d.cts +36 -0
  74. package/compat/compat/router.d.cts +2 -0
  75. package/compat/compat-router.cjs +7 -0
  76. package/compat/constants.cjs +8 -0
  77. package/compat/constants.d.cts +7 -0
  78. package/compat/cookies.cjs +129 -0
  79. package/compat/data-cache.cjs +389 -0
  80. package/compat/dist/shared/lib/app-router-context.shared-runtime.d.cts +3 -0
  81. package/compat/dist/shared/lib/router-context.d.cts +1 -0
  82. package/compat/dist/shared/lib/router-context.shared-runtime.d.cts +3 -0
  83. package/compat/document.cjs +73 -0
  84. package/compat/document.d.cts +41 -0
  85. package/compat/draft.cjs +28 -0
  86. package/compat/dynamic-bailout.cjs +13 -0
  87. package/compat/dynamic.cjs +119 -0
  88. package/compat/dynamic.d.cts +32 -0
  89. package/compat/error.cjs +36 -0
  90. package/compat/error.d.cts +15 -0
  91. package/compat/fetch.d.cts +10 -0
  92. package/compat/font/google.d.cts +1 -0
  93. package/compat/font/local.d.cts +2 -0
  94. package/compat/font-google.cjs +2 -0
  95. package/compat/font-google.d.cts +1944 -0
  96. package/compat/font-local.cjs +5 -0
  97. package/compat/font-local.d.cts +3 -0
  98. package/compat/font-types.d.cts +25 -0
  99. package/compat/head.cjs +180 -0
  100. package/compat/head.d.cts +3 -0
  101. package/compat/headers.cjs +89 -0
  102. package/compat/headers.d.cts +26 -0
  103. package/compat/image-config.cjs +3 -0
  104. package/compat/image-imports.d.ts +12 -0
  105. package/compat/image-shared.cjs +62 -0
  106. package/compat/image.cjs +64 -0
  107. package/compat/image.d.cts +35 -0
  108. package/compat/incremental-cache.cjs +186 -0
  109. package/compat/index.d.ts +159 -0
  110. package/compat/instant-samples.cjs +39 -0
  111. package/compat/instant.cjs +13 -0
  112. package/compat/link.cjs +68 -0
  113. package/compat/link.d.cts +17 -0
  114. package/compat/locale.cjs +30 -0
  115. package/compat/metadata.d.cts +77 -0
  116. package/compat/navigation-controls.cjs +27 -0
  117. package/compat/navigation-server.cjs +25 -0
  118. package/compat/navigation.cjs +52 -0
  119. package/compat/navigation.d.cts +28 -0
  120. package/compat/next-app-router-context.cjs +6 -0
  121. package/compat/next-router-context.cjs +3 -0
  122. package/compat/og.cjs +32 -0
  123. package/compat/og.d.cts +1 -0
  124. package/compat/paths.cjs +33 -0
  125. package/compat/preview.cjs +41 -0
  126. package/compat/rewrite.cjs +41 -0
  127. package/compat/route-request.cjs +64 -0
  128. package/compat/router.cjs +137 -0
  129. package/compat/router.d.cts +58 -0
  130. package/compat/script-context.cjs +5 -0
  131. package/compat/script-loader.cjs +135 -0
  132. package/compat/script.cjs +69 -0
  133. package/compat/script.d.cts +17 -0
  134. package/compat/server-primitives.cjs +109 -0
  135. package/compat/server.cjs +13 -0
  136. package/compat/server.d.cts +37 -0
  137. package/compat/static-generation.cjs +108 -0
  138. package/compat/use-cache.cjs +129 -0
  139. package/index.mjs +1 -0
  140. package/native/platforms.json +6 -0
  141. package/native/resolve.mjs +81 -0
  142. package/package.json +127 -0
  143. package/release/verify.mjs +59 -0
  144. package/runtime/action-client.mjs +19 -0
  145. package/runtime/action-crypto.mjs +138 -0
  146. package/runtime/action-reference.mjs +2 -0
  147. package/runtime/action-server.mjs +161 -0
  148. package/runtime/action-ssr.mjs +5 -0
  149. package/runtime/api.mjs +326 -0
  150. package/runtime/app-client.mjs +539 -0
  151. package/runtime/app-content.mjs +8 -0
  152. package/runtime/app-errors.mjs +12 -0
  153. package/runtime/app-instant.mjs +30 -0
  154. package/runtime/app-metadata.mjs +410 -0
  155. package/runtime/app-partial-model.mjs +228 -0
  156. package/runtime/app-partial.mjs +130 -0
  157. package/runtime/app-prefetch.mjs +34 -0
  158. package/runtime/app-recovery.mjs +87 -0
  159. package/runtime/app-render.mjs +544 -0
  160. package/runtime/app-routing-access.mjs +143 -0
  161. package/runtime/app-routing-context.mjs +35 -0
  162. package/runtime/app-routing-state.mjs +61 -0
  163. package/runtime/app-routing.mjs +323 -0
  164. package/runtime/app-segments.mjs +22 -0
  165. package/runtime/app-static-params.mjs +120 -0
  166. package/runtime/app-static.mjs +86 -0
  167. package/runtime/app-stream-channel.mjs +92 -0
  168. package/runtime/app-stream-html.mjs +279 -0
  169. package/runtime/build-directory.mjs +48 -0
  170. package/runtime/cache-arguments.mjs +33 -0
  171. package/runtime/cache-components-rsc.mjs +64 -0
  172. package/runtime/cache-request.mjs +23 -0
  173. package/runtime/client-navigation.mjs +40 -0
  174. package/runtime/dev-client.mjs +129 -0
  175. package/runtime/dev-file-changes.mjs +110 -0
  176. package/runtime/document.mjs +96 -0
  177. package/runtime/edge.mjs +105 -0
  178. package/runtime/env.mjs +68 -0
  179. package/runtime/fetch-cache.mjs +379 -0
  180. package/runtime/font-preload.mjs +4 -0
  181. package/runtime/http.mjs +190 -0
  182. package/runtime/incremental-cache.mjs +83 -0
  183. package/runtime/metadata-route.mjs +83 -0
  184. package/runtime/middleware.mjs +186 -0
  185. package/runtime/module-loader.mjs +21 -0
  186. package/runtime/navigation.mjs +16 -0
  187. package/runtime/og-loader.mjs +17 -0
  188. package/runtime/pages-client.mjs +197 -0
  189. package/runtime/pages-error-props.mjs +6 -0
  190. package/runtime/pages-errors.mjs +85 -0
  191. package/runtime/pages-initial-props.mjs +43 -0
  192. package/runtime/pages-navigation.mjs +565 -0
  193. package/runtime/pages-paths.mjs +80 -0
  194. package/runtime/pages-revalidate.mjs +33 -0
  195. package/runtime/partial-artifact-cache.mjs +37 -0
  196. package/runtime/partial-template.mjs +174 -0
  197. package/runtime/profile.mjs +9 -0
  198. package/runtime/profiles.json +47 -0
  199. package/runtime/render.mjs +304 -0
  200. package/runtime/request-transport.mjs +41 -0
  201. package/runtime/request-work.mjs +7 -0
  202. package/runtime/route-static.mjs +117 -0
  203. package/runtime/rsc-worker.mjs +426 -0
  204. package/runtime/script-html.mjs +61 -0
  205. package/runtime/stream-select.mjs +25 -0
  206. package/runtime/stream-utils.mjs +127 -0
  207. package/runtime/transport.mjs +108 -0
  208. package/runtime/watch-project.mjs +130 -0
  209. package/runtime/worker-artifacts.mjs +22 -0
  210. package/runtime/worker-metadata.mjs +31 -0
  211. package/runtime/worker.mjs +197 -0
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+ const { parseCookieHeader } = require('./cookies.cjs');
3
+ const COOKIE_NAME = '__prerender_bypass';
4
+
5
+ function previewId(input) { return input.previewModeId || input.manifest?.previewModeId; }
6
+ // Native/Pages requests carry plain header records. Do not initialize Node's
7
+ // entire Web Request implementation just to check an absent preview cookie.
8
+ function cookieHeader(headers) {
9
+ return typeof headers?.get === 'function' ? headers.get('cookie')
10
+ : Object.entries(headers || {}).find(([key]) => key.toLowerCase() === 'cookie')?.[1];
11
+ }
12
+ function isDraftRequest(input) {
13
+ if (input.staticGeneration || input.staticState || input.renderMode === 'isr' || input.isFallback) return false;
14
+ const id = previewId(input);
15
+ if (!id) return false;
16
+ const header = cookieHeader(input.headers);
17
+ if (!header || !String(header).includes(COOKIE_NAME)) return false;
18
+ return parseCookieHeader(header).get(COOKIE_NAME)?.value === id;
19
+ }
20
+ function draftCookie(input, enabled, { path = '/', keepValue = false } = {}) {
21
+ const id = previewId(input);
22
+ if (!id) throw new Error('Draft Mode requires a build with a previewModeId');
23
+ return { name: COOKIE_NAME, value: enabled || keepValue ? id : '', path, httpOnly: true,
24
+ sameSite: input.production === false || input.manifest?.dev ? 'lax' : 'none',
25
+ secure: !(input.production === false || input.manifest?.dev),
26
+ ...(!enabled ? { expires: new Date(0) } : {}) };
27
+ }
28
+ module.exports = { COOKIE_NAME, previewId, isDraftRequest, draftCookie, cookieHeader };
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+ const DYNAMIC_BAILOUT = 'BAILOUT_TO_CLIENT_SIDE_RENDERING';
3
+
4
+ class DynamicBailout extends Error {
5
+ constructor() {
6
+ super('Bail out to client-side rendering: next/dynamic');
7
+ this.digest = DYNAMIC_BAILOUT;
8
+ }
9
+ }
10
+
11
+ function isDynamicBailout(error) { return error?.digest === DYNAMIC_BAILOUT; }
12
+
13
+ module.exports = { DynamicBailout, isDynamicBailout };
@@ -0,0 +1,119 @@
1
+ 'use strict';
2
+ const React = require('react');
3
+
4
+ const DynamicContext = React.createContext(null);
5
+ const serverInitializers = new Set();
6
+ const readyInitializers = new Map();
7
+ const server = typeof window === 'undefined';
8
+ let preloading;
9
+
10
+ function componentOf(module) { return module && module.default ? module.default : module; }
11
+ function DefaultLoading({ error, pastDelay }) {
12
+ if (process.env.NODE_ENV !== 'production' && pastDelay && error) {
13
+ return React.createElement('p', null, error.message, React.createElement('br'), error.stack);
14
+ }
15
+ return null;
16
+ }
17
+
18
+ function resource(loader, options) {
19
+ const listeners = new Set();
20
+ let state, promise, delay, timeout, attempt = 0;
21
+ const clear = () => { clearTimeout(delay); clearTimeout(timeout); };
22
+ const update = patch => {
23
+ state = { ...state, ...patch };
24
+ for (const listener of listeners) listener();
25
+ };
26
+ const retry = () => {
27
+ clear();
28
+ const version = ++attempt;
29
+ state = { loading: true, loaded: null, error: null, pastDelay: options.delay === 0, timedOut: false };
30
+ promise = Promise.resolve().then(loader);
31
+ if (typeof options.delay === 'number' && options.delay > 0) delay = setTimeout(() => update({ pastDelay: true }), options.delay);
32
+ if (typeof options.timeout === 'number') timeout = setTimeout(() => update({ timedOut: true }), options.timeout);
33
+ void promise.then(loaded => {
34
+ if (version !== attempt) return;
35
+ clear(); update({ loading: false, loaded });
36
+ }, error => {
37
+ if (version !== attempt) return;
38
+ clear(); update({ loading: false, error });
39
+ });
40
+ for (const listener of listeners) listener();
41
+ return promise;
42
+ };
43
+ retry();
44
+ return { retry, promise: () => promise, snapshot: () => state,
45
+ subscribe(callback) { listeners.add(callback); return () => listeners.delete(callback); } };
46
+ }
47
+
48
+ function dynamic(input, options) {
49
+ const normalized = input instanceof Promise ? { loader: () => input }
50
+ : typeof input === 'function' ? { loader: input } : input || {};
51
+ const opts = { loading: DefaultLoading, delay: 200, timeout: null, ...normalized, ...options };
52
+ Object.assign(opts, opts.loadableGenerated);
53
+ const Loading = opts.loading || DefaultLoading;
54
+ if (opts.ssr === false && server) {
55
+ return function NoSSR() {
56
+ return React.createElement(Loading, { error: null, isLoading: true, pastDelay: false, timedOut: false });
57
+ };
58
+ }
59
+ const loader = opts.loader || (() => Promise.resolve(() => null));
60
+ if (typeof loader !== 'function') throw new TypeError('dynamic loader must be a function returning a Promise');
61
+ let loaded;
62
+ const init = () => { loaded ||= resource(loader, opts); return loaded.promise(); };
63
+ const ids = opts.ssr === false ? [] : Array.isArray(opts.modules) ? opts.modules : [];
64
+ if (server) serverInitializers.add(init);
65
+ else if (ids.length) readyInitializers.set(init, ids);
66
+ const Component = React.forwardRef(function DynamicComponent(props, ref) {
67
+ init();
68
+ const modules = React.useContext(DynamicContext);
69
+ if (modules) for (const id of ids) modules.add(id);
70
+ const state = React.useSyncExternalStore(loaded.subscribe, loaded.snapshot, loaded.snapshot);
71
+ React.useImperativeHandle(ref, () => ({ retry: loaded.retry }), []);
72
+ if (state.loading || state.error) return React.createElement(Loading, {
73
+ isLoading: state.loading, pastDelay: state.pastDelay, timedOut: state.timedOut,
74
+ error: state.error, retry: loaded.retry,
75
+ });
76
+ return state.loaded ? React.createElement(componentOf(state.loaded), props) : null;
77
+ });
78
+ Component.displayName = 'LoadableComponent';
79
+ return Component;
80
+ }
81
+
82
+ async function preloadAll() {
83
+ if (preloading) return preloading;
84
+ preloading = (async () => {
85
+ while (serverInitializers.size) {
86
+ const pending = [...serverInitializers];
87
+ serverInitializers.clear();
88
+ await Promise.all(pending.map(init => init()));
89
+ }
90
+ })();
91
+ try { await preloading; }
92
+ finally { preloading = undefined; }
93
+ }
94
+
95
+ async function preloadReady(ids = []) {
96
+ const rendered = new Set(ids);
97
+ while (true) {
98
+ const pending = [];
99
+ for (const [init, modules] of readyInitializers) {
100
+ if (!modules.some(id => rendered.has(id))) continue;
101
+ readyInitializers.delete(init);
102
+ pending.push(init());
103
+ }
104
+ if (!pending.length) return;
105
+ // Loading components display failures. Nested imports may register more
106
+ // components whose IDs were also present in the server-rendered document.
107
+ await Promise.allSettled(pending);
108
+ }
109
+ }
110
+
111
+ function DynamicProvider({ modules, children }) {
112
+ return React.createElement(DynamicContext.Provider, { value: modules }, children);
113
+ }
114
+
115
+ module.exports = dynamic;
116
+ module.exports.default = dynamic;
117
+ module.exports.preloadAll = preloadAll;
118
+ module.exports.preloadReady = preloadReady;
119
+ module.exports.DynamicProvider = DynamicProvider;
@@ -0,0 +1,32 @@
1
+ import type { ComponentType, ReactNode } from 'react';
2
+
3
+ export type LoaderComponent<P = {}> = Promise<ComponentType<P> | { default: ComponentType<P> }>;
4
+ export type Loader<P = {}> = (() => LoaderComponent<P>) | LoaderComponent<P>;
5
+
6
+ export interface DynamicOptionsLoadingProps {
7
+ error?: Error | null;
8
+ isLoading?: boolean;
9
+ pastDelay?: boolean;
10
+ retry?: () => void;
11
+ timedOut?: boolean;
12
+ }
13
+
14
+ export interface DynamicOptions<P = {}> {
15
+ loading?: (props: DynamicOptionsLoadingProps) => ReactNode;
16
+ loader?: Loader<P>;
17
+ ssr?: boolean;
18
+ /** Pages loading-state delay in milliseconds; ignored by the App Router. */
19
+ delay?: number;
20
+ /** Pages timedOut indicator in milliseconds; does not cancel the loader. Ignored by App. */
21
+ timeout?: number;
22
+ }
23
+
24
+ export type LoadableOptions<P = {}> = DynamicOptions<P>;
25
+ export type LoadableFn<P = {}> = (options: LoadableOptions<P>) => ComponentType<P>;
26
+ export type LoadableComponent<P = {}> = ComponentType<P>;
27
+
28
+ /** App Router usage requires a loader function; ssr:false belongs in a Client Component. */
29
+ export default function dynamic<P = {}>(
30
+ loader: Loader<P> | DynamicOptions<P>,
31
+ options?: DynamicOptions<P>,
32
+ ): ComponentType<P>;
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+ const React = require('react');
3
+ const Head = require('./head.cjs');
4
+
5
+ const titles = { 400: 'Bad Request', 404: 'This page could not be found', 405: 'Method Not Allowed', 500: 'Internal Server Error' };
6
+
7
+ function getInitialProps({ req, res, err }) {
8
+ const statusCode = res?.statusCode || (err ? err.statusCode : 404);
9
+ let hostname;
10
+ if (typeof window !== 'undefined') hostname = window.location.hostname;
11
+ else if (req?.headers?.host) {
12
+ try { hostname = new URL(`http://${req.headers.host}`).hostname; } catch { /* An invalid Host is not page content. */ }
13
+ }
14
+ return { statusCode, hostname };
15
+ }
16
+
17
+ class ErrorPage extends React.Component {
18
+ static displayName = 'ErrorPage';
19
+ static getInitialProps = getInitialProps;
20
+ static origGetInitialProps = getInitialProps;
21
+ render() {
22
+ const { statusCode, hostname, withDarkMode = true } = this.props;
23
+ const title = this.props.title || titles[statusCode] || 'An unexpected error has occurred';
24
+ const clientTitle = 'Application error: a client-side exception has occurred';
25
+ const description = this.props.title || statusCode ? title
26
+ : `${clientTitle}${hostname ? ` while loading ${hostname}` : ''} (see the browser console for more information)`;
27
+ return React.createElement('div', { style: { fontFamily: 'system-ui, sans-serif', height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center' } },
28
+ React.createElement(Head, null, React.createElement('title', null, statusCode ? `${statusCode}: ${title}` : clientTitle)),
29
+ React.createElement('style', null, `body{margin:0;color:#000;background:#fff}.prnext-error-code{border-right:1px solid rgba(0,0,0,.3)}${withDarkMode ? '@media(prefers-color-scheme:dark){body{color:#fff;background:#000}.prnext-error-code{border-color:rgba(255,255,255,.3)}}' : ''}`),
30
+ React.createElement('div', null,
31
+ statusCode ? React.createElement('h1', { className: 'prnext-error-code', style: { display: 'inline-block', margin: '0 20px 0 0', paddingRight: 23, fontSize: 24, fontWeight: 500, lineHeight: '48px', verticalAlign: 'top' } }, statusCode) : null,
32
+ React.createElement('div', { style: { display: 'inline-block' } }, React.createElement('h2', { style: { fontSize: 14, fontWeight: 400, lineHeight: '28px' } }, `${description}.`))));
33
+ }
34
+ }
35
+ module.exports = ErrorPage;
36
+ module.exports.default = ErrorPage;
@@ -0,0 +1,15 @@
1
+ import { Component, type ReactElement } from 'react';
2
+ import type { NextPageContext } from './index.d.ts';
3
+
4
+ export interface ErrorProps {
5
+ statusCode: number;
6
+ hostname?: string;
7
+ title?: string;
8
+ withDarkMode?: boolean;
9
+ }
10
+ export default class ErrorPage<Props = {}> extends Component<Props & ErrorProps> {
11
+ static displayName: string;
12
+ static getInitialProps(context: NextPageContext): ErrorProps | Promise<ErrorProps>;
13
+ static origGetInitialProps: typeof ErrorPage.getInitialProps;
14
+ render(): ReactElement;
15
+ }
@@ -0,0 +1,10 @@
1
+ export {};
2
+
3
+ declare global {
4
+ interface RequestInit {
5
+ next?: {
6
+ revalidate?: number | false;
7
+ tags?: string[];
8
+ };
9
+ }
10
+ }
@@ -0,0 +1 @@
1
+ export * from '../font-google.cjs';
@@ -0,0 +1,2 @@
1
+ import localFont = require('../font-local.cjs');
2
+ export = localFont;
@@ -0,0 +1,2 @@
1
+ 'use strict';
2
+ throw new Error('prnext/font/google must be compiled by PRNext. Import a named Google font and call it in a module-level const with literal options.');