@riebeckite/plugin-folder-pages 0.0.16 → 0.0.18
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/dist/index.js +141 -81
- package/dist/src/types.d.ts +1 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -13,21 +13,22 @@ function collapseFolderEntryLocations(locations) {
|
|
|
13
13
|
owners.set(location.permalink, location.slug);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
const
|
|
17
|
-
for (const slug of locations
|
|
18
|
-
const basename =
|
|
16
|
+
const byFolderLanguage = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const [slug, location] of locations) {
|
|
18
|
+
const basename = entryBaseSegment(slug, location.language);
|
|
19
19
|
if (!isEntryBasename(basename)) continue;
|
|
20
|
-
const
|
|
21
|
-
const slugs =
|
|
20
|
+
const key = languageKey(parentFolder(slug), location.language);
|
|
21
|
+
const slugs = byFolderLanguage.get(key);
|
|
22
22
|
if (slugs) slugs.push(slug);
|
|
23
|
-
else
|
|
23
|
+
else byFolderLanguage.set(key, [slug]);
|
|
24
24
|
}
|
|
25
|
-
for (const slugs of
|
|
25
|
+
for (const slugs of byFolderLanguage.values()) {
|
|
26
26
|
if (slugs.length !== 1) continue;
|
|
27
27
|
const slug = slugs[0];
|
|
28
|
+
if (slug === void 0) continue;
|
|
28
29
|
const location = locations.get(slug);
|
|
29
30
|
if (!location) continue;
|
|
30
|
-
const basename =
|
|
31
|
+
const basename = entryBaseSegment(slug, location.language);
|
|
31
32
|
if (!location.permalink.endsWith(`/${basename}`)) continue;
|
|
32
33
|
const target = location.permalink.slice(
|
|
33
34
|
0,
|
|
@@ -46,83 +47,111 @@ function collapseFolderEntryLocations(locations) {
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
function buildFolderPages(manifest) {
|
|
49
|
-
const pagesByFolder = /* @__PURE__ */ new Map();
|
|
50
|
-
const subfoldersOf = /* @__PURE__ */ new Map();
|
|
51
|
-
const allFolders = /* @__PURE__ */ new Set();
|
|
52
50
|
const routableBySlug = /* @__PURE__ */ new Map();
|
|
53
51
|
const routablePermalinks = /* @__PURE__ */ new Set();
|
|
54
52
|
for (const entry of manifest.publicEntries) {
|
|
55
53
|
routableBySlug.set(entry.slug, entry);
|
|
56
54
|
routablePermalinks.add(stripTrailingSlash(entry.permalink));
|
|
57
55
|
}
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
const allFolders = /* @__PURE__ */ new Set();
|
|
57
|
+
const folderLanguages = /* @__PURE__ */ new Map();
|
|
58
|
+
const pagesByFolderLanguage = /* @__PURE__ */ new Map();
|
|
59
|
+
const subfolders = /* @__PURE__ */ new Map();
|
|
60
|
+
const addLanguage = (folder, language) => {
|
|
61
|
+
const set = folderLanguages.get(folder);
|
|
62
|
+
if (set) set.add(language);
|
|
63
|
+
else folderLanguages.set(folder, /* @__PURE__ */ new Set([language]));
|
|
64
64
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (!isEntryBasename(basename)) {
|
|
71
|
-
const pages2 = pagesByFolder.get(parent);
|
|
72
|
-
if (pages2) pages2.push(entry);
|
|
73
|
-
else pagesByFolder.set(parent, [entry]);
|
|
65
|
+
const addPage = (folder, language, entry) => {
|
|
66
|
+
let byLanguage = pagesByFolderLanguage.get(folder);
|
|
67
|
+
if (!byLanguage) {
|
|
68
|
+
byLanguage = /* @__PURE__ */ new Map();
|
|
69
|
+
pagesByFolderLanguage.set(folder, byLanguage);
|
|
74
70
|
}
|
|
75
|
-
|
|
71
|
+
const entries = byLanguage.get(language);
|
|
72
|
+
if (entries) entries.push(entry);
|
|
73
|
+
else byLanguage.set(language, [entry]);
|
|
74
|
+
};
|
|
75
|
+
const addSubfolder = (parent, language, child) => {
|
|
76
|
+
let byLanguage = subfolders.get(parent);
|
|
77
|
+
if (!byLanguage) {
|
|
78
|
+
byLanguage = /* @__PURE__ */ new Map();
|
|
79
|
+
subfolders.set(parent, byLanguage);
|
|
80
|
+
}
|
|
81
|
+
const set = byLanguage.get(language);
|
|
82
|
+
if (set) set.add(child);
|
|
83
|
+
else byLanguage.set(language, /* @__PURE__ */ new Set([child]));
|
|
84
|
+
};
|
|
85
|
+
for (const entry of manifest.discoverableEntries) {
|
|
86
|
+
const language = entry.publicLocation.language;
|
|
87
|
+
const folder = parentFolder(entry.slug);
|
|
88
|
+
allFolders.add(folder);
|
|
89
|
+
let child = folder;
|
|
76
90
|
while (child !== "") {
|
|
91
|
+
addLanguage(child, language);
|
|
77
92
|
const grandparent = parentFolder(child);
|
|
78
|
-
addSubfolder(grandparent, child);
|
|
93
|
+
addSubfolder(grandparent, language, child);
|
|
79
94
|
child = grandparent;
|
|
80
95
|
}
|
|
96
|
+
if (isEntryBasename(entryBaseSegment(entry.slug, language))) continue;
|
|
97
|
+
if (folder !== "") addPage(folder, language, entry);
|
|
81
98
|
}
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
99
|
+
const owners = /* @__PURE__ */ new Map();
|
|
100
|
+
for (const entry of manifest.publicEntries) {
|
|
101
|
+
const language = entry.publicLocation.language;
|
|
102
|
+
const basename = entryBaseSegment(entry.slug, language);
|
|
103
|
+
if (!isEntryBasename(basename)) continue;
|
|
104
|
+
const folder = parentFolder(entry.slug);
|
|
105
|
+
if (folder === "") continue;
|
|
106
|
+
const key = languageKey(folder, language);
|
|
107
|
+
const existing = owners.get(key);
|
|
108
|
+
if (!existing || basename === "README") owners.set(key, entry);
|
|
109
|
+
}
|
|
110
|
+
const hasOwner = (folder, language) => owners.has(languageKey(folder, language));
|
|
111
|
+
const hasRoutablePage = (folder, language) => {
|
|
112
|
+
const entry = routableBySlug.get(folder);
|
|
113
|
+
return entry !== void 0 && entry.publicLocation.language === language;
|
|
114
|
+
};
|
|
115
|
+
const generatedPath = (folder, language) => resolveGeneratedFolderLocation(manifest, folder, language);
|
|
116
|
+
const subfoldersFor = (folder, language) => subfolders.get(folder)?.get(language) ?? /* @__PURE__ */ new Set();
|
|
117
|
+
const sortedPages = (folder, language) => {
|
|
118
|
+
const subs = subfoldersFor(folder, language);
|
|
119
|
+
const pages2 = (pagesByFolderLanguage.get(folder)?.get(language) ?? []).filter((entry) => !subs.has(entry.slug));
|
|
89
120
|
pages2.sort(compareEntries);
|
|
90
121
|
return pages2;
|
|
91
122
|
};
|
|
92
123
|
const navigableCache = /* @__PURE__ */ new Map();
|
|
93
|
-
const isNavigable = (folder) => {
|
|
94
|
-
const
|
|
124
|
+
const isNavigable = (folder, language) => {
|
|
125
|
+
const key = languageKey(folder, language);
|
|
126
|
+
const cached = navigableCache.get(key);
|
|
95
127
|
if (cached !== void 0) return cached;
|
|
96
|
-
navigableCache.set(
|
|
97
|
-
let result = sortedPages(folder).length > 0 ||
|
|
128
|
+
navigableCache.set(key, false);
|
|
129
|
+
let result = sortedPages(folder, language).length > 0 || hasOwner(folder, language) || hasRoutablePage(folder, language);
|
|
98
130
|
if (!result) {
|
|
99
|
-
for (const sub of
|
|
100
|
-
if (isListed(sub)) {
|
|
131
|
+
for (const sub of subfoldersFor(folder, language)) {
|
|
132
|
+
if (isListed(sub, language)) {
|
|
101
133
|
result = true;
|
|
102
134
|
break;
|
|
103
135
|
}
|
|
104
136
|
}
|
|
105
137
|
}
|
|
106
|
-
navigableCache.set(
|
|
138
|
+
navigableCache.set(key, result);
|
|
107
139
|
return result;
|
|
108
140
|
};
|
|
109
|
-
const isListed = (folder) =>
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
if (owner) return { title: owner.title, permalink: owner.permalink };
|
|
115
|
-
}
|
|
116
|
-
const page = routableBySlug.get(folder);
|
|
141
|
+
const isListed = (folder, language) => hasOwner(folder, language) || hasRoutablePage(folder, language) || isNavigable(folder, language) && generatedPath(folder, language) !== null;
|
|
142
|
+
const folderLink = (folder, language) => {
|
|
143
|
+
const owner = owners.get(languageKey(folder, language));
|
|
144
|
+
if (owner) return { title: owner.title, permalink: owner.permalink };
|
|
145
|
+
const page = hasRoutablePage(folder, language) ? routableBySlug.get(folder) : void 0;
|
|
117
146
|
if (page) return { title: page.title, permalink: page.permalink };
|
|
118
|
-
const pathname = generatedPath(folder);
|
|
147
|
+
const pathname = generatedPath(folder, language);
|
|
119
148
|
if (!pathname) return null;
|
|
120
149
|
return { title: lastSegment(folder), permalink: pathname };
|
|
121
150
|
};
|
|
122
|
-
const sortedSubfolders = (folder) => {
|
|
123
|
-
const subs = [...
|
|
124
|
-
if (!isListed(sub)) return [];
|
|
125
|
-
const link = folderLink(sub);
|
|
151
|
+
const sortedSubfolders = (folder, language) => {
|
|
152
|
+
const subs = [...subfoldersFor(folder, language)].flatMap((sub) => {
|
|
153
|
+
if (!isListed(sub, language)) return [];
|
|
154
|
+
const link = folderLink(sub, language);
|
|
126
155
|
return link ? [{ folder: sub, link }] : [];
|
|
127
156
|
});
|
|
128
157
|
subs.sort((a, b) => compareLinks(a.link, b.link));
|
|
@@ -133,36 +162,59 @@ function buildFolderPages(manifest) {
|
|
|
133
162
|
const pages = [];
|
|
134
163
|
const takenPaths = /* @__PURE__ */ new Set();
|
|
135
164
|
for (const folder of folders) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
type: "folder",
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
for (const language of sortedLanguages(folderLanguages.get(folder))) {
|
|
166
|
+
if (!isNavigable(folder, language)) continue;
|
|
167
|
+
if (hasOwner(folder, language)) continue;
|
|
168
|
+
if (hasRoutablePage(folder, language)) continue;
|
|
169
|
+
const pathname = generatedPath(folder, language);
|
|
170
|
+
if (!pathname) continue;
|
|
171
|
+
if (pathname === "/") continue;
|
|
172
|
+
if (routablePermalinks.has(stripTrailingSlash(pathname))) continue;
|
|
173
|
+
if (takenPaths.has(pathname)) continue;
|
|
174
|
+
takenPaths.add(pathname);
|
|
175
|
+
const folderLinks = sortedSubfolders(folder, language);
|
|
176
|
+
pages.push({
|
|
177
|
+
folder,
|
|
178
|
+
pathname,
|
|
179
|
+
language,
|
|
180
|
+
title: lastSegment(folder),
|
|
181
|
+
pages: sortedPages(folder, language).map(toLink),
|
|
182
|
+
folders: folderLinks.map((sub) => sub.link),
|
|
183
|
+
dependencies: [
|
|
184
|
+
{ type: "folder", folder },
|
|
185
|
+
...folderLinks.map((sub) => ({
|
|
186
|
+
type: "folder",
|
|
187
|
+
folder: sub.folder
|
|
188
|
+
}))
|
|
189
|
+
]
|
|
190
|
+
});
|
|
191
|
+
}
|
|
160
192
|
}
|
|
161
193
|
pages.sort((a, b) => compareStrings(a.pathname, b.pathname));
|
|
162
194
|
const byPath = /* @__PURE__ */ new Map();
|
|
163
195
|
for (const page of pages) byPath.set(page.pathname, page);
|
|
164
196
|
return { paths: pages.map((page) => page.pathname), byPath };
|
|
165
197
|
}
|
|
198
|
+
function languageKey(folder, language) {
|
|
199
|
+
return `${folder}\0${language ?? ""}`;
|
|
200
|
+
}
|
|
201
|
+
function entryBaseSegment(slug, language) {
|
|
202
|
+
const segment = lastSegment(slug);
|
|
203
|
+
if (!language) return segment;
|
|
204
|
+
return segment.replace(
|
|
205
|
+
new RegExp(`[._-]${escapeRegExp(language)}$`, "i"),
|
|
206
|
+
""
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
function sortedLanguages(languages) {
|
|
210
|
+
return [...languages ?? []].sort((a, b) => {
|
|
211
|
+
const left = a ?? "";
|
|
212
|
+
const right = b ?? "";
|
|
213
|
+
if (left < right) return -1;
|
|
214
|
+
if (left > right) return 1;
|
|
215
|
+
return 0;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
166
218
|
function isEntryBasename(basename) {
|
|
167
219
|
return ENTRY_BASENAMES.includes(basename);
|
|
168
220
|
}
|
|
@@ -181,6 +233,9 @@ function stripTrailingSlash(url) {
|
|
|
181
233
|
if (url.length > 1 && url.endsWith("/")) return url.slice(0, -1);
|
|
182
234
|
return url;
|
|
183
235
|
}
|
|
236
|
+
function escapeRegExp(value) {
|
|
237
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
238
|
+
}
|
|
184
239
|
function compareEntries(a, b) {
|
|
185
240
|
return compareStrings(a.permalink, b.permalink) || compareStrings(a.title, b.title) || compareStrings(a.slug, b.slug);
|
|
186
241
|
}
|
|
@@ -273,7 +328,11 @@ function folderPages(options = {}) {
|
|
|
273
328
|
},
|
|
274
329
|
onManifestCreated: ({ manifest }) => {
|
|
275
330
|
for (const page of modelFor(manifest).byPath.values()) {
|
|
276
|
-
manifest.folderLocations.set(page.
|
|
331
|
+
manifest.folderLocations.set(page.pathname, {
|
|
332
|
+
pathname: page.pathname,
|
|
333
|
+
folder: page.folder,
|
|
334
|
+
...page.language === void 0 ? {} : { language: page.language }
|
|
335
|
+
});
|
|
277
336
|
}
|
|
278
337
|
},
|
|
279
338
|
pageTypes: [
|
|
@@ -292,7 +351,8 @@ function folderPages(options = {}) {
|
|
|
292
351
|
type: "folder-page",
|
|
293
352
|
pathname: page.pathname,
|
|
294
353
|
title: rendered.title,
|
|
295
|
-
body: rendered.html
|
|
354
|
+
body: rendered.html,
|
|
355
|
+
language: page.language
|
|
296
356
|
};
|
|
297
357
|
}
|
|
298
358
|
}
|
package/dist/src/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-folder-pages",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@riebeckite/core": "0.0.
|
|
17
|
+
"@riebeckite/core": "0.0.18"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"tsx": "^4.22.4",
|
|
21
|
-
"@riebeckite/plugin-
|
|
22
|
-
"@riebeckite/plugin-
|
|
21
|
+
"@riebeckite/plugin-taxonomy": "0.0.18",
|
|
22
|
+
"@riebeckite/plugin-l10n": "0.0.18"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|