Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/project/project-config.ts
6446 views
1
/*
2
* project-config.ts
3
*
4
* Copyright (C) 2020-2022 Posit Software, PBC
5
*/
6
7
import { join } from "../deno_ral/path.ts";
8
9
import * as ld from "../core/lodash.ts";
10
11
import { safeExistsSync } from "../core/path.ts";
12
13
import { readInputTargetIndex } from "./project-index.ts";
14
import { fileExecutionEngine } from "../execute/engine.ts";
15
import { ProjectContext, SidebarItem } from "./types.ts";
16
17
export type SidebarContext = {
18
counter: number;
19
};
20
21
export const sidebarContext = (): SidebarContext => {
22
return { counter: 0 };
23
};
24
25
export function normalizeSidebarItem(
26
projectDir: string,
27
item: SidebarItem,
28
context: { counter: number },
29
): SidebarItem {
30
// clone so we can mutate
31
item = ld.cloneDeep(item);
32
33
if (typeof item === "string") {
34
if (safeExistsSync(join(projectDir, item))) {
35
item = {
36
href: item,
37
};
38
} else {
39
item = {
40
text: item,
41
};
42
}
43
} else {
44
// resolve aliases for href
45
resolveHrefAttribute(item);
46
47
// section is a special key that can provide either text or href
48
// for an item with 'contents'
49
const section = item.section;
50
if (section) {
51
// Increment the counter
52
context.counter = context.counter + 1;
53
54
const sectionPath = join(projectDir, section);
55
if (safeExistsSync(sectionPath) && Deno.statSync(sectionPath).isFile) {
56
item.href = section;
57
} else {
58
item.text = section;
59
}
60
// The htmlId could be empty, in which case we will not have created
61
// an unambiguous sectionId, so don't write the section Id in this
62
// case
63
item.sectionId = `${kQuartoSidebarPrefix}${context.counter}`;
64
delete item.section;
65
66
// If this is a section, we should insist that it have 'contents'
67
// even if they are empty.
68
item.contents = item.contents || [];
69
}
70
71
// handle subitems
72
if (item.contents) {
73
for (let i = 0; i < item.contents.length; i++) {
74
item.contents[i] = normalizeSidebarItem(
75
projectDir,
76
item.contents[i],
77
context,
78
);
79
}
80
}
81
}
82
83
return item;
84
}
85
86
const kQuartoSidebarPrefix = "quarto-sidebar-section-";
87
88
export function resolveHrefAttribute(
89
item: { href?: string; file?: string; url?: string },
90
) {
91
item.href = item.href || item.file || item.url;
92
delete item.file;
93
delete item.url;
94
}
95
96
export async function partitionedMarkdownForInput(
97
project: ProjectContext,
98
input: string,
99
) {
100
// first see if we can get the partioned markdown out of the index
101
const { index } = readInputTargetIndex(project.dir, input);
102
if (index) {
103
return index.markdown;
104
// otherwise fall back to calling the engine to do the partition
105
} else {
106
const inputPath = join(project.dir, input);
107
const engine = await fileExecutionEngine(inputPath, undefined, project);
108
if (engine) {
109
return await engine.partitionedMarkdown(inputPath);
110
} else {
111
return undefined;
112
}
113
}
114
}
115
116