Add dev tools
parent
0c2add7454
commit
6fb2a40216
|
@ -0,0 +1,13 @@
|
|||
# SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
|
@ -0,0 +1,5 @@
|
|||
# SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
dist
|
|
@ -0,0 +1,181 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
// SPDX-FileCopyrightText: 2022 David Archibald
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
parserOptions: {
|
||||
ecmaVersion: 13,
|
||||
extraFileExtensions: [".cjs", ".mjs"],
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
jquery: true,
|
||||
},
|
||||
|
||||
extends: ["eslint:recommended", "@typhonjs-fvtt/eslint-config-foundry.js/0.8.0"],
|
||||
|
||||
plugins: [],
|
||||
|
||||
rules: {
|
||||
"array-bracket-spacing": ["warn", "never"],
|
||||
"array-callback-return": "warn",
|
||||
"arrow-spacing": "warn",
|
||||
"comma-dangle": ["warn", "only-multiline"],
|
||||
"comma-style": "warn",
|
||||
"computed-property-spacing": "warn",
|
||||
"constructor-super": "error",
|
||||
"default-param-last": "warn",
|
||||
"dot-location": ["warn", "property"],
|
||||
"eol-last": ["error", "always"],
|
||||
eqeqeq: ["warn", "smart"],
|
||||
"func-call-spacing": "warn",
|
||||
"func-names": ["warn", "never"],
|
||||
"getter-return": "warn",
|
||||
"lines-between-class-members": "warn",
|
||||
"new-parens": ["warn", "always"],
|
||||
"no-alert": "warn",
|
||||
"no-array-constructor": "warn",
|
||||
"no-class-assign": "warn",
|
||||
"no-compare-neg-zero": "warn",
|
||||
"no-cond-assign": "warn",
|
||||
"no-const-assign": "error",
|
||||
"no-constant-condition": "warn",
|
||||
"no-constructor-return": "warn",
|
||||
"no-delete-var": "warn",
|
||||
"no-dupe-args": "warn",
|
||||
"no-dupe-class-members": "warn",
|
||||
"no-dupe-keys": "warn",
|
||||
"no-duplicate-case": "warn",
|
||||
"no-duplicate-imports": ["warn", { includeExports: true }],
|
||||
"no-empty": ["warn", { allowEmptyCatch: true }],
|
||||
"no-empty-character-class": "warn",
|
||||
"no-empty-pattern": "warn",
|
||||
"no-func-assign": "warn",
|
||||
"no-global-assign": "warn",
|
||||
"no-implicit-coercion": ["warn", { allow: ["!!"] }],
|
||||
"no-implied-eval": "warn",
|
||||
"no-import-assign": "warn",
|
||||
"no-invalid-regexp": "warn",
|
||||
"no-irregular-whitespace": "warn",
|
||||
"no-iterator": "warn",
|
||||
"no-lone-blocks": "warn",
|
||||
"no-lonely-if": "warn",
|
||||
"no-misleading-character-class": "warn",
|
||||
"no-mixed-operators": "warn",
|
||||
"no-multi-str": "warn",
|
||||
"no-multiple-empty-lines": ["warn", { max: 1 }],
|
||||
"no-new-func": "warn",
|
||||
"no-new-object": "warn",
|
||||
"no-new-symbol": "warn",
|
||||
"no-new-wrappers": "warn",
|
||||
"no-nonoctal-decimal-escape": "warn",
|
||||
"no-obj-calls": "warn",
|
||||
"no-octal": "warn",
|
||||
"no-octal-escape": "warn",
|
||||
"no-promise-executor-return": "warn",
|
||||
"no-proto": "warn",
|
||||
"no-regex-spaces": "warn",
|
||||
"no-script-url": "warn",
|
||||
"no-self-assign": "warn",
|
||||
"no-self-compare": "warn",
|
||||
"no-setter-return": "warn",
|
||||
"no-sequences": "warn",
|
||||
"no-template-curly-in-string": "warn",
|
||||
"no-this-before-super": "error",
|
||||
"no-unexpected-multiline": "warn",
|
||||
"no-unmodified-loop-condition": "warn",
|
||||
"no-unneeded-ternary": "warn",
|
||||
"no-unreachable": "warn",
|
||||
"no-unreachable-loop": "warn",
|
||||
"no-unsafe-negation": ["warn", { enforceForOrderingRelations: true }],
|
||||
"no-unsafe-optional-chaining": ["warn", { disallowArithmeticOperators: true }],
|
||||
"no-unused-expressions": "warn",
|
||||
"no-useless-backreference": "warn",
|
||||
"no-useless-call": "warn",
|
||||
"no-useless-catch": "warn",
|
||||
"no-useless-computed-key": ["warn", { enforceForClassMembers: true }],
|
||||
"no-useless-concat": "warn",
|
||||
"no-useless-constructor": "warn",
|
||||
"no-useless-rename": "warn",
|
||||
"no-useless-return": "warn",
|
||||
"no-var": "warn",
|
||||
"no-void": "warn",
|
||||
"no-whitespace-before-property": "warn",
|
||||
"prefer-numeric-literals": "warn",
|
||||
"prefer-object-spread": "warn",
|
||||
"prefer-regex-literals": "warn",
|
||||
"prefer-spread": "warn",
|
||||
"rest-spread-spacing": ["warn", "never"],
|
||||
"semi-spacing": "warn",
|
||||
"semi-style": ["warn", "last"],
|
||||
"space-unary-ops": ["warn", { words: true, nonwords: false }],
|
||||
"switch-colon-spacing": "warn",
|
||||
"symbol-description": "warn",
|
||||
"template-curly-spacing": ["warn", "never"],
|
||||
"unicode-bom": ["warn", "never"],
|
||||
"use-isnan": ["warn", { enforceForSwitchCase: true, enforceForIndexOf: true }],
|
||||
"valid-typeof": ["warn", { requireStringLiterals: true }],
|
||||
"wrap-iife": ["warn", "inside"],
|
||||
|
||||
"arrow-parens": ["warn", "always"],
|
||||
"comma-spacing": "warn",
|
||||
"dot-notation": "warn",
|
||||
"key-spacing": "warn",
|
||||
"keyword-spacing": ["warn", { overrides: { catch: { before: true, after: false } } }],
|
||||
"max-len": [
|
||||
"warn",
|
||||
{
|
||||
code: 120,
|
||||
ignoreComments: true,
|
||||
ignoreTrailingComments: true,
|
||||
ignoreUrls: true,
|
||||
ignoreStrings: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
ignoreRegExpLiterals: true,
|
||||
},
|
||||
],
|
||||
"no-extra-boolean-cast": ["warn", { enforceForLogicalOperands: true }],
|
||||
"no-extra-semi": "warn",
|
||||
"no-multi-spaces": ["warn", { ignoreEOLComments: true }],
|
||||
"no-throw-literal": "error",
|
||||
"no-trailing-spaces": "warn",
|
||||
"no-useless-escape": "warn",
|
||||
"no-unused-vars": ["warn", { args: "none" }],
|
||||
"nonblock-statement-body-position": ["warn", "beside"],
|
||||
"one-var": ["warn", "never"],
|
||||
"operator-linebreak": [
|
||||
"warn",
|
||||
"before",
|
||||
{
|
||||
overrides: { "=": "after", "+=": "after", "-=": "after" },
|
||||
},
|
||||
],
|
||||
"prefer-template": "warn",
|
||||
"quote-props": ["warn", "as-needed", { keywords: false }],
|
||||
quotes: ["warn", "double", { avoidEscape: true, allowTemplateLiterals: false }],
|
||||
semi: "warn",
|
||||
"space-before-blocks": ["warn", "always"],
|
||||
"space-before-function-paren": [
|
||||
"warn",
|
||||
{
|
||||
anonymous: "always",
|
||||
named: "never",
|
||||
asyncArrow: "always",
|
||||
},
|
||||
],
|
||||
"spaced-comment": "warn",
|
||||
},
|
||||
|
||||
overrides: [
|
||||
{
|
||||
files: ["./*.js", "./*.cjs", "./*.mjs"],
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -0,0 +1,65 @@
|
|||
# SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Checks
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
env:
|
||||
node_version: 16
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ env.node_version }}
|
||||
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .npm
|
||||
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-node-
|
||||
${{ runner.OS }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --cache .npm --prefer-offline
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ env.node_version }}
|
||||
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .npm
|
||||
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-node-
|
||||
${{ runner.OS }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --cache .npm --prefer-offline
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
|
@ -0,0 +1,116 @@
|
|||
# SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
package_type: module
|
||||
node_version: 16
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ env.node_version }}
|
||||
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .npm
|
||||
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-node-
|
||||
${{ runner.OS }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --cache .npm --prefer-offline
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ env.node_version }}
|
||||
|
||||
- name: Cache Node.js modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .npm
|
||||
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.OS }}-node-
|
||||
${{ runner.OS }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci --cache .npm --prefer-offline
|
||||
|
||||
- name: Extract tag version number
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
|
||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||
id: sub_manifest_link_version
|
||||
uses: microsoft/variable-substitution@v1
|
||||
with:
|
||||
files: 'src/${{ env.package_type }}.json'
|
||||
env:
|
||||
version: ${{ steps.get_version.outputs.version-without-v }}
|
||||
url: https://github.com/${{ github.repository }}
|
||||
manifest: https://github.com/${{ github.repository }}/releases/latest/download/${{ env.package_type }}.json
|
||||
download: https://github.com/${{ github.repository }}/releases/download/${{ github.event.release.tag_name }}/${{ env.package_type }}.zip
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Archive production artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
|
||||
publish:
|
||||
needs:
|
||||
- lint
|
||||
- build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download production artifacts for publication
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
|
||||
- name: Create zip file
|
||||
working-directory: ./dist
|
||||
run: zip -r ../${{ env.package_type }}.zip .
|
||||
|
||||
- name: Create release
|
||||
id: create_version_release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
name: ${{ github.event.release.name }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts: './dist/${{ env.package_type }}.json, ./${{ env.package_type }}.zip'
|
||||
body: ${{ github.event.release.body }}
|
|
@ -0,0 +1,32 @@
|
|||
# SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vs/
|
||||
|
||||
# Node Modules
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
|
||||
# yarn2
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/releases
|
||||
!.yarn/plugins
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
.pnp.*
|
||||
|
||||
# Local configuration
|
||||
foundryconfig.json
|
||||
|
||||
# Distribution files
|
||||
dist
|
||||
|
||||
# ESLint
|
||||
.eslintcache
|
||||
|
||||
# Junit results
|
||||
junit.xml
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"flags": {
|
||||
"gulpfile": "gulpfile.mjs"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
|
@ -0,0 +1,8 @@
|
|||
# SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
dist
|
||||
package-lock.json
|
||||
.pnp.cjs
|
||||
.pnp.js
|
|
@ -0,0 +1,9 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
module.exports = {
|
||||
printWidth: 120,
|
||||
tabWidth: 4,
|
||||
useTabs: true,
|
||||
};
|
|
@ -0,0 +1,65 @@
|
|||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
In order to build this module, recent versions of `node` and `npm` are
|
||||
required. Most likely, using `yarn` also works, but only `npm` 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
|
||||
|
||||
```
|
||||
nvm install
|
||||
```
|
||||
|
||||
in the project's root directory.
|
||||
|
||||
You also need to install the project's dependencies. To do so, run
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
You can build the project by running
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Alternatively, you can run
|
||||
|
||||
```
|
||||
npm run build:watch
|
||||
```
|
||||
|
||||
to watch for changes and automatically build as necessary.
|
||||
|
||||
### Linking the built project to Foundry VTT
|
||||
|
||||
In order to provide a fluent development experience, it is recommended to link
|
||||
the built module to your local Foundry VTT installation's data folder. In
|
||||
order to do so, first add a file called `foundryconfig.json` to the project root
|
||||
with the following content:
|
||||
|
||||
```
|
||||
{
|
||||
"dataPath": ["/absolute/path/to/your/FoundryVTT"]
|
||||
}
|
||||
```
|
||||
|
||||
(if you are using Windows, make sure to use `\` as a path separator instead of
|
||||
`/`)
|
||||
|
||||
Then run
|
||||
|
||||
```
|
||||
npm run 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.
|
||||
|
||||
You can also link to multiple data folders by specifying multiple paths in the
|
||||
`dataPath` array.
|
16
README.md
16
README.md
|
@ -4,16 +4,6 @@ Tired of scrolling compendia? Easily browse and filter for spells, feats, items,
|
|||
|
||||
Compendium Browser is faster and better-behaved; **it no longer loads all the compendia into memory on start-up** (which sometimes hung servers because of memory or CPU requirements). Instead, it filters and loads on-demand, as well as giving you a Module Setting to control how many rows are loaded at a time.
|
||||
|
||||
## Summary
|
||||
|
||||
- **Authors**: Discord: Spetzel#0103; Felix (felix.mueller.86@web.de); ZoltantheDM (Zoltan#8700); eduardopato41
|
||||
- **Version**: 0.9.0
|
||||
- **Foundry VTT Compatibility**: 9-10
|
||||
- **System Compatibility (If applicable)**: dnd5e
|
||||
- **Translation Support**: en, de (thanks https://github.com/CarnVanBeck), es (thanks https://github.com/JJBocanegra), fr, ja, pt-BR
|
||||
|
||||
[Patch Notes](https://github.com/ZoltanTheDM/compendium-browser/blob/master/Patchnotes.md)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Go to the Add-on Modules tab in Foundry Setup
|
||||
|
@ -32,6 +22,8 @@ All filters featured in the app are included in this manner and can be found in
|
|||
|
||||
## License
|
||||
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons Licence" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Compendium Browser - a module for Foundry VTT -</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://github.com/syl3r86?tab=repositories" property="cc:attributionName" rel="cc:attributionURL">Felix Müller</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.
|
||||
This project is a fork of Compendium Browser by [Felix Müller](https://github.com/syl3r86).
|
||||
|
||||
This work is licensed under Foundry Virtual Tabletop [EULA - Limited License Agreement for module development v 0.1.6](http://foundryvtt.com/pages/license.html).
|
||||
## Community Contribution
|
||||
|
||||
See the [CONTRIBUTING](/CONTRIBUTING.md) file for information about how you can help this project.
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
// SPDX-FileCopyrightText: 2022 David Archibald
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import fs from "fs-extra";
|
||||
import gulp from "gulp";
|
||||
import less from "gulp-less";
|
||||
import sourcemaps from "gulp-sourcemaps";
|
||||
import path from "node:path";
|
||||
import buffer from "vinyl-buffer";
|
||||
import source from "vinyl-source-stream";
|
||||
import yargs from "yargs";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
|
||||
import rollupStream from "@rollup/stream";
|
||||
|
||||
import rollupConfig from "./rollup.config.mjs";
|
||||
|
||||
/** ******************/
|
||||
/* CONFIGURATION */
|
||||
/** ******************/
|
||||
|
||||
const packageId = "compendium-browser";
|
||||
const sourceDirectory = "./src";
|
||||
const distDirectory = "./dist";
|
||||
const stylesDirectory = `${sourceDirectory}/styles`;
|
||||
const stylesExtension = "less";
|
||||
const sourceFileExtension = "js";
|
||||
const staticFiles = ["assets", "fonts", "lang", "packs", "templates", "module.json"];
|
||||
|
||||
/** ******************/
|
||||
/* BUILD */
|
||||
/** ******************/
|
||||
|
||||
let cache;
|
||||
|
||||
/**
|
||||
* Build the distributable JavaScript code
|
||||
*/
|
||||
function buildCode() {
|
||||
return rollupStream({ ...rollupConfig(), cache })
|
||||
.on("bundle", (bundle) => {
|
||||
cache = bundle;
|
||||
})
|
||||
.pipe(source(`${packageId}.js`))
|
||||
.pipe(buffer())
|
||||
.pipe(sourcemaps.init({ loadMaps: true }))
|
||||
.pipe(sourcemaps.write("."))
|
||||
.pipe(gulp.dest(`${distDirectory}/module`));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build style sheets
|
||||
*/
|
||||
function buildStyles() {
|
||||
return gulp
|
||||
.src(`${stylesDirectory}/${packageId}.${stylesExtension}`)
|
||||
.pipe(less())
|
||||
.pipe(gulp.dest(`${distDirectory}/styles`));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export function watch() {
|
||||
gulp.watch(`${sourceDirectory}/**/*.${sourceFileExtension}`, { ignoreInitial: false }, buildCode);
|
||||
gulp.watch(`${stylesDirectory}/**/*.${stylesExtension}`, { ignoreInitial: false }, buildStyles);
|
||||
gulp.watch(
|
||||
staticFiles.map((file) => `${sourceDirectory}/${file}`),
|
||||
{ ignoreInitial: false },
|
||||
copyFiles,
|
||||
);
|
||||
}
|
||||
|
||||
export const build = gulp.series(clean, gulp.parallel(buildCode, buildStyles, copyFiles));
|
||||
|
||||
/** ******************/
|
||||
/* CLEAN */
|
||||
/** ******************/
|
||||
|
||||
/**
|
||||
* Remove built files from `dist` folder while ignoring source files
|
||||
*/
|
||||
export async function clean() {
|
||||
const files = [...staticFiles, "module"];
|
||||
|
||||
if (fs.existsSync(`${stylesDirectory}/${packageId}.${stylesExtension}`)) {
|
||||
files.push("styles");
|
||||
}
|
||||
|
||||
console.log(" ", "Files to clean:");
|
||||
console.log(" ", files.join("\n "));
|
||||
|
||||
for (const filePath of files) {
|
||||
await fs.remove(`${distDirectory}/${filePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** ******************/
|
||||
/* LINK */
|
||||
/** ******************/
|
||||
|
||||
/**
|
||||
* Get the data paths of Foundry VTT based on what is configured in `foundryconfig.json`
|
||||
*/
|
||||
function getDataPaths() {
|
||||
const config = fs.readJSONSync("foundryconfig.json");
|
||||
const dataPath = config?.dataPath;
|
||||
|
||||
if (dataPath) {
|
||||
const dataPaths = Array.isArray(dataPath) ? dataPath : [dataPath];
|
||||
|
||||
return dataPaths.map((dataPath) => {
|
||||
if (typeof dataPath !== "string") {
|
||||
throw new Error(
|
||||
`Property dataPath in foundryconfig.json is expected to be a string or an array of strings, but found ${dataPath}`,
|
||||
);
|
||||
}
|
||||
if (!fs.existsSync(path.resolve(dataPath))) {
|
||||
throw new Error(`The dataPath ${dataPath} does not exist on the file system`);
|
||||
}
|
||||
return path.resolve(dataPath);
|
||||
});
|
||||
} else {
|
||||
throw new Error("No dataPath defined in foundryconfig.json");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link build to User Data folder
|
||||
*/
|
||||
export async function link() {
|
||||
let destinationDirectory;
|
||||
if (fs.existsSync(path.resolve(sourceDirectory, "module.json"))) {
|
||||
destinationDirectory = "modules";
|
||||
} else {
|
||||
throw new Error("Could not find module.json");
|
||||
}
|
||||
|
||||
const linkDirectories = getDataPaths().map((dataPath) =>
|
||||
path.resolve(dataPath, "Data", destinationDirectory, packageId),
|
||||
);
|
||||
|
||||
const argv = yargs(hideBin(process.argv)).option("clean", {
|
||||
alias: "c",
|
||||
type: "boolean",
|
||||
default: false,
|
||||
}).argv;
|
||||
const clean = argv.c;
|
||||
|
||||
for (const linkDirectory of linkDirectories) {
|
||||
if (clean) {
|
||||
console.log(`Removing build in ${linkDirectory}.`);
|
||||
|
||||
await fs.remove(linkDirectory);
|
||||
} else if (!fs.existsSync(linkDirectory)) {
|
||||
console.log(`Linking dist to ${linkDirectory}.`);
|
||||
await fs.ensureDir(path.resolve(linkDirectory, ".."));
|
||||
await fs.symlink(path.resolve(distDirectory), linkDirectory);
|
||||
} else {
|
||||
console.log(`Skipped linking to ${linkDirectory}, as it already exists.`);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"build:watch": "gulp watch",
|
||||
"link-project": "gulp link",
|
||||
"clean": "gulp clean",
|
||||
"clean:link": "gulp link --clean",
|
||||
"lint": "eslint --ext .js,.cjs,.mjs .",
|
||||
"lint:fix": "eslint --ext .js,.cjs,.mjs --fix .",
|
||||
"postinstall": "husky install"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/stream": "^3.0.1",
|
||||
"@typhonjs-fvtt/eslint-config-foundry.js": "^0.8.0",
|
||||
"eslint": "^8.53.0",
|
||||
"fs-extra": "^11.1.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-less": "^5.0.0",
|
||||
"gulp-sourcemaps": "^3.0.0",
|
||||
"husky": "^8.0.3",
|
||||
"less": "^3.13.1",
|
||||
"lint-staged": "^15.0.2",
|
||||
"rollup": "^2.79.1",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vinyl-source-stream": "^2.0.0",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(js|cjs|mjs)": "eslint --fix"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
// SPDX-FileCopyrightText: 2022 David Archibald
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
||||
|
||||
export default () => ({
|
||||
input: "src/module/compendium-browser.js",
|
||||
output: {
|
||||
dir: "dist/module",
|
||||
format: "es",
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: [nodeResolve()],
|
||||
});
|
|
@ -2,16 +2,23 @@
|
|||
"id": "compendium-browser",
|
||||
"title": "Compendium Browser",
|
||||
"description": "Easily browse and filter spells, feats, items, and npcs loaded from compendiums!",
|
||||
"version": "2.0.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matheus Clemente",
|
||||
"discord": "mclemente#5524"
|
||||
}
|
||||
],
|
||||
"systems": ["dnd5e"],
|
||||
"scripts": ["./compendium-browser.js"],
|
||||
"styles": ["./compendium-browser.css"],
|
||||
"url": "This is auto replaced",
|
||||
"readme": "https://github.com/mclemente/compendium-browser/blob/master/README.md",
|
||||
"bugs": "https://github.com/mclemente/compendium-browser/issues",
|
||||
"changelog": "https://github.com/mclemente/compendium-browser/blob/master/Patchnotes.md",
|
||||
"version": "This is auto replaced",
|
||||
"compatibility": {
|
||||
"minimum": "11",
|
||||
"verified": "11"
|
||||
},
|
||||
"esmodules": ["module/compendium-browser.js"],
|
||||
"styles": ["styles/compendium-browser.css"],
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
|
@ -44,15 +51,14 @@
|
|||
"path": "lang/de.json"
|
||||
}
|
||||
],
|
||||
"url": "https://github.com/mclemente/compendium-browser",
|
||||
"manifest": "https://github.com/mclemente/compendium-browser/releases/latest/download/module.json",
|
||||
"download": "https://github.com/mclemente/compendium-browser/releases/download/latest/compendium-browser.zip",
|
||||
"compatibility": {
|
||||
"minimum": "11",
|
||||
"verified": "11"
|
||||
"relationships": {
|
||||
"systems": [{
|
||||
"id": "dnd5e",
|
||||
"type": "system"
|
||||
}],
|
||||
"requires": [],
|
||||
"conflicts": []
|
||||
},
|
||||
"allowBugReporter": true,
|
||||
"bugs": "https://github.com/mclemente/compendium-browser/issues",
|
||||
"readme": "https://github.com/mclemente/compendium-browser/blob/master/README.md",
|
||||
"changelog": "https://github.com/mclemente/compendium-browser/blob/master/Patchnotes.md"
|
||||
"manifest": "This is auto replaced",
|
||||
"download": "This is auto replaced"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
const STOP_SEARCH = "StopSearchException";
|
||||
import { preloadTemplates } from "./preloadTemplates.js";
|
||||
import { registerSettings } from "./settings.js";
|
||||
|
||||
const STOP_SEARCH = "StopSearchException";
|
||||
const NOT_MIGRATED = "NotMigratedException";
|
||||
|
||||
class CompendiumBrowser extends Application {
|
||||
|
@ -7,7 +10,7 @@ class CompendiumBrowser extends Application {
|
|||
title: "CMPBrowser.compendiumBrowser",
|
||||
tabs: [{ navSelector: ".tabs", contentSelector: ".content", initial: "spell" }],
|
||||
classes: ["compendium-browser"],
|
||||
template: "modules/compendium-browser/template/template.html",
|
||||
template: "modules/compendium-browser/templates/template.html",
|
||||
width: 800,
|
||||
height: 730,
|
||||
resizable: true,
|
||||
|
@ -31,7 +34,7 @@ class CompendiumBrowser extends Application {
|
|||
this.hookCompendiumList(html);
|
||||
});
|
||||
|
||||
//Reset the filters used in the dialog
|
||||
// Reset the filters used in the dialog
|
||||
this.spellFilters = {
|
||||
registeredFilterCategorys: {},
|
||||
activeFilters: {},
|
||||
|
@ -59,11 +62,11 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
/** @override */
|
||||
async getData() {
|
||||
//0.4.1 Filter as we load to support new way of filtering
|
||||
//Previously loaded all data and filtered in place; now loads minimal (preload) amount, filtered as we go
|
||||
//First time (when you press Compendium Browser button) is called with filters unset
|
||||
// 0.4.1 Filter as we load to support new way of filtering
|
||||
// Previously loaded all data and filtered in place; now loads minimal (preload) amount, filtered as we go
|
||||
// First time (when you press Compendium Browser button) is called with filters unset
|
||||
|
||||
//0.4.1k: Don't do any item/npc loading until tab is visible
|
||||
// 0.4.1k: Don't do any item/npc loading until tab is visible
|
||||
let data = {
|
||||
items: [],
|
||||
npcs: [],
|
||||
|
@ -94,7 +97,7 @@ class CompendiumBrowser extends Application {
|
|||
});
|
||||
|
||||
// make draggable
|
||||
//0.4.1: Avoid the game.packs lookup
|
||||
// 0.4.1: Avoid the game.packs lookup
|
||||
html.find(".draggable").each((i, li) => {
|
||||
li.setAttribute("draggable", true);
|
||||
li.addEventListener(
|
||||
|
@ -128,7 +131,7 @@ class CompendiumBrowser extends Application {
|
|||
if (!e.isIntersecting) continue;
|
||||
const img = e.target;
|
||||
// Avatar image
|
||||
//const img = li.querySelector("img");
|
||||
// const img = li.querySelector("img");
|
||||
if (img && img.dataset.src) {
|
||||
img.src = img.dataset.src;
|
||||
delete img.dataset.src;
|
||||
|
@ -201,15 +204,15 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
for (let tab of ["spell", "feat", "item", "npc"]) {
|
||||
// reset filters and re-render
|
||||
//0.4.3: Reset ALL filters because when we do a re-render it affects all tabs
|
||||
// 0.4.3: Reset ALL filters because when we do a re-render it affects all tabs
|
||||
html.find(`#reset-${tab}-filter`).click((ev) => {
|
||||
this.resetFilters();
|
||||
//v0.4.3: Re-render so that we display the filters correctly
|
||||
// v0.4.3: Re-render so that we display the filters correctly
|
||||
this.refreshList = tab;
|
||||
this.render();
|
||||
});
|
||||
|
||||
//copy Javascript seach to clipboard
|
||||
// copy Javascript seach to clipboard
|
||||
html.find(`#copy-search-${tab}`).click(async (ev) => {
|
||||
this.copySearchToClipboard(tab);
|
||||
});
|
||||
|
@ -246,7 +249,7 @@ class CompendiumBrowser extends Application {
|
|||
});
|
||||
|
||||
// activating or deactivating filters
|
||||
//0.4.1: Now does a re-load and updates just the data side
|
||||
// 0.4.1: Now does a re-load and updates just the data side
|
||||
// text filters
|
||||
html.find(".filter[data-type=text] input, .filter[data-type=text] select").on("keyup change paste", (ev) => {
|
||||
const path = $(ev.target).parents(".filter").data("path");
|
||||
|
@ -365,14 +368,14 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
);
|
||||
|
||||
//Just for the loading image
|
||||
// Just for the loading image
|
||||
if (this.observer) {
|
||||
html.find("img").each((i, img) => this.observer.observe(img));
|
||||
}
|
||||
}
|
||||
|
||||
async checkListsLoaded() {
|
||||
//Provides extra info not in the standard SRD, like which classes can learn a spell
|
||||
// Provides extra info not in the standard SRD, like which classes can learn a spell
|
||||
if (!this.classList) {
|
||||
this.classList = await fetch("modules/compendium-browser/spell-classes.json")
|
||||
.then((result) => {
|
||||
|
@ -411,23 +414,23 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
this.CurrentSeachNumber = seachNumber;
|
||||
|
||||
//0.4.1: Load and filter just one of spells, feats, and items (specified by browserTab)
|
||||
// 0.4.1: Load and filter just one of spells, feats, and items (specified by browserTab)
|
||||
let unfoundSpells = "";
|
||||
let numItemsLoaded = 0;
|
||||
let compactItems = {};
|
||||
|
||||
try {
|
||||
//Filter the full list, but only save the core compendium information + displayed info
|
||||
// Filter the full list, but only save the core compendium information + displayed info
|
||||
for (let pack of game.packs) {
|
||||
if (pack.documentName === "Item" && this.settings.loadedSpellCompendium[pack.collection].load) {
|
||||
//can query just for spells since there is only 1 type
|
||||
// can query just for spells since there is only 1 type
|
||||
let query = {};
|
||||
if (browserTab === "spell") {
|
||||
query = { type: "spell" };
|
||||
}
|
||||
|
||||
//FIXME: How much could we do with the loaded index rather than all content?
|
||||
//OR filter the content up front for the decoratedItem.type??
|
||||
// FIXME: How much could we do with the loaded index rather than all content?
|
||||
// OR filter the content up front for the decoratedItem.type??
|
||||
await pack.getDocuments(query).then((content) => {
|
||||
if (browserTab === "spell") {
|
||||
content.reduce(
|
||||
|
@ -446,8 +449,8 @@ class CompendiumBrowser extends Application {
|
|||
const decoratedItem = this.decorateItem(item5e);
|
||||
|
||||
if (
|
||||
decoratedItem &&
|
||||
this.passesFilter(decoratedItem, this.spellFilters.activeFilters)
|
||||
decoratedItem
|
||||
&& this.passesFilter(decoratedItem, this.spellFilters.activeFilters)
|
||||
) {
|
||||
itemsList[item5e.id] = {
|
||||
compendium: pack.collection,
|
||||
|
@ -482,9 +485,9 @@ class CompendiumBrowser extends Application {
|
|||
const decoratedItem = this.decorateItem(item5e);
|
||||
|
||||
if (
|
||||
decoratedItem &&
|
||||
["feat", "class", "subclass", "background"].includes(decoratedItem.type) &&
|
||||
this.passesFilter(decoratedItem, this.featFilters.activeFilters)
|
||||
decoratedItem
|
||||
&& ["feat", "class", "subclass", "background"].includes(decoratedItem.type)
|
||||
&& this.passesFilter(decoratedItem, this.featFilters.activeFilters)
|
||||
) {
|
||||
itemsList[item5e.id] = {
|
||||
compendium: pack.collection,
|
||||
|
@ -515,11 +518,11 @@ class CompendiumBrowser extends Application {
|
|||
const decoratedItem = this.decorateItem(item5e);
|
||||
|
||||
if (
|
||||
decoratedItem &&
|
||||
!["spell", "feat", "class", "subclass", "background"].includes(
|
||||
decoratedItem
|
||||
&& !["spell", "feat", "class", "subclass", "background"].includes(
|
||||
decoratedItem.type
|
||||
) &&
|
||||
this.passesFilter(decoratedItem, this.itemFilters.activeFilters)
|
||||
)
|
||||
&& this.passesFilter(decoratedItem, this.itemFilters.activeFilters)
|
||||
) {
|
||||
itemsList[item5e.id] = {
|
||||
compendium: pack.collection,
|
||||
|
@ -540,11 +543,11 @@ class CompendiumBrowser extends Application {
|
|||
updateLoading(numItemsLoaded, false);
|
||||
}
|
||||
});
|
||||
} //end if pack entity === Item
|
||||
} //for packs
|
||||
} catch (e) {
|
||||
} // end if pack entity === Item
|
||||
} // for packs
|
||||
} catch(e) {
|
||||
if (e === STOP_SEARCH) {
|
||||
//stopping search early
|
||||
// stopping search early
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
|
@ -602,8 +605,8 @@ class CompendiumBrowser extends Application {
|
|||
if (npc5e.name != "#[CF_tempEntity]") {
|
||||
const decoratedNpc = this.decorateNpc(npc5e, indexFields);
|
||||
if (
|
||||
decoratedNpc &&
|
||||
this.passesFilter(decoratedNpc, this.npcFilters.activeFilters)
|
||||
decoratedNpc
|
||||
&& this.passesFilter(decoratedNpc, this.npcFilters.activeFilters)
|
||||
) {
|
||||
actorsList[npc5e._id] = {
|
||||
compendium: pack.collection,
|
||||
|
@ -628,11 +631,11 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
});
|
||||
}
|
||||
//0.4.1 Only preload a limited number and fill more in as needed
|
||||
// 0.4.1 Only preload a limited number and fill more in as needed
|
||||
}
|
||||
} catch (e) {
|
||||
} catch(e) {
|
||||
if (e == STOP_SEARCH) {
|
||||
//breaking out
|
||||
// breaking out
|
||||
} else if (e == NOT_MIGRATED) {
|
||||
console.log("Cannot browse compendium %s as it is not migrated to v10 format", collectionName);
|
||||
} else {
|
||||
|
@ -660,9 +663,9 @@ class CompendiumBrowser extends Application {
|
|||
// Handle button clicks
|
||||
cbButton.click((ev) => {
|
||||
ev.preventDefault();
|
||||
//0.4.1: Reset filters when you click button
|
||||
// 0.4.1: Reset filters when you click button
|
||||
this.resetFilters();
|
||||
//0.4.3: Reset everything (including data) when you press the button - calls afterRender() hook
|
||||
// 0.4.3: Reset everything (including data) when you press the button - calls afterRender() hook
|
||||
|
||||
if (!this.refreshList) {
|
||||
if (game.user.isGM || this.settings.allowSpellBrowser) {
|
||||
|
@ -682,7 +685,7 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
/* Hook to load the first data */
|
||||
static afterRender(cb, html) {
|
||||
//0.4.3: Because a render always resets ALL the displayed filters (on all tabs) to unselected , we have to blank all the lists as well
|
||||
// 0.4.3: Because a render always resets ALL the displayed filters (on all tabs) to unselected , we have to blank all the lists as well
|
||||
// (because the current HTML template doesn't set the selected filter values)
|
||||
if (!cb?.refreshList) {
|
||||
return;
|
||||
|
@ -705,10 +708,10 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
|
||||
async replaceList(html, browserTab, options = { reload: true }) {
|
||||
//After rendering the first time or re-rendering trigger the load/reload of visible data
|
||||
// After rendering the first time or re-rendering trigger the load/reload of visible data
|
||||
|
||||
let elements = null;
|
||||
//0.4.2 Display a Loading... message while the data is being loaded and filtered
|
||||
// 0.4.2 Display a Loading... message while the data is being loaded and filtered
|
||||
let loadingMessage = null;
|
||||
const tabElements = {
|
||||
spell: { elements: "ul#CBSpells", message: "#CBSpellsMessage" },
|
||||
|
@ -725,7 +728,7 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
|
||||
if (elements?.length) {
|
||||
//0.4.2b: On a tab-switch, only reload if there isn't any data already
|
||||
// 0.4.2b: On a tab-switch, only reload if there isn't any data already
|
||||
if (options?.reload || !elements[0].children.length) {
|
||||
const updateLoading = async (numLoaded, doneLoading) => {
|
||||
if (loadingMessage.length) {
|
||||
|
@ -739,20 +742,20 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
};
|
||||
updateLoading(0, false);
|
||||
//Uses loadAndFilterItems to read compendia for items which pass the current filters and render on this tab
|
||||
// Uses loadAndFilterItems to read compendia for items which pass the current filters and render on this tab
|
||||
const newItemsHTML = await this.renderItemData(browserTab, updateLoading);
|
||||
elements[0].innerHTML = newItemsHTML;
|
||||
//Re-sort before setting up lazy loading
|
||||
// Re-sort before setting up lazy loading
|
||||
this.triggerSort(html, browserTab);
|
||||
|
||||
//Lazy load images
|
||||
// Lazy load images
|
||||
if (this.observer) {
|
||||
$(elements)
|
||||
.find("img")
|
||||
.each((i, img) => this.observer.observe(img));
|
||||
}
|
||||
|
||||
//Reactivate listeners for clicking and dragging
|
||||
// Reactivate listeners for clicking and dragging
|
||||
this.activateItemListListeners($(elements));
|
||||
}
|
||||
}
|
||||
|
@ -761,7 +764,7 @@ class CompendiumBrowser extends Application {
|
|||
async renderLoading(messageElement, itemType, numLoaded, maxLoaded = false, doneLoading = false) {
|
||||
if (!messageElement) return;
|
||||
|
||||
let loadingHTML = await renderTemplate("modules/compendium-browser/template/loading.html", {
|
||||
let loadingHTML = await renderTemplate("modules/compendium-browser/templates/loading.html", {
|
||||
numLoaded: numLoaded,
|
||||
itemType: itemType,
|
||||
maxLoaded: maxLoaded,
|
||||
|
@ -777,14 +780,14 @@ class CompendiumBrowser extends Application {
|
|||
} else {
|
||||
listItems = await this.loadAndFilterItems(browserTab, updateLoading);
|
||||
}
|
||||
const html = await renderTemplate(`modules/compendium-browser/template/${browserTab}-browser-list.html`, {
|
||||
const html = await renderTemplate(`modules/compendium-browser/templates/${browserTab}-browser-list.html`, {
|
||||
listItems: listItems,
|
||||
});
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
//SORTING
|
||||
// SORTING
|
||||
triggerSort(html, browserTab) {
|
||||
if (browserTab === "spell") {
|
||||
html.find(".spell-browser select[name=sortorder]").trigger("change");
|
||||
|
@ -925,7 +928,7 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
decorateItem(item5e) {
|
||||
if (!item5e) return null;
|
||||
//Decorate and then filter a compendium entry - returns null or the item
|
||||
// Decorate and then filter a compendium entry - returns null or the item
|
||||
|
||||
const item = { ...item5e };
|
||||
|
||||
|
@ -953,12 +956,12 @@ class CompendiumBrowser extends Application {
|
|||
.replace(/[^一-龠ぁ-ゔァ-ヴーa-zA-Z0-9a-zA-Z0-9々〆〤]/g, "")
|
||||
.replace("'", "")
|
||||
.replace(/ /g, "");
|
||||
//let cleanSpellName = spell.name.toLowerCase().replace(/[^a-zA-Z0-9\s:]/g, '').replace("'", '').replace(/ /g, '');
|
||||
// let cleanSpellName = spell.name.toLowerCase().replace(/[^a-zA-Z0-9\s:]/g, '').replace("'", '').replace(/ /g, '');
|
||||
if (this.classList[cleanSpellName]) {
|
||||
let classes = this.classList[cleanSpellName];
|
||||
item.classes = classes.split(",");
|
||||
} else {
|
||||
//FIXME: unfoundSpells += cleanSpellName + ',';
|
||||
// FIXME: unfoundSpells += cleanSpellName + ',';
|
||||
}
|
||||
} else if (item.type === "feat" || item.type === "class") {
|
||||
// getting class
|
||||
|
@ -982,7 +985,7 @@ class CompendiumBrowser extends Application {
|
|||
// getting uses/ressources status
|
||||
item.usesRessources = item5e.hasLimitedUses;
|
||||
} else if (item.type === "subclass") {
|
||||
//subclasses dont exist lower then version 10
|
||||
// subclasses dont exist lower then version 10
|
||||
item.classRequirement = [item.system.classIdentifier];
|
||||
item.classRequirementString = item.system.classIdentifier;
|
||||
} else {
|
||||
|
@ -1012,17 +1015,17 @@ class CompendiumBrowser extends Application {
|
|||
return npcDict;
|
||||
}, {});
|
||||
|
||||
//0.8.0: update for V10 to use actor.system instead of actor.data
|
||||
// 0.8.0: update for V10 to use actor.system instead of actor.data
|
||||
let npcData = npc.system;
|
||||
|
||||
// cr display
|
||||
let cr = npcData.details?.cr; //0.7.2c: Possibly because of getIndex() use we now have to check for existence of details (doesn't for Character-type NPCs)
|
||||
let cr = npcData.details?.cr; // 0.7.2c: Possibly because of getIndex() use we now have to check for existence of details (doesn't for Character-type NPCs)
|
||||
if (cr === undefined || cr === "") cr = 0;
|
||||
else cr = Number(cr);
|
||||
|
||||
decoratedNpc.orderCR = cr;
|
||||
|
||||
if (cr > 0 && cr < 1) cr = "1/" + 1 / cr;
|
||||
if (cr > 0 && cr < 1) cr = `1/${1 / cr}`;
|
||||
decoratedNpc.displayCR = cr;
|
||||
|
||||
decoratedNpc.displaySize = "unset";
|
||||
|
@ -1059,7 +1062,7 @@ class CompendiumBrowser extends Application {
|
|||
break;
|
||||
}
|
||||
return decoratedNpc;
|
||||
} catch (e) {
|
||||
} catch(e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -1116,10 +1119,10 @@ class CompendiumBrowser extends Application {
|
|||
} else {
|
||||
if (prop === undefined) return false;
|
||||
if (
|
||||
filter.value !== undefined &&
|
||||
prop !== undefined &&
|
||||
prop != filter.value &&
|
||||
!(filter.value === true && prop)
|
||||
filter.value !== undefined
|
||||
&& prop !== undefined
|
||||
&& prop != filter.value
|
||||
&& !(filter.value === true && prop)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1156,17 +1159,17 @@ class CompendiumBrowser extends Application {
|
|||
return true;
|
||||
}
|
||||
|
||||
//incomplete removal of duplicate items
|
||||
// incomplete removal of duplicate items
|
||||
removeDuplicates(spellList) {
|
||||
//sort at n log n
|
||||
// sort at n log n
|
||||
let sortedList = Object.values(spellList).sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
//search through sorted list for duplicates
|
||||
// search through sorted list for duplicates
|
||||
for (let index = 0; index < sortedList.length - 1; ) {
|
||||
//all duplicates will be next to eachother
|
||||
// all duplicates will be next to eachother
|
||||
if (sortedList[index].name == sortedList[index + 1].name) {
|
||||
//duplicate something is getting removed
|
||||
//TODO choose what to remove rather then the second
|
||||
// duplicate something is getting removed
|
||||
// TODO choose what to remove rather then the second
|
||||
let remove = index + 1;
|
||||
|
||||
delete spellList[sortedList[remove].id];
|
||||
|
@ -1196,13 +1199,13 @@ class CompendiumBrowser extends Application {
|
|||
if (compendium.documentName === "Item") {
|
||||
defaultSettings.loadedSpellCompendium[compendium.collection] = {
|
||||
load: true,
|
||||
name: `${compendium["metadata"]["label"]} (${compendium.collection})`,
|
||||
name: `${compendium.metadata.label} (${compendium.collection})`,
|
||||
};
|
||||
}
|
||||
if (compendium.documentName === "Actor") {
|
||||
defaultSettings.loadedNpcCompendium[compendium.collection] = {
|
||||
load: true,
|
||||
name: `${compendium["metadata"]["label"]} (${compendium.collection})`,
|
||||
name: `${compendium.metadata.label} (${compendium.collection})`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1235,21 +1238,21 @@ class CompendiumBrowser extends Application {
|
|||
// load settings from container and apply to default settings (available compendie might have changed)
|
||||
let settings = game.settings.get("compendium-browser", "settings");
|
||||
for (let compKey in defaultSettings.loadedSpellCompendium) {
|
||||
//v0.7.1 Check for settings.loadedSpellCompendium
|
||||
// v0.7.1 Check for settings.loadedSpellCompendium
|
||||
if (settings.loadedSpellCompendium && settings.loadedSpellCompendium[compKey] !== undefined) {
|
||||
defaultSettings.loadedSpellCompendium[compKey].load = settings.loadedSpellCompendium[compKey].load;
|
||||
}
|
||||
}
|
||||
for (let compKey in defaultSettings.loadedNpcCompendium) {
|
||||
//v0.7.1 Check for settings.loadedNpcCompendium
|
||||
// v0.7.1 Check for settings.loadedNpcCompendium
|
||||
if (settings.loadedNpcCompendium && settings.loadedNpcCompendium[compKey] !== undefined) {
|
||||
defaultSettings.loadedNpcCompendium[compKey].load = settings.loadedNpcCompendium[compKey].load;
|
||||
}
|
||||
}
|
||||
defaultSettings.allowSpellBrowser = settings.allowSpellBrowser ? true : false;
|
||||
defaultSettings.allowFeatBrowser = settings.allowFeatBrowser ? true : false;
|
||||
defaultSettings.allowItemBrowser = settings.allowItemBrowser ? true : false;
|
||||
defaultSettings.allowNpcBrowser = settings.allowNpcBrowser ? true : false;
|
||||
defaultSettings.allowSpellBrowser = !!settings.allowSpellBrowser;
|
||||
defaultSettings.allowFeatBrowser = !!settings.allowFeatBrowser;
|
||||
defaultSettings.allowItemBrowser = !!settings.allowItemBrowser;
|
||||
defaultSettings.allowNpcBrowser = !!settings.allowNpcBrowser;
|
||||
|
||||
if (game.user.isGM) {
|
||||
game.settings.set("compendium-browser", "settings", defaultSettings);
|
||||
|
@ -1257,8 +1260,8 @@ class CompendiumBrowser extends Application {
|
|||
this.settings = defaultSettings;
|
||||
}
|
||||
|
||||
//FILTERS - Added on the Ready hook
|
||||
//0.4.0 Make this async so filters can be added all at once
|
||||
// FILTERS - Added on the Ready hook
|
||||
// 0.4.0 Make this async so filters can be added all at once
|
||||
async addFilter(entityType, category, label, path, type, possibleValues = null, valIsArray = false) {
|
||||
let target = `${entityType}Filters`;
|
||||
let filter = {};
|
||||
|
@ -1338,7 +1341,7 @@ class CompendiumBrowser extends Application {
|
|||
"select",
|
||||
this._sortPackValues(CONFIG.DND5E.damageTypes)
|
||||
);
|
||||
//JV-082: Fix for missing "Class" search feature
|
||||
// JV-082: Fix for missing "Class" search feature
|
||||
this.addSpellFilter(
|
||||
"CMPBrowser.general",
|
||||
"ITEM.TypeClass",
|
||||
|
@ -1437,7 +1440,7 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
async addFeatFilters() {
|
||||
// Feature Filters
|
||||
//Foundry v10+ Item#data is now Item#system
|
||||
// Foundry v10+ Item#data is now Item#system
|
||||
this.addFeatFilter("CMPBrowser.general", "DND5E.Source", "system.source", "text");
|
||||
this.addFeatFilter(
|
||||
"CMPBrowser.general",
|
||||
|
@ -1651,7 +1654,7 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
|
||||
async renderWith(tab = "spell", filters = []) {
|
||||
//if there isn't a tab error out
|
||||
// if there isn't a tab error out
|
||||
if (!this[`${tab}Filters`]) {
|
||||
ui.notifications.warn(`no tab by name ${tab}`);
|
||||
return;
|
||||
|
@ -1685,8 +1688,8 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
this[`${tab}Filters`].activeFilters = activateFilters;
|
||||
|
||||
//wait for after the afterRender function to change tabs
|
||||
//this avoids some errors when initially opening the window
|
||||
// wait for after the afterRender function to change tabs
|
||||
// this avoids some errors when initially opening the window
|
||||
CompendiumBrowser.postRender = async () => {
|
||||
CompendiumBrowser.postRender = () => {};
|
||||
|
||||
|
@ -1719,7 +1722,7 @@ class CompendiumBrowser extends Application {
|
|||
c.prop("checked", true);
|
||||
}
|
||||
} else {
|
||||
ui.notifications.warn(`Unknown filter type?`);
|
||||
ui.notifications.warn("Unknown filter type?");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1756,7 +1759,7 @@ class CompendiumBrowser extends Application {
|
|||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
ui.notifications.info("Javascript Copied to clipboard");
|
||||
} catch (err) {
|
||||
} catch(err) {
|
||||
ui.notifications.warn("failed to copy javascript to clipboard, check logs for string");
|
||||
console.error("Failed to copy: ", err);
|
||||
}
|
||||
|
@ -1765,9 +1768,9 @@ class CompendiumBrowser extends Application {
|
|||
getSearchText(tab) {
|
||||
const target = `${tab}Filters`;
|
||||
|
||||
//map active filters to their labels
|
||||
// map active filters to their labels
|
||||
let output = Object.values(this[target].activeFilters).map((filter) => {
|
||||
//find Filters from paths
|
||||
// find Filters from paths
|
||||
let out = this.findFilterR(target, filter);
|
||||
|
||||
if (filter.value) {
|
||||
|
@ -1795,7 +1798,7 @@ class CompendiumBrowser extends Application {
|
|||
|
||||
ui.notifications.warn("Could not find the filter!!");
|
||||
console.warn(filterTarget);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static async addTidySheetButton(cb, html, actor) {
|
||||
|
@ -1872,7 +1875,7 @@ class CompendiumBrowser extends Application {
|
|||
});
|
||||
}
|
||||
|
||||
//find the first caster class of the character
|
||||
// find the first caster class of the character
|
||||
static findCasterClass(character) {
|
||||
const options = ["artificer", "bard", "cleric", "druid", "paladin", "ranger", "sorcerer", "warlock", "wizard"];
|
||||
|
||||
|
@ -1886,9 +1889,9 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
|
||||
static findMaxCasterLevel(character) {
|
||||
//find max spell level
|
||||
// find max spell level
|
||||
let maxLevel = Object.keys(character.system.spells).reduce((acc, spell) => {
|
||||
//special case for pact magic
|
||||
// special case for pact magic
|
||||
if (spell == "pact") {
|
||||
return Math.max(character.system.spells[spell].level, acc);
|
||||
} else {
|
||||
|
@ -1916,27 +1919,16 @@ class CompendiumBrowser extends Application {
|
|||
}
|
||||
}
|
||||
|
||||
Hooks.on("init", async () => {
|
||||
await loadTemplates([
|
||||
"modules/compendium-browser/template/spell-browser.html",
|
||||
"modules/compendium-browser/template/spell-browser-list.html",
|
||||
"modules/compendium-browser/template/npc-browser.html",
|
||||
"modules/compendium-browser/template/npc-browser-list.html",
|
||||
"modules/compendium-browser/template/feat-browser.html",
|
||||
"modules/compendium-browser/template/feat-browser-list.html",
|
||||
"modules/compendium-browser/template/item-browser.html",
|
||||
"modules/compendium-browser/template/item-browser-list.html",
|
||||
"modules/compendium-browser/template/filter-container.html",
|
||||
"modules/compendium-browser/template/settings.html",
|
||||
"modules/compendium-browser/template/loading.html",
|
||||
]);
|
||||
Hooks.once("init", async () => {
|
||||
registerSettings();
|
||||
await preloadTemplates();
|
||||
});
|
||||
|
||||
Hooks.on("ready", () => {
|
||||
if (game.compendiumBrowser === undefined) {
|
||||
game.compendiumBrowser = new CompendiumBrowser();
|
||||
//0.4.0 Defer loading content until we actually use the Compendium Browser
|
||||
//A compromise approach would be better (periodic loading) except would still create the memory use problem
|
||||
// 0.4.0 Defer loading content until we actually use the Compendium Browser
|
||||
// A compromise approach would be better (periodic loading) except would still create the memory use problem
|
||||
game.compendiumBrowser.initialize();
|
||||
}
|
||||
|
||||
|
@ -1955,11 +1947,11 @@ function stripDotCharacters(str) {
|
|||
}
|
||||
|
||||
function set(obj, path, value) {
|
||||
var schema = obj; // a moving reference to internal objects within obj
|
||||
var pList = path.split(".");
|
||||
var len = pList.length;
|
||||
for (var i = 0; i < len - 1; i++) {
|
||||
var elem = pList[i];
|
||||
let schema = obj; // a moving reference to internal objects within obj
|
||||
let pList = path.split(".");
|
||||
let len = pList.length;
|
||||
for (let i = 0; i < len - 1; i++) {
|
||||
let elem = pList[i];
|
||||
if (!schema[elem]) schema[elem] = {};
|
||||
schema = schema[elem];
|
||||
}
|
||||
|
@ -1970,13 +1962,13 @@ function set(obj, path, value) {
|
|||
function getPropByString(obj, propString) {
|
||||
if (!propString) return obj;
|
||||
|
||||
var prop,
|
||||
props = propString.split(".");
|
||||
let prop;
|
||||
let props = propString.split(".");
|
||||
|
||||
for (var i = 0, iLen = props.length - 1; i < iLen; i++) {
|
||||
prop = props[i];
|
||||
|
||||
var candidate = obj[prop];
|
||||
let candidate = obj[prop];
|
||||
if (candidate !== undefined) {
|
||||
obj = candidate;
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export async function preloadTemplates() {
|
||||
const templatePaths = [
|
||||
"modules/compendium-browser/templates/spell-browser.html",
|
||||
"modules/compendium-browser/templates/spell-browser-list.html",
|
||||
"modules/compendium-browser/templates/npc-browser.html",
|
||||
"modules/compendium-browser/templates/npc-browser-list.html",
|
||||
"modules/compendium-browser/templates/feat-browser.html",
|
||||
"modules/compendium-browser/templates/feat-browser-list.html",
|
||||
"modules/compendium-browser/templates/item-browser.html",
|
||||
"modules/compendium-browser/templates/item-browser-list.html",
|
||||
"modules/compendium-browser/templates/filter-container.html",
|
||||
"modules/compendium-browser/templates/settings.html",
|
||||
"modules/compendium-browser/templates/loading.html",
|
||||
];
|
||||
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export function registerSettings() {
|
||||
// Register any custom module settings here
|
||||
}
|
|
@ -24,11 +24,11 @@
|
|||
<button id="reset-feat-filter">{{localize "CMPBrowser.Filters.ResetFilters"}}</button>
|
||||
<!-- <button id="copy-search-feat">Export to <i class="fa-brands fa-square-js"></i></button> -->
|
||||
</div>
|
||||
{{> "modules/compendium-browser/template/filter-container.html" filters=featFilters}}
|
||||
{{> "modules/compendium-browser/templates/filter-container.html" filters=featFilters}}
|
||||
</div>
|
||||
<div class="list-area flexcol">
|
||||
<ul id="CBFeats">
|
||||
{{> "modules/compendium-browser/template/feat-browser-list.html" feats=items}}
|
||||
{{> "modules/compendium-browser/templates/feat-browser-list.html" feats=items}}
|
||||
</ul>
|
||||
<span class="loading" id="CBFeatsMessage" style="flex: 0"></span>
|
||||
</div>
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
<button id="reset-item-filter">{{localize "CMPBrowser.Filters.ResetFilters"}}</button>
|
||||
<!-- <button id="copy-search-item">Export to <i class="fa-brands fa-square-js"></i></button> -->
|
||||
</div>
|
||||
{{> "modules/compendium-browser/template/filter-container.html" filters=itemFilters}}
|
||||
{{> "modules/compendium-browser/templates/filter-container.html" filters=itemFilters}}
|
||||
</div>
|
||||
<div class="list-area flexcol">
|
||||
<ul id="CBItems">
|
||||
{{> "modules/compendium-browser/template/item-browser-list.html" items=items}}
|
||||
{{> "modules/compendium-browser/templates/item-browser-list.html" items=items}}
|
||||
</ul>
|
||||
<span class="loading" id="CBItemsMessage" style="flex: 0"></span>
|
||||
</div>
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
<button id="reset-npc-filter">{{localize "CMPBrowser.Filters.ResetFilters"}}</button>
|
||||
<!-- <button id="copy-search-item">Export to <i class="fa-brands fa-square-js"></i></button> -->
|
||||
</div>
|
||||
{{> "modules/compendium-browser/template/filter-container.html" filters=npcFilters}}
|
||||
{{> "modules/compendium-browser/templates/filter-container.html" filters=npcFilters}}
|
||||
</div>
|
||||
<div class="list-area flexcol">
|
||||
<ul id="CBNPCs">
|
||||
{{> "modules/compendium-browser/template/npc-browser-list.html" npcs=npcs}}
|
||||
{{> "modules/compendium-browser/templates/npc-browser-list.html" npcs=npcs}}
|
||||
</ul>
|
||||
<span class="loading" id="CBNpcsMessage" style="flex: 0"></span>
|
||||
</div>
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
<button id="reset-spell-filter">{{localize "CMPBrowser.Filters.ResetFilters"}}</button>
|
||||
<!-- <button id="copy-search-spell">Export to <i class="fa-brands fa-square-js"></i></button> -->
|
||||
</div>
|
||||
{{> "modules/compendium-browser/template/filter-container.html" filters=spellFilters}}
|
||||
{{> "modules/compendium-browser/templates/filter-container.html" filters=spellFilters}}
|
||||
</div>
|
||||
<div class="list-area flexcol">
|
||||
<ul id="CBSpells">
|
||||
{{> "modules/compendium-browser/template/spell-browser-list.html" spells=items}}
|
||||
{{> "modules/compendium-browser/templates/spell-browser-list.html" spells=items}}
|
||||
</ul>
|
||||
<span class="loading" id="CBSpellsMessage" style="flex: 0"></span>
|
||||
</div>
|
||||
|
|
|
@ -16,23 +16,23 @@
|
|||
<div class="content">
|
||||
<div class="tab" data-tab="spell">
|
||||
{{#if showSpellBrowser}}{{>
|
||||
"modules/compendium-browser/template/spell-browser.html"}}{{/if}}
|
||||
"modules/compendium-browser/templates/spell-browser.html"}}{{/if}}
|
||||
</div>
|
||||
<div class="tab" data-tab="feat">
|
||||
{{#if showFeatBrowser}}{{>
|
||||
"modules/compendium-browser/template/feat-browser.html"}}{{/if}}
|
||||
"modules/compendium-browser/templates/feat-browser.html"}}{{/if}}
|
||||
</div>
|
||||
<div class="tab" data-tab="item">
|
||||
{{#if showItemBrowser}}{{>
|
||||
"modules/compendium-browser/template/item-browser.html"}}{{/if}}
|
||||
"modules/compendium-browser/templates/item-browser.html"}}{{/if}}
|
||||
</div>
|
||||
<div class="tab" data-tab="npc">
|
||||
{{#if showNpcBrowser}} {{>
|
||||
"modules/compendium-browser/template/npc-browser.html"}}{{/if}}
|
||||
"modules/compendium-browser/templates/npc-browser.html"}}{{/if}}
|
||||
</div>
|
||||
<div class="tab" data-tab="setting">
|
||||
{{#if isGM}} {{>
|
||||
"modules/compendium-browser/template/settings.html"}}{{/if}}
|
||||
"modules/compendium-browser/templates/settings.html"}}{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue