1
1
require ( 'dotenv' ) . config ( {
2
2
path : `.env.${ process . env . NODE_ENV } ` ,
3
3
} ) ;
4
- const utf8Truncate = require ( 'truncate-utf8-bytes' ) ;
5
4
const gracefulFs = require ( 'graceful-fs' ) ;
6
5
6
+ const algoliaTransformer = require ( './src/constants/algolia-indexing.js' ) ;
7
+
7
8
const ANSI_BLUE = '\033[34m' ;
8
9
const ANSI_GREEN = '\033[32m' ;
9
10
const ANSI_STOP = '\033[0m' ;
@@ -124,181 +125,6 @@ const indexQuery = `
124
125
}
125
126
` ;
126
127
127
- const transformNodeForAlgolia = ( node ) => {
128
- let newNode = node ;
129
- newNode [ 'title' ] = node . frontmatter . title ;
130
- newNode [ 'path' ] = node . fields . path ;
131
- newNode [ 'type' ] = 'guide' ;
132
- if ( node . frontmatter . product ) {
133
- newNode [ 'product' ] = node . frontmatter . product ;
134
- }
135
- if ( node . frontmatter . platform ) {
136
- newNode [ 'platform' ] = node . frontmatter . platform ;
137
- }
138
-
139
- if ( node . fields . docType == 'doc' ) {
140
- newNode [ 'product' ] = node . fields . product ;
141
- newNode [ 'version' ] = node . fields . version ;
142
- newNode [ 'productVersion' ] =
143
- node . fields . product + ' > ' + node . fields . version ;
144
- newNode [ 'type' ] = 'doc' ;
145
- }
146
-
147
- delete newNode [ 'frontmatter' ] ;
148
- delete newNode [ 'fields' ] ;
149
- return newNode ;
150
- } ;
151
-
152
- const makePathDictionary = ( nodes ) => {
153
- let dictionary = { } ;
154
- for ( let node of nodes ) {
155
- dictionary [ node . fields . path ] = node . frontmatter . title ;
156
- }
157
- return dictionary ;
158
- } ;
159
-
160
- const makeBreadcrumbs = ( node , dictionary , advocacy = false ) => {
161
- let depth = advocacy ? 3 : 4 ;
162
- let trail = '' ;
163
- const path = node . fields . path ;
164
- const pathPieces = path . split ( '/' ) ;
165
- for ( let i = depth ; i < pathPieces . length ; i ++ ) {
166
- let parentPath = pathPieces . slice ( 0 , i ) . join ( '/' ) ;
167
- trail += dictionary [ parentPath ] + ' / ' ;
168
- }
169
- return trail ;
170
- } ;
171
-
172
- const addBreadcrumbsToNodes = ( nodes ) => {
173
- const pathDictionary = makePathDictionary ( nodes ) ;
174
- let newNodes = [ ] ;
175
- for ( let node of nodes ) {
176
- let newNode = node ;
177
- const advocacy = ! node . fields . product ;
178
- newNode [ 'breadcrumb' ] = makeBreadcrumbs ( node , pathDictionary , advocacy ) ;
179
- newNodes . push ( newNode ) ;
180
- }
181
- return newNodes ;
182
- } ;
183
-
184
- const mdxTreeToSearchNodes = ( rootNode ) => {
185
- rootNode . depth = 0 ;
186
- const stack = [ rootNode ] ;
187
- const searchNodes = [ ] ;
188
- const initialSearchNode = { text : '' , heading : '' } ;
189
-
190
- let parseState = {
191
- attribute : 'text' ,
192
- nextAttribute : null ,
193
- transitionDepth : null ,
194
- } ;
195
- const nextParseStateIfDepth = ( depth ) => {
196
- if ( ! parseState . transitionDepth || depth > parseState . transitionDepth )
197
- return ;
198
- parseState = {
199
- attribute : parseState . nextAttribute ,
200
- nextAttribute : null ,
201
- transitionDepth : null ,
202
- } ;
203
- } ;
204
- const setHeadingParseState = ( depth ) => {
205
- parseState = {
206
- attribute : 'heading' ,
207
- nextAttribute : 'text' ,
208
- transitionDepth : depth ,
209
- } ;
210
- } ;
211
-
212
- let searchNode = { ...initialSearchNode } ;
213
- let node = null ;
214
- while ( stack . length > 0 ) {
215
- node = stack . pop ( ) ;
216
- nextParseStateIfDepth ( node . depth ) ;
217
-
218
- if ( [ 'import' , 'export' ] . includes ( node . type ) ) {
219
- // skip these nodes
220
- continue ;
221
- }
222
-
223
- if ( node . type === 'heading' ) {
224
- // break on headings
225
- if ( searchNode . text . length > 0 ) {
226
- searchNodes . push ( searchNode ) ;
227
- }
228
- searchNode = { ...initialSearchNode } ;
229
- setHeadingParseState ( node . depth ) ;
230
- }
231
-
232
- if ( node . value && ! [ 'html' , 'jsx' ] . includes ( node . type ) ) {
233
- searchNode [ parseState . attribute ] += ` ${ node . value } ` ;
234
- } else {
235
- ( node . children || [ ] )
236
- . slice ( )
237
- . reverse ( )
238
- . forEach ( ( child ) => {
239
- child . depth = node . depth + 1 ;
240
- stack . push ( child ) ;
241
- } ) ;
242
- }
243
- }
244
- if ( searchNode . text . length > '' ) {
245
- searchNodes . push ( searchNode ) ;
246
- }
247
-
248
- return searchNodes ;
249
- } ;
250
-
251
- const trimSpaces = ( str ) => {
252
- return str . replace ( / \s + / g, ' ' ) . trim ( ) ;
253
- } ;
254
-
255
- const splitNodeContent = ( nodes ) => {
256
- const result = [ ] ;
257
- for ( const node of nodes ) {
258
- // skip indexing this content for now
259
- if (
260
- node . path . includes ( '/postgresql_journey/' ) ||
261
- node . path . includes ( '/playground/' )
262
- ) {
263
- console . log ( `skipped indexing ${ node . path } ` ) ;
264
- continue ;
265
- }
266
-
267
- const searchNodes = mdxTreeToSearchNodes ( node . mdxAST ) ;
268
-
269
- searchNodes . forEach ( ( searchNode , i ) => {
270
- let newNode = { ...node } ;
271
- delete newNode [ 'mdxAST' ] ;
272
-
273
- newNode . id = `${ newNode . path } -${ i + 1 } ` ;
274
- newNode . heading = trimSpaces ( searchNode . heading ) ;
275
- newNode . excerpt = utf8Truncate (
276
- trimSpaces ( `${ searchNode . heading } : ${ searchNode . text } ` ) ,
277
- 8000 ,
278
- ) ;
279
- if ( searchNode . heading . length > 0 ) {
280
- const anchor = newNode . heading
281
- . split ( ' ' )
282
- . join ( '-' )
283
- . toLowerCase ( )
284
- . replace ( '/' , '' ) ;
285
- newNode . path = `${ newNode . path } #${ anchor } ` ;
286
- }
287
-
288
- result . push ( newNode ) ;
289
- } ) ;
290
- }
291
- return result ;
292
- } ;
293
-
294
- const netlifyHeaders = ( ) => {
295
- if ( isProduction ) return { } ;
296
-
297
- return {
298
- '/*' : [ 'X-Robots-Tag: noindex' ] ,
299
- } ;
300
- } ;
301
-
302
128
/********** Gatsby config *********/
303
129
module . exports = {
304
130
flags : {
@@ -325,7 +151,9 @@ module.exports = {
325
151
{
326
152
resolve : 'gatsby-plugin-netlify' ,
327
153
options : {
328
- headers : netlifyHeaders ( ) ,
154
+ headers : {
155
+ '/*' : isProduction ? [ ] : [ 'X-Robots-Tag: noindex' ] ,
156
+ } ,
329
157
} ,
330
158
} ,
331
159
// 'gatsby-plugin-remove-fingerprints', // speeds up Netlify, see https://github.com/narative/gatsby-plugin-remove-fingerprints
@@ -438,32 +266,24 @@ module.exports = {
438
266
whereToIncludeRedirects : '' , // defaults to: "server"
439
267
} ,
440
268
} ,
269
+ {
270
+ // This plugin must be placed last in your list of plugins to ensure that it can query all the GraphQL data
271
+ resolve : `gatsby-plugin-algolia` ,
272
+ options : {
273
+ appId : process . env . ALGOLIA_APP_ID ,
274
+ apiKey : process . env . ALGOLIA_API_KEY ,
275
+ indexName : algoliaIndex ,
276
+ queries : [
277
+ {
278
+ query : indexQuery ,
279
+ transformer : algoliaTransformer ,
280
+ indexName : algoliaIndex ,
281
+ } ,
282
+ ] ,
283
+ chunkSize : 1000 ,
284
+ enablePartialUpdates : false ,
285
+ skipIndexing : process . env . INDEX_ON_BUILD !== 'true' ,
286
+ } ,
287
+ } ,
441
288
] ,
442
289
} ;
443
-
444
- if ( process . env . INDEX_ON_BUILD && process . env . INDEX_ON_BUILD !== 'false' ) {
445
- module . exports [ 'plugins' ] . push ( {
446
- // This plugin must be placed last in your list of plugins to ensure that it can query all the GraphQL data
447
- resolve : `gatsby-plugin-algolia` ,
448
- options : {
449
- appId : process . env . ALGOLIA_APP_ID ,
450
- apiKey : process . env . ALGOLIA_API_KEY ,
451
- indexName : algoliaIndex ,
452
- queries : [
453
- {
454
- query : indexQuery ,
455
- transformer : ( { data } ) =>
456
- splitNodeContent (
457
- addBreadcrumbsToNodes ( data . allMdx . nodes ) . map ( ( node ) =>
458
- transformNodeForAlgolia ( node ) ,
459
- ) ,
460
- ) ,
461
- indexName : algoliaIndex ,
462
- } ,
463
- ] ,
464
- chunkSize : 1000 , // default: 1000,
465
- enablePartialUpdates : false ,
466
- skipIndexing : ! process . env . INDEX_ON_BUILD , // useless on plugin version 0.13.0, just for posterity
467
- } ,
468
- } ) ;
469
- }
0 commit comments