feat: add document viewer widget (#7666)

* created new widget

* new lib for document viewer

* added cypress tests

* updated icon

* handling different url types with viewer

* add to ignore react-documents in jest transformIgnorePatterns

* added jest test, updated comments

* required changes

* updated cypress test

* updated icon svg

* doc viewer new renderers added

* comment as required

* updated test case

* added url / base64 validations

* updated url checking condition for space and updated test case

* cypress selector update

* updated url validations

* Merge branch 'release' into feature/new-document-viewer

* lazy load external lib
This commit is contained in:
Bhavin K 2021-11-29 21:07:49 +05:30 committed by GitHub
parent f6acbf1407
commit 6ea90e7c7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1349 additions and 23 deletions

View File

@ -0,0 +1,45 @@
{
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 1280,
"snapColumns": 64,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0,
"bottomRow": 1230,
"containerStyle": "none",
"snapRows": 125,
"parentRowSpace": 1,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 39,
"minHeight": 1240,
"parentColumnSpace": 1,
"dynamicTriggerPathList": [],
"dynamicBindingPathList": [],
"leftColumn": 0,
"children": [
{
"widgetName": "DocumentViewer1",
"rightColumn": 36,
"isCanvas": false,
"displayName": "Document Viewer",
"iconSVG": "/static/media/icon.5c440258.svg",
"widgetId": "0vgeledo9u",
"topRow": 20,
"bottomRow": 60,
"parentRowSpace": 10,
"isVisible": true,
"type": "DOCUMENT_VIEWER_WIDGET",
"version": 1,
"hideCard": false,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"parentColumnSpace": 19.8125,
"leftColumn": 12,
"docUrl": "https://www.learningcontainer.com/wp-content/uploads/2019/09/sample-pdf-file.pdf",
"key": "gprnooq82y"
}
]
}

View File

@ -0,0 +1,18 @@
const dsl = require("../../../../fixtures/DocumentViewerDsl.json");
const explorer = require("../../../../locators/explorerlocators.json");
describe("DocumentViewer Widget Functionality", function() {
beforeEach(() => {
cy.addDsl(dsl);
});
it("Add new DocumentViewer", () => {
cy.get(explorer.addWidget).click();
cy.dragAndDropToCanvas("documentviewerwidget", { x: 300, y: 300 });
cy.get(".t--widget-documentviewerwidget").should("exist");
});
it("Open Existing DocumentViewer from Widgets list", () => {
cy.get(".t--widget-documentviewerwidget").should("exist");
});
});

View File

@ -15,7 +15,7 @@ module.exports = {
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node", "css"],
moduleDirectories: ["node_modules", "src", "test"],
transformIgnorePatterns: [
"<rootDir>/node_modules/(?!codemirror|react-dnd|dnd-core|@babel|(@blueprintjs/core/lib/esnext)|(@blueprintjs/core/lib/esm)|@github|lodash-es|@draft-js-plugins)",
"<rootDir>/node_modules/(?!codemirror|react-dnd|dnd-core|@babel|(@blueprintjs/core/lib/esnext)|(@blueprintjs/core/lib/esm)|@github|lodash-es|@draft-js-plugins|react-documents)",
],
moduleNameMapper: {
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js",

View File

@ -51,6 +51,7 @@
"draft-js": "^0.11.7",
"emoji-mart": "^3.0.1",
"eslint": "^7.11.0",
"exceljs-lightweight": "^1.14.0",
"fast-deep-equal": "^3.1.1",
"fast-xml-parser": "^3.17.5",
"flow-bin": "^0.148.0",
@ -74,6 +75,7 @@
"lodash-move": "^1.1.1",
"loglevel": "^1.7.1",
"lottie-web": "^5.7.4",
"mammoth": "^1.4.19",
"marked": "^2.0.0",
"memoize-one": "^5.2.1",
"moment": "^2.24.0",
@ -97,6 +99,7 @@
"react-dnd": "^9.3.4",
"react-dnd-html5-backend": "^9.3.4",
"react-dnd-touch-backend": "^9.4.0",
"react-documents": "^1.0.4",
"react-dom": "^16.7.0",
"react-google-maps": "^9.4.5",
"react-google-recaptcha": "^2.1.0",

View File

@ -97,6 +97,9 @@ import AudioWidget, {
import AudioRecorderWidget, {
CONFIG as AUDIO_RECORDER_WIDGET_CONFIG,
} from "widgets/AudioRecorderWidget";
import DocumentViewerWidget, {
CONFIG as DOCUMENT_VIEWER_WIDGET_CONFIG,
} from "widgets/DocumentViewerWidget";
import ButtonGroupWidget, {
CONFIG as BUTTON_GROUP_CONFIG,
} from "widgets/ButtonGroupWidget";
@ -147,6 +150,7 @@ export const registerWidgets = () => {
registerWidget(FilePickerWidgetV2, FILEPICKER_WIDGET_V2_CONFIG);
registerWidget(StatboxWidget, STATBOX_WIDGET_CONFIG);
registerWidget(AudioRecorderWidget, AUDIO_RECORDER_WIDGET_CONFIG);
registerWidget(DocumentViewerWidget, DOCUMENT_VIEWER_WIDGET_CONFIG);
registerWidget(ButtonGroupWidget, BUTTON_GROUP_CONFIG);
registerWidget(MultiSelectTreeWidget, MULTI_SELECT_TREE_WIDGET_CONFIG);
registerWidget(SingleSelectTreeWidget, SINGLE_SELECT_TREE_WIDGET_CONFIG);

View File

@ -0,0 +1,53 @@
import React, { useEffect, useState } from "react";
import mammoth from "mammoth";
import styled from "styled-components";
import Interweave from "interweave";
const StyledViewer = styled.div`
width: 100%;
height: 100%;
background: #fff;
overflow: auto;
`;
export default function DocViewer(props: { blob?: Blob }) {
const [state, setState] = useState({ isLoading: false, isError: false });
const [htmlContent, setHtmlContent] = useState("");
// when DocViewer gets new Blob of uploaded file convert it to html for preview
useEffect(() => {
setState({ isLoading: true, isError: false });
setHtmlContent("");
props.blob
?.arrayBuffer()
.then((buffer) => {
mammoth
.convertToHtml(
{ arrayBuffer: buffer },
{ includeEmbeddedStyleMap: true, includeDefaultStyleMap: true },
)
.then((result) => {
setState({ isLoading: false, isError: false });
setHtmlContent(result.value);
})
.catch(() => {
setHtmlContent("");
setState({ isLoading: false, isError: true });
});
})
.catch(() => {
setState({ isLoading: false, isError: false });
setHtmlContent("");
});
}, [props.blob]);
return (
<StyledViewer>
<Interweave content={htmlContent} />
{state.isLoading ? (
<div>Loading...</div>
) : state.isError ? (
<div>Failed to read docx content</div>
) : (
<div />
)}
</StyledViewer>
);
}

View File

@ -0,0 +1,204 @@
import React, { useEffect, useState, useRef, useCallback } from "react";
import styled from "styled-components";
import Excel from "exceljs-lightweight";
import { useTable, Column } from "react-table";
import _ from "lodash";
const StyledViewer = styled.div`
width: 100%;
height: 100%;
background: #fff;
overflow: auto;
table {
border: 1px solid #b0cbef;
border-width: 1px 0 0 1px;
border-spacing: 0;
border-collapse: collapse;
padding: 10px;
th {
font-weight: 700;
font-size: 14px;
border: 1px solid #9eb6ce;
border-width: 0 1px 1px 0;
height: 17px;
line-height: 17px;
text-align: center;
background: #9eb6ce4d;
}
td {
background-color: #fff;
padding: 0 4px 0 2px;
border: 1px solid #d0d7e5;
border-width: 0 1px 1px 0;
}
}
`;
const chars = [
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
// get excel column name from index, e.g. A,B,...,AA,AB
const numberToExcelHeader = (index: number): string => {
index -= 1;
const quotient = Math.floor(index / 26);
if (quotient > 0) {
return numberToExcelHeader(quotient) + chars[index % 26];
}
return chars[index % 26];
};
type sheetsDataType = {
name: string;
id: number;
};
export default function XlsxViewer(props: { blob?: Blob }) {
const [sheets, setSheets] = useState([] as sheetsDataType[]);
const [tableData, setTableData] = useState([]);
const [headerData, setHeaderData] = useState([] as Column[]);
const workbook = useRef(new Excel.Workbook());
useEffect(() => {
props.blob?.arrayBuffer().then((buffer) => {
// read excel
workbook.current.xlsx.load(buffer).then(() => {
const newSheets = [] as any;
// get all sheets from excel
workbook.current.eachSheet((sheet, id) => {
newSheets.push({ name: sheet.name, id });
});
setSheets(newSheets);
// get 1st sheet data
getSheetData(1);
});
});
}, [props.blob]);
// get provided sheet data, read all row and columns
const getSheetData = useCallback((sheetId: number) => {
const worksheet = workbook.current.getWorksheet(sheetId);
// collect all row data
const data = [] as any;
worksheet.eachRow({ includeEmpty: true }, (row) => {
const currRow = {} as any;
// read value of each cell of current row
row.eachCell((cell) => {
// value can be merged value | Date | formula result | string | number
let value: any;
if (cell.isMerged) {
value = _.get(cell, "_mergeCount") ? cell.value : "";
} else {
value = cell.value;
}
if (_.isDate(value)) {
value = value.toDateString();
} else if (_.isObject(value) && _.has(value, "result")) {
value = _.get(value, "result", "");
}
currRow[String(numberToExcelHeader(Number(cell.col)))] = value;
});
data.push(currRow);
});
setTableData(data);
if (data.length) {
// create header letters based on columnCount
const newHeader = [];
for (let index = 1; index <= worksheet.columnCount; index++) {
const currHeader = numberToExcelHeader(index);
newHeader.push({
Header: currHeader,
accessor: currHeader,
});
}
setHeaderData(newHeader);
} else {
setHeaderData([]);
}
}, []);
// when user click on another sheet, re-generate data
const updateSheet = useCallback(
(sheetId) => () => {
getSheetData(sheetId);
},
[],
);
const {
getTableBodyProps,
getTableProps,
headerGroups,
prepareRow,
rows,
} = useTable({ columns: headerData, data: tableData });
return (
<StyledViewer>
<div>
{sheets.map((sheet) => (
<button key={sheet.id} onClick={updateSheet(sheet.id)}>
{sheet.name}
</button>
))}
</div>
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup, hgInd) => (
<tr {...headerGroup.getHeaderGroupProps()} key={hgInd}>
{headerGroup.headers.map((column, colId) => (
<th {...column.getHeaderProps()} key={colId}>
{column.render("Header")}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, rInd) => {
prepareRow(row);
return (
<tr {...row.getRowProps()} key={rInd}>
{row.cells.map((cell, ind) => {
return (
<td {...cell.getCellProps()} key={ind}>
{cell.render("Cell")}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</StyledViewer>
);
}

View File

@ -0,0 +1,68 @@
import { getDocViewerConfigs } from "widgets/DocumentViewerWidget/component";
import { Renderers } from "../constants";
describe("validate document viewer url", () => {
it("validate correct config should return for extension based urls", () => {
const input = [
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.docx",
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.odt",
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.rtf",
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.pdf",
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.txt",
];
const expected = [
{
url:
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.docx",
viewer: "office",
errorMessage: "",
renderer: Renderers.DOCUMENT_VIEWER,
},
{
url:
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.odt",
viewer: "url",
errorMessage: "Current file type is not supported",
renderer: Renderers.ERROR,
},
{
url:
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.rtf",
viewer: "url",
errorMessage: "Current file type is not supported",
renderer: Renderers.ERROR,
},
{
url:
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.pdf",
viewer: "url",
errorMessage: "",
renderer: Renderers.DOCUMENT_VIEWER,
},
{
url:
"https://roteemealplancover.s3.ap-south-1.amazonaws.com/sample/Project+proposal.txt",
viewer: "url",
errorMessage: "",
renderer: Renderers.DOCUMENT_VIEWER,
},
];
for (let index = 0; index < input.length; index++) {
const result = getDocViewerConfigs(input[index]);
expect(result).toStrictEqual(expected[index]);
}
});
it("validate errorMessage should return for empty url", () => {
const input = "";
const result = getDocViewerConfigs(input);
expect(result).toStrictEqual({
url: "",
viewer: "url",
errorMessage: "No document url provided for viewer",
renderer: Renderers.ERROR,
});
});
});

View File

@ -0,0 +1,220 @@
import React, { Suspense, lazy } from "react";
import styled from "styled-components";
import { DocumentViewer } from "react-documents";
import { includes, replace, split, get } from "lodash";
import {
SUPPORTED_EXTENSIONS,
Renderers,
Renderer,
ViewerType,
} from "../constants";
import { retryPromise } from "utils/AppsmithUtils";
import Skeleton from "components/utils/Skeleton";
const DocViewer = lazy(() => retryPromise(() => import("./DocViewer")));
const XlsxViewer = lazy(() => retryPromise(() => import("./XlsxViewer")));
const ErrorWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
background: #fff;
`;
const checkUrlExtension = (docUrl: string) => {
// Remove everything to the last slash in URL
let url = docUrl.substr(1 + docUrl.lastIndexOf("/"));
// Break URL at ? and take first part (file name, extension)
url = url.split("?")[0];
// Sometimes URL doesn't have ? but #, so we should aslo do the same for #
url = url.split("#")[0];
// Now we have only filename and extension
const chunkList = url.split(".");
if (chunkList.length > 1) {
const ext = chunkList[chunkList.length - 1];
// check extension is valid or not
const validExtension = SUPPORTED_EXTENSIONS.includes(ext);
return {
hasExtension: true,
validExtension: validExtension,
extension: ext,
};
} else {
// might be preview url
return { hasExtension: false };
}
};
const getBlob = (docUrl: string) => {
// Split into two parts
const parts = docUrl.split(";base64,");
// Hold the content type
const mimeType = parts[0].split(":")[1];
try {
// Decode Base64 string
const decodedData = window.atob(parts[1]);
// Create UNIT8ARRAY of size same as row data length
const uInt8Array = new Uint8Array(decodedData.length);
// Insert all character code into uInt8Array
for (let i = 0; i < decodedData.length; ++i) {
uInt8Array[i] = decodedData.charCodeAt(i);
}
// Return BLOB image after conversion
const blob = new Blob([uInt8Array], { type: mimeType });
return blob;
} catch (error) {
return;
}
};
// get extension from base64
const getFileExtensionFromBase64 = (docUrl: string) => {
let extension = "";
const fileType = docUrl.split(";")[0].split("/")[1];
switch (fileType) {
case "vnd.openxmlformats-officedocument.wordprocessingml.document":
extension = "docx";
break;
case "vnd.openxmlformats-officedocument.spreadsheetml.sheet":
extension = "xlsx";
break;
case "plain":
extension = "txt";
break;
case "pdf":
extension = "pdf";
break;
default:
break;
}
return extension;
};
interface ConfigResponse {
url: string;
blob?: Blob;
viewer: ViewerType;
renderer: Renderer;
errorMessage?: string;
}
export const getDocViewerConfigs = (docUrl: string): ConfigResponse => {
/**
* From user provided document url decide on which viewer to use
* handle different cases for url hosts
* Case 1: Dropbox
* if user exported download url than change that to raw url
* Case 2: Onedrive
* change url to embeded url to show in viewer
* Case 3:
* All other urls will be either Google Preview or urls with file extentions ( e.x. from aws s3 )
* need to verify urls with extention and use default viewer "url viewer" for them
*/
let viewer = "url" as ViewerType;
let url = docUrl;
let blob;
let errorMessage = !!docUrl ? "" : "No document url provided for viewer";
let renderer: Renderer = errorMessage
? Renderers.ERROR
: Renderers.DOCUMENT_VIEWER;
if (docUrl && includes(docUrl, "base64")) {
const extension = getFileExtensionFromBase64(docUrl);
const isValidExtension = SUPPORTED_EXTENSIONS.includes(extension);
if (isValidExtension) {
blob = getBlob(docUrl);
if (blob) {
if (extension === "docx") {
renderer = Renderers.DOCX_VIEWER;
} else if (extension === "xlsx") {
renderer = Renderers.XLSX_VIEWER;
}
} else {
errorMessage = "invalid base64 data";
renderer = Renderers.ERROR;
}
} else {
errorMessage = "Current file type is not supported " + extension;
renderer = Renderers.ERROR;
}
return { blob, url, viewer, errorMessage, renderer };
}
// handled dropbox url
if (includes(url, "dropbox.com")) {
if (includes(url, "?dl=0") || !includes(url, "?raw=1")) {
url = replace(url, "?dl=0", "");
url = url + "?raw=1";
}
return { url, viewer, renderer };
}
// handled onedrive url
if (includes(url, "onedrive.live.com")) {
const onedriveUrl = new URL(url);
const onedriveUrlParamList = split(onedriveUrl.search, /[?&=]+/);
const cid = get(
onedriveUrlParamList,
onedriveUrlParamList.indexOf("cid") + 1,
);
const resid = get(
onedriveUrlParamList,
onedriveUrlParamList.indexOf("id") + 1,
);
url = `https://onedrive.live.com/embed?cid=${cid}&resid=${resid}&em=2`;
return { url, viewer, renderer };
}
// check url extension and if it is supported
const { extension, hasExtension, validExtension } = checkUrlExtension(url);
if (hasExtension) {
if (validExtension) {
if (!(extension === "txt" || extension === "pdf")) {
viewer = "office";
renderer = Renderers.DOCUMENT_VIEWER;
}
} else {
errorMessage = "Current file type is not supported";
renderer = Renderers.ERROR;
}
}
return { url, viewer, errorMessage, renderer };
};
function DocumentViewerComponent(props: DocumentViewerComponentProps) {
const { blob, errorMessage, renderer, url, viewer } = React.useMemo(
() => getDocViewerConfigs(props.docUrl),
[props.docUrl],
);
switch (renderer) {
case Renderers.ERROR:
return <ErrorWrapper>{errorMessage}</ErrorWrapper>;
case Renderers.DOCX_VIEWER:
return (
<Suspense fallback={<Skeleton />}>
<DocViewer blob={blob} />
</Suspense>
);
case Renderers.XLSX_VIEWER:
return (
<Suspense fallback={<Skeleton />}>
<XlsxViewer blob={blob} />
</Suspense>
);
case Renderers.DOCUMENT_VIEWER:
return <DocumentViewer url={url} viewer={viewer} />;
default:
return null;
}
}
export interface DocumentViewerComponentProps {
docUrl: string;
}
export default DocumentViewerComponent;

View File

@ -0,0 +1,23 @@
// This file contains common constants which can be used across the widget configuration file (index.ts), widget and component folders.
export const DOCUMENTVIEWER_WIDGET_CONSTANT = "";
// txt and pdf handle by viewerType = "url"
// and other types handle by viewerType = "office"
export const SUPPORTED_EXTENSIONS = [
"txt",
"pdf",
"docx",
"ppt",
"pptx",
"xlsx",
];
export const Renderers = {
DOCUMENT_VIEWER: "DOCUMENT_VIEWER",
DOCX_VIEWER: "DOCX_VIEWER",
XLSX_VIEWER: "XLSX_VIEWER",
ERROR: "ERROR",
};
export type Renderer = typeof Renderers[keyof typeof Renderers];
export type ViewerType = "google" | "office" | "mammoth" | "pdf" | "url";

View File

@ -0,0 +1,6 @@
<svg width="22" height="27" viewBox="0 0 22 27" fill="#4b4848" xmlns="http://www.w3.org/2000/svg">
<path d="M4.66675 16.2654H5.69897V14.7103H6.70044C7.7395 14.7103 8.43335 14.0403 8.43335 13.0252V13.0184C8.43335 12.0032 7.7395 11.3333 6.70044 11.3333H4.66675V16.2654ZM6.44751 12.1502C7.03882 12.1502 7.38745 12.4612 7.38745 13.0218V13.0286C7.38745 13.5892 7.03882 13.9036 6.44751 13.9036H5.69897V12.1502H6.44751Z"/>
<path d="M9.16201 16.2654H11.1034C12.58 16.2654 13.4174 15.3631 13.4174 13.7703V13.7635C13.4174 12.2186 12.5697 11.3333 11.1034 11.3333H9.16201V16.2654ZM10.1942 15.4144V12.1844H10.9394C11.8349 12.1844 12.3646 12.7654 12.3646 13.7806V13.7874C12.3646 14.8401 11.8519 15.4144 10.9394 15.4144H10.1942Z"/>
<path d="M14.1768 16.2654H15.209V14.324H17.2154V13.5071H15.209V12.1844H17.4068V11.3333H14.1768V16.2654Z"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 26.6667H21.3333V0H4.80651L0 4.83331V26.6667ZM18.6667 24H2.66667V6.33331L6.16675 2.66667H18.6667V24Z"/>
</svg>

After

Width:  |  Height:  |  Size: 986 B

View File

@ -0,0 +1,27 @@
import Widget from "./widget";
import IconSVG from "./icon.svg";
import { GRID_DENSITY_MIGRATION_V1 } from "widgets/constants";
export const CONFIG = {
type: Widget.getWidgetType(),
name: "Document Viewer", // The display name which will be made in uppercase and show in the widgets panel ( can have spaces )
iconSVG: IconSVG,
needsMeta: false, // Defines if this widget adds any meta properties
isCanvas: false, // Defines if this widget has a canvas within in which we can drop other widgets
defaults: {
widgetName: "DocumentViewer",
docUrl:
"https://www.learningcontainer.com/wp-content/uploads/2019/09/sample-pdf-file.pdf",
rows: 10 * GRID_DENSITY_MIGRATION_V1,
columns: 6 * GRID_DENSITY_MIGRATION_V1,
version: 1,
},
properties: {
derived: Widget.getDerivedPropertiesMap(),
default: Widget.getDefaultPropertiesMap(),
meta: Widget.getMetaPropertiesMap(),
config: Widget.getPropertyPaneConfig(),
},
};
export default Widget;

View File

@ -0,0 +1,127 @@
import { documentUrlValidation } from ".";
describe("validate propertypane input : docUrl", () => {
it("validation for empty or space value", () => {
const input1 = "";
const expected1 = {
isValid: true,
parsed: "",
messages: [""],
};
const result = documentUrlValidation(input1);
expect(result).toStrictEqual(expected1);
const input2 = "https: //www.example.com";
const expected2 = {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
const result1 = documentUrlValidation(input2);
expect(result1).toStrictEqual(expected2);
const input3 = "https://www.exam ple.com";
const expected3 = {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
const result2 = documentUrlValidation(input3);
expect(result2).toStrictEqual(expected3);
const input4 = "https://examplecom";
const expected4 = {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
const result3 = documentUrlValidation(input4);
expect(result3).toStrictEqual(expected4);
const input6 = "://www.appsmith.com/docs/sample.pdf";
const expected6 = {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
const result5 = documentUrlValidation(input6);
expect(result5).toStrictEqual(expected6);
});
it("validation for invalid url or base64 value", () => {
const input1 = "htt";
const expected1 = {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
const result1 = documentUrlValidation(input1);
expect(result1).toStrictEqual(expected1);
const input2 = "data:application/pdf;base64";
const expected2 = {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
const result2 = documentUrlValidation(input2);
expect(result2).toStrictEqual(expected2);
});
it("validation for valid url or base64 value", () => {
const input1 = "https://www.example.com";
const expected1 = {
isValid: true,
parsed: "https://www.example.com/",
};
const result1 = documentUrlValidation(input1);
expect(result1).toStrictEqual(expected1);
const input2 =
"data:application/pdf;base64,JVBERi0xLjIgCjkgMCBvYmoKPDwKPj4Kc3RyZWFtCkJULyAzMiBUZiggIFlPVVIgVEVYVCBIRVJFICAgKScgRVQKZW5kc3RyZWFtCmVuZG9iago0IDAgb2JqCjw8Ci9UeXBlIC9QYWdlCi9QYXJlbnQgNSAwIFIKL0NvbnRlbnRzIDkgMCBSCj4+CmVuZG9iago1IDAgb2JqCjw8Ci9LaWRzIFs0IDAgUiBdCi9Db3VudCAxCi9UeXBlIC9QYWdlcwovTWVkaWFCb3ggWyAwIDAgMjUwIDUwIF0KPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1BhZ2VzIDUgMCBSCi9UeXBlIC9DYXRhbG9nCj4+CmVuZG9iagp0cmFpbGVyCjw8Ci9Sb290IDMgMCBSCj4+CiUlRU9G";
const expected2 = {
isValid: true,
parsed: input2,
};
const result2 = documentUrlValidation(input2);
expect(result2).toStrictEqual(expected2);
const input3 = "https:www.appsmith.com/docs/sample.pdf";
const expected3 = {
isValid: true,
parsed: "https://www.appsmith.com/docs/sample.pdf",
};
const result3 = documentUrlValidation(input3);
expect(result3).toStrictEqual(expected3);
const input4 = "https://www.apsmith.com/docs/sample";
const expected4 = {
isValid: true,
parsed: "https://www.apsmith.com/docs/sample",
};
const result4 = documentUrlValidation(input4);
expect(result4).toStrictEqual(expected4);
const input5 =
"www.learningcontainer.com/wp-content/uploads/2019/09/sample-pdf-file.pdf";
const expected5 = {
isValid: true,
parsed:
"https://www.learningcontainer.com/wp-content/uploads/2019/09/sample-pdf-file.pdf",
};
const result5 = documentUrlValidation(input5);
expect(result5).toStrictEqual(expected5);
});
});

View File

@ -0,0 +1,121 @@
import React from "react";
import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget";
import DocumentViewerComponent from "../component";
import {
ValidationTypes,
ValidationResponse,
} from "constants/WidgetValidation";
import { AutocompleteDataType } from "utils/autocomplete/TernServer";
export function documentUrlValidation(value: unknown): ValidationResponse {
// applied validations if value exist
if (value) {
const whiteSpaceRegex = /\s/g;
const urlRegex = /(?:https:\/\/|www)?([\da-z.-]+)\.([a-z.]{2,6})[/\w .-]*\/?/;
const base64Regex = /^\s*data:([a-z]+\/[a-z]+(;[a-z\-]+\=[a-z\-]+)?)?(;base64)?,[a-z0-9\!\$\&\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i;
if (
urlRegex.test(value as string) &&
!whiteSpaceRegex.test(value as string)
) {
if ((value as string).startsWith("www")) {
return {
isValid: true,
parsed: "https://" + value,
};
}
try {
const newUrl = new URL(value as string);
// URL is valid
return {
isValid: true,
parsed: newUrl.href,
};
} catch (error) {
return {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
}
} else if (base64Regex.test(value as string)) {
// base 64 is valid
return {
isValid: true,
parsed: value,
};
} else {
// value is not valid URL / Base64
return {
isValid: false,
parsed: "",
messages: ["Provided URL / Base64 is invalid."],
};
}
}
// value is empty here
return {
isValid: true,
parsed: "",
messages: [""],
};
}
class DocumentViewerWidget extends BaseWidget<
DocumentViewerWidgetProps,
WidgetState
> {
static getPropertyPaneConfig() {
return [
{
sectionName: "General",
children: [
{
helpText:
"Document url for preview. for URL, supported extensions are txt, pdf, docx, ppt, pptx, xlsx. ppt is currently not supported by base64.",
propertyName: "docUrl",
label: "Document Link",
controlType: "INPUT_TEXT",
placeholderText: "URL / Base64",
isBindProperty: true,
isTriggerProperty: false,
validation: {
type: ValidationTypes.FUNCTION,
params: {
fn: documentUrlValidation,
expected: {
type: "URL / Base64",
example: "https://www.example.com",
autocompleteDataType: AutocompleteDataType.STRING,
},
},
},
},
{
helpText: "Controls visibility of the widget",
propertyName: "isVisible",
label: "Visible",
controlType: "SWITCH",
isJSConvertible: true,
isBindProperty: true,
isTriggerProperty: false,
validation: { type: ValidationTypes.BOOLEAN },
},
],
},
];
}
getPageView() {
return <DocumentViewerComponent docUrl={this.props.docUrl} />;
}
static getWidgetType(): string {
return "DOCUMENT_VIEWER_WIDGET";
}
}
export interface DocumentViewerWidgetProps extends WidgetProps {
docUrl: string;
}
export default DocumentViewerWidget;

View File

@ -4075,6 +4075,35 @@ arch@^2.2.0:
resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
archiver-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
dependencies:
glob "^7.1.4"
graceful-fs "^4.2.0"
lazystream "^1.0.0"
lodash.defaults "^4.2.0"
lodash.difference "^4.5.0"
lodash.flatten "^4.4.0"
lodash.isplainobject "^4.0.6"
lodash.union "^4.6.0"
normalize-path "^3.0.0"
readable-stream "^2.0.0"
archiver@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.1.1.tgz#9db7819d4daf60aec10fe86b16cb9258ced66ea0"
integrity sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==
dependencies:
archiver-utils "^2.1.0"
async "^2.6.3"
buffer-crc32 "^0.2.1"
glob "^7.1.4"
readable-stream "^3.4.0"
tar-stream "^2.1.0"
zip-stream "^2.1.2"
are-we-there-yet@~1.1.2:
version "1.1.5"
resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz"
@ -4093,6 +4122,14 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
arguments-extended@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/arguments-extended/-/arguments-extended-0.0.3.tgz#6107e4917d0eb6f0a4dd66320fc15afc72ef4946"
integrity sha1-YQfkkX0OtvCk3WYyD8Fa/HLvSUY=
dependencies:
extended "~0.0.3"
is-extended "~0.0.8"
aria-query@^4.2.2:
version "4.2.2"
resolved "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz"
@ -4121,6 +4158,15 @@ array-each@^1.0.1:
resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f"
integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8=
array-extended@~0.0.3, array-extended@~0.0.4, array-extended@~0.0.5:
version "0.0.11"
resolved "https://registry.yarnpkg.com/array-extended/-/array-extended-0.0.11.tgz#d7144ae748de93ca726f121009dbff1626d164bd"
integrity sha1-1xRK50jek8pybxIQCdv/FibRZL0=
dependencies:
arguments-extended "~0.0.3"
extended "~0.0.3"
is-extended "~0.0.3"
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz"
@ -4267,9 +4313,10 @@ async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz"
async@^2.6.2:
async@^2.6.2, async@^2.6.3:
version "2.6.3"
resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
dependencies:
lodash "^4.17.14"
@ -4528,6 +4575,11 @@ base64-js@^1.0.2:
version "1.3.1"
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz"
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
base@^0.11.1:
version "0.11.2"
resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz"
@ -4569,6 +4621,11 @@ bfj@^7.0.2:
hoopy "^0.1.4"
tryer "^1.0.1"
big-integer@^1.6.17:
version "1.6.51"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz"
@ -4581,12 +4638,29 @@ binary-extensions@^2.0.0:
version "2.1.0"
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz"
binary@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=
dependencies:
buffers "~0.1.1"
chainsaw "~0.1.0"
bindings@^1.5.0:
version "1.5.0"
resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz"
dependencies:
file-uri-to-path "1.0.0"
bl@^4.0.3:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
dependencies:
buffer "^5.5.0"
inherits "^2.0.4"
readable-stream "^3.4.0"
blob-util@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
@ -4596,6 +4670,11 @@ bluebird@^3.5.5, bluebird@^3.7.2:
version "3.7.2"
resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz"
bluebird@~3.4.0, bluebird@~3.4.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
version "4.12.0"
resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz"
@ -4759,14 +4838,20 @@ bser@2.1.1:
dependencies:
node-int64 "^0.4.0"
buffer-crc32@~0.2.3:
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-from@1.x, buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz"
buffer-indexof-polyfill@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
buffer-indexof@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz"
@ -4783,6 +4868,19 @@ buffer@^4.3.0:
ieee754 "^1.1.4"
isarray "^1.0.0"
buffer@^5.1.0, buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.1.13"
buffers@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s=
builtin-modules@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz"
@ -4965,6 +5063,13 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz"
chainsaw@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=
dependencies:
traverse ">=0.3.0 <0.4"
chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
@ -5466,6 +5571,16 @@ compose-function@3.0.3:
dependencies:
arity-n "^1.0.4"
compress-commons@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-2.1.1.tgz#9410d9a534cf8435e3fbbb7c6ce48de2dc2f0610"
integrity sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==
dependencies:
buffer-crc32 "^0.2.13"
crc32-stream "^3.0.1"
normalize-path "^3.0.0"
readable-stream "^2.3.6"
compressible@~2.0.16:
version "2.0.18"
resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz"
@ -5688,6 +5803,21 @@ craco-babel-loader@^0.1.4:
dependencies:
"@craco/craco" "^5.0.0"
crc32-stream@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85"
integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==
dependencies:
crc "^3.4.4"
readable-stream "^3.4.0"
crc@^3.4.4:
version "3.8.0"
resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
dependencies:
buffer "^5.1.0"
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz"
@ -6130,6 +6260,15 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
date-extended@~0.0.3:
version "0.0.6"
resolved "https://registry.yarnpkg.com/date-extended/-/date-extended-0.0.6.tgz#23802d57dd1bf7818813fe0c32e851a86da267c9"
integrity sha1-I4AtV90b94GIE/4MMuhRqG2iZ8k=
dependencies:
array-extended "~0.0.3"
extended "~0.0.3"
is-extended "~0.0.3"
date-fns@^1.27.2:
version "1.30.1"
resolved "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz"
@ -6147,6 +6286,11 @@ dayjs@^1.10.4, dayjs@^1.10.6:
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.6.tgz#288b2aa82f2d8418a6c9d4df5898c0737ad02a63"
integrity sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==
dayjs@^1.8.15:
version "1.10.7"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468"
integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
@ -6200,6 +6344,11 @@ decimal.js@^10.2.0:
version "10.2.1"
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz"
declare.js@~0.0.4:
version "0.0.8"
resolved "https://registry.yarnpkg.com/declare.js/-/declare.js-0.0.8.tgz#0478adff9564c004f51df73d8bc134019d28dcde"
integrity sha1-BHit/5VkwAT1Hfc9i8E0AZ0o3N4=
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz"
@ -6391,6 +6540,11 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
dingbat-to-unicode@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz#5091dd673241453e6b5865e26e5a4452cdef5c83"
integrity sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
@ -6579,6 +6733,20 @@ draft-js@^0.11.7:
immutable "~3.7.4"
object-assign "^4.1.1"
duck@^0.1.12:
version "0.1.12"
resolved "https://registry.yarnpkg.com/duck/-/duck-0.1.12.tgz#de7adf758421230b6d7aee799ce42670586b9efa"
integrity sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==
dependencies:
underscore "^1.13.1"
duplexer2@~0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
dependencies:
readable-stream "^2.0.2"
duplexer@^0.1.1:
version "0.1.2"
resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
@ -6682,9 +6850,10 @@ encoding@^0.1.11:
dependencies:
iconv-lite "^0.6.2"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
@ -6854,6 +7023,11 @@ es6-iterator@2.0.3, es6-iterator@~2.0.3:
es5-ext "^0.10.35"
es6-symbol "^3.1.1"
es6-promise@^3.0.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=
es6-symbol@^3.1.1, es6-symbol@~3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz"
@ -7235,6 +7409,20 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
exceljs-lightweight@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/exceljs-lightweight/-/exceljs-lightweight-1.14.0.tgz#0535209784ef00159b7820fbf12012f0be56255d"
integrity sha512-piaCFqJVC4d/8iaiH4RhGmRHDMf5cDDe4DZT8dwoIb2fxH0sYzQ4NsdgyTZ713A9rt2I3XM2G20m+Or37vmfxA==
dependencies:
archiver "^3.0.0"
dayjs "^1.8.15"
fast-csv "^2.4.1"
jszip "^3.1.5"
promish "^5.1.1"
sax "^1.2.4"
tmp "^0.1.0"
unzipper "^0.9.12"
exec-sh@^0.3.2:
version "0.3.4"
resolved "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz"
@ -7381,6 +7569,20 @@ extend@^3.0.0, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz"
extended@0.0.6, extended@~0.0.3:
version "0.0.6"
resolved "https://registry.yarnpkg.com/extended/-/extended-0.0.6.tgz#7fb8bf7b9dae397586e48570acfd642c78e50669"
integrity sha1-f7i/e52uOXWG5IVwrP1kLHjlBmk=
dependencies:
extender "~0.0.5"
extender@~0.0.5:
version "0.0.10"
resolved "https://registry.yarnpkg.com/extender/-/extender-0.0.10.tgz#589c07482be61a1460b6d81f9c24aa67e8f324cd"
integrity sha1-WJwHSCvmGhRgttgfnCSqZ+jzJM0=
dependencies:
declare.js "~0.0.4"
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz"
@ -7428,6 +7630,17 @@ factory.ts@^0.5.1:
clone-deep "^4.0.1"
source-map-support "^0.5.9"
fast-csv@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-2.5.0.tgz#5332dfede3f59340cb8e9f46b2e6dff1e7612005"
integrity sha512-M/9ezLU9/uDwvDZTt9sNFJa0iLDUsbhYJwPtnE0D9MjeuB6DY9wRCyUPZta9iI6cSz5wBWGaUPL61QH8h92cNA==
dependencies:
extended "0.0.6"
is-extended "0.0.10"
object-extended "0.0.7"
safer-buffer "^2.1.2"
string-extended "0.0.8"
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
@ -7819,6 +8032,11 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-extra@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
@ -7898,6 +8116,16 @@ fsevents@~2.3.1, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
fstream@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
mkdirp ">=0.5 0"
rimraf "2"
fsu@^1.0.2:
version "1.1.1"
resolved "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz"
@ -8633,6 +8861,11 @@ identity-obj-proxy@3.0.0:
dependencies:
harmony-reflect "^1.4.6"
ieee754@^1.1.13:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
ieee754@^1.1.4:
version "1.1.13"
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz"
@ -8747,7 +8980,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
@ -9052,6 +9285,13 @@ is-extendable@^1.0.1:
dependencies:
is-plain-object "^2.0.4"
is-extended@0.0.10, is-extended@~0.0.3, is-extended@~0.0.8:
version "0.0.10"
resolved "https://registry.yarnpkg.com/is-extended/-/is-extended-0.0.10.tgz#244e140df75bb1c9a3106f412ff182fb534a6d62"
integrity sha1-JE4UDfdbscmjEG9BL/GC+1NKbWI=
dependencies:
extended "~0.0.3"
is-extglob@^2.1.0, is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
@ -10033,6 +10273,16 @@ jszip@^3.1.3:
readable-stream "~2.3.6"
set-immediate-shim "~1.0.1"
jszip@^3.1.5, jszip@^3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9"
integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==
dependencies:
lie "~3.3.0"
pako "~1.0.2"
readable-stream "~2.3.6"
set-immediate-shim "~1.0.1"
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz"
@ -10102,6 +10352,13 @@ lazy-cache@^1.0.3:
version "1.0.4"
resolved "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz"
lazystream@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638"
integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==
dependencies:
readable-stream "^2.0.5"
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz"
@ -10194,6 +10451,11 @@ lint-staged@^9.2.5:
string-argv "^0.3.0"
stringify-object "^3.3.0"
listenercount@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=
listr-silent-renderer@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz"
@ -10340,10 +10602,25 @@ lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
lodash.difference@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
lodash.escape@^4.0.1:
version "4.0.1"
resolved "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz"
lodash.flatten@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
lodash.flow@^3.3.0:
version "3.5.0"
resolved "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz"
@ -10407,6 +10684,11 @@ lodash.topath@^4.5.2:
resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009"
integrity sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=
lodash.union@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz"
@ -10479,6 +10761,15 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lop@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/lop/-/lop-0.4.1.tgz#744f1696ef480e68ce1947fe557b09db5af2a738"
integrity sha512-9xyho9why2A2tzm5aIcMWKvzqKsnxrf9B5I+8O30olh6lQU8PH978LqZoI4++37RBgS1Em5i54v1TFs/3wnmXQ==
dependencies:
duck "^0.1.12"
option "~0.2.1"
underscore "^1.13.1"
lottie-web@^5.7.4:
version "5.7.4"
resolved "https://registry.npmjs.org/lottie-web/-/lottie-web-5.7.4.tgz"
@ -10579,6 +10870,21 @@ makeerror@1.0.x:
dependencies:
tmpl "1.0.x"
mammoth@^1.4.19:
version "1.4.19"
resolved "https://registry.yarnpkg.com/mammoth/-/mammoth-1.4.19.tgz#7a4d82e0656a824a568746df5fafefdee78c892e"
integrity sha512-VgqsTvBeA1JrNDYMLp+QX5LQPkVPOgl+TKCDklRBedb9Kuv2i7jT+Tgwst8k6mqzH3AchuViiHmBd875Msfivg==
dependencies:
argparse "~1.0.3"
bluebird "~3.4.0"
dingbat-to-unicode "^1.0.1"
jszip "^3.7.1"
lop "^0.4.1"
path-is-absolute "^1.0.0"
sax "~1.1.1"
underscore "^1.13.1"
xmlbuilder "^10.0.0"
map-cache@^0.2.0, map-cache@^0.2.2:
version "0.2.2"
resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz"
@ -10920,7 +11226,7 @@ mkdirp@0.3.0:
version "0.3.0"
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz"
mkdirp@0.5.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz"
dependencies:
@ -11440,6 +11746,15 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
object-extended@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/object-extended/-/object-extended-0.0.7.tgz#84fd23f56b15582aeb3e88b05cb55d2432d68a33"
integrity sha1-hP0j9WsVWCrrPoiwXLVdJDLWijM=
dependencies:
array-extended "~0.0.4"
extended "~0.0.3"
is-extended "~0.0.3"
object-hash@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
@ -11633,6 +11948,11 @@ optimize-css-assets-webpack-plugin@5.0.4:
cssnano "^4.1.10"
last-call-webpack-plugin "^3.0.0"
option@~0.2.1:
version "0.2.4"
resolved "https://registry.yarnpkg.com/option/-/option-0.2.4.tgz#fd475cdf98dcabb3cb397a3ba5284feb45edbfe4"
integrity sha1-/Udc35jcq7PLOXo7pShP60Xtv+Q=
optionator@^0.8.1:
version "0.8.3"
resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz"
@ -12924,6 +13244,13 @@ promise@^8.0.3, promise@^8.1.0:
dependencies:
asap "~2.0.6"
promish@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/promish/-/promish-5.1.1.tgz#a5fdfc508d1233087cda33f1bb27b23d5b46d70f"
integrity sha512-37xEzvSas6JIYI/BcKh5TwhaqWepI44u/hC+tQStkX1sxMf+L756beESPgSWirxRCPqtXHzosoNzpjLnTnP8FA==
dependencies:
es6-promise "^3.0.2"
prompts@2.4.0:
version "2.4.0"
resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz"
@ -13396,6 +13723,11 @@ react-docgen-typescript@^1.15.0:
version "1.20.5"
resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-1.20.5.tgz"
react-documents@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/react-documents/-/react-documents-1.0.4.tgz#f1dee4d4a558210140f151b16a147eece4d85b54"
integrity sha512-EpoY+MZEu3hPffIWA4FadUYu8daubNkr+LK2zuoPkCAVtyNY+z+/RuzzTriuhjcDydKXzgzp42kQTfAD2j3Mxw==
react-dom@^16.7.0, react-dom@^16.8.5:
version "16.13.1"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz"
@ -13874,7 +14206,7 @@ read-pkg@^5.2.0:
parse-json "^5.0.0"
type-fest "^0.6.0"
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz"
dependencies:
@ -13895,9 +14227,10 @@ readable-stream@1.1:
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0:
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
@ -14316,15 +14649,15 @@ rgba-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz"
rimraf@2.6.3:
version "2.6.3"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz"
rimraf@2, rimraf@^2.5.4, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz"
dependencies:
glob "^7.1.3"
rimraf@^2.5.4, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz"
rimraf@2.6.3:
version "2.6.3"
resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz"
dependencies:
glob "^7.1.3"
@ -14421,9 +14754,10 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sane@^4.0.3:
version "4.1.0"
@ -14462,9 +14796,15 @@ sass-loader@8.0.2:
schema-utils "^2.6.1"
semver "^6.3.0"
sax@~1.2.4:
sax@^1.2.4, sax@~1.2.4:
version "1.2.4"
resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
sax@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240"
integrity sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA=
saxes@^5.0.0:
version "5.0.1"
@ -14650,7 +14990,7 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@^1.0.4, setimmediate@^1.0.5:
setimmediate@^1.0.4, setimmediate@^1.0.5, setimmediate@~1.0.4:
version "1.0.5"
resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz"
@ -15121,6 +15461,16 @@ string-argv@^0.3.0:
version "0.3.1"
resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz"
string-extended@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/string-extended/-/string-extended-0.0.8.tgz#741957dff487b0272a79eec5a44f239ee6f17ccd"
integrity sha1-dBlX3/SHsCcqee7FpE8jnubxfM0=
dependencies:
array-extended "~0.0.5"
date-extended "~0.0.3"
extended "~0.0.3"
is-extended "~0.0.3"
string-length@^4.0.1:
version "4.0.1"
resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz"
@ -15490,6 +15840,17 @@ tapable@^1.0.0, tapable@^1.1.3:
version "1.1.3"
resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz"
tar-stream@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
dependencies:
bl "^4.0.3"
end-of-stream "^1.4.1"
fs-constants "^1.0.0"
inherits "^2.0.3"
readable-stream "^3.1.1"
tar@^6.0.2:
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
@ -15658,6 +16019,13 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
tmp@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877"
integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==
dependencies:
rimraf "^2.6.3"
tmp@^0.2.1, tmp@~0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz"
@ -15753,6 +16121,11 @@ tr46@^2.0.2:
dependencies:
punycode "^2.1.1"
"traverse@>=0.3.0 <0.4":
version "0.3.9"
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=
trim-newlines@^3.0.0:
version "3.0.1"
resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz"
@ -15961,6 +16334,11 @@ unc-path-regex@^0.1.2:
resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
underscore@^1.13.1:
version "1.13.1"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1"
integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==
unescape-js@^1.1.4:
version "1.1.4"
resolved "https://registry.npmjs.org/unescape-js/-/unescape-js-1.1.4.tgz"
@ -16053,6 +16431,21 @@ untildify@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz"
unzipper@^0.9.12:
version "0.9.15"
resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.9.15.tgz#97d99203dad17698ee39882483c14e4845c7549c"
integrity sha512-2aaUvO4RAeHDvOCuEtth7jrHFaCKTSXPqUkXwADaLBzGbgZGzUDccoEdJ5lW+3RmfpOZYNx0Rw6F6PUzM6caIA==
dependencies:
big-integer "^1.6.17"
binary "~0.3.0"
bluebird "~3.4.1"
buffer-indexof-polyfill "~1.0.0"
duplexer2 "~0.1.4"
fstream "^1.0.12"
listenercount "~1.0.1"
readable-stream "~2.3.6"
setimmediate "~1.0.4"
upath@^1.1.1, upath@^1.1.2, upath@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz"
@ -16746,6 +17139,11 @@ xml@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz"
xmlbuilder@^10.0.0:
version "10.1.1"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-10.1.1.tgz#8cae6688cc9b38d850b7c8d3c0a4161dcaf475b0"
integrity sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==
xmlchars@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz"
@ -16904,6 +17302,15 @@ yjs@^13.5.12:
dependencies:
lib0 "^0.2.41"
zip-stream@^2.1.2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.3.tgz#26cc4bdb93641a8590dd07112e1f77af1758865b"
integrity sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==
dependencies:
archiver-utils "^2.1.0"
compress-commons "^2.1.1"
readable-stream "^3.4.0"
zipcelx@^1.6.2:
version "1.6.2"
resolved "https://registry.npmjs.org/zipcelx/-/zipcelx-1.6.2.tgz"