-
Notifications
You must be signed in to change notification settings - Fork 84
/
gatsby-browser.js
167 lines (149 loc) · 6.18 KB
/
gatsby-browser.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//import * as whatwg-fetch from 'whatwg-fetch';
// Need fetch polyfill in gatsby browser?
import { addGlobalEventListener } from './src/utils/misc';
import { getRouteData } from './src/utils/routes';
import './src/styles/custom-code-buttons.less';
import 'prismjs/themes/prism-tomorrow.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/command-line/prism-command-line.css';
/* This function adds redirects for any 'page' that sets a redirect property
Currently used for redirecting a parent page like 'Android' to the first of
its child pages as indicated in the _template file.
The 'onEnter' redirect is needed for when the route is entered from a sibling route:
docs.com/faq -> docs.com/dev/android -> docs.com/dev/android/getting-started
The 'onChange' redirect is needed for when the route is entered from a child route:
docs.com/dev/android/events -> docs.com/dev/android -> docs.com/dev/android/getting-started
These lifecycle functions may be deprecated in future versions of '@reach/router' so
we will need to keep an eye on this when moving to new Gatsby versions in the future */
function addRedirects(routes) {
const redirect = getRouteData(routes).redirect;
if (redirect && routes.path) {
routes.onChange = (prev, next, replace, callback) => {
if (next && next.location
&& (next.location.pathname === routes.path
|| next.location.pathname === `${routes.path}/`)) {
replace(redirect);
}
callback();
}
routes.onEnter = (next, replace) => {
if (next && next.location
&& (next.location.pathname === routes.path
|| next.location.pathname === `${routes.path}/`)) {
replace(redirect);
}
}
}
if (routes.childRoutes && routes.childRoutes.length > 0) {
routes.childRoutes.forEach(addRedirects);
}
}
// There is a bug in the automatic route/templating logic within Gatsby that wants to set
// '/integrations/facebook' as a parent of '/integrations/facebook-atlas'
// This is a hacky fix but should do the trick until we move to Gatsby 1.0
function integrationsRouteFix(routes, rootRoutePath, previousIntegrationRoute) {
let i = 0;
const rootRoutes = routes.childRoutes;
// Find the route that incorrectly has its parent set as the root
for (; i < rootRoutes.length; i++) {
if (rootRoutes[i].path.indexOf(rootRoutePath) >= 0) {
break;
}
}
if (i < rootRoutes.length) {
let removed = rootRoutes.splice(i, 1)[0];
// Find the spot in the 'integrations' routes that the removed route should be inserted after
const integrations = rootRoutes.filter(x => x.path.indexOf('integrations') >= 0)[0].childRoutes;
for (i = 0; i < integrations.length; i++) {
if (integrations[i].path.indexOf(previousIntegrationRoute) >= 0) {
i = i + 1;
break;
}
}
if (i < integrations.length) {
integrations.splice(i, 0, removed);
}
}
}
function optionalTrailingSlashes(routes, level) {
if (routes.path && level > 0) {
routes.path = routes.path.replace(/\/$/, '');
}
if (routes.childRoutes) {
routes.childRoutes.forEach((r) => {
optionalTrailingSlashes(r, level + 1);
});
}
return routes;
}
/*export const modifyRoutes = (routes) => {
addRedirects(routes);
integrationsRouteFix(routes,'facebook-atlas', 'facebook');
integrationsRouteFix(routes,'adobe-audience-manager', 'adobe');
integrationsRouteFix(routes, 'amazon-kinesis-firehose', 'amazon-kinesis');
integrationsRouteFix(routes, 'branch-metrics-server', 'branch-metrics');
optionalTrailingSlashes(routes, 0);
return routes;
}*/
// This code fixes the issue of React not being able to navigate directly
// to 'hash' locations as part of page load or navigation.
function scrollToHash(location) {
if (location.hash) {
// For some reason, after navigating a while the window history ends up keeping
// a stale state with the same key - this tells the router that subsequent hashChange
// events are not new navigations and thus the listeners are not notified.
if (window.history && window.history.state) {
window.history.state.key = null;
}
setTimeout(() => {
const content = document.querySelector(`${location.hash}`);
if (content && content.scrollIntoView) {
content.scrollIntoView();
} else if (window.mParticle) {
mParticle.logPageView('Error 404', {
targetUrl: `${location.pathname}${location.hash}`
});
}
}, 0);
} else {
// If there isn't a hash, scroll to the top just to be safe
window.scrollTo(0, 0);
}
}
export const onRouteUpdate = ({ location }) => {
scrollToHash(location);
if (window.mParticle) {
return mParticle.logPageView(
"Docs Page View",
{
anchor: location.pathname,
},
{
"Google.Page": location.pathname,
}
);
}
};
function logError(e) {
if (window.mParticle) {
mParticle.logEvent("Docs error", {error: e});
}
}
addGlobalEventListener('onerror', logError);
window.addEventListener('error', logError);
// addGlobalEventListener('onhashchange', () => scrollToHash(window.location));
// Polyfill for 'matches' function -- used for checking on outside clicks for search, flyouts
if (!Element.prototype.matches) {
Element.prototype.matches =
Element.prototype.matchesSelector ||
Element.prototype.mozMatchesSelector ||
Element.prototype.msMatchesSelector ||
Element.prototype.oMatchesSelector ||
Element.prototype.webkitMatchesSelector ||
function(s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i = matches.length;
while (--i >= 0 && matches.item(i) !== this) {}
return i > -1;
};
}