Contributing to xcfreader
February 13, 2026 · View on GitHub
Thank you for your interest in contributing to xcfreader! This document provides guidelines and instructions for contributing.
Development Setup
Prerequisites
- Node.js 18.x or higher
- npm 9.x or higher
- Git
Getting Started
Option 1: Development Container (Recommended)
The easiest way to get started is using a development container:
-
Install prerequisites:
-
Open in container:
git clone https://github.com/yourusername/xcfreader.git cd xcfreader code .Then click "Reopen in Container" when prompted.
Everything will be automatically configured! See .devcontainer/README.md for details.
Option 2: Local Setup
-
Fork and clone the repository
git clone https://github.com/yourusername/xcfreader.git cd xcfreader -
Install dependencies
npm install -
Set up git hooks
npm run prepare
Development Workflow
Building
npm run build # Compile TypeScript
npm run watch # Watch mode for development
Running Examples
npm run single # Parse and render single.xcf
npm run multi # Parse multi.xcf with layers
npm run map # Parse map1.xcf
npm run text # Parse text.xcf with parasites
npm run empty # Parse empty.xcf
Testing
npm test # Run all tests
Code Quality
npm run lint # Run ESLint
npm run lint:fix # Fix linting issues
npm run format # Format code with Prettier
npm run format:check # Check code formatting
npm run validate:packages # Validate package.json consistency
npm run validate:exports # Check TypeScript type exports
Supply Chain Security
npm run sbom # Generate SBOM for monorepo
npm run sbom:all # Generate SBOMs for all packages
Software Bill of Materials (SBOM) files are generated during releases and attached to GitHub releases for supply chain transparency.
Git Hooks (Automated)
The project uses Husky for Git hooks:
- pre-commit: Runs Prettier and ESLint on staged files (via lint-staged)
- commit-msg: Validates commit message format (conventional commits)
- pre-push: Runs full test suite before allowing push
Skipping Git Hooks
In rare cases where you need to skip hooks (e.g., WIP commits, emergency fixes):
# Skip pre-commit and commit-msg hooks
git commit --no-verify -m "WIP: work in progress"
# Skip pre-push hook
git push --no-verify
# Skip all hooks for a single commit
git commit --no-verify -m "emergency fix" && git push --no-verify
⚠️ Important: Only use --no-verify when absolutely necessary. Skipping hooks can introduce:
- Unformatted code (pre-commit)
- Invalid commit messages (commit-msg)
- Broken builds on CI (pre-push)
Fast Smoke Tests
If the pre-push hook is too slow during development, you can run a quick smoke test instead:
# Quick smoke test (builds + runs a subset of tests)
npm run build:xcfreader && npm run test:xcfreader
# Then push with --no-verify to skip the full test suite
git push --no-verify
Best practice: Let CI run the full test suite on your pull request, but use smoke tests locally for faster iteration.
Commit Message Format
Use conventional commit format:
type(scope): subject
[optional body]
[optional footer]
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
Examples:
feat(xcfreader): add support for XCF v012 formatfix(ui-xcfimage): resolve layer visibility bugdocs: update README with installation instructionschore(deps): update dependencies
Creating Changesets
For changes that affect package versions, create a changeset:
npm run changeset
This will prompt you to:
- Select which packages changed
- Choose bump type (major, minor, patch)
- Write a summary of changes
Changesets are used to automatically generate changelogs and version bumps.
Publishing Packages
When publishing packages to npm, the project uses package provenance for transparency and security:
- CI Publishing: GitHub Actions automatically publishes with provenance (
--provenanceflag) - Local Publishing: Use
npm run changeset:publishwhich includes provenance automatically - Manual Publishing: If publishing manually, always use
npm publish --provenance --access public
Provenance provides cryptographic proof that packages were built in a specific CI environment, improving supply chain security.
Requirements:
- npm >= 9.5.0
- Publishing from GitHub Actions (for provenance attestation)
- OIDC token permissions (
id-token: writein CI)
Code Style & Review Process
- All code must pass ESLint and TypeScript strict mode
- Code is automatically formatted with Prettier on commit
- Use 2-space indentation, LF line endings
- Follow conventional commit message format
- PRs should include tests for new features/bugfixes
- PRs are reviewed for clarity, type safety, and documentation
- Reference issues in commit messages when applicable
Documentation
npm run docs # Generate TypeDoc API documentation
Making Changes
Code Style
- TypeScript: Strict mode enabled
- Formatting: EditorConfig (
.editorconfig) enforces consistent formatting - Linting: ESLint with
@typescript-eslintrules - Indentation: 2 spaces
- Line endings: LF (Unix-style)
Adding Features
- Create a new branch:
git checkout -b feature/my-feature - Make your changes in
src/ - Write tests in
src/tests/ - Update JSDoc comments
- Update documentation if needed
- Run
npm run lint:fixto auto-fix issues - Run
npm testto verify tests pass - Commit: git hooks will run linting and tests automatically
Adding Tests
- Create a new test file:
src/tests/NN-description.ts - Export a
testNNFunctionfunction - Add the test to
src/tests/runner.tsimports - Run
npm testto verify
Example test:
import { XCFParser } from "../gimpparser.js";
export async function test09MyFeature(): Promise<void> {
const xcfPath = "./examples/single.xcf";
const parser = await XCFParser.parseFileAsync(xcfPath);
if (!parser || !parser.width) {
throw new Error("Test failed: parser invalid");
}
console.log("PASS: my feature works");
}
Updating Documentation
- API Docs: Update JSDoc comments in source files
- README: Keep
readme.mdcurrent with examples - CHANGELOG: Document changes in
CHANGELOG.md - Guides: Add to
.github/copilot-instructions.mdif architecture changes
Commit Guidelines
- Use clear, descriptive commit messages
- Reference issues when applicable:
Fixes #123 - Format:
type: descriptionfeat:new featurefix:bug fixdocs:documentationstyle:formatting/style changestest:test additions/fixesrefactor:code refactoringperf:performance improvements
Pull Request Process
- Ensure all tests pass:
npm test - Ensure linting passes:
npm run lint - Update documentation and CHANGELOG
- Provide clear description of changes
- Link related issues
Type Safety
This project uses TypeScript with strict mode. When adding features:
- Avoid
anytypes - use specific types or generics - Add JSDoc comments with
@paramand@returnstags - Export public types for consumers
- Update type declaration files if needed
Performance Considerations
When modifying parsing or rendering:
- Run benchmarks:
npm run benchmark - Profile large files to ensure no regressions
- Consider memory usage for large XCF files
Questions?
- Check readme.md for API documentation
- See
.github/copilot-instructions.mdfor architecture details - Review existing tests for usage examples
Adding a New XCF Property Parser
To add support for a new XCF property type:
-
Define the Property Type
- Add a new constant (e.g.,
PROP_MY_THING = N) insrc/gimpparser.tsnear the other property constants.
- Add a new constant (e.g.,
-
Create a Parser
- Implement a new parser for your property using
new Parser()(see existing property parsers for examples).
- Implement a new parser for your property using
-
Register the Parser
- Add your parser to the
propertyListParser.choice(...).choicesobject with the key[PROP_MY_THING].
- Add your parser to the
-
Access the Property
- Use
layer.getProps(PROP_MY_THING)to retrieve your property from a layer.
- Use
-
Test Your Parser
- Add or update a test in
src/tests/to verify your property is parsed correctly. - Run
npm testto ensure all tests pass.
- Add or update a test in
-
Document the Change
- Update JSDoc comments and the API documentation as needed.
See .github/copilot-instructions.md for more details on the parsing architecture.
License
By contributing, you agree that your contributions will be licensed under the MIT License.