fix: 🐛 Update ohif pdf extension to optionally use pdfjs (#1162)
* fix: 🐛 Update ohif pdf extension to optionally use pdfjs Update ohif pdf extension of optionally use pdfjs Closes: #1049 * Update branch and fix scrolling * Dynamically import component * Fix wrong file change * Fix import * Add multi opened pdf configuration * Refactor connected component * Specify worker explicitly * Specify worker explicitly * CR Update: Remove dead code * CR Update: Refactor state * CR Update: use refs * CR Update: use refs
This commit is contained in:
parent
25599a2e2a
commit
31e542dfd9
@ -37,7 +37,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.5.5",
|
"@babel/runtime": "^7.5.5",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"lodash.isequal": "^4.5.0"
|
"lodash.isequal": "^4.5.0",
|
||||||
|
"pdfjs-dist": "^2.2.228"
|
||||||
},
|
},
|
||||||
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
"gitHead": "a5baa9228c0eda0df880136bde4420d78e6f8706"
|
||||||
}
|
}
|
||||||
|
|||||||
27
extensions/dicom-pdf/src/ConnectedOHIFDicomPDFViewer.js
Normal file
27
extensions/dicom-pdf/src/ConnectedOHIFDicomPDFViewer.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import OHIF from '@ohif/core';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import OHIFDicomPDFViewport from './OHIFDicomPDFViewport';
|
||||||
|
|
||||||
|
const { setViewportActive } = OHIF.redux.actions;
|
||||||
|
|
||||||
|
const mapStateToProps = (state, ownProps) => {
|
||||||
|
const { activeViewportIndex } = state.viewports;
|
||||||
|
return { activeViewportIndex };
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||||
|
const { viewportIndex } = ownProps;
|
||||||
|
|
||||||
|
return {
|
||||||
|
setViewportActive: () => {
|
||||||
|
dispatch(setViewportActive(viewportIndex));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConnectedOHIFDicomPDFViewer = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(OHIFDicomPDFViewport);
|
||||||
|
|
||||||
|
export default ConnectedOHIFDicomPDFViewer;
|
||||||
62
extensions/dicom-pdf/src/DicomPDFViewport.css
Normal file
62
extensions/dicom-pdf/src/DicomPDFViewport.css
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
.DicomPDFViewport {
|
||||||
|
--header-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #fff;
|
||||||
|
padding: 0.5em;
|
||||||
|
border-bottom: var(--ui-border-thickness) solid var(--ui-border-color);
|
||||||
|
height: var(--header-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #canvas {
|
||||||
|
height: calc(100% - var(--header-height));
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #text-layer {
|
||||||
|
height: 100%;
|
||||||
|
margin-top: var(--header-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #pdf-canvas-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport canvas, #text-layer {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #toolbar button {
|
||||||
|
color: currentColor;
|
||||||
|
background-color: transparent;
|
||||||
|
font: inherit;
|
||||||
|
border: var(--ui-border-thickness) solid var(--ui-border-color);
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #text-layer {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0.2;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DicomPDFViewport #text-layer>span {
|
||||||
|
color: transparent;
|
||||||
|
position: absolute;
|
||||||
|
white-space: pre;
|
||||||
|
cursor: text;
|
||||||
|
transform-origin: 0% 0%;
|
||||||
|
}
|
||||||
@ -1,6 +1,14 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component, createRef } from 'react';
|
||||||
import dicomParser from 'dicom-parser';
|
import dicomParser from 'dicom-parser';
|
||||||
|
import PDFJS from 'pdfjs-dist';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import TypedArrayProp from './TypedArrayProp';
|
import TypedArrayProp from './TypedArrayProp';
|
||||||
|
import './DicomPDFViewport.css';
|
||||||
|
|
||||||
|
import pdfjsBuild from 'pdfjs-dist/build/pdf';
|
||||||
|
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
|
||||||
|
pdfjsBuild.GlobalWorkerOptions.workerSrc = pdfjsWorker;
|
||||||
|
|
||||||
// TODO: Should probably use dcmjs for this
|
// TODO: Should probably use dcmjs for this
|
||||||
const SOP_CLASS_UIDS = {
|
const SOP_CLASS_UIDS = {
|
||||||
@ -8,16 +16,88 @@ const SOP_CLASS_UIDS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class DicomPDFViewport extends Component {
|
class DicomPDFViewport extends Component {
|
||||||
state = {
|
constructor(props) {
|
||||||
fileURL: null,
|
super(props);
|
||||||
error: null,
|
|
||||||
};
|
this.state = {
|
||||||
|
fileURL: null,
|
||||||
|
error: null,
|
||||||
|
currentPageIndex: 1,
|
||||||
|
pdf: null,
|
||||||
|
scale: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.canvas = createRef();
|
||||||
|
this.textLayer = createRef();
|
||||||
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
byteArray: TypedArrayProp.uint8,
|
byteArray: TypedArrayProp.uint8,
|
||||||
|
useNative: PropTypes.bool,
|
||||||
|
viewportData: PropTypes.object,
|
||||||
|
activeViewportIndex: PropTypes.number,
|
||||||
|
setViewportActive: PropTypes.func,
|
||||||
|
viewportIndex: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderPDF = (dataSet, byteArray) => {
|
static defaultProps = {
|
||||||
|
useNative: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
const dataSet = this.parseByteArray(this.props.byteArray);
|
||||||
|
const fileURL = this.getPDFFileUrl(dataSet, this.props.byteArray);
|
||||||
|
|
||||||
|
this.setState(state => ({ ...state, fileURL }));
|
||||||
|
|
||||||
|
if (!this.props.useNative) {
|
||||||
|
const pdf = await PDFJS.getDocument(fileURL).promise;
|
||||||
|
this.setState(state => ({ ...state, pdf }), () => this.updatePDFCanvas());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePDFCanvas = async () => {
|
||||||
|
const { pdf, scale, currentPageIndex } = this.state;
|
||||||
|
const context = this.canvas.getContext('2d');
|
||||||
|
|
||||||
|
const page = await pdf.getPage(currentPageIndex);
|
||||||
|
let viewport = page.getViewport({ scale });
|
||||||
|
|
||||||
|
this.canvas.height = viewport.height;
|
||||||
|
this.canvas.width = viewport.width;
|
||||||
|
|
||||||
|
const renderContext = {
|
||||||
|
canvasContext: context,
|
||||||
|
viewport: viewport,
|
||||||
|
};
|
||||||
|
|
||||||
|
await page.render(renderContext);
|
||||||
|
const textContent = await page.getTextContent();
|
||||||
|
|
||||||
|
this.textLayer.innerHTML = '';
|
||||||
|
this.textLayer.style.height = viewport.height + 'px';
|
||||||
|
this.textLayer.style.width = viewport.width + 'px';
|
||||||
|
|
||||||
|
PDFJS.renderTextLayer({
|
||||||
|
textContent,
|
||||||
|
container: this.textLayer,
|
||||||
|
viewport,
|
||||||
|
textDivs: [],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
const { currentPageIndex, scale } = this.state;
|
||||||
|
const newValidScale = prevState.scale !== scale && scale > 0;
|
||||||
|
const newValidPageNumber =
|
||||||
|
prevState.currentPageIndex !== currentPageIndex && currentPageIndex > 0;
|
||||||
|
|
||||||
|
if (newValidScale || newValidPageNumber) {
|
||||||
|
this.updatePDFCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPDFFileUrl = (dataSet, byteArray) => {
|
||||||
let pdfByteArray = byteArray;
|
let pdfByteArray = byteArray;
|
||||||
|
|
||||||
if (dataSet) {
|
if (dataSet) {
|
||||||
@ -36,50 +116,144 @@ class DicomPDFViewport extends Component {
|
|||||||
const PDF = new Blob([pdfByteArray], { type: 'application/pdf' });
|
const PDF = new Blob([pdfByteArray], { type: 'application/pdf' });
|
||||||
const fileURL = URL.createObjectURL(PDF);
|
const fileURL = URL.createObjectURL(PDF);
|
||||||
|
|
||||||
this.setState({
|
return fileURL;
|
||||||
fileURL,
|
};
|
||||||
});
|
|
||||||
|
onPageChange = async event => {
|
||||||
|
const { currentPageIndex, pdf } = this.state;
|
||||||
|
let newPageIndex = currentPageIndex;
|
||||||
|
|
||||||
|
const action = event.target.getAttribute('data-pager');
|
||||||
|
if (action === 'prev') {
|
||||||
|
if (currentPageIndex === 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newPageIndex -= 1;
|
||||||
|
if (currentPageIndex < 0) {
|
||||||
|
newPageIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'next') {
|
||||||
|
if (currentPageIndex === pdf.numPages - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newPageIndex += 1;
|
||||||
|
if (currentPageIndex > pdf.numPages - 1) {
|
||||||
|
newPageIndex = pdf.numPages - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(state => ({ ...state, currentPageIndex: newPageIndex }));
|
||||||
|
};
|
||||||
|
|
||||||
|
onZoomChange = () => {
|
||||||
|
let newZoomValue = this.state.scale;
|
||||||
|
|
||||||
|
const action = event.target.getAttribute('data-pager');
|
||||||
|
|
||||||
|
if (action === '+') {
|
||||||
|
newZoomValue += 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === '-') {
|
||||||
|
newZoomValue -= 0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(state => ({ ...state, scale: newZoomValue }));
|
||||||
};
|
};
|
||||||
|
|
||||||
parseByteArray = byteArray => {
|
parseByteArray = byteArray => {
|
||||||
const options = {
|
const options = { untilTag: '' };
|
||||||
untilTag: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
let dataSet;
|
let dataSet;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dataSet = dicomParser.parseDicom(byteArray, options);
|
dataSet = dicomParser.parseDicom(byteArray, options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setState({
|
this.setState(state => ({ ...state, error }));
|
||||||
error,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataSet;
|
return dataSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
setViewportActiveHandler = () => {
|
||||||
const dataSet = this.parseByteArray(this.props.byteArray);
|
const {
|
||||||
|
setViewportActive,
|
||||||
|
viewportIndex,
|
||||||
|
activeViewportIndex,
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
this.renderPDF(dataSet, this.props.byteArray);
|
if (viewportIndex !== activeViewportIndex) {
|
||||||
}
|
setViewportActive(viewportIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
downloadPDFCanvas = () => {
|
||||||
|
const { fileURL } = this.state;
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = fileURL;
|
||||||
|
a.download = fileURL.substr(fileURL.lastIndexOf('/') + 1);
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { fileURL, pdf, error } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={'DicomPDFViewport'}
|
className={'DicomPDFViewport'}
|
||||||
|
onClick={this.setViewportActiveHandler}
|
||||||
|
onScroll={this.setViewportActiveHandler}
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
>
|
>
|
||||||
{this.state.fileURL && (
|
{!this.props.useNative ? (
|
||||||
|
<>
|
||||||
|
<div id="toolbar">
|
||||||
|
<div id="pager">
|
||||||
|
{pdf && pdf.numPages > 1 && (
|
||||||
|
<>
|
||||||
|
<button data-pager="prev" onClick={this.onPageChange}>
|
||||||
|
{`<`}
|
||||||
|
</button>
|
||||||
|
<button data-pager="next" onClick={this.onPageChange}>
|
||||||
|
{`>`}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<button data-pager="-" onClick={this.onZoomChange}>
|
||||||
|
{`-`}
|
||||||
|
</button>
|
||||||
|
<button data-pager="+" onClick={this.onZoomChange}>
|
||||||
|
{`+`}
|
||||||
|
</button>
|
||||||
|
<button onClick={this.downloadPDFCanvas}>Download</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="canvas">
|
||||||
|
<div id="pdf-canvas-container">
|
||||||
|
<canvas
|
||||||
|
id="pdf-canvas"
|
||||||
|
ref={canvas => (this.canvas = canvas)}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
id="text-layer"
|
||||||
|
ref={textLayer => (this.textLayer = textLayer)}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
<object
|
<object
|
||||||
data={this.state.fileURL}
|
aria-label="PDF Viewer"
|
||||||
|
data={fileURL}
|
||||||
type="application/pdf"
|
type="application/pdf"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{this.state.error && <h2>{JSON.stringify(this.state.error)}</h2>}
|
{error && <h2>{JSON.stringify(error)}</h2>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,9 @@ class OHIFDicomPDFViewport extends Component {
|
|||||||
studies: PropTypes.object,
|
studies: PropTypes.object,
|
||||||
displaySet: PropTypes.object,
|
displaySet: PropTypes.object,
|
||||||
viewportIndex: PropTypes.number,
|
viewportIndex: PropTypes.number,
|
||||||
|
viewportData: PropTypes.object,
|
||||||
|
activeViewportIndex: PropTypes.number,
|
||||||
|
setViewportActive: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -30,42 +33,36 @@ class OHIFDicomPDFViewport extends Component {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { displaySet, studies } = this.props.viewportData;
|
const { displaySet, studies } = this.props.viewportData;
|
||||||
const {
|
|
||||||
studyInstanceUid,
|
|
||||||
seriesInstanceUid,
|
|
||||||
sopInstanceUid,
|
|
||||||
wadoRoot,
|
|
||||||
wadoUri,
|
|
||||||
authorizationHeaders,
|
|
||||||
} = displaySet;
|
|
||||||
|
|
||||||
DicomLoaderService.findDicomDataPromise(displaySet, studies).then(
|
DicomLoaderService.findDicomDataPromise(displaySet, studies).then(
|
||||||
data => {
|
data => this.setState({ byteArray: new Uint8Array(data) }),
|
||||||
const byteArray = new Uint8Array(data);
|
|
||||||
this.setState({
|
|
||||||
byteArray: byteArray,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
error => {
|
error => {
|
||||||
this.setState({
|
this.setState({ error });
|
||||||
error,
|
|
||||||
});
|
|
||||||
|
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
setViewportActive,
|
||||||
|
viewportIndex,
|
||||||
|
activeViewportIndex,
|
||||||
|
} = this.props;
|
||||||
|
const { byteArray, error } = this.state;
|
||||||
const { id, init, destroy } = OHIFDicomPDFViewport;
|
const { id, init, destroy } = OHIFDicomPDFViewport;
|
||||||
const pluginProps = { id, init, destroy };
|
const pluginProps = { id, init, destroy };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OHIFComponentPlugin {...pluginProps}>
|
<OHIFComponentPlugin {...pluginProps}>
|
||||||
{this.state.byteArray && (
|
{byteArray && (
|
||||||
<DicomPDFViewport byteArray={this.state.byteArray} />
|
<DicomPDFViewport
|
||||||
|
byteArray={byteArray}
|
||||||
|
setViewportActive={setViewportActive}
|
||||||
|
viewportIndex={viewportIndex}
|
||||||
|
activeViewportIndex={activeViewportIndex}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{this.state.error && <h2>{JSON.stringify(this.state.error)}</h2>}
|
{error && <h2>{JSON.stringify(error)}</h2>}
|
||||||
</OHIFComponentPlugin>
|
</OHIFComponentPlugin>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
37
extensions/dicom-pdf/src/asyncComponent.js
Normal file
37
extensions/dicom-pdf/src/asyncComponent.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* We use this component to leverage "Code Splitting"
|
||||||
|
*
|
||||||
|
* Link: https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export default function asyncComponent(importComponent) {
|
||||||
|
class AsyncComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
component: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
// Add dynamically loaded component to state
|
||||||
|
const { default: component } = await importComponent();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
component: component,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const C = this.state.component;
|
||||||
|
|
||||||
|
// Render the loaded component, or null
|
||||||
|
return C ? <C {...this.props} /> : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AsyncComponent;
|
||||||
|
}
|
||||||
@ -1,16 +1,21 @@
|
|||||||
|
import asyncComponent from './asyncComponent.js';
|
||||||
import OHIFDicomPDFSopClassHandler from './OHIFDicomPDFSopClassHandler.js';
|
import OHIFDicomPDFSopClassHandler from './OHIFDicomPDFSopClassHandler.js';
|
||||||
import OHIFDicomPDFViewport from './OHIFDicomPDFViewport.js';
|
|
||||||
|
const ConnectedOHIFDicomPDFViewer = asyncComponent(() =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "ConnectedOHIFDicomPDFViewer" */ './ConnectedOHIFDicomPDFViewer'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* Only required property. Should be a unique value across all extensions.
|
* Only required property. Should be a unique value across all extensions.
|
||||||
*/
|
*/
|
||||||
id: 'pdf',
|
id: 'pdf',
|
||||||
|
|
||||||
getViewportModule() {
|
getViewportModule() {
|
||||||
return OHIFDicomPDFViewport;
|
return ConnectedOHIFDicomPDFViewer;
|
||||||
},
|
},
|
||||||
getSopClassHandlerModule() {
|
getSopClassHandlerModule() {
|
||||||
return OHIFDicomPDFSopClassHandler;
|
return OHIFDicomPDFSopClassHandler;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
13
yarn.lock
13
yarn.lock
@ -13296,6 +13296,11 @@ node-dir@^0.1.10:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimatch "^3.0.2"
|
minimatch "^3.0.2"
|
||||||
|
|
||||||
|
node-ensure@^0.0.0:
|
||||||
|
version "0.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
|
||||||
|
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
|
||||||
|
|
||||||
node-fetch-npm@^2.0.2:
|
node-fetch-npm@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
|
resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
|
||||||
@ -14423,6 +14428,14 @@ pbkdf2@^3.0.3:
|
|||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
sha.js "^2.4.8"
|
sha.js "^2.4.8"
|
||||||
|
|
||||||
|
pdfjs-dist@^2.2.228:
|
||||||
|
version "2.2.228"
|
||||||
|
resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.2.228.tgz#777b068a0a16c96418433303807c183058b47aaa"
|
||||||
|
integrity sha512-W5LhYPMS2UKX0ELIa4u+CFCMoox5qQNQElt0bAK2mwz1V8jZL0rvLao+0tBujce84PK6PvWG36Nwr7agCCWFGQ==
|
||||||
|
dependencies:
|
||||||
|
node-ensure "^0.0.0"
|
||||||
|
worker-loader "^2.0.0"
|
||||||
|
|
||||||
pend@~1.2.0:
|
pend@~1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user