diff --git a/website/package-lock.json b/website/package-lock.json index 5fdf491f1cf..df0c9652529 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -27,6 +27,7 @@ "gray-matter": "^4.0.3", "hast-util-is-element": "^1.1.0", "js-yaml": "^4.1.0", + "markdown-to-jsx": "^7.5.0", "mobx": "^6.3.9", "node-polyfill-webpack-plugin": "^1.1.4", "papaparse": "^5.3.2", @@ -17038,6 +17039,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/markdown-to-jsx": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.5.0.tgz", + "integrity": "sha512-RrBNcMHiFPcz/iqIj0n3wclzHXjwS7mzjBNWecKKVhNTIxQepIix6Il/wZCn2Cg5Y1ow2Qi84+eJrryFRWBEWw==", + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", diff --git a/website/package.json b/website/package.json index 51edae4bf17..a16c8f9db9b 100644 --- a/website/package.json +++ b/website/package.json @@ -30,6 +30,7 @@ "gray-matter": "^4.0.3", "hast-util-is-element": "^1.1.0", "js-yaml": "^4.1.0", + "markdown-to-jsx": "^7.5.0", "mobx": "^6.3.9", "node-polyfill-webpack-plugin": "^1.1.4", "papaparse": "^5.3.2", diff --git a/website/src/components/sortableTable/index.js b/website/src/components/sortableTable/index.js new file mode 100644 index 00000000000..93d54252c94 --- /dev/null +++ b/website/src/components/sortableTable/index.js @@ -0,0 +1,114 @@ +import React, { useState, useMemo } from 'react'; +import Markdown from 'markdown-to-jsx'; + +const stripMarkdown = (text) => { + let strippedText = text.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); + strippedText = strippedText.replace(/[_*`~]/g, ''); + return strippedText; +}; + +const parseMarkdownTable = (markdown) => { + const rows = markdown.trim().split('\n'); + const headers = rows[0].split('|').map((header) => header.trim()).filter(Boolean); + + const alignmentsRow = rows[1].split('|').map((align) => align.trim()).filter(Boolean); + const columnAlignments = alignmentsRow.map((alignment) => { + if (alignment.startsWith(':') && alignment.endsWith(':')) { + return 'center'; + } else if (alignment.startsWith(':')) { + return 'left'; + } else if (alignment.endsWith(':')) { + return 'right'; + } else { + return 'left'; + } + }); + + const data = rows.slice(2).map(row => row.split('|').map(cell => cell.trim()).filter(Boolean)); + + return { headers, data, columnAlignments }; +}; + +const SortableTable = ({ children }) => { + const { headers, data: initialData, columnAlignments } = useMemo( + () => parseMarkdownTable(children), + [children] + ); + + const [data, setData] = useState(initialData); + const [sortConfig, setSortConfig] = useState({ key: '', direction: 'asc' }); + + const sortTable = (keyIndex) => { + const newDirection = (sortConfig.key === keyIndex && sortConfig.direction === 'asc') ? 'desc' : 'asc'; + setSortConfig({ key: keyIndex, direction: newDirection }); + + const sortedData = [...data].sort((a, b) => { + const aVal = stripMarkdown(a[keyIndex]); + const bVal = stripMarkdown(b[keyIndex]); + if (aVal < bVal) return newDirection === 'asc' ? -1 : 1; + if (aVal > bVal) return newDirection === 'asc' ? 1 : -1; + return 0; + }); + + setData(sortedData); + }; + + return ( + + + + {headers.map((header, index) => ( + + ))} + + + + {data.map((row, rowIndex) => ( + + {row.map((cell, cellIndex) => ( + + ))} + + ))} + +
sortTable(index)} + style={{ + cursor: 'pointer', + position: 'relative', + textAlign: columnAlignments[index], + padding: '10px' + }} + > +
+ {header} + + ↑ + + + ↓ + +
+
+ {cell || '\u00A0'} +
+ ); +}; + +export default SortableTable; diff --git a/website/src/theme/MDXComponents/index.js b/website/src/theme/MDXComponents/index.js index d136222a0ce..422d6c99fab 100644 --- a/website/src/theme/MDXComponents/index.js +++ b/website/src/theme/MDXComponents/index.js @@ -13,6 +13,7 @@ import Mermaid from '@theme/Mermaid'; /* dbt Customizations: * Imports the following components below for export */ +import SortableTable from '@site/src/components/sortableTable'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem' import Changelog from '@site/src/components/changelog'; @@ -95,5 +96,6 @@ const MDXComponents = { DetailsToggle: DetailsToggle, Expandable: Expandable, ConfettiTrigger: ConfettiTrigger, + SortableTable: SortableTable, }; export default MDXComponents;