gatsby 4.19.0-next.4 → 4.19.2

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 (74) hide show
  1. package/cache-dir/app.js +26 -71
  2. package/cache-dir/commonjs/app.js +27 -52
  3. package/cache-dir/commonjs/dev-loader.js +3 -5
  4. package/cache-dir/commonjs/fast-refresh-overlay/components/runtime-errors.js +5 -3
  5. package/cache-dir/commonjs/head/components/fire-callback-in-effect.js +19 -0
  6. package/cache-dir/commonjs/head/constants.js +6 -0
  7. package/cache-dir/commonjs/head/head-export-handler-for-browser.js +106 -0
  8. package/cache-dir/commonjs/head/head-export-handler-for-ssr.js +129 -0
  9. package/cache-dir/commonjs/head/utils.js +61 -0
  10. package/cache-dir/commonjs/loader.js +11 -7
  11. package/cache-dir/commonjs/page-renderer.js +31 -27
  12. package/cache-dir/commonjs/production-app.js +8 -19
  13. package/cache-dir/commonjs/react-dom-utils.js +42 -0
  14. package/cache-dir/commonjs/ssr-develop-static-entry.js +19 -15
  15. package/cache-dir/commonjs/static-entry.js +17 -18
  16. package/cache-dir/dev-loader.js +3 -6
  17. package/cache-dir/fast-refresh-overlay/components/runtime-errors.js +5 -2
  18. package/cache-dir/head/components/fire-callback-in-effect.js +12 -0
  19. package/cache-dir/head/constants.js +9 -0
  20. package/cache-dir/head/head-export-handler-for-browser.js +98 -0
  21. package/cache-dir/head/head-export-handler-for-ssr.js +100 -0
  22. package/cache-dir/head/utils.js +54 -0
  23. package/cache-dir/loader.js +29 -25
  24. package/cache-dir/page-renderer.js +37 -25
  25. package/cache-dir/production-app.js +4 -15
  26. package/cache-dir/react-dom-utils.js +33 -0
  27. package/cache-dir/ssr-develop-static-entry.js +26 -23
  28. package/cache-dir/static-entry.js +13 -20
  29. package/dist/bootstrap/requires-writer.js +25 -5
  30. package/dist/bootstrap/requires-writer.js.map +1 -1
  31. package/dist/commands/develop.js +17 -176
  32. package/dist/commands/develop.js.map +1 -1
  33. package/dist/commands/types.js.map +1 -1
  34. package/dist/internal-plugins/internal-data-bridge/gatsby-node.js +1 -1
  35. package/dist/internal-plugins/internal-data-bridge/gatsby-node.js.map +1 -1
  36. package/dist/query/file-parser.js +6 -3
  37. package/dist/query/file-parser.js.map +1 -1
  38. package/dist/schema/graphql-engine/bundle-webpack.js +14 -1
  39. package/dist/schema/graphql-engine/bundle-webpack.js.map +1 -1
  40. package/dist/services/start-webpack-server.js +1 -1
  41. package/dist/services/start-webpack-server.js.map +1 -1
  42. package/dist/utils/babel/babel-plugin-remove-api.js +20 -2
  43. package/dist/utils/babel/babel-plugin-remove-api.js.map +1 -1
  44. package/dist/utils/babel-loader-helpers.js +14 -3
  45. package/dist/utils/babel-loader-helpers.js.map +1 -1
  46. package/dist/utils/babel-loader.js +7 -4
  47. package/dist/utils/babel-loader.js.map +1 -1
  48. package/dist/utils/eslint-rules/limited-exports-page-templates.js +23 -3
  49. package/dist/utils/eslint-rules/limited-exports-page-templates.js.map +1 -1
  50. package/dist/utils/graphql-typegen/file-writes.js +1 -1
  51. package/dist/utils/graphql-typegen/file-writes.js.map +1 -1
  52. package/dist/utils/start-server.js +2 -4
  53. package/dist/utils/start-server.js.map +1 -1
  54. package/dist/{schema/graphql-engine/webpack-remove-apis-loader.d.ts → utils/webpack/loaders/webpack-remove-exports-loader.d.ts} +0 -0
  55. package/dist/utils/webpack/loaders/webpack-remove-exports-loader.js +41 -0
  56. package/dist/utils/webpack/loaders/webpack-remove-exports-loader.js.map +1 -0
  57. package/dist/utils/webpack/plugins/static-query-mapper.js +39 -18
  58. package/dist/utils/webpack/plugins/static-query-mapper.js.map +1 -1
  59. package/dist/utils/webpack-utils.js +3 -1
  60. package/dist/utils/webpack-utils.js.map +1 -1
  61. package/dist/utils/webpack.config.js.map +1 -1
  62. package/index.d.ts +29 -0
  63. package/package.json +22 -23
  64. package/dist/schema/graphql-engine/webpack-remove-apis-loader.js +0 -26
  65. package/dist/schema/graphql-engine/webpack-remove-apis-loader.js.map +0 -1
  66. package/dist/utils/develop-proxy.d.ts +0 -15
  67. package/dist/utils/develop-proxy.js +0 -78
  68. package/dist/utils/develop-proxy.js.map +0 -1
  69. package/dist/utils/restarting-screen.d.ts +0 -2
  70. package/dist/utils/restarting-screen.js +0 -136
  71. package/dist/utils/restarting-screen.js.map +0 -1
  72. package/dist/utils/telemetry-server.d.ts +0 -1
  73. package/dist/utils/telemetry-server.js +0 -70
  74. package/dist/utils/telemetry-server.js.map +0 -1
package/cache-dir/app.js CHANGED
@@ -1,7 +1,6 @@
1
1
  /* global HAS_REACT_18 */
2
2
  import React from "react"
3
3
  import ReactDOM from "react-dom"
4
- import io from "socket.io-client"
5
4
 
6
5
  import socketIo from "./socketIo"
7
6
  import emitter from "./emitter"
@@ -40,23 +39,36 @@ loader.setApiRunner(apiRunner)
40
39
 
41
40
  window.___loader = publicLoader
42
41
 
43
- let reactRender
44
- let reactHydrate
42
+ let reactFirstRenderOrHydrate
45
43
  if (HAS_REACT_18) {
46
44
  const reactDomClient = require(`react-dom/client`)
47
- reactRender = (Component, el) => {
48
- const root = reactDomClient.createRoot(el)
49
- root.render(Component)
50
- return () => root.unmount()
45
+ reactFirstRenderOrHydrate = (Component, el) => {
46
+ // we will use hydrate if mount element has any content inside
47
+ const useHydrate = el && el.children.length
48
+
49
+ if (useHydrate) {
50
+ const root = reactDomClient.hydrateRoot(el, Component)
51
+ return () => root.unmount()
52
+ } else {
53
+ const root = reactDomClient.createRoot(el)
54
+ root.render(Component)
55
+ return () => root.unmount()
56
+ }
51
57
  }
52
- reactHydrate = (Component, el) => reactDomClient.hydrateRoot(el, Component)
53
58
  } else {
54
59
  const reactDomClient = require(`react-dom`)
55
- reactRender = (Component, el) => {
56
- reactDomClient.render(Component, el)
57
- return () => ReactDOM.unmountComponentAtNode(el)
60
+ reactFirstRenderOrHydrate = (Component, el) => {
61
+ // we will use hydrate if mount element has any content inside
62
+ const useHydrate = el && el.children.length
63
+
64
+ if (useHydrate) {
65
+ reactDomClient.hydrate(Component, el)
66
+ return () => ReactDOM.unmountComponentAtNode(el)
67
+ } else {
68
+ reactDomClient.render(Component, el)
69
+ return () => ReactDOM.unmountComponentAtNode(el)
70
+ }
58
71
  }
59
- reactHydrate = reactDomClient.hydrate
60
72
  }
61
73
 
62
74
  // Do dummy dynamic import so the jsonp __webpack_require__.e is added to the commons.js
@@ -80,53 +92,6 @@ apiRunnerAsync(`onClientEntry`).then(() => {
80
92
  })
81
93
  }
82
94
 
83
- fetch(`/___services`)
84
- .then(res => res.json())
85
- .then(services => {
86
- if (services.developstatusserver) {
87
- let isRestarting = false
88
- const parentSocket = io(
89
- `${window.location.protocol}//${window.location.hostname}:${services.developstatusserver.port}`
90
- )
91
-
92
- parentSocket.on(`structured-log`, msg => {
93
- if (
94
- !isRestarting &&
95
- msg.type === `LOG_ACTION` &&
96
- msg.action.type === `DEVELOP` &&
97
- msg.action.payload === `RESTART_REQUIRED` &&
98
- window.confirm(
99
- `The develop process needs to be restarted for the changes to ${msg.action.dirtyFile} to be applied.\nDo you want to restart the develop process now?`
100
- )
101
- ) {
102
- isRestarting = true
103
- parentSocket.emit(`develop:restart`, () => {
104
- window.location.reload()
105
- })
106
- }
107
-
108
- if (
109
- isRestarting &&
110
- msg.type === `LOG_ACTION` &&
111
- msg.action.type === `SET_STATUS` &&
112
- msg.action.payload === `SUCCESS`
113
- ) {
114
- isRestarting = false
115
- window.location.reload()
116
- }
117
- })
118
-
119
- // Prevents certain browsers spamming XHR 'ERR_CONNECTION_REFUSED'
120
- // errors within the console, such as when exiting the develop process.
121
- parentSocket.on(`disconnect`, () => {
122
- console.warn(
123
- `[socket.io] Disconnected. Unable to perform health-check.`
124
- )
125
- parentSocket.close()
126
- })
127
- }
128
- })
129
-
130
95
  /**
131
96
  * Service Workers are persistent by nature. They stick around,
132
97
  * serving a cached version of the site if they aren't removed.
@@ -147,20 +112,10 @@ apiRunnerAsync(`onClientEntry`).then(() => {
147
112
  }
148
113
 
149
114
  const rootElement = document.getElementById(`___gatsby`)
150
-
151
- const focusEl = document.getElementById(`gatsby-focus-wrapper`)
152
-
153
- // Client only pages have any empty body so we just do a normal
154
- // render to avoid React complaining about hydration mis-matches.
155
- let defaultRenderer = reactRender
156
- if (focusEl && focusEl.children.length) {
157
- defaultRenderer = reactHydrate
158
- }
159
-
160
115
  const renderer = apiRunner(
161
116
  `replaceHydrateFunction`,
162
117
  undefined,
163
- defaultRenderer
118
+ reactFirstRenderOrHydrate
164
119
  )[0]
165
120
 
166
121
  let dismissLoadingIndicator
@@ -184,7 +139,7 @@ apiRunnerAsync(`onClientEntry`).then(() => {
184
139
  if (indicatorMountElement) {
185
140
  // If user defined replaceHydrateFunction themselves the cleanupFn return might not be there
186
141
  // So fallback to unmountComponentAtNode for now
187
- if (cleanupFn) {
142
+ if (cleanupFn && typeof cleanupFn === `function`) {
188
143
  cleanupFn()
189
144
  } else {
190
145
  ReactDOM.unmountComponentAtNode(indicatorMountElement)
@@ -9,8 +9,6 @@ var _react = _interopRequireDefault(require("react"));
9
9
 
10
10
  var _reactDom = _interopRequireDefault(require("react-dom"));
11
11
 
12
- var _socket = _interopRequireDefault(require("socket.io-client"));
13
-
14
12
  var _socketIo = _interopRequireDefault(require("./socketIo"));
15
13
 
16
14
  var _emitter = _interopRequireDefault(require("./emitter"));
@@ -52,28 +50,39 @@ const loader = new _devLoader.default(_asyncRequires.default, _matchPaths.defaul
52
50
  (0, _loader.setLoader)(loader);
53
51
  loader.setApiRunner(_apiRunnerBrowser.apiRunner);
54
52
  window.___loader = _loader.publicLoader;
55
- let reactRender;
56
- let reactHydrate;
53
+ let reactFirstRenderOrHydrate;
57
54
 
58
55
  if (HAS_REACT_18) {
59
56
  const reactDomClient = require(`react-dom/client`);
60
57
 
61
- reactRender = (Component, el) => {
62
- const root = reactDomClient.createRoot(el);
63
- root.render(Component);
64
- return () => root.unmount();
65
- };
58
+ reactFirstRenderOrHydrate = (Component, el) => {
59
+ // we will use hydrate if mount element has any content inside
60
+ const useHydrate = el && el.children.length;
66
61
 
67
- reactHydrate = (Component, el) => reactDomClient.hydrateRoot(el, Component);
62
+ if (useHydrate) {
63
+ const root = reactDomClient.hydrateRoot(el, Component);
64
+ return () => root.unmount();
65
+ } else {
66
+ const root = reactDomClient.createRoot(el);
67
+ root.render(Component);
68
+ return () => root.unmount();
69
+ }
70
+ };
68
71
  } else {
69
72
  const reactDomClient = require(`react-dom`);
70
73
 
71
- reactRender = (Component, el) => {
72
- reactDomClient.render(Component, el);
73
- return () => _reactDom.default.unmountComponentAtNode(el);
74
- };
74
+ reactFirstRenderOrHydrate = (Component, el) => {
75
+ // we will use hydrate if mount element has any content inside
76
+ const useHydrate = el && el.children.length;
75
77
 
76
- reactHydrate = reactDomClient.hydrate;
78
+ if (useHydrate) {
79
+ reactDomClient.hydrate(Component, el);
80
+ return () => _reactDom.default.unmountComponentAtNode(el);
81
+ } else {
82
+ reactDomClient.render(Component, el);
83
+ return () => _reactDom.default.unmountComponentAtNode(el);
84
+ }
85
+ };
77
86
  } // Do dummy dynamic import so the jsonp __webpack_require__.e is added to the commons.js
78
87
  // bundle. This ensures hot reloading doesn't break when someone first adds
79
88
  // a dynamic import.
@@ -97,32 +106,6 @@ function notCalledFunction() {
97
106
  window.location.reload();
98
107
  });
99
108
  }
100
-
101
- fetch(`/___services`).then(res => res.json()).then(services => {
102
- if (services.developstatusserver) {
103
- let isRestarting = false;
104
- const parentSocket = (0, _socket.default)(`${window.location.protocol}//${window.location.hostname}:${services.developstatusserver.port}`);
105
- parentSocket.on(`structured-log`, msg => {
106
- if (!isRestarting && msg.type === `LOG_ACTION` && msg.action.type === `DEVELOP` && msg.action.payload === `RESTART_REQUIRED` && window.confirm(`The develop process needs to be restarted for the changes to ${msg.action.dirtyFile} to be applied.\nDo you want to restart the develop process now?`)) {
107
- isRestarting = true;
108
- parentSocket.emit(`develop:restart`, () => {
109
- window.location.reload();
110
- });
111
- }
112
-
113
- if (isRestarting && msg.type === `LOG_ACTION` && msg.action.type === `SET_STATUS` && msg.action.payload === `SUCCESS`) {
114
- isRestarting = false;
115
- window.location.reload();
116
- }
117
- }); // Prevents certain browsers spamming XHR 'ERR_CONNECTION_REFUSED'
118
- // errors within the console, such as when exiting the develop process.
119
-
120
- parentSocket.on(`disconnect`, () => {
121
- console.warn(`[socket.io] Disconnected. Unable to perform health-check.`);
122
- parentSocket.close();
123
- });
124
- }
125
- });
126
109
  /**
127
110
  * Service Workers are persistent by nature. They stick around,
128
111
  * serving a cached version of the site if they aren't removed.
@@ -132,6 +115,7 @@ function notCalledFunction() {
132
115
  * Let's warn if we find service workers in development.
133
116
  */
134
117
 
118
+
135
119
  if (`serviceWorker` in navigator) {
136
120
  navigator.serviceWorker.getRegistrations().then(registrations => {
137
121
  if (registrations.length > 0) console.warn(`Warning: found one or more service workers present.`, `If your site isn't behaving as expected, you might want to remove these.`, registrations);
@@ -139,16 +123,7 @@ function notCalledFunction() {
139
123
  }
140
124
 
141
125
  const rootElement = document.getElementById(`___gatsby`);
142
- const focusEl = document.getElementById(`gatsby-focus-wrapper`); // Client only pages have any empty body so we just do a normal
143
- // render to avoid React complaining about hydration mis-matches.
144
-
145
- let defaultRenderer = reactRender;
146
-
147
- if (focusEl && focusEl.children.length) {
148
- defaultRenderer = reactHydrate;
149
- }
150
-
151
- const renderer = (0, _apiRunnerBrowser.apiRunner)(`replaceHydrateFunction`, undefined, defaultRenderer)[0];
126
+ const renderer = (0, _apiRunnerBrowser.apiRunner)(`replaceHydrateFunction`, undefined, reactFirstRenderOrHydrate)[0];
152
127
  let dismissLoadingIndicator;
153
128
 
154
129
  if (process.env.GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND && process.env.GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR === `true`) {
@@ -166,7 +141,7 @@ function notCalledFunction() {
166
141
  if (indicatorMountElement) {
167
142
  // If user defined replaceHydrateFunction themselves the cleanupFn return might not be there
168
143
  // So fallback to unmountComponentAtNode for now
169
- if (cleanupFn) {
144
+ if (cleanupFn && typeof cleanupFn === `function`) {
170
145
  cleanupFn();
171
146
  } else {
172
147
  _reactDom.default.unmountComponentAtNode(indicatorMountElement);
@@ -16,8 +16,6 @@ var _normalizePagePath = _interopRequireDefault(require("./normalize-page-path")
16
16
  var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
17
17
 
18
18
  // TODO move away from lodash
19
- const preferDefault = m => m && m.default || m;
20
-
21
19
  function mergePageEntry(cachedPage, newPageData) {
22
20
  return { ...cachedPage,
23
21
  payload: { ...cachedPage.payload,
@@ -36,12 +34,12 @@ function mergePageEntry(cachedPage, newPageData) {
36
34
 
37
35
  class DevLoader extends _loader.BaseLoader {
38
36
  constructor(asyncRequires, matchPaths) {
39
- const loadComponent = chunkName => {
40
- if (!this.asyncRequires.components[chunkName]) {
37
+ const loadComponent = (chunkName, exportType = `components`) => {
38
+ if (!this.asyncRequires[exportType][chunkName]) {
41
39
  throw new Error(`We couldn't find the correct component chunk with the name "${chunkName}"`);
42
40
  }
43
41
 
44
- return this.asyncRequires.components[chunkName]().then(preferDefault) // loader will handle the case when component is error
42
+ return this.asyncRequires[exportType][chunkName]() // loader will handle the case when component is error
45
43
  .catch(err => err);
46
44
  };
47
45
 
@@ -32,12 +32,14 @@ function WrappedAccordionItem({
32
32
  const stacktrace = _stackTrace.default.parse(error);
33
33
 
34
34
  const codeFrameInformation = (0, _utils.getCodeFrameInformation)(stacktrace);
35
- const filePath = codeFrameInformation === null || codeFrameInformation === void 0 ? void 0 : codeFrameInformation.moduleId;
35
+ const modulePath = codeFrameInformation === null || codeFrameInformation === void 0 ? void 0 : codeFrameInformation.moduleId;
36
36
  const lineNumber = codeFrameInformation === null || codeFrameInformation === void 0 ? void 0 : codeFrameInformation.lineNumber;
37
37
  const columnNumber = codeFrameInformation === null || codeFrameInformation === void 0 ? void 0 : codeFrameInformation.columnNumber;
38
- const name = codeFrameInformation === null || codeFrameInformation === void 0 ? void 0 : codeFrameInformation.functionName;
38
+ const name = codeFrameInformation === null || codeFrameInformation === void 0 ? void 0 : codeFrameInformation.functionName; // With the introduction of Metadata management the modulePath can have a resourceQuery that needs to be removed first
39
+
40
+ const filePath = modulePath.replace(/\?export=(default|head)$/, ``);
39
41
  const res = (0, _hooks.useStackFrame)({
40
- moduleId: filePath,
42
+ moduleId: modulePath,
41
43
  lineNumber,
42
44
  columnNumber
43
45
  });
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.FireCallbackInEffect = FireCallbackInEffect;
5
+
6
+ var _react = require("react");
7
+
8
+ /*
9
+ * Calls callback in an effect and renders children
10
+ */
11
+ function FireCallbackInEffect({
12
+ children,
13
+ callback
14
+ }) {
15
+ (0, _react.useEffect)(() => {
16
+ callback();
17
+ });
18
+ return children;
19
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.VALID_NODE_NAMES = void 0;
5
+ const VALID_NODE_NAMES = [`link`, `meta`, `style`, `title`, `base`, `noscript`, `script`];
6
+ exports.VALID_NODE_NAMES = VALID_NODE_NAMES;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.headHandlerForBrowser = headHandlerForBrowser;
5
+
6
+ var _react = _interopRequireWildcard(require("react"));
7
+
8
+ var _gatsby = require("gatsby");
9
+
10
+ var _reachRouter = require("@gatsbyjs/reach-router");
11
+
12
+ var _reactDomUtils = require("../react-dom-utils");
13
+
14
+ var _fireCallbackInEffect = require("./components/fire-callback-in-effect");
15
+
16
+ var _constants = require("./constants");
17
+
18
+ var _utils = require("./utils");
19
+
20
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
+
22
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
23
+
24
+ const hiddenRoot = document.createElement(`div`);
25
+
26
+ const removePrevHeadElements = () => {
27
+ const prevHeadNodes = [...document.querySelectorAll(`[data-gatsby-head]`)];
28
+ prevHeadNodes.forEach(e => e.remove());
29
+ };
30
+
31
+ const onHeadRendered = () => {
32
+ const validHeadNodes = [];
33
+ removePrevHeadElements();
34
+ const seenIds = new Map();
35
+
36
+ for (const node of hiddenRoot.childNodes) {
37
+ var _node$attributes$id;
38
+
39
+ const nodeName = node.nodeName.toLowerCase();
40
+ const id = (_node$attributes$id = node.attributes.id) === null || _node$attributes$id === void 0 ? void 0 : _node$attributes$id.value;
41
+
42
+ if (!_constants.VALID_NODE_NAMES.includes(nodeName)) {
43
+ (0, _utils.warnForInvalidTags)(nodeName);
44
+ } else {
45
+ const clonedNode = node.cloneNode(true);
46
+ clonedNode.setAttribute(`data-gatsby-head`, true);
47
+
48
+ if (id) {
49
+ if (!seenIds.has(id)) {
50
+ validHeadNodes.push(clonedNode);
51
+ seenIds.set(id, validHeadNodes.length - 1);
52
+ } else {
53
+ const indexOfPreviouslyInsertedNode = seenIds.get(id);
54
+ validHeadNodes[indexOfPreviouslyInsertedNode].remove();
55
+ validHeadNodes[indexOfPreviouslyInsertedNode] = clonedNode;
56
+ }
57
+ } else {
58
+ validHeadNodes.push(clonedNode);
59
+ }
60
+ }
61
+ }
62
+
63
+ document.head.append(...validHeadNodes);
64
+ };
65
+
66
+ if (process.env.BUILD_STAGE === `develop`) {
67
+ // We set up observer to be able to regenerate <head> after react-refresh
68
+ // updates our hidden element.
69
+ const observer = new MutationObserver(onHeadRendered);
70
+ observer.observe(hiddenRoot, {
71
+ attributes: true,
72
+ childList: true,
73
+ characterData: true,
74
+ subtree: true
75
+ });
76
+ }
77
+
78
+ function headHandlerForBrowser({
79
+ pageComponent,
80
+ staticQueryResults,
81
+ pageComponentProps
82
+ }) {
83
+ (0, _react.useEffect)(() => {
84
+ if (pageComponent !== null && pageComponent !== void 0 && pageComponent.Head) {
85
+ (0, _utils.headExportValidator)(pageComponent.Head);
86
+ const {
87
+ render
88
+ } = (0, _reactDomUtils.reactDOMUtils)();
89
+ const Head = pageComponent.Head;
90
+ render(
91
+ /*#__PURE__*/
92
+ // just a hack to call the callback after react has done first render
93
+ // Note: In dev, we call onHeadRendered twice( in FireCallbackInEffect and after mutualution observer dectects initail render into hiddenRoot) this is for hot reloading
94
+ // In Prod we only call onHeadRendered in FireCallbackInEffect to render to head
95
+ _react.default.createElement(_fireCallbackInEffect.FireCallbackInEffect, {
96
+ callback: onHeadRendered
97
+ }, /*#__PURE__*/_react.default.createElement(_gatsby.StaticQueryContext.Provider, {
98
+ value: staticQueryResults
99
+ }, /*#__PURE__*/_react.default.createElement(_reachRouter.LocationProvider, null, /*#__PURE__*/_react.default.createElement(Head, (0, _utils.filterHeadProps)(pageComponentProps))))), hiddenRoot);
100
+ }
101
+
102
+ return () => {
103
+ removePrevHeadElements();
104
+ };
105
+ });
106
+ }
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ exports.__esModule = true;
6
+ exports.headHandlerForSSR = headHandlerForSSR;
7
+
8
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
+
10
+ const React = require(`react`);
11
+
12
+ const {
13
+ grabMatchParams
14
+ } = require(`../find-path`);
15
+
16
+ const {
17
+ createElement
18
+ } = require(`react`);
19
+
20
+ const {
21
+ StaticQueryContext
22
+ } = require(`gatsby`);
23
+
24
+ const {
25
+ headExportValidator,
26
+ filterHeadProps,
27
+ warnForInvalidTags
28
+ } = require(`./utils`);
29
+
30
+ const {
31
+ ServerLocation,
32
+ Router
33
+ } = require(`@gatsbyjs/reach-router`);
34
+
35
+ const {
36
+ renderToString
37
+ } = require(`react-dom/server`);
38
+
39
+ const {
40
+ parse
41
+ } = require(`node-html-parser`);
42
+
43
+ const {
44
+ VALID_NODE_NAMES
45
+ } = require(`./constants`);
46
+
47
+ function headHandlerForSSR({
48
+ pageComponent,
49
+ setHeadComponents,
50
+ staticQueryContext,
51
+ pageData,
52
+ pagePath
53
+ }) {
54
+ if (pageComponent !== null && pageComponent !== void 0 && pageComponent.Head) {
55
+ headExportValidator(pageComponent.Head);
56
+
57
+ function HeadRouteHandler(props) {
58
+ var _pageData$result, _pageData$result$page;
59
+
60
+ const _props = { ...props,
61
+ ...pageData.result,
62
+ params: { ...grabMatchParams(props.location.pathname),
63
+ ...(((_pageData$result = pageData.result) === null || _pageData$result === void 0 ? void 0 : (_pageData$result$page = _pageData$result.pageContext) === null || _pageData$result$page === void 0 ? void 0 : _pageData$result$page.__params) || {})
64
+ }
65
+ };
66
+ return createElement(pageComponent.Head, filterHeadProps(_props));
67
+ }
68
+
69
+ const routerElement = /*#__PURE__*/React.createElement(StaticQueryContext.Provider, {
70
+ value: staticQueryContext
71
+ }, /*#__PURE__*/React.createElement(ServerLocation, {
72
+ url: `${__BASE_PATH__}${pagePath}`
73
+ }, /*#__PURE__*/React.createElement(Router, {
74
+ baseuri: __BASE_PATH__,
75
+ component: ({
76
+ children
77
+ }) => /*#__PURE__*/React.createElement(React.Fragment, null, children)
78
+ }, /*#__PURE__*/React.createElement(HeadRouteHandler, {
79
+ path: "/*"
80
+ })))); // extract head nodes from string
81
+
82
+ const rawString = renderToString(routerElement);
83
+ const headNodes = parse(rawString).childNodes;
84
+ const validHeadNodes = [];
85
+ const seenIds = new Map();
86
+
87
+ for (const node of headNodes) {
88
+ const {
89
+ rawTagName
90
+ } = node;
91
+ const id = node.attributes.id;
92
+
93
+ if (!VALID_NODE_NAMES.includes(rawTagName)) {
94
+ warnForInvalidTags(rawTagName);
95
+ } else {
96
+ let element;
97
+ const attributes = { ...node.attributes,
98
+ "data-gatsby-head": true
99
+ };
100
+
101
+ if (rawTagName === `script`) {
102
+ element = /*#__PURE__*/React.createElement("script", (0, _extends2.default)({}, attributes, {
103
+ dangerouslySetInnerHTML: {
104
+ __html: node.text
105
+ }
106
+ }));
107
+ } else {
108
+ var _node$childNodes$;
109
+
110
+ element = /*#__PURE__*/React.createElement(node.rawTagName, attributes, (_node$childNodes$ = node.childNodes[0]) === null || _node$childNodes$ === void 0 ? void 0 : _node$childNodes$.textContent);
111
+ }
112
+
113
+ if (id) {
114
+ if (!seenIds.has(id)) {
115
+ validHeadNodes.push(element);
116
+ seenIds.set(id, validHeadNodes.length - 1);
117
+ } else {
118
+ const indexOfPreviouslyInsertedNode = seenIds.get(id);
119
+ validHeadNodes[indexOfPreviouslyInsertedNode] = element;
120
+ }
121
+ } else {
122
+ validHeadNodes.push(element);
123
+ }
124
+ }
125
+ }
126
+
127
+ setHeadComponents(validHeadNodes);
128
+ }
129
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.filterHeadProps = filterHeadProps;
5
+ exports.headExportValidator = headExportValidator;
6
+ exports.warnForInvalidTags = warnForInvalidTags;
7
+
8
+ var _constants = require("./constants");
9
+
10
+ /**
11
+ * Filter the props coming from a page down to just the ones that are relevant for head.
12
+ * This e.g. filters out properties that are undefined during SSR.
13
+ */
14
+ function filterHeadProps(input) {
15
+ return {
16
+ location: {
17
+ pathname: input.location.pathname
18
+ },
19
+ params: input.params,
20
+ data: input.data || {},
21
+ pageContext: input.pageContext
22
+ };
23
+ }
24
+ /**
25
+ * Throw error if Head export is not a valid
26
+ */
27
+
28
+
29
+ function headExportValidator(head) {
30
+ if (typeof head !== `function`) throw new Error(`Expected "Head" export to be a function got "${typeof head}".`);
31
+ }
32
+ /**
33
+ * Warn once for same messsage
34
+ */
35
+
36
+
37
+ let warnOnce = _ => {};
38
+
39
+ if (process.env.NODE_ENV !== `production`) {
40
+ const warnings = new Set();
41
+
42
+ warnOnce = msg => {
43
+ if (!warnings.has(msg)) {
44
+ console.warn(msg);
45
+ }
46
+
47
+ warnings.add(msg);
48
+ };
49
+ }
50
+ /**
51
+ * Warn for invalid tags in head.
52
+ * @param {string} tagName
53
+ */
54
+
55
+
56
+ function warnForInvalidTags(tagName) {
57
+ if (process.env.NODE_ENV !== `production`) {
58
+ const warning = `<${tagName}> is not a valid head element. Please use one of the following: ${_constants.VALID_NODE_NAMES.join(`, `)}`;
59
+ warnOnce(warning);
60
+ }
61
+ }