Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/format/dashboard/format-dashboard-tables.ts
6451 views
1
/*
2
* format-dashboard-tables.ts
3
*
4
* Copyright (C) 2020-2022 Posit Software, PBC
5
*/
6
7
import { Document, Element } from "../../core/deno-dom.ts";
8
import { lines } from "../../core/text.ts";
9
import { kDTTableSentinel } from "./format-dashboard-shared.ts";
10
11
// Strip regexes
12
const kStripRegexes = [
13
/\/\/ Import jquery and DataTable/,
14
/^\s*import 'https:\/\/code\.jquery\.com\/jquery\-.*';$/,
15
/^\s*import dt from 'https:\/\/cdn\.datatables\.net\/.*\.mjs';$/,
16
/^\s*dt\(\$\);/,
17
];
18
19
// This is the table initialization
20
const kDatatableInit =
21
/\$\(document\).ready\(function \(\) \{(?:\s|.)*?\$\('#(.*?)'\)\.DataTable\(dt_args\);(?:\s|.)*?\}\);.*/g;
22
const kDatatable16 = /.DataTable\(dt_args\)/g;
23
24
// The href for the datatable CSS that is injected
25
const kDtCssHrefRegex =
26
/^\s*https:\/\/cdn\.datatables\.net\/.*?\/jquery\.dataTables\.min\.css$/;
27
28
export function processDatatables(
29
doc: Document,
30
): { resources: string[]; supporting: string[] } {
31
const resources: string[] = [];
32
const supporting: string[] = [];
33
34
// Look through the scripts in the body and see if we spot Datatables that we should fix up
35
const scriptNodes = doc.querySelectorAll(
36
".cell-output script[type='module']",
37
);
38
39
let keepDeps = false;
40
41
for (const scriptNode of scriptNodes) {
42
const scriptEl = scriptNode as Element;
43
const code = scriptEl.innerText;
44
45
let hasConnectedDt = false;
46
47
// First filter out lines and add configuration
48
const codeFiltered: string[] = [];
49
for (const line of lines(code)) {
50
if (
51
kStripRegexes.some((regex) => {
52
return !!line.match(regex);
53
})
54
) {
55
hasConnectedDt = true;
56
// ignore this line, we want to strip it
57
} else {
58
codeFiltered.push(line);
59
}
60
}
61
62
if (hasConnectedDt) {
63
keepDeps = true;
64
// Replace the table initialization
65
const codeText = codeFiltered.join("\n");
66
// for iTables < 1.7, do fixups
67
// for iTables 1.7, don't
68
if (codeText.match(kDatatable16)) {
69
const codeWithInit = codeText.replace(
70
kDatatableInit,
71
"let table = new DataTable('#$1', dt_args);",
72
);
73
scriptEl.innerText = codeWithInit;
74
} else {
75
scriptEl.innerText = codeText;
76
}
77
78
// Remove the inline css
79
const linkCssNodes = doc.querySelectorAll(
80
'link[rel="stylesheet"][type="text/css"][href]',
81
);
82
for (const linkCssNode of linkCssNodes) {
83
const linkCssEl = linkCssNode as Element;
84
const href = linkCssEl.getAttribute("href");
85
if (href?.match(kDtCssHrefRegex)) {
86
linkCssEl.remove();
87
}
88
}
89
}
90
}
91
92
if (keepDeps) {
93
// We found tables, clear the DT sentinel attr
94
const dtNodes = doc.querySelectorAll(`[${kDTTableSentinel}="true"]`);
95
dtNodes.forEach((node) => {
96
(node as Element).removeAttribute(kDTTableSentinel);
97
});
98
} else {
99
// We didn't find any DT, remove the dependencies that we injected at the root level
100
const dtNodes = doc.querySelectorAll(`[${kDTTableSentinel}="true"]`);
101
dtNodes.forEach((node) => {
102
(node as Element).remove();
103
});
104
}
105
106
return {
107
resources,
108
supporting,
109
};
110
}
111
112