Path: blob/main/src/format/dashboard/format-dashboard-tables.ts
6451 views
/*1* format-dashboard-tables.ts2*3* Copyright (C) 2020-2022 Posit Software, PBC4*/56import { Document, Element } from "../../core/deno-dom.ts";7import { lines } from "../../core/text.ts";8import { kDTTableSentinel } from "./format-dashboard-shared.ts";910// Strip regexes11const kStripRegexes = [12/\/\/ Import jquery and DataTable/,13/^\s*import 'https:\/\/code\.jquery\.com\/jquery\-.*';$/,14/^\s*import dt from 'https:\/\/cdn\.datatables\.net\/.*\.mjs';$/,15/^\s*dt\(\$\);/,16];1718// This is the table initialization19const kDatatableInit =20/\$\(document\).ready\(function \(\) \{(?:\s|.)*?\$\('#(.*?)'\)\.DataTable\(dt_args\);(?:\s|.)*?\}\);.*/g;21const kDatatable16 = /.DataTable\(dt_args\)/g;2223// The href for the datatable CSS that is injected24const kDtCssHrefRegex =25/^\s*https:\/\/cdn\.datatables\.net\/.*?\/jquery\.dataTables\.min\.css$/;2627export function processDatatables(28doc: Document,29): { resources: string[]; supporting: string[] } {30const resources: string[] = [];31const supporting: string[] = [];3233// Look through the scripts in the body and see if we spot Datatables that we should fix up34const scriptNodes = doc.querySelectorAll(35".cell-output script[type='module']",36);3738let keepDeps = false;3940for (const scriptNode of scriptNodes) {41const scriptEl = scriptNode as Element;42const code = scriptEl.innerText;4344let hasConnectedDt = false;4546// First filter out lines and add configuration47const codeFiltered: string[] = [];48for (const line of lines(code)) {49if (50kStripRegexes.some((regex) => {51return !!line.match(regex);52})53) {54hasConnectedDt = true;55// ignore this line, we want to strip it56} else {57codeFiltered.push(line);58}59}6061if (hasConnectedDt) {62keepDeps = true;63// Replace the table initialization64const codeText = codeFiltered.join("\n");65// for iTables < 1.7, do fixups66// for iTables 1.7, don't67if (codeText.match(kDatatable16)) {68const codeWithInit = codeText.replace(69kDatatableInit,70"let table = new DataTable('#$1', dt_args);",71);72scriptEl.innerText = codeWithInit;73} else {74scriptEl.innerText = codeText;75}7677// Remove the inline css78const linkCssNodes = doc.querySelectorAll(79'link[rel="stylesheet"][type="text/css"][href]',80);81for (const linkCssNode of linkCssNodes) {82const linkCssEl = linkCssNode as Element;83const href = linkCssEl.getAttribute("href");84if (href?.match(kDtCssHrefRegex)) {85linkCssEl.remove();86}87}88}89}9091if (keepDeps) {92// We found tables, clear the DT sentinel attr93const dtNodes = doc.querySelectorAll(`[${kDTTableSentinel}="true"]`);94dtNodes.forEach((node) => {95(node as Element).removeAttribute(kDTTableSentinel);96});97} else {98// We didn't find any DT, remove the dependencies that we injected at the root level99const dtNodes = doc.querySelectorAll(`[${kDTTableSentinel}="true"]`);100dtNodes.forEach((node) => {101(node as Element).remove();102});103}104105return {106resources,107supporting,108};109}110111112