@jungvonmatt/cssg-plugin-hugo 1.1.0 → 1.4.0
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/CHANGELOG.md +38 -0
- package/index.js +165 -9
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,44 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.4.0](https://github.com/jungvonmatt/contentful-ssg/compare/v1.3.2...v1.4.0) (2022-01-19)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @jungvonmatt/cssg-plugin-hugo
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [1.3.2](https://github.com/jungvonmatt/contentful-ssg/compare/v1.3.1...v1.3.2) (2022-01-14)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @jungvonmatt/cssg-plugin-hugo
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# [1.3.0](https://github.com/jungvonmatt/contentful-ssg/compare/v1.2.0...v1.3.0) (2022-01-10)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* 🎸 Consider menu reference in page node when building menu ([42499a4](https://github.com/jungvonmatt/contentful-ssg/commit/42499a4efb2f25275d8ea4fb74f72461aa441ba0))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# [1.2.0](https://github.com/jungvonmatt/contentful-ssg/compare/v1.1.1...v1.2.0) (2021-12-21)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Features
|
|
37
|
+
|
|
38
|
+
* 🎸 Generates hugo's menu.toml ([27e95a3](https://github.com/jungvonmatt/contentful-ssg/commit/27e95a33452b1aa5158ee89070889383cee4b6c5))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
6
44
|
# [1.1.0](https://github.com/jungvonmatt/contentful-ssg/compare/v1.0.6...v1.1.0) (2021-12-02)
|
|
7
45
|
|
|
8
46
|
|
package/index.js
CHANGED
|
@@ -20,9 +20,16 @@ const defaultOptions = {
|
|
|
20
20
|
translationStrategy: STRATEGY_DIRECTORY,
|
|
21
21
|
typeIdI18n: 'd-i18n',
|
|
22
22
|
languageConfig: true,
|
|
23
|
+
menuDepth: 0,
|
|
24
|
+
autoSubMenu: false,
|
|
25
|
+
typeIdMenu: 'c-menu',
|
|
23
26
|
fieldIdHome: 'home',
|
|
24
27
|
fieldIdSlug: 'slug',
|
|
25
28
|
fieldIdParent: 'parent_page',
|
|
29
|
+
fieldIdMenu: 'menu',
|
|
30
|
+
fieldIdMenuEntries: 'entries',
|
|
31
|
+
fieldIdMenuHide: 'hide_in_menu',
|
|
32
|
+
fieldIdMenuPos: 'menu_pos',
|
|
26
33
|
typeConfig: {
|
|
27
34
|
[TYPE_CONTENT]: ['page'],
|
|
28
35
|
},
|
|
@@ -61,6 +68,136 @@ export default (args) => {
|
|
|
61
68
|
return type;
|
|
62
69
|
};
|
|
63
70
|
|
|
71
|
+
const buildMenu = async (transformContext, depth = 0) => {
|
|
72
|
+
const { entry, entryMap } = transformContext;
|
|
73
|
+
const entries = entry.fields?.[options.fieldIdMenuEntries] ?? [];
|
|
74
|
+
const nodes = entries
|
|
75
|
+
.filter((node) => node?.sys?.id && node?.sys?.contentType?.sys?.id)
|
|
76
|
+
.map((node, index) => ({
|
|
77
|
+
identifier: node.sys.id,
|
|
78
|
+
weight: (index + 1) * -10,
|
|
79
|
+
params: {
|
|
80
|
+
id: node.sys.id,
|
|
81
|
+
// eslint-disable-next-line camelcase
|
|
82
|
+
content_type: node.sys.contentType.sys.id,
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
// Resolve page entry
|
|
87
|
+
const resolvePageEntry = async (entry) => {
|
|
88
|
+
const id = entry?.sys?.id ?? 0;
|
|
89
|
+
const node = entryMap.get(id);
|
|
90
|
+
const contentType = node?.sys?.contentType?.sys?.id ?? '';
|
|
91
|
+
const pageId = node?.fields?.link_to_entry?.sys?.id;
|
|
92
|
+
if (contentType === 'page') {
|
|
93
|
+
return node;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (pageId) {
|
|
97
|
+
return entryMap.get(pageId);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (typeof options.resolvePage === 'function') {
|
|
101
|
+
return options.resolvePage(entry, entryMap);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const getChildnodesManual = async (entry, depth, ids = []) => {
|
|
106
|
+
const id = entry?.sys?.id ?? 0;
|
|
107
|
+
const page = await resolvePageEntry(entry);
|
|
108
|
+
const contentType = page?.sys?.contentType?.sys?.id ?? '';
|
|
109
|
+
const menuId = page?.fields?.[options.fieldIdMenu]?.sys?.id;
|
|
110
|
+
|
|
111
|
+
if (
|
|
112
|
+
!id ||
|
|
113
|
+
!contentType ||
|
|
114
|
+
!menuId ||
|
|
115
|
+
!entryMap.has(menuId) ||
|
|
116
|
+
ids.includes(id) ||
|
|
117
|
+
depth <= 0
|
|
118
|
+
) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const menu = entryMap.get(menuId);
|
|
123
|
+
const subentries = menu?.fields?.[options.fieldIdMenuEntries] ?? [];
|
|
124
|
+
|
|
125
|
+
const collected = await Promise.all(
|
|
126
|
+
subentries.flatMap((node) => getChildnodesManual(node, depth - 1, [...ids, id]))
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
return [
|
|
130
|
+
...subentries
|
|
131
|
+
.filter((node) => node?.sys?.id && node?.sys?.contentType?.sys?.id)
|
|
132
|
+
.map((node, index) => ({
|
|
133
|
+
identifier: node.sys.id,
|
|
134
|
+
parent: id,
|
|
135
|
+
weight: (index + 1) * -10,
|
|
136
|
+
params: {
|
|
137
|
+
id: node.sys.id,
|
|
138
|
+
// eslint-disable-next-line camelcase
|
|
139
|
+
content_type: node.sys.contentType.sys.id,
|
|
140
|
+
},
|
|
141
|
+
})),
|
|
142
|
+
...collected,
|
|
143
|
+
];
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const getChildnodesRecursive = async (entry, depth) => {
|
|
147
|
+
const id = entry?.sys?.id ?? 0;
|
|
148
|
+
const page = await resolvePageEntry(id);
|
|
149
|
+
const contentType = page?.sys?.contentType?.sys?.id ?? '';
|
|
150
|
+
|
|
151
|
+
if (!id || !contentType || depth <= 0) {
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const childnodes = [...entryMap.values()].filter(
|
|
156
|
+
(entry) => (entry?.fields?.[options.fieldIdParent]?.sys?.id ?? '') === id
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Filter childnodes based on hide_in_menu field
|
|
160
|
+
const filtered = childnodes.filter(
|
|
161
|
+
(entry) => !(entry?.fields?.[options.fieldIdMenuHide] ?? false)
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Sort based on menuPos field
|
|
165
|
+
const sorted = [...filtered].sort(
|
|
166
|
+
(a, b) =>
|
|
167
|
+
(a?.fields?.[options.fieldIdMenuPos] ?? Number.MAX_SAFE_INTEGER) -
|
|
168
|
+
(b?.fields?.[options.fieldIdMenuPos] ?? Number.MAX_SAFE_INTEGER)
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return Array.from(
|
|
172
|
+
await Promise.allSettled([
|
|
173
|
+
...sorted
|
|
174
|
+
.filter((node) => node?.sys?.id && node?.sys?.contentType?.sys?.id)
|
|
175
|
+
.map((node, index) => ({
|
|
176
|
+
identifier: node.sys.id,
|
|
177
|
+
parent: id,
|
|
178
|
+
weight: (index + 1) * -10,
|
|
179
|
+
params: {
|
|
180
|
+
id: node.sys.id,
|
|
181
|
+
// eslint-disable-next-line camelcase
|
|
182
|
+
content_type: node.sys.contentType.sys.id,
|
|
183
|
+
},
|
|
184
|
+
})),
|
|
185
|
+
...sorted.flatMap((node) => getChildnodesRecursive(node, depth - 1)),
|
|
186
|
+
])
|
|
187
|
+
)
|
|
188
|
+
.map((a) => a.value)
|
|
189
|
+
.filter((v) => v);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// When autoSubMenu parameter is set, we collect child pages automatically
|
|
193
|
+
// Otherwise we look for dedicated menu entries in page nodes
|
|
194
|
+
const childentries = options.autoSubMenu
|
|
195
|
+
? await Promise.all(entries.flatMap((node) => getChildnodesRecursive(node, depth)))
|
|
196
|
+
: await Promise.all(entries.flatMap((node) => getChildnodesManual(node, depth)));
|
|
197
|
+
|
|
198
|
+
return [...nodes, ...childentries].flat(Infinity).filter((v) => v);
|
|
199
|
+
};
|
|
200
|
+
|
|
64
201
|
return {
|
|
65
202
|
config(prev) {
|
|
66
203
|
const { managedDirectories } = prev || {};
|
|
@@ -76,10 +213,10 @@ export default (args) => {
|
|
|
76
213
|
// Initialize getSettings
|
|
77
214
|
const getSettings = getSettingsHelper(runtimeContext);
|
|
78
215
|
helper.getSettings = getSettings;
|
|
79
|
-
// Write config
|
|
216
|
+
// Write config yaml according to locale settings in contentful
|
|
80
217
|
if (options.languageConfig) {
|
|
81
218
|
const rootDir = runtimeContext?.config?.rootDir ?? process.cwd();
|
|
82
|
-
const dst = path.join(rootDir, 'config/_default/languages.
|
|
219
|
+
const dst = path.join(rootDir, 'config/_default/languages.yaml');
|
|
83
220
|
const languageConfig = Object.fromEntries(
|
|
84
221
|
locales.map((locale) => {
|
|
85
222
|
const { code, name: languageName } = locale;
|
|
@@ -105,7 +242,7 @@ export default (args) => {
|
|
|
105
242
|
];
|
|
106
243
|
})
|
|
107
244
|
);
|
|
108
|
-
await outputFile(dst, converter.
|
|
245
|
+
await outputFile(dst, converter.yaml.stringify(languageConfig));
|
|
109
246
|
}
|
|
110
247
|
|
|
111
248
|
// Find section pages and add them to the runtimeconfig
|
|
@@ -125,8 +262,9 @@ export default (args) => {
|
|
|
125
262
|
);
|
|
126
263
|
|
|
127
264
|
const i18n = Object.fromEntries(locales.map((locale) => [locale.code, {}]));
|
|
265
|
+
const menus = Object.fromEntries(locales.map((locale) => [locale.code, {}]));
|
|
128
266
|
|
|
129
|
-
return { ...runtimeContext, helper, localized: enhancedLocalized, i18n };
|
|
267
|
+
return { ...runtimeContext, helper, localized: enhancedLocalized, i18n, menus };
|
|
130
268
|
},
|
|
131
269
|
|
|
132
270
|
/**
|
|
@@ -231,7 +369,7 @@ export default (args) => {
|
|
|
231
369
|
},
|
|
232
370
|
|
|
233
371
|
async transform(transformContext, runtimeContext) {
|
|
234
|
-
const { content, id, contentTypeId, locale } = transformContext;
|
|
372
|
+
const { content, id, contentTypeId, locale, entry } = transformContext;
|
|
235
373
|
|
|
236
374
|
const type = getEntryType(transformContext);
|
|
237
375
|
|
|
@@ -247,6 +385,15 @@ export default (args) => {
|
|
|
247
385
|
return undefined;
|
|
248
386
|
}
|
|
249
387
|
|
|
388
|
+
// Automatically build hugo menus
|
|
389
|
+
// See https://gohugo.io/content-management/menus/
|
|
390
|
+
if (options.typeIdMenu && contentTypeId === options.typeIdMenu) {
|
|
391
|
+
const { name = 'main' } = entry.fields;
|
|
392
|
+
const menu = await buildMenu(transformContext, options.menuDepth);
|
|
393
|
+
|
|
394
|
+
runtimeContext.menus[locale.code][name] = menu;
|
|
395
|
+
}
|
|
396
|
+
|
|
250
397
|
if (type === TYPE_CONTENT) {
|
|
251
398
|
return {
|
|
252
399
|
...snakeCaseKeys({
|
|
@@ -261,17 +408,26 @@ export default (args) => {
|
|
|
261
408
|
|
|
262
409
|
async after(runtimeContext) {
|
|
263
410
|
const contentDir = runtimeContext.config.directory;
|
|
264
|
-
const {
|
|
411
|
+
const { yaml } = runtimeContext.converter;
|
|
265
412
|
const i18n = runtimeContext?.i18n ?? {};
|
|
266
413
|
|
|
267
414
|
await Promise.all(
|
|
268
415
|
Object.entries(i18n).map(async ([localeCode, translations]) => {
|
|
269
|
-
const dictionaryPath = path.join(contentDir, `../i18n/${localeCode}.
|
|
416
|
+
const dictionaryPath = path.join(contentDir, `../i18n/${localeCode}.yaml`);
|
|
270
417
|
const oldContent = existsSync(dictionaryPath)
|
|
271
|
-
?
|
|
418
|
+
? yaml.parse(await readFile(dictionaryPath, 'utf8'))
|
|
272
419
|
: {};
|
|
273
420
|
|
|
274
|
-
return outputFile(dictionaryPath,
|
|
421
|
+
return outputFile(dictionaryPath, yaml.stringify({ ...oldContent, ...translations }));
|
|
422
|
+
})
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
const menus = runtimeContext?.menus ?? {};
|
|
426
|
+
await Promise.all(
|
|
427
|
+
Object.entries(menus).map(([localeCode, menuData]) => {
|
|
428
|
+
const file = `config/_default/menus.${localeCode}.yaml`;
|
|
429
|
+
const data = yaml.stringify(menuData);
|
|
430
|
+
return outputFile(file, data);
|
|
275
431
|
})
|
|
276
432
|
);
|
|
277
433
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungvonmatt/cssg-plugin-hugo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "./index.d.ts",
|
|
@@ -20,16 +20,16 @@
|
|
|
20
20
|
},
|
|
21
21
|
"keywords": [],
|
|
22
22
|
"author": "Ben Zörb",
|
|
23
|
-
"license": "
|
|
23
|
+
"license": "MIT",
|
|
24
24
|
"bugs": {
|
|
25
25
|
"url": "https://github.com/jungvonmatt/contentful-ssg/issues"
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://github.com/jungvonmatt/contentful-ssg#readme",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@jungvonmatt/contentful-ssg": "^1.
|
|
29
|
+
"@jungvonmatt/contentful-ssg": "^1.4.0",
|
|
30
30
|
"fs-extra": "^10.0.0",
|
|
31
31
|
"merge-options": "^3.0.4",
|
|
32
32
|
"micromatch": "^4.0.4"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "0d323f9884ae8fa48049e25bcd127954ee7988b8"
|
|
35
35
|
}
|