Compare commits

..

No commits in common. "master" and "0.1.0" have entirely different histories.

58 changed files with 3514 additions and 5383 deletions

View file

@ -2,7 +2,4 @@
#
# SPDX-License-Identifier: MIT
/dist
/.pnp.cjs
/.pnp.loader.mjs
/.yarn/
dist

View file

@ -4,14 +4,13 @@
module.exports = {
parserOptions: {
ecmaVersion: 2022,
ecmaVersion: 2020,
sourceType: 'module',
},
env: {
browser: true,
es2021: true,
jquery: true,
es2020: true,
},
extends: ['eslint:recommended', '@typhonjs-fvtt/eslint-config-foundry.js/0.8.0', 'plugin:prettier/recommended'],
@ -19,7 +18,6 @@ module.exports = {
plugins: [],
globals: {
DefaultTokenConfig: false,
PrototypeTokenDocument: false,
},
@ -29,11 +27,9 @@ module.exports = {
overrides: [
{
files: ['./*.js', './*.cjs', './*.mjs', './tools/**/*'],
files: ['./*.js'],
env: {
node: true,
browser: false,
jquery: false,
},
},
],

2
.gitignore vendored
View file

@ -30,5 +30,3 @@ dist
# Junit results
junit.xml
foundry.js

90
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,90 @@
# SPDX-FileCopyrightText: 2021 Johannes Loher
# SPDX-FileCopyrightText: 2021 Oliver Rümpelein
#
# SPDX-License-Identifier: MIT
image: node:lts
stages:
- test
- build
- release
before_script:
- yarn install --immutable
cache: &global_cache
paths:
- .yarn/cache
lint:
stage: test
script:
- yarn lint
cache:
<<: *global_cache
reuse:
stage: test
image:
name: fsfe/reuse:latest
entrypoint: [""]
before_script: []
script:
- reuse lint
build:
stage: build
script:
- yarn build
- mv dist darkness-dependent-vision
cache:
<<: *global_cache
artifacts:
paths:
- darkness-dependent-vision
expire_in: 1 week
.release-template: &release-template
stage: release
before_script:
- yarn install
- apt update
- apt install --yes jq
- REPOSITORY_URL=$(echo "${CI_REPOSITORY_URL}" | sed -e "s|gitlab-ci-token:.*@|${RELEASE_TOKEN}:${RELEASE_TOKEN_SECRET}@|g")
- git remote set-url origin $REPOSITORY_URL
- git config user.name $GITLAB_USER_LOGIN
- git config user.email $GITLAB_USER_EMAIL
- git branch -D ci-processing || true
- git checkout -b ci-processing
cache:
<<: *global_cache
script: |
yarn bump-version --release=${RELEASE_TYPE}
RELEASE_VERSION=$(jq -r '.version' < package.json)
git add package.json src/module.json
git --no-pager diff
git commit -m "release version ${RELEASE_VERSION}"
git tag -f latest
git tag -f ${RELEASE_VERSION}
git push origin ci-processing:${CI_BUILD_REF_NAME}
git push origin latest -f
git push origin ${RELEASE_VERSION}
only:
- master
when: manual
release-patch:
variables:
RELEASE_TYPE: patch
<<: *release-template
release-minor:
variables:
RELEASE_TYPE: minor
<<: *release-template
release-major:
variables:
RELEASE_TYPE: major
<<: *release-template

View file

@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn run commitlint --edit "$1"

View file

@ -1,3 +0,0 @@
SPDX-FileCopyrightText: 2021 Johannes Loher
SPDX-License-Identifier: MIT

View file

@ -2,8 +2,5 @@
#
# SPDX-License-Identifier: MIT
/dist
dist
package-lock.json
/.pnp.cjs
/.pnp.loader.mjs
/.yarn/

View file

@ -1,7 +1,7 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: darkness-dependent-vision
Upstream-Contact: Johannes Loher <johannes.loher@fg4f.de>
Source: https://git2.f3l.de/saluu/darkness-dependent-vision
Source: https://git.f3l.de/ghost/darkness-dependent-vision
Files: .yarn/**
Copyright: Copyright (c) 2016-present, Yarn Contributors. All rights reserved.

View file

@ -1,32 +0,0 @@
# SPDX-FileCopyrightText: 2023 Johannes Loher
#
# SPDX-License-Identifier: MIT
variables:
- &node_image node:lts
when:
- event: push
- event: tag
- event: manual
steps:
install:
image: *node_image
commands:
- yarn install --immutable
lint:
group: test
image: *node_image
commands:
- yarn lint
reuse:
group: test
image: fsfe/reuse:latest
commands:
- reuse lint
build:
group: build
image: *node_image
commands:
- yarn build

View file

@ -1,72 +0,0 @@
# SPDX-FileCopyrightText: 2023 Johannes Loher
#
# SPDX-License-Identifier: MIT
variables:
- &node_image node:lts
when:
event: tag
evaluate: CI_COMMIT_TAG matches "^[0-9]+\\\\.[0-9]+\\\\.[0-9]+$"
depends_on:
- checks
steps:
install:
image: *node_image
commands:
- yarn install --immutable
build:
image: *node_image
environment:
NODE_ENV: production
commands:
- yarn build
package:
group: prepare-release
image: alpine:latest
commands:
- apk update
- apk add zip curl
- mv dist ${CI_REPO_NAME}
- zip -r ${CI_REPO_NAME}.zip ${CI_REPO_NAME}/*
changelog:
group: prepare-release
image: *node_image
commands:
- yarn changelog
release:
image: woodpeckerci/plugin-gitea-release
settings:
base_url: ${CI_FORGE_URL}
title: ${CI_COMMIT_TAG}
note: CHANGELOG.md
files:
- ${CI_REPO_NAME}.zip
- ${CI_REPO_NAME}/module.json
api_key:
from_secret: forge_token
publish-latest-manifest:
group: publish
image: alpine:latest
commands:
- apk update
- apk add curl
- 'curl --header "Authorization: token $${FORGE_TOKEN}" -X "DELETE" "${CI_FORGE_URL}/api/packages/${CI_REPO_OWNER}/generic/${CI_REPO_NAME}/latest/module.json"'
- 'curl --fail --header "Authorization: token $${FORGE_TOKEN}" --upload-file ${CI_REPO_NAME}/module.json "${CI_FORGE_URL}/api/packages/${CI_REPO_OWNER}/generic/${CI_REPO_NAME}/latest/module.json"'
secrets:
- forge_token
publish-to-foundry-admin:
group: publish
image: johannesloher/foundry-publish
environment:
FVTT_DELETE_OBSOLETE_VERSIONS: 'true'
commands:
- export FVTT_MANIFEST_PATH=${CI_REPO_NAME}/module.json
- export FVTT_MANIFEST_URL=${CI_REPO_URL}/releases/download/${CI_COMMIT_TAG}/module.json
- foundry-publish
secrets:
- fvtt_package_id
- fvtt_username
- fvtt_password

View file

@ -1,39 +0,0 @@
# SPDX-FileCopyrightText: 2023 Johannes Loher
#
# SPDX-License-Identifier: MIT
variables:
- &node_image node:lts
when:
event: manual
branch: ${CI_REPO_DEFAULT_BRANCH}
depends_on:
- checks
steps:
install:
image: *node_image
commands:
- yarn install --immutable
release:
image: *node_image
commands:
- apt-get update
- apt-get install --yes jq
- export REPOSITORY_URL=$(echo "${CI_REPO_CLONE_URL}" | sed -e "s|://|://$${FORGE_TOKEN_NAME}:$${FORGE_TOKEN}@|g")
- git remote set-url origin $${REPOSITORY_URL}
- git config user.name woodpecker[bot]
- git config user.email woodpecker[bot]@${CI_SYSTEM_HOST}
- yarn bump-version --release=${RELEASE_TYPE}
- export RELEASE_VERSION=$(jq -r '.version' < package.json)
- git --no-pager diff
- git add package.json module.json
- 'git commit -m "chore(release): $${RELEASE_VERSION}"'
- git tag -f $${RELEASE_VERSION}
- git push origin ${CI_COMMIT_BRANCH}
- git push origin $${RELEASE_VERSION}
secrets:
- forge_token_name
- forge_token

55
.yarn/releases/yarn-2.4.2.cjs vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,13 +1,13 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const relPnpApiPath = "../../../../.pnp.js";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {

View file

@ -1,20 +1,20 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const relPnpApiPath = "../../../../.pnp.js";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint
// Setup the environment to be able to require eslint/lib/api.js
require(absPnpApiPath).setup();
}
}
// Defer to the real eslint your application uses
module.exports = absRequire(`eslint`);
// Defer to the real eslint/lib/api.js your application uses
module.exports = absRequire(`eslint/lib/api.js`);

View file

@ -1,6 +1,6 @@
{
"name": "eslint",
"version": "8.25.0-sdk",
"version": "7.29.0-pnpify",
"main": "./lib/api.js",
"type": "commonjs"
}

View file

@ -1,5 +1,5 @@
# This file is automatically generated by @yarnpkg/sdks.
# Manual changes might be lost!
# This file is automatically generated by PnPify.
# Manual changes will be lost!
integrations:
- vscode

View file

@ -1,13 +1,13 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {createRequire, createRequireFromPath} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../.pnp.cjs";
const relPnpApiPath = "../../../.pnp.js";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {

View file

@ -1,6 +1,6 @@
{
"name": "prettier",
"version": "2.7.1-sdk",
"version": "2.3.2-pnpify",
"main": "./index.js",
"type": "commonjs"
}

View file

@ -1,5 +1,9 @@
# SPDX-FileCopyrightText: 2021 Johannes Loher
#
# SPDX-License-Identifier: MIT
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: '@yarnpkg/plugin-interactive-tools'
spec: "@yarnpkg/plugin-interactive-tools"
yarnPath: .yarn/releases/yarn-3.8.6.cjs
yarnPath: .yarn/releases/yarn-2.4.2.cjs

View file

@ -1,3 +0,0 @@
SPDX-FileCopyrightText: 2021 Johannes Loher
SPDX-License-Identifier: MIT

View file

@ -1,18 +0,0 @@
<!--
SPDX-FileCopyrightText: 2021 Johannes Loher
SPDX-License-Identifier: MIT
-->
This project is being developed under the terms of the
[LIMITED LICENSE AGREEMENT FOR MODULE DEVELOPMENT] for Foundry Virtual Tabletop.
The project itself is licensed under multiple licenses. [REUSE] is used to
specify the licenses for the individual files. Most of the licenses are
specified either inside the source file or by an accompanying `.license` file,
but for some files, the licenses are specified in [.reuse/dep5].
[LIMITED LICENSE AGREEMENT FOR MODULE DEVELOPMENT]: https://foundryvtt.com/article/license/
[REUSE]: https://reuse.software/
[.reuse/dep5]: .reuse/dep5

View file

@ -6,12 +6,6 @@ SPDX-License-Identifier: MIT
# Darkness Dependent Vision
[![status-badge](https://ci.f3l.de/api/badges/1/status.svg)](https://ci.f3l.de/repos/1)
[![REUSE status](https://api.reuse.software/badge/git2.f3l.de/saluu/darkness-dependent-vision)](https://api.reuse.software/info/git2.f3l.de/saluu/darkness-dependent-vision)
[![Forge installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Fdarkness-dependent-vision&colorB=4aa94a)](https://forge-vtt.com/bazaar#package=darkness-dependent-vision)
[![Supported foundry versions](https://img.shields.io/endpoint?url=https://foundryshields.com/version?url=https%3A%2F%2Fgit2.f3l.de%2Fapi%2Fpackages%2Fsaluu%2Fgeneric%2Fdarkness-dependent-vision%2Flatest%2Fmodule.json)](https://git2.f3l.de/saluu/darkness-dependent-vision)
[![Ko-fi](https://img.shields.io/badge/Ko--fi-ghostfvtt-00B9FE?logo=kofi)](https://ko-fi.com/ghostfvtt)
A module for [Foundry Virtual Tabletop] that provides functionality to make the
dim and bright vision of tokens depend on the scene's darkness level.
@ -21,7 +15,7 @@ To install and use the Darkness Dependent Vision module for Foundry Virtual
Tabletop, simply paste the following URL into the **Install Module** dialog on
the Setup menu of the application.
https://git2.f3l.de/api/packages/saluu/generic/darkness-dependent-vision/latest/module.json
https://git.f3l.de/ghost/darkness-dependent-vision/-/raw/latest/src/module.json?inline=false
### libWrapper
@ -41,7 +35,7 @@ Token Configuration:
[![Usage 2](img/usage_2.png)](img/usage_2.png)
In the next image, you can see an example of the module in action: The token is
configured to only have bright vision at a darkness level between 0 and 0.5, but
configured to only have bright vision at a darkness level between 0 and 0.5 but
the scene's darkness level is set to 0.6, so the token has no bright vision. On
the other hand, the token is also configured to have dim vision at a darkness
level between 0 and 0.7, so it _does_ have dim vision.
@ -54,8 +48,9 @@ level between 0 and 0.7, so it _does_ have dim vision.
In order to build this module, recent versions of `node` and `yarn` are
required. Most likely using `npm` also works but only `yarn` is officially
supported. We recommend using the latest lts version of `node`. If you use `nvm`
to manage your `node` versions, you can simply run
supported. We recommend using the latest lts version of `node`, which is
`v14.17.1` at the time of writing. If you use `nvm` to manage your `node`
versions, you can simply run
```
nvm install
@ -63,7 +58,7 @@ nvm install
in the project's root directory.
You also need to install the project's dependencies. To do so, run
You also need to install the the project's dependencies. To do so, run
```
yarn install
@ -107,22 +102,31 @@ Then run
yarn link-project
```
On Windows, creating symlinks requires administrator privileges, so
unfortunately you need to run the above command in an administrator terminal for
it to work.
On Windows, creating symlinks requires administrator privileges so unfortunately
you need to run the above command in an administrator terminal for it to work.
## Licensing
This project is being developed under the terms of the
[LIMITED LICENSE AGREEMENT FOR MODULE DEVELOPMENT] for Foundry Virtual Tabletop.
The project itself is licensed under multiple licenses. [REUSE] is used to
specify the licenses for the individual files. Most of the licenses are
specified either inside the source file or by an accompanying `.license` file,
but for some files, the licenses are specified in [.reuse/dep5].
The project itself is licensed under multiple licenses. It is difficult to keep
this section up to date, so here is a brief summary as of June 2021:
* The images in [img] are licensed under [CC BY 4.0].
* The files in [.yarn] by the [Yarn] Contributors are licensed under
[BSD-2-Clause].
* Other files are licensed under [MIT].
For more accurate information, check the individual files.
[Foundry Virtual Tabletop]: http://foundryvtt.com
[libWrapper]: https://github.com/ruipin/fvtt-lib-wrapper
[Yarn]: https://github.com/yarnpkg/berry
[LIMITED LICENSE AGREEMENT FOR MODULE DEVELOPMENT]: https://foundryvtt.com/article/license/
[REUSE]: https://reuse.software/
[.reuse/dep5]: .reuse/dep5
[CC BY 4.0]: LICENSES/CC-BY-4.0.txt
[MIT]: LICENSES/MIT.txt
[BSD-2-Clause]: LICENSES/BSD-2-Clause.txt
[img]: img
[.yarn]: .yarn

View file

@ -1,5 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
module.exports = { extends: ['@commitlint/config-conventional'] };

202
gulpfile.js Normal file
View file

@ -0,0 +1,202 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
const { rollup } = require('rollup');
const argv = require('yargs').argv;
const chalk = require('chalk');
const fs = require('fs-extra');
const gulp = require('gulp');
const path = require('path');
const rollupConfig = require('./rollup.config');
const semver = require('semver');
/********************/
/* CONFIGURATION */
/********************/
const name = path.basename(path.resolve('.'));
const sourceDirectory = './src';
const distDirectory = './dist';
const sourceFileExtension = 'js';
const staticFiles = ['lang', 'templates', 'module.json'];
const getDownloadURL = (version) =>
`https://git.f3l.de/ghost/darkness-dependent-vision/-/jobs/artifacts/${version}/download?job=build`;
/********************/
/* BUILD */
/********************/
/**
* Build the distributable JavaScript code
*/
async function buildCode() {
const build = await rollup({ input: rollupConfig.input, plugins: rollupConfig.plugins });
return build.write(rollupConfig.output);
}
/**
* Copy static files
*/
async function copyFiles() {
for (const file of staticFiles) {
if (fs.existsSync(`${sourceDirectory}/${file}`)) {
await fs.copy(`${sourceDirectory}/${file}`, `${distDirectory}/${file}`);
}
}
}
/**
* Watch for changes for each build step
*/
function buildWatch() {
gulp.watch(`${sourceDirectory}/**/*.${sourceFileExtension}`, { ignoreInitial: false }, buildCode);
gulp.watch(
staticFiles.map((file) => `${sourceDirectory}/${file}`),
{ ignoreInitial: false },
copyFiles,
);
}
/********************/
/* CLEAN */
/********************/
/**
* Remove built files from `dist` folder while ignoring source files
*/
async function clean() {
const files = [...staticFiles, 'module'];
console.log(' ', chalk.yellow('Files to clean:'));
console.log(' ', chalk.blueBright(files.join('\n ')));
for (const filePath of files) {
await fs.remove(`${distDirectory}/${filePath}`);
}
}
/********************/
/* LINK */
/********************/
/**
* Get the data path of Foundry VTT based on what is configured in `foundryconfig.json`
*/
function getDataPath() {
const config = fs.readJSONSync('foundryconfig.json');
if (config?.dataPath) {
if (!fs.existsSync(path.resolve(config.dataPath))) {
throw new Error('User Data path invalid, no Data directory found');
}
return path.resolve(config.dataPath);
} else {
throw new Error('No User Data path defined in foundryconfig.json');
}
}
/**
* Link build to User Data folder
*/
async function linkUserData() {
let destinationDirectory;
if (fs.existsSync(path.resolve(sourceDirectory, 'module.json'))) {
destinationDirectory = 'modules';
} else {
throw new Error(`Could not find ${chalk.blueBright('module.json')}`);
}
const linkDirectory = path.resolve(getDataPath(), destinationDirectory, name);
if (argv.clean || argv.c) {
console.log(chalk.yellow(`Removing build in ${chalk.blueBright(linkDirectory)}.`));
await fs.remove(linkDirectory);
} else if (!fs.existsSync(linkDirectory)) {
console.log(chalk.green(`Linking dist to ${chalk.blueBright(linkDirectory)}.`));
await fs.ensureDir(path.resolve(linkDirectory, '..'));
await fs.symlink(path.resolve(distDirectory), linkDirectory);
}
}
/********************/
/* VERSIONING */
/********************/
/**
* Get the contents of the manifest file as object.
*/
function getManifest() {
const manifestPath = `${sourceDirectory}/module.json`;
if (fs.existsSync(manifestPath)) {
return {
file: fs.readJSONSync(manifestPath),
name: 'module.json',
};
}
}
/**
* Get the target version based on on the current version and the argument passed as release.
*/
function getTargetVersion(currentVersion, release) {
if (['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'].includes(release)) {
return semver.inc(currentVersion, release);
} else {
return semver.valid(release);
}
}
/**
* Update version and download URL.
*/
function bumpVersion(cb) {
const packageJson = fs.readJSONSync('package.json');
const manifest = getManifest();
if (!manifest) cb(Error(chalk.red('Manifest JSON not found')));
try {
const release = argv.release || argv.r;
const currentVersion = packageJson.version;
if (!release) {
return cb(Error('Missing release type'));
}
const targetVersion = getTargetVersion(currentVersion, release);
if (!targetVersion) {
return cb(new Error(chalk.red('Error: Incorrect version arguments')));
}
if (targetVersion === currentVersion) {
return cb(new Error(chalk.red('Error: Target version is identical to current version')));
}
console.log(`Updating version number to '${targetVersion}'`);
packageJson.version = targetVersion;
fs.writeJSONSync('package.json', packageJson, { spaces: 2 });
manifest.file.version = targetVersion;
manifest.file.download = getDownloadURL(targetVersion);
fs.writeJSONSync(`${sourceDirectory}/${manifest.name}`, manifest.file, { spaces: 2 });
return cb();
} catch (err) {
cb(err);
}
}
const execBuild = gulp.parallel(buildCode, copyFiles);
exports.build = gulp.series(clean, execBuild);
exports.watch = buildWatch;
exports.clean = clean;
exports.link = linkUserData;
exports.bumpVersion = bumpVersion;

View file

@ -1,11 +0,0 @@
{
"DarknessDependentVision.WarningLackingPermissionToConfigure": "Dir fehlt die Berechtigung diese Figur zu konfigurieren!",
"DarknessDependentVision.Title": "Einstellungen zur dunkelheitsabhängigen Sicht",
"DarknessDependentVision.TokenConfigHeaderButtonLabel": "DDV",
"DarknessDependentVision.DimVisionDarknessRange": "Dämmersicht Dunkelheitsbereich",
"DarknessDependentVision.DimVisionDarknessRangeHint": "Du kannst einen Bereich an Dunkelheitswerten angeben, in denen diese Figur Dämmersicht hat.",
"DarknessDependentVision.BrightVisionDarknessRange": "Helle Sicht Dunkelheitsbereich",
"DarknessDependentVision.BrightVisionDarknessRangeHint": "Du kannst einen Bereich an Dunkelheitswerten angeben, in denen diese Figur helle Sicht hat.",
"DarknessDependentVision.ConfigurationViaHeaderButtonName": "Konfiguration per Button in der Titelleiste",
"DarknessDependentVision.ConfigurationViaHeaderButtonHint": "Ist diese Einstellung ausgewählt, so erscheint in den Figur Einstellungen ein zusätzlicher Button in der Titelleiste, der ein weiteres Fester öffnet, über das die duneklheitsabhängige Sicht konfiguriert werden kann. Ist sie deaktiviert, so erscheineinen die entsprechenden Eingabefelder direkt im Vision Tab der Figur Einstellungen."
}

View file

@ -1,3 +0,0 @@
SPDX-FileCopyrightText: 2021 Johannes Loher
SPDX-License-Identifier: MIT

View file

@ -1,41 +0,0 @@
{
"name": "darkness-dependent-vision",
"id": "darkness-dependent-vision",
"title": "Darkness Dependent Vision",
"description": "A module for Foundry Virtual Tabletop that provides functionality to make the dim and bright vision of tokens depend on the scene's darkness level.",
"version": "0.3.13",
"author": "Johannes Loher",
"authors": [
{
"name": "Johannes Loher",
"email": "johannes.loher@fg4f.de"
}
],
"minimumCoreVersion": "9.236",
"compatibleCoreVersion": "9",
"compatibility": {
"minimum": "9.236",
"verified": "9",
"maximum": "9"
},
"esmodules": ["darkness-dependent-vision.js"],
"languages": [
{
"lang": "de",
"name": "Deutsch",
"path": "lang/de.json"
},
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
],
"url": "https://git2.f3l.de/saluu/darkness-dependent-vision",
"manifest": "https://git2.f3l.de/api/packages/saluu/generic/darkness-dependent-vision/latest/module.json",
"download": "https://git2.f3l.de/saluu/darkness-dependent-vision/releases/download/0.3.13/darkness-dependent-vision.zip",
"bugs": "https://git2.f3l.de/saluu/darkness-dependent-vision/issues",
"changelog": "https://git2.f3l.de/saluu/darkness-dependent-vision/releases/tag/0.3.13",
"readme": "https://git2.f3l.de/saluu/darkness-dependent-vision/raw/tag/0.3.13/README.md",
"license": "https://git2.f3l.de/saluu/darkness-dependent-vision/raw/tag/0.3.13/LICENSE.md"
}

View file

@ -1,16 +1,16 @@
{
"private": true,
"name": "darkness-dependent-vision",
"version": "0.3.13",
"version": "0.1.0",
"description": "A module for Foundry Virtual Tabletop that provides functionality to make the dim and bright vision of tokens depend on the scene's darkness level.",
"license": "https://git2.f3l.de/saluu/darkness-dependent-vision/src/branch/master/LICENSE.md",
"homepage": "https://git2.f3l.de/saluu/darkness-dependent-vision",
"license": "https://git.f3l.de/ghost/darkness-dependent-vision#licensing",
"homepage": "https://git.f3l.de/ghost/darkness-dependent-vision",
"repository": {
"type": "git",
"url": "https://git2.f3l.de/saluu/darkness-dependent-vision"
"url": "https://git.f3l.de/ghost/darkness-dependent-vision"
},
"bugs": {
"url": "https://git2.f3l.de/saluu/darkness-dependent-vision/issues"
"url": "https://git.f3l.de/ghost/darkness-dependent-vision/-/issues"
},
"contributors": [
{
@ -18,48 +18,35 @@
"email": "johannes.loher@fg4f.de"
}
],
"type": "module",
"scripts": {
"build": "run-s clean:files build:files",
"build:files": "rollup -c",
"watch": "rollup -c -w",
"link-package": "node ./tools/link-package.mjs",
"clean": "run-p clean:files clean:link",
"clean:files": "rimraf dist",
"clean:link": "node ./tools/link-package.mjs --clean",
"lint": "eslint --ext .ts,.js,.cjs,.mjs .",
"lint:fix": "eslint --ext .ts,.js,.cjs,.mjs --fix .",
"format": "prettier --write \"./**/*.(ts|js|cjs|mjs|json|scss|yml)\"",
"typecheck": "tsc --noEmit",
"bump-version": "node ./tools/bump-version.mjs",
"postinstall": "husky install",
"changelog": "conventional-changelog -p conventionalcommits -o CHANGELOG.md -r 2"
"build": "gulp build",
"build:watch": "gulp watch",
"link-project": "gulp link",
"clean": "gulp clean",
"clean:link": "gulp link --clean",
"bump-version": "gulp bumpVersion",
"lint": "eslint --ext .js .",
"lint:fix": "eslint --ext .js --fix .",
"format": "prettier --write \"./**/*.(js|json|css)\"",
"postinstall": "husky install"
},
"devDependencies": {
"@commitlint/cli": "19.5.0",
"@commitlint/config-conventional": "19.5.0",
"@guanghechen/rollup-plugin-copy": "6.0.2",
"@typhonjs-fvtt/eslint-config-foundry.js": "0.8.0",
"conventional-changelog-cli": "5.0.0",
"conventional-changelog-conventionalcommits": "8.0.0",
"eslint": "8.57.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "4.2.1",
"fs-extra": "11.2.0",
"gulp": "5.0.0",
"husky": "9.1.6",
"lint-staged": "15.2.10",
"npm-run-all": "4.1.5",
"prettier": "2.8.8",
"rimraf": "6.0.1",
"rollup": "4.24.0",
"rollup-plugin-terser": "7.0.2",
"semver": "7.6.3",
"yargs": "17.7.2"
"@typhonjs-fvtt/eslint-config-foundry.js": "^0.8.0",
"chalk": "^4.1.1",
"eslint": "^7.29.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"fs-extra": "^10.0.0",
"gulp": "^4.0.2",
"husky": "^6.0.0",
"lint-staged": "^11.0.0",
"prettier": "^2.3.2",
"rollup": "^2.52.3",
"semver": "^7.3.5",
"yargs": "^17.0.1"
},
"lint-staged": {
"*.(js|mjs|cjs)": "eslint --fix",
"*.(json|css|yml)": "prettier --write"
},
"packageManager": "yarn@3.8.6"
"*.(js)": "eslint --fix",
"*.(json|css)": "prettier --write"
}
}

View file

@ -1,7 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base", ":automergeAll", ":automergeBranch", ":prHourlyLimitNone", ":prConcurrentLimitNone"],
"lockFileMaintenance": {
"enabled": true
}
}

View file

@ -1,3 +0,0 @@
SPDX-FileCopyrightText: 2021 Johannes Loher
SPDX-License-Identifier: MIT

View file

@ -2,40 +2,11 @@
//
// SPDX-License-Identifier: MIT
import { copy } from '@guanghechen/rollup-plugin-copy';
import { terser } from 'rollup-plugin-terser';
import { distDirectory, name, sourceDirectory } from './tools/const.mjs';
const staticFiles = [
'.reuse',
'img',
'lang',
'LICENSE.md',
'LICENSES',
'module.json.license',
'module.json',
'README.md',
'templates',
];
const isProduction = process.env.NODE_ENV === 'production';
/**
* @type {import('rollup').RollupOptions}
*/
const config = {
input: { [`${name}`]: `${sourceDirectory}/${name}.js` },
module.exports = {
input: 'src/module/darkness-dependent-vision.js',
output: {
dir: distDirectory,
dir: 'dist/module',
format: 'es',
sourcemap: true,
assetFileNames: '[name].[ext]',
},
plugins: [
copy({
targets: [{ src: staticFiles, dest: distDirectory }],
}),
isProduction && terser({ ecma: 2020, keep_fnames: true }),
],
};
export default config;

View file

@ -1,10 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
export default async function registerHandlebarsPartials() {
const templatePaths = [
'modules/darkness-dependent-vision/templates/darkness-dependent-vision-config-form-groups.hbs',
];
await loadTemplates(templatePaths);
}

View file

@ -1,21 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { packageName } from '../config';
export default function registerForRenderTokenConfigHook() {
Hooks.on('renderTokenConfig', onRenderTokenConfig);
}
async function onRenderTokenConfig(app, html, data) {
if (game.settings.get(packageName, 'configurationViaHeaderButton')) {
return;
}
const contents = await renderTemplate(
'modules/darkness-dependent-vision/templates/darkness-dependent-vision-config-form-groups.hbs',
data,
);
html.find(`div[data-tab="vision"] .form-group`).last().after(contents);
app.setPosition({ height: 'auto' });
}

View file

@ -5,7 +5,5 @@
"DarknessDependentVision.DimVisionDarknessRange": "Dim Vision Darkness Range",
"DarknessDependentVision.DimVisionDarknessRangeHint": "You may specify a range of darkness levels during which this token has dim vision.",
"DarknessDependentVision.BrightVisionDarknessRange": "Bright Vision Darkness Range",
"DarknessDependentVision.BrightVisionDarknessRangeHint": "You may specify a range of darkness levels during which this token has bright vision.",
"DarknessDependentVision.ConfigurationViaHeaderButtonName": "Configuration via Header Button",
"DarknessDependentVision.ConfigurationViaHeaderButtonHint": "If checked, a header button that opens a separate window to configure darkness dependent vision is added to the Token Configuration. If unchecked, the corresponding configuration fields are injected directly into the Vision tab of the Token Configuration."
"DarknessDependentVision.BrightVisionDarknessRangeHint": "You may specify a range of darkness levels during which this token has bright vision."
}

30
src/module.json Normal file
View file

@ -0,0 +1,30 @@
{
"name": "darkness-dependent-vision",
"title": "Darkness Dependent Vision",
"description": "A module for Foundry Virtual Tabletop that provides functionality to make the dim and bright vision of tokens depend on the scene's darkness level.",
"version": "0.1.0",
"author": "Johannes Loher",
"authors": [
{
"name": "Johannes Loher",
"email": "johannes.loher@fg4f.de"
}
],
"minimumCoreVersion": "0.8.8",
"compatibleCoreVersion": "0.8.8",
"esmodules": ["module/darkness-dependent-vision.js"],
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
],
"url": "https://git.f3l.de/ghost/darkness-dependent-vision",
"manifest": "https://git.f3l.de/ghost/darkness-dependent-vision/-/raw/latest/src/module.json?inline=false",
"download": "https://git.f3l.de/ghost/darkness-dependent-vision/-/jobs/artifacts/0.1.0/download?job=build",
"license": "https://git.f3l.de/ghost/darkness-dependent-vision#licensing",
"readme": "https://git.f3l.de/ghost/darkness-dependent-vision/-/blob/master/README.md",
"bugs": "https://git.f3l.de/ghost/darkness-dependent-vision/-/issues",
"changelog": "https://git.f3l.de/ghost/darkness-dependent-vision/-/releases"
}

View file

@ -52,10 +52,6 @@ export class DarknessDependentVisionConfig extends FormApplication {
return `${name}: ${game.i18n.localize('DarknessDependentVision.Title')}`;
}
get isDefault() {
return this.options.tokenConfig instanceof DefaultTokenConfig;
}
async getData() {
const data = this.isPrototype ? this.actor.data.token : this.token.data;
return {
@ -73,23 +69,9 @@ export class DarknessDependentVisionConfig extends FormApplication {
}
async _updateObject(event, formData) {
// Configure the Default Token Configuration
if (this.isDefault) {
const current = game.settings.get('core', DefaultTokenConfig.SETTING);
const update = foundry.utils.mergeObject(current, formData, { inplace: false });
const result = await game.settings.set('core', DefaultTokenConfig.SETTING, update);
const tokenConfig = this.options.tokenConfig;
tokenConfig.data = new foundry.data.TokenData(result);
tokenConfig.object = new TokenDocument(tokenConfig.data, { actor: null });
tokenConfig.token = tokenConfig.object;
tokenConfig.render();
return result;
}
// Configure the Prototype Token data of an Actor
if (this.isPrototype) return this.actor.update({ token: formData });
// Update an embedded Token document
return this.token.update(formData);
else return this.token.update(formData);
}
}

View file

@ -4,7 +4,6 @@
import registerForGetTokenConfigHeaderButtonsHook from './hooks/getTokenConfigHeaderButtons';
import registerForInitHook from './hooks/init';
import registerForRenderTokenConfigHook from './hooks/renderTokenConfig';
import registerForUpdateSceneHook from './hooks/updateScene';
import registerForUpdateTokenHook from './hooks/updateToken';
@ -16,5 +15,4 @@ export default function registerForHooks() {
registerForUpdateSceneHook();
registerForUpdateTokenHook();
registerForGetTokenConfigHeaderButtonsHook();
registerForRenderTokenConfigHook();
}

View file

@ -2,7 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { packageName } from '../config';
import { DarknessDependentVisionConfig } from '../darkness-dependent-vision-config';
export default function registerForGetTokenConfigHeaderButtonsHook() {
@ -14,15 +13,12 @@ export default function registerForGetTokenConfigHeaderButtonsHook() {
* @param {ApplicationHeaderButton[]} buttons
*/
function onGetTokenConfigHeaderButtons(tokenConfig, buttons) {
if (!game.settings.get(packageName, 'configurationViaHeaderButton')) {
return;
}
buttons.unshift({
label: 'DarknessDependentVision.TokenConfigHeaderButtonLabel',
class: 'configure-darkness-dependent-vision',
icon: 'fas fa-eye',
onclick: async () => {
return new DarknessDependentVisionConfig(tokenConfig.object, { tokenConfig }).render(true);
return new DarknessDependentVisionConfig(tokenConfig.object).render(true);
},
});
}

View file

@ -3,17 +3,15 @@
// SPDX-License-Identifier: MIT
import { packageName } from '../config';
import registerHandlebarsPartials from '../handlebars-partials';
import logger from '../logger';
import registerSettings from '../setiings';
import { libWrapper } from '../shims/libWrapperShim';
import { getBrightRadius, getDimRadius, updateVisionSource } from '../wrappers/token';
import { getBrightRadius, getDimRadius, updateSource } from '../wrappers/token';
export default function registerForInitHook() {
Hooks.on('init', onInit);
}
async function onInit() {
function onInit() {
logger.info(`Initializing ${packageName}`);
const dimRadiusTarget = 'Token.prototype.dimRadius';
@ -30,13 +28,5 @@ async function onInit() {
logger.warn(`Failed to override ${brightRadiusTarget}, some things might not work correctly:`, e);
}
const updateVisionSourceTarget = 'Token.prototype.updateVisionSource';
try {
libWrapper.register(packageName, updateVisionSourceTarget, updateVisionSource, 'OVERRIDE');
} catch (e) {
logger.warn(`Failed to override ${updateVisionSourceTarget}, some things might not work correctly:`, e);
}
registerSettings();
await registerHandlebarsPartials();
libWrapper.register(packageName, 'Token.prototype.updateSource', updateSource, 'WRAPPER');
}

View file

@ -8,6 +8,6 @@ export default function registerForUpdateSceneHook() {
function onUpdateScene(scene, change) {
if (change.darkness != null) {
scene.getEmbeddedCollection('Token').forEach((tokenDocument) => tokenDocument.object.updateVisionSource());
scene.getEmbeddedCollection('Token').forEach((tokenDocument) => tokenDocument.object.updateSource());
}
}

View file

@ -7,13 +7,13 @@ export default function registerForUpdateTokenHook() {
}
function onUpdateToken(token, change) {
const shouldUpdateVisionSource = [
const shouldUpdateSource = [
'dimVisionDarknessMin',
'dimVisionDarknessMax',
'brightVisionDarknessMin',
'brightVisionDarknessMax',
].some((flagKey) => `flags.darkness-dependent-vision.${flagKey}` in foundry.utils.flattenObject(change));
if (shouldUpdateVisionSource) {
token.object.updateVisionSource();
if (shouldUpdateSource) {
token.object.updateSource();
}
}

View file

@ -1,16 +1,11 @@
// SPDX-License-Identifier: MIT
// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro
'use strict';
// 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
// A shim for the libWrapper library
export let libWrapper = undefined;
export const VERSIONS = [1, 12, 1];
export const TGT_SPLIT_RE = new RegExp('([^.[]+|\\[(\'([^\'\\\\]|\\\\.)+?\'|"([^"\\\\]|\\\\.)+?")\\])', 'g');
export const TGT_CLEANUP_RE = new RegExp('(^\\[\'|\'\\]$|^\\["|"\\]$)', 'g');
// Main shim code
Hooks.once('init', () => {
// Check if the real module is already loaded - if so, use it
if (globalThis.libWrapper && !(globalThis.libWrapper.is_fallback ?? true)) {
@ -24,31 +19,14 @@ Hooks.once('init', () => {
return true;
}
static get WRAPPER() {
return 'WRAPPER';
}
static get MIXED() {
return 'MIXED';
}
static get OVERRIDE() {
return 'OVERRIDE';
}
static register(package_id, target, fn, type = 'MIXED', { chain = undefined, bind = [] } = {}) {
static register(package_id, target, fn, type = 'MIXED', { chain = undefined } = {}) {
const is_setter = target.endsWith('#set');
target = !is_setter ? target : target.slice(0, -4);
const split = target.match(TGT_SPLIT_RE).map((x) => x.replace(/\\(.)/g, '$1').replace(TGT_CLEANUP_RE, ''));
const split = target.split('.');
const fn_name = split.pop();
const root_nm = split.splice(0, 1)[0];
let obj, fn_name;
if (split.length == 0) {
obj = globalThis;
fn_name = root_nm;
} else {
const _eval = eval;
fn_name = split.pop();
obj = split.reduce((x, y) => x[y], globalThis[root_nm] ?? _eval(root_nm));
}
const _eval = eval; // The browser doesn't expose all global variables (e.g. 'Game') inside globalThis, but it does to an eval. We copy it to a variable to have it run in global scope.
const obj = split.reduce((x, y) => x[y], globalThis[root_nm] ?? _eval(root_nm));
let iObj = obj;
let descriptor = null;
@ -58,19 +36,18 @@ Hooks.once('init', () => {
iObj = Object.getPrototypeOf(iObj);
}
if (!descriptor || descriptor?.configurable === false)
throw new Error(
`libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`,
);
throw `libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`;
let original = null;
const wrapper =
chain ?? (type.toUpperCase?.() != 'OVERRIDE' && type != 3)
? function (...args) {
return fn.call(this, original.bind(this), ...bind, ...args);
chain ?? type != 'OVERRIDE'
? function () {
return fn.call(this, original.bind(this), ...arguments);
}
: function (...args) {
return fn.call(this, ...bind, ...args);
: function () {
return fn.apply(this, arguments);
};
if (!is_setter) {
if (descriptor.value) {
original = descriptor.value;
@ -80,7 +57,7 @@ Hooks.once('init', () => {
descriptor.get = wrapper;
}
} else {
if (!descriptor.set) throw new Error(`libWrapper Shim: '${target}' does not have a setter`);
if (!descriptor.set) throw `libWrapper Shim: '${target}' does not have a setter`;
original = descriptor.set;
descriptor.set = wrapper;
}
@ -91,8 +68,11 @@ Hooks.once('init', () => {
};
//************** USER CUSTOMIZABLE:
// Set up the ready hook that shows the "libWrapper not installed" warning dialog. Remove if undesired.
{
// Whether to warn GM that the fallback is being used
const WARN_FALLBACK = true;
// Set up the ready hook that shows the "libWrapper not installed" warning dialog
if (WARN_FALLBACK) {
//************** USER CUSTOMIZABLE:
// Package ID & Package Title - by default attempts to auto-detect, but you might want to hardcode your package ID and title here to avoid potential auto-detect issues
const [PACKAGE_ID, PACKAGE_TITLE] = (() => {

View file

@ -25,19 +25,23 @@ export function getBrightRadius() {
}
/**
* Update an Token vision source associated for this token.
* @param {boolean} [defer] Defer refreshing the LightingLayer to manually call that refresh later.
* @param {boolean} [deleted] Indicate that this vision source has been deleted.
* @param {boolean} [skipUpdateFog] Never update the Fog exploration progress for this update.
* Update the light and vision source objects associated with this Token
* @typedef {({defer, deleted, noUpdateFog}?: {defer?: boolean, deleted?: boolean, noUpdateFog?: boolean}) => void} UpdateSourceFunction
* @param {UpdateSourceFunction} wrapped The function that is wrapped by this function and needs to be called next in the chain
* @param {boolean} [defer] Defer refreshing the SightLayer to manually call that refresh later.
* @param {boolean} [deleted] Indicate that this light source has been deleted.
* @param {boolean} [noUpdateFog] Never update the Fog exploration progress for this update.
*/
export function updateVisionSource({ defer = false, deleted = false, skipUpdateFog = false } = {}) {
// Prepare data
export function updateSource(wrapped, { defer = false, deleted = false, noUpdateFog = false } = {}) {
wrapped({ defer, deleted, noUpdateFog });
// Prepare some common data
const origin = this.getSightOrigin();
const sourceId = this.sourceId;
const d = canvas.dimensions;
const isVisionSource = this._isVisionSource();
// Initialize vision source
// Update vision source
const isVisionSource = this._isVisionSource();
if (isVisionSource && !deleted) {
const dimSight = getDimVision.call(this);
const brightSight = getBrightVision.call(this);
@ -52,16 +56,14 @@ export function updateVisionSource({ defer = false, deleted = false, skipUpdateF
rotation: this.data.rotation,
});
canvas.sight.sources.set(sourceId, this.vision);
if (!defer) {
this.vision.drawLight();
canvas.sight.refresh({ noUpdateFog });
}
} else {
canvas.sight.sources.delete(sourceId);
if (isVisionSource && !defer) canvas.sight.refresh();
}
// Remove vision source
else canvas.sight.sources.delete(sourceId);
// Schedule a perception update
if (!defer && (isVisionSource || deleted))
canvas.perception.schedule({
sight: { refresh: true, skipUpdateFog },
});
}
/**

View file

@ -1,23 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { packageName } from './config';
export default function registerSettings() {
game.settings.register(packageName, 'configurationViaHeaderButton', {
name: 'DarknessDependentVision.ConfigurationViaHeaderButtonName',
hint: 'DarknessDependentVision.ConfigurationViaHeaderButtonHint',
scope: 'client',
config: true,
type: Boolean,
default: true,
onChange: () =>
Object.values(ui.windows)
.filter((w) => w instanceof TokenConfig)
.forEach(async (w) => {
await w.close();
w.render(true);
}),
});
}

View file

@ -0,0 +1,40 @@
{{!--
SPDX-FileCopyrightText: 2021 Johannes Loher
//
SPDX-License-Identifier: MIT
--}}
<form class="{{cssClasses}}" autocomplete="off">
<div class="form-group">
<label>{{ localize 'DarknessDependentVision.DimVisionDarknessRange' }}</label>
<div class="form-fields">
<label for="flags.darkness-dependent-vision.dimVisionDarknessMin">{{ localize "Between" }}</label>
<input type="number" name="flags.darkness-dependent-vision.dimVisionDarknessMin"
value="{{object.flags.darkness-dependent-vision.dimVisionDarknessMin}}" min="0" max="1" step="any"
placeholder="0" />
<label for="flags.darkness-dependent-vision.dimVisionDarknessMax">{{ localize "and" }}</label>
<input type="number" name="flags.darkness-dependent-vision.dimVisionDarknessMax"
value="{{object.flags.darkness-dependent-vision.dimVisionDarknessMax}}" min="0" max="1" step="any"
placeholder="1" />
</div>
<p class="hint">{{ localize "DarknessDependentVision.DimVisionDarknessRangeHint" }}</p>
</div>
<div class="form-group">
<label>{{ localize 'DarknessDependentVision.BrightVisionDarknessRange' }}</label>
<div class="form-fields">
<label for="flags.darkness-dependent-vision.brightVisionDarknessMin">{{ localize "Between" }}</label>
<input type="number" name="flags.darkness-dependent-vision.brightVisionDarknessMin"
value="{{object.flags.darkness-dependent-vision.brightVisionDarknessMin}}" min="0" max="1" step="any"
placeholder="0" />
<label for="flags.darkness-dependent-vision.brightVisionDarknessMax">{{ localize "and" }}</label>
<input type="number" name="flags.darkness-dependent-vision.brightVisionDarknessMax"
value="{{object.flags.darkness-dependent-vision.brightVisionDarknessMax}}" min="0" max="1" step="any"
placeholder="1" />
</div>
<p class="hint">{{ localize "DarknessDependentVision.BrightVisionDarknessRangeHint" }}</p>
</div>
<button type="submit" name="submit" value="1"><i class="far fa-save"></i> {{localize "TOKEN.Update"}}</button>
</form>

View file

@ -1,35 +0,0 @@
{{!--
SPDX-FileCopyrightText: 2021 Johannes Loher
//
SPDX-License-Identifier: MIT
--}}
<div class="form-group slim">
<label>{{ localize 'DarknessDependentVision.DimVisionDarknessRange' }}</label>
<div class="form-fields">
<label for="flags.darkness-dependent-vision.dimVisionDarknessMin">{{ localize "Between" }}</label>
<input type="number" name="flags.darkness-dependent-vision.dimVisionDarknessMin"
value="{{object.flags.darkness-dependent-vision.dimVisionDarknessMin}}" min="0" max="1" step="any"
placeholder="0" />
<label for="flags.darkness-dependent-vision.dimVisionDarknessMax">{{ localize "and" }}</label>
<input type="number" name="flags.darkness-dependent-vision.dimVisionDarknessMax"
value="{{object.flags.darkness-dependent-vision.dimVisionDarknessMax}}" min="0" max="1" step="any"
placeholder="1" />
</div>
<p class="hint">{{ localize "DarknessDependentVision.DimVisionDarknessRangeHint" }}</p>
</div>
<div class="form-group slim">
<label>{{ localize 'DarknessDependentVision.BrightVisionDarknessRange' }}</label>
<div class="form-fields">
<label for="flags.darkness-dependent-vision.brightVisionDarknessMin">{{ localize "Between" }}</label>
<input type="number" name="flags.darkness-dependent-vision.brightVisionDarknessMin"
value="{{object.flags.darkness-dependent-vision.brightVisionDarknessMin}}" min="0" max="1" step="any"
placeholder="0" />
<label for="flags.darkness-dependent-vision.brightVisionDarknessMax">{{ localize "and" }}</label>
<input type="number" name="flags.darkness-dependent-vision.brightVisionDarknessMax"
value="{{object.flags.darkness-dependent-vision.brightVisionDarknessMax}}" min="0" max="1" step="any"
placeholder="1" />
</div>
<p class="hint">{{ localize "DarknessDependentVision.BrightVisionDarknessRangeHint" }}</p>
</div>

View file

@ -1,10 +0,0 @@
{{!--
SPDX-FileCopyrightText: 2021 Johannes Loher
//
SPDX-License-Identifier: MIT
--}}
<form class="{{cssClasses}}" autocomplete="off">
{{> modules/darkness-dependent-vision/templates/darkness-dependent-vision-config-form-groups.hbs}}
<button type="submit" name="submit" value="1"><i class="far fa-save"></i> {{localize "TOKEN.Update"}}</button>
</form>

View file

@ -1,93 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
import fs from 'fs-extra';
import semver from 'semver';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
const packageType = 'module';
const repositoryOwner = process.env.CI_REPO_OWNER;
const repositoryName = process.env.CI_REPO_NAME;
const repositoryURL = process.env.CI_REPO_LINK;
const forgeURL = process.env.CI_FORGE_URL;
const manifestURL = `${forgeURL}/api/packages/${repositoryOwner}/generic/${repositoryName}/latest/${packageType}.json`;
const getDownloadURL = (version) => `${repositoryURL}/releases/download/${version}/${repositoryName}.zip`;
const bugsURL = `${repositoryURL}/issues`;
const getChangelogURL = (version) => `${repositoryURL}/releases/tag/${version}`;
const getReadmeURL = (version) => `${repositoryURL}/raw/tag/${version}/README.md`;
const getLicenseURL = (version) => `${repositoryURL}/raw/tag/${version}/LICENSE.md`;
const manifestPath = `${packageType}.json`;
/**
* Get the contents of the manifest file as object.
* @returns {unknown} An object describing the manifest
*/
function getManifest() {
if (fs.existsSync(manifestPath)) {
return fs.readJSONSync(manifestPath);
}
}
/**
* Get the target version based on on the current version and the argument passed as release.
* @param {string} currentVersion The current version
* @param {semver.ReleaseType | string} release Either a semver release type or a valid semver version
* @returns {string | null} The target version
*/
function getTargetVersion(currentVersion, release) {
if (['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'].includes(release)) {
return semver.inc(currentVersion, release);
} else {
return semver.valid(release);
}
}
/**
* Update version and download URL.
* @param {semver.ReleaseType | string} release Either a semver release type or a valid semver version
*/
function bumpVersion(release) {
if (!release) {
throw new Error('Missing release type');
}
const packageJson = fs.readJSONSync('package.json');
const manifest = getManifest();
if (!manifest) throw new Error('Manifest JSON not found');
const currentVersion = packageJson.version;
const targetVersion = getTargetVersion(currentVersion, release);
if (!targetVersion) {
throw new Error('Incorrect version arguments');
}
if (targetVersion === currentVersion) {
throw new Error('Target version is identical to current version');
}
console.log(`Bumping version number to '${targetVersion}'`);
packageJson.version = targetVersion;
fs.writeJSONSync('package.json', packageJson, { spaces: 2 });
manifest.version = targetVersion;
manifest.url = repositoryURL;
manifest.manifest = manifestURL;
manifest.download = getDownloadURL(targetVersion);
manifest.bugs = bugsURL;
manifest.changelog = getChangelogURL(targetVersion);
manifest.readme = getReadmeURL(targetVersion);
manifest.license = getLicenseURL(targetVersion);
fs.writeJSONSync(manifestPath, manifest, { spaces: 2 });
}
const argv = yargs(hideBin(process.argv)).usage('Usage: $0').option('release', {
alias: 'r',
type: 'string',
demandOption: true,
description: 'Either a semver release type or a valid semver version',
}).argv;
const release = argv.r;
bumpVersion(release);

View file

@ -1,9 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
export const name = 'darkness-dependent-vision';
export const sourceDirectory = './src';
export const distDirectory = './dist';
export const destinationDirectory = 'modules';
export const foundryconfigFile = './foundryconfig.json';

View file

@ -1,55 +0,0 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
//
// SPDX-License-Identifier: MIT
import fs from 'fs-extra';
import path from 'node:path';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { destinationDirectory, distDirectory, foundryconfigFile, name } from './const.mjs';
/**
* Get the data path of Foundry VTT based on what is configured in the {@link foundryconfigFile}.
*/
function getDataPath() {
const config = fs.readJSONSync(foundryconfigFile);
if (config?.dataPath) {
if (!fs.existsSync(path.resolve(config.dataPath))) {
throw new Error('User data path invalid, no Data directory found');
}
return path.resolve(config.dataPath);
} else {
throw new Error(`No user data path defined in ${foundryconfigFile}`);
}
}
/**
* Link the built package to the user data folder.
* @param {boolean} clean Whether to remove the link instead of creating it
*/
async function linkPackage(clean) {
if (!fs.existsSync(path.resolve('module.json'))) {
throw new Error('Could not find module.json');
}
const linkDirectory = path.resolve(getDataPath(), 'Data', destinationDirectory, name);
if (clean) {
console.log(`Removing link to built package at ${linkDirectory}.`);
await fs.remove(linkDirectory);
} else if (!fs.existsSync(linkDirectory)) {
console.log(`Linking built package to ${linkDirectory}.`);
await fs.ensureDir(path.resolve(linkDirectory, '..'));
await fs.symlink(path.resolve('.', distDirectory), linkDirectory);
}
}
const argv = yargs(hideBin(process.argv)).usage('Usage: $0').option('clean', {
alias: 'c',
type: 'boolean',
default: false,
description: 'Remove the link instead of creating it',
}).argv;
const clean = argv.c;
await linkPackage(clean);

6736
yarn.lock

File diff suppressed because it is too large Load diff