Last active
January 7, 2026 09:54
-
-
Save neuralpain/b487f4620da0f7436980cadffb6e5dc7 to your computer and use it in GitHub Desktop.
A script to publish updates for both your new and existing Typst packages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # THIS SCRIPT MUST BE STARTED IN THE PACKAGE GIT REPOSITORY | |
| # '/c/path/to/my/typst/package/repository' | |
| # | |
| # Example run scenario: | |
| # ``` | |
| # cd '/c/path/to/my/typst/package/repository' | |
| # /path/to/publish.sh | |
| # ``` | |
| if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then | |
| echo "ERROR: This script must be run from the root of your package git repository." | |
| exit 1 | |
| fi | |
| # --- | |
| # Use a VERSION file to retrieve version numbers. | |
| if [ ! -f "VERSION" ]; then | |
| echo "ERROR: 'VERSION' file not found." | |
| exit 1 | |
| fi | |
| version=$(<VERSION) | |
| # OR write the version number directly. | |
| # version="0.0.0" | |
| # --- | |
| # The username which owns the package repository on GitHub. | |
| username="my_github_username" | |
| # Your package name on Typst Universe. | |
| package_name="my_package_name" | |
| # The package repository name on GitHub. | |
| # Change this if the repository name is different from the package name. | |
| repository=$package_name | |
| # The name set for your fork of the `typst/packages` repository on GitHub. | |
| # Default name is `packages`. Change this to match the name of your fork. | |
| packages_fork_name="packages" | |
| # --- | |
| # Access URL & Protocol | |
| ssh="git@github.com:" | |
| http="https://github.com/" | |
| # Set `upstream` to use either `ssh` or `http` based on your preference. | |
| upstream="${http}typst/packages" | |
| # Set the fork address to use either `ssh` or `http` based on your preference. | |
| packages_fork_address="${http}$username/$packages_fork_name" | |
| current_dir=$(basename "$PWD") | |
| if [ "$current_dir" != "$repository" ]; then | |
| echo "WARN: Current directory '$current_dir' does not match repository name '$repository'." | |
| # read -p "Continue anyway? (y/n) " -n 1 -r | |
| # echo | |
| # if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
| exit 1 | |
| # fi | |
| fi | |
| # --- | |
| # This will clone the latest commit on your `typst/packages` fork. | |
| echo "======== Create partial clone =======================" | |
| cd .. | |
| if [ -d "$packages_fork_name" ]; then | |
| rm -rf "$packages_fork_name" | |
| fi | |
| git clone --depth 1 --no-checkout --filter="tree:0" "$packages_fork_address" || { | |
| echo "ERROR: Failed to clone fork. Check your username and fork name." | |
| if [ -d "$packages_fork_name" ]; then | |
| rm -rf "$packages_fork_name" | |
| fi | |
| exit 1 | |
| } | |
| cd "$packages_fork_name" | |
| git sparse-checkout init | |
| git sparse-checkout set packages/preview/$package_name | |
| git remote add upstream $upstream | |
| git config remote.upstream.partialclonefilter tree:0 | |
| git checkout main | |
| # This will update the your local clone with the latest commit from upstream. | |
| echo "======== Update with latest commit ==================" | |
| git log -n 1 | |
| git fetch upstream --depth=1 | |
| git reset --hard upstream/main | |
| git log -n 1 | |
| echo "======== Create new branch ==========================" | |
| new_branch=$package_name-$version | |
| commit_message=$package_name:$version | |
| git branch $new_branch | |
| git switch $new_branch | |
| cd .. | |
| echo "======== Copy new files =============================" | |
| # Destination directory for the new version | |
| dest="$packages_fork_name/packages/preview/$package_name/$version" | |
| mkdir -pv "$dest" | |
| required_files=( | |
| "lib.typ" | |
| "LICENSE" | |
| "README.md" | |
| "typst.toml" | |
| ) | |
| for file in "${required_files[@]}"; do | |
| if [ ! -f "$repository/$file" ]; then | |
| echo "ERROR: Required file '$file' missing in $repository" | |
| exit 1 | |
| fi | |
| cp -v "$repository/$file" "$dest" | |
| done | |
| folders=( | |
| "examples" | |
| "src" | |
| # Add more folders... | |
| ) | |
| for folder in "${folders[@]}"; do | |
| if [ ! -d "$repository/$folder" ]; then | |
| echo "WARN: Folder '$folder' missing in $repository" | |
| else | |
| # Create directories for the new version. | |
| # Empty folders are not committed to git. | |
| mkdir -pv "$dest/$folder" | |
| cp -rv "$repository/$folder" "$dest" | |
| fi | |
| done | |
| # --- | |
| # Delete unnecessary files. | |
| cleanup() { | |
| find "$dest" -name "$1" -delete -print | |
| } | |
| echo "======== Remove PDFs ================================" | |
| cleanup "*.pdf" | |
| echo "======== Remove Backup files ========================" | |
| cleanup "*.bak" | |
| cleanup "*.bkp" | |
| echo "======== Remove Temporary files =====================" | |
| cleanup "*.tmp" | |
| cleanup "*.temp" | |
| echo "======== Remove Test files ==========================" | |
| cleanup "*temp*" | |
| cleanup "*test*" | |
| cleanup "test" | |
| echo "======== Remove other files =========================" | |
| # cleanup "*.<file-extension>" | |
| echo "======== Commit changes on new branch ===============" | |
| cd "$packages_fork_name" | |
| git add . | |
| git commit -m "$commit_message" | |
| git log -n 1 | |
| echo "======== Push new branch upstream ===================" | |
| # NOTE: This is a test. Remove `--dry-run` to actually push your code upstream. | |
| git push --dry-run origin $new_branch # --force # <-- Overwrite branch on origin. | |
| cd .. | |
| echo "======== Done =======================================" | |
| echo | |
| echo "Go to <${http}$username/$packages_fork_name/tree/$new_branch> to review and create a pull request." | |
| # Return to local package directory | |
| cd $repository |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment