/
graph.ts
62 lines (57 loc) · 1.93 KB
/
graph.ts
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
import type { GetModuleInfo, ModuleInfo } from 'rollup';
import { ASTRO_PAGE_RESOLVED_MODULE_ID } from './plugins/plugin-pages.js';
// This walks up the dependency graph and yields out each ModuleInfo object.
export function* walkParentInfos(
id: string,
ctx: { getModuleInfo: GetModuleInfo },
until?: (importer: string) => boolean,
depth = 0,
order = 0,
seen = new Set<string>(),
childId = ''
): Generator<[ModuleInfo, number, number], void, unknown> {
seen.add(id);
const info = ctx.getModuleInfo(id);
if (info) {
if (childId) {
const idx = info.importedIds.indexOf(childId);
if (idx === -1) {
// Dynamic imports come after all normal imports. So first add the number of normal imports.
order += info.importedIds.length;
// Then add on the dynamic ones.
order += info.dynamicallyImportedIds.indexOf(childId);
} else {
order += idx;
}
}
yield [info, depth, order];
}
if (until?.(id)) return;
const importers = (info?.importers || []).concat(info?.dynamicImporters || []);
for (const imp of importers) {
if (seen.has(imp)) {
continue;
}
yield* walkParentInfos(imp, ctx, until, ++depth, order, seen, id);
}
}
// Returns true if a module is a top-level page. We determine this based on whether
// it is imported by the top-level virtual module.
export function moduleIsTopLevelPage(info: ModuleInfo): boolean {
return (
info.importers[0]?.includes(ASTRO_PAGE_RESOLVED_MODULE_ID) ||
info.dynamicImporters[0]?.includes(ASTRO_PAGE_RESOLVED_MODULE_ID)
);
}
// This function walks the dependency graph, going up until it finds a page component.
// This could be a .astro page, a .markdown or a .md (or really any file extension for markdown files) page.
export function* getTopLevelPages(
id: string,
ctx: { getModuleInfo: GetModuleInfo }
): Generator<[ModuleInfo, number, number], void, unknown> {
for (const res of walkParentInfos(id, ctx)) {
if (moduleIsTopLevelPage(res[0])) {
yield res;
}
}
}