mirror of
https://github.com/pdfme/pdfme.git
synced 2026-06-06 21:36:40 -04:00
* Migrate pdf-lib into pdfme monorepo - Add @pdfme/pdf-lib package to packages/ directory - Update root package.json to include pdf-lib in workspaces - Update all package dependencies to use workspace:* for @pdfme/pdf-lib - Configure TypeScript build targets (cjs, esm, node) for pdf-lib - Add ESLint configuration with relaxed rules for pdf-lib migration - Integrate pdf-lib into monorepo build and clean scripts - Add basic test suite for pdf-lib package - All lint, build, and test suites pass successfully This migration improves maintainability by consolidating all PDF operations into a single repository and unified build/test/release process. Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Fix TypeScript module resolution for workspace dependencies - Changed moduleResolution from 'bundler' to 'node' in common package - This should resolve '@pdfme/pdf-lib' module resolution issues - Reverted workspace dependency format back to '*' for npm compatibility Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Fix pdf-lib package.json exports paths - Updated main, module, and exports paths to point to correct locations - Changed from dist/*/index.js to dist/*/src/index.js to match build output - Fixed TypeScript types path from dist/types/index.d.ts to dist/types/src/index.d.ts - Resolves Vite package entry resolution errors and TypeScript module resolution issues Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Fix CodeQL security alerts in svg.ts - Add input validation and sanitization for HTML/SVG parsing - Prevent ReDoS attacks with regex limits and input size checks - Sanitize font family names to prevent prototype pollution - Add URL validation for image sources to prevent path traversal - Limit transformation parsing to prevent infinite loops - Maintain backward compatibility while improving security Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Implement comprehensive security fixes for CodeQL alerts in svg.ts - Add input validation and sanitization for SVG content - Implement safe HTML parsing with null checks and size limits - Add controlled dynamic property access with allowlisted tag names - Prevent style injection with filtered and limited style entries - Add regex match limits to prevent ReDoS attacks - Enhance font selection with input validation and type safety - Sanitize image sources to prevent path traversal and injection - Limit CSS style parsing to prevent potential vulnerabilities These changes address the 2 high-severity CodeQL security alerts while maintaining backward compatibility and functionality. Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Add additional security fixes for CodeQL alerts in svg.ts - Implement safer property access for polygon node transformation - Add input validation for points attribute with regex pattern matching - Replace Object.assign with safer property assignment to prevent prototype pollution - Add null checks and type validation for node attributes and childNodes - Implement safer SVG node parsing with comprehensive validation - Add array type checks for childNodes processing These changes target the remaining 2 high-severity CodeQL security alerts by addressing potential prototype pollution and unsafe property access. Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Implement comprehensive security hardening for CodeQL alerts in svg.ts - Add comprehensive SVG content sanitization with allowlist-based tag filtering - Implement strict input validation with bounds checking for all numeric inputs - Replace unsafe dynamic property assignment with Object.defineProperty - Add try-catch error handling for HTML parsing operations - Restrict allowed style properties and validate string lengths - Use setAttribute/removeAttribute instead of direct attribute manipulation - Add type safety checks for all node operations - Implement safer polygon-to-path conversion with validation These changes address the 10 high-severity CodeQL security alerts by: 1. Preventing XSS through comprehensive input sanitization 2. Avoiding prototype pollution with safer property assignment 3. Adding bounds checking to prevent DoS attacks 4. Using allowlist-based validation for all user inputs 5. Implementing proper error handling to prevent crashes Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com> * Potential fix for code scanning alert no. 32: Incomplete multi-character sanitization Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Potential fix for code scanning alert no. 39: Incomplete multi-character sanitization Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Fix inefficient regular expression in svg.ts to pass CodeQL - Changed /([^:\s]+)*\s*:\s*([^;]+)/g to /([^:\s]+)\s*:\s*([^;]+)/g - Removed the problematic * quantifier that could cause exponential backtracking - This fixes the "Inefficient regular expression" security alert from GitHub Advanced Security 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * remove sanitize-html * move tests * fix for security * update dependabot.yml * organize --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
154 lines
5.7 KiB
TypeScript
154 lines
5.7 KiB
TypeScript
import { svgPathToOperators } from '../../src/api/svgPath';
|
|
|
|
// Test paths adapted from https://svgwg.org/svg2-draft/paths.html
|
|
describe(`svgPathToOperators`, () => {
|
|
it(`can map triangle paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('M 100 100 L 300 100 L 200 300 z');
|
|
expect(operators.length).toBe(4);
|
|
expect(operators.toString()).toBe('100 100 m,300 100 l,200 300 l,h');
|
|
});
|
|
|
|
it(`can map relative triangle paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('m 100 100 l 200 0 l -100 200 z');
|
|
expect(operators.length).toBe(4);
|
|
expect(operators.toString()).toBe('100 100 m,300 100 l,200 300 l,h');
|
|
});
|
|
|
|
it(`can map triangle decimal paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('M 50.5 100 L 250.5 100 150.5 300 z');
|
|
expect(operators.length).toBe(4);
|
|
expect(operators.toString()).toBe('50.5 100 m,250.5 100 l,150.5 300 l,h');
|
|
});
|
|
|
|
it(`can map rectangle with lines paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('M 50 50 V 100 H 100 v -100 h -50 Z');
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'50 50 m,50 100 l,100 100 l,100 0 l,50 0 l,h',
|
|
);
|
|
});
|
|
|
|
it(`can map bezier curve paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M100,200 C100,100 250,100 250,200 S400,300 400,200',
|
|
);
|
|
expect(operators.length).toBe(3);
|
|
expect(operators.toString()).toBe(
|
|
'100 200 m,100 100 250 100 250 200 c,250 300 400 300 400 200 c',
|
|
);
|
|
});
|
|
|
|
it(`can map relative bezier curve paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M100,200 c0,-100 150,-100 150,0 s150,100 150,0',
|
|
);
|
|
expect(operators.length).toBe(3);
|
|
expect(operators.toString()).toBe(
|
|
'100 200 m,100 100 250 100 250 200 c,250 300 400 300 400 200 c',
|
|
);
|
|
});
|
|
|
|
it(`can map quadratic curve paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('M200,300 Q400,50 600,300 T1000,300');
|
|
expect(operators.length).toBe(3);
|
|
expect(operators.toString()).toBe(
|
|
'200 300 m,400 50 600 300 v,800 550 1000 300 v',
|
|
);
|
|
});
|
|
|
|
it(`can map relative quadratic curve paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('M200,300 q200,-250 400,0 t400,0');
|
|
expect(operators.length).toBe(3);
|
|
expect(operators.toString()).toBe(
|
|
'200 300 m,400 50 600 300 v,800 550 1000 300 v',
|
|
);
|
|
});
|
|
|
|
it(`can map arc paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M300,200 h-150 a150,150 0 1,0 150,-150 z',
|
|
);
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'300 200 m,150 200 l,150 282.8427124746191 217.15728752538098 350 300 350 c,382.84271247461896 350 450 282.842712474619 450 200.00000000000003 c,450 117.15728752538101 382.84271247461896 50.00000000000003 300 50.00000000000002 c,h',
|
|
);
|
|
});
|
|
|
|
it(`can map relative arc paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M300,200 h-150 A150,150 0 1,0 300,50 z',
|
|
);
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'300 200 m,150 200 l,150 282.8427124746191 217.15728752538098 350 300 350 c,382.84271247461896 350 450 282.842712474619 450 200.00000000000003 c,450 117.15728752538101 382.84271247461896 50.00000000000003 300 50.00000000000002 c,h',
|
|
);
|
|
});
|
|
|
|
it(`can map cubic bezier paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'm 100 100 S 200,100 200,200 200,200 100,200 T 0,250',
|
|
);
|
|
expect(operators.length).toBe(4);
|
|
expect(operators.toString()).toBe(
|
|
'100 100 m,100 100 200 100 200 200 c,200 300 200 200 100 200 c,0 200 0 250 v',
|
|
);
|
|
});
|
|
|
|
it(`can map dashed line paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M 0,25 5,25 M 10,25 15,25 M 20,25 25,25',
|
|
);
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'0 25 m,5 25 l,10 25 m,15 25 l,20 25 m,25 25 l',
|
|
);
|
|
});
|
|
|
|
it(`can map relative dashed line paths to PDF operators`, () => {
|
|
const operators = svgPathToOperators('m 0,25 5,0 m 5,0 5,0 m 5,0 5,0');
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'0 25 m,5 25 l,10 25 m,15 25 l,20 25 m,25 25 l',
|
|
);
|
|
});
|
|
|
|
it(`can map paths with odd inputs to PDF operators`, () => {
|
|
const operators = svgPathToOperators('M 0,25 5,25 m 5-0 5..0 m 5,0 5,0');
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'0 25 m,5 25 l,10 25 m,15 25 l,20 25 m,25 25 l',
|
|
);
|
|
});
|
|
|
|
it(`can map paths that reset cubic bezier control points to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M100 100 S200,100 200,200 M95 105 s100,0 100,100',
|
|
);
|
|
expect(operators.length).toBe(4);
|
|
expect(operators.toString()).toBe(
|
|
'100 100 m,100 100 200 100 200 200 c,95 105 m,95 105 195 105 195 205 c',
|
|
);
|
|
});
|
|
|
|
it(`can map paths that reset quadratic bezier control points to PDF operators`, () => {
|
|
const operators = svgPathToOperators(
|
|
'M100 100 T100,200 200,200 M90,120 t0,100 100,0',
|
|
);
|
|
expect(operators.length).toBe(6);
|
|
expect(operators.toString()).toBe(
|
|
'100 100 m,100 100 100 200 v,100 300 200 200 v,90 120 m,90 120 90 220 v,90 320 190 220 v',
|
|
);
|
|
});
|
|
|
|
it(`correctly updates control points for T command`, () => {
|
|
// See https://github.com/Hopding/pdf-lib/issues/1443
|
|
const operators = svgPathToOperators(
|
|
'M 10,25 Q 30,0 50,25 Q 70,50 90,25 T 130,25 T 170,25',
|
|
);
|
|
expect(operators.length).toBe(5);
|
|
expect(operators.toString()).toBe(
|
|
'10 25 m,30 0 50 25 v,70 50 90 25 v,110 0 130 25 v,150 50 170 25 v'
|
|
);
|
|
});
|
|
});
|