Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/command/render/resources.ts
3583 views
1
/*
2
* resources.ts
3
*
4
* Copyright (C) 2020-2022 Posit Software, PBC
5
*/
6
7
import { dirname, join } from "../../deno_ral/path.ts";
8
import {
9
normalizePath,
10
ResolvedPathGlobs,
11
resolvePathGlobs,
12
safeExistsSync,
13
} from "../../core/path.ts";
14
import * as ld from "../../core/lodash.ts";
15
import { engineIgnoreGlobs } from "../../execute/engine.ts";
16
import { kQuartoScratch } from "../../project/project-scratch.ts";
17
import { extractResolvedResourceFilenamesFromQmd } from "../../execute/ojs/extract-resources.ts";
18
import { asMappedString } from "../../core/mapped-text.ts";
19
import { RenderedFile, RenderResourceFiles } from "./types.ts";
20
import { PartitionedMarkdown } from "../../core/pandoc/types.ts";
21
22
export function resourcesFromMetadata(resourcesMetadata?: unknown) {
23
// interrogate / typecast raw yaml resources into array of strings
24
const resources: string[] = [];
25
if (resourcesMetadata) {
26
if (Array.isArray(resourcesMetadata)) {
27
for (const file of resourcesMetadata) {
28
resources.push(String(file));
29
}
30
} else {
31
resources.push(String(resourcesMetadata));
32
}
33
}
34
return resources;
35
}
36
37
// FIXME markdown should come as a MappedString but we don't want to port
38
// over the entirety of quarto just yet.
39
export async function resolveFileResources(
40
rootDir: string,
41
fileDir: string,
42
excludeDirs: string[],
43
markdown: string,
44
globs: string[],
45
skipOjsDiscovery?: boolean,
46
): Promise<ResolvedPathGlobs> {
47
const ignore = engineIgnoreGlobs()
48
.concat(kQuartoScratch + "/")
49
.concat(["**/.*", "**/.*/**"]) // hidden (dot prefix))
50
.concat(
51
...excludeDirs,
52
);
53
54
const resources = resolvePathGlobs(fileDir, globs, ignore, {
55
mode: "always",
56
explicitSubfolderSearch: true,
57
});
58
if (markdown.length > 0 && !skipOjsDiscovery) {
59
resources.include.push(
60
...(await extractResolvedResourceFilenamesFromQmd(
61
asMappedString(markdown),
62
fileDir,
63
rootDir,
64
)),
65
);
66
}
67
return resources;
68
}
69
70
export function resourceFilesFromRenderedFile(
71
baseDir: string,
72
excludeDirs: string[],
73
renderedFile: RenderedFile,
74
partitioned?: PartitionedMarkdown,
75
) {
76
return resourceFilesFromFile(
77
baseDir,
78
excludeDirs,
79
renderedFile.file,
80
renderedFile.resourceFiles,
81
renderedFile.selfContained,
82
renderedFile.supporting,
83
partitioned,
84
true,
85
);
86
}
87
88
export async function resourceFilesFromFile(
89
baseDir: string,
90
excludeDirs: string[],
91
file: string,
92
resources: RenderResourceFiles,
93
selfContained: boolean,
94
supporting?: string[],
95
partitioned?: PartitionedMarkdown,
96
skipOjsDiscovery?: boolean,
97
) {
98
const resourceDir = join(baseDir, dirname(file));
99
const markdown = partitioned ? partitioned.markdown : "";
100
const globs = resources.globs;
101
const fileResourceFiles = await resolveFileResources(
102
baseDir,
103
resourceDir,
104
excludeDirs,
105
markdown,
106
globs,
107
skipOjsDiscovery,
108
);
109
110
// add the explicitly discovered files (if they exist and
111
// the output isn't self-contained)
112
if (!selfContained) {
113
const resultFiles = resources.files
114
.map((file) => join(resourceDir, file))
115
.filter(safeExistsSync)
116
.map(normalizePath);
117
fileResourceFiles.include.push(...resultFiles);
118
}
119
120
// apply removes and filter files dir
121
const resourceFiles = fileResourceFiles.include.filter(
122
(file: string) => {
123
if (fileResourceFiles.exclude.includes(file)) {
124
return false;
125
} else if (
126
supporting &&
127
supporting.some((support) => file.startsWith(join(baseDir, support)))
128
) {
129
return false;
130
} else {
131
return true;
132
}
133
},
134
);
135
// return unique entries
136
return ld.uniq(resourceFiles) as string[];
137
}
138
139