Initialize project files

This commit is contained in:
Eldritch-Oliver 2025-10-16 23:24:36 -06:00
parent 22a4cc1611
commit 643b2e0c88
16 changed files with 1833 additions and 0 deletions

2
.env.template Normal file
View file

@ -0,0 +1,2 @@
# The absolute path to the Foundry installation to create symlinks to
FOUNDRY_ROOT=""

51
.github/workflows/draft-release.yaml vendored Normal file
View file

@ -0,0 +1,51 @@
name: Create Draft Release
on: [workflow_dispatch]
jobs:
everything:
runs-on: ubuntu-latest
steps:
# Checkout the repository
- uses: actions/checkout@v4
# Install node and NPM
- uses: actions/setup-node@v4
with:
node-version: "19"
# Install required packages
- run: npm install
- name: Reading the module.json for the version
id: "version"
run: cat module.json | echo version=`jq -r ".version"` >> "$GITHUB_OUTPUT"
# Check that tag doesn't exist
- uses: mukunku/tag-exists-action@v1.5.0
id: check-tag
with:
tag: "v${{ steps.version.outputs.version }}"
- name: "Ensure that the tag doesn't exist"
if: ${{ steps.check-tag.outputs.exists == 'true' }}
run: exit 1
- name: Update the manifest with the relevant properties
id: manifest-update
uses: microsoft/variable-substitution@v1
with:
files: "module.json"
env:
download: "https://github.com/${{ github.repository }}/releases/download/v${{ steps.version.outputs.version }}/release.zip"
- name: Create the zip
run: zip -r release.zip module.json packs module langs assets templates README.md
- name: Create the draft release
uses: ncipollo/release-action@v1
with:
tag: "v${{ steps.version.outputs.version }}"
commit: ${{ github.ref }}
draft: true
body: <img aria-hidden="true" src="https://img.shields.io/github/downloads/${{ github.repository }}/v${{ steps.version.outputs.version }}/release.zip?style=flat-square&color=%2300aa00">
generateReleaseNotes: true
artifacts: "release.zip,module.json"

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules/
.env
/foundry

18
.vscode/foundry.html-data.json vendored Normal file
View file

@ -0,0 +1,18 @@
{
"version": 1.1,
"globalAttributes": [
{ "name": "data-tooltip", "description": "The content for the tooltip to display" },
{ "name": "data-tooltip-direction", "description": "The direction that the tooltip renders in, in relation to the element that has the tooltip", "valueSet": "tooltip-direction" }
],
"valueSets": [
{
"name": "tooltip-direction",
"values": [
{ "name": "UP", "description": "Put the tooltip above the element" },
{ "name": "LEFT", "description": "Put the tooltip to the left of the element" },
{ "name": "RIGHT", "description": "Put the tooltip to the right of element" },
{ "name": "DOWN", "description": "Put the tooltip below the element" }
]
}
]
}

16
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,16 @@
{
"files.exclude": {
"**/node_modules": true,
"foundry": true
},
"search.exclude": {
"foundry": true
},
"html.customData": [
"./.vscode/foundry.html-data.json"
],
"workbench.editorAssociations": {
"*.svg": "default",
},
"git.branchProtection": []
}

92
eslint.config.mjs Normal file
View file

@ -0,0 +1,92 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import stylistic from "@stylistic/eslint-plugin";
export default [
// Tell eslint to ignore files that I don't mind being formatted slightly differently
{ ignores: [ `scripts/`, `foundry/` ] },
{
languageOptions: {
globals: globals.browser,
},
},
pluginJs.configs.recommended,
// MARK: Foundry Globals
{
languageOptions: {
globals: {
CONFIG: `writable`,
CONST: `readonly`,
game: `readonly`,
Handlebars: `readonly`,
Hooks: `readonly`,
ui: `readonly`,
Actor: `readonly`,
Item: `readonly`,
foundry: `readonly`,
ChatMessage: `readonly`,
ActiveEffect: `readonly`,
Dialog: `readonly`,
renderTemplate: `readonly`,
TextEditor: `readonly`,
fromUuid: `readonly`,
Combat: `readonly`,
Combatant: `readonly`,
canvas: `readonly`,
Token: `readonly`,
Tour: `readonly`,
},
},
},
// MARK: Project Specific
{
plugins: {
"@stylistic": stylistic,
},
languageOptions: {
globals: {},
},
rules: {
"curly": `error`,
"func-names": [`warn`, `as-needed`],
"grouped-accessor-pairs": `error`,
"no-alert": `error`,
"no-empty": [`error`, { allowEmptyCatch: true }],
"no-implied-eval": `error`,
"no-invalid-this": `error`,
"no-lonely-if": `error`,
"no-unneeded-ternary": `error`,
"no-nested-ternary": `error`,
"no-var": `error`,
"no-unused-vars": [
`error`,
{
"vars": `local`,
"args": `after-used`,
"varsIgnorePattern": `^_`,
"argsIgnorePattern": `^_`,
},
],
"sort-imports": [`warn`, { "ignoreCase": true, "allowSeparatedGroups": true }],
"@stylistic/semi": [`warn`, `always`, { "omitLastInOneLineBlock": true }],
"@stylistic/no-trailing-spaces": `warn`,
"@stylistic/space-before-blocks": [`warn`, `always`],
"@stylistic/space-infix-ops": `warn`,
"@stylistic/eol-last": `warn`,
"@stylistic/operator-linebreak": [`warn`, `before`],
"@stylistic/indent": [`warn`, `tab`],
"@stylistic/brace-style": [`warn`, `stroustrup`, { "allowSingleLine": true }],
"@stylistic/quotes": [`warn`, `backtick`, { "avoidEscape": true }],
"@stylistic/comma-dangle": [`warn`, { arrays: `always-multiline`, objects: `always-multiline`, imports: `always-multiline`, exports: `always-multiline`, functions: `always-multiline` }],
"@stylistic/comma-style": [`warn`, `last`],
"@stylistic/dot-location": [`error`, `property`],
"@stylistic/no-confusing-arrow": `error`,
"@stylistic/no-whitespace-before-property": `error`,
"@stylistic/nonblock-statement-body-position": [
`error`,
`beside`,
{ "overrides": { "while": `below` } },
],
},
},
];

3
langs/en-ca.json Normal file
View file

@ -0,0 +1,3 @@
{
"OFT": {}
}

39
module.json Normal file
View file

@ -0,0 +1,39 @@
{
"id": "oft",
"title": "Oliver's Foundry Tweaks",
"version": "0.0.0",
"authors": [
{ "name": "Oliver" }
],
"download": "",
"manifest": "",
"url": "",
"compatibility": {
"minimum": 13,
"verified": 13,
"maximum": 13
},
"esmodules": [
"module/oft.mjs"
],
"styles": [
{
"src": "styles/main.css",
"layer": "modules.oft"
}
],
"languages": [
{
"lang": "en",
"name": "English (Canadian)",
"path": "langs/en-ca.json"
}
],
"flags": {
"inDev": true,
"hotReload": {
"extensions": ["css", "hbs", "mjs", "svg", "json"],
"paths": ["module", "langs", "styles", "assets"]
}
}
}

5
module/consts.mjs Normal file
View file

@ -0,0 +1,5 @@
export const __ID = `otf`;
export function inDev() {
return game.modules.get(__ID).flags.inDev;
};

5
module/hooks/ready.mjs Normal file
View file

@ -0,0 +1,5 @@
import { __ID } from "../consts.mjs";
Hooks.on(`ready`, () => {
console.log(`${__ID} | Ready`);
});

2
module/oft.mjs Normal file
View file

@ -0,0 +1,2 @@
// Hooks
import "./hooks/ready.mjs";

15
package.json Normal file
View file

@ -0,0 +1,15 @@
{
"devDependencies": {
"@eslint/js": "^9.8.0",
"@foundryvtt/foundryvtt-cli": "^1.0.3",
"@stylistic/eslint-plugin": "^2.6.1",
"dotenv": "^17.2.2",
"eslint": "^9.8.0",
"globals": "^15.9.0"
},
"scripts": {
"link": "node scripts/linkFoundry.mjs",
"lint": "eslint --fix",
"lint:nofix": "eslint"
}
}

1500
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load diff

47
scripts/linkFoundry.mjs Normal file
View file

@ -0,0 +1,47 @@
import { existsSync } from "fs";
import { symlink, unlink } from "fs/promises";
import { join } from "path";
import { config } from "dotenv";
config({ quiet: true });
const root = process.env.FOUNDRY_ROOT;
// Early exit
if (!root) {
console.error(`Must provide a FOUNDRY_ROOT environment variable`);
process.exit(1);
};
// Assert Foundry exists
if (!existsSync(root)) {
console.error(`Foundry root not found.`);
process.exit(1);
};
// Removing existing symlink
if (existsSync(`foundry`)) {
console.log(`Attempting to unlink foundry instance`);
try {
await unlink(`foundry`);
} catch {
console.error(`Failed to unlink foundry folder.`);
process.exit(1);
};
};
// Account for if the root is pointing at an Electron install
let targetRoot = root;
if (existsSync(join(root, `resources`, `app`))) {
console.log(`Switching to use the "${root}/resources/app" directory`);
targetRoot = join(root, `resources`, `app`);
};
// Create symlink
console.log(`Linking foundry source into folder`);
try {
await symlink(targetRoot, `foundry`);
} catch (e) {
console.error(e);
process.exit(1);
};

View file

@ -0,0 +1,35 @@
/*
The intent of this script is to do all of the modifications of the manifest file
that we need to do in order to release the package. This can include removing
dev-only fields/attributes that end users will never, and should never, care
about nor need.
*/
import { readFile, writeFile } from "fs/promises";
const MANIFEST_PATH = `module.json`;
let manifest;
try {
manifest = JSON.parse(await readFile(MANIFEST_PATH, `utf-8`));
} catch {
console.error(`Failed to parse manifest file.`);
process.exit(1);
};
// Filter out dev-only resources
if (manifest.esmodules) {
manifest.esmodules = manifest.esmodules.filter(
filepath => !filepath.startsWith(`dev/`)
);
};
// Remove dev flags
delete manifest.flags?.hotReload;
delete manifest.flags?.inDev;
if (Object.keys(manifest.flags).length === 0) {
delete manifest.flags;
};
await writeFile(MANIFEST_PATH, JSON.stringify(manifest, undefined, `\t`));

0
styles/main.css Normal file
View file