
Research
/Security News
Critical Vulnerability in NestJS Devtools: Localhost RCE via Sandbox Escape
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
custom-forge-viewer
Advanced tools
Enhanced Autodesk Forge PDF Viewer with custom navigation toolbar
Production-ready Autodesk Forge PDF Viewer with intelligent page detection and custom navigation toolbar for seamless document browsing.
# Install via npm
npm install custom-forge-viewer
# Install via yarn
yarn add custom-forge-viewer
# Install via pnpm
pnpm add custom-forge-viewer
import React, { useState } from "react";
import { ViewerForgePDF } from "custom-forge-viewer";
function DocumentViewer() {
const [viewer, setViewer] = useState(null);
return (
<div style={{ width: "100%", height: "600px" }}>
<ViewerForgePDF
filePath="https://example.com/document.pdf"
fileExt="pdf"
setViewer={setViewer}
/>
</div>
);
}
export default DocumentViewer;
import React, { useState, useCallback } from "react";
import { ViewerForgePDF } from "custom-forge-viewer";
function EnterpriseDocumentViewer() {
const [viewer, setViewer] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const handleViewerReady = useCallback((viewerInstance) => {
setViewer(viewerInstance);
setIsLoading(false);
// Access advanced viewer APIs
viewerInstance.addEventListener("documentLoadSuccess", () => {
console.log("Document loaded successfully");
});
}, []);
return (
<div style={{ width: "100%", height: "100vh", position: "relative" }}>
{isLoading && (
<div
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
}}
>
Loading document...
</div>
)}
<ViewerForgePDF
filePath="https://cdn.example.com/technical-specs.dwf"
fileExt="dwf"
setViewer={handleViewerReady}
reactInstance={React} // Explicit React injection for complex webpack setups
/>
</div>
);
}
export default EnterpriseDocumentViewer;
import React, { useState } from "react";
import { ViewerForgePDF } from "custom-forge-viewer";
interface DocumentViewerProps {
documentUrl: string;
documentType: "pdf" | "dwf" | "dwfx";
onViewerReady?: (viewer: any) => void;
}
const DocumentViewer: React.FC<DocumentViewerProps> = ({
documentUrl,
documentType,
onViewerReady,
}) => {
const [viewer, setViewer] = useState<any>(null);
const handleViewerInit = (viewerInstance: any) => {
setViewer(viewerInstance);
onViewerReady?.(viewerInstance);
};
return (
<div style={{ width: "100%", height: "600px" }}>
<ViewerForgePDF
filePath={documentUrl}
fileExt={documentType}
setViewer={handleViewerInit}
/>
</div>
);
};
export default DocumentViewer;
Prop | Type | Required | Default | Description |
---|---|---|---|---|
filePath | string | โ Yes | - | URL or path to the document file |
fileExt | 'pdf' | 'dwf' | 'dwfx' | โ Yes | - | File extension for proper viewer initialization |
setViewer | (viewer: any) => void | โ Yes | - | Callback function to receive the initialized viewer |
reactInstance | React | โ No | auto-detected | React instance for environments with custom React setups |
Once the viewer is initialized, you gain access to the full Autodesk Forge Viewer API plus our custom enhancements:
// Navigation methods (auto-detected for multi-page documents)
viewer.navigateToPage(pageNumber); // Navigate to specific page
viewer.nextPage(); // Go to next page
viewer.previousPage(); // Go to previous page
// View manipulation
viewer.fitToView(); // Fit document to viewport
viewer.zoom(scaleFactor); // Zoom in/out
viewer.pan(deltaX, deltaY); // Pan the view
// Document information
viewer.getCurrentPage(); // Get current page number
viewer.getTotalPages(); // Get total page count
viewer.getDocumentInfo(); // Get document metadata
// Markup and annotations (if extensions loaded)
viewer.enterMarkupMode(); // Enable markup tools
viewer.exitMarkupMode(); // Disable markup tools
The viewer automatically adapts its interface based on document characteristics:
Single-Page Documents:
Multi-Page Documents:
Our advanced detection algorithm analyzes multiple document characteristics:
/* Customize the toolbar appearance */
#custom-bottom-toolbar {
background-color: rgba(255, 255, 255, 0.95) !important;
border: 1px solid #e0e0e0 !important;
border-radius: 8px !important;
}
/* Customize button hover effects */
#custom-bottom-toolbar .adsk-button:hover {
background-color: rgba(0, 122, 255, 0.1) !important;
}
/* Customize navigation input */
#custom-page-input {
background-color: #f5f5f5 !important;
color: #333 !important;
border: 1px solid #ccc !important;
}
// For Next.js applications
import dynamic from "next/dynamic";
const ViewerForgePDF = dynamic(
() => import("custom-forge-viewer").then((mod) => mod.ViewerForgePDF),
{ ssr: false }
);
// For Webpack 5 applications
module.exports = {
resolve: {
fallback: {
fs: false,
path: false,
crypto: false,
},
},
};
// Redux integration example
import { useDispatch, useSelector } from "react-redux";
function ReduxDocumentViewer() {
const dispatch = useDispatch();
const { documentUrl, currentPage } = useSelector((state) => state.documents);
const handleViewerReady = (viewer) => {
dispatch(setViewer(viewer));
// Listen for page changes
viewer.addEventListener("pageChanged", (page) => {
dispatch(setCurrentPage(page));
});
};
return (
<ViewerForgePDF
filePath={documentUrl}
fileExt="pdf"
setViewer={handleViewerReady}
/>
);
}
Browser | Minimum Version | Features Available |
---|---|---|
Chrome | 80+ | All features |
Firefox | 75+ | All features |
Safari | 13+ | All features |
Edge | 80+ | All features |
Browser | Minimum Version | Features Available |
---|---|---|
Mobile Safari | 13+ | Touch navigation |
Chrome Mobile | 80+ | Touch navigation |
Samsung Internet | 12+ | Touch navigation |
// Preload viewer resources for faster initialization
import { preloadForgeResources } from "custom-forge-viewer/preload";
// Call this early in your application lifecycle
preloadForgeResources();
// Use React.memo for components that don't change frequently
const MemoizedViewer = React.memo(ViewerForgePDF);
// Implement proper cleanup in useEffect
useEffect(() => {
return () => {
if (viewer) {
viewer.finish();
viewer = null;
}
};
}, [viewer]);
// Error: Invalid hook call
// Solution: Explicit React instance injection
<ViewerForgePDF
reactInstance={React}
filePath="document.pdf"
fileExt="pdf"
setViewer={setViewer}
/>
// Server configuration needed for cross-origin documents
// Add these headers to your document server:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
// For production deployments, ensure proper Forge credentials
// Required environment variables:
FORGE_CLIENT_ID = your_client_id;
FORGE_CLIENT_SECRET = your_client_secret;
// For Webpack 5, add to webpack.config.js:
module.exports = {
resolve: {
fallback: {
stream: require.resolve("stream-browserify"),
buffer: require.resolve("buffer"),
},
},
};
// Enable debug mode for development
import { ViewerForgePDF, enableDebugMode } from "custom-forge-viewer";
if (process.env.NODE_ENV === "development") {
enableDebugMode(true);
}
// Monitor viewer performance
const handleViewerReady = (viewer) => {
// Track initialization time
console.time("ViewerInit");
viewer.addEventListener("documentLoadSuccess", () => {
console.timeEnd("ViewerInit");
});
// Monitor memory usage
if (performance.memory) {
console.log("Memory usage:", performance.memory);
}
};
import { render, screen } from "@testing-library/react";
import { ViewerForgePDF } from "custom-forge-viewer";
test("renders document viewer", () => {
const mockSetViewer = jest.fn();
render(
<ViewerForgePDF
filePath="test.pdf"
fileExt="pdf"
setViewer={mockSetViewer}
/>
);
expect(screen.getByRole("application")).toBeInTheDocument();
});
describe("Document Viewer", () => {
it("loads and displays document", () => {
cy.visit("/viewer");
cy.get("#forgeViewerPDF").should("be.visible");
cy.get("#custom-bottom-toolbar").should("be.visible");
});
it("navigates between pages", () => {
cy.get("#custom-next-page").click();
cy.get("#custom-page-input").should("have.value", "2");
});
});
# Build for production
npm run build
# Analyze bundle size
npm run analyze
# Run production tests
npm run test:prod
<!-- Include via CDN -->
<script src="https://cdn.jsdelivr.net/npm/custom-forge-viewer@latest/dist/index.min.js"></script>
<!-- Or use specific version -->
<script src="https://cdn.jsdelivr.net/npm/custom-forge-viewer@1.0.0/dist/index.min.js"></script>
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
MIT License - See LICENSE file for details.
We welcome contributions from the community! Here's how to get started:
# Clone the repository
git clone https://github.com/DTDucas/custom-forge-viewer.git
cd custom-forge-viewer
# Install dependencies
npm install
# Start development server
npm run dev
# Run tests
npm test
# Build library
npm run build
For enterprise customers, we offer:
Contact us at enterprise@example.com for enterprise inquiries.
โ ๏ธ Production Notice: This library requires access to Autodesk Forge Viewer APIs. Ensure proper authentication and licensing compliance for production deployments. For commercial usage, please review Autodesk Forge Terms of Service.
Made with โค๏ธ by Duong Tran Quang
โญ Star this repository if it helps your project!
FAQs
Enhanced Autodesk Forge PDF Viewer with custom navigation toolbar
The npm package custom-forge-viewer receives a total of 147 weekly downloads. As such, custom-forge-viewer popularity was classified as not popular.
We found that custom-forge-viewer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.ย It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Product
Customize license detection with Socketโs new license overlays: gain control, reduce noise, and handle edge cases with precision.
Product
Socket now supports Rust and Cargo, offering package search for all users and experimental SBOM generation for enterprise projects.