@google-psat/report 0.9.0-3 → 0.10.1-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/dashboard/components/cookiesWithIssues/index.js +43 -0
  2. package/dist/dashboard/components/header/index.js +26 -0
  3. package/dist/dashboard/components/siteMapReport/cookies.js +73 -0
  4. package/dist/dashboard/components/siteMapReport/index.js +31 -0
  5. package/dist/dashboard/components/siteMapReport/layout.js +140 -0
  6. package/dist/dashboard/components/siteMapReport/sidebarData.js +46 -0
  7. package/dist/dashboard/components/siteMapReport/sitemapCookiesWithIssues.js +9 -0
  8. package/dist/dashboard/components/siteReport/components/layout.js +145 -0
  9. package/dist/dashboard/components/siteReport/index.js +33 -0
  10. package/dist/dashboard/components/siteReport/stateProviders/contentStore/index.js +55 -0
  11. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/blockedCookiesSection.js +82 -0
  12. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/cookiesSection.js +38 -0
  13. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/exemptedCookiesSection.js +63 -0
  14. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/framesSection.js +38 -0
  15. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/index.js +17 -0
  16. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/knownBreakages.js +53 -0
  17. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/landing.js +110 -0
  18. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/index.js +58 -0
  19. package/dist/dashboard/components/siteReport/tabs/cookies/cookiesListing/index.js +47 -0
  20. package/dist/dashboard/components/siteReport/tabs/cookies/index.js +56 -0
  21. package/dist/dashboard/components/siteReport/tabs/index.js +54 -0
  22. package/dist/dashboard/components/siteReport/tabs/siteCookiesWithIssues/index.js +29 -0
  23. package/dist/dashboard/components/siteReport/tabs/technologies/index.js +91 -0
  24. package/dist/dashboard/components/utils/NamePrefixIconSelector.js +67 -0
  25. package/dist/dashboard/components/utils/extractCookies.js +36 -0
  26. package/dist/dashboard/components/utils/extractReportData.js +56 -0
  27. package/dist/dashboard/components/utils/reportDownloader/generateSiteMapReportandDownload.js +44 -0
  28. package/dist/dashboard/components/utils/reportDownloader/generateSiteReportandDownload.js +52 -0
  29. package/dist/dashboard/components/utils/reportDownloader/index.js +17 -0
  30. package/dist/dashboard/components/utils/reportDownloader/utils.js +148 -0
  31. package/dist/dashboard/components/utils/reshapeCookies.js +102 -0
  32. package/dist/dashboard/components/utils/tests/data.mock.js +176 -0
  33. package/dist/dashboard/components/utils/tests/extractCookies.js +84 -0
  34. package/dist/dashboard/components/utils/tests/extractReportData.js +64 -0
  35. package/dist/dashboard/components/utils/tests/reshapeCookies.js +89 -0
  36. package/dist/dashboard/hooks/useCookieListing/index.js +412 -0
  37. package/dist/dashboard/index.js +19 -0
  38. package/dist/index.js +16 -0
  39. package/dist-types/dashboard/components/cookiesWithIssues/index.d.ts +8 -0
  40. package/dist-types/dashboard/components/header/index.d.ts +6 -0
  41. package/dist-types/dashboard/components/siteMapReport/cookies.d.ts +15 -0
  42. package/dist-types/dashboard/components/siteMapReport/index.d.ts +11 -0
  43. package/dist-types/dashboard/components/siteMapReport/layout.d.ts +18 -0
  44. package/dist-types/dashboard/components/siteMapReport/sidebarData.d.ts +3 -0
  45. package/dist-types/dashboard/components/siteMapReport/sitemapCookiesWithIssues.d.ts +10 -0
  46. package/dist-types/dashboard/components/siteReport/components/layout.d.ts +13 -0
  47. package/dist-types/dashboard/components/siteReport/index.d.ts +17 -0
  48. package/dist-types/dashboard/components/siteReport/stateProviders/contentStore/index.d.ts +32 -0
  49. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/blockedCookiesSection.d.ts +8 -0
  50. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/cookiesSection.d.ts +7 -0
  51. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/exemptedCookiesSection.d.ts +7 -0
  52. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/framesSection.d.ts +9 -0
  53. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/index.d.ts +2 -0
  54. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/knownBreakages.d.ts +9 -0
  55. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/cookieLanding/landing.d.ts +15 -0
  56. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesLandingContainer/index.d.ts +23 -0
  57. package/dist-types/dashboard/components/siteReport/tabs/cookies/cookiesListing/index.d.ts +9 -0
  58. package/dist-types/dashboard/components/siteReport/tabs/cookies/index.d.ts +9 -0
  59. package/dist-types/dashboard/components/siteReport/tabs/index.d.ts +3 -0
  60. package/dist-types/dashboard/components/siteReport/tabs/siteCookiesWithIssues/index.d.ts +5 -0
  61. package/dist-types/dashboard/components/siteReport/tabs/technologies/index.d.ts +5 -0
  62. package/dist-types/dashboard/components/utils/NamePrefixIconSelector.d.ts +3 -0
  63. package/dist-types/dashboard/components/utils/extractCookies.d.ts +6 -0
  64. package/dist-types/dashboard/components/utils/extractReportData.d.ts +11 -0
  65. package/dist-types/dashboard/components/utils/reportDownloader/generateSiteMapReportandDownload.d.ts +4 -0
  66. package/dist-types/dashboard/components/utils/reportDownloader/generateSiteReportandDownload.d.ts +4 -0
  67. package/dist-types/dashboard/components/utils/reportDownloader/index.d.ts +2 -0
  68. package/dist-types/dashboard/components/utils/reportDownloader/utils.d.ts +9 -0
  69. package/dist-types/dashboard/components/utils/reshapeCookies.d.ts +8 -0
  70. package/dist-types/dashboard/components/utils/tests/data.mock.d.ts +6 -0
  71. package/dist-types/dashboard/components/utils/tests/extractCookies.d.ts +1 -0
  72. package/dist-types/dashboard/components/utils/tests/extractReportData.d.ts +1 -0
  73. package/dist-types/dashboard/components/utils/tests/reshapeCookies.d.ts +1 -0
  74. package/dist-types/dashboard/hooks/useCookieListing/index.d.ts +10 -0
  75. package/dist-types/dashboard/index.d.ts +4 -0
  76. package/dist-types/index.d.ts +1 -0
  77. package/package.json +11 -5
  78. package/public/index.html +1 -0
  79. package/tsconfig.json +19 -3
@@ -0,0 +1,91 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * https://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * External dependencies
19
+ */
20
+ import { useMemo, useState } from 'react';
21
+ import { Resizable } from 're-resizable';
22
+ import { noop } from '@google-psat/common';
23
+ import { I18n } from '@google-psat/i18n';
24
+ import { Table, TableProvider, } from '@google-psat/design-system';
25
+ /**
26
+ * Internal dependencies
27
+ */
28
+ import { useContentStore } from '../../stateProviders/contentStore';
29
+ const Technologies = ({ selectedSite }) => {
30
+ const data = useContentStore(({ state }) => state.technologies || []);
31
+ const [selectedRow, setSelectedRow] = useState();
32
+ const tableColumns = useMemo(() => [
33
+ {
34
+ header: I18n.getMessage('name'),
35
+ accessorKey: 'name',
36
+ cell: (info) => info,
37
+ enableHiding: false,
38
+ },
39
+ {
40
+ header: I18n.getMessage('description'),
41
+ accessorKey: 'description',
42
+ cell: (info) => info,
43
+ },
44
+ {
45
+ header: I18n.getMessage('confidence'),
46
+ accessorKey: 'confidence',
47
+ cell: (info) => (_jsx("span", { className: "w-full flex justify-center", children: info + '%' })),
48
+ },
49
+ {
50
+ header: I18n.getMessage('website'),
51
+ accessorKey: 'website',
52
+ cell: (info) => info,
53
+ },
54
+ {
55
+ header: I18n.getMessage('category'),
56
+ accessorKey: 'categories',
57
+ cell: (info) => info.map((i) => i.name).join(' | '),
58
+ sortingComparator: (a, b) => {
59
+ const aCategories = a
60
+ ?.map((i) => i.name)
61
+ .join(' | ') || '';
62
+ const bCategories = b
63
+ ?.map((i) => i.name)
64
+ .join(' | ') || '';
65
+ return aCategories.localeCompare(bCategories);
66
+ },
67
+ },
68
+ ], []);
69
+ const filters = useMemo(() => ({}), []);
70
+ const searchKeys = useMemo(() => ['name', 'website'], []);
71
+ const tablePersistentSettingsKey = useMemo(() => {
72
+ if (selectedSite) {
73
+ return `technologyListing#${selectedSite}`;
74
+ }
75
+ return 'technologyListing';
76
+ }, [selectedSite]);
77
+ return (_jsxs("div", { className: "w-full h-full text-outer-space-crayola border-x border-american-silver dark:border-quartz flex flex-col", children: [_jsx(Resizable, { defaultSize: {
78
+ width: '100%',
79
+ height: '80%',
80
+ }, minHeight: "6%", maxHeight: "95%", enable: {
81
+ top: false,
82
+ right: false,
83
+ bottom: true,
84
+ left: false,
85
+ }, className: "h-full flex", children: _jsx(TableProvider, { data: data, tableColumns: tableColumns, tableFilterData: filters, tableSearchKeys: searchKeys, tablePersistentSettingsKey: tablePersistentSettingsKey, onRowClick: (row) => {
86
+ setSelectedRow(row);
87
+ }, onRowContextMenu: noop, getRowObjectKey: (row) => {
88
+ return row.originalData.slug;
89
+ }, children: _jsx(Table, { hideFiltering: true, selectedKey: selectedRow?.slug }) }) }), _jsx("div", { className: "flex-1 border border-gray-300 dark:border-quartz shadow h-full min-w-[10rem]", children: selectedRow ? (_jsxs("div", { className: "text-xs py-1 px-1.5", children: [selectedRow.name && (_jsxs(_Fragment, { children: [_jsx("p", { className: "font-bold text-granite-gray dark:text-manatee mb-1 text-semibold flex items-center", children: _jsx("span", { children: I18n.getMessage('technologyDetails') }) }), _jsx("p", { className: "mb-4 break-words text-outer-space-crayola dark:text-bright-gray", children: selectedRow.name })] })), _jsxs(_Fragment, { children: [_jsx("p", { className: "font-bold text-granite-gray dark:text-manatee mb-1", children: I18n.getMessage('description') }), _jsx("p", { className: "text-outer-space-crayola dark:text-bright-gray", children: selectedRow?.description || I18n.getMessage('noDescription') })] })] })) : (_jsx("div", { className: "h-full p-8 flex items-center", children: _jsx("p", { className: "text-lg w-full font-bold text-granite-gray dark:text-manatee text-center", children: I18n.getMessage('selectRowToPreview') }) })) })] }));
90
+ };
91
+ export default Technologies;
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * https://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * External dependencies.
19
+ */
20
+ import { BLOCK_STATUS } from '@google-psat/common';
21
+ import { InboundIcon, OutboundIcon, OutboundInboundColoredIcon, OutboundInboundIcon, QuestionMark, GreenTick, } from '@google-psat/design-system';
22
+ const NamePrefixIconSelector = ({ originalData }) => {
23
+ const data = originalData;
24
+ const isDomainInAllowList = data?.isDomainInAllowList;
25
+ if (isDomainInAllowList) {
26
+ return _jsx(GreenTick, {});
27
+ }
28
+ const isInboundBlocked = data?.blockingStatus?.inboundBlock !== undefined &&
29
+ data.blockingStatus.inboundBlock !== BLOCK_STATUS.NOT_BLOCKED;
30
+ const isInboundBlockedInAll = data?.blockingStatus?.inboundBlock === BLOCK_STATUS.BLOCKED_IN_ALL_EVENTS;
31
+ const isOutboundBlocked = data?.blockingStatus?.outboundBlock !== undefined &&
32
+ data.blockingStatus.outboundBlock !== BLOCK_STATUS.NOT_BLOCKED;
33
+ const isOutboundBlockedInAll = data?.blockingStatus?.outboundBlock === BLOCK_STATUS.BLOCKED_IN_ALL_EVENTS;
34
+ const hasValidBlockedReason = data?.blockedReasons && data.blockedReasons.length !== 0;
35
+ if (!hasValidBlockedReason) {
36
+ if (isInboundBlocked || isOutboundBlocked) {
37
+ return _jsx(QuestionMark, {});
38
+ }
39
+ return _jsx(_Fragment, {});
40
+ }
41
+ if (isInboundBlocked && isOutboundBlocked) {
42
+ if (isInboundBlockedInAll && isOutboundBlockedInAll) {
43
+ return _jsx(OutboundInboundIcon, { className: "stroke-[#D8302F] scale-150" });
44
+ }
45
+ if (!isInboundBlockedInAll && !isOutboundBlockedInAll) {
46
+ return _jsx(OutboundInboundIcon, { className: "stroke-[#FE8455] scale-150" });
47
+ }
48
+ if (isInboundBlockedInAll) {
49
+ return _jsx(OutboundInboundColoredIcon, { className: "rotate-180 scale-150" });
50
+ }
51
+ return _jsx(OutboundInboundColoredIcon, { className: "scale-150" });
52
+ }
53
+ if (isInboundBlocked) {
54
+ if (isInboundBlockedInAll) {
55
+ return _jsx(InboundIcon, { className: "stroke-[#D8302F] scale-150" });
56
+ }
57
+ return _jsx(InboundIcon, { className: "stroke-[#FE8455] scale-150" });
58
+ }
59
+ if (isOutboundBlocked) {
60
+ if (isOutboundBlockedInAll) {
61
+ return _jsx(OutboundIcon, { className: "stroke-[#D8302F] scale-150" });
62
+ }
63
+ return _jsx(OutboundIcon, { className: "stroke-[#FE8455] scale-150" });
64
+ }
65
+ return _jsx(_Fragment, {});
66
+ };
67
+ export default NamePrefixIconSelector;
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { calculateEffectiveExpiryDate, } from '@google-psat/common';
17
+ /**
18
+ * Internal dependencies
19
+ */
20
+ const extractCookies = (cookieData, pageUrl, shouldAddUrlToKey = false) => {
21
+ return Object.entries(cookieData).reduce((acc, [frame, _data]) => {
22
+ acc[frame] = Object.fromEntries(Object.entries(_data.frameCookies).map(([key, cookie]) => [
23
+ key + (shouldAddUrlToKey ? '' : pageUrl),
24
+ {
25
+ ...cookie,
26
+ pageUrl,
27
+ parsedCookie: {
28
+ ...cookie.parsedCookie,
29
+ expires: calculateEffectiveExpiryDate(cookie.parsedCookie.expires),
30
+ },
31
+ },
32
+ ]));
33
+ return acc;
34
+ }, {});
35
+ };
36
+ export default extractCookies;
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * Internal dependencies
18
+ */
19
+ import extractCookies from './extractCookies';
20
+ const extractReportData = (data) => {
21
+ const landingPageCookies = {};
22
+ const technologies = [];
23
+ const consolidatedLibraryMatches = {};
24
+ data.forEach(({ cookieData, pageUrl, libraryMatches, technologyData }) => {
25
+ formatCookieData(extractCookies(cookieData, pageUrl, true), landingPageCookies);
26
+ technologies.push(...technologyData.map((technology) => ({
27
+ ...technology,
28
+ pageUrl,
29
+ })));
30
+ consolidatedLibraryMatches[pageUrl] = libraryMatches;
31
+ });
32
+ return {
33
+ landingPageCookies,
34
+ consolidatedLibraryMatches,
35
+ };
36
+ };
37
+ const formatCookieData = (cookieData, store) => {
38
+ Object.entries(cookieData).forEach(([frame, _cData]) => {
39
+ if (!store[frame]) {
40
+ store[frame] = {};
41
+ }
42
+ Object.entries(_cData).forEach(([key, cookie]) => {
43
+ store[frame][key] = {
44
+ ...cookie,
45
+ isBlocked: store[frame][key]?.isBlocked || cookie.isBlocked,
46
+ blockedReasons: [
47
+ ...new Set([
48
+ ...(store[frame][key]?.blockedReasons || []),
49
+ ...(cookie.blockedReasons || []),
50
+ ]),
51
+ ],
52
+ };
53
+ });
54
+ });
55
+ };
56
+ export default extractReportData;
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * External dependencies
18
+ */
19
+ import JSZip from 'jszip';
20
+ import { saveAs } from 'file-saver';
21
+ import { getCurrentDateAndTime } from '@google-psat/common';
22
+ import {} from '@google-psat/design-system';
23
+ /**
24
+ * Internal dependencies
25
+ */
26
+ import { createZip, getFolderName, generateSitemapHTMLFile } from './utils';
27
+ const generateSiteMapReportandDownload = async (JSONReport, appliedFilters, path) => {
28
+ if (!JSONReport.length) {
29
+ return;
30
+ }
31
+ const zip = new JSZip();
32
+ JSONReport.forEach((data) => {
33
+ const zipFolder = zip.folder(`psat_cli_report_${getFolderName(data.pageUrl)}_${getCurrentDateAndTime('YYYY-MM-DD_HH-MM-SS')}`);
34
+ if (!zipFolder) {
35
+ return;
36
+ }
37
+ createZip(data, appliedFilters, zipFolder);
38
+ });
39
+ const report = generateSitemapHTMLFile(JSONReport, appliedFilters);
40
+ zip.file('report.html', report);
41
+ const content = await zip.generateAsync({ type: 'blob' });
42
+ saveAs(content, `psat_cli_report_${getFolderName(path)}_${getCurrentDateAndTime('YYYY-MM-DD_HH-MM-SS')}.zip`);
43
+ };
44
+ export default generateSiteMapReportandDownload;
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * External dependencies
18
+ */
19
+ import JSZip from 'jszip';
20
+ import { saveAs } from 'file-saver';
21
+ import { getCurrentDateAndTime } from '@google-psat/common';
22
+ import {} from '@google-psat/design-system';
23
+ /**
24
+ * Internal dependencies
25
+ */
26
+ import { createZip, getFolderName } from './utils';
27
+ const generateSiteReportandDownload = async (JSONReport, appliedFilters, selectedPageUrl) => {
28
+ if (!JSONReport.length) {
29
+ return;
30
+ }
31
+ const zip = new JSZip();
32
+ let siteAnalysisData;
33
+ if (selectedPageUrl) {
34
+ siteAnalysisData = JSONReport.find(({ pageUrl }) => pageUrl === selectedPageUrl);
35
+ }
36
+ else {
37
+ siteAnalysisData = JSONReport[0];
38
+ }
39
+ const hostName = new URL(siteAnalysisData.pageUrl).hostname;
40
+ // @ts-ignore -- because this data will already be injected from the extension.
41
+ const fileName = globalThis?.PSAT_EXTENSION
42
+ ? `${hostName.replace('.', '-')}-report-${getCurrentDateAndTime('YYYY-MM-DD_HH-MM-SS')}`
43
+ : `psat_cli_report_${getFolderName(JSONReport[0].pageUrl)}_${getCurrentDateAndTime('YYYY-MM-DD_HH-MM-SS')}`;
44
+ const zipFolder = zip.folder(fileName);
45
+ if (!zipFolder) {
46
+ return;
47
+ }
48
+ createZip(siteAnalysisData, appliedFilters, zipFolder);
49
+ const content = await zip.generateAsync({ type: 'blob' });
50
+ saveAs(content, fileName + '.zip');
51
+ };
52
+ export default generateSiteReportandDownload;
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export { default as generateSiteMapReportandDownload } from './generateSiteMapReportandDownload';
17
+ export { default as generateSiteReportandDownload } from './generateSiteReportandDownload';
@@ -0,0 +1,148 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { generateCookiesWithIssuesCSV, generateAllCookiesCSV, generateSummaryDataCSV, generateTechnologyCSV, } from '@google-psat/common';
17
+ import {} from '@google-psat/design-system';
18
+ const generateCSVFiles = (data) => {
19
+ const allCookiesCSV = generateAllCookiesCSV(data);
20
+ let technologyDataCSV = null;
21
+ if (data.technologyData.length > 0) {
22
+ technologyDataCSV = generateTechnologyCSV(data);
23
+ }
24
+ const cookiesWithIssuesDataCSV = generateCookiesWithIssuesCSV(data);
25
+ const summaryDataCSV = generateSummaryDataCSV(data);
26
+ return {
27
+ allCookiesCSV,
28
+ technologyDataCSV,
29
+ cookiesWithIssuesDataCSV,
30
+ summaryDataCSV,
31
+ };
32
+ };
33
+ const generateHTMLFile = (analysisData, appliedFilters) => {
34
+ const parser = new DOMParser();
35
+ const reportDom = parser.parseFromString(`
36
+ <html>
37
+ ${document.documentElement.innerHTML}
38
+ </html>
39
+ `, 'text/html');
40
+ const translations =
41
+ // @ts-ignore
42
+ globalThis?.PSAT_DATA?.translations;
43
+ const previousJSONDATA = reportDom.getElementById('JSONDATASCRIPT');
44
+ const styleNodes = reportDom.querySelectorAll('style');
45
+ if (styleNodes.length > 1) {
46
+ styleNodes.forEach((styleNode, index) => {
47
+ if (index !== 0) {
48
+ reportDom.head.removeChild(styleNode);
49
+ }
50
+ });
51
+ }
52
+ if (previousJSONDATA) {
53
+ reportDom.head.removeChild(previousJSONDATA);
54
+ }
55
+ // Injections
56
+ const script = reportDom.createElement('script');
57
+ const reportData = {
58
+ json: [analysisData],
59
+ type: 'url',
60
+ // @ts-ignore -- because this data will already be injected from cli or the extension.
61
+ selectedSite: globalThis?.PSAT_DATA?.selectedSite ?? '',
62
+ translations,
63
+ appliedFilters,
64
+ // @ts-ignore -- because this data will already be injected from cli or the extension.
65
+ dateTime: globalThis?.PSAT_DATA.dateTime,
66
+ hideDownloadButton: true,
67
+ };
68
+ let code = `window.PSAT_DATA = ${JSON.stringify(reportData)};`;
69
+ // @ts-ignore -- because this data will already be injected from cli or the extension.
70
+ if (globalThis?.PSAT_EXTENSION) {
71
+ code += `window.PSAT_EXTENSION = true;`;
72
+ }
73
+ // @ts-ignore -- because this data will already be injected from the extension.
74
+ code += `window.PSAT_USING_CDP = ${globalThis?.PSAT_USING_CDP ?? undefined};`;
75
+ script.text = code;
76
+ script.id = 'JSONDATASCRIPT';
77
+ reportDom.head.appendChild(script);
78
+ const injectedHtmlText = `<head>${reportDom.head.innerHTML}<head><body>${reportDom.body.innerHTML}</body>`;
79
+ const html = new Blob([injectedHtmlText]);
80
+ return html;
81
+ };
82
+ export const generateSitemapHTMLFile = (analysisData, appliedFilters) => {
83
+ const parser = new DOMParser();
84
+ const reportDom = parser.parseFromString(`
85
+ <html>
86
+ ${document.documentElement.innerHTML}
87
+ </html>
88
+ `, 'text/html');
89
+ const previousJSONDATA = reportDom.getElementById('JSONDATASCRIPT');
90
+ const styleNodes = reportDom.querySelectorAll('style');
91
+ if (styleNodes.length > 1) {
92
+ styleNodes.forEach((styleNode, index) => {
93
+ if (index !== 0) {
94
+ reportDom.head.removeChild(styleNode);
95
+ }
96
+ });
97
+ }
98
+ if (previousJSONDATA) {
99
+ reportDom.head.removeChild(previousJSONDATA);
100
+ }
101
+ // Injections
102
+ const script = reportDom.createElement('script');
103
+ const translations =
104
+ // @ts-ignore
105
+ globalThis?.PSAT_DATA?.translations;
106
+ const reportData = {
107
+ json: analysisData,
108
+ type: 'sitemap',
109
+ // @ts-ignore -- because this data will already be injected from cli or the extension.
110
+ selectedSite: globalThis?.PSAT_DATA?.selectedSite ?? '',
111
+ translations,
112
+ // @ts-ignore -- because this data will already be injected from cli or the extension.
113
+ dateTime: globalThis?.PSAT_DATA.dateTime,
114
+ appliedFilters,
115
+ hideDownloadButton: true,
116
+ };
117
+ const code = `window.PSAT_DATA = ${JSON.stringify(reportData)}`;
118
+ script.text = code;
119
+ script.id = 'JSONDATASCRIPT';
120
+ reportDom.head.appendChild(script);
121
+ const injectedHtmlText = `<head>${reportDom.head.innerHTML}<head><body>${reportDom.body.innerHTML}</body>`;
122
+ const html = new Blob([injectedHtmlText]);
123
+ return html;
124
+ };
125
+ export const createZip = (analysisData, appliedFilters, zipObject) => {
126
+ const { allCookiesCSV, technologyDataCSV, cookiesWithIssuesDataCSV, summaryDataCSV, } = generateCSVFiles(analysisData);
127
+ const file = generateHTMLFile(analysisData, appliedFilters);
128
+ zipObject.file('cookies.csv', allCookiesCSV);
129
+ if (technologyDataCSV) {
130
+ zipObject.file('technologies.csv', technologyDataCSV);
131
+ }
132
+ zipObject.file('cookie-issues.csv', cookiesWithIssuesDataCSV);
133
+ zipObject.file('report.csv', summaryDataCSV);
134
+ zipObject.file('report.json', JSON.stringify(analysisData, null, 4));
135
+ zipObject.file('report.html', file);
136
+ };
137
+ export const getFolderName = (pageUrl) => {
138
+ let folderName = pageUrl
139
+ .trim()
140
+ .replace(/^https?:\/\//, '')
141
+ .replace(/\/+/g, '-')
142
+ .replace(/\./g, '-');
143
+ if (folderName.endsWith('-')) {
144
+ const lastDashIndex = folderName.lastIndexOf('-');
145
+ folderName = folderName.substring(0, lastDashIndex);
146
+ }
147
+ return folderName;
148
+ };
@@ -0,0 +1,102 @@
1
+ /*
2
+ * Copyright 2023 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * External dependencies
18
+ */
19
+ import { deriveBlockingStatus, } from '@google-psat/common';
20
+ import { I18n } from '@google-psat/i18n';
21
+ const reshapeCookies = (cookies) => {
22
+ return Object.entries(cookies)
23
+ .filter(([frame]) => frame.includes('http'))
24
+ .map(([frame, _cookies]) => createCookieObj(frame, _cookies))
25
+ .reduce((acc, cookieObj) => {
26
+ Object.keys(cookieObj).forEach((key) => {
27
+ if (acc[key]) {
28
+ const frameUrls = [
29
+ ...(acc[key]?.frameUrls ?? []),
30
+ ...(cookieObj[key]?.frameUrls ?? []),
31
+ ];
32
+ const blockedReasons = [
33
+ ...new Set([
34
+ ...(acc[key]?.blockedReasons ?? []),
35
+ ...(cookieObj[key]?.blockedReasons ?? []),
36
+ ]),
37
+ ];
38
+ const frameIdList = Array.from(new Set([
39
+ ...(acc[key]?.frameIdList ?? []),
40
+ ...(cookieObj[key]?.frameIdList ?? []),
41
+ ]));
42
+ const networkEvents = {
43
+ requestEvents: [
44
+ ...(cookieObj[key]?.networkEvents?.requestEvents || []),
45
+ ...(acc[key].networkEvents?.requestEvents || []),
46
+ ],
47
+ responseEvents: [
48
+ ...(cookieObj[key]?.networkEvents?.responseEvents || []),
49
+ ...(acc[key].networkEvents?.responseEvents || []),
50
+ ],
51
+ };
52
+ let blockingStatus = deriveBlockingStatus(networkEvents);
53
+ //@ts-ignore -- Since this has to be run for data coming from extension only.
54
+ if (globalThis?.PSAT_EXTENSION) {
55
+ blockingStatus = cookieObj[key].blockingStatus;
56
+ }
57
+ acc[key] = {
58
+ ...cookieObj[key],
59
+ ...acc[key],
60
+ blockedReasons,
61
+ frameIdList,
62
+ exemptionReason: acc[key]?.exemptionReason || cookieObj[key]?.exemptionReason,
63
+ frameUrls,
64
+ networkEvents,
65
+ blockingStatus,
66
+ };
67
+ }
68
+ else {
69
+ acc[key] = cookieObj[key];
70
+ }
71
+ });
72
+ return acc;
73
+ }, {});
74
+ };
75
+ const createCookieObj = (frame, cookies) => Object.fromEntries(Object.values(cookies).map((cookie) => [
76
+ cookie.parsedCookie.name +
77
+ ':' +
78
+ cookie.parsedCookie.domain +
79
+ ':' +
80
+ cookie.parsedCookie.path,
81
+ {
82
+ parsedCookie: cookie.parsedCookie,
83
+ analytics: {
84
+ ...cookie.analytics,
85
+ category: cookie.analytics?.category === 'Unknown Category'
86
+ ? I18n.getMessage('sdUncategorized')
87
+ : cookie.analytics?.category,
88
+ },
89
+ url: cookie.url,
90
+ headerType: 'response',
91
+ blockedReasons: cookie.blockedReasons,
92
+ isFirstParty: cookie.isFirstParty,
93
+ frameIdList: [frame], // Hot fix: For Displaying cookies in CLI Dashboard.
94
+ isBlocked: cookie.isBlocked,
95
+ networkEvents: cookie.networkEvents,
96
+ blockingStatus: cookie.blockingStatus,
97
+ frameUrls: [frame],
98
+ exemptionReason: cookie.exemptionReason,
99
+ pageUrl: cookie.pageUrl,
100
+ },
101
+ ]));
102
+ export default reshapeCookies;