@jungvonmatt/contentful-ssg 1.0.0 → 1.0.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.
- package/README.md +71 -27
- package/dist/index.js +1 -6
- package/dist/lib/config.js +14 -2
- package/dist/lib/file-manager.d.ts +2 -1
- package/dist/lib/file-manager.js +20 -11
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -7
- package/src/lib/config.ts +15 -3
- package/src/lib/file-manager.test.ts +6 -6
- package/src/lib/file-manager.ts +39 -12
- package/src/types.ts +1 -1
package/README.md
CHANGED
|
@@ -40,28 +40,67 @@ npx cssg init --typescript
|
|
|
40
40
|
<!-- prettier-ignore -->
|
|
41
41
|
#### Configuration values
|
|
42
42
|
|
|
43
|
-
| Name | Type
|
|
44
|
-
| ------------------ |
|
|
45
|
-
| accessToken | `
|
|
46
|
-
| previewAccessToken | `
|
|
47
|
-
| spaceId | `
|
|
48
|
-
| environmentId | `
|
|
49
|
-
| format | `
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
43
|
+
| Name | Type | Default | Description |
|
|
44
|
+
| ------------------ | --------------------------------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
+
| accessToken | `string` | `undefined` | Content Delivery API - access token |
|
|
46
|
+
| previewAccessToken | `string` | `undefined` | Content Preview API - access token |
|
|
47
|
+
| spaceId | `string` | `undefined` | Contentful Space id |
|
|
48
|
+
| environmentId | `string` | `'master'` | Contentful Environment id |
|
|
49
|
+
| format | `string`\|`function`\|`object` | `'yaml'` | File format ( `yaml`, `toml`, `md`, `json`) You can add a function returning the format or you can add a mapping object like `{yaml: [glob pattern]}` ([pattern](https://github.com/micromatch/micromatch) should match the directory) |
|
|
50
|
+
| plugins | `[string]`\|`[[string, options]]`\|`[{resolve:'string', options:{}}]` | `[]` | Add plugins to contentful-ssg. See [Plugins](#plugins) |
|
|
51
|
+
| directory | `string` | `'./content'` | Base directory for content files. |
|
|
52
|
+
| validate | `function` | `undefined` | Pass `function(transformContext, runtimeContext){...}` to validate an entry. Return `false` to skip the entry completely. Without a validate function entries with a missing required field are skipped. |
|
|
53
|
+
| transform | `function` | `undefined` | Pass `function(transformContext, runtimeContext){...}` to modify the stored object. Return `undefined` to skip the entry completely. (no file will be written) |
|
|
54
|
+
| mapDirectory | `function` | `undefined` | Pass `function(transformContext, runtimeContext, defaultValue){...}` to customize the directory per content-type relative to the base directory. |
|
|
55
|
+
| mapFilename | `function` | `undefined` | Pass `function(transformContext, runtimeContext, defaultValue){...}` to customize the filename per entry |
|
|
56
|
+
| mapAssetLink | `function` | `undefined` | Pass `function(transformContext, runtimeContext, defaultValue){...}` to customize how asset links are stored |
|
|
57
|
+
| mapEntryLink | `function` | `undefined` | Pass `function(transformContext, runtimeContext, defaultValue){...}` to customize how entry links are stored |
|
|
58
|
+
| mapMetaFields | `function` | `undefined` | Pass `function(transformContext, runtimeContext, defaultValue){...}` to customize the meta fields per entry |
|
|
59
|
+
| richTextRenderer | `boolean`\|`object`\|`function` | `{}` | We use the contentful [`rich-text-html-renderer`](https://github.com/contentful/rich-text/tree/master/packages/rich-text-html-renderer) to render the html.<br/> You can pass a [configuration object](https://github.com/contentful/rich-text/tree/master/packages/rich-text-html-renderer#usage)<br/> or you can pass `function(document){...}` to use your own richtext renderer or you can turn it off by passing `false` to get a mirrored version of the JSON output |
|
|
60
|
+
| before | `function` | `undefined` | Runs `function(runtimeContext){...}` before processing the content right after pulling data from contentful |
|
|
61
|
+
| after | `function` | `undefined` | Runs `function(runtimeContext){...}` after processing the content right before the cleanup |
|
|
62
|
+
|
|
63
|
+
### Plugins
|
|
64
|
+
|
|
65
|
+
You can add plugins to contentful-ssg by adding the package name or a local path to the plugins array of your configuration.
|
|
61
66
|
|
|
67
|
+
```js
|
|
68
|
+
plugins: ['my-plugin-package', './plugins/my-local-plugin]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
All plugins can have options specified by wrapping the name and an options object in an array inside your config or by using a more verbose object notation.
|
|
72
|
+
|
|
73
|
+
For specifying no options, these are all equivalent:
|
|
74
|
+
```js
|
|
75
|
+
{
|
|
76
|
+
"plugins": ["my-plugin", ["my-plugin"], ["my-plugin", {}], {resolve: "my-plugin", options: {}}]
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To specify an option, pass an object with the keys as the option names.
|
|
81
|
+
```js
|
|
82
|
+
{
|
|
83
|
+
"plugins": [
|
|
84
|
+
[
|
|
85
|
+
"my-plugin-a",
|
|
86
|
+
{
|
|
87
|
+
"option": "value"
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
{
|
|
91
|
+
resolve: "my-plugin-b",
|
|
92
|
+
options: {
|
|
93
|
+
"option": "value"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
```
|
|
62
99
|
|
|
63
100
|
### Runtime Hooks
|
|
101
|
+
|
|
64
102
|
**before**
|
|
103
|
+
|
|
65
104
|
```js
|
|
66
105
|
import
|
|
67
106
|
(runtimeContext) => {
|
|
@@ -72,44 +111,50 @@ import
|
|
|
72
111
|
```
|
|
73
112
|
|
|
74
113
|
**after**
|
|
114
|
+
|
|
75
115
|
```js
|
|
76
116
|
(runtimeContext) => {
|
|
77
117
|
// Do things after processing the localized contentful entries before cleanup
|
|
78
118
|
// We have access to values added to the context in the before hook
|
|
79
|
-
console.log(runtimeContext.key) // -> 'test'
|
|
80
|
-
}
|
|
119
|
+
console.log(runtimeContext.key); // -> 'test'
|
|
120
|
+
};
|
|
81
121
|
```
|
|
82
122
|
|
|
83
123
|
### Transform Hooks
|
|
124
|
+
|
|
84
125
|
**transform**
|
|
126
|
+
|
|
85
127
|
```js
|
|
86
128
|
(transformContext, runtimeContext) => {
|
|
87
|
-
const {content} = transformContext;
|
|
129
|
+
const { content } = transformContext;
|
|
88
130
|
// modify content and
|
|
89
131
|
// return object
|
|
90
132
|
return content;
|
|
91
|
-
}
|
|
133
|
+
};
|
|
92
134
|
```
|
|
93
135
|
|
|
94
136
|
**mapFilename**
|
|
137
|
+
|
|
95
138
|
```js
|
|
96
139
|
(transformContext, runtimeContext, defaultValue) => {
|
|
97
140
|
// customize the filename on entry level
|
|
98
141
|
// return string
|
|
99
142
|
return defaultValue;
|
|
100
|
-
}
|
|
143
|
+
};
|
|
101
144
|
```
|
|
102
145
|
|
|
103
146
|
**mapDirectory**
|
|
147
|
+
|
|
104
148
|
```js
|
|
105
149
|
(transformContext, runtimeContext, defaultValue) => {
|
|
106
150
|
// customize the directory on entry level
|
|
107
151
|
// return string
|
|
108
152
|
return defaultValue;
|
|
109
|
-
}
|
|
153
|
+
};
|
|
110
154
|
```
|
|
111
155
|
|
|
112
156
|
**mapAssetLink**
|
|
157
|
+
|
|
113
158
|
```js
|
|
114
159
|
(transformContext, runtimeContext, defaultValue) => {
|
|
115
160
|
const {asset} = transformContext;
|
|
@@ -120,6 +165,7 @@ import
|
|
|
120
165
|
```
|
|
121
166
|
|
|
122
167
|
**mapEntryLink**
|
|
168
|
+
|
|
123
169
|
```js
|
|
124
170
|
(transformContext, runtimeContext, defaultValue) => {
|
|
125
171
|
const {entry} = transformContext;
|
|
@@ -130,6 +176,7 @@ import
|
|
|
130
176
|
```
|
|
131
177
|
|
|
132
178
|
**mapMetaFields**
|
|
179
|
+
|
|
133
180
|
```js
|
|
134
181
|
(transformContext, runtimeContext, defaultValue) => {
|
|
135
182
|
const {entry} = transformContext;
|
|
@@ -139,7 +186,6 @@ import
|
|
|
139
186
|
}
|
|
140
187
|
```
|
|
141
188
|
|
|
142
|
-
|
|
143
189
|
#### Helper functions
|
|
144
190
|
|
|
145
191
|
###### collectValues
|
|
@@ -177,12 +223,10 @@ npx cssg fetch
|
|
|
177
223
|
|
|
178
224
|
See [`cssg-plugin-grow`](../cssg-plugin-grow)
|
|
179
225
|
|
|
180
|
-
|
|
181
226
|
### Hugo
|
|
182
227
|
|
|
183
228
|
See [`cssg-plugin-hugo`](../cssg-plugin-hugo)
|
|
184
229
|
|
|
185
|
-
|
|
186
230
|
[npm-url]: https://www.npmjs.com/package/@jungvonmatt/contentful-ssg
|
|
187
231
|
[npm-image]: https://img.shields.io/npm/v/@jungvonmatt/contentful-ssg.svg
|
|
188
232
|
[ci-url]: https://github.com/jungvonmatt/contentful-ssg/actions?workflow=Tests
|
package/dist/index.js
CHANGED
|
@@ -116,12 +116,7 @@ export const run = async (config) => {
|
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
title: 'Cleanup',
|
|
119
|
-
|
|
120
|
-
task: async (ctx) => {
|
|
121
|
-
console.log(`Cleaning ${ctx.fileManager.count} files...`);
|
|
122
|
-
await ctx.fileManager.cleanup();
|
|
123
|
-
console.log('done');
|
|
124
|
-
},
|
|
119
|
+
task: async (ctx) => ctx.fileManager.cleanup(),
|
|
125
120
|
},
|
|
126
121
|
], { renderer: CustomListrRenderer });
|
|
127
122
|
const ctx = await tasks.run();
|
package/dist/lib/config.js
CHANGED
|
@@ -14,8 +14,20 @@ const typescriptLoader = async (filePath) => {
|
|
|
14
14
|
};
|
|
15
15
|
const mergeOptions = mergeOptionsModule.bind({ ignoreUndefined: true });
|
|
16
16
|
const resolvePlugin = async (plugin, config) => {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
let pluginName;
|
|
18
|
+
let pluginOptions;
|
|
19
|
+
if (typeof plugin === 'string') {
|
|
20
|
+
pluginName = plugin;
|
|
21
|
+
pluginOptions = {};
|
|
22
|
+
}
|
|
23
|
+
else if (Array.isArray(plugin)) {
|
|
24
|
+
pluginName = plugin[0];
|
|
25
|
+
pluginOptions = plugin[1] || {};
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
pluginName = plugin.resolve;
|
|
29
|
+
pluginOptions = plugin.options || {};
|
|
30
|
+
}
|
|
19
31
|
const { rootDir, verbose } = config;
|
|
20
32
|
try {
|
|
21
33
|
const requireSource = rootDir === null ? createRequire() : createRequire(`${rootDir}/:internal:`);
|
|
@@ -12,5 +12,6 @@ export declare class FileManager {
|
|
|
12
12
|
initialize(): Promise<void>;
|
|
13
13
|
writeFile(file: string, data: any, options?: WriteFileOptions | BufferEncoding | string): Promise<void>;
|
|
14
14
|
deleteFile(file: string): Promise<void>;
|
|
15
|
-
|
|
15
|
+
removeEmptyDirectories(directory: string): Promise<void>;
|
|
16
|
+
cleanup(): Promise<boolean>;
|
|
16
17
|
}
|
package/dist/lib/file-manager.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { dirname, resolve, relative } from 'path';
|
|
1
|
+
import { dirname, resolve, relative, join } from 'path';
|
|
2
2
|
import ignore from 'ignore';
|
|
3
|
-
import { readFile, readdir } from 'fs/promises';
|
|
3
|
+
import { readFile, readdir, lstat } from 'fs/promises';
|
|
4
4
|
import { remove, outputFile } from 'fs-extra';
|
|
5
5
|
export class FileManager {
|
|
6
6
|
ignoreBase = process.cwd();
|
|
@@ -35,21 +35,30 @@ export class FileManager {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
async deleteFile(file) {
|
|
38
|
-
await remove(file);
|
|
39
38
|
if (this.files.has(resolve(file))) {
|
|
40
39
|
this.files.delete(resolve(file));
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
return remove(file);
|
|
42
|
+
}
|
|
43
|
+
async removeEmptyDirectories(directory) {
|
|
44
|
+
const fileStats = await lstat(directory);
|
|
45
|
+
if (!fileStats.isDirectory()) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let fileNames = await readdir(directory);
|
|
49
|
+
if (fileNames.length > 0) {
|
|
50
|
+
const recursiveRemovalPromises = fileNames.map(async (fileName) => this.removeEmptyDirectories(join(directory, fileName)));
|
|
51
|
+
await Promise.all(recursiveRemovalPromises);
|
|
52
|
+
fileNames = await readdir(directory);
|
|
53
|
+
}
|
|
54
|
+
if (fileNames.length === 0 && directory !== this.config.directory) {
|
|
55
|
+
await remove(directory);
|
|
48
56
|
}
|
|
49
|
-
catch { }
|
|
50
57
|
}
|
|
51
58
|
async cleanup() {
|
|
52
59
|
const promises = [...this.ignoredFiles].map(async (file) => this.deleteFile(file));
|
|
53
|
-
|
|
60
|
+
await Promise.allSettled(promises);
|
|
61
|
+
await this.removeEmptyDirectories(this.config.directory);
|
|
62
|
+
return true;
|
|
54
63
|
}
|
|
55
64
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export declare type Config = Partial<ContentfulConfig> & Hooks & {
|
|
|
47
47
|
rootDir?: string;
|
|
48
48
|
directory: string;
|
|
49
49
|
verbose?: boolean;
|
|
50
|
-
plugins?: Array<PluginInfo | string>;
|
|
50
|
+
plugins?: Array<[string, KeyValueMap] | PluginInfo | string>;
|
|
51
51
|
resolvedPlugins?: Hooks[];
|
|
52
52
|
preset?: string;
|
|
53
53
|
richTextRenderer?: RichTextConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungvonmatt/contentful-ssg",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -138,5 +138,5 @@
|
|
|
138
138
|
"module": "es2020"
|
|
139
139
|
}
|
|
140
140
|
},
|
|
141
|
-
"gitHead": "
|
|
141
|
+
"gitHead": "c0d7b4e36ede445f92bcc059e379e8ac9584f527"
|
|
142
142
|
}
|
package/src/index.ts
CHANGED
|
@@ -143,13 +143,7 @@ export const run = async (config: Config): Promise<void> => {
|
|
|
143
143
|
|
|
144
144
|
{
|
|
145
145
|
title: 'Cleanup',
|
|
146
|
-
|
|
147
|
-
task: async (ctx) => {
|
|
148
|
-
console.log(`Cleaning ${ctx.fileManager.count} files...`);
|
|
149
|
-
await ctx.fileManager.cleanup();
|
|
150
|
-
|
|
151
|
-
console.log('done');
|
|
152
|
-
},
|
|
146
|
+
task: async (ctx) => ctx.fileManager.cleanup(),
|
|
153
147
|
},
|
|
154
148
|
],
|
|
155
149
|
{ renderer: CustomListrRenderer }
|
package/src/lib/config.ts
CHANGED
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
ContentfulConfig,
|
|
11
11
|
ContentfulRcConfig,
|
|
12
12
|
Hooks,
|
|
13
|
+
KeyValueMap,
|
|
13
14
|
PluginInfo,
|
|
14
15
|
PluginModule,
|
|
15
16
|
} from '../types.js';
|
|
@@ -29,11 +30,22 @@ const typescriptLoader: Loader = async (filePath: string): Promise<any> => {
|
|
|
29
30
|
const mergeOptions = mergeOptionsModule.bind({ ignoreUndefined: true });
|
|
30
31
|
|
|
31
32
|
const resolvePlugin = async (
|
|
32
|
-
plugin: string | PluginInfo,
|
|
33
|
+
plugin: string | [string, KeyValueMap] | PluginInfo,
|
|
33
34
|
config: Partial<Config>
|
|
34
35
|
): Promise<Hooks> => {
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
let pluginName: string;
|
|
37
|
+
let pluginOptions: KeyValueMap;
|
|
38
|
+
if (typeof plugin === 'string') {
|
|
39
|
+
pluginName = plugin;
|
|
40
|
+
pluginOptions = {};
|
|
41
|
+
} else if (Array.isArray(plugin)) {
|
|
42
|
+
pluginName = plugin[0];
|
|
43
|
+
pluginOptions = plugin[1] || {};
|
|
44
|
+
} else {
|
|
45
|
+
pluginName = plugin.resolve;
|
|
46
|
+
pluginOptions = plugin.options || {};
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
const { rootDir, verbose } = config;
|
|
38
50
|
|
|
39
51
|
try {
|
|
@@ -11,8 +11,9 @@ jest.mock('fs-extra', () => ({
|
|
|
11
11
|
remove: jest.fn(),
|
|
12
12
|
}));
|
|
13
13
|
jest.mock('fs/promises', () => ({
|
|
14
|
+
lstat: jest.fn().mockResolvedValue({isDirectory: jest.fn().mockReturnValue(false).mockResolvedValueOnce(true).mockResolvedValueOnce(true)}),
|
|
14
15
|
readFile: jest.fn().mockResolvedValue(''),
|
|
15
|
-
readdir: jest.fn().mockResolvedValue([]).mockResolvedValueOnce(['/test
|
|
16
|
+
readdir: jest.fn().mockResolvedValue([]).mockResolvedValueOnce(['/test']),
|
|
16
17
|
}));
|
|
17
18
|
|
|
18
19
|
describe('FileManager', () => {
|
|
@@ -60,14 +61,13 @@ describe('FileManager', () => {
|
|
|
60
61
|
.mockReturnValueOnce(true)
|
|
61
62
|
.mockReturnValueOnce(true)
|
|
62
63
|
.mockReturnValue(false);
|
|
63
|
-
const result = await fileManager.cleanup();
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
expect(result
|
|
65
|
+
const result = await fileManager.cleanup();
|
|
66
|
+
expect(result).toEqual(true);
|
|
67
67
|
|
|
68
|
-
expect(remove).toHaveBeenCalledTimes(3);
|
|
69
68
|
expect(remove).toHaveBeenNthCalledWith(1, '/test/a.md');
|
|
70
69
|
expect(remove).toHaveBeenNthCalledWith(2, '/test/b.md');
|
|
71
|
-
expect(remove).toHaveBeenNthCalledWith(3, '/test');
|
|
70
|
+
expect(remove).toHaveBeenNthCalledWith(3, '/testbase/test');
|
|
71
|
+
expect(remove).toHaveBeenCalledTimes(3);
|
|
72
72
|
});
|
|
73
73
|
});
|
package/src/lib/file-manager.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { WriteFileOptions } from 'fs-extra';
|
|
2
2
|
import type { Config, Ignore } from '../types';
|
|
3
|
-
import { dirname, resolve, relative } from 'path';
|
|
3
|
+
import { dirname, resolve, relative, join } from 'path';
|
|
4
4
|
import ignore from 'ignore';
|
|
5
|
-
import { readFile, readdir } from 'fs/promises';
|
|
5
|
+
import { readFile, readdir, lstat } from 'fs/promises';
|
|
6
6
|
import { remove, outputFile } from 'fs-extra';
|
|
7
7
|
|
|
8
8
|
export class FileManager {
|
|
@@ -56,24 +56,51 @@ export class FileManager {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
async deleteFile(file: string) {
|
|
59
|
-
await remove(file);
|
|
60
|
-
|
|
61
59
|
if (this.files.has(resolve(file))) {
|
|
62
60
|
this.files.delete(resolve(file));
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
return remove(file);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Recursively removes empty directories from the given directory.
|
|
68
|
+
*
|
|
69
|
+
* If the directory itself is empty, it is also removed.
|
|
70
|
+
*
|
|
71
|
+
* Code taken from: https://gist.github.com/jakub-g/5903dc7e4028133704a4
|
|
72
|
+
*
|
|
73
|
+
* @param {string} directory Path to the directory to clean up
|
|
74
|
+
*/
|
|
75
|
+
async removeEmptyDirectories(directory: string) {
|
|
76
|
+
// Lstat does not follow symlinks (in contrast to stat)
|
|
77
|
+
const fileStats = await lstat(directory);
|
|
78
|
+
if (!fileStats.isDirectory()) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let fileNames = await readdir(directory);
|
|
83
|
+
if (fileNames.length > 0) {
|
|
84
|
+
const recursiveRemovalPromises = fileNames.map(async (fileName) =>
|
|
85
|
+
this.removeEmptyDirectories(join(directory, fileName))
|
|
86
|
+
);
|
|
87
|
+
await Promise.all(recursiveRemovalPromises);
|
|
88
|
+
|
|
89
|
+
// Re-evaluate fileNames; after deleting subdirectory
|
|
90
|
+
// we may have parent directory empty now
|
|
91
|
+
fileNames = await readdir(directory);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (fileNames.length === 0 && directory !== this.config.directory) {
|
|
95
|
+
await remove(directory);
|
|
96
|
+
}
|
|
72
97
|
}
|
|
73
98
|
|
|
74
99
|
async cleanup() {
|
|
75
100
|
const promises = [...this.ignoredFiles].map(async (file) => this.deleteFile(file));
|
|
76
101
|
|
|
77
|
-
|
|
102
|
+
await Promise.allSettled(promises);
|
|
103
|
+
await this.removeEmptyDirectories(this.config.directory);
|
|
104
|
+
return true;
|
|
78
105
|
}
|
|
79
106
|
}
|
package/src/types.ts
CHANGED
|
@@ -81,7 +81,7 @@ export type Config = Partial<ContentfulConfig> &
|
|
|
81
81
|
rootDir?: string;
|
|
82
82
|
directory: string;
|
|
83
83
|
verbose?: boolean;
|
|
84
|
-
plugins?: Array<PluginInfo | string>;
|
|
84
|
+
plugins?: Array<[string, KeyValueMap] | PluginInfo | string>;
|
|
85
85
|
resolvedPlugins?: Hooks[];
|
|
86
86
|
preset?: string;
|
|
87
87
|
richTextRenderer?: RichTextConfig;
|