Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/core/config.ts
3557 views
1
/*
2
* config.ts
3
*
4
* Copyright (C) 2020-2022 Posit Software, PBC
5
*/
6
7
import * as ld from "./lodash.ts";
8
import { makeTimedFunction } from "./performance/function-times.ts";
9
10
export const mergeConfigs = makeTimedFunction(
11
"mergeConfigs",
12
function mergeConfigs<T>(config: T, ...configs: Array<unknown>): T {
13
// copy all configs so we don't mutate them
14
config = ld.cloneDeep(config);
15
configs = ld.cloneDeep(configs);
16
17
return ld.mergeWith(
18
config,
19
...configs,
20
mergeArrayCustomizer,
21
);
22
},
23
);
24
25
export function mergeArrayCustomizer(objValue: unknown, srcValue: unknown) {
26
if (ld.isArray(objValue) || ld.isArray(srcValue)) {
27
// handle nulls
28
if (!objValue) {
29
return srcValue;
30
} else if (!srcValue) {
31
return objValue;
32
// coerce scalers to array
33
} else {
34
if (!ld.isArray(objValue)) {
35
objValue = [objValue];
36
}
37
if (!ld.isArray(srcValue)) {
38
srcValue = [srcValue];
39
}
40
}
41
42
const combined = (objValue as Array<unknown>).concat(
43
srcValue as Array<unknown>,
44
);
45
return ld.uniqBy(combined, (value: unknown) => {
46
if (typeof value === "function") {
47
return globalThis.crypto.randomUUID();
48
} else {
49
return JSON.stringify(value);
50
}
51
});
52
}
53
}
54
55
// the camelToKebab transform is not well-defined for
56
// sequences of uppercase characters ("URL" being the
57
// example that comes up in practice). For example,
58
// the string "isURLHTML" can't be transformed to
59
// the "correct" "is-url-html" because it's not clear
60
// where the hyphens should go. As a heuristic,
61
// we assume that a sequence of uppercase characters
62
// that is followed by a lowercase character should
63
// be treated as a single word, except for the last
64
// uppercase character if it's followed by subsequent
65
// lowercase characters. So "isURLHTML" becomes
66
// "is-urlhtml", but "isURLHTMLString" becomes
67
// "is-urlhtml-string".
68
export function camelToKebab(camel: string) {
69
camel = camel.replace(/([A-Z])([A-Z]+)$/g, function (_, p1, p2) {
70
return p1 + p2.toLowerCase();
71
});
72
camel = camel.replaceAll(/([A-Z])([A-Z]+)([A-Z])/g, function (_, p1, p2, p3) {
73
return p1 + p2.toLowerCase() + p3;
74
});
75
const kebab: string[] = [];
76
for (let i = 0; i < camel.length; i++) {
77
const ch = camel.charAt(i);
78
if (ch === ch.toUpperCase() && !/^\d+/.test(ch)) {
79
if (i > 0) {
80
kebab.push("-");
81
}
82
kebab.push(ch.toLowerCase());
83
} else {
84
kebab.push(ch);
85
}
86
}
87
return kebab.join("");
88
}
89
90
export function kebabToCamel(kebab: string, leadingUppercase = false) {
91
const camel: string[] = [];
92
for (let i = 0; i < kebab.length; i++) {
93
const ch = kebab.charAt(i);
94
if (ch === "-") {
95
camel.push(kebab.charAt(++i).toUpperCase());
96
} else if ((i === 0) && leadingUppercase) {
97
camel.push(ch.toUpperCase());
98
} else {
99
camel.push(ch);
100
}
101
}
102
return camel.join("");
103
}
104
105