Building and testing
Go 1.27 or later, and Node.js for the TypeScript packages and the demo site.
Tests check the current behavior: successful input, invalid input, boundary conditions, resource limits, and rendering results. Assert expected values directly instead of copying an old implementation into a test. Fixtures for older file formats remain useful while those formats are supported. Keep one-off research, manual diagnostic output, and historical test results out of the test suite.
Go
go test ./... # every package
go run ./cmd/bdf demo out.bdf # write the fixture document
go build -tags bdf_noconv ./... # without the image/WOFF2 codecs (the browser build's profile)
GOEXPERIMENT=simd go build ./... # Go 1.27, amd64/arm64: SIMD codec variants (amd64 needs AVX2)
bdf_noconv leaves out the codecs the browser doesn't need (see design.md §2). CI builds and tests this configuration separately, so a change that only works with them compiled in won't surface until CI unless you check it locally too.
TypeScript
npm ci
npm run build # tsc -b packages/core packages/render
npm test # node --test on packages/*/test/*.test.mjs (builds first)
npm run test:browser # browser rendering, selection, search and accessibility
Browser integration tests need Chromium. Install it with npx playwright-core install chromium, or set CHROMIUM_PATH to an installed executable. They check current behavior and do not compare saved screenshots.
Regenerating fixtures
npm run testdata rebuilds everything under testdata/ from the source files under each converter/*/testdata/ (needs Go); CI checks the result byte-for-byte against what's committed. Each format's sample inputs (the .pptx, .dxf, .epub … files themselves) are generated by their own script, most needing Python:
npm run test:pptx:gen # python-pptx, msoffcrypto-tool
npm run test:xlsx:gen # openpyxl
npm run test:dxf:gen # ezdxf
npm run test:kicad:gen
npm run test:musicxml:gen # (run from converter/musicxml/testdata)
npm run test:audio:gen # ffmpeg, mutagen
# … one per format; see package.json's scripts for the full list
Running a viewer locally
npm run demo # http://127.0.0.1:8765/examples/viewer/.out/ — the viewer alone, opens any .bdf under the repo via ?src=
npm run site # builds site/dist: the full site (top page, viewer, thumbnail/text pages, docs), needs Go
npm run site:serve # npm run site, then serves it
node examples/viewer/serve.mjs # same as npm run demo
?src= points the standalone viewer at a .bdf path in the repository, e.g. http://127.0.0.1:8765/examples/viewer/.out/?src=/testdata/drawio/multipage.bdf; &layout=spread opens it as a book. BDF_SITE_FONTS=dir1:dir2 npm run site publishes those fonts with the site instead of the default test fonts.
Rendering or inspecting an arbitrary .bdf
node test/render.mjs out.bdf pngdir/ # render every page to PNG with headless Chromium
go run ./cmd/bdf ls out.bdf # part list
go run ./cmd/bdf render -page 2 out.bdf page2.png # render one page, in pure Go (no browser)
Matching CI's output exactly
CI's testdata is up to date step compares bdf generate output byte-for-byte on ubuntu-latest (amd64). Go's floating-point contraction differs by architecture, though, so the same command run on Apple Silicon can produce a few different low bits in an object's bounding boxes. Cross-compile with GOARCH=amd64 go build and run that binary under Rosetta to reproduce CI's bytes locally, before assuming a diff is a real regression.
See the API reference for what each package and command exposes, and The BDF command for bdf's subcommands.