document-viewer-ts
Advanced tools
Comparing version 0.1.2 to 0.2.0
@@ -1,11 +0,3 @@ | ||
export interface ViewerWindow extends Window { | ||
viewerState: { | ||
[key: string]: { | ||
pageBreaks: number[]; | ||
canvasElements: HTMLCanvasElement[]; | ||
}; | ||
}; | ||
} | ||
export declare const renderPDF: (containerDiv: Element, documentUrl: string) => Promise<unknown>; | ||
export declare const renderDocument: (containerDiv: Element) => void; | ||
export declare const init: (workerSrc: string) => void; |
@@ -30,15 +30,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
const vw = window; | ||
vw.viewerState = {}; | ||
const pdfScale = 10; | ||
const zoomedWidth = '100%'; | ||
const defaultWidth = '80%'; | ||
const recalculatePDFPageBreaks = (documentId) => { | ||
var _a; | ||
(vw.viewerState[documentId] || { pageBreaks: [] }).pageBreaks = | ||
(((_a = vw.viewerState[documentId]) === null || _a === void 0 ? void 0 : _a.canvasElements) || []).reduce((acc, curr) => { | ||
const breakPoint = (acc[(acc.length || 0) - 1] || -(curr.offsetHeight / 2 + 16)) + curr.offsetHeight + 32; | ||
return [...acc, breakPoint]; | ||
}, []); | ||
}; | ||
const scaleTextLayer = (textLayerDiv, textContent, pdfPage, canvas, viewport) => __awaiter(void 0, void 0, void 0, function* () { | ||
@@ -58,17 +48,4 @@ textLayerDiv.innerHTML = ''; | ||
}); | ||
const scalePDF = (textLayerDiv, textContent, pdfPage, canvas, viewport, documentId) => { | ||
scaleTextLayer(textLayerDiv, textContent, pdfPage, canvas, viewport); | ||
recalculatePDFPageBreaks(documentId); | ||
}; | ||
export const renderPDF = (containerDiv, documentUrl) => __awaiter(void 0, void 0, void 0, function* () { | ||
const documentId = containerDiv.id; | ||
vw.viewerState[documentId] = { | ||
pageBreaks: [], | ||
canvasElements: [], | ||
}; | ||
const getPageId = (pageNumber) => `${documentId}-page-${pageNumber}`; | ||
const getPage = (scrollTop) => { | ||
var _a, _b; | ||
return Math.min((((_a = vw.viewerState[documentId]) === null || _a === void 0 ? void 0 : _a.pageBreaks.filter(b => b < scrollTop).length) || 0) + 1, ((_b = vw.viewerState[documentId]) === null || _b === void 0 ? void 0 : _b.pageBreaks.length) || Infinity); | ||
}; | ||
const canvasContainer = document.createElement('div'); | ||
@@ -80,4 +57,4 @@ canvasContainer.className = 'canvasContainer'; | ||
fullPageNumberDiv.className = 'pageNumber'; | ||
const pageNumberDiv = document.createElement('div'); | ||
pageNumberDiv.className = 'pageNumberRaw'; | ||
const pageNumberInput = document.createElement('input'); | ||
pageNumberInput.className = 'pageNumberInput'; | ||
const pageDiv = document.createElement('div'); | ||
@@ -93,15 +70,7 @@ const outOfDiv = document.createElement('div'); | ||
const loadingTask = getDocument(documentUrl); | ||
// handle updating page number on scroll | ||
canvasContainer.addEventListener('scroll', () => { | ||
const pageNumber = getPage(canvasContainer.scrollTop); | ||
pageNumberDiv.textContent = `${pageNumber}`; | ||
if (!controlsDiv.style.opacity) { | ||
controlsDiv.style.opacity = '1'; | ||
setTimeout(() => controlsDiv.removeAttribute('style'), 1000); | ||
} | ||
}); | ||
try { | ||
const pdfDocument = yield loadingTask.promise; | ||
const isValidPage = (page) => page <= pdfDocument.numPages && page > 0; | ||
// initial viewer setup | ||
pageNumberDiv.textContent = '1'; | ||
pageNumberInput.value = '1'; | ||
pageDiv.textContent = 'Page '; | ||
@@ -111,17 +80,18 @@ outOfDiv.textContent = '/'; | ||
fullPageNumberDiv.appendChild(pageDiv); | ||
fullPageNumberDiv.appendChild(pageNumberDiv); | ||
fullPageNumberDiv.appendChild(pageNumberInput); | ||
fullPageNumberDiv.appendChild(outOfDiv); | ||
fullPageNumberDiv.appendChild(pageCountDiv); | ||
const skipPage = (direction) => () => { | ||
var _a; | ||
const pageNumber = parseInt(pageNumberDiv.textContent || '1'); | ||
const nextPageNumber = pageNumber + direction; | ||
if (nextPageNumber <= pdfDocument.numPages && nextPageNumber > 0) { | ||
const nextPage = getPageId(nextPageNumber); | ||
canvasContainer.scrollTo({ top: ((_a = document.getElementById(nextPage)) === null || _a === void 0 ? void 0 : _a.parentElement).offsetTop }); | ||
pageNumberDiv.textContent = `${pageNumber + direction}`; | ||
} | ||
}; | ||
nextButton.onclick = skipPage(1); | ||
prevButton.onclick = skipPage(-1); | ||
// page container setup | ||
const pageContainer = document.createElement('div'); | ||
pageContainer.className = 'pageContainer'; | ||
pageContainer.style.width = defaultWidth; | ||
canvasContainer.appendChild(pageContainer); | ||
const canvas = document.createElement('canvas'); | ||
canvas.className = 'pdfViewerCanvas'; | ||
canvas.id = `${documentId}-canvas`; | ||
pageContainer.appendChild(canvas); | ||
// text layer setup | ||
const textLayerDiv = document.createElement('div'); | ||
textLayerDiv.className = 'textLayer'; | ||
pageContainer.appendChild(textLayerDiv); | ||
nextButton.innerHTML = chevronRight; | ||
@@ -136,17 +106,5 @@ prevButton.innerHTML = chevronLeft; | ||
containerDiv.appendChild(canvasContainer); | ||
const canvasElements = [...Array(pdfDocument.numPages).keys()].map(page => { | ||
const pageContainer = document.createElement('div'); | ||
pageContainer.className = 'pageContainer'; | ||
pageContainer.style.width = defaultWidth; | ||
canvasContainer.appendChild(pageContainer); | ||
const canvas = document.createElement('canvas'); | ||
canvas.className = 'pdfViewerCanvas'; | ||
canvas.id = getPageId(page + 1); | ||
pageContainer.appendChild(canvas); | ||
return { pageContainer, canvas }; | ||
}); | ||
(vw.viewerState[documentId] || { canvasElements: [] }).canvasElements = canvasElements.map(({ canvas }) => canvas); | ||
// load pages simultaneously | ||
yield Promise.all(canvasElements.map(({ pageContainer, canvas }, page) => __awaiter(void 0, void 0, void 0, function* () { | ||
const pdfPage = yield pdfDocument.getPage(page + 1); | ||
const displayPage = (page) => __awaiter(void 0, void 0, void 0, function* () { | ||
pageNumberInput.value = `${page}`; | ||
const pdfPage = yield pdfDocument.getPage(page); | ||
const viewport = pdfPage.getViewport({ scale: pdfScale }); | ||
@@ -161,9 +119,5 @@ canvas.width = viewport.width; | ||
}); | ||
const textLayerDiv = document.createElement('div'); | ||
textLayerDiv.className = 'textLayer'; | ||
const textContent = yield pdfPage.getTextContent(); | ||
pageContainer.appendChild(textLayerDiv); | ||
scaleTextLayer(textLayerDiv, textContent, pdfPage, canvas, viewport); | ||
// handle zoom in/out | ||
zoomButton.addEventListener('click', () => { | ||
zoomButton.onclick = () => { | ||
if (pageContainer.style.width === defaultWidth) { | ||
@@ -177,10 +131,38 @@ pageContainer.style.width = zoomedWidth; | ||
} | ||
scalePDF(textLayerDiv, textContent, pdfPage, canvas, viewport, documentId); | ||
}); | ||
// make sure text selection layer and page breaks resize dynamically | ||
window.addEventListener('resize', () => { | ||
scalePDF(textLayerDiv, textContent, pdfPage, canvas, viewport, documentId); | ||
}); | ||
}))); | ||
recalculatePDFPageBreaks(documentId); | ||
scaleTextLayer(textLayerDiv, textContent, pdfPage, canvas, viewport); | ||
}; | ||
}); | ||
const skipPage = (direction) => () => { | ||
const pageNumber = parseInt(pageNumberInput.value || '1'); | ||
const nextPageNumber = pageNumber + direction; | ||
if (isValidPage(nextPageNumber)) { | ||
displayPage(nextPageNumber); | ||
} | ||
}; | ||
nextButton.onclick = skipPage(1); | ||
prevButton.onclick = skipPage(-1); | ||
pageNumberInput.onchange = () => { | ||
const pageNumber = Math.max(Math.min(parseInt(pageNumberInput.value), pdfDocument.numPages), 1); | ||
displayPage(pageNumber); | ||
}; | ||
pageNumberInput.addEventListener('click', (e) => e.stopPropagation()); | ||
containerDiv.addEventListener('keydown', (e) => { | ||
e.stopPropagation(); | ||
switch (e.key) { | ||
case ('ArrowLeft'): | ||
skipPage(-1)(); | ||
return; | ||
case ('ArrowRight'): | ||
skipPage(1)(); | ||
return; | ||
default: | ||
return; | ||
} | ||
}); | ||
containerDiv.addEventListener('click', () => { | ||
containerDiv.focus(); | ||
}); | ||
containerDiv.setAttribute('tabIndex', '1'); | ||
containerDiv.focus(); | ||
yield displayPage(1); | ||
} | ||
@@ -201,2 +183,8 @@ catch (err) { | ||
}; | ||
const renderTxt = (containerDiv, documentUrl) => { | ||
const embed = document.createElement('embed'); | ||
embed.className = 'txtEmbed'; | ||
embed.setAttribute('src', documentUrl); | ||
containerDiv.appendChild(embed); | ||
}; | ||
export const renderDocument = (containerDiv) => { | ||
@@ -210,11 +198,28 @@ var _a; | ||
const extension = (_a = splitOnPeriods[(splitOnPeriods.length - 1)]) === null || _a === void 0 ? void 0 : _a.split('?')[0]; | ||
if (extension === 'pdf') { | ||
renderPDF(containerDiv, documentUrl); | ||
switch (extension) { | ||
case 'pdf': | ||
renderPDF(containerDiv, documentUrl); | ||
return; | ||
case 'doc': | ||
case 'docx': | ||
case 'ppt': | ||
case 'pptx': | ||
case 'xls': | ||
case 'xlsx': | ||
case 'xlt': | ||
case 'xlsm': | ||
case 'xlw': | ||
case 'pps': | ||
case 'ppxs': | ||
case 'ppsm': | ||
case 'sldx': | ||
case 'sldm': | ||
renderDocx(containerDiv, documentUrl); | ||
return; | ||
case 'txt': | ||
renderTxt(containerDiv, documentUrl); | ||
return; | ||
default: | ||
throw new Error('This file type is not supported for viewing in a web browser. Please click the “Download” button to view this document.'); | ||
} | ||
else if (extension === 'doc' || extension === 'docx') { | ||
renderDocx(containerDiv, documentUrl); | ||
} | ||
else { | ||
throw new Error('Unsupported file type'); | ||
} | ||
} | ||
@@ -221,0 +226,0 @@ catch (err) { |
@@ -1,11 +0,3 @@ | ||
export interface ViewerWindow extends Window { | ||
viewerState: { | ||
[key: string]: { | ||
pageBreaks: number[]; | ||
canvasElements: HTMLCanvasElement[]; | ||
}; | ||
}; | ||
} | ||
export declare const renderPDF: (containerDiv: Element, documentUrl: string) => Promise<unknown>; | ||
export declare const renderDocument: (containerDiv: Element) => void; | ||
export declare const init: (workerSrc: string) => void; |
@@ -33,15 +33,5 @@ "use strict"; | ||
}; | ||
const vw = window; | ||
vw.viewerState = {}; | ||
const pdfScale = 10; | ||
const zoomedWidth = '100%'; | ||
const defaultWidth = '80%'; | ||
const recalculatePDFPageBreaks = (documentId) => { | ||
var _a; | ||
(vw.viewerState[documentId] || { pageBreaks: [] }).pageBreaks = | ||
(((_a = vw.viewerState[documentId]) === null || _a === void 0 ? void 0 : _a.canvasElements) || []).reduce((acc, curr) => { | ||
const breakPoint = (acc[(acc.length || 0) - 1] || -(curr.offsetHeight / 2 + 16)) + curr.offsetHeight + 32; | ||
return [...acc, breakPoint]; | ||
}, []); | ||
}; | ||
const scaleTextLayer = (textLayerDiv, textContent, pdfPage, canvas, viewport) => __awaiter(void 0, void 0, void 0, function* () { | ||
@@ -61,17 +51,4 @@ textLayerDiv.innerHTML = ''; | ||
}); | ||
const scalePDF = (textLayerDiv, textContent, pdfPage, canvas, viewport, documentId) => { | ||
scaleTextLayer(textLayerDiv, textContent, pdfPage, canvas, viewport); | ||
recalculatePDFPageBreaks(documentId); | ||
}; | ||
const renderPDF = (containerDiv, documentUrl) => __awaiter(void 0, void 0, void 0, function* () { | ||
const documentId = containerDiv.id; | ||
vw.viewerState[documentId] = { | ||
pageBreaks: [], | ||
canvasElements: [], | ||
}; | ||
const getPageId = (pageNumber) => `${documentId}-page-${pageNumber}`; | ||
const getPage = (scrollTop) => { | ||
var _a, _b; | ||
return Math.min((((_a = vw.viewerState[documentId]) === null || _a === void 0 ? void 0 : _a.pageBreaks.filter(b => b < scrollTop).length) || 0) + 1, ((_b = vw.viewerState[documentId]) === null || _b === void 0 ? void 0 : _b.pageBreaks.length) || Infinity); | ||
}; | ||
const canvasContainer = document.createElement('div'); | ||
@@ -83,4 +60,4 @@ canvasContainer.className = 'canvasContainer'; | ||
fullPageNumberDiv.className = 'pageNumber'; | ||
const pageNumberDiv = document.createElement('div'); | ||
pageNumberDiv.className = 'pageNumberRaw'; | ||
const pageNumberInput = document.createElement('input'); | ||
pageNumberInput.className = 'pageNumberInput'; | ||
const pageDiv = document.createElement('div'); | ||
@@ -96,15 +73,7 @@ const outOfDiv = document.createElement('div'); | ||
const loadingTask = (0, pdfjs_dist_1.getDocument)(documentUrl); | ||
// handle updating page number on scroll | ||
canvasContainer.addEventListener('scroll', () => { | ||
const pageNumber = getPage(canvasContainer.scrollTop); | ||
pageNumberDiv.textContent = `${pageNumber}`; | ||
if (!controlsDiv.style.opacity) { | ||
controlsDiv.style.opacity = '1'; | ||
setTimeout(() => controlsDiv.removeAttribute('style'), 1000); | ||
} | ||
}); | ||
try { | ||
const pdfDocument = yield loadingTask.promise; | ||
const isValidPage = (page) => page <= pdfDocument.numPages && page > 0; | ||
// initial viewer setup | ||
pageNumberDiv.textContent = '1'; | ||
pageNumberInput.value = '1'; | ||
pageDiv.textContent = 'Page '; | ||
@@ -114,17 +83,18 @@ outOfDiv.textContent = '/'; | ||
fullPageNumberDiv.appendChild(pageDiv); | ||
fullPageNumberDiv.appendChild(pageNumberDiv); | ||
fullPageNumberDiv.appendChild(pageNumberInput); | ||
fullPageNumberDiv.appendChild(outOfDiv); | ||
fullPageNumberDiv.appendChild(pageCountDiv); | ||
const skipPage = (direction) => () => { | ||
var _a; | ||
const pageNumber = parseInt(pageNumberDiv.textContent || '1'); | ||
const nextPageNumber = pageNumber + direction; | ||
if (nextPageNumber <= pdfDocument.numPages && nextPageNumber > 0) { | ||
const nextPage = getPageId(nextPageNumber); | ||
canvasContainer.scrollTo({ top: ((_a = document.getElementById(nextPage)) === null || _a === void 0 ? void 0 : _a.parentElement).offsetTop }); | ||
pageNumberDiv.textContent = `${pageNumber + direction}`; | ||
} | ||
}; | ||
nextButton.onclick = skipPage(1); | ||
prevButton.onclick = skipPage(-1); | ||
// page container setup | ||
const pageContainer = document.createElement('div'); | ||
pageContainer.className = 'pageContainer'; | ||
pageContainer.style.width = defaultWidth; | ||
canvasContainer.appendChild(pageContainer); | ||
const canvas = document.createElement('canvas'); | ||
canvas.className = 'pdfViewerCanvas'; | ||
canvas.id = `${documentId}-canvas`; | ||
pageContainer.appendChild(canvas); | ||
// text layer setup | ||
const textLayerDiv = document.createElement('div'); | ||
textLayerDiv.className = 'textLayer'; | ||
pageContainer.appendChild(textLayerDiv); | ||
nextButton.innerHTML = chevronRight; | ||
@@ -139,17 +109,5 @@ prevButton.innerHTML = chevronLeft; | ||
containerDiv.appendChild(canvasContainer); | ||
const canvasElements = [...Array(pdfDocument.numPages).keys()].map(page => { | ||
const pageContainer = document.createElement('div'); | ||
pageContainer.className = 'pageContainer'; | ||
pageContainer.style.width = defaultWidth; | ||
canvasContainer.appendChild(pageContainer); | ||
const canvas = document.createElement('canvas'); | ||
canvas.className = 'pdfViewerCanvas'; | ||
canvas.id = getPageId(page + 1); | ||
pageContainer.appendChild(canvas); | ||
return { pageContainer, canvas }; | ||
}); | ||
(vw.viewerState[documentId] || { canvasElements: [] }).canvasElements = canvasElements.map(({ canvas }) => canvas); | ||
// load pages simultaneously | ||
yield Promise.all(canvasElements.map(({ pageContainer, canvas }, page) => __awaiter(void 0, void 0, void 0, function* () { | ||
const pdfPage = yield pdfDocument.getPage(page + 1); | ||
const displayPage = (page) => __awaiter(void 0, void 0, void 0, function* () { | ||
pageNumberInput.value = `${page}`; | ||
const pdfPage = yield pdfDocument.getPage(page); | ||
const viewport = pdfPage.getViewport({ scale: pdfScale }); | ||
@@ -164,9 +122,5 @@ canvas.width = viewport.width; | ||
}); | ||
const textLayerDiv = document.createElement('div'); | ||
textLayerDiv.className = 'textLayer'; | ||
const textContent = yield pdfPage.getTextContent(); | ||
pageContainer.appendChild(textLayerDiv); | ||
scaleTextLayer(textLayerDiv, textContent, pdfPage, canvas, viewport); | ||
// handle zoom in/out | ||
zoomButton.addEventListener('click', () => { | ||
zoomButton.onclick = () => { | ||
if (pageContainer.style.width === defaultWidth) { | ||
@@ -180,10 +134,38 @@ pageContainer.style.width = zoomedWidth; | ||
} | ||
scalePDF(textLayerDiv, textContent, pdfPage, canvas, viewport, documentId); | ||
}); | ||
// make sure text selection layer and page breaks resize dynamically | ||
window.addEventListener('resize', () => { | ||
scalePDF(textLayerDiv, textContent, pdfPage, canvas, viewport, documentId); | ||
}); | ||
}))); | ||
recalculatePDFPageBreaks(documentId); | ||
scaleTextLayer(textLayerDiv, textContent, pdfPage, canvas, viewport); | ||
}; | ||
}); | ||
const skipPage = (direction) => () => { | ||
const pageNumber = parseInt(pageNumberInput.value || '1'); | ||
const nextPageNumber = pageNumber + direction; | ||
if (isValidPage(nextPageNumber)) { | ||
displayPage(nextPageNumber); | ||
} | ||
}; | ||
nextButton.onclick = skipPage(1); | ||
prevButton.onclick = skipPage(-1); | ||
pageNumberInput.onchange = () => { | ||
const pageNumber = Math.max(Math.min(parseInt(pageNumberInput.value), pdfDocument.numPages), 1); | ||
displayPage(pageNumber); | ||
}; | ||
pageNumberInput.addEventListener('click', (e) => e.stopPropagation()); | ||
containerDiv.addEventListener('keydown', (e) => { | ||
e.stopPropagation(); | ||
switch (e.key) { | ||
case ('ArrowLeft'): | ||
skipPage(-1)(); | ||
return; | ||
case ('ArrowRight'): | ||
skipPage(1)(); | ||
return; | ||
default: | ||
return; | ||
} | ||
}); | ||
containerDiv.addEventListener('click', () => { | ||
containerDiv.focus(); | ||
}); | ||
containerDiv.setAttribute('tabIndex', '1'); | ||
containerDiv.focus(); | ||
yield displayPage(1); | ||
} | ||
@@ -205,2 +187,8 @@ catch (err) { | ||
}; | ||
const renderTxt = (containerDiv, documentUrl) => { | ||
const embed = document.createElement('embed'); | ||
embed.className = 'txtEmbed'; | ||
embed.setAttribute('src', documentUrl); | ||
containerDiv.appendChild(embed); | ||
}; | ||
const renderDocument = (containerDiv) => { | ||
@@ -214,11 +202,28 @@ var _a; | ||
const extension = (_a = splitOnPeriods[(splitOnPeriods.length - 1)]) === null || _a === void 0 ? void 0 : _a.split('?')[0]; | ||
if (extension === 'pdf') { | ||
(0, exports.renderPDF)(containerDiv, documentUrl); | ||
switch (extension) { | ||
case 'pdf': | ||
(0, exports.renderPDF)(containerDiv, documentUrl); | ||
return; | ||
case 'doc': | ||
case 'docx': | ||
case 'ppt': | ||
case 'pptx': | ||
case 'xls': | ||
case 'xlsx': | ||
case 'xlt': | ||
case 'xlsm': | ||
case 'xlw': | ||
case 'pps': | ||
case 'ppxs': | ||
case 'ppsm': | ||
case 'sldx': | ||
case 'sldm': | ||
renderDocx(containerDiv, documentUrl); | ||
return; | ||
case 'txt': | ||
renderTxt(containerDiv, documentUrl); | ||
return; | ||
default: | ||
throw new Error('This file type is not supported for viewing in a web browser. Please click the “Download” button to view this document.'); | ||
} | ||
else if (extension === 'doc' || extension === 'docx') { | ||
renderDocx(containerDiv, documentUrl); | ||
} | ||
else { | ||
throw new Error('Unsupported file type'); | ||
} | ||
} | ||
@@ -225,0 +230,0 @@ catch (err) { |
{ | ||
"name": "document-viewer-ts", | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"description": "PDF and MS Doc viewer written in TypeScript for React and vanilla JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "dist/lib/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
621
0
51105