Be sure you have these tools installed:
-
Python 3.10 and below.
-
Node.js v18+ (if using Linux or Mac, we recommend installing via nvm)
- Yarn v1.x
Depending on your platform, here are some extra instructions:
If you're using an ARM-based Mac, node-canvas (one of our dependencies) also requires some additional packages to be installed. Install Homebrew if you don't already have it, then run this command:
brew install pkg-config cairo pango libpng jpeg giflib librsvg pixman
Here are some WSL-specific guides:
For wasm-bindgen
, install an OpenSSL development package:
apt-get install libssl-dev
Once you've installed all prerequisites, clone this repo. Then open a terminal in your clone of it; for instance, if you cloned it via the terminal, run this command:
cd penrose/
The rest of this document assumes you are running commands from this directory, unless otherwise specified. Next install dependencies from npm:
yarn
Then, build the dependencies of our roger
tool.
yarn build:roger
Finally, enter the directory of roger
to install it as a global binary executable, and then come
back to this directory:
pushd packages/roger/
npm link
popd
Open a separate terminal (to the same directory), and run these commands:
cd packages/examples/
roger watch
You should see this output:
watching on port 9160
Then, back in your original terminal, run this command:
yarn start
Once it finishes building, you should see this near the end of the output:
> Local: http://localhost:3000/try/
> Network: use `--host` to expose
Click that link. The page may take some time to load, but once it does, you should see something like this:
Type in the drop-down boxes to search for any Penrose trio in
packages/examples/
; for example:
- Substance:
src/set-theory-domain/tree.substance
- Style:
src/set-theory-domain/venn.style
- Domain:
src/set-theory-domain/setTheory.domain
... and voilà! ✨ See the results in your browser:
If you run yarn start
, open the browser, and see a blank page with a browser console error message along the lines of The requested module ... penrose_optimizer.js ... does not provide an export named ...
, this appears to be a dependency re-optimization issue. Try running with
yarn start --force
in this case.
Run this command to build all packages for production:
yarn build
Run this command to typecheck all packages:
yarn typecheck
We have a packages/examples/src/registry.json
file which lists several
diagrams from the packages/examples/src/
directory. All the trios listed in
this file are automatically run in GitHub Actions to produce the SVG files in
the ci/*
branches.
If you create a new diagram in packages/examples/src/
and you'd like to make
sure that future changes to Penrose don't inadvertently break your diagram, go
ahead add it to the registry! For instance, let's say you create this directory
under packages/examples/src/
:
packages/examples/src/foo-domain/
├── foo.domain
├── bar.style
└── baz.substance
The first step in adding this to the registry is to create a trio JSON file; if
you find that these give a nice diagram using variation CedarEagle308
, put
this in packages/examples/src/foo-domain/example.trio.json
:
{
"domain": "./foo.domain",
"style": ["./bar.style"],
"substance": "./baz.substance",
"variation": "CedarEagle308"
}
The add the following to packages/examples/src/registry.json
. By default,
examples won't show up in @penrose/editor
. Setting "gallery": true
will add
your example to the example gallery in editor
:
"foo-domain/example": {
"name": "My Trio",
"gallery": true
}
And you're done!
To render all diagrams in the registry, run yarn registry
in the repo root. The output SVGs will be saved under packages/examples/diagrams
.
To delete all build artifacts (but no node_modules/
):
git clean -dfxe node_modules/
To delete node_modules/
(but not build artifacts) in all packages/
:
yarn lerna clean
To delete the node_modules/
at the repo root:
npx rimraf node_modules/
To do all of the above at once:
git clean -dfx
Under the hood, roger
is an executable script (packages/roger/bin/run.js
), which is symlinked by npm link
. If roger
is not working as expected and you think it might be out of date, run
these commands to re-install it:
pushd packages/roger/
npm unlink --global @penrose/roger
npm link
popd
yarn
also provides a link
functionality but we favor npm link
because of known issues with yarn link
.
To run all tests:
yarn test
To automatically re-run tests as you make changes to core
:
npx nx run core:test-watch
The CI process runs a test that checks whether the set-venn-diagram example generates the same image that goes onto the README
page. If you made changes to Penrose, it might generate something different from the image on the README page. If this is expected, update the README
image by doing the following:
- Build
@penrose/roger
- Run
.github/gen_readme.js
This should update the image that is placed onto the README
page.
To add a project dependency to, e.g., browser-ui
(note, we don't use npm
):
pushd packages/browser-ui/
yarn add $DEPENDENCY_NAME
popd
To add a dev dependency:
pushd packages/$PACKAGE_NAME/
yarn add --dev $DEPENDENCY_NAME
popd
If you're using a package that involves the DOM, you probably want the react
version (e.g. react-graph-vis
instead of visjs
).
We use Nx to manage dependencies among our various scripts/tasks, which uses
metadata in all our package/*/package.json
files. Specifically, below the
"scripts"
section we usually have a "nx"
section defining metadata about
each script. When you update a script, be sure to update its accompanying
metadata!
The "targetDefaults"
part of nx.json
defines default dependencies for some
scripts for which we use the same semantics across all our packages:
build
means to produce executable artifacts (usually JavaScript files), and should depend on thebuild
scripts of that package's dependenciesbuild-decls
means to produce TypeScript declaration files, and should depend on thebuild-decls
scripts of that package's dependenciestypecheck
means to check for type errors in the package, and should depend on thebuild-decls
script of that same package (with the intention being that for any given package you either write abuild-decls
script or atypecheck
script, but not both)
Some packages do not need to do anything for one or more of these scripts. In
that case, the script should still be present in the "scripts"
section of that
package's package.json
file, so that Nx doesn't break the dependency chain; in
this case, the contents of the script should just be ":"
.
To import a type or function from core
in another package like browser-ui
,
import the type into packages/core/src/index.ts
and export it from there
again, then import into your project.
If you'd like to make a change and contribute it back to the project, but you don't have write permissions to this repository, you'll need to create a fork. Click the Fork button in the top-right corner of this page.
You should already have a clone of this repo by following the instructions at the start of this document, so now you simply need to add your fork as another remote:
git remote add fork https://github.com/<your-github-account-name>/penrose.git
Check out our list of good first issues.
-
Before working on one of them, let us know that you are interested so we can give you more guidance! (Currently the issue descriptions are fairly brief.)
-
Create a separate branch in your forked repo to work on the issue:
git switch --create my-branch git push --set-upstream fork my-branch
If you need to merge new changes from upstream (i.e. the original Penrose repo):
git fetch origin main:main
git merge main
After running the above, manage any merge conflicts, commit to your branch, and then push to your fork:
git push
For some PRs, it can be helpful to add tests that help verify the correctness of new features, and which ensure features don't break in future versions. Tests can be created as example diagrams in packages/examples/src
and added to the registry.
When your work is ready for review:
- Open a pull request (PR) by clicking on the Contribute button on the
homepage of your forked repo
(
https://github.com/<your-github-account-name>/penrose
). - Put
fix:
orfeat:
at the beginning of the PR title depending on if it's a fix or a feature. We follow conventional commit guidelines in our repo. - Document your changes in the PR's description (including specific paths for reproducing specific examples, and link(s) to any issue(s) you address).
- Some things will be checked automatically by our CI:
- Make sure the system passes the regression tests.
- Run Prettier via
yarn format
.
- If you have permission, request review from the relevant person. Otherwise, no worries: we'll take a look at your PR and assign it to a maintainer.
- When your PR is approved, a maintainer will merge it.
If you hit any snags in the process, run into bugs, or just have questions, please file an issue!
Our repo uses semantic versioning and maintains the same version number for all packages. Generally speaking, we release new versions whenever new features are introduced (PRs with feat
tag). Here are the steps for creating new releases.
- Make sure all PRs for the upcoming release are merged. Switch to
main
and checkgit status
to make sure it's clean and up-to-date. - At repo root, run
yarn new-version
to create a new version. - Run
yarn format
to clean up auto-generated file changes. - Create a new branch (
git switch --create release-X.Y.Z
) from main and commit the changes. - Open a new PR with a title
chore: bump version to X.Y.Z
and merge after CI passes. - Create a new GitHub release.
- CI will run after the new release is created, automatically publishing packages to npm.