Skip to content
Merged

Dev #172

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ members = [
"packages/ducsvg/src/pdf2svg",
]

[workspace.dependencies]
duc = { version = "1" }

[profile.release]
lto = true
Expand Down
43 changes: 22 additions & 21 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/ducpdf/src/duc2pdf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ path = "src/lib.rs"
crate-type = ["cdylib", "rlib"]

[dependencies]
# Local dev: uses path. Publish: release script updates to crates.io version
duc = { version = "0.0.0-development", path = "../../../ducrs" }
hipdf = { version = "1.3.2", features = ["wasm_js"] }
svg2pdf = "0.13.0"
Expand Down
1 change: 1 addition & 0 deletions packages/ducpdf/src/duc2pdf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@ To ensure smooth releases with semantic-release, please follow [these guidelines
---

*The duc format and libraries are constantly evolving, aiming to set new standards in the 2D CAD industry. Be a part of this transformation and help shape the future of design technology!*

7 changes: 5 additions & 2 deletions packages/ducpdf/src/duc2pdf/release.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ module.exports = {
[
"@semantic-release/exec",
{
// Prepare step: Set the crate version and build the project
// Prepare step:
// 1. Update duc dependency to use crates.io version (not development)
// 2. Set the crate version
// 3. Build the project
prepareCmd:
"cargo set-version ${nextRelease.version} && cargo build --release",
"node ../../../../scripts/cargo-set-duc-dep-version.js . 2 && cargo set-version ${nextRelease.version} && cargo build --release",

Copilot AI Dec 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version "2" is hardcoded in the release script. This creates a tight coupling between the release configuration and the actual version of the 'duc' dependency available on crates.io. If the duc package version changes, this hardcoded value will need to be manually updated in the release config.

Consider making this configurable, either through an environment variable or by determining the version dynamically (e.g., reading from a configuration file or using a semantic version range like "^2.0.0" if appropriate for crates.io compatibility).

Suggested change
"node ../../../../scripts/cargo-set-duc-dep-version.js . 2 && cargo set-version ${nextRelease.version} && cargo build --release",
"node ../../../../scripts/cargo-set-duc-dep-version.js . ${DUC_VERSION:-2} && cargo set-version ${nextRelease.version} && cargo build --release",

Copilot uses AI. Check for mistakes.

// Publish step: Publish the crate to crates.io
publishCmd:
Expand Down
1 change: 1 addition & 0 deletions packages/ducsvg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"semantic-release": "^24.1.2",
"typescript": "^5.8.3",
"vite": "^6.0.0",
"vite-plugin-compression": "^0.5.1",

Copilot AI Dec 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vite-plugin-compression version 0.5.1 is from 2022, which is significantly older than other dependencies in the project (e.g., vite is at ^6.0.0). Consider checking if there's a more recent version of vite-plugin-compression available that's compatible with Vite 6. Older plugins may not be fully compatible with newer Vite versions and could have unpatched security vulnerabilities or missing features.

Additionally, verify that this older plugin version is compatible with the Vite 6.0.0 being used in this project.

Suggested change
"vite-plugin-compression": "^0.5.1",
"vite-plugin-compression": "^0.6.0",

Copilot uses AI. Check for mistakes.
"vitest": "^3.2.4"
},
"files": [
Expand Down
16 changes: 14 additions & 2 deletions packages/ducsvg/vite.config.mts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { defineConfig } from 'vite';
import viteCompression from 'vite-plugin-compression';

export default defineConfig({
plugins: [
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
filter: /\.(wasm|js)$/i,
threshold: 1024, // Only compress files > 1KB
deleteOriginFile: false, // Keep original files for compatibility
}),
Comment on lines +6 to +12

Copilot AI Dec 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The threshold value of 1024 bytes (1KB) for compression is quite aggressive. Brotli compression has overhead, and compressing very small files (1-2KB) may actually result in larger file sizes or negligible benefits.

Consider increasing the threshold to at least 10KB (10240 bytes) for WASM files and 5KB (5120 bytes) for JS files. This is a more common practice that ensures compression overhead doesn't outweigh the benefits for smaller files.

Suggested change
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
filter: /\.(wasm|js)$/i,
threshold: 1024, // Only compress files > 1KB
deleteOriginFile: false, // Keep original files for compatibility
}),
// Compress WASM files > 10KB
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
filter: /\.(wasm)$/i,
threshold: 10240, // Only compress WASM files > 10KB
deleteOriginFile: false, // Keep original files for compatibility
}),
// Compress JS files > 5KB
viteCompression({
algorithm: 'brotliCompress',
ext: '.br',
filter: /\.(js)$/i,
threshold: 5120, // Only compress JS files > 5KB
deleteOriginFile: false, // Keep original files for compatibility
}),

Copilot uses AI. Check for mistakes.
],
build: {
emptyOutDir: false,
lib: {
Expand All @@ -14,8 +24,10 @@ export default defineConfig({
rollupOptions: {
// Externalize dependencies that have WASM runtimes or shouldn't be bundled
external: [
'ducpdf', // Uses Rust WASM - let consuming app handle
'ducjs', // Workspace dependency
'ducpdf', // Uses Rust WASM - let consuming app handle
'ducjs', // Workspace dependency
/pdf2svg/, // Externalize pdf2svg wasm bindings to prevent inline base64 bundling

Copilot AI Dec 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern /pdf2svg/ will match any module path containing "pdf2svg" anywhere in the string. This might be overly broad and could unintentionally externalize modules that happen to have "pdf2svg" in their path but aren't the intended pdf2svg package.

Consider making the pattern more specific, such as /^pdf2svg/ to only match modules that start with "pdf2svg", or use a string 'pdf2svg' if you want to match the exact package name. The current pattern could match paths like 'node_modules/some-package/pdf2svg-utils/index.js' which may not be intended.

Suggested change
/pdf2svg/, // Externalize pdf2svg wasm bindings to prevent inline base64 bundling
'pdf2svg', // Externalize pdf2svg wasm bindings to prevent inline base64 bundling

Copilot uses AI. Check for mistakes.
/\.wasm$/, // Don't bundle WASM files inline
],
output: {
globals: {
Expand Down
51 changes: 51 additions & 0 deletions scripts/cargo-set-duc-dep-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env node
/**
* Updates the 'duc' dependency version in a Cargo.toml file.
* Used during semantic-release to set the duc dependency to a crates.io-compatible version.
*
* Usage: node scripts/cargo-set-duc-dep-version.js <cargoTomlPath> <version>
* Example: node scripts/cargo-set-duc-dep-version.js packages/ducpdf/src/duc2pdf/Cargo.toml 2
*/
const fs = require("fs");
const path = require("path");

const cargoTomlPath = process.argv[2];
const version = process.argv[3];

if (!cargoTomlPath || !version) {
console.error("Usage: node scripts/cargo-set-duc-dep-version.js <cargoTomlPath> <version>");
console.error("Example: node scripts/cargo-set-duc-dep-version.js packages/ducpdf/src/duc2pdf/Cargo.toml 2");
process.exit(1);
}

let fullPath = path.resolve(process.cwd(), cargoTomlPath);

// If path is a directory, append Cargo.toml
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
fullPath = path.join(fullPath, "Cargo.toml");
}

if (!fs.existsSync(fullPath)) {
console.error(`File not found: ${fullPath}`);
process.exit(1);
}

let content = fs.readFileSync(fullPath, "utf8");

// Match entire duc dependency line and replace with version-only format
// Handles variations like:
// duc = { version = "0.0.0-development", path = "..." }
// duc = { path = "...", version = "..." }
// Replaces with: duc = "VERSION"
const ducDepRegex = /^(#[^\n]*\n)*duc\s*=\s*\{[^}]+\}/m;

if (!ducDepRegex.test(content)) {
console.error("Could not find duc dependency with version/path in Cargo.toml");
process.exit(1);
}

// Replace the entire duc dependency (including any comment above it) with simple version
content = content.replace(ducDepRegex, `duc = "${version}"`);
Comment on lines +40 to +48

Copilot AI Dec 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern /^(#[^\n]*\n)*duc\s*=\s*\{[^}]+\}/m may not handle all edge cases correctly:

  1. Multi-line duc dependency declarations with nested braces would fail (e.g., if there are features with nested config)
  2. The pattern [^}]+ is greedy and will match up to the first }, which might not be the correct closing brace if the dependency has nested structures
  3. Comments with special characters or unicode might cause issues with [^\n]*

While these edge cases may not occur in the current codebase, consider using a more robust TOML parser library (like @iarna/toml or toml) to parse, modify, and serialize the Cargo.toml file. This would be more maintainable and handle edge cases correctly.

Copilot uses AI. Check for mistakes.

Copilot AI Dec 16, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script directly uses user input (process.argv[3]) in a string replacement without validation or sanitization. While the version parameter is expected to be a simple version string, a malicious or malformed input could potentially inject unexpected content into the Cargo.toml file.

Consider adding validation for the version parameter to ensure it matches expected version patterns (e.g., semver format like 1.2.3, 2, 1.0.0-beta, etc.) before using it in the replacement. For example:

if (!/^[\d.]+(-[a-zA-Z0-9.-]+)?$/.test(version)) {
  console.error(`Invalid version format: ${version}`);
  process.exit(1);
}

This would prevent injection of malicious or malformed content into the Cargo.toml file.

Copilot uses AI. Check for mistakes.

fs.writeFileSync(fullPath, content);
console.log(`Updated duc dependency to "${version}" (removed path) in ${fullPath}`);