chore: initial commit
Some checks failed
Build and Deploy Docs / build (push) Failing after 1m41s
Bump version / Bump version and create changelog with commitizen (push) Failing after 7s

This commit is contained in:
Ulenar of Mondarth 2025-07-14 18:00:35 +00:00
commit 6803c8336b
59 changed files with 6657 additions and 0 deletions

1
.commitlintrc.mjs Normal file
View File

@ -0,0 +1 @@
export default { extends: ['@commitlint/config-conventional'] };

4
.cz.toml Normal file
View File

@ -0,0 +1,4 @@
[tool.commitizen]
version = "0.6.0"
version_files = ["package.json:version", "docs/conf.py:release"]
tag_format = "v${version}"

1
.foundryvtt/.env Normal file
View File

@ -0,0 +1 @@
VERSION=12

View File

@ -0,0 +1,28 @@
---
secrets:
config_json:
file: secrets.json
services:
foundry:
image: felddy/foundryvtt:${VERSION}
container_name: campaign-vtt
hostname: localhost
volumes:
- type: bind
source: ./data
target: /data
- type: bind
source: ..
target: /data/Data/modules/mondarth-campaign
environment:
- CONTAINER_PRESERVE_CONFIG=true
- FOUNDRY_UID=1000
- FOUNDRY_GID=1000
ports:
- target: 30000
published: 31000
protocol: tcp
secrets:
- source: config_json
target: config.json

7
.gitattributes vendored Normal file
View File

@ -0,0 +1,7 @@
# Set line endings.
* text eol=lf
# Explicitly mark binary files.
*.png binary
*.jpg binary
*.ico binary

View File

@ -0,0 +1,50 @@
name: Build and Deploy Docs
on:
workflow_call:
push:
branches:
- main
paths:
- 'docs/**'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
concurrency:
group: generate-docs
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
attestations: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Extract version from tag without the v
id: get-version
run: echo "v=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Patch version into docs configuration
id: sub_docs_release
run: sed -i "s/release\s+=.*/release = '${{steps.get-version.outputs.v}}/'" docs/conf.py
- name: Build Documentation
run: |
docker run --rm -v "${{ github.workspace }}/docs":/docs ghcr.io/ulenarofmondarth/sphinx-docs:latest make html
cd ./docs/_build/html
zip -r ${{ github.workspace }}/documentation-${{ github.ref_name }}.zip .
- name: Preserve Documentation
uses: actions/upload-artifact@v4
with:
name: documentation-${{ github.ref_name}}
path: ${{ github.workspace }}/documentation-${{ github.ref_name }}.zip
- name: Deploy Documentation
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/_build/html

View File

@ -0,0 +1,98 @@
name: Build and Release Module and Documentation
on:
push:
tags: [ "v*" ]
paths-ignore:
- "docs/**"
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-documentation:
uses: ./.github/workflows/build-and-deploy-docs.yml
build:
needs:
- build-documentation
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
attestations: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22.x
cache: "pnpm"
- name: Dump
env:
GHC: ${{ toJson(github) }}
run: 'echo "Dump: ${GHC}"'
- name: Extract version from tag without the v
id: get-version
run: echo "v=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Test
run: pnpm test
- name: Compile build
run: pnpm build
# Substitute the Manifest and Download URLs in the `module.json`.
- name: Substitute Manifest and Download Links For Versioned Ones
id: sub_manifest_link_version
uses: microsoft/variable-substitution@v1
with:
files: 'module.json'
env:
version: ${{steps.get-version.outputs.v}}
url: https://github.com/${{github.repository}}
readme: https://github.com/${{github.repository}}/blob/master/README.md
bugs: https://github.com/${{github.repository}}/issues
changelog: https://github.com/${{github.repository}}/releases/latest
manifest: https://github.com/${{github.repository}}/releases/latest/download/module.json
download: https://github.com/${{github.repository}}/releases/download/${{github.ref_name}}/module.zip
# Create a zip file with all files required by the module to add to the release.
- name: Bundle into ZIP file
run: zip -r ./module.zip module.json assets/ dist/ lang/ packs/ LICENSE documentation-${{ github.ref_name }}.zip
- name: Recover Release Data
uses: dawidd6/action-download-artifact@v6
with:
workflow: bump-version.yml
workflow_conclusion: success
name: release-${{ github.ref_name }}
path: ${{ github.workspace }}/release-${{ github.ref_name }}
search_artifacts: true
- name: Release
if: ${{ !env.ACT }}
uses: softprops/action-gh-release@v1
with:
body_path: "${{ github.workspace }}/release-${{ github.ref_name }}/release-note.md"
tag_name: ${{ github.ref_name }}
files: |
documentation-${{ github.ref_name }}.zip
module.json
module.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,30 @@
name: Bump version
on:
push:
branches:
- main
paths-ignore:
- 'docs/**'
jobs:
bump-version:
if: "!startsWith(github.event.head_commit.message, 'bump:')"
runs-on: ubuntu-latest
name: "Bump version and create changelog with commitizen"
steps:
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"
- name: Create bump and changelog
uses: commitizen-tools/commitizen-action@master
with:
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
changelog_increment_filename: release-note.md
- name: Preserve Release Note
uses: actions/upload-artifact@v4
with:
name: release-v${{ env.REVISION }}
path: release-note.md

5
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,5 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: mondarth
ko_fi: ulenarofmondarth

36
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,36 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
assignees: 'typhonrt'
---
**Module Version:** v0.0.0
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Browser:**
-
**Foundry Version:**
**Game System:**
**Additional context**
Add any other context (like other modules installed) about the problem here.

View File

@ -0,0 +1,10 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---

10
.github/ISSUE_TEMPLATE/styling.md vendored Normal file
View File

@ -0,0 +1,10 @@
---
name: Styling
about: Request a change or bug related to styles
title: ''
labels: styling
assignees: ''
---

View File

@ -0,0 +1,50 @@
name: Build and Deploy Docs
on:
workflow_call:
push:
branches:
- main
paths:
- 'docs/**'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
concurrency:
group: generate-docs
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
attestations: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Extract version from tag without the v
id: get-version
run: echo "v=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Patch version into docs configuration
id: sub_docs_release
run: sed -i "s/release\s+=.*/release = '${{steps.get-version.outputs.v}}/'" docs/conf.py
- name: Build Documentation
run: |
docker run --rm -v "${{ github.workspace }}/docs":/docs ghcr.io/ulenarofmondarth/sphinx-docs:latest make html
cd ./docs/_build/html
zip -r ${{ github.workspace }}/documentation-${{ github.ref_name }}.zip .
- name: Preserve Documentation
uses: actions/upload-artifact@v4
with:
name: documentation-${{ github.ref_name}}
path: ${{ github.workspace }}/documentation-${{ github.ref_name }}.zip
- name: Deploy Documentation
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/_build/html

98
.github/workflows/build-and-release.yml vendored Normal file
View File

@ -0,0 +1,98 @@
name: Build and Release Module and Documentation
on:
push:
tags: [ "v*" ]
paths-ignore:
- "docs/**"
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-documentation:
uses: ./.github/workflows/build-and-deploy-docs.yml
build:
needs:
- build-documentation
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
attestations: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22.x
cache: "pnpm"
- name: Dump
env:
GHC: ${{ toJson(github) }}
run: 'echo "Dump: ${GHC}"'
- name: Extract version from tag without the v
id: get-version
run: echo "v=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Test
run: pnpm test
- name: Compile build
run: pnpm build
# Substitute the Manifest and Download URLs in the `module.json`.
- name: Substitute Manifest and Download Links For Versioned Ones
id: sub_manifest_link_version
uses: microsoft/variable-substitution@v1
with:
files: 'module.json'
env:
version: ${{steps.get-version.outputs.v}}
url: https://github.com/${{github.repository}}
readme: https://github.com/${{github.repository}}/blob/master/README.md
bugs: https://github.com/${{github.repository}}/issues
changelog: https://github.com/${{github.repository}}/releases/latest
manifest: https://github.com/${{github.repository}}/releases/latest/download/module.json
download: https://github.com/${{github.repository}}/releases/download/${{github.ref_name}}/module.zip
# Create a zip file with all files required by the module to add to the release.
- name: Bundle into ZIP file
run: zip -r ./module.zip module.json assets/ dist/ lang/ packs/ LICENSE documentation-${{ github.ref_name }}.zip
- name: Recover Release Data
uses: dawidd6/action-download-artifact@v6
with:
workflow: bump-version.yml
workflow_conclusion: success
name: release-${{ github.ref_name }}
path: ${{ github.workspace }}/release-${{ github.ref_name }}
search_artifacts: true
- name: Release
if: ${{ !env.ACT }}
uses: softprops/action-gh-release@v1
with:
body_path: "${{ github.workspace }}/release-${{ github.ref_name }}/release-note.md"
tag_name: ${{ github.ref_name }}
files: |
documentation-${{ github.ref_name }}.zip
module.json
module.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

30
.github/workflows/bump-version.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: Bump version
on:
push:
branches:
- main
paths-ignore:
- 'docs/**'
jobs:
bump-version:
if: "!startsWith(github.event.head_commit.message, 'bump:')"
runs-on: ubuntu-latest
name: "Bump version and create changelog with commitizen"
steps:
- name: Check out
uses: actions/checkout@v4
with:
fetch-depth: 0
token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}"
- name: Create bump and changelog
uses: commitizen-tools/commitizen-action@master
with:
github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
changelog_increment_filename: release-note.md
- name: Preserve Release Note
uses: actions/upload-artifact@v4
with:
name: release-v${{ env.REVISION }}
path: release-note.md

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.idea
.DS_Store
.vite-cache/
.vscode/**/*
!.vscode/extensions.json
_build/
dist/
node_modules/
.foundryvtt/data/
.foundryvtt/secrets.json

3
.husky/commit-msg Executable file
View File

@ -0,0 +1,3 @@
#!/bin/env bash
pnpm exec commitlint --edit $1

3
.husky/pre-commit Executable file
View File

@ -0,0 +1,3 @@
#!/bin/env bash
pnpm lint-staged

13
.husky/prepare-commit-msg Executable file
View File

@ -0,0 +1,13 @@
#!/bin/env bash
if [ "$2" = "commit" ]; then
echo "Skipping prepare-commit-msg hook due to amend."
exit 0
fi
if [ -n "$GIT_SEQUENCE_EDITOR" ]; then
echo "Skipping prepare-commit-msg hook due to rebase."
exit 0
fi
exec < /dev/tty && pnpm exec cz --hook || true

5
.lintstagedrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"*.json": ["pnpm prettier:format"],
"*.{css,scss}": ["pnpm prettier:format"],
"*.{js,ts,mjs,svelte}": ["pnpm prettier:format", "pnpm lint", "vitest related --run"]
}

2
.prettierignore Normal file
View File

@ -0,0 +1,2 @@
/dist
/pnpm-lock.yaml

45
.prettierrc.json Normal file
View File

@ -0,0 +1,45 @@
{
"printWidth": 120,
"tabWidth": 2,
"overrides": [
{
"files": ["*.scss", "*.css"],
"options": {
"requirePragma": false,
"parser": "scss"
}
},
{
"files": ["*.ts", "*.js", "*.mjs"],
"options": {
"arrowParens": "avoid",
"singleQuote": true,
"semi": true,
"bracketSameLine": true,
"trailingComma": "all"
}
},
{
"files": ["*.yml"],
"options": {
"tabWidth": 2
}
},
{
"files": "*.html",
"options": {
"requirePragma": false,
"parser": "html",
"htmlWhitespaceSensitivity": "ignore"
}
},
{
"files": "*.hbs",
"options": {
"requirePragma": false,
"parser": "angular",
"htmlWhitespaceSensitivity": "ignore"
}
}
]
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 TyphonJS-FVTT-Demo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Foundry VTT Module

Binary file not shown.

After

Width:  |  Height:  |  Size: 969 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

20
docs/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

41
docs/conf.py Normal file
View File

@ -0,0 +1,41 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'A Module'
copyright = 'Author Copyright'
author = 'Author'
release = '0.1.0'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = ['sphinx_rtd_theme', 'sphinx.ext.todo', 'sphinxcontrib.mermaid', 'sphinxcontrib.youtube', 'sphinx_design']
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
# -- Esure TODOs are output (these should all be cleared before a commit)
# https://www.sphinx-doc.org/en/master/usage/extensions/todo.html#directive-todo
todo_include_todos = True
todo_emit_warnings = True
rst_prolog = """
.. |LSP| replace:: :abbr:`LSP (Language Server Protocol)`
.. |HMR| replace:: :abbr:`HMR (Hot Module Reload)`
.. |IMHO| replace:: :abbr:`IMHO (In My Humble Opinion)`
"""

View File

@ -0,0 +1,44 @@
Alternatives
============
Can I use ``npm`` instead of ``pnpm``?
--------------------------------------
Replacing ``pnpm`` with ``npm`` is simple enough. You will need to modify the following:
``package.json``
Change the ``packageManager`` entry, remove the ``scrips.preinstall`` entry. Check for any embedded ``pnpm`` commands and replace with the corresponding ``npm`` command. Most day-to-day 'heavy lifting' is done with :ref:`zx scripts` and these are independent of the package manager in use.
``.github/workflows``
Check these as they use ``pnpm`` and a github cache action for ``pnpm``.
.. _replacing github:
Can I use an alternative to ``github``?
---------------------------------------
You can use another host for your version control and deployment but you will need to review and update:
``.github/workflows``
These (obviously) rely on github being used\ [#F1]_. These build, package and deploy your module and its associated documentation.
``module.json``
The elements in this file that change with each release are automatically maintained by the ``.github/workflows``. You will need to implement alternatives if you choose another host.
.. _replacing sphinx:
Can I replace the documentation system?
---------------------------------------
This template uses Docker to isolate a documentation system based on `Sphinx <https://www.sphinx-doc.org/en/master/>`_. The ``.github/workflows`` assume this documentation system is used when building and deploying the documentation to :program:`github pages`.
If you replace the documentation system you will need to review and update:
``.github/workflows/buid_and_release_docs.yml``
This is responsible for the release build of documentation and publishing to :program:`github pages`.
``package.json``
Update (or remove) the ``serve:docs`` and ``devserve:docs`` script entries.
``scripts``
Update (or remove) the scripts invoked from ``package.json``.
.. rubric:: Footnotes
.. [#F1] Well, at least something that understands Github actions and workflow format. Try `act <https://github.com/nektos/act>`_, this can be usefull for local testing of workflows. It is also the workflow system used by `Gitea <https://about.gitea.com/>`_ (if you fancy an alternative web-based repository host).

View File

@ -0,0 +1,22 @@
.. _prerequisites:
Prerequisites
=============
``nodeJS``
This template is tested against ``modejs`` version 22.14.0.
``pnpm``
The package manager of choice. (See :ref:`replace pnpm` if you object to efficiency.)
``docker``
(And ``docker compose``---commonly bundled when you install Docker.)
* ``docker`` version v28+
* ``docker compose`` version v2.33+
``git``
Pretty much any modern ``git``, at the time of writing I have v2.39.5 installed.

52
docs/developers/setup.rst Normal file
View File

@ -0,0 +1,52 @@
Setup
=====
Once the :ref:`prerequisites` are installed setup is simple enough.
.. code-block
git clone -depth 1 https://github.com/Mondarth..... project-name
cd project-name
rm -rf .git
git init
pnpm install
pnpm prepare
Edit ``module.json`` and set:
``id``
A unique id for the module. Use ``-`` instead of a space (and no spaces), lowercase.
``title``
A string short title for the module. This will appear in on the Foundry Add-Modules page.
``description``
A description of what the module does. Keep it short. This also appears on the Add-Module screen.
``authors``
Porvide at least one Author entry.
``compatibility``
Set which versions of Foundry this module is compatible.
You may also need to set various other values in ``module.json`` (e.g. ``socket`` if your module uses ``socketlib``), but these will vary widely according to what your module does.
If you use :program:`github` for your versioning and distribution then you can leave the following entries alone and the ``.github/workflows`` will maintain them for you. (Otherwise, see :ref:`replacing github`.)
* ``url``
* ``readme``
* ``bugs``
* ``changelog``
* ``manifest``
* ``download``
Edit ``docs/conf.py`` and change:
``project``
This will be the documentation's main title (and home page).
``copyright``
holder of the copyright to the documenation.
``author``
Who wrote the documentation.
If using the provided :program:`github` setup the ``release`` will be maintained by the documentation build workflow.
And you should be good to go.

43
docs/developers/why.rst Normal file
View File

@ -0,0 +1,43 @@
Why ...
=======
... use ``pnpm``?
-----------------
``pnpm`` uses a cache and is more efficient than ``npm``.
... use ``github``?
-------------------
It is pretty ubiquitous and virtually a standard for managing Foundry modules.
... use ``zx`` for scripting?
-----------------------------
We have ``nodejs`` installed so may as well stick with javascript. It is also more platform independent.
... use ``vite``?
-----------------
It provides nice tools (like an |HMR| development server) out of the box.
... use ``vitest``?
-------------------
Clean, simple, flexible, and ties in to ``vite`` ecosystem.
... use ``docker``?
-------------------
For ancillary tooling it provides a neat way to isolate from the host (so we can provide neat features without needing to have you install a load of stuff). It also provides a nicely isolated environment for running development Foundry VTT servers, which can also be used in more advances scenarios in ``.github/wormflows``.
... document with Sphinx?
-------------------------
This is just my taste. I like the power and simplicity of ReStructured Text (more that Markdown but shallower learning curve than, for example, LaTeX). I also like the flexible output method from Sphinx. (See :ref:`replacing sphinx`)
... all the ``svelte`` stuff?
-----------------------------
This module template assumes you will be using `svelte <https://svelte.dev>`_ for any UI (rather than the Foundry Handlebars). :program:`Svelte` is (|IMHO|) a more powerful, more reactive, yet simpler, UI framework. It plays nicely with ``vite`` and together they produce small modules. One can use a complete library, such as `TyphonJS <https://github.com/typhonjs-fvtt-lib>`_ (which attempts to replicate the Foundry API UI as Svelte components), or simply wrap standard Svelte by extending `ApplicationV2 <https://foundryvtt.com/api/v12/classes/foundry.applications.api.ApplicationV2.html>`_. Which is better depends on your objectives.

View File

@ -0,0 +1,7 @@
Why not...
==========
... use ``docker`` to isolate the whole development environment?
----------------------------------------------------------------
More trouble than it is worth. Although less of an issue than it used to be using docker in docker can be tricky. Similarly, individual developer IDE preferences can get messy when using docker development containers. It is simpler to use ``nodejs`` on the host and rely on ``pnpm`` for most of the build/runtime environment isolation.

View File

@ -0,0 +1,74 @@
.. _zx scripts:
``zx`` Scripts
==============
These scripts are utilities for use during development, build, and testing. They are not part of the final module.
The Scripts
-----------
These scripts defer to `PDT <https://github.com/ulenarofmondarth/pdt>`_\ [#F2]_ if it is installed. Otherwise they offer limited capabilities aimed at providing single module development and test environments.
foundryvtt
~~~~~~~~~~
Controls one or more local Foundry VTT instances.
:program:`foundryvtt start`
Start the default Foundry VTT. If a previously stopped default instance exists this will restart it. If the instance is already running nothing is done.
:program:`foundryvtt stop`
Stop the default Foundry VTT. If the instance is not running nothing is done.
:program:`foundryvtt reset`
Reset (clear all data, so use with care) the default Foundry VTT. It the instance exists it is stopped (if running), the container is destroyed, and the data directory is destroyed.
Configuring Scripts
-------------------
The easiest way to set the environment variables for these scripts is with a `'.env`` file in the root of your project. All environment variables specific to these scripts are prefixed with ``ZXS_`` (for 'ZX Script').
You will find the defaults in ``.env``. These defaults will generally work well in a standalone module build environment\ [#F1]_. To override these it is recommended to create a ``.env.local`` specific to your development environment. You should not commit ``.env.local`` into :program:`git`.
The general form of configuration environment variables is: ``ZXS_<hierarchical namespace>`` where the namespaces are delineated by ``_``.
The configuration
.. code-block:: json
{
"docker": {
"main-vtt": {
"name": "foundry-vtt",
"ports": {
"vtt": {
"container": 8000,
"host": 8080
}
}
}
}
}
}
is represented with the environment vairables
.. code-block:: sh
ZXS_DOCKER_MAIN-VTT_NAME = "foundry-vtt"
ZXS_DOCKER_MAIN-VTT_PORTS_VTT_CONTAINER = 8000
ZXS_DOCKER_MAIN-VTT_PORTS_VTT_HOST = 8080
.. note:: No attempt is made to represent an array in this schema. Instead an 'array' is represented as the values of an object, in the example neithes ``docker`` nor ``ports`` care about their keys, the script treats the values as a simple array.
.. rubric:: Footnote
.. [#F2] PDT offers a suite of tools to help with development and testing of Foundry modules.
.. [#F1] If you are incorporating this module into a monorepo then you will need to rework a lot of the scripts and workflows. This is *way* beyond the scope of this text. Dealing with the defaults in ``.env`` is going to be the least of your issues.

22
docs/index.rst Normal file
View File

@ -0,0 +1,22 @@
Module documentation
====================
Add your content using ``reStructuredText`` syntax. See the
`reStructuredText <https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html>`_
documentation for details.
.. toctree::
:maxdepth: 2
:caption: Contents:
.. toctree::
:maxdepth: 2
:caption: For Developers:
developers/prerequisites.rst
developers/setup.rst
developers/zx_scripts.rst
developers/alternatives.rst
developers/why.rst
developers/why_not.rst

35
docs/make.bat Normal file
View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

25
eslint.config.mjs Normal file
View File

@ -0,0 +1,25 @@
import js from '@eslint/js';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import ts from 'typescript-eslint';
export default ts.config(js.configs.recommended, ...ts.configs.recommended, ...svelte.configs.recommended, {
languageOptions: {
globals: {
...globals.node,
...globals.browser,
...globals.jquery,
},
},
rules: {
'no-shadow': [
'error',
{
builtinGlobals: true,
hoist: 'all',
allow: ['document', 'event', 'name', 'parent', 'status', 'top'],
},
],
},
});

9
jsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"lib": ["ES2022", "DOM"],
"module": "ES2022",
"moduleResolution": "Bundler",
"target": "ES2022"
},
"exclude": ["node_modules"]
}

5
lang/en.json Normal file
View File

@ -0,0 +1,5 @@
{
"TemplateESM": {
"title": "Template Svelte (ESM)"
}
}

62
module.json Normal file
View File

@ -0,0 +1,62 @@
{
"id": "mondarth-campaign",
"title": "Mondarth Campaign",
"description": "Collection of Material fo Mondarth Campaign",
"version": "0.0.0",
"authors": [
{
"name": "Ulenar of Mondarth",
"url": "https://mondarth.com",
"flags": {}
}
],
"compatibility": {
"minimum": "12",
"verified": "12"
},
"esmodules": ["dist/module.js"],
"flags": {
"hotReload": {
"extensions": ["json"],
"paths": ["lang"]
}
},
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json",
"flags": {}
}
],
"url": "https://gitea/Mondarth/mondarth-campaign",
"readme": "https://gitea/Mondarth/mondarth-campaign/blob/master/README.md",
"bugs": "https://gitea/Mondarth/mondarth-campaign/issues",
"changelog": "https://gitea/Mondarth/mondarth-campaign/releases/latest/",
"manifest": "https://gitea/Mondarth/mondarth-campaign/releases/latest/download/module.json",
"download": "https://gitea/Mondarth/mondarth-campaign/releases/download/0.0.0/module.zip",
"packs": [
{
"name": "mondarth",
"label": "Mondarth",
"path": "packs/mondarth",
"type": "Adventure",
"ownership": {
"PLAYER": "OBSERVER",
"ASSISTANT": "OWNER"
},
"system": "dnd5e"
},
{
"name": "otrikius",
"label": "Otrikius",
"path": "packs/otrikius",
"type": "Adventure",
"ownership": {
"PLAYER": "OBSERVER",
"ASSISTANT": "OWNER"
},
"system": "dnd5e"
}
]
}

63
package.json Normal file
View File

@ -0,0 +1,63 @@
{
"description": "Provides a bare-bones Foundry module template repo to get set up using Svelte with ES Modules and vitest.",
"license": "MIT",
"private": true,
"type": "module",
"author": "YOUR INFO HERE",
"contributors": [
"YOUR INFO HERE"
],
"packageManager": "pnpm@10.5.2",
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"build": "vite build",
"dev": "vite",
"test": "vitest --typecheck --run",
"eslint": "eslint .",
"prepare": "husky",
"serve:vtt": "cd .foundryvtt && docker compose up -d",
"build:docs": "docker run --rm --user \"$(id -u):$(id -g)\" -v \"$(pwd)/docs\":/docs ghcr.io/ulenarofmondarth/sphinx-docs make html",
"serve:docs": "docker run --rm --name docserver -d -p 8080:80 -v \"$(pwd)/docs/_build/html\":/usr/share/nginx/html:ro nginx",
"devserve:docs": "docker run --rm --user \"$(id -u):$(id -g)\" --name doctplserver -d -p 8087:8000 -v \"$(pwd)/docs\":/doc -w /doc ghcr.io/ulenarofmondarth/sphinx-docs sphinx-autobuild --host 0.0.0.0 --port 8000 . _build/html",
"prettier:format": "prettier --config .prettierrc.json --write \"./src/**/*.{ts,js,mjs,json,scss,css}\"",
"lint-staged": "lint-staged",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix"
},
"devDependencies": {
"@commitlint/cli": "19.8.0",
"@commitlint/config-conventional": "19.8.0",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.25.1",
"@league-of-foundry-developers/foundry-vtt-types": "12.331.3-beta",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tsconfig/svelte": "^5.0.4",
"commitizen": "4.3.1",
"cz-conventional-changelog": "3.3.0",
"eslint": "^9.25.1",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-jsdoc": "^50.6.10",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-svelte": "^3.5.1",
"globals": "^16.0.0",
"husky": "^9.1.7",
"lint-staged": "^15.5.1",
"prettier": "^3.5.3",
"svelte": "^5.28.2",
"svelte-preprocess": "^6.0.3",
"typescript": "^5.8.3",
"typescript-eslint": "^8.31.0",
"vite": "^6.3.3",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.1.2"
},
"browserslist": [
">5%",
"not IE 11"
]
}

View File

1
packs/mondarth/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000018

0
packs/mondarth/LOCK Normal file
View File

3
packs/mondarth/LOG Normal file
View File

@ -0,0 +1,3 @@
2025/07/14-17:24:29.774777 7175d6c02b38 Recovering log #16
2025/07/14-17:24:29.779329 7175d6c02b38 Delete type=0 #16
2025/07/14-17:24:29.779410 7175d6c02b38 Delete type=3 #14

7
packs/mondarth/LOG.old Normal file
View File

@ -0,0 +1,7 @@
2025/07/14-14:10:11.092327 7175d8002b38 Recovering log #12
2025/07/14-14:10:11.095077 7175d8002b38 Delete type=0 #12
2025/07/14-14:10:11.095181 7175d8002b38 Delete type=3 #10
2025/07/14-17:23:35.319812 7175d629fb38 Level-0 table #17: started
2025/07/14-17:23:35.319864 7175d629fb38 Level-0 table #17: 0 bytes OK
2025/07/14-17:23:35.321179 7175d629fb38 Delete type=0 #15
2025/07/14-17:23:35.326765 7175d629fb38 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)

Binary file not shown.

BIN
packs/otrikius/000017.ldb Normal file

Binary file not shown.

View File

1
packs/otrikius/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000018

0
packs/otrikius/LOCK Normal file
View File

3
packs/otrikius/LOG Normal file
View File

@ -0,0 +1,3 @@
2025/07/14-17:24:29.783447 7175d8002b38 Recovering log #16
2025/07/14-17:24:29.786378 7175d8002b38 Delete type=0 #16
2025/07/14-17:24:29.786457 7175d8002b38 Delete type=3 #14

7
packs/otrikius/LOG.old Normal file
View File

@ -0,0 +1,7 @@
2025/07/14-14:10:11.098903 7175d6202b38 Recovering log #12
2025/07/14-14:10:11.100733 7175d6202b38 Delete type=0 #12
2025/07/14-14:10:11.100762 7175d6202b38 Delete type=3 #10
2025/07/14-17:23:35.322553 7175d629fb38 Level-0 table #17: started
2025/07/14-17:23:35.325504 7175d629fb38 Level-0 table #17: 17658 bytes OK
2025/07/14-17:23:35.326559 7175d629fb38 Delete type=0 #15
2025/07/14-17:23:35.328370 7175d629fb38 Manual compaction at level-0 from '!adventures!YiGZKfP78SoqZM0k' @ 72057594037927935 : 1 .. '!adventures!YiGZKfP78SoqZM0k' @ 0 : 0; will stop at (end)

Binary file not shown.

5394
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

3
src/index.ts Normal file
View File

@ -0,0 +1,3 @@
Hooks.once('ready', () => {
console.log('ready to go');
});

5
test/some.test.ts Normal file
View File

@ -0,0 +1,5 @@
import { describe, test } from 'vitest';
describe('a thing', () => {
test('does something', () => {});
});

18
tsconfig.json Normal file
View File

@ -0,0 +1,18 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"moduleResolution": "node",
"module": "esnext",
"target": "esnext",
"types": ["svelte", "@league-of-foundry-developers/foundry-vtt-types", "node", "vitest/importMeta"],
"strict": true,
"strictNullChecks": true,
"rootDir": "src",
"baseUrl": ".",
"paths": {
"@lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}

128
vite.config.js Normal file
View File

@ -0,0 +1,128 @@
/* eslint-env node */
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { sveltePreprocess } from 'svelte-preprocess';
import moduleJSON from './module.json' with { type: 'json' };
import tsconfigPaths from 'vite-tsconfig-paths';
// ATTENTION!
// Please modify the below variables: s_PACKAGE_ID and s_SVELTE_HASH_ID appropriately.
const s_PACKAGE_ID = `modules/${moduleJSON.id}`;
// A short additional string to add to Svelte CSS hash values to make yours unique. This reduces the amount of
// duplicated framework CSS overlap between many TRL packages enabled on Foundry VTT at the same time. 'tse' is chosen
// by shortening 'template-svelte-esm'.
const s_SVELTE_HASH_ID = 'monpj';
const s_COMPRESS = false; // Set to true to compress the module bundle.
const s_SOURCEMAPS = true; // Generate sourcemaps for the bundle (recommended).
export default ({ mode }) => {
// Provides a custom hash adding the string defined in `s_SVELTE_HASH_ID` to scoped Svelte styles;
// This is reasonable to do as the framework styles in TRL compiled across `n` different packages will
// be the same. Slightly modifying the hash ensures that your package has uniquely scoped styles for all
// TRL components and makes it easier to review styles in the browser debugger.
const compilerOptions =
mode === 'production'
? {
cssHash: ({ hash, css }) => `svelte-${s_SVELTE_HASH_ID}-${hash(css)}`,
}
: {};
/** @type {import('vite').UserConfig} */
return {
root: 'src/', // Source location / esbuild root.
base: `/${s_PACKAGE_ID}/dist`, // Base module path that 30001 / served dev directory.
publicDir: false, // No public resources to copy.
cacheDir: '../.vite-cache', // Relative from root directory.
test: {
include: ['**/*.{test,spec}.?(c|m)[jt]s?(x)', '../test/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
includeSource: ['**/*.{ts,js}'],
},
define: {
'import.meta.vitest': false,
},
resolve: {
conditions: ['browser', 'import'],
},
esbuild: {
target: ['es2022'],
},
css: {
postcss: { plugins: { autoprefixer: {} }, compress: s_COMPRESS, sourceMap: s_SOURCEMAPS },
},
// About server options:
// - Set to `open` to boolean `false` to not open a browser window automatically. This is useful if you set up a
// debugger instance in your IDE and launch it with the URL: 'http://localhost:30001/game'.
//
// - The top proxy entry redirects requests under the module path for `style.css` and following standard static
// directories: `assets`, `lang`, and `packs` and will pull those resources from the main Foundry / 30000 server.
// This is necessary to reference the dev resources as the root is `/src` and there is no public / static
// resources served with this particular Vite configuration. Modify the proxy rule as necessary for your
// static resources / project.
server: {
port: 31001,
host: true,
allowedHosts: ['foundrymoddev1'],
// open: '/game',
proxy: {
// Serves static files from main Foundry server.
[`^(/${s_PACKAGE_ID}/(assets|lang|packs|dist/${moduleJSON.id}.css))`]: 'http://localhost:31000',
// All other paths besides package ID path are served from main Foundry server.
[`^(?!/${s_PACKAGE_ID}/)`]: 'http://localhost:31000',
// Rewrite incoming `module-id.js` request from Foundry to the dev server `index.js`.
[`/${s_PACKAGE_ID}/dist/${moduleJSON.id}.js`]: {
target: `http://localhost:31001/${s_PACKAGE_ID}/dist`,
rewrite: () => '/index.ts',
},
// Enable socket.io from main Foundry server.
'/socket.io': { target: 'ws://localhost:31000', ws: true },
},
},
build: {
outDir: '../dist',
emptyOutDir: false,
sourcemap: s_SOURCEMAPS,
brotliSize: true,
minify: s_COMPRESS ? 'esbuild' : false,
target: ['es2022'],
lib: {
entry: './index.ts',
formats: ['es'],
fileName: moduleJSON.id,
},
rollupOptions: {
output: {
// Rewrite the default style.css to a more recognizable file name.
assetFileNames: assetInfo => (assetInfo.name === 'style.css' ? `${moduleJSON.id}.css` : assetInfo.name),
},
},
},
// Necessary when using the dev server for top-level await usage inside TRL.
optimizeDeps: {
esbuildOptions: {
target: 'es2022',
},
},
plugins: [
tsconfigPaths(),
svelte({
compilerOptions,
preprocess: sveltePreprocess(),
}),
],
};
};