diff --git a/.gitignore b/.gitignore
index 0ae596bf..56dc2b9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,5 @@ lib
dist
.parcel-cache/*
-.DS_Store
\ No newline at end of file
+.DS_Store
+.vscode
\ No newline at end of file
diff --git a/package.json b/package.json
index f5a07c35..af25cf97 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@civicactions/data-catalog-components",
- "version": "1.17.1",
+ "version": "1.18.0",
"description": "React Components for Open Data Catalogs.",
"main": "dist/index.js",
"source": "src/index.ts",
@@ -26,7 +26,6 @@
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@tanstack/react-table": "^8.10.7",
- "axios": "^1.6.2",
"bootstrap": "^4.2.1",
"excerpts": "0.0.3",
"html-to-react": "^1.7.0",
@@ -63,7 +62,8 @@
},
"peerDependencies": {
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "@tanstack/react-query": "^5.14.1"
},
"files": [
"lib",
diff --git a/src/components/ColumnFilter/index.jsx b/src/components/ColumnFilter/index.jsx
index e9ca8ff8..bca3265e 100644
--- a/src/components/ColumnFilter/index.jsx
+++ b/src/components/ColumnFilter/index.jsx
@@ -1,20 +1,26 @@
- import React from "react";
+ import React, {useState, useEffect} from "react";
function ColumnFilter({
- column: { getFilterValue, setFilterValue, Header },
- resourceState
+ column,
+ count
}) {
+ const [inputValue, setInputValue] = useState(column.getFilterValue() || '')
+
+ useEffect(() => {
+ const delayedInputTimeout = setTimeout(() => {
+ column.setFilterValue(inputValue || '');
+ }, 500)
+ return () => clearTimeout(delayedInputTimeout);
+ }, [inputValue, 500]);
return (
{
- e.preventDefault();
- e.stopPropagation();
- setFilterValue(e.target.value || undefined); // Set undefined to remove the filter entirely
+ setInputValue(e.target.value || '')
}}
- placeholder={`Search ${resourceState.count} records...`}
+ placeholder={`Search ${count} records...`}
/>
);
};
diff --git a/src/components/DataTable/DataTablePageResults/index.jsx b/src/components/DataTable/DataTablePageResults/index.jsx
index 3d5dc727..40b754b3 100644
--- a/src/components/DataTable/DataTablePageResults/index.jsx
+++ b/src/components/DataTable/DataTablePageResults/index.jsx
@@ -1,13 +1,16 @@
-import React from 'react';
+import React, { useContext } from 'react';
+import { ResourceDispatch } from '../../../services/resource/resource_defaults';
import PropTypes from 'prop-types';
const DataTablePageResults = ({
total,
- pageSize,
- currentPage,
className,
viewing = false
}) => {
+ const { resourceState } = useContext(ResourceDispatch);
+ const pageSize = resourceState.pageSize;
+ const currentPage = resourceState.currentPage
+
// Add one to offset the 0 array index.
const page = currentPage + 1;
let displayTotal = total;
@@ -48,8 +51,6 @@ DataTablePageResults.defaultProps = {
DataTablePageResults.propTypes = {
className: PropTypes.string,
total: PropTypes.number.isRequired,
- pageSize: PropTypes.number.isRequired,
- currentPage: PropTypes.number.isRequired,
};
export default DataTablePageResults;
diff --git a/src/components/DataTable/DataTablePageResults/index.test.jsx b/src/components/DataTable/DataTablePageResults/index.test.jsx
index ea115b0c..75abb16c 100644
--- a/src/components/DataTable/DataTablePageResults/index.test.jsx
+++ b/src/components/DataTable/DataTablePageResults/index.test.jsx
@@ -1,39 +1,46 @@
import React from 'react';
import { render } from '@testing-library/react';
import DataTablePageResults from '.';
+import { ResourceDispatch, defaultResourceState } from '../../../services/resource/resource_defaults';
import { getByTextContent } from '../../../tests/utils';
describe('', () => {
+ const dispatch = jest.fn();
it('renders correct initial results', () => {
+ const resourceState = {
+ pageSize: 10,
+ currentPage: 0
+ }
render(
- ,
+
+
+
);
expect(getByTextContent('1 - 10 of 100 rows')).toBeInTheDocument();
});
it('renders correct results on subsequent pages', () => {
+ const resourceState = {
+ pageSize: 10,
+ currentPage: 4
+ }
render(
- ,
+
+
+
);
expect(getByTextContent('41 - 50 of 100 rows')).toBeInTheDocument();
});
it('Correctly displays appended viewing to results list', () => {
+ const resourceState = {
+ pageSize: 10,
+ currentPage: 4
+ }
render(
- ,
+
+
+
);
expect(getByTextContent('Viewing 41 - 50 of 100 rows')).toBeInTheDocument();
})
diff --git a/src/components/DataTable/DataTablePageSizer/index.jsx b/src/components/DataTable/DataTablePageSizer/index.jsx
index 992aacc3..f2745c69 100644
--- a/src/components/DataTable/DataTablePageSizer/index.jsx
+++ b/src/components/DataTable/DataTablePageSizer/index.jsx
@@ -1,26 +1,28 @@
-import React from 'react';
+import React, {useContext} from 'react';
import PropTypes from 'prop-types';
+import { ResourceDispatch } from '../../../services/resource/resource_defaults';
const DataTablePageSizer = ({
label,
- pageSizeChange,
- initSize,
options,
className,
selectClassName,
id,
}) => {
- const [selValue, setSelValue] = React.useState(initSize);
- React.useEffect(() => {
- pageSizeChange(Number(selValue));
- }, [selValue]);
+ const {dispatch, resourceState} = useContext(ResourceDispatch);
+
return (
-
+ >
);
};
diff --git a/src/templates/DataTableHeader/index.jsx b/src/templates/DataTableHeader/index.jsx
index 5ad64a7d..c509a87d 100644
--- a/src/templates/DataTableHeader/index.jsx
+++ b/src/templates/DataTableHeader/index.jsx
@@ -1,37 +1,26 @@
import React from 'react';
-import { ResourceDispatch } from '../../services/resource/resource_defaults';
import ManageColumns from '../../components/DataTable/ManageColumns';
import DataTablePageResults from '../../components/DataTable/DataTablePageResults';
import DataTableDensity from '../../components/DataTable/DataTableDensity';
import DataTablePageSizer from '../../components/DataTable/DataTablePageSizer';
import DataIcon from '../../components/DataIcon';
-const DataTableHeader = () => {
- const { reactTable, resourceState, dispatch } = React.useContext(ResourceDispatch);
+const DataTableHeader = ({reactTable, total, setDensity}) => {
+ const columns = reactTable.getAllColumns();
return (
- {resourceState.store
+ {reactTable
&& (
<>
{
- dispatch({
- type: 'UPDATE_PAGE_SIZE',
- data: { pageSize: value },
- });
- reactTable.resetPagination();
- }}
- id={resourceState.store.id}
- initSize={resourceState.pageSize}
+ id={""} //todo
/>
dispatch({ type: 'UPDATE_DENSITY', data: { density } })}
+ densityChange={(density) => setDensity(density)}
items={[
{
icon: (
@@ -74,8 +63,8 @@ const DataTableHeader = () => {
},
]}
/>
- {reactTable.getAllColumns()
- && }
+ {columns ?
+ : ""}
>
)}
diff --git a/src/templates/NavBar/index.jsx b/src/templates/NavBar/index.jsx
index 33fef288..b2d59a0d 100644
--- a/src/templates/NavBar/index.jsx
+++ b/src/templates/NavBar/index.jsx
@@ -21,7 +21,7 @@ const NavBar = ({
toggleOpen(!isOpen)}>
diff --git a/src/templates/SearchContent/index.jsx b/src/templates/SearchContent/index.jsx
index 64eb783b..6f49be42 100644
--- a/src/templates/SearchContent/index.jsx
+++ b/src/templates/SearchContent/index.jsx
@@ -5,18 +5,19 @@ import SearchListItem from '../../components/SearchListItem';
import SearchInput from '../../components/SearchInput';
import SearchPaginationResults from '../../components/SearchPaginationResults';
import SearchPageSizer from '../../components/SearchPageSizer';
-import { SearchDispatch } from '../../services/search/search_defaults';
import { List } from 'react-content-loader';
+import { normalizeItems } from "../../components/Search/functions";
+import { SearchDispatch } from '../../services/search/search_defaults';
-const SearchContent = () => {
+const SearchContent = ({loading, data}) => {
const { searchState, dispatch, defaultFacets } = useContext(SearchDispatch);
- const { items, fulltext, totalItems, selectedFacets, loading } = searchState;
+ const { fulltext, selectedFacets } = searchState;
const facetTypes = Object.keys(defaultFacets);
-
+ const items = data.results ? normalizeItems(data.results) : [];
+ const Loading = () =>
return (
- {items
- && (
+ {items && (
{
/>
{
facetSeparator=" & "
/>
- {loading ?
+ {loading || !items || !items.length ?
-
+
:
{items.map((item) => (
@@ -52,7 +53,7 @@ const SearchContent = () => {
@@ -67,7 +68,7 @@ const SearchContent = () => {
hideDisabled
activePage={searchState.page}
itemsCountPerPage={Number(searchState['page-size'])}
- totalItemsCount={Number(totalItems)}
+ totalItemsCount={Number(data.total)}
pageRangeDisplayed={5}
onChange={(e) => dispatch({
type: 'UPDATE_CURRENT_PAGE',
diff --git a/src/templates/SearchSidebar/index.jsx b/src/templates/SearchSidebar/index.jsx
index aa6b9125..0e460ab1 100644
--- a/src/templates/SearchSidebar/index.jsx
+++ b/src/templates/SearchSidebar/index.jsx
@@ -1,47 +1,58 @@
-import React, { useContext } from 'react';
+import React, { useContext, useState } from 'react';
import PropTypes from 'prop-types';
-import { Label, Input } from 'reactstrap';
+import { Label, Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
import SearchFacets from '../../components/SearchFacets';
import { SearchDispatch } from '../../services/search/search_defaults';
import { BulletList } from 'react-content-loader';
-const SearchSidebar = ({ sortOptions }) => {
+const SearchSidebar = ({ sortOptions, facetsResults }) => {
const { searchState, dispatch, defaultFacets } = useContext(SearchDispatch);
- const { facetsResults, loading } = searchState;
+ const { loading, sort } = searchState;
+ const [dropdownOpen, setDropdownOpen] = useState(false);
+ const toggle = () => setDropdownOpen((prevState) => !prevState);
+
+ const label = sortOptions.filter((s) => {
+ return s.field == sort;
+ })[0].label
+ const Loading = () =>
+
return (
diff --git a/src/tests/utils.js b/src/tests/utils.js
index 629712af..424a9cb1 100644
--- a/src/tests/utils.js
+++ b/src/tests/utils.js
@@ -1,6 +1,7 @@
import { screen } from '@testing-library/react';
export const getByTextContent = (text) => {
+ console.log(text)
return screen.getByText((content, element) => {
const hasText = element => element.textContent === text
const elementHasText = hasText(element)
diff --git a/stories/dataset.stories.jsx b/stories/dataset.stories.jsx
index 67da2e44..2f519512 100755
--- a/stories/dataset.stories.jsx
+++ b/stories/dataset.stories.jsx
@@ -28,7 +28,6 @@ import tables from './data/tables.json';
import '../src/theme/styles/index.scss';
import TopicIcon from '../src/templates/TopicIcon';
import TopicWrapper from '../src/components/TopicWrapper';
-import { ResourceDispatch } from '../src/services/resource/resource_defaults';
import DataTable from '../src/templates/DataTable';
import { resourceData } from './data/resourceData';
@@ -179,11 +178,5 @@ storiesOf('Dataset', module)
useSortBy,
usePagination,
);
- return (
-
({}), reactTable }}
- >
-
-
- );
+ return (
);
});
diff --git a/yarn.lock b/yarn.lock
index 05ef23d1..35ed111a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,7 +2,7 @@
# yarn lockfile v1
-"@adobe/css-tools@^4.3.1":
+"@adobe/css-tools@^4.3.2":
version "4.3.2"
resolved "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz"
integrity sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==
@@ -2450,6 +2450,18 @@
resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz"
integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==
+"@tanstack/query-core@5.14.1":
+ version "5.14.1"
+ resolved "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.14.1.tgz"
+ integrity sha512-TlZarySCVEiap4K7BCvrsYZnX7jBbEkR55YMrk8ELcRbuAx6ydL+qoxqUt8Fq8VMvQyGt52icn6T7eJL1Q35KQ==
+
+"@tanstack/react-query@^5.14.1":
+ version "5.14.1"
+ resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.14.1.tgz"
+ integrity sha512-v7jhe/3jhChiR0XJbGHaG5WNPd/cURwzDGBCr4rzpUTeudPzxrtVRKsF1xJRLcJK3qH/0gIwTYHIPZ3gj+01Yw==
+ dependencies:
+ "@tanstack/query-core" "5.14.1"
+
"@tanstack/react-table@^8.10.7":
version "8.10.7"
resolved "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.10.7.tgz"
@@ -2477,16 +2489,16 @@
pretty-format "^27.0.2"
"@testing-library/jest-dom@^6.1.5":
- version "6.1.5"
- resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.5.tgz"
- integrity sha512-3y04JLW+EceVPy2Em3VwNr95dOKqA8DhR0RJHhHKDZNYXcVXnEK7WIrpj4eYU8SVt/qYZ2aRWt/WgQ+grNES8g==
+ version "6.2.0"
+ resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.2.0.tgz"
+ integrity sha512-+BVQlJ9cmEn5RDMUS8c2+TU6giLvzaHZ8sU/x0Jj7fk+6/46wPdwlgOPcpxS17CjcanBi/3VmGMqVr2rmbUmNw==
dependencies:
- "@adobe/css-tools" "^4.3.1"
+ "@adobe/css-tools" "^4.3.2"
"@babel/runtime" "^7.9.2"
aria-query "^5.0.0"
chalk "^3.0.0"
css.escape "^1.5.1"
- dom-accessibility-api "^0.5.6"
+ dom-accessibility-api "^0.6.3"
lodash "^4.17.15"
redent "^3.0.0"
@@ -2500,9 +2512,9 @@
"@types/react-dom" "^18.0.0"
"@testing-library/user-event@^14.5.1":
- version "14.5.1"
- resolved "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.1.tgz"
- integrity sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==
+ version "14.5.2"
+ resolved "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz"
+ integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==
"@tootallnate/once@2":
version "2.0.0"
@@ -2531,9 +2543,9 @@
"@types/babel__traverse" "*"
"@types/babel__generator@*":
- version "7.6.7"
- resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.7.tgz"
- integrity sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==
+ version "7.6.8"
+ resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz"
+ integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==
dependencies:
"@babel/types" "^7.0.0"
@@ -2546,9 +2558,9 @@
"@babel/types" "^7.0.0"
"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6":
- version "7.20.4"
- resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz"
- integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==
+ version "7.20.5"
+ resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz"
+ integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==
dependencies:
"@babel/types" "^7.20.7"
@@ -2863,14 +2875,14 @@ acorn@^6.4.1:
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
acorn@^8.1.0:
- version "8.11.2"
- resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz"
- integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==
+ version "8.11.3"
+ resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz"
+ integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
acorn@^8.8.1:
- version "8.11.2"
- resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz"
- integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==
+ version "8.11.3"
+ resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz"
+ integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
acorn@^8.8.2:
version "8.11.2"
@@ -2982,14 +2994,7 @@ argparse@^2.0.1:
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
-aria-query@^5.0.0:
- version "5.3.0"
- resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz"
- integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==
- dependencies:
- dequal "^2.0.3"
-
-aria-query@5.1.3:
+aria-query@^5.0.0, aria-query@5.1.3:
version "5.1.3"
resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz"
integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==
@@ -3079,7 +3084,7 @@ available-typed-arrays@^1.0.5:
resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz"
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
-axios@^1.4.0, axios@^1.6.2:
+axios@^1.4.0:
version "1.6.2"
resolved "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz"
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
@@ -4170,11 +4175,6 @@ delayed-stream@~1.0.0:
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
-dequal@^2.0.3:
- version "2.0.3"
- resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz"
- integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
-
des.js@^1.0.0:
version "1.1.0"
resolved "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz"
@@ -4226,11 +4226,16 @@ dnd-core@^16.0.1:
"@react-dnd/invariant" "^4.0.1"
redux "^4.2.0"
-dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9:
+dom-accessibility-api@^0.5.9:
version "0.5.16"
resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz"
integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
+dom-accessibility-api@^0.6.3:
+ version "0.6.3"
+ resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz"
+ integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==
+
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz"
@@ -9235,9 +9240,9 @@ write-file-atomic@^4.0.2:
signal-exit "^3.0.7"
ws@^8.11.0:
- version "8.15.1"
- resolved "https://registry.npmjs.org/ws/-/ws-8.15.1.tgz"
- integrity sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==
+ version "8.16.0"
+ resolved "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz"
+ integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
xml-but-prettier@^1.0.1:
version "1.0.1"