-
Notifications
You must be signed in to change notification settings - Fork 37
/
gatsby-node.js
143 lines (110 loc) · 5.21 KB
/
gatsby-node.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
'use strict';
const fs = require('fs');
const path = require('path');
const util = require('util');
const pMap = require('p-map');
const globby = require('globby');
const isTextPath = require('is-text-path');
const readFileAsync = util.promisify(fs.readFile);
const writeFileAsync = util.promisify(fs.writeFile);
const TRANSFORM_CONCURRENCY = 10;
const getRelativePrefix = (path) => {
const depth = path.split('/').length - 2;
const relativePrefix = depth > 0 ? '../'.repeat(depth) : './';
return relativePrefix;
};
const relativizeHtmlFiles = async () => {
// Replaces all /__GATSBY_IPFS_PATH_PREFIX__/ strings with the correct relative paths
// based on the depth of the file within the `public/` folder
const paths = await globby(['public/**/*.html']);
await pMap(paths, async (path) => {
const buffer = await readFileAsync(path);
let contents = buffer.toString();
// Skip if there's nothing to do
if (!contents.includes('__GATSBY_IPFS_PATH_PREFIX__')) {
return;
}
const relativePrefix = getRelativePrefix(path);
contents = contents
.replace(/\/__GATSBY_IPFS_PATH_PREFIX__\//g, () => relativePrefix);
await writeFileAsync(path, contents);
}, { concurrency: TRANSFORM_CONCURRENCY });
};
const relativizeJsFiles = async () => {
// Replaces all "/__GATSBY_IPFS_PATH_PREFIX__" strings __GATSBY_IPFS_PATH_PREFIX__
// Replaces all "/__GATSBY_IPFS_PATH_PREFIX__/" strings with __GATSBY_IPFS_PATH_PREFIX__ + "/"
// Replaces all "/__GATSBY_IPFS_PATH_PREFIX__/xxxx" strings with __GATSBY_IPFS_PATH_PREFIX__ + "/xxxx"
// Also ensures that `__GATSBY_IPFS_PATH_PREFIX__` is defined in case this JS file is outside the document context, e.g.: in a worker
const paths = await globby(['public/**/*.js']);
await pMap(paths, async (path) => {
const buffer = await readFileAsync(path);
let contents = buffer.toString();
// Skip if there's nothing to do
if (!contents.includes('__GATSBY_IPFS_PATH_PREFIX__')) {
return;
}
// DO NOT remove the extra spaces, otherwise the code will be invalid when minified,
// e.g.: return"__GATSBY_IPFS_PATH_PREFIX__/static/..." -> return __GATSBY_IPFS_PATH_PREFIX + "/static/..."
contents = contents
.replace(/["']\/__GATSBY_IPFS_PATH_PREFIX__['"]/g, () => ' __GATSBY_IPFS_PATH_PREFIX__ ')
// Erases "/__GATSBY_IPFS_PATH_PREFIX__", usually found in filepaths
.replace(/\/__GATSBY_IPFS_PATH_PREFIX__/g, () => '');
// prevents placement of header if all instances of
// __GATSBY_IPFS_PATH_PREFIX__ were removed in previous line
if (contents.includes('__GATSBY_IPFS_PATH_PREFIX__')) {
contents = `if(typeof __GATSBY_IPFS_PATH_PREFIX__ === 'undefined'){__GATSBY_IPFS_PATH_PREFIX__=''}${contents}`;
}
await writeFileAsync(path, contents);
}, { concurrency: TRANSFORM_CONCURRENCY });
};
const relativizeMiscAssetFiles = async () => {
// Replaces all /__GATSBY_IPFS_PATH_PREFIX__/ strings to standard relative paths
const paths = await globby(['public/**/*', '!public/**/*.html', '!public/**/*.js']);
await pMap(paths, async (path) => {
// Skip if this is not a text file
if (!isTextPath(path)) {
return;
}
const buffer = await readFileAsync(path);
let contents = buffer.toString();
// Skip if there's nothing to do
if (!contents.includes('__GATSBY_IPFS_PATH_PREFIX__')) {
return;
}
const relativePrefix = getRelativePrefix(path);
contents = contents
.replace(/\/__GATSBY_IPFS_PATH_PREFIX__\//g, () => relativePrefix);
await writeFileAsync(path, contents);
}, { concurrency: TRANSFORM_CONCURRENCY });
};
const injectScriptInHtmlFiles = async () => {
// Injects a script into the <head> of all HTML files that defines the
// __GATSBY_IPFS_PATH_PREFIX__ variable
const scriptBuffer = await readFileAsync(path.resolve(__dirname, 'runtime/head-script.js'));
const scriptContents = scriptBuffer.toString();
const paths = await globby(['public/**/*.html']);
await pMap(paths, async (path) => {
let contents = await readFileAsync(path);
contents = contents
.toString()
.replace(/<head>/, () => `<head><script>${scriptContents}</script>`);
await writeFileAsync(path, contents);
}, { concurrency: TRANSFORM_CONCURRENCY });
};
exports.onPreBootstrap = ({ store, reporter }) => {
const { config, program } = store.getState();
if (!/\/?__GATSBY_IPFS_PATH_PREFIX__/.test(config.pathPrefix)) {
reporter.panic('The pathPrefix must be set to __GATSBY_IPFS_PATH_PREFIX__ in your gatsby-config.js file');
}
if (program._[0] === 'build' && !program.prefixPaths) {
reporter.panic('The build command must be run with --prefix-paths');
}
};
exports.onPostBuild = async () => {
// Relativize all occurrences of __GATSBY_IPFS_PATH_PREFIX__ within the built files
await relativizeHtmlFiles();
await relativizeJsFiles();
await relativizeMiscAssetFiles();
// Inject the runtime script into the <head> of all HTML files
await injectScriptInHtmlFiles();
};