diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..69cb355
Binary files /dev/null and b/.DS_Store differ
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..435132e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,11 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+[*.yml]
+indent_size = 2
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..565bde5
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,8 @@
+gulpfile.js
+.eslintrc.js
+.prettierrc.js
+dist
+jsconfig.json
+/dist
+/.pnp.js
+/.yarn/
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..cfc46a2
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,250 @@
+{
+ "env": {
+ "browser": true,
+ "es2021": true,
+ "node": true,
+ "jquery": true
+ },
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 2018,
+ "requireConfigFile": false,
+ "sourceType": "module",
+ "project": "./tsconfig.json"
+ },
+ "plugins": [
+ "jsdoc"
+ ],
+ "extends": [
+ "prettier",
+ "plugin:import/errors",
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:json/recommended"
+ ],
+ "ignorePatterns": ["dist/"],
+ "rules": {
+ "array-bracket-spacing": ["warn", "never"],
+ "array-callback-return": "warn",
+ "arrow-spacing": "warn",
+ "comma-dangle": ["warn", "never"],
+ "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-loop-func": "warn",
+ "no-misleading-character-class": "warn",
+ "no-mixed-operators": "warn",
+ "no-multi-str": "warn",
+ "no-multiple-empty-lines": "warn",
+ "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", "as-needed", {"requireForBlockBody": false}],
+ "capitalized-comments": ["warn", "always", {"ignoreConsecutiveComments": true}],
+ "comma-spacing": "warn",
+ "dot-notation": "warn",
+ "indent": ["warn", 2, {"SwitchCase": 1}],
+ "key-spacing": "warn",
+ "keyword-spacing": ["warn", {"overrides": {"catch": {"before": true, "after": false}}}],
+ "max-len": ["warn", {
+ "code": 120,
+ "ignoreTrailingComments": true,
+ "ignoreUrls": true,
+ "ignoreStrings": true,
+ "ignoreTemplateLiterals": true
+ }],
+ "no-extra-boolean-cast": ["warn", {"enforceForLogicalOperands": true}],
+ "no-extra-semi": "warn",
+ "no-multi-spaces": ["warn", {"ignoreEOLComments": true}],
+ "no-tabs": "warn",
+ "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": "never",
+ "named": "never",
+ "asyncArrow": "always"
+ }],
+ // "spaced-comment": "warn",
+
+ "jsdoc/check-access": "warn",
+ "jsdoc/check-alignment": "warn",
+ "jsdoc/check-examples": "off",
+ "jsdoc/check-indentation": "off",
+ "jsdoc/check-line-alignment": "off",
+ "jsdoc/check-param-names": "warn",
+ "jsdoc/check-property-names": "warn",
+ "jsdoc/check-syntax": "off",
+ "jsdoc/check-tag-names": "warn",
+ "jsdoc/check-types": "warn",
+ "jsdoc/check-values": "warn",
+ "jsdoc/empty-tags": "warn",
+ "jsdoc/implements-on-classes": "warn",
+ "jsdoc/match-description": "off",
+ "jsdoc/newline-after-description": "off",
+ "jsdoc/no-bad-blocks": "warn",
+ "jsdoc/no-defaults": "off",
+ "jsdoc/no-types": "off",
+ "jsdoc/no-undefined-types": "off",
+ "jsdoc/require-description": "warn",
+ "jsdoc/require-description-complete-sentence": "off",
+ "jsdoc/require-example": "off",
+ "jsdoc/require-file-overview": "off",
+ "jsdoc/require-hyphen-before-param-description": ["warn", "never"],
+ "jsdoc/require-jsdoc": "warn",
+ "jsdoc/require-param": "warn",
+ "jsdoc/require-param-description": "off",
+ "jsdoc/require-param-name": "warn",
+ "jsdoc/require-param-type": "warn",
+ "jsdoc/require-property": "warn",
+ "jsdoc/require-property-description": "off",
+ "jsdoc/require-property-name": "warn",
+ "jsdoc/require-property-type": "warn",
+ "jsdoc/require-returns": "warn",
+ "jsdoc/require-returns-check": "warn",
+ "jsdoc/require-returns-description": "off",
+ "jsdoc/require-returns-type": "warn",
+ "jsdoc/require-throws": "off",
+ "jsdoc/require-yields": "warn",
+ "jsdoc/require-yields-check": "warn",
+ "jsdoc/valid-types": "off",
+
+ "eqeqeq": ["error", "always"],
+ "import/named": "off",
+ "import/no-default-export": "error",
+ "prettier/prettier": "error",
+ "no-console": "off",
+ "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
+ "spaced-comment": "error",
+ "@typescript-eslint/await-thenable": "error",
+ "@typescript-eslint/ban-ts-comment": "off",
+ "@typescript-eslint/ban-types": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off",
+ "@typescript-eslint/lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/no-namespace": ["error", { "allowDeclarations": true }],
+ "@typescript-eslint/no-empty-function": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/no-unused-vars": "off", // Handled by tsconfig
+ "@typescript-eslint/array-type": ["error", { "default": "array" }]
+ },
+ "settings": {
+ "jsdoc": {
+ "preferredTypes": {
+ ".<>": "<>"
+ },
+ "tagNamePreference": {
+ "auguments": "extends"
+ }
+ },
+ "import/resolver": {
+ "node": {
+ "paths": ["src", "types", "", "dist"],
+ "extensions": [".css", ".js", ".mjs", ".json", ".jsx", ".scss", ".ts", ".tsx"]
+ },
+ "eslint-import-resolver-typescript": true,
+ "typescript": {
+ "alwaysTryTypes": true
+ }
+ },
+ "import/parsers": { "@typescript-eslint/parser": [".ts"] }
+ }
+}
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 8bb74b9..0000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,462 +0,0 @@
-module.exports = {
- env: {
- jquery: true,
- browser: true,
- es2020: true,
- },
- extends: [
- 'airbnb-base',
- ],
- parser: 'babel-eslint',
- parserOptions: {
- ecmaVersion: 11,
- sourceType: 'module',
- },
- rules: {
- // Required for Foundry compatibility
- 'no-underscore-dangle': 'off',
- 'import/extensions': 'off',
- 'class-methods-use-this': ['error', {
- exceptMethods: ['getData', '_updateObject'],
- }],
- // Personal Preference
- 'linebreak-style': 'off',
- 'no-mixed-operators': 'off',
- 'no-param-reassign': 'off',
- 'brace-style': [
- 'error',
- 'stroustrup',
- ],
- },
- globals: {
- AudioHelper: 'readonly',
- Collection: 'readonly',
- Hooks: 'readonly',
- KeyboardManager: 'readonly',
- ClientSettings: 'readonly',
- WorldSettingsStorage: 'readonly',
- SetupConfiguration: 'readonly',
- SocketInterface: 'readonly',
- SortingHelpers: 'readonly',
- VideoHelper: 'readonly',
- Application: 'readonly',
- FormApplication: 'readonly',
- BaseEntitySheet: 'readonly',
- Localization: 'readonly',
- Game: 'readonly',
- Die: 'readonly',
- FateDie: 'readonly',
- DicePool: 'readonly',
- Roll: 'readonly',
- MersenneTwister: 'readonly',
- EntityCollection: 'readonly',
- Compendium: 'readonly',
- Entity: 'readonly',
- Canvas: 'readonly',
- CanvasLayer: 'readonly',
- PlaceableObject: 'readonly',
- PlaceablesLayer: 'readonly',
- ContextMenu: 'readonly',
- Dialog: 'readonly',
- Draggable: 'readonly',
- DragDrop: 'readonly',
- TextEditor: 'readonly',
- FilePicker: 'readonly',
- Notifications: 'readonly',
- Tabs: 'readonly',
- TabsV2: 'readonly',
- WebRTC: 'readonly',
- WebRTCInterface: 'readonly',
- WebRTCSettings: 'readonly',
- ActorSheet: 'readonly',
- AVConfig: 'readonly',
- CombatTrackerConfig: 'readonly',
- FolderConfig: 'readonly',
- GridConfig: 'readonly',
- ImagePopout: 'readonly',
- ItemSheet: 'readonly',
- JournalSheet: 'readonly',
- MacroConfig: 'readonly',
- MeasuredTemplateConfig: 'readonly',
- PermissionControl: 'readonly',
- PlayerConfig: 'readonly',
- PlaylistConfig: 'readonly',
- PlaylistSoundConfig: 'readonly',
- RollTableConfig: 'readonly',
- SceneConfig: 'readonly',
- EntitySheetConfig: 'readonly',
- CameraPopoutAppWrapper: 'readonly',
- CameraViews: 'readonly',
- ChatBubbles: 'readonly',
- HeadsUpDisplay: 'readonly',
- SceneControls: 'readonly',
- Hotbar: 'readonly',
- BasePlaceableHUD: 'readonly',
- MainMenu: 'readonly',
- SceneNavigation: 'readonly',
- Pause: 'readonly',
- PlayerList: 'readonly',
- DrawingConfig: 'readonly',
- DrawingHUD: 'readonly',
- LightConfig: 'readonly',
- NoteConfig: 'readonly',
- AmbientSoundConfig: 'readonly',
- TileConfig: 'readonly',
- TileHUD: 'readonly',
- TokenConfig: 'readonly',
- TokenHUD: 'readonly',
- WallConfig: 'readonly',
- EULA: 'readonly',
- InstallPackage: 'readonly',
- SetupConfigurationForm: 'readonly',
- UpdateNotes: 'readonly',
- UserManagement: 'readonly',
- WorldConfig: 'readonly',
- Sidebar: 'readonly',
- SidebarTab: 'readonly',
- SidebarDirectory: 'readonly',
- Actors: 'readonly',
- Actor: 'readonly',
- ActorTokenHelpers: 'readonly',
- CombatEncounters: 'readonly',
- Combat: 'readonly',
- Folders: 'readonly',
- Folder: 'readonly',
- Items: 'readonly',
- Item: 'readonly',
- Journal: 'readonly',
- JournalEntry: 'readonly',
- Macros: 'readonly',
- Macro: 'readonly',
- Messages: 'readonly',
- ChatMessage: 'readonly',
- Playlists: 'readonly',
- Playlist: 'readonly',
- Scenes: 'readonly',
- Scene: 'readonly',
- RollTables: 'readonly',
- RollTable: 'readonly',
- Users: 'readonly',
- User: 'readonly',
- UserTargets: 'readonly',
- CanvasAnimation: 'readonly',
- ControlIcon: 'readonly',
- TextureLoader: 'readonly',
- MouseInteractionManager: 'readonly',
- Ray: 'readonly',
- NormalizedRectangle: 'readonly',
- ResizeHandle: 'readonly',
- SightLayerSource: 'readonly',
- BackgroundLayer: 'readonly',
- DrawingsLayer: 'readonly',
- EffectsLayer: 'readonly',
- LightingLayer: 'readonly',
- NotesLayer: 'readonly',
- SightLayer: 'readonly',
- SoundsLayer: 'readonly',
- TemplateLayer: 'readonly',
- TilesLayer: 'readonly',
- TokenLayer: 'readonly',
- WallsLayer: 'readonly',
- Drawing: 'readonly',
- AmbientLight: 'readonly',
- Note: 'readonly',
- AmbientSound: 'readonly',
- MeasuredTemplate: 'readonly',
- Tile: 'readonly',
- Token: 'readonly',
- Wall: 'readonly',
- SettingsConfig: 'readonly',
- ControlsReference: 'readonly',
- InvitationLinks: 'readonly',
- ModuleManagement: 'readonly',
- PermissionConfig: 'readonly',
- ActorDirectory: 'readonly',
- ChatLog: 'readonly',
- CombatTracker: 'readonly',
- CompendiumDirectory: 'readonly',
- ItemDirectory: 'readonly',
- JournalDirectory: 'readonly',
- MacroDirectory: 'readonly',
- PlaylistDirectory: 'readonly',
- SceneDirectory: 'readonly',
- Settings: 'readonly',
- FrameViewer: 'readonly',
- RollTableDirectory: 'readonly',
- Cursor: 'readonly',
- DoorControl: 'readonly',
- ControlsLayer: 'readonly',
- Ruler: 'readonly',
- SpecialEffect: 'readonly',
- AutumnLeavesWeatherEffect: 'readonly',
- RainWeatherEffect: 'readonly',
- SnowWeatherEffect: 'readonly',
- BaseGrid: 'readonly',
- HexagonalGrid: 'readonly',
- GridHighlight: 'readonly',
- GridLayer: 'readonly',
- SquareGrid: 'readonly',
- EasyRTCClient: 'readonly',
- parent: 'readonly',
- opener: 'readonly',
- top: 'readonly',
- length: 'readonly',
- frames: 'readonly',
- closed: 'readonly',
- location: 'readonly',
- self: 'readonly',
- window: 'readonly',
- document: 'readonly',
- name: 'readonly',
- customElements: 'readonly',
- history: 'readonly',
- locationbar: 'readonly',
- menubar: 'readonly',
- personalbar: 'readonly',
- scrollbars: 'readonly',
- statusbar: 'readonly',
- toolbar: 'readonly',
- status: 'readonly',
- frameElement: 'readonly',
- navigator: 'readonly',
- origin: 'readonly',
- external: 'readonly',
- screen: 'readonly',
- innerWidth: 'readonly',
- innerHeight: 'readonly',
- scrollX: 'readonly',
- pageXOffset: 'readonly',
- scrollY: 'readonly',
- pageYOffset: 'readonly',
- visualViewport: 'readonly',
- screenX: 'readonly',
- screenY: 'readonly',
- outerWidth: 'readonly',
- outerHeight: 'readonly',
- devicePixelRatio: 'readonly',
- clientInformation: 'readonly',
- screenLeft: 'readonly',
- screenTop: 'readonly',
- defaultStatus: 'readonly',
- defaultstatus: 'readonly',
- styleMedia: 'readonly',
- onsearch: 'readonly',
- isSecureContext: 'readonly',
- onabort: 'readonly',
- onblur: 'readonly',
- oncancel: 'readonly',
- oncanplay: 'readonly',
- oncanplaythrough: 'readonly',
- onchange: 'readonly',
- onclick: 'readonly',
- onclose: 'readonly',
- oncontextmenu: 'readonly',
- oncuechange: 'readonly',
- ondblclick: 'readonly',
- ondrag: 'readonly',
- ondragend: 'readonly',
- ondragenter: 'readonly',
- ondragleave: 'readonly',
- ondragover: 'readonly',
- ondragstart: 'readonly',
- ondrop: 'readonly',
- ondurationchange: 'readonly',
- onemptied: 'readonly',
- onended: 'readonly',
- onerror: 'readonly',
- onfocus: 'readonly',
- onformdata: 'readonly',
- oninput: 'readonly',
- oninvalid: 'readonly',
- onkeydown: 'readonly',
- onkeypress: 'readonly',
- onkeyup: 'readonly',
- onload: 'readonly',
- onloadeddata: 'readonly',
- onloadedmetadata: 'readonly',
- onloadstart: 'readonly',
- onmousedown: 'readonly',
- onmouseenter: 'readonly',
- onmouseleave: 'readonly',
- onmousemove: 'readonly',
- onmouseout: 'readonly',
- onmouseover: 'readonly',
- onmouseup: 'readonly',
- onmousewheel: 'readonly',
- onpause: 'readonly',
- onplay: 'readonly',
- onplaying: 'readonly',
- onprogress: 'readonly',
- onratechange: 'readonly',
- onreset: 'readonly',
- onresize: 'readonly',
- onscroll: 'readonly',
- onseeked: 'readonly',
- onseeking: 'readonly',
- onselect: 'readonly',
- onstalled: 'readonly',
- onsubmit: 'readonly',
- onsuspend: 'readonly',
- ontimeupdate: 'readonly',
- ontoggle: 'readonly',
- onvolumechange: 'readonly',
- onwaiting: 'readonly',
- onwebkitanimationend: 'readonly',
- onwebkitanimationiteration: 'readonly',
- onwebkitanimationstart: 'readonly',
- onwebkittransitionend: 'readonly',
- onwheel: 'readonly',
- onauxclick: 'readonly',
- ongotpointercapture: 'readonly',
- onlostpointercapture: 'readonly',
- onpointerdown: 'readonly',
- onpointermove: 'readonly',
- onpointerup: 'readonly',
- onpointercancel: 'readonly',
- onpointerover: 'readonly',
- onpointerout: 'readonly',
- onpointerenter: 'readonly',
- onpointerleave: 'readonly',
- onselectstart: 'readonly',
- onselectionchange: 'readonly',
- onanimationend: 'readonly',
- onanimationiteration: 'readonly',
- onanimationstart: 'readonly',
- ontransitionend: 'readonly',
- onafterprint: 'readonly',
- onbeforeprint: 'readonly',
- onbeforeunload: 'readonly',
- onhashchange: 'readonly',
- onlanguagechange: 'readonly',
- onmessage: 'readonly',
- onmessageerror: 'readonly',
- onoffline: 'readonly',
- ononline: 'readonly',
- onpagehide: 'readonly',
- onpageshow: 'readonly',
- onpopstate: 'readonly',
- onrejectionhandled: 'readonly',
- onstorage: 'readonly',
- onunhandledrejection: 'readonly',
- onunload: 'readonly',
- performance: 'readonly',
- stop: 'readonly',
- open: 'readonly',
- alert: 'readonly',
- confirm: 'readonly',
- prompt: 'readonly',
- print: 'readonly',
- queueMicrotask: 'readonly',
- requestAnimationFrame: 'readonly',
- cancelAnimationFrame: 'readonly',
- captureEvents: 'readonly',
- releaseEvents: 'readonly',
- requestIdleCallback: 'readonly',
- cancelIdleCallback: 'readonly',
- getComputedStyle: 'readonly',
- matchMedia: 'readonly',
- moveTo: 'readonly',
- moveBy: 'readonly',
- resizeTo: 'readonly',
- resizeBy: 'readonly',
- scroll: 'readonly',
- scrollTo: 'readonly',
- scrollBy: 'readonly',
- getSelection: 'readonly',
- find: 'readonly',
- webkitRequestAnimationFrame: 'readonly',
- webkitCancelAnimationFrame: 'readonly',
- fetch: 'readonly',
- btoa: 'readonly',
- atob: 'readonly',
- setTimeout: 'readonly',
- clearTimeout: 'readonly',
- setInterval: 'readonly',
- clearInterval: 'readonly',
- createImageBitmap: 'readonly',
- close: 'readonly',
- focus: 'readonly',
- blur: 'readonly',
- postMessage: 'readonly',
- onappinstalled: 'readonly',
- onbeforeinstallprompt: 'readonly',
- crypto: 'readonly',
- indexedDB: 'readonly',
- webkitStorageInfo: 'readonly',
- sessionStorage: 'readonly',
- localStorage: 'readonly',
- chrome: 'readonly',
- applicationCache: 'readonly',
- onpointerrawupdate: 'readonly',
- trustedTypes: 'readonly',
- speechSynthesis: 'readonly',
- webkitRequestFileSystem: 'readonly',
- webkitResolveLocalFileSystemURL: 'readonly',
- openDatabase: 'readonly',
- caches: 'readonly',
- ondevicemotion: 'readonly',
- ondeviceorientation: 'readonly',
- ondeviceorientationabsolute: 'readonly',
- Handlebars: 'readonly',
- HandlebarsIntl: 'readonly',
- HowlerGlobal: 'readonly',
- Howler: 'readonly',
- Howl: 'readonly',
- Sound: 'readonly',
- WebFont: 'readonly',
- PIXI: 'readonly',
- io: 'readonly',
- tinymce: 'readonly',
- tinyMCE: 'readonly',
- easyrtc_lang: 'readonly',
- adapter: 'readonly',
- easyrtc: 'readonly',
- duplicate: 'readonly',
- getType: 'readonly',
- invertObject: 'readonly',
- filterObject: 'readonly',
- flattenObject: 'readonly',
- expandObject: 'readonly',
- isObjectEmpty: 'readonly',
- mergeObject: 'readonly',
- diffObject: 'readonly',
- hasProperty: 'readonly',
- getProperty: 'readonly',
- setProperty: 'readonly',
- encodeURL: 'readonly',
- rgbToHsv: 'readonly',
- hsvToRgb: 'readonly',
- rgbToHex: 'readonly',
- hexToRGB: 'readonly',
- hexToRGBAString: 'readonly',
- colorStringToHex: 'readonly',
- isNewerVersion: 'readonly',
- randomID: 'readonly',
- loadFont: 'readonly',
- saveDataToFile: 'readonly',
- readTextFromFile: 'readonly',
- fromUuid: 'readonly',
- _handleMouseWheelInputChange: 'readonly',
- getTemplate: 'readonly',
- loadTemplates: 'readonly',
- renderTemplate: 'readonly',
- srcExists: 'readonly',
- getTexture: 'readonly',
- loadTexture: 'readonly',
- CONST: 'readonly',
- toDegrees: 'readonly',
- normalizeDegrees: 'readonly',
- toRadians: 'readonly',
- normalizeRadians: 'readonly',
- validateForm: 'readonly',
- timeSince: 'readonly',
- _templateCache: 'readonly',
- CONFIG: 'readonly',
- socket: 'readonly',
- ui: 'readonly',
- canvas: 'readonly',
- keyboard: 'readonly',
- JSHINT: 'readonly',
- game: 'readonly',
- },
-};
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..2376a0d
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,7 @@
+.github export-ignore
+FUNDING.yml export-ignore
+
+.gitattributes export-ignore
+README.md export-ignore
+preview.jpg export-ignore
+patchnotes.md export-ignore
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..d8ed97e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,44 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: "[BUG]"
+labels: bug
+assignees: ''
+
+---
+
+**Module Version:** v0.0.0
+
+**Before open any issue**
+
+1) Enable the module setting _"Enable debugging"_
+2) Click F12 go to the _console_ tab
+3) make the test you want and replicate the error
+4) Go to the tab console open on point 2) and just right click and click 'Save as' and 'Save' or send a screenshot of the exception on the console.
+5) Attach the text file on the github issue with all the logs related tot he module, or send a screenshot of the messages on the console.
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Browser:**
+ -
+
+**Foundry Version:**
+
+**Game System:**
+
+**Additional context**
+Add any other context (like other modules installed) about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..809b7b0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,10 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: enhancement
+assignees: ''
+
+---
+
+
diff --git a/.github/ISSUE_TEMPLATE/styling.md b/.github/ISSUE_TEMPLATE/styling.md
new file mode 100644
index 0000000..914837c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/styling.md
@@ -0,0 +1,10 @@
+---
+name: Styling
+about: Request a change or bug related to styles
+title: ''
+labels: styling
+assignees: ''
+
+---
+
+
diff --git a/.github/workflows/main.yml.DISABLED b/.github/workflows/main.yml.DISABLED
new file mode 100644
index 0000000..a94342d
--- /dev/null
+++ b/.github/workflows/main.yml.DISABLED
@@ -0,0 +1,54 @@
+name: Release Creation
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ #Substitute the Manifest and Download URLs in the module.json
+ - name: Substitute Manifest and Download Links For Versioned Ones
+ id: sub_manifest_link_version
+ uses: microsoft/variable-substitution@v1
+ with:
+ files: 'src/module.json'
+ env:
+ version: ${{github.event.release.tag_name}}
+ manifest: https://github.com/${{github.repository}}/releases/latest/download/module.json
+ download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip
+
+ # create a zip file with all files required by the module to add to the release
+ - run: cd src; zip -r ./module.zip *
+
+ # Create a release for this specific version
+ - name: Update Release with Files
+ id: create_version_release
+ uses: ncipollo/release-action@v1
+ with:
+ allowUpdates: true # set this to false if you want to prevent updating existing releases
+ name: ${{ github.event.release.name }}
+ draft: false
+ prerelease: false
+ token: ${{ secrets.GITHUB_TOKEN }}
+ artifacts: 'src/module.json, src/module.zip'
+ tag: ${{ github.event.release.tag_name }}
+ body: ${{ github.event.release.body }}
+
+ # Update the 'latest' release
+ - name: Create Release
+ id: create_latest_release
+ uses: ncipollo/release-action@v1
+ if: endsWith(github.ref, 'master')
+ with:
+ allowUpdates: true
+ name: Latest
+ draft: false
+ prerelease: false
+ token: ${{ secrets.GITHUB_TOKEN }}
+ artifacts: 'src/module.json,src/module.zip'
+ tag: latest
+ body: ${{ github.event.release.body }}
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..d133067
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,59 @@
+name: Release Creation
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ # get part of the tag after the `v`
+ - name: Extract tag version number
+ id: get_version
+ uses: battila7/get-version-action@v2
+
+ # Substitute the Manifest and Download URLs in the module.json for Pre-Release
+ - name: Substitute Manifest and Download Links For Pre-Release Tests
+ if: ${{ github.event.release.prerelease == true }}
+ id: sub_manifest_link_version_prerelease
+ uses: microsoft/variable-substitution@v1
+ with:
+ files: 'src/module.json'
+ env:
+ version: ${{steps.get_version.outputs.version-without-v}}
+ url: https://github.com/${{github.repository}}
+ manifest: https://github.com/${{github.repository}}/releases/${{github.event.release.tag_name}}/download/module.json
+ download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip
+
+ # Substitute the Manifest and Download URLs in the module.json in Releases
+ - name: Substitute Manifest and Download Links For Versioned Ones
+ if: ${{ github.event.release.prerelease == false }}
+ id: sub_manifest_link_version
+ uses: microsoft/variable-substitution@v1
+ with:
+ files: 'src/module.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/module.json
+ download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip
+
+ # Create a zip file with all files required by the module to add to the release
+ - run: cd src; zip -r ./module.zip *
+
+ # Create a release for this specific version
+ - name: Update Release with Files
+ id: create_version_release
+ uses: ncipollo/release-action@v1
+ with:
+ allowUpdates: true # Set this to false if you want to prevent updating existing releases
+ name: ${{ github.event.release.name }}
+ draft: ${{ github.event.release.unpublished }}
+ prerelease: ${{ github.event.release.prerelease }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+ artifacts: './src/module.json, ./src/module.zip'
+ tag: ${{ github.event.release.tag_name }}
+ body: ${{ github.event.release.body }}
diff --git a/.gitignore b/.gitignore
index b0775f6..00e8c01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,3 @@
-foundry.js
-.vscode
-simplefog.zip
-
# Logs
logs
*.log
@@ -86,7 +82,6 @@ out
# Nuxt.js build / generate output
.nuxt
-dist
# Gatsby files
.cache/
@@ -117,4 +112,13 @@ dist
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
-.pnp.*
\ No newline at end of file
+.pnp.*
+
+# Foundry
+foundry.js
+/.vscode
+/dist
+/package
+
+# Intellij
+/.idea
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..3251356
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,31 @@
+module.exports = {
+ printWidth: 120,
+ tabWidth: 4,
+ useTabs: true,
+ overrides: [
+ {
+ files: ["*.scss", "*.css"],
+ options: {
+ requirePragma: false,
+ parser: "scss",
+ },
+ },
+ {
+ files: "*.html",
+ options: {
+ requirePragma: false,
+ parser: "html",
+ htmlWhitespaceSensitivity: "ignore",
+ },
+ },
+ {
+ files: "*.hbs",
+ options: {
+ requirePragma: false,
+ parser: "glimmer",
+ singleQuote: false,
+ htmlWhitespaceSensitivity: "ignore",
+ },
+ },
+ ],
+};
diff --git a/README.md b/README.md
index 685f7e5..d74b0a4 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,32 @@
+    
+
+ [](https://forge-vtt.com/bazaar#package=simplefog)   [](https://www.foundryvtt-hub.com/package/simplefog/) 
+
+[](https://weblate.foundryvtt-hub.com/engage/simplefog/)
+
# Simplefog
A module for [FoundryVTT](https://foundryvtt.com) that lets you draw fog of war manually.
+## Installation
+
+It's always easiest to install modules from the in game add-on browser.
+
+To install this module manually:
+1. Inside the Foundry "Configuration and Setup" screen, click "Add-on Modules"
+2. Click "Install Module"
+3. In the "Manifest URL" field, paste the following url:
+`https://raw.githubusercontent.com/League-of-Foundry-Developers/simplefog/master/src/module.json`
+4. Click 'Install' and wait for installation to complete
+5. Don't forget to enable the module in game using the "Manage Module" button
+
## Feature overview video
+
[](https://www.youtube.com/watch?v=gTt6FDQ7iQA)
Encounter Library did a review of Simplefog which explains how it works much better than I can, please check it out if you would like an idea how this module works.
## Features
+
- Simplefog implements a manual fog of war layer above the core vision layer
- Enable and disable the simplefog layer at any time, per scene
- This allows you to use both Simplefog AND the core vision for line of sight, or alternatively use only one or the other, on a scene by scene basis
@@ -21,11 +41,13 @@ Encounter Library did a review of Simplefog which explains how it works much bet
- Click the orange handle to finish your drawing, or right click to cancel
- Grid tool
- Reveals any grid square you drag across, works for both Hex and Square grids
+- Add an image to the Simplefog layer which overlays the selected tint for both GMs and Players.

## Scene Configuration
Allows you to set various options which affect the entire layer for the current scene
+- Set an image overlay for the fog on both player and GM screens.
- Set the opacity of the entire fog layer for both players and GMs
- Animate transitions in opacity, allowing for effects such as "Fade to Black"
- Change tint of the fog for both player and GM, for example to indicate a green poison cloud
@@ -41,10 +63,83 @@ Allows you to set various options which affect the entire layer for the current
- Reveal only if entire token visible
- Reveal if any part of token is visible
- Brush Smoothing / Interpolation
-- Image based fog import
- Sepia / monochrome filters
- Add indicator icon of player controlled icons hidden under fog
- Currently incompatible with the module "GM Scene Background" when a GM layer is active
-# Bugs and Feature Requests
-Please ping me on discord @vance#1935
\ No newline at end of file
+## Api
+
+# Build
+
+## Install all packages
+
+```bash
+npm install
+```
+## npm build scripts
+
+### build
+
+will build the code and copy all necessary assets into the dist folder and make a symlink to install the result into your foundry data; create a
+`foundryconfig.json` file with your Foundry Data path.
+
+```json
+{
+ "dataPath": "~/.local/share/FoundryVTT/"
+}
+```
+
+`build` will build and set up a symlink between `dist` and your `dataPath`.
+
+```bash
+npm run-script build
+```
+
+### NOTE:
+
+You don't need to build the `foundryconfig.json` file you can just copy the content of the `dist` folder on the module folder under `modules` of Foundry
+
+### build:watch
+
+`build:watch` will build and watch for changes, rebuilding automatically.
+
+```bash
+npm run-script build:watch
+```
+
+### clean
+
+`clean` will remove all contents in the dist folder (but keeps the link from build:install).
+
+```bash
+npm run-script clean
+```
+
+### prettier-format
+
+`prettier-format` launch the prettier plugin based on the configuration [here](./.prettierrc)
+
+```bash
+npm run-script prettier-format
+```
+
+### package
+
+`package` generates a zip file containing the contents of the dist folder generated previously with the `build` command. Useful for those who want to manually load the module or want to create their own release
+
+```bash
+npm run-script package
+```
+
+## [Changelog](./changelog.md)
+
+## Issues
+
+Any issues, bugs, or feature requests are always welcome to be reported directly to the [Issue Tracker](https://github.com/p4535992/foundryvtt-final-blow/issues ), or using the [Bug Reporter Module](https://foundryvtt.com/packages/bug-reporter/).
+
+## License
+
+This package is under an [MIT license](LICENSE) and the [Foundry Virtual Tabletop Limited License Agreement for module development](https://foundryvtt.com/article/license/).
+## Credit
+
+- This is a continuation of SimpleFog, created by Vance. This is now being maintained under this fork with his permission. This was under the MIT license and continues to be so.
diff --git a/changelog.md b/changelog.md
index d4da976..aea4c0c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,45 +1,120 @@
-## 0.1.10
+# Simplefog Change Log
+
+### 0.3.4: Bug Fixes
+Jul 29, 2023
+* Fixes for v11 by @macskay in #110
+* Fixes for v11 by @mattd in #111
+
+### 0.3.3: Bug Fixes
+Jun 4, 2023
+* Prettier format by @cirrahn in #104
+* Avoid crash on initial load of history-less scene by @cirrahn in #105
+* Handle v10 changes in tooling by @cirrahn in #106
+
+### 0.3.1: Bug Fixes
+Dec 17, 2022
+* Fix Grid tool misaligned with the map's grid (Thanks cirrahn!) #95
+* Fog auto-enabling on all scenes repeatedly #92 #96
+
+### 0.3.0: v10 Support
+Oct 8, 2022
+* Release from beta
+
+### 0.3.0-BETA.7: v10 Support
+Oct 8, 2022
+* Various bug fixes for v10 #78
+* Image Overlay/fog not working #88
+* v10 Module Manifest #87
+
+### 0.3.0-ALPHA.3: v10 Support
+Sept 17, 2022
+* Initial dev support for v10 #78
+* Migrate global settings form the scene specific config to game settings #59
+
+### 0.2.2-ALPHA.0: Bugfixes
+June 16, 2022
+* Token labels appearing above fog #65
+ * **NOTE**: The current fix for this is to move the token controls down a few levels, so now they will be covered by not only simplefog, but also weather, lighting, and other effects. A more permanent solution is being investigated.
+* ZIndex not always being saved #66
+* Include notification to GM if version changes #68
+
+### 0.2.1: Bugfixes
+June 4, 2022
+* Rendering inconsistency on initial draw of history #58
+* Error during reload for partially initialized objects #57
+* Cleanup some debug code
+
+### 0.2.0: v9 Compatibility
+June 3, 2022
+* Integrate LoFD templates, github actions, etc...
+* Confirmation before toggle off #52
+* Migrate Simple Fog layer into the primary canvas group for v9 compatibility #51
+* Add in option for hotkey activation of Simple Fog #43 - Thanks @kenster421
+* Updates to japanese localizations #39 - Thanks @BrotherSharper
+* Make hotkey tool selectable
+* Update description, cleanup, etc...
+
+### 0.1.18: Compatibility Updates!
+Jun 03, 2021
+* Merge pull request #32 from Azzurite/compatibility-0.8.6
+* Compatibility for core version 0.8.6
+
+### 0.1.17: Bug Fixes
+Feb 07, 2021
+* Removed a feature that I believe was causing some bugs. This feature hasn't been working correctly anyways since Foundry updated to new layer system.
+
+### 0.1.16
+* Added ability to set whether fog is automatically enabled. Look at the bottom of the settings panel. Make sure to "Set current setttings to default" so it uses those settings by default ever time you create a a new scene.
+* Added Japanese localization. Thanks touge!
+
+### 0.1.15
+* Added the ability to optionally add an image over the fog!
+
+### 0.1.11 - 1.1.14
+* Compatibility fixes.
+
+### 0.1.10
* Fixes issue where migrations caused error when trying to update old fog data
* Fixes issue where grid drawing on hex grids would occassionally get stuck on certain coordinates
-## 0.1.9
+### 0.1.9
* Should fix the issue where fog would randomly reset under certain rare circumstances
* Adds option to blank the fog when resetting (i.e. reset to completely revealed state)
* Some more performance optimizations
* Prevent [ ] from activating when focus is not game board
-## 0.1.8
+### 0.1.8
* Fixes issue where shift + negative rect brush direction did not work properly
* Fixes issue where brush controls could become hidden under long lists of active scenes
* Fixes issue where hex grid detection was slightly inaccurate near corners
* Implements more efficient data storage which should reduce size of db data
-## 0.1.7
+### 0.1.7
* Fixes issue where brush tool labels were reversed
-* Fixes issue where quickly clicking brush tool could cause a race condition resulting in fog being reset
+* Fixes issue where quickly clicking brush tool could cause a race condition resulting in fog being reset
-## 0.1.6
+### 0.1.6
* Adds localization support
* Fixes bug where undo was not working correctly
-## 0.1.5
+### 0.1.5
* Significantly optimized the autovisibility feature which should make it useable on any size map with little performance impact
* Improvements to the fog storage data which should reduce the impact on scene database file size
-## 0.1.4
+### 0.1.4
* Fixes issue where players could receive warnings about not having permissions to edit scene
* Fixes incompatibility with various modules and systems, if you still encounter problems please let me know
-## 0.1.3
+### 0.1.3
* Fixes a rather nasty memory leak, thanks to @ruipin for pointing out the possibility for this to occur.
* The simplefog renderable texture will now scale resolution to allow for very large (> 16000x16000) scenes to work properly, albeit at a slightly reduced fog quality
* Players will now maintain control over their own token when moving into simplefog when autovisibility is enabled
-## 0.1.2
+### 0.1.2
* Allows AutoVisibility to be disabled for GM players while still enabled for players
-## 0.1.1
+### 0.1.1
* Fixes a compatibility issue with various modules that affect the layer stack
-## 0.1.0
-* Initial release
\ No newline at end of file
+### 0.1.0
+* Initial release
diff --git a/classes/BrushControls.js b/classes/BrushControls.js
deleted file mode 100644
index 44179b7..0000000
--- a/classes/BrushControls.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import { hexToPercent, percentToHex } from '../js/helpers.js';
-
-export default class BrushControls extends FormApplication {
- static get defaultOptions() {
- return mergeObject(super.defaultOptions, {
- classes: ['form'],
- closeOnSubmit: false,
- submitOnChange: true,
- submitOnClose: true,
- popOut: false,
- editable: game.user.isGM,
- template: 'modules/simplefog/templates/brush-controls.html',
- id: 'filter-config',
- title: game.i18n.localize('Simplefog Options'),
- });
- }
-
- /* -------------------------------------------- */
-
- /**
- * Obtain module metadata and merge it with game settings which track current module visibility
- * @return {Object} The data provided to the template when rendering the form
- */
- getData() {
- // Return data to the template
- return {
- brushSize: canvas.simplefog.getUserSetting('brushSize'),
- brushOpacity: hexToPercent(canvas.simplefog.getUserSetting('brushOpacity')),
- };
- }
-
- /* -------------------------------------------- */
- /* Event Listeners and Handlers */
- /* -------------------------------------------- */
-
- /** @override */
- activateListeners(html) {
- super.activateListeners(html);
- }
-
- /**
- * This method is called upon form submission after form data is validated
- * @param event {Event} The initial triggering submission event
- * @param formData {Object} The object of validated form data with which to update the object
- * @private
- */
- async _updateObject(event, formData) {
- canvas.simplefog.setUserSetting('brushSize', formData.brushSize);
- await canvas.simplefog.setUserSetting('brushOpacity', percentToHex(formData.brushOpacity));
- canvas.simplefog.setPreviewTint();
- }
-}
diff --git a/classes/MaskLayer.js b/classes/MaskLayer.js
deleted file mode 100644
index 75f8741..0000000
--- a/classes/MaskLayer.js
+++ /dev/null
@@ -1,377 +0,0 @@
-/* MaskLayer extends CanvasLayer
- *
- * Creates an interactive layer which has an alpha channel mask
- * that can be rendered to and history for syncing between players
- * and replaying the mask / undo etc.
- */
-
-import { simplefogLog } from '../js/helpers.js';
-
-export default class MaskLayer extends CanvasLayer {
- constructor(layername) {
- super();
- this.lock = false;
- this.layername = layername;
- this.historyBuffer = [];
- this.pointer = 0;
- this.gridLayout = {};
- this.dragStart = { x: 0, y: 0 };
- // Not actually used, just to prevent foundry from complaining
- this.history = [];
- this.BRUSH_TYPES = {
- ELLIPSE: 0,
- BOX: 1,
- ROUNDED_RECT: 2,
- POLYGON: 3,
- };
- this.DEFAULTS = {
- visible: false,
- blurQuality: 2,
- blurRadius: 5,
- };
- }
-
- /* -------------------------------------------- */
- /* Init */
- /* -------------------------------------------- */
-
- /**
- * Called on canvas init, creates the canvas layers and various objects and registers listeners
- *
- * Important objects:
- *
- * layer - PIXI Sprite which holds all the mask elements
- * filters - Holds filters such as blur applied to the layer
- * layer.mask - PIXI Sprite wrapping the renderable mask
- * maskTexture - renderable texture that holds the actual mask data
- */
- async maskInit() {
- // Check if masklayer is flagged visible
- let v = this.getSetting('visible');
- if (v === undefined) v = false;
- this.visible = v;
-
- // The layer is the primary sprite to be displayed
- this.layer = MaskLayer.getCanvasSprite();
- this.addChild(this.layer);
- this.setTint(this.getTint());
- this.setAlpha(this.getAlpha(), true);
-
- // Filters
- this.blur = new PIXI.filters.BlurFilter();
- this.blur.padding = 0;
- this.blur.repeatEdgePixels = true;
- this.blur.blur = this.getSetting('blurRadius');
- this.blur.quality = this.getSetting('blurQuality');
- this.filters = [this.blur];
-
- this.maskTexture = MaskLayer.getMaskTexture();
- this.layer.mask = new PIXI.Sprite(this.maskTexture);
- this.addChild(this.layer.mask);
- this.setFill();
-
- // Allow zIndex prop to function for items on this layer
- this.sortableChildren = true;
-
- // Render initial history stack
- this.renderStack();
- }
-
- /* -------------------------------------------- */
- /* History & Buffer */
- /* -------------------------------------------- */
-
- static getMaskTexture() {
- const d = canvas.dimensions;
- let res = 1.0;
- if ((d.width * d.height) > (16000 ** 2)) res = 0.25;
- else if ((d.width * d.height) > (8000 ** 2)) res = 0.5;
-
- // Create the mask elements
- const tex = PIXI.RenderTexture.create({
- width: canvas.dimensions.width,
- height: canvas.dimensions.height,
- resolution: res,
- });
- return tex;
- }
-
- /**
- * Gets and sets various layer wide properties
- * Some properties have different values depending on if user is a GM or player
- */
-
- getSetting(name) {
- let setting = canvas.scene.getFlag(this.layername, name);
- if (setting === undefined) setting = this.getUserSetting(name);
- if (setting === undefined) setting = this.DEFAULTS[name];
- return setting;
- }
-
- async setSetting(name, value) {
- const v = await canvas.scene.setFlag(this.layername, name, value);
- return v;
- }
-
- getUserSetting(name) {
- let setting = game.user.getFlag(this.layername, name);
- if (setting === undefined) setting = this.DEFAULTS[name];
- return setting;
- }
-
- async setUserSetting(name, value) {
- const v = await game.user.setFlag(this.layername, name, value);
- return v;
- }
-
- /**
- * Renders the history stack to the mask
- * @param history {Array} A collection of history events
- * @param start {Number} The position in the history stack to begin rendering from
- * @param start {Number} The position in the history stack to stop rendering
- */
- renderStack(
- history = canvas.scene.getFlag(this.layername, 'history'),
- start = this.pointer,
- stop = canvas.scene.getFlag(this.layername, 'history.pointer'),
- ) {
- // If history is blank, do nothing
- if (history === undefined) return;
- // If history is zero, reset scene fog
- if (history.events.length === 0) this.resetMask(false);
- if (start === undefined) start = 0;
- if (stop === undefined) stop = history.events.length;
- // If pointer preceeds the stop, reset and start from 0
- if (stop <= this.pointer) {
- this.resetMask(false);
- start = 0;
- }
-
- simplefogLog(`Rendering from: ${start} to ${stop}`);
- // Render all ops starting from pointer
- for (let i = start; i < stop; i += 1) {
- for (let j = 0; j < history.events[i].length; j += 1) {
- this.renderBrush(history.events[i][j], false);
- }
- }
- // Update local pointer
- this.pointer = stop;
- // Prevent calling update when no lights loaded
- if (!canvas.sight?.light?.los?.geometry) return;
- // Update sight layer
- canvas.sight.update();
- }
-
- /**
- * Add buffered history stack to scene flag and clear buffer
- */
- async commitHistory() {
- // Do nothing if no history to be committed, otherwise get history
- if (this.historyBuffer.length === 0) return;
- if (this.lock) return;
- this.lock = true;
- let history = canvas.scene.getFlag(this.layername, 'history');
- // If history storage doesnt exist, create it
- if (!history) {
- history = {
- events: [],
- pointer: 0,
- };
- }
- // If pointer is less than history length (f.x. user undo), truncate history
- history.events = history.events.slice(0, history.pointer);
- // Push the new history buffer to the scene
- history.events.push(this.historyBuffer);
- history.pointer = history.events.length;
- await canvas.scene.unsetFlag(this.layername, 'history');
- await this.setSetting('history', history);
- simplefogLog(`Pushed ${this.historyBuffer.length} updates.`);
- // Clear the history buffer
- this.historyBuffer = [];
- this.lock = false;
- }
-
- /**
- * Resets the mask of the layer
- * @param save {Boolean} If true, also resets the layer history
- */
- async resetMask(save = true) {
- // Fill fog layer with solid
- this.setFill();
- // If save, also unset history and reset pointer
- if (save) {
- await canvas.scene.unsetFlag(this.layername, 'history');
- await canvas.scene.setFlag(this.layername, 'history', { events: [], pointer: 0 });
- this.pointer = 0;
- }
- }
-
- /**
- * Resets the mask of the layer
- * @param save {Boolean} If true, also resets the layer history
- */
- async blankMask() {
- await this.resetMask();
- this.renderBrush({
- shape: this.BRUSH_TYPES.BOX,
- x: 0,
- y: 0,
- width: this.width,
- height: this.height,
- fill: 0x000000,
- });
- this.commitHistory();
- }
-
- /**
- * Steps the history buffer back X steps and redraws
- * @param steps {Integer} Number of steps to undo, default 1
- */
- async undo(steps = 1) {
- simplefogLog(`Undoing ${steps} steps.`);
- // Grab existing history
- // Todo: this could probably just grab and set the pointer for a slight performance improvement
- let history = canvas.scene.getFlag(this.layername, 'history');
- if (!history) {
- history = {
- events: [],
- pointer: 0,
- };
- }
- let newpointer = this.pointer - steps;
- if (newpointer < 0) newpointer = 0;
- // Set new pointer & update history
- history.pointer = newpointer;
- await canvas.scene.unsetFlag(this.layername, 'history');
- await canvas.scene.setFlag(this.layername, 'history', history);
- }
-
- /* -------------------------------------------- */
- /* Shapes, sprites and PIXI objs */
- /* -------------------------------------------- */
-
- /**
- * Creates a PIXI graphic using the given brush parameters
- * @param data {Object} A collection of brush parameters
- * @returns {Object} PIXI.Graphics() instance
- *
- * @example
- * const myBrush = this.brush({
- * shape: "ellipse",
- * x: 0,
- * y: 0,
- * fill: 0x000000,
- * width: 50,
- * height: 50,
- * alpha: 1,
- * visible: true
- * });
- */
- brush(data) {
- // Get new graphic & begin filling
- const alpha = (typeof data.alpha === 'undefined') ? 1 : data.alpha;
- const visible = (typeof data.visible === 'undefined') ? true : data.visible;
- const brush = new PIXI.Graphics();
- brush.beginFill(data.fill);
- // Draw the shape depending on type of brush
- switch (data.shape) {
- case this.BRUSH_TYPES.ELLIPSE:
- brush.drawEllipse(0, 0, data.width, data.height);
- break;
- case this.BRUSH_TYPES.BOX:
- brush.drawRect(0, 0, data.width, data.height);
- break;
- case this.BRUSH_TYPES.ROUNDED_RECT:
- brush.drawRoundedRect(0, 0, data.width, data.height, 10);
- break;
- case this.BRUSH_TYPES.POLYGON:
- brush.drawPolygon(data.vertices);
- break;
- default:
- break;
- }
- // End fill and set the basic props
- brush.endFill();
- brush.alpha = alpha;
- brush.visible = visible;
- brush.x = data.x;
- brush.y = data.y;
- brush.zIndex = data.zIndex;
- return brush;
- }
-
- /**
- * Gets a brush using the given parameters, renders it to mask and saves the event to history
- * @param data {Object} A collection of brush parameters
- * @param save {Boolean} If true, will add the operation to the history buffer
- */
- renderBrush(data, save = true) {
- const brush = this.brush(data);
- this.composite(brush);
- brush.destroy();
- if (save) this.historyBuffer.push(data);
- }
-
- /**
- * Renders the given brush to the layer mask
- * @param data {Object} PIXI Object to be used as brush
- */
- composite(brush) {
- canvas.app.renderer.render(brush, this.maskTexture, false, null, false);
- }
-
- /**
- * Returns a blank PIXI Sprite of canvas dimensions
- */
- static getCanvasSprite() {
- const sprite = new PIXI.Sprite(PIXI.Texture.WHITE);
- const d = canvas.dimensions;
- sprite.width = d.width;
- sprite.height = d.height;
- sprite.x = 0;
- sprite.y = 0;
- sprite.zIndex = 0;
- return sprite;
- }
-
- /**
- * Fills the mask layer with solid white
- */
- setFill() {
- const fill = new PIXI.Graphics();
- fill.beginFill(0xFFFFFF);
- fill.drawRect(0, 0, canvas.dimensions.width, canvas.dimensions.height);
- fill.endFill();
- this.composite(fill);
- fill.destroy();
- }
-
- /**
- * Toggles visibility of primary layer
- */
- toggle() {
- const v = this.getSetting('visible');
- this.visible = !v;
- this.setSetting('visible', !v);
- }
-
- /**
- * Actions upon layer becoming active
- */
- activate() {
- super.activate();
- this.interactive = true;
- }
-
- /**
- * Actions upon layer becoming inactive
- */
- deactivate() {
- super.deactivate();
- this.interactive = false;
- }
-
- async draw() {
- super.draw();
- }
-}
diff --git a/classes/SimplefogConfig.js b/classes/SimplefogConfig.js
deleted file mode 100644
index d9e2992..0000000
--- a/classes/SimplefogConfig.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { webToHex, hexToWeb } from '../js/helpers.js';
-
-export default class SimplefogConfig extends FormApplication {
- static get defaultOptions() {
- return mergeObject(super.defaultOptions, {
- classes: ['form'],
- closeOnSubmit: false,
- submitOnChange: true,
- submitOnClose: true,
- popOut: true,
- editable: game.user.isGM,
- width: 500,
- template: 'modules/simplefog/templates/scene-config.html',
- id: 'simplefog-scene-config',
- title: game.i18n.localize('Simplefog Options'),
- });
- }
-
- /* -------------------------------------------- */
-
- /**
- * Obtain module metadata and merge it with game settings which track current module visibility
- * @return {Object} The data provided to the template when rendering the form
- */
- getData() {
- // Return data to the template
- return {
- gmAlpha: Math.round(canvas.simplefog.getSetting('gmAlpha') * 100),
- gmTint: hexToWeb(canvas.simplefog.getSetting('gmTint')),
- playerAlpha: Math.round(canvas.simplefog.getSetting('playerAlpha') * 100),
- playerTint: hexToWeb(canvas.simplefog.getSetting('playerTint')),
- transition: canvas.simplefog.getSetting('transition'),
- transitionSpeed: canvas.simplefog.getSetting('transitionSpeed'),
- blurRadius: canvas.simplefog.getSetting('blurRadius'),
- blurQuality: canvas.simplefog.getSetting('blurQuality'),
- autoVisibility: canvas.simplefog.getSetting('autoVisibility'),
- autoVisGM: canvas.simplefog.getSetting('autoVisGM'),
- vThreshold: Math.round(canvas.simplefog.getSetting('vThreshold') * 100),
- };
- }
-
- /* -------------------------------------------- */
- /* Event Listeners and Handlers */
- /* -------------------------------------------- */
-
- /**
- * This method is called upon form submission after form data is validated
- * @param event {Event} The initial triggering submission event
- * @param formData {Object} The object of validated form data with which to update the object
- * @private
- */
- async _updateObject(event, formData) {
- Object.entries(formData).forEach(async ([key, val]) => {
- // If setting is an opacity slider, convert from 1-100 to 0-1
- if (['gmAlpha', 'playerAlpha', 'vThreshold'].includes(key)) val /= 100;
- // If setting is a color value, convert webcolor to hex before saving
- if (['gmTint', 'playerTint'].includes(key)) val = webToHex(val);
- // Save settings to scene
- await canvas.simplefog.setSetting(key, val);
- // If saveDefaults button clicked, also save to user's defaults
- if (event.submitter?.name === 'saveDefaults') {
- canvas.simplefog.setUserSetting(key, val);
- }
- });
-
- // If save button was clicked, close app
- if (event.submitter?.name === 'submit') {
- Object.values(ui.windows).forEach((val) => {
- if (val.id === 'simplefog-scene-config') val.close();
- });
- }
-
- // Update sight layer
- canvas.sight.update();
- }
-}
diff --git a/classes/SimplefogLayer.js b/classes/SimplefogLayer.js
deleted file mode 100644
index 4104dc7..0000000
--- a/classes/SimplefogLayer.js
+++ /dev/null
@@ -1,681 +0,0 @@
-/* SimplefogLayer extends MaskLayer
- *
- * Implements tools for manipulating the MaskLayer
- */
-
-import MaskLayer from './MaskLayer.js';
-import { Layout } from '../libs/hexagons.js';
-import { hexObjsToArr, hexToPercent } from '../js/helpers.js';
-
-export default class SimplefogLayer extends MaskLayer {
- constructor() {
- super('simplefog');
- // Register event listerenrs
- this._registerMouseListeners();
- this._registerKeyboardListeners();
-
- this.DEFAULTS = Object.assign(this.DEFAULTS, {
- gmAlpha: 0.6,
- gmTint: '0x000000',
- playerAlpha: 1,
- playerTint: '0x000000',
- transition: true,
- transitionSpeed: 800,
- previewColor: '0x00FFFF',
- handlefill: '0xff6400',
- handlesize: 20,
- previewAlpha: 0.4,
- brushSize: 50,
- brushOpacity: 1,
- autoVisibility: false,
- autoVisGM: false,
- vThreshold: 1,
- });
-
- // React to canvas zoom
- Hooks.on('canvasPan', (canvas, dimensions) => {
- // Scale blur filter radius to account for zooming
- this.blur.blur = this.getSetting('blurRadius') * dimensions.scale;
- });
-
- // React to changes to current scene
- Hooks.on('updateScene', (scene, data) => this._updateScene(scene, data));
- }
-
- async init() {
- this.maskInit();
- // Preview brush objects
- this.boxPreview = this.brush({
- shape: this.BRUSH_TYPES.BOX,
- x: 0,
- y: 0,
- fill: 0xFFFFFF,
- alpha: this.DEFAULTS.previewAlpha,
- width: 100,
- height: 100,
- visible: false,
- zIndex: 10,
- });
- this.ellipsePreview = this.brush({
- shape: this.BRUSH_TYPES.ELLIPSE,
- x: 0,
- y: 0,
- fill: 0xFFFFFF,
- alpha: this.DEFAULTS.previewAlpha,
- width: 100,
- height: 100,
- visible: false,
- zIndex: 10,
- });
- this.polygonPreview = this.brush({
- shape: this.BRUSH_TYPES.POLYGON,
- x: 0,
- y: 0,
- vertices: [],
- fill: 0xFFFFFF,
- alpha: this.DEFAULTS.previewAlpha,
- visible: false,
- zIndex: 10,
- });
- this.polygonHandle = this.brush({
- shape: this.BRUSH_TYPES.BOX,
- x: 0,
- y: 0,
- fill: this.DEFAULTS.handlefill,
- width: this.DEFAULTS.handlesize * 2,
- height: this.DEFAULTS.handlesize * 2,
- alpha: this.DEFAULTS.previewAlpha,
- visible: false,
- zIndex: 15,
- });
- // Add preview brushes to layer
- this.addChild(this.boxPreview);
- this.addChild(this.ellipsePreview);
- this.addChild(this.polygonPreview);
- this.addChild(this.polygonHandle);
-
- // Set default flags if they dont exist already
- Object.keys(this.DEFAULTS).forEach((key) => {
- if (!game.user.isGM) return;
- // Check for existing scene specific setting
- if (this.getSetting(key) !== undefined) return;
- // Check for custom default
- const def = this.getUserSetting(key);
- // If user has custom default, set it for scene
- if (def !== undefined) this.setSetting(key, def);
- // Otherwise fall back to module default
- else this.setSetting(key, this.DEFAULTS[key]);
- });
- }
-
- /* -------------------------------------------- */
- /* Getters and setters for layer props */
- /* -------------------------------------------- */
-
- // Tint & Alpha have special cases because they can differ between GM & Players
- // And alpha can be animated for transition effects
- getTint() {
- let tint;
- if (game.user.isGM) tint = this.getSetting('gmTint');
- else tint = this.getSetting('playerTint');
- if (!tint) {
- if (game.user.isGM) tint = this.gmTintDefault;
- else tint = this.playerTintDefault;
- }
- return tint;
- }
-
- setTint(tint) {
- this.layer.tint = tint;
- }
-
- getAlpha() {
- let alpha;
- if (game.user.isGM) alpha = this.getSetting('gmAlpha');
- else alpha = this.getSetting('playerAlpha');
- if (!alpha) {
- if (game.user.isGM) alpha = this.DEFAULTS.gmAlpha;
- else alpha = this.DEFAULTS.playerAlpha;
- }
- return alpha;
- }
-
- /**
- * Sets the scene's alpha for the primary layer.
- * @param alpha {Number} 0-1 opacity representation
- * @param skip {Boolean} Optional override to skip using animated transition
- */
- async setAlpha(alpha, skip = false) {
- // If skip is false, do not transition and just set alpha immediately
- if (skip || !this.getSetting('transition')) this.layer.alpha = alpha;
- // Loop until transition is complete
- else {
- const start = this.layer.alpha;
- const dist = start - alpha;
- const fps = 60;
- const speed = this.getSetting('transitionSpeed');
- const frame = 1000 / fps;
- const rate = dist / (fps * speed / 1000);
- let f = fps * speed / 1000;
- while (f > 0) {
- // Delay 1 frame before updating again
- // eslint-disable-next-line no-await-in-loop
- await new Promise((resolve) => setTimeout(resolve, frame));
- this.layer.alpha -= rate;
- f -= 1;
- }
- // Reset target alpha in case loop overshot a bit
- this.layer.alpha = alpha;
- }
- }
-
- /* -------------------------------------------- */
- /* Event Listeners and Handlers */
- /* -------------------------------------------- */
-
- /**
- * React to updates of canvas.scene flags
- */
- _updateScene(scene, data) {
- // Check if update applies to current viewed scene
- if (!scene._view) return;
- // React to visibility change
- if (hasProperty(data, `flags.${this.layername}.visible`)) {
- canvas[this.layername].visible = data.flags[this.layername].visible;
- }
- // React to composite history change
- if (hasProperty(data, `flags.${this.layername}.blurRadius`)) {
- canvas[this.layername].blur.blur = this.getSetting('blurRadius');
- }
- // React to composite history change
- if (hasProperty(data, `flags.${this.layername}.blurQuality`)) {
- canvas[this.layername].blur.quality = this.getSetting('blurQuality');
- }
- // React to composite history change
- if (hasProperty(data, `flags.${this.layername}.history`)) {
- canvas[this.layername].renderStack(data.flags[this.layername].history);
- canvas.sight.update();
- }
- // React to autoVisibility setting changes
- if (
- hasProperty(data, `flags.${this.layername}.autoVisibility`)
- || hasProperty(data, `flags.${this.layername}.vThreshold`)
- ) {
- canvas.sight.update();
- }
- // React to alpha/tint changes
- if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.playerAlpha`)) {
- canvas[this.layername].setAlpha(data.flags[this.layername].playerAlpha);
- }
- if (game.user.isGM && hasProperty(data, `flags.${this.layername}.gmAlpha`)) {
- canvas[this.layername].setAlpha(data.flags[this.layername].gmAlpha);
- }
- if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.playerTint`)) canvas[this.layername].setTint(data.flags[this.layername].playerTint);
- if (game.user.isGM && hasProperty(data, `flags.${this.layername}.gmTint`)) canvas[this.layername].setTint(data.flags[this.layername].gmTint);
- }
-
- /**
- * Adds the mouse listeners to the layer
- */
- _registerMouseListeners() {
- this.addListener('pointerdown', this._pointerDown);
- this.addListener('pointerup', this._pointerUp);
- this.addListener('pointermove', this._pointerMove);
- this.dragging = false;
- this.brushing = false;
- }
-
- /**
- * Adds the keyboard listeners to the layer
- */
- _registerKeyboardListeners() {
- $(document).keydown((event) => {
- // Only react if simplefog layer is active
- if (ui.controls.activeControl !== this.layername) return;
- // Don't react if game body isn't target
- if (!event.target.tagName === 'BODY') return;
- if (event.which === 219 && this.activeTool === 'brush') {
- const s = this.getUserSetting('brushSize');
- this.setBrushSize(s * 0.8);
- }
- if (event.which === 221 && this.activeTool === 'brush') {
- const s = this.getUserSetting('brushSize');
- this.setBrushSize(s * 1.25);
- }
- // React to ctrl+z
- if (event.which === 90 && event.ctrlKey) {
- event.stopPropagation();
- this.undo();
- }
- });
- }
-
- /**
- * Sets the active tool & shows preview for brush & grid tools
- */
- setActiveTool(tool) {
- this.clearActiveTool();
- this.activeTool = tool;
- this.setPreviewTint();
- if (tool === 'brush') {
- this.ellipsePreview.visible = true;
- $('#simplefog-brush-controls #brush-size-container').show();
- }
- else {
- $('#simplefog-brush-controls #brush-size-container').hide();
- }
- if (tool === 'grid') {
- if (canvas.scene.data.gridType === 1) {
- this.boxPreview.width = canvas.scene.data.grid;
- this.boxPreview.height = canvas.scene.data.grid;
- this.boxPreview.visible = true;
- }
- else if ([2, 3, 4, 5].includes(canvas.scene.data.gridType)) {
- this._initGrid();
- this.polygonPreview.visible = true;
- }
- }
- }
-
- setPreviewTint() {
- const vt = this.getSetting('vThreshold');
- const bo = hexToPercent(this.getUserSetting('brushOpacity')) / 100;
- let tint = 0xFF0000;
- if (bo < vt) tint = 0x00FF00;
- this.ellipsePreview.tint = tint;
- this.boxPreview.tint = tint;
- this.polygonPreview.tint = tint;
- }
-
- /**
- * Sets the active tool & shows preview for brush & grid tools
- * @param {Number} Size in pixels
- */
- async setBrushSize(s) {
- await this.setUserSetting('brushSize', s);
- const p = { x: this.ellipsePreview.x, y: this.ellipsePreview.y };
- this._pointerMoveBrush(p);
- }
-
- /**
- * Aborts any active drawing tools
- */
- clearActiveTool() {
- // Box preview
- this.boxPreview.visible = false;
- // Ellipse Preview
- this.ellipsePreview.visible = false;
- // Shape preview
- this.polygonPreview.clear();
- this.polygonPreview.visible = false;
- this.polygonHandle.visible = false;
- this.polygon = [];
- // Cancel op flag
- this.op = false;
- // Clear history buffer
- this.historyBuffer = [];
- }
-
- /**
- * Mouse handlers for canvas layer interactions
- */
- _pointerDown(e) {
- // Don't allow new action if history push still in progress
- if (this.historyBuffer.length > 0) return;
- // On left mouse button
- if (e.data.button === 0) {
- const p = e.data.getLocalPosition(canvas.app.stage);
- // Round positions to nearest pixel
- p.x = Math.round(p.x);
- p.y = Math.round(p.y);
- this.op = true;
- // Check active tool
- switch (this.activeTool) {
- case 'brush': this._pointerDownBrush(p, e);
- break;
- case 'grid': this._pointerDownGrid(p, e);
- break;
- case 'box': this._pointerDownBox(p, e);
- break;
- case 'ellipse': this._pointerDownEllipse(p, e);
- break;
- case 'polygon': this._pointerDownPolygon(p, e);
- break;
- default: // Do nothing
- break;
- }
- // Call _pointermove so single click will still draw brush if mouse does not move
- this._pointerMove(e);
- }
- // On right button, cancel action
- else if (e.data.button === 2) {
- // Todo: Not sure why this doesnt trigger when drawing ellipse & box
- if (['polygon', 'box', 'ellipse'].includes(this.activeTool)) {
- this.clearActiveTool();
- }
- }
- }
-
- _pointerMove(e) {
- // Get mouse position translated to canvas coords
- const p = e.data.getLocalPosition(canvas.app.stage);
- // Round positions to nearest pixel
- p.x = Math.round(p.x);
- p.y = Math.round(p.y);
- switch (this.activeTool) {
- case 'brush': this._pointerMoveBrush(p, e);
- break;
- case 'box': this._pointerMoveBox(p, e);
- break;
- case 'grid': this._pointerMoveGrid(p, e);
- break;
- case 'ellipse': this._pointerMoveEllipse(p, e);
- break;
- default:
- break;
- }
- }
-
- _pointerUp(e) {
- // Only react to left mouse button
- if (e.data.button === 0) {
- // Translate click to canvas position
- const p = e.data.getLocalPosition(canvas.app.stage);
- // Round positions to nearest pixel
- p.x = Math.round(p.x);
- p.y = Math.round(p.y);
- switch (this.op) {
- case 'box': this._pointerUpBox(p, e);
- break;
- case 'ellipse': this._pointerUpEllipse(p, e);
- break;
- default: // Do nothing
- break;
- }
- // Reset operation
- this.op = false;
- // Push the history buffer
- this.commitHistory();
- }
- }
-
- /**
- * Brush Tool
- */
- _pointerDownBrush() {
- this.op = true;
- }
-
- _pointerMoveBrush(p) {
- const size = this.getUserSetting('brushSize');
- this.ellipsePreview.width = size * 2;
- this.ellipsePreview.height = size * 2;
- this.ellipsePreview.x = p.x;
- this.ellipsePreview.y = p.y;
- // If drag operation has started
- if (this.op) {
- // Send brush movement events to renderbrush to be drawn and added to history stack
- this.renderBrush({
- shape: this.BRUSH_TYPES.ELLIPSE,
- x: p.x,
- y: p.y,
- fill: this.getUserSetting('brushOpacity'),
- width: this.getUserSetting('brushSize'),
- height: this.getUserSetting('brushSize'),
- });
- }
- }
-
- /*
- * Box Tool
- */
- _pointerDownBox(p) {
- // Set active drag operation
- this.op = 'box';
- // Set drag start coords
- this.dragStart.x = p.x;
- this.dragStart.y = p.y;
- // Reveal the preview shape
- this.boxPreview.visible = true;
- this.boxPreview.x = p.x;
- this.boxPreview.y = p.y;
- }
-
- _pointerMoveBox(p, e) {
- // If drag operation has started
- if (this.op) {
- // update the preview shape
- const d = this._getDragBounds(p, e);
- this.boxPreview.width = d.w;
- this.boxPreview.height = d.h;
- }
- }
-
- _pointerUpBox(p, e) {
- // update the preview shape
- const d = this._getDragBounds(p, e);
- this.renderBrush({
- shape: this.BRUSH_TYPES.BOX,
- x: this.dragStart.x,
- y: this.dragStart.y,
- width: d.w,
- height: d.h,
- fill: this.getUserSetting('brushOpacity'),
- });
- this.boxPreview.visible = false;
- }
-
- /*
- * Ellipse Tool
- */
- _pointerDownEllipse(p) {
- // Set active drag operation
- this.op = 'ellipse';
- // Set drag start coords
- this.dragStart.x = p.x;
- this.dragStart.y = p.y;
- // Reveal the preview shape
- this.ellipsePreview.x = p.x;
- this.ellipsePreview.y = p.y;
- this.ellipsePreview.visible = true;
- }
-
- _pointerMoveEllipse(p, e) {
- // If drag operation has started
- const d = this._getDragBounds(p, e);
- if (this.op) {
- // Just update the preview shape
- this.ellipsePreview.width = d.w * 2;
- this.ellipsePreview.height = d.h * 2;
- }
- }
-
- _pointerUpEllipse(p, e) {
- const d = this._getDragBounds(p, e);
- this.renderBrush({
- shape: this.BRUSH_TYPES.ELLIPSE,
- x: this.dragStart.x,
- y: this.dragStart.y,
- width: Math.abs(d.w),
- height: Math.abs(d.h),
- fill: this.getUserSetting('brushOpacity'),
- });
- this.ellipsePreview.visible = false;
- }
-
- /*
- * Polygon Tool
- */
- _pointerDownPolygon(p) {
- if (!this.polygon) this.polygon = [];
- const x = Math.floor(p.x);
- const y = Math.floor(p.y);
- // If this is not the first vertex...
- if (this.polygon.length) {
- // Check if new point is close enough to start to close the polygon
- const xo = Math.abs(this.polygon[0].x - x);
- const yo = Math.abs(this.polygon[0].y - y);
- if (xo < this.DEFAULTS.handlesize && yo < this.DEFAULTS.handlesize) {
- const verts = hexObjsToArr(this.polygon);
- // render the new shape to history
- this.renderBrush({
- shape: this.BRUSH_TYPES.POLYGON,
- x: 0,
- y: 0,
- vertices: verts,
- fill: this.getUserSetting('brushOpacity'),
- });
- // Reset the preview shape
- this.polygonPreview.clear();
- this.polygonPreview.visible = false;
- this.polygonHandle.visible = false;
- this.polygon = [];
- return;
- }
- }
- // If this is first vertex...
- else {
- // Draw shape handle
- this.polygonHandle.x = x - this.DEFAULTS.handlesize;
- this.polygonHandle.y = y - this.DEFAULTS.handlesize;
- this.polygonHandle.visible = true;
- }
- // If intermediate vertex, add it to array and redraw the preview
- this.polygon.push({ x, y });
- this.polygonPreview.clear();
- this.polygonPreview.beginFill(0xFFFFFF);
- this.polygonPreview.drawPolygon(hexObjsToArr(this.polygon));
- this.polygonPreview.endFill();
- this.polygonPreview.visible = true;
- }
-
- /**
- * Grid Tool
- */
- _pointerDownGrid() {
- // Set active drag operation
- this.op = 'grid';
- this._initGrid();
- }
-
- _pointerMoveGrid(p) {
- const { grid, gridType } = canvas.scene.data;
- // Square grid
- if (gridType === 1) {
- const gridx = Math.floor(p.x / grid);
- const gridy = Math.floor(p.y / grid);
- const x = gridx * grid;
- const y = gridy * grid;
- const coord = `${x},${y}`;
- this.boxPreview.x = x;
- this.boxPreview.y = y;
- this.boxPreview.width = grid;
- this.boxPreview.height = grid;
- if (this.op) {
- if (!this.dupes.includes(coord)) {
- // Flag cell as drawn in dupes
- this.dupes.push(coord);
- this.renderBrush({
- shape: this.BRUSH_TYPES.BOX,
- x,
- y,
- width: grid,
- height: grid,
- fill: this.getUserSetting('brushOpacity'),
- });
- }
- }
- }
- // Hex Grid
- else if ([2, 3, 4, 5].includes(gridType)) {
- // Convert pixel coord to hex coord
- const qr = this.gridLayout.pixelToHex(p).round();
- // Get current grid coord verts
- const vertices = this.gridLayout.polygonCorners({ q: qr.q, r: qr.r });
- // Convert to array of individual verts
- const vertexArray = hexObjsToArr(vertices);
- // Update the preview shape
- this.polygonPreview.clear();
- this.polygonPreview.beginFill(0xFFFFFF);
- this.polygonPreview.drawPolygon(vertexArray);
- this.polygonPreview.endFill();
- // If drag operation has started
- if (this.op) {
- const coord = `${qr.q},${qr.r}`;
- // Check if this grid cell was already drawn
- if (!this.dupes.includes(coord)) {
- // Get the vert coords for the hex
- this.renderBrush({
- shape: this.BRUSH_TYPES.POLYGON,
- vertices: vertexArray,
- x: 0,
- y: 0,
- fill: this.getUserSetting('brushOpacity'),
- });
- // Flag cell as drawn in dupes
- this.dupes.push(`${qr.q},${qr.r}`);
- }
- }
- }
- }
-
- /*
- * Returns height and width given a pointer coord and event for modifer keys
- */
- _getDragBounds(p, e) {
- let h = p.y - this.dragStart.y;
- let w = p.x - this.dragStart.x;
- if (e.data.originalEvent.shiftKey) {
- const ws = Math.sign(w);
- const hs = Math.sign(h);
- if (Math.abs(h) > Math.abs(w)) w = Math.abs(h) * ws;
- else h = Math.abs(w) * hs;
- }
- return { w, h };
- }
-
- /*
- * Checks grid type, creates a dupe detection matrix & if hex grid init a layout
- */
- _initGrid() {
- const { grid } = canvas.scene.data;
- this.dupes = [];
- switch (canvas.scene.data.gridType) {
- // Square grid
- // Pointy Hex Odd
- case 2:
- this.gridLayout = new Layout(
- Layout.pointy,
- { x: grid / 2, y: grid / 2 },
- { x: 0, y: grid / 2 },
- );
- break;
- // Pointy Hex Even
- case 3:
- this.gridLayout = new Layout(
- Layout.pointy,
- { x: grid / 2, y: grid / 2 },
- { x: Math.sqrt(3) * grid / 4, y: grid / 2 },
- );
- break;
- // Flat Hex Odd
- case 4:
- this.gridLayout = new Layout(
- Layout.flat,
- { x: grid / 2, y: grid / 2 },
- { x: grid / 2, y: 0 },
- );
- break;
- // Flat Hex Even
- case 5:
- this.gridLayout = new Layout(
- Layout.flat,
- { x: grid / 2, y: grid / 2 },
- { x: grid / 2, y: Math.sqrt(3) * grid / 4 },
- );
- break;
- default:
- break;
- }
- }
-}
diff --git a/classes/SimplefogMigrations.js b/classes/SimplefogMigrations.js
deleted file mode 100644
index 08a9d38..0000000
--- a/classes/SimplefogMigrations.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Provides for the ability to check and run migration code for changes to data
- */
-/* eslint-disable max-len */
-import { simplefogLog } from '../js/helpers.js';
-
-export default class SimplefogMigrations {
- static check() {
- if (!game.user.isGM) return;
- simplefogLog('Checking migrations');
- const ver = game.settings.get('simplefog', 'migrationVersion');
- if (ver < 1) SimplefogMigrations.migration1();
- }
-
- /*
- * Tidys up some messy data storage from early versions
- * - Converts string based shape names to integers
- * - Rounds any decimal x / y / height / width values
- * - Deletes any unnecessary visible & alpha props
- */
- static migration1() {
- simplefogLog('Performing migration #1', true);
- game.scenes.forEach(async (s) => {
- // Check if scene has simplefog history
- if (s.data.flags?.simplefog?.history?.events) {
- const { history } = s.data.flags.simplefog;
- // Loop through all events to check for old data
- for (let i = 0; i < history.events.length; i += 1) {
- for (let j = 0; j < history.events[i].length; j += 1) {
- // Update shape props to use integers instead of strings
- switch (history.events[i][j].shape) {
- case 'ellipse':
- history.events[i][j].shape = 0;
- break;
- case 'box':
- history.events[i][j].shape = 1;
- break;
- case 'shape':
- history.events[i][j].shape = 3;
- break;
- case 'polygon':
- history.events[i][j].shape = 3;
- break;
- default:
- break;
- }
- // Round decimal values
- if (history.events[i][j].x) history.events[i][j].x = Math.round(history.events[i][j].x);
- if (history.events[i][j].x) history.events[i][j].y = Math.round(history.events[i][j].y);
- if (history.events[i][j].height) history.events[i][j].height = Math.round(history.events[i][j].height);
- if (history.events[i][j].width) history.events[i][j].width = Math.round(history.events[i][j].width);
- // Remove unnecessary visible & alpha props
- if (history.events[i][j].visible) delete history.events[i][j].visible;
- if (history.events[i][j].alpha) delete history.events[i][j].alpha;
- }
- }
- await s.unsetFlag('simplefog', 'history');
- s.setFlag('simplefog', 'history', history);
- game.settings.set('simplefog', 'migrationVersion', 1);
- }
- });
- }
-}
diff --git a/css/brush-controls.css b/css/brush-controls.css
deleted file mode 100644
index de8d6e2..0000000
--- a/css/brush-controls.css
+++ /dev/null
@@ -1,26 +0,0 @@
-#simplefog-brush-controls {
- position: absolute;
- left: 120px;
- width: 180px;
- text-align: center;
-}
-
-#simplefog-brush-controls h3,
-#simplefog-brush-controls .label {
- color: #FFF;
- text-shadow: 1px 1px 0 #000;
-}
-
-#simplefog-brush-controls .label {
- position: absolute;
- top: 14px;
-}
-#simplefog-brush-controls .brush-opacity {
- position: relative;
-}
-#simplefog-brush-controls .right-label {
- right: 0;
-}
-#simplefog-brush-controls .left-label {
- left: 0;
-}
\ No newline at end of file
diff --git a/docs/simplefog-options.png b/docs/simplefog-options.png
index 04c07ff..c9fd917 100644
Binary files a/docs/simplefog-options.png and b/docs/simplefog-options.png differ
diff --git a/foundryconfig.json b/foundryconfig.json
new file mode 100644
index 0000000..b25a6c6
--- /dev/null
+++ b/foundryconfig.json
@@ -0,0 +1,6 @@
+{
+ "dataPath": "/absolute/path/to/your/FoundryVTT/Data",
+ "foundryUri": "http://localhost:30001",
+ "repository": "",
+ "rawURL": ""
+}
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..498e44c
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,686 @@
+/* eslint-disable no-useless-escape */
+/* eslint-disable @typescript-eslint/no-var-requires */
+
+/**
+ * This is important for the bundle.js
+ */
+const mainFilePath = `src/foundryvtt-arms-reach.ts`; // MOD 4535992
+
+const gulp = require(`gulp`);
+const fs = require(`fs`);
+const path = require(`path`);
+const archiver = require(`archiver`);
+const stringify = require(`json-stringify-pretty-compact`);
+
+const sourcemaps = require(`gulp-sourcemaps`);
+const buffer = require(`vinyl-buffer`);
+const source = require(`vinyl-source-stream`);
+
+const loadJson = (path) => {
+ console.log(path);
+ try {
+ const str = fs.readFileSync(path).toString();
+ return JSON.parse(str);
+ } catch {
+ throw Error(`Unable to load module.json`);
+ }
+};
+
+const typescript = require(`typescript`);
+// const createLiteral = typescript.createLiteral;
+const createLiteral = typescript.factory.createStringLiteral;
+const factory = typescript.factory;
+const isExportDeclaration = typescript.isExportDeclaration;
+const isImportDeclaration = typescript.isImportDeclaration;
+const isStringLiteral = typescript.isStringLiteral;
+const LiteralExpression = typescript.LiteralExpression;
+const Node = typescript.Node;
+const TransformationContext = typescript.TransformationContext;
+const TSTransformer = typescript.Transformer;
+const TransformerFactory = typescript.TransformerFactory;
+const visitEachChild = typescript.visitEachChild;
+const visitNode = typescript.visitNode;
+
+const less = require(`gulp-less`);
+const sass = require(`gulp-sass`)(require(`sass`));
+
+// import type {ModuleData} from `@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/packages.mjs`; // MOD 4535992
+const browserify = require(`browserify`);
+const tsify = require(`tsify`);
+
+const ts = require(`gulp-typescript`);
+const git = require(`gulp-git`);
+const jest = require(`gulp-jest`).default;
+
+const argv = require(`yargs`).argv;
+
+function getConfig() {
+ const configPath = path.resolve(process.cwd(), `foundryconfig.json`);
+ let config;
+
+ if (fs.existsSync(configPath)) {
+ config = loadJson(configPath);
+ return config;
+ } else {
+ return;
+ }
+}
+
+/* MOD 4535992
+interface Manifest {
+ root: string;
+ file: ModuleData;
+ name: string;
+}
+*/
+const getManifest = () => {
+ const json = {
+ root: ``,
+ // @ts-ignore
+ file: {},
+ name: ``,
+ };
+
+ if (fs.existsSync(`src`)) {
+ json.root = `src`;
+ } else {
+ json.root = `dist`;
+ }
+
+ const modulePath = path.join(json.root, `module.json`);
+ const systemPath = path.join(json.root, `system.json`);
+
+ if (fs.existsSync(modulePath)) {
+ json.file = loadJson(modulePath);
+ json.name = `module.json`;
+ } else if (fs.existsSync(systemPath)) {
+ json.file = loadJson(systemPath);
+ json.name = `system.json`;
+ } else {
+ return null;
+ }
+
+ // If we can pull our version from our package - saves us having to maintain the number in different places
+ if (process.env.npm_package_version) {
+ json.file[`version`] = process.env.npm_package_version;
+ }
+ return json;
+};
+
+const createTransformer = () => {
+ /**
+ * @param {typescript.Node} node
+ */
+ const shouldMutateModuleSpecifier = (node) => {
+ if (!isImportDeclaration(node) && !isExportDeclaration(node)) return false;
+ if (node.moduleSpecifier === undefined) return false;
+ if (!isStringLiteral(node.moduleSpecifier)) return false;
+ if (!node.moduleSpecifier.text.startsWith(`./`) && !node.moduleSpecifier.text.startsWith(`../`)) return false;
+
+ return path.extname(node.moduleSpecifier.text) === ``;
+ };
+
+ return (context) => {
+ return (node) => {
+ function visitor(node) {
+ if (shouldMutateModuleSpecifier(node)) {
+ if (isImportDeclaration(node)) {
+ const newModuleSpecifier = createLiteral(`${node.moduleSpecifier.text}.js`);
+ return factory.updateImportDeclaration(
+ node,
+ node.decorators,
+ node.modifiers,
+ node.importClause,
+ newModuleSpecifier,
+ undefined
+ );
+ } else if (isExportDeclaration(node)) {
+ const newModuleSpecifier = createLiteral(`${node.moduleSpecifier.text}.js`);
+ return factory.updateExportDeclaration(
+ node,
+ node.decorators,
+ node.modifiers,
+ false,
+ node.exportClause,
+ newModuleSpecifier,
+ undefined
+ );
+ }
+ }
+ console.log(`22`);
+ return visitEachChild(node, visitor, context);
+ }
+ console.log(`23`);
+ return visitNode(node, visitor);
+ };
+ };
+};
+
+const tsConfig = ts.createProject(`tsconfig.json`, {
+ getCustomTransformers: (_program) => ({
+ after: [createTransformer()],
+ }),
+});
+
+/********************/
+/* BUILD */
+/********************/
+
+/**
+ * Build TypeScript
+ */
+function buildTS() {
+ return (
+ gulp
+ .src(`src/**/*.ts`)
+ .pipe(tsConfig())
+
+ // // eslint() attaches the lint output to the `eslint` property
+ // // of the file object so it can be used by other modules.
+ // .pipe(eslint())
+ // // eslint.format() outputs the lint results to the console.
+ // // Alternatively use eslint.formatEach() (see Docs).
+ // .pipe(eslint.format())
+ // // To have the process exit with an error code (1) on
+ // // lint error, return the stream and pipe to failAfterError last.
+ // .pipe(eslint.failAfterError())
+
+ .pipe(gulp.dest(`dist`))
+ );
+}
+
+// function buildTS() {
+// const debug = process.env.npm_lifecycle_event !== `package`;
+// const res = tsConfig.src()
+// .pipe(sourcemaps.init())
+// .pipe(tsConfig());
+
+// return res.js
+// .pipe(sourcemaps.write(``, { debug: debug, includeContent: true, sourceRoot: `./ts/src` }))
+// .pipe(gulp.dest(`dist`));
+// }
+
+/**
+ * Build JavaScript
+ */
+function buildJS() {
+ return (
+ gulp
+ .src(`src/**/*.js`)
+
+ // // eslint() attaches the lint output to the `eslint` property
+ // // of the file object so it can be used by other modules.
+ // .pipe(eslint())
+ // // eslint.format() outputs the lint results to the console.
+ // // Alternatively use eslint.formatEach() (see Docs).
+ // .pipe(eslint.format())
+ // // To have the process exit with an error code (1) on
+ // // lint error, return the stream and pipe to failAfterError last.
+ // .pipe(eslint.failAfterError())
+
+ .pipe(gulp.dest(`dist`))
+ );
+}
+
+/**
+ * Build Module JavaScript
+ */
+function buildMJS() {
+ return (
+ gulp
+ .src(`src/**/*.mjs`)
+
+ // // eslint() attaches the lint output to the `eslint` property
+ // // of the file object so it can be used by other modules.
+ // .pipe(eslint())
+ // // eslint.format() outputs the lint results to the console.
+ // // Alternatively use eslint.formatEach() (see Docs).
+ // .pipe(eslint.format())
+ // // To have the process exit with an error code (1) on
+ // // lint error, return the stream and pipe to failAfterError last.
+ // .pipe(eslint.failAfterError())
+
+ .pipe(gulp.dest(`dist`))
+ );
+}
+
+/**
+ * Build Css
+ */
+function buildCSS() {
+ return gulp.src(`src/**/*.css`).pipe(gulp.dest(`dist`));
+}
+
+/**
+ * Build Less
+ */
+function buildLess() {
+ return gulp.src(`src/**/*.less`).pipe(less()).pipe(gulp.dest(`dist`));
+}
+
+/**
+ * Build SASS
+ */
+function buildSASS() {
+ return gulp.src(`src/**/*.scss`).pipe(sass().on(`error`, sass.logError)).pipe(gulp.dest(`dist`));
+}
+
+const bundleModule = async () => {
+ const debug = argv.dbg || argv.debug;
+ const bsfy = browserify(path.join(__dirname, mainFilePath), { debug: debug });
+ return bsfy
+ .on(`error`, console.error)
+ .plugin(tsify)
+ .bundle()
+ .pipe(source(path.join(`dist`, `bundle.js`)))
+ .pipe(buffer())
+ .pipe(sourcemaps.init({ loadMaps: true }))
+ .pipe(sourcemaps.write(`./`))
+ .pipe(gulp.dest(`./`));
+
+ // await Promise.resolve(`bundleModule done`);
+};
+
+const copyFiles = async () => {
+ const statics = [
+ `lang`,
+ `languages`,
+ `fonts`,
+ `assets`,
+ `icons`,
+ `templates`,
+ `packs`,
+ `module.json`,
+ `system.json`,
+ `template.json`,
+ ];
+
+ const recursiveFileSearch = (dir, callback) => {
+ const err = callback.err;
+ const res = callback.res;
+ let results = [];
+ fs.readdir(dir, (err, list) => {
+ if (err) return callback(err, results);
+
+ let pending = list.length;
+ if (!pending) return callback(null, results);
+
+ for (let file of list) {
+ file = path.resolve(dir, file);
+ fs.stat(file, (err, stat) => {
+ if (stat && stat.isDirectory()) {
+ recursiveFileSearch(file, (err, res) => {
+ results = results.concat(res);
+ if (!--pending) callback(null, results);
+ });
+ } else {
+ results.push(file);
+ if (!--pending) callback(null, results);
+ }
+ });
+ }
+ });
+ };
+ console.log(`files:` + statics);
+ try {
+ for (const entity of statics) {
+ const p = path.join(`src`, entity);
+ /* MOD 4535992
+ let p:string|null = null;
+ if (entity.endsWith(`module.json`) || entity.endsWith(`templates`) || entity.endsWith(`lang`)) {
+ p = path.join(`src`, entity);
+ } else {
+ p = path.join(`assets`, entity);
+ }
+ */
+ if (fs.existsSync(p)) {
+ if (fs.lstatSync(p).isDirectory())
+ recursiveFileSearch(p, (err, res) => {
+ if (err) throw err;
+
+ for (const file of res) {
+ const newFile = path.join(
+ `dist`,
+ path.relative(process.cwd(), file.replace(/src[\/\\]/g, ``))
+ );
+ console.log(`Copying file: ` + newFile);
+ const folder = path.parse(newFile).dir;
+ if (!fs.existsSync(folder)) {
+ fs.mkdirSync(folder, { recursive: true });
+ }
+ fs.copyFileSync(file, newFile);
+ }
+ });
+ else {
+ console.log(`Copying file: ` + p + ` to ` + path.join(`dist`, entity));
+ fs.copyFileSync(p, path.join(`dist`, entity));
+ }
+ }
+ }
+ return Promise.resolve();
+ } catch (err) {
+ await Promise.reject(err);
+ }
+};
+
+const cleanDist = async () => {
+ if (argv.dbg || argv.debug) {
+ return;
+ }
+ console.log(`Cleaning dist file clutter`);
+
+ const files = [];
+ const getFiles = async (dir) => {
+ const arr = await fs.promises.readdir(dir);
+ for (const entry of arr) {
+ const fullPath = path.join(dir, entry);
+ const stat = await fs.promises.stat(fullPath);
+ if (stat.isDirectory()) await getFiles(fullPath);
+ else files.push(fullPath);
+ }
+ };
+
+ await getFiles(path.resolve(`./dist`));
+ for (const file of files) {
+ /* MOD 4535992
+ if (file.endsWith(`bundle.js`) ||
+ file.endsWith(`.css`) ||
+ file.endsWith(`module.json`) ||
+ file.endsWith(`templates`) ||
+ file.endsWith(`lang`)||
+ file.endsWith(`.json`) ||
+ file.endsWith(`.html`)){
+ continue;
+ }
+ */
+ console.warn(`Cleaning ` + path.relative(process.cwd(), file));
+ await fs.promises.unlink(file);
+ }
+};
+
+/**
+ * Watch for changes for each build step
+ */
+const buildWatch = () => {
+ // gulp.watch(`src/**/*.ts`, { ignoreInitial: false }, gulp.series(buildTS, bundleModule));
+ gulp.watch(`src/**/*.ts`, { ignoreInitial: false }, gulp.series(buildTS));
+ gulp.watch(`src/**/*.less`, { ignoreInitial: false }, buildLess);
+ gulp.watch(`src/**/*.sass`, { ignoreInitial: false }, buildSASS);
+ gulp.watch(
+ [`src/fonts`, `src/lang`, `src/languages`, `src/templates`, `src/*.json`],
+ { ignoreInitial: false },
+ copyFiles
+ );
+};
+
+/********************/
+/* CLEAN */
+/********************/
+
+/**
+ * Remove built files from `dist` folder
+ * while ignoring source files
+ */
+const clean = async () => {
+ if (!fs.existsSync(`dist`)) {
+ fs.mkdirSync(`dist`);
+ }
+
+ const name = path.basename(path.resolve(`.`));
+ const files = [];
+
+ // If the project uses TypeScript
+ // if (fs.existsSync(path.join(`src`, mainFilePath))) { // MOD 4535992
+ files.push(
+ `lang`,
+ `languages`,
+ `fonts`,
+ `icons`,
+ `packs`,
+ `templates`,
+ `assets`,
+ `module`,
+ `index.js`,
+ `module.json`,
+ `system.json`,
+ `template.json`
+ );
+ // } // MOD 4535992
+
+ // If the project uses Less
+ /* MOD 4535992
+ // if (fs.existsSync(path.join(`src/styles/`, `${name}.less`))) {
+ // files.push(`fonts`, `${name}.css`);
+ // }
+ */
+ // Attempt to remove the files
+ try {
+ for (const filePath of files) {
+ if (fs.existsSync(path.join(`dist`, filePath))) {
+ // fs.unlinkSync(path.join(`dist`, filePath)); // MOD 4535992
+ fs.rmSync(path.join(`dist`, filePath), { recursive: true, force: true });
+ }
+ }
+ return Promise.resolve();
+ } catch (err) {
+ await Promise.reject(err);
+ }
+};
+
+const linkUserData = async () => {
+ const manifest = getManifest()?.file;
+ const moduleId = manifest?.id;
+ const config = loadJson(`foundryconfig.json`);
+
+ let destDir;
+ try {
+ if (
+ fs.existsSync(path.resolve(`.`, `dist`, `module.json`)) ||
+ fs.existsSync(path.resolve(`.`, `src`, `module.json`))
+ ) {
+ destDir = `modules`;
+ } else {
+ throw Error(`Could not find module.json or system.json`);
+ }
+
+ let linkDir;
+ if (config.dataPath) {
+ if (!fs.existsSync(path.join(config.dataPath, `Data`)))
+ throw Error(`User Data path invalid, no Data directory found`);
+
+ linkDir = path.join(config.dataPath, `Data`, destDir, moduleId);
+ } else {
+ throw Error(`No User Data path defined in foundryconfig.json`);
+ }
+
+ if (argv.clean || argv.c) {
+ console.warn(`Removing build in ${linkDir}`);
+
+ fs.unlinkSync(linkDir);
+ } else if (!fs.existsSync(linkDir)) {
+ console.log(`Copying build to ${linkDir}`);
+ fs.symlinkSync(path.resolve(`./dist`), linkDir);
+ }
+ return Promise.resolve();
+ } catch (err) {
+ await Promise.reject(err);
+ }
+};
+
+/*********************/
+/* PACKAGE */
+/*********************/
+
+/**
+ * Package build
+ */
+async function packageBuild() {
+ const manifest = getManifest();
+ if (manifest === null) {
+ console.error(`Manifest file could not be loaded.`);
+ throw Error();
+ }
+
+ return new Promise((resolve, reject) => {
+ try {
+ // Remove the package dir without doing anything else
+ if (argv.clean || argv.c) {
+ console.warn(`Removing all packaged files`);
+ fs.rmSync(`package`, { force: true, recursive: true });
+ return;
+ }
+
+ // Ensure there is a directory to hold all the packaged versions
+ // fs.existsSync(`package`);
+ if (!fs.existsSync(`package`)) {
+ fs.mkdirSync(`package`, { recursive: true });
+ }
+
+ // Initialize the zip file
+ const zipName = `module.zip`; // `${manifest.file.name}-v${manifest.file.version}.zip`; // MOD 4535992
+ const zipFile = fs.createWriteStream(path.join(`package`, zipName));
+ //@ts-ignore
+ const zip = archiver(`zip`, { zlib: { level: 9 } });
+
+ zipFile.on(`close`, () => {
+ console.log(zip.pointer() + ` total bytes`);
+ console.log(`Zip file ${zipName} has been written`);
+ return resolve(true);
+ });
+
+ zip.on(`error`, (err) => {
+ throw err;
+ });
+
+ zip.pipe(zipFile);
+
+ // Add the directory with the final code
+ // zip.directory(`dist/`, manifest.file.name);
+ const moduleJson = JSON.parse(fs.readFileSync("./src/module.json"));
+ zip.directory(`dist/`, moduleJson.id);
+ /* MOD 4535992
+ zip.file(`dist/module.json`, { name: `module.json` });
+ zip.file(`dist/bundle.js`, { name: `bundle.js` });
+ zip.glob(`dist/*.css`, {cwd:__dirname});
+ zip.directory(`dist/lang`, `lang`);
+ zip.directory(`dist/templates`, `templates`);
+ */
+ console.log(`Zip files`);
+
+ zip.finalize();
+ return resolve(`done`);
+ } catch (err) {
+ return reject(err);
+ }
+ });
+}
+
+/*********************/
+/* PACKAGE */
+/*********************/
+
+/**
+ * Update version and URLs in the manifest JSON
+ */
+const updateManifest = (cb) => {
+ const packageJson = loadJson(`package.json`);
+ const config = getConfig(),
+ manifest = getManifest(),
+ rawURL = config.rawURL,
+ repoURL = config.repository,
+ manifestRoot = manifest?.root;
+
+ if (!config) {
+ cb(Error(`foundryconfig.json not found`));
+ }
+ if (manifest === null) {
+ cb(Error(`Manifest JSON not found`));
+ return;
+ }
+ if (!rawURL || !repoURL) {
+ cb(Error(`Repository URLs not configured in foundryconfig.json`));
+ }
+ try {
+ const version = argv.update || argv.u;
+
+ /* Update version */
+
+ const versionMatch = /^(\d{1,}).(\d{1,}).(\d{1,})$/;
+ const currentVersion = manifest?.file.version;
+ let targetVersion = ``;
+
+ if (!version) {
+ cb(Error(`Missing version number`));
+ }
+
+ if (versionMatch.test(version)) {
+ targetVersion = version;
+ } else {
+ targetVersion = currentVersion.replace(versionMatch, (substring, major, minor, patch) => {
+ console.log(substring, Number(major) + 1, Number(minor) + 1, Number(patch) + 1);
+ if (version === `major`) {
+ return `${Number(major) + 1}.0.0`;
+ } else if (version === `minor`) {
+ return `${major}.${Number(minor) + 1}.0`;
+ } else if (version === `patch`) {
+ return `${major}.${minor}.${Number(patch) + 1}`;
+ } else {
+ return ``;
+ }
+ });
+ }
+
+ if (targetVersion === ``) {
+ return cb(Error(`Error: Incorrect version arguments.`));
+ }
+
+ if (targetVersion === currentVersion) {
+ return cb(Error(`Error: Target version is identical to current version.`));
+ }
+
+ console.log(`Updating version number to "${targetVersion}"`);
+
+ packageJson.version = targetVersion;
+ manifest.file.version = targetVersion;
+
+ /* Update URLs */
+
+ const result = `${repoURL}/releases/download/${manifest.file.version}/module.zip`;
+
+ manifest.file.url = repoURL;
+ manifest.file.manifest = `${rawURL}/${manifest.file.version}/${manifestRoot}/${manifest.name}`;
+ manifest.file.download = result;
+
+ const prettyProjectJson = stringify(manifest.file, {
+ maxLength: 35,
+ indent: `\t`,
+ });
+
+ fs.writeFileSync(`package.json`, JSON.stringify(packageJson, null, `\t`));
+ fs.writeFileSync(path.join(manifest.root, manifest.id), prettyProjectJson, `utf8`);
+
+ return cb();
+ } catch (err) {
+ cb(err);
+ }
+};
+const test = () => {
+ return gulp.src(`src/__tests__`).pipe(
+ jest({
+ preprocessorIgnorePatterns: [`dist/`, `node_modules/`],
+ automock: false,
+ })
+ );
+};
+
+// const execBuild = gulp.parallel(buildTS, buildLess, copyFiles); // MOD 4535992
+const execBuild = gulp.parallel(buildTS, buildJS, buildMJS, buildCSS, buildLess, buildSASS, copyFiles);
+
+exports.build = gulp.series(clean, execBuild);
+exports.bundle = gulp.series(clean, execBuild, bundleModule, cleanDist);
+exports.watch = buildWatch;
+exports.clean = clean;
+exports.link = linkUserData;
+exports.package = packageBuild;
+exports.update = updateManifest;
+exports.publish = gulp.series(clean, updateManifest, execBuild, bundleModule, cleanDist, packageBuild);
diff --git a/js/config.js b/js/config.js
deleted file mode 100644
index fb77ab9..0000000
--- a/js/config.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Global SimpleFog Configuration Options
- */
-
-export default [
- {
- name: 'migrationVersion',
- data: {
- name: 'Simplefog Migration Version',
- scope: 'world',
- config: false,
- type: Number,
- default: 0,
- },
- },
-];
diff --git a/js/controls.js b/js/controls.js
deleted file mode 100644
index ee2a731..0000000
--- a/js/controls.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import SimplefogConfig from '../classes/SimplefogConfig.js';
-import BrushControls from '../classes/BrushControls.js';
-
-/**
- * Add control buttons
- */
-Hooks.on('getSceneControlButtons', (controls) => {
- if (game.user.isGM) {
- controls.push({
- name: 'simplefog',
- title: game.i18n.localize('SIMPLEFOG.sf'),
- icon: 'fas fa-cloud',
- layer: 'SimplefogLayer',
- tools: [
- {
- name: 'simplefogtoggle',
- title: game.i18n.localize('SIMPLEFOG.onoff'),
- icon: 'fas fa-eye',
- onClick: () => {
- canvas.simplefog.toggle();
- canvas.sight.update();
- },
- active: canvas.simplefog.visible,
- toggle: true,
- },
- {
- name: 'brush',
- title: game.i18n.localize('SIMPLEFOG.brushTool'),
- icon: 'fas fa-paint-brush',
- },
- {
- name: 'grid',
- title: game.i18n.localize('SIMPLEFOG.gridTool'),
- icon: 'fas fa-border-none',
- },
- {
- name: 'polygon',
- title: game.i18n.localize('SIMPLEFOG.polygonTool'),
- icon: 'fas fa-draw-polygon',
- },
- {
- name: 'box',
- title: game.i18n.localize('SIMPLEFOG.boxTool'),
- icon: 'far fa-square',
- },
- {
- name: 'ellipse',
- title: game.i18n.localize('SIMPLEFOG.ellipseTool'),
- icon: 'far fa-circle',
- },
- // {
- // name: "image",
- // title: "Image Tool",
- // icon: "far fa-image",
- // },
- {
- name: 'sceneConfig',
- title: game.i18n.localize('SIMPLEFOG.sceneConfig'),
- icon: 'fas fa-cog',
- onClick: () => {
- new SimplefogConfig().render(true);
- },
- button: true,
- },
- {
- name: 'clearfog',
- title: game.i18n.localize('SIMPLEFOG.reset'),
- icon: 'fas fa-trash',
- onClick: () => {
- const dg = new Dialog({
- title: game.i18n.localize('SIMPLEFOG.reset'),
- content: game.i18n.localize('SIMPLEFOG.confirmReset'),
- buttons: {
- reset: {
- icon: '',
- label: 'Reset',
- callback: () => canvas.simplefog.resetMask(),
- },
- blank: {
- icon: '',
- label: 'Blank',
- callback: () => canvas.simplefog.blankMask(),
- },
- cancel: {
- icon: '',
- label: 'Cancel',
- },
- },
- default: 'reset',
- });
- dg.render(true);
- },
- button: true,
- },
- ],
- activeTool: 'brush',
- });
- }
-});
-
-/**
- * Handles adding the custom brush controls pallet
- * and switching active brush flag
- */
-Hooks.on('renderSceneControls', (controls) => {
- // Switching to layer
- if (controls.activeControl === 'simplefog') {
- // Open brush tools if not already open
- if (!$('#simplefog-brush-controls').length) new BrushControls().render(true);
- // Set active tool
- const tool = controls.controls.find((control) => control.name === 'simplefog').activeTool;
- canvas.simplefog.setActiveTool(tool);
- }
- // Switching away from layer
- else {
- // Clear active tool
- canvas.simplefog.clearActiveTool();
- // Remove brush tools if open
- const bc = $('#simplefog-brush-controls');
- if (bc) bc.remove();
- }
-});
-
-/**
- * Sets Y position of the brush controls to account for scene navigation buttons
- */
-function setBrushControlPos() {
- const bc = $('#simplefog-brush-controls');
- if (bc) {
- const h = $('#navigation').height();
- bc.css({ top: `${h + 30}px` });
- }
-}
-
-// Reset position when brush controls are rendered or sceneNavigation changes
-Hooks.on('renderBrushControls', setBrushControlPos);
-Hooks.on('renderSceneNavigation', setBrushControlPos);
diff --git a/js/helpers.js b/js/helpers.js
deleted file mode 100644
index af15e72..0000000
--- a/js/helpers.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * Converts web colors to base 16
- * @param n {Hex} Web format color, f.x. #FF0000
- * @return {Hex} Base 16 format color, f.x. 0xFF0000
- */
-export function webToHex(n) {
- return n.replace('#', '0x');
-}
-
-/**
- * Converts a base16 color into a web color
- * @param n {Hex} Base 16 Color, f.x. 0xFF0000
- * @return {Hex} Web format color, f.x. #FF0000
- */
-export function hexToWeb(n) {
- return (`${n}`).replace('0x', '#');
-}
-
-/**
- * Converts a hexadecimal color to an integer percentage
- * @param n {Hex} Base 16 Color, f.x. 0x000000
- * @return {Integer} f.x 0
- */
-export function hexToPercent(n) {
- return Math.ceil(n / 0xFFFFFF * 100);
-}
-
-/**
- * Converts an integer percent (0-100) to a hexadecimal greyscale color
- * @param n {Number} 0-100 numeric input
- * @return {Hex} Base 16 format color, f.x. 0xFFFFFF
- */
-export function percentToHex(n) {
- let c = Math.ceil(n * 2.55).toString(16);
- if (c.length === 1) c = `0${c}`;
- c = `0x${c}${c}${c}`;
- return c;
-}
-
-/**
- * Converts an object containing coordinate pair arrays into a single array of points for PIXI
- * @param hex {Object} An object containing a set of [x,y] pairs
- */
-export function hexObjsToArr(hex) {
- const a = [];
- hex.forEach((point) => {
- a.push(point.x);
- a.push(point.y);
- });
- // Append first point to end of array to complete the shape
- a.push(hex[0].x);
- a.push(hex[0].y);
- return a;
-}
-
-/**
- * Dumps a render of a given pixi container or texture to a new tab
- */
-export function pixiDump(tgt = null) {
- canvas.app.render();
- const data = canvas.app.renderer.extract.base64(tgt);
- const win = window.open();
- win.document.write(``);
-}
-
-/**
- * Prints formatted console msg if string, otherwise dumps object
- * @param data {String | Object} Output to be dumped
- * @param force {Boolean} Log output even if CONFIG.debug.simplefog = false
- */
-export function simplefogLog(data, force = false) {
- if (CONFIG.debug.simplefog || force) {
- // eslint-disable-next-line no-console
- if (typeof data === 'string') console.log(`Simplefog | ${data}`);
- // eslint-disable-next-line no-console
- else console.log(data);
- }
-}
-
-/**
- * Gets a single pixel of texture data from GPU
- * @param target {Object} PIXI Object to read from
- * @param x {Integer} X Position to read
- * @param y {Integer} Y Position to read
- */
-export function readPixel(target, x = 0, y = 0) {
- const { renderer } = canvas.app;
- let resolution;
- let renderTexture;
- let generated = false;
- if (target instanceof PIXI.RenderTexture) {
- renderTexture = target;
- }
- else {
- renderTexture = renderer.generateTexture(target);
- generated = true;
- }
- if (renderTexture) {
- resolution = renderTexture.baseTexture.resolution;
- renderer.renderTexture.bind(renderTexture);
- }
- const pixel = new Uint8Array(4);
- // read pixels to the array
- const { gl } = renderer;
- gl.readPixels(x * resolution, y * resolution, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
- if (generated) {
- renderTexture.destroy(true);
- }
- return pixel;
-}
diff --git a/js/sightLayerUpdate.js b/js/sightLayerUpdate.js
deleted file mode 100644
index b6ba136..0000000
--- a/js/sightLayerUpdate.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Monkeypatch for core canvas.sight.update() that implements autovisibility
- */
-import { readPixel } from './helpers.js';
-
-/*
- * The token's worldTransform is not updated yet when this is called
- * probably because the token will be animated, so we need to convert
- * the token's grid position to world coords since grid position updates
- * immediately
- *
- * If there is a more straight forward way to do this it would be nice!
- */
-function _getCanvasCoords(placeable) {
- const { grid } = canvas.scene.data;
- // Check if placeable is a door
- const p = (placeable.data.door) ? placeable.doorControl : placeable.data;
- return {
- x: Math.round(grid / 2 + p.x),
- y: Math.round(grid / 2 + p.y),
- };
-}
-
-/*
- * Checks mask opacity at location of placeable and sets visibility
- */
-function _setPlaceableVisibility(placeable) {
- if (placeable.observer && !game.user.isGM) return;
- const pos = _getCanvasCoords(placeable);
- const p = readPixel(canvas.simplefog.maskTexture, pos.x, pos.y);
- const pAvg = (p[0] + p[1] + p[2]) / 3;
- const v = ((pAvg / 255) < canvas.scene.getFlag('simplefog', 'vThreshold'));
- // if this is a door, we set vis on it's control object instead
- if (placeable.data.door) placeable.doorControl.visible = v;
- else placeable.visible = v;
-}
-
-/*
- * Extends canvas.sight.update() to set visibility for placeables based on simplefog
- */
-export default function sightLayerUpdate() {
- // Skip checking placeables if simplefog not visible anyway
- if (!canvas.simplefog.visible) return;
- // Skip if autoVisibility not enabled for this scene
- if (!canvas.scene.getFlag('simplefog', 'autoVisibility')) return;
- // Skip if user is GM and autoVisGM Disabled
- if (game.user.isGM && !canvas.scene.getFlag('simplefog', 'autoVisGM')) return;
- // loop through placeables
- canvas.tokens.placeables.forEach((placeable) => {
- _setPlaceableVisibility(placeable);
- });
- canvas.notes.placeables.forEach((placeable) => {
- _setPlaceableVisibility(placeable);
- });
- canvas.walls.placeables.forEach((placeable) => {
- if (placeable.data.door) {
- _setPlaceableVisibility(placeable);
- }
- });
-}
diff --git a/js/simplefog.js b/js/simplefog.js
deleted file mode 100644
index 896847a..0000000
--- a/js/simplefog.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import SimplefogLayer from '../classes/SimplefogLayer.js';
-import sightLayerUpdate from './sightLayerUpdate.js';
-import SimplefogMigrations from '../classes/SimplefogMigrations.js';
-import config from './config.js';
-import { simplefogLog } from './helpers.js';
-
-Hooks.once('init', () => {
- // eslint-disable-next-line no-console
- simplefogLog('Initializing simplefog', true);
-
- // Register global module settings
- config.forEach((cfg) => {
- game.settings.register('simplefog', cfg.name, cfg.data);
- });
-});
-
-Hooks.once('canvasInit', () => {
- // Add SimplefogLayer to canvas
- const layerct = canvas.stage.children.length;
- canvas.simplefog = canvas.stage.addChildAt(new SimplefogLayer(), layerct);
-});
-
-Hooks.on('canvasInit', () => {
- canvas.simplefog.init();
-});
-
-/*
- * Apply compatibility patches
- */
-Hooks.once('ready', () => {
- // Check if any migrations need to be performed
- SimplefogMigrations.check();
- // Monkeypatch SightLayer to check simplefog vision on updates
- if (game.data.version.startsWith('0.6')) {
- const origUpdate = canvas.sight.update;
- canvas.sight.update = function update(...args) {
- origUpdate.call(this, ...args);
- sightLayerUpdate();
- };
- canvas.sight.update();
- }
- else {
- const origUpdate = canvas.sight.refresh;
- canvas.sight.refresh = function refresh(...args) {
- origUpdate.call(this, ...args);
- sightLayerUpdate();
- };
- canvas.sight.refresh();
- }
-});
diff --git a/jsconfig.json b/jsconfig.json
index 8c97d6e..0967ef4 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,6 +1 @@
-{
- "compilerOptions": {
- "module": "commonjs",
- "target": "es2020"
- }
-}
+{}
diff --git a/jsdoc-conf.json b/jsdoc-conf.json
new file mode 100644
index 0000000..1c69a50
--- /dev/null
+++ b/jsdoc-conf.json
@@ -0,0 +1,6 @@
+{
+ "source": {
+ "includePattern": ".+\\.(m|c)?js(doc|x)?$"
+ },
+ "plugins": ["@pixi/jsdoc-template/plugins/es6-fix"]
+}
diff --git a/lang/en.json b/lang/en.json
deleted file mode 100644
index 3d75d29..0000000
--- a/lang/en.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "SIMPLEFOG.brushOpacity": "Brush Opacity",
- "SIMPLEFOG.brushSize": "Brush Size",
- "SIMPLEFOG.hide": "Hide",
- "SIMPLEFOG.reveal": "Reveal",
- "SIMPLEFOG.gmFogSettings": "GM Fog Settings",
- "SIMPLEFOG.color": "Color",
- "SIMPLEFOG.opacity": "Opacity",
- "SIMPLEFOG.playerFogSettings": "Player Fog Settings",
- "SIMPLEFOG.filterSettings": "Filter Settings",
- "SIMPLEFOG.blurRadius": "Blur Radius",
- "SIMPLEFOG.blurQuality": "Blur Quality",
- "SIMPLEFOG.blurQualityDesc": "Higher blur quality improves the appearance of the blur effect, but may cause slower performance.",
- "SIMPLEFOG.transitionSettings": "Transition Settings",
- "SIMPLEFOG.enableTransitions": "Enable Transitions",
- "SIMPLEFOG.transitionSpeed": "Transition Speed",
- "SIMPLEFOG.visibilitySettings": "Visibility Settings",
- "SIMPLEFOG.enableAutovis": "Enable Automatic Visibility",
- "SIMPLEFOG.enableForGM": "Enable for GM",
- "SIMPLEFOG.visThreshold": "Visibility Threshold",
- "SIMPLEFOG.saveAsDef": "Save current settings as default",
- "SIMPLEFOG.ok": "OK",
- "SIMPLEFOG.sf": "Simple Fog",
- "SIMPLEFOG.onoff": "Enable/Disable Simple Fog",
- "SIMPLEFOG.brushTool": "Brush Tool",
- "SIMPLEFOG.gridTool": "Grid Tool",
- "SIMPLEFOG.polygonTool": "Polygon Tool",
- "SIMPLEFOG.boxTool": "Box Tool",
- "SIMPLEFOG.ellipseTool": "Ellipse Tool",
- "SIMPLEFOG.sceneConfig": "Scene Configuration",
- "SIMPLEFOG.reset": "Reset Simple Fog",
- "SIMPLEFOG.confirmReset": "Are you sure? Fog of war will be reset.",
- "SIMPLEFOG.autoVisNotes": "When enabled, Automatic Visibility will show/hide tokens based on fog opacity level at their location based on the threshold setting. Brush color changes to green/red to indicate whether a token would be visible."
-}
diff --git a/libs/hexagons.js b/libs/hexagons.js
deleted file mode 100644
index 91cf6ad..0000000
--- a/libs/hexagons.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/* eslint-disable */
-// Generated code -- CC0 -- No Rights Reserved -- http://www.redblobgames.com/grids/hexagons/
-export class Point {
- constructor(x, y) {
- this.x = x;
- this.y = y;
- }
-}
-export class Hex {
- constructor(q, r, s) {
- this.q = q;
- this.r = r;
- this.s = s;
- if (Math.round(q + r + s) !== 0)
- throw "q + r + s must be 0";
- }
- add(b) {
- return new Hex(this.q + b.q, this.r + b.r, this.s + b.s);
- }
- subtract(b) {
- return new Hex(this.q - b.q, this.r - b.r, this.s - b.s);
- }
- scale(k) {
- return new Hex(this.q * k, this.r * k, this.s * k);
- }
- rotateLeft() {
- return new Hex(-this.s, -this.q, -this.r);
- }
- rotateRight() {
- return new Hex(-this.r, -this.s, -this.q);
- }
- static direction(direction) {
- return Hex.directions[direction];
- }
- neighbor(direction) {
- return this.add(Hex.direction(direction));
- }
- diagonalNeighbor(direction) {
- return this.add(Hex.diagonals[direction]);
- }
- len() {
- return (Math.abs(this.q) + Math.abs(this.r) + Math.abs(this.s)) / 2;
- }
- distance(b) {
- return this.subtract(b).len();
- }
- round() {
- var qi = Math.round(this.q);
- var ri = Math.round(this.r);
- var si = Math.round(this.s);
- var q_diff = Math.abs(qi - this.q);
- var r_diff = Math.abs(ri - this.r);
- var s_diff = Math.abs(si - this.s);
- if (q_diff > r_diff && q_diff > s_diff) {
- qi = -ri - si;
- }
- else if (r_diff > s_diff) {
- ri = -qi - si;
- }
- else {
- si = -qi - ri;
- }
- return new Hex(qi, ri, si);
- }
- lerp(b, t) {
- return new Hex(this.q * (1.0 - t) + b.q * t, this.r * (1.0 - t) + b.r * t, this.s * (1.0 - t) + b.s * t);
- }
- linedraw(b) {
- var N = this.distance(b);
- var a_nudge = new Hex(this.q + 1e-06, this.r + 1e-06, this.s - 2e-06);
- var b_nudge = new Hex(b.q + 1e-06, b.r + 1e-06, b.s - 2e-06);
- var results = [];
- var step = 1.0 / Math.max(N, 1);
- for (var i = 0; i <= N; i++) {
- results.push(a_nudge.lerp(b_nudge, step * i).round());
- }
- return results;
- }
-}
-Hex.directions = [new Hex(1, 0, -1), new Hex(1, -1, 0), new Hex(0, -1, 1), new Hex(-1, 0, 1), new Hex(-1, 1, 0), new Hex(0, 1, -1)];
-Hex.diagonals = [new Hex(2, -1, -1), new Hex(1, -2, 1), new Hex(-1, -1, 2), new Hex(-2, 1, 1), new Hex(-1, 2, -1), new Hex(1, 1, -2)];
-export class OffsetCoord {
- constructor(col, row) {
- this.col = col;
- this.row = row;
- }
- static qoffsetFromCube(offset, h) {
- var col = h.q;
- var row = h.r + (h.q + offset * (h.q & 1)) / 2;
- if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) {
- throw "offset must be EVEN (+1) or ODD (-1)";
- }
- return new OffsetCoord(col, row);
- }
- static qoffsetToCube(offset, h) {
- var q = h.col;
- var r = h.row - (h.col + offset * (h.col & 1)) / 2;
- var s = -q - r;
- if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) {
- throw "offset must be EVEN (+1) or ODD (-1)";
- }
- return new Hex(q, r, s);
- }
- static roffsetFromCube(offset, h) {
- var col = h.q + (h.r + offset * (h.r & 1)) / 2;
- var row = h.r;
- if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) {
- throw "offset must be EVEN (+1) or ODD (-1)";
- }
- return new OffsetCoord(col, row);
- }
- static roffsetToCube(offset, h) {
- var q = h.col - (h.row + offset * (h.row & 1)) / 2;
- var r = h.row;
- var s = -q - r;
- if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) {
- throw "offset must be EVEN (+1) or ODD (-1)";
- }
- return new Hex(q, r, s);
- }
-}
-OffsetCoord.EVEN = 1;
-OffsetCoord.ODD = -1;
-export class DoubledCoord {
- constructor(col, row) {
- this.col = col;
- this.row = row;
- }
- static qdoubledFromCube(h) {
- var col = h.q;
- var row = 2 * h.r + h.q;
- return new DoubledCoord(col, row);
- }
- qdoubledToCube() {
- var q = this.col;
- var r = (this.row - this.col) / 2;
- var s = -q - r;
- return new Hex(q, r, s);
- }
- static rdoubledFromCube(h) {
- var col = 2 * h.q + h.r;
- var row = h.r;
- return new DoubledCoord(col, row);
- }
- rdoubledToCube() {
- var q = (this.col - this.row) / 2;
- var r = this.row;
- var s = -q - r;
- return new Hex(q, r, s);
- }
-}
-export class Orientation {
- constructor(f0, f1, f2, f3, b0, b1, b2, b3, start_angle) {
- this.f0 = f0;
- this.f1 = f1;
- this.f2 = f2;
- this.f3 = f3;
- this.b0 = b0;
- this.b1 = b1;
- this.b2 = b2;
- this.b3 = b3;
- this.start_angle = start_angle;
- }
-}
-export class Layout {
- constructor(orientation, size, origin) {
- this.orientation = orientation;
- this.size = size;
- this.origin = origin;
- }
- hexToPixel(h) {
- var M = this.orientation;
- var size = this.size;
- var origin = this.origin;
- var x = (M.f0 * h.q + M.f1 * h.r) * size.x;
- var y = (M.f2 * h.q + M.f3 * h.r) * size.y;
- return new Point(x + origin.x, y + origin.y);
- }
- pixelToHex(p) {
- var M = this.orientation;
- var size = this.size;
- var origin = this.origin;
- var pt = new Point((p.x - origin.x) / size.x, (p.y - origin.y) / size.y);
- var q = M.b0 * pt.x + M.b1 * pt.y;
- var r = M.b2 * pt.x + M.b3 * pt.y;
- return new Hex(q, r, -q - r);
- }
- hexCornerOffset(corner) {
- var M = this.orientation;
- var size = this.size;
- var angle = 2.0 * Math.PI * (M.start_angle - corner) / 6.0;
- return new Point(size.x * Math.cos(angle), size.y * Math.sin(angle));
- }
- polygonCorners(h) {
- var corners = [];
- var center = this.hexToPixel(h);
- for (var i = 0; i < 6; i++) {
- var offset = this.hexCornerOffset(i);
- corners.push(new Point(center.x + offset.x, center.y + offset.y));
- }
- return corners;
- }
-}
-Layout.pointy = new Orientation(Math.sqrt(3.0), Math.sqrt(3.0) / 2.0, 0.0, 3.0 / 2.0, Math.sqrt(3.0) / 3.0, -1.0 / 3.0, 0.0, 2.0 / 3.0, 0.5);
-Layout.flat = new Orientation(3.0 / 2.0, 0.0, Math.sqrt(3.0) / 2.0, Math.sqrt(3.0), 2.0 / 3.0, 0.0, -1.0 / 3.0, Math.sqrt(3.0) / 3.0, 0.0);
\ No newline at end of file
diff --git a/module.json b/module.json
deleted file mode 100644
index 5d11fbe..0000000
--- a/module.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "simplefog",
- "title": "Simplefog - Manual Fog of War",
- "description": "Simplefog allows you to draw fog of war manually, optionally automatically hiding and revealing tokens underneath based on opacity. It provides a number of tools to quickly draw and erase fog in various shapes - brush, rectangles, ellipses, polygons or to reveal tiles you click/drag on the grid.",
- "author": "Vance Cole",
- "version": "0.1.11",
- "minimumCoreVersion": "0.6.4",
- "compatibleCoreVersion": "0.7.3",
- "esmodules": [
- "js/simplefog.js",
- "js/controls.js"
- ],
- "styles": [
- "css/brush-controls.css"
- ],
- "languages": [
- {
- "lang": "en",
- "name": "English",
- "path": "lang/en.json"
- }
- ],
- "url": "https://github.com/VanceCole/simplefog",
- "manifest": "https://raw.githubusercontent.com/VanceCole/simplefog/master/module.json",
- "readme": "https://github.com/VanceCole/simplefog/blob/master/README.md",
- "changelog": "https://github.com/VanceCole/simplefog/blob/master/changelog.md",
- "download": "https://github.com/VanceCole/simplefog/releases/download/0.1.11/simplefog.zip"
-}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 5b98e61..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,4381 +0,0 @@
-{
- "name": "simplefog",
- "version": "0.1.6",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "@babel/code-frame": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
- "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
- "dev": true,
- "requires": {
- "@babel/highlight": "^7.10.4"
- }
- },
- "@babel/generator": {
- "version": "7.11.4",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz",
- "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.11.0",
- "jsesc": "^2.5.1",
- "source-map": "^0.5.0"
- }
- },
- "@babel/helper-function-name": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
- "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
- "dev": true,
- "requires": {
- "@babel/helper-get-function-arity": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-get-function-arity": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
- "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
- "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.11.0"
- }
- },
- "@babel/helper-validator-identifier": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
- "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
- "dev": true
- },
- "@babel/highlight": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
- "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.10.4",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- },
- "dependencies": {
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- }
- }
- },
- "@babel/parser": {
- "version": "7.11.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
- "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==",
- "dev": true
- },
- "@babel/template": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
- "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/parser": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/traverse": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz",
- "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/generator": "^7.11.0",
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.11.0",
- "@babel/parser": "^7.11.0",
- "@babel/types": "^7.11.0",
- "debug": "^4.1.0",
- "globals": "^11.1.0",
- "lodash": "^4.17.19"
- },
- "dependencies": {
- "globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true
- }
- }
- },
- "@babel/types": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
- "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.10.4",
- "lodash": "^4.17.19",
- "to-fast-properties": "^2.0.0"
- }
- },
- "@types/color-name": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
- "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
- "dev": true
- },
- "@types/jquery": {
- "version": "3.5.1",
- "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.1.tgz",
- "integrity": "sha512-Tyctjh56U7eX2b9udu3wG853ASYP0uagChJcQJXLUXEU6C/JiW5qt5dl8ao01VRj1i5pgXPAf8f1mq4+FDLRQg==",
- "dev": true,
- "requires": {
- "@types/sizzle": "*"
- }
- },
- "@types/json5": {
- "version": "0.0.29",
- "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
- "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
- "dev": true
- },
- "@types/sizzle": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
- "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
- "dev": true
- },
- "@types/socket.io-client": {
- "version": "1.4.33",
- "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.33.tgz",
- "integrity": "sha512-m4LnxkljsI9fMsjwpW5QhRpMixo2BeeLpFmg0AE+sS4H1pzAd/cs/ftTiL60FLZgfFa8PFRPx5KsHu8O0bADKQ==",
- "dev": true
- },
- "@types/tinymce": {
- "version": "4.5.24",
- "resolved": "https://registry.npmjs.org/@types/tinymce/-/tinymce-4.5.24.tgz",
- "integrity": "sha512-g2aFp+/GHTD6P2ZI2tBwZGIDi+64oocoDleCHtAWLYlFOR9fjPO+pdvmGjpJG3C7XeMZvugFx2NhRBL+Jb/wbQ==",
- "dev": true,
- "requires": {
- "@types/jquery": "*"
- }
- },
- "acorn": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
- "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
- "dev": true
- },
- "acorn-jsx": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
- "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
- "dev": true
- },
- "ajv": {
- "version": "6.12.3",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
- "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "ansi-colors": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
- "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
- "dev": true
- },
- "ansi-gray": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
- "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
- "dev": true,
- "requires": {
- "ansi-wrap": "0.1.0"
- }
- },
- "ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
- "dev": true
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "ansi-wrap": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
- "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
- "dev": true
- },
- "anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
- "dev": true,
- "requires": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
- }
- },
- "append-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz",
- "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=",
- "dev": true,
- "requires": {
- "buffer-equal": "^1.0.0"
- }
- },
- "archy": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
- "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
- "dev": true
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
- "dev": true
- },
- "arr-filter": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz",
- "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=",
- "dev": true,
- "requires": {
- "make-iterator": "^1.0.0"
- }
- },
- "arr-flatten": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
- "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
- "dev": true
- },
- "arr-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz",
- "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=",
- "dev": true,
- "requires": {
- "make-iterator": "^1.0.0"
- }
- },
- "arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
- "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
- "dev": true
- },
- "array-each": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
- "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=",
- "dev": true
- },
- "array-includes": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
- "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0",
- "is-string": "^1.0.5"
- }
- },
- "array-initial": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz",
- "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=",
- "dev": true,
- "requires": {
- "array-slice": "^1.0.0",
- "is-number": "^4.0.0"
- },
- "dependencies": {
- "is-number": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
- "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
- "dev": true
- }
- }
- },
- "array-last": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz",
- "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==",
- "dev": true,
- "requires": {
- "is-number": "^4.0.0"
- },
- "dependencies": {
- "is-number": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
- "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
- "dev": true
- }
- }
- },
- "array-slice": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
- "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
- "dev": true
- },
- "array-sort": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz",
- "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==",
- "dev": true,
- "requires": {
- "default-compare": "^1.0.0",
- "get-value": "^2.0.6",
- "kind-of": "^5.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
- }
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
- },
- "array.prototype.flat": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
- "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1"
- }
- },
- "assign-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
- "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
- "dev": true
- },
- "astral-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
- "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
- "dev": true
- },
- "async-done": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz",
- "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.2",
- "process-nextick-args": "^2.0.0",
- "stream-exhaust": "^1.0.1"
- }
- },
- "async-each": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
- "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
- "dev": true
- },
- "async-settle": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz",
- "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=",
- "dev": true,
- "requires": {
- "async-done": "^1.2.2"
- }
- },
- "atob": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
- "dev": true
- },
- "babel-eslint": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
- "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "@babel/parser": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0",
- "eslint-visitor-keys": "^1.0.0",
- "resolve": "^1.12.0"
- }
- },
- "bach": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
- "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=",
- "dev": true,
- "requires": {
- "arr-filter": "^1.1.1",
- "arr-flatten": "^1.0.1",
- "arr-map": "^2.0.0",
- "array-each": "^1.0.0",
- "array-initial": "^1.0.0",
- "array-last": "^1.1.1",
- "async-done": "^1.2.2",
- "async-settle": "^1.0.0",
- "now-and-later": "^2.0.0"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
- },
- "base": {
- "version": "0.11.2",
- "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
- "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
- "dev": true,
- "requires": {
- "cache-base": "^1.0.1",
- "class-utils": "^0.3.5",
- "component-emitter": "^1.2.1",
- "define-property": "^1.0.0",
- "isobject": "^3.0.1",
- "mixin-deep": "^1.2.0",
- "pascalcase": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
- "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
- "dev": true
- },
- "bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "buffer-equal": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
- "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=",
- "dev": true
- },
- "buffer-from": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
- "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
- "dev": true
- },
- "cache-base": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
- "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
- "dev": true,
- "requires": {
- "collection-visit": "^1.0.0",
- "component-emitter": "^1.2.1",
- "get-value": "^2.0.6",
- "has-value": "^1.0.0",
- "isobject": "^3.0.1",
- "set-value": "^2.0.0",
- "to-object-path": "^0.3.0",
- "union-value": "^1.0.0",
- "unset-value": "^1.0.0"
- }
- },
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true
- },
- "camelcase": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
- "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
- "dev": true
- },
- "chalk": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
- "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "dependencies": {
- "ansi-styles": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
- "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
- "dev": true,
- "requires": {
- "@types/color-name": "^1.1.1",
- "color-convert": "^2.0.1"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true
- },
- "supports-color": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
- "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
- "dev": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
- "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
- "dev": true,
- "requires": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "fsevents": "^1.2.7",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
- },
- "dependencies": {
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- }
- }
- },
- "class-utils": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
- "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
- "dev": true,
- "requires": {
- "arr-union": "^3.1.0",
- "define-property": "^0.2.5",
- "isobject": "^3.0.0",
- "static-extend": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
- },
- "cliui": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
- "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
- "dev": true,
- "requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wrap-ansi": "^2.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- }
- }
- },
- "clone": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
- "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
- "dev": true
- },
- "clone-buffer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
- "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
- "dev": true
- },
- "clone-stats": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
- "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
- "dev": true
- },
- "cloneable-readable": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz",
- "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.1",
- "process-nextick-args": "^2.0.0",
- "readable-stream": "^2.3.5"
- }
- },
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
- },
- "collection-map": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz",
- "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=",
- "dev": true,
- "requires": {
- "arr-map": "^2.0.2",
- "for-own": "^1.0.0",
- "make-iterator": "^1.0.0"
- }
- },
- "collection-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
- "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
- "dev": true,
- "requires": {
- "map-visit": "^1.0.0",
- "object-visit": "^1.0.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
- "dev": true
- },
- "color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "dev": true
- },
- "component-emitter": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
- "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
- },
- "concat-stream": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
- "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
- "dev": true,
- "requires": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^2.2.2",
- "typedarray": "^0.0.6"
- }
- },
- "confusing-browser-globals": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz",
- "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==",
- "dev": true
- },
- "contains-path": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
- "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
- "dev": true
- },
- "convert-source-map": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
- "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.1"
- }
- },
- "copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
- "dev": true
- },
- "copy-props": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz",
- "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==",
- "dev": true,
- "requires": {
- "each-props": "^1.3.0",
- "is-plain-object": "^2.0.1"
- }
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
- "dev": true
- },
- "cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
- },
- "d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "dev": true,
- "requires": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
- }
- },
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
- },
- "decode-uri-component": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
- "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
- "dev": true
- },
- "deep-is": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
- "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
- "dev": true
- },
- "default-compare": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz",
- "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==",
- "dev": true,
- "requires": {
- "kind-of": "^5.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
- }
- },
- "default-resolution": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz",
- "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=",
- "dev": true
- },
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "dev": true,
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- },
- "dependencies": {
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "detect-file": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
- "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
- "dev": true
- },
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "duplexify": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
- "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0",
- "stream-shift": "^1.0.0"
- }
- },
- "each-props": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz",
- "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.1",
- "object.defaults": "^1.1.0"
- }
- },
- "emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
- },
- "end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
- "dev": true,
- "requires": {
- "once": "^1.4.0"
- }
- },
- "enquirer": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
- "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
- "dev": true,
- "requires": {
- "ansi-colors": "^4.1.1"
- }
- },
- "error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
- "es-abstract": {
- "version": "1.17.6",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
- "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
- "dev": true,
- "requires": {
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.1",
- "is-callable": "^1.2.0",
- "is-regex": "^1.1.0",
- "object-inspect": "^1.7.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.0",
- "string.prototype.trimend": "^1.0.1",
- "string.prototype.trimstart": "^1.0.1"
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "es5-ext": {
- "version": "0.10.53",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
- "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
- "dev": true,
- "requires": {
- "es6-iterator": "~2.0.3",
- "es6-symbol": "~3.1.3",
- "next-tick": "~1.0.0"
- }
- },
- "es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
- "dev": true,
- "requires": {
- "d": "1",
- "es5-ext": "^0.10.35",
- "es6-symbol": "^3.1.1"
- }
- },
- "es6-symbol": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
- "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
- "dev": true,
- "requires": {
- "d": "^1.0.1",
- "ext": "^1.1.2"
- }
- },
- "es6-weak-map": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
- "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
- "dev": true,
- "requires": {
- "d": "1",
- "es5-ext": "^0.10.46",
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.1"
- }
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
- },
- "eslint": {
- "version": "7.5.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz",
- "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.0.0",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "enquirer": "^2.3.5",
- "eslint-scope": "^5.1.0",
- "eslint-utils": "^2.1.0",
- "eslint-visitor-keys": "^1.3.0",
- "espree": "^7.2.0",
- "esquery": "^1.2.0",
- "esutils": "^2.0.2",
- "file-entry-cache": "^5.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash": "^4.17.19",
- "minimatch": "^3.0.4",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "progress": "^2.0.0",
- "regexpp": "^3.1.0",
- "semver": "^7.2.1",
- "strip-ansi": "^6.0.0",
- "strip-json-comments": "^3.1.0",
- "table": "^5.2.3",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
- }
- },
- "eslint-config-airbnb-base": {
- "version": "14.2.0",
- "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz",
- "integrity": "sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==",
- "dev": true,
- "requires": {
- "confusing-browser-globals": "^1.0.9",
- "object.assign": "^4.1.0",
- "object.entries": "^1.1.2"
- }
- },
- "eslint-import-resolver-node": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz",
- "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==",
- "dev": true,
- "requires": {
- "debug": "^2.6.9",
- "resolve": "^1.13.1"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "eslint-module-utils": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
- "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
- "dev": true,
- "requires": {
- "debug": "^2.6.9",
- "pkg-dir": "^2.0.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "eslint-plugin-import": {
- "version": "2.22.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz",
- "integrity": "sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg==",
- "dev": true,
- "requires": {
- "array-includes": "^3.1.1",
- "array.prototype.flat": "^1.2.3",
- "contains-path": "^0.1.0",
- "debug": "^2.6.9",
- "doctrine": "1.5.0",
- "eslint-import-resolver-node": "^0.3.3",
- "eslint-module-utils": "^2.6.0",
- "has": "^1.0.3",
- "minimatch": "^3.0.4",
- "object.values": "^1.1.1",
- "read-pkg-up": "^2.0.0",
- "resolve": "^1.17.0",
- "tsconfig-paths": "^3.9.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "doctrine": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
- "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2",
- "isarray": "^1.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "eslint-scope": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
- "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.1.0",
- "estraverse": "^4.1.1"
- }
- },
- "eslint-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
- "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^1.1.0"
- }
- },
- "eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true
- },
- "espree": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz",
- "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==",
- "dev": true,
- "requires": {
- "acorn": "^7.3.1",
- "acorn-jsx": "^5.2.0",
- "eslint-visitor-keys": "^1.3.0"
- }
- },
- "esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true
- },
- "esquery": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
- "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
- "dev": true,
- "requires": {
- "estraverse": "^5.1.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
- "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
- "dev": true
- }
- }
- },
- "esrecurse": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
- "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
- "dev": true,
- "requires": {
- "estraverse": "^4.1.0"
- }
- },
- "estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true
- },
- "esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true
- },
- "expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
- "dev": true,
- "requires": {
- "debug": "^2.3.3",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "posix-character-classes": "^0.1.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "expand-tilde": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
- "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
- "dev": true,
- "requires": {
- "homedir-polyfill": "^1.0.1"
- }
- },
- "ext": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
- "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
- "dev": true,
- "requires": {
- "type": "^2.0.0"
- },
- "dependencies": {
- "type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
- "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==",
- "dev": true
- }
- }
- },
- "extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true
- },
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "dev": true,
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
- "dev": true,
- "requires": {
- "array-unique": "^0.3.2",
- "define-property": "^1.0.0",
- "expand-brackets": "^2.1.4",
- "extend-shallow": "^2.0.1",
- "fragment-cache": "^0.2.1",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "fancy-log": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
- "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
- "dev": true,
- "requires": {
- "ansi-gray": "^0.1.1",
- "color-support": "^1.1.3",
- "parse-node-version": "^1.0.0",
- "time-stamp": "^1.0.0"
- }
- },
- "fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
- "dev": true
- },
- "file-entry-cache": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
- "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
- "dev": true,
- "requires": {
- "flat-cache": "^2.0.1"
- }
- },
- "file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "dev": true,
- "optional": true
- },
- "fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
- "dev": true,
- "requires": {
- "locate-path": "^2.0.0"
- }
- },
- "findup-sync": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
- "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
- "dev": true,
- "requires": {
- "detect-file": "^1.0.0",
- "is-glob": "^4.0.0",
- "micromatch": "^3.0.4",
- "resolve-dir": "^1.0.1"
- }
- },
- "fined": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz",
- "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==",
- "dev": true,
- "requires": {
- "expand-tilde": "^2.0.2",
- "is-plain-object": "^2.0.3",
- "object.defaults": "^1.1.0",
- "object.pick": "^1.2.0",
- "parse-filepath": "^1.0.1"
- }
- },
- "flagged-respawn": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz",
- "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==",
- "dev": true
- },
- "flat-cache": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
- "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
- "dev": true,
- "requires": {
- "flatted": "^2.0.0",
- "rimraf": "2.6.3",
- "write": "1.0.3"
- }
- },
- "flatted": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
- "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
- "dev": true
- },
- "flush-write-stream": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
- "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "readable-stream": "^2.3.6"
- }
- },
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
- "dev": true
- },
- "for-own": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
- "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
- "dev": true,
- "requires": {
- "for-in": "^1.0.1"
- }
- },
- "foundry-pc-types": {
- "version": "gitlab:foundry-projects/foundry-pc/foundry-pc-types#6ead51c20f4027a3ed0ce7ab474bb54a645269af",
- "from": "gitlab:foundry-projects/foundry-pc/foundry-pc-types",
- "dev": true,
- "requires": {
- "@types/jquery": "^3.3.31",
- "@types/socket.io-client": "^1.4.33",
- "@types/tinymce": "^4.5.24"
- }
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "dev": true,
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
- "fs-mkdirp-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
- "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.11",
- "through2": "^2.0.3"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
- "dev": true
- },
- "fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "dev": true,
- "optional": true,
- "requires": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- }
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
- "dev": true
- },
- "get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
- "dev": true
- },
- "get-value": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
- "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
- "dev": true
- },
- "glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "glob-parent": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
- "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- },
- "glob-stream": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
- "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=",
- "dev": true,
- "requires": {
- "extend": "^3.0.0",
- "glob": "^7.1.1",
- "glob-parent": "^3.1.0",
- "is-negated-glob": "^1.0.0",
- "ordered-read-streams": "^1.0.0",
- "pumpify": "^1.3.5",
- "readable-stream": "^2.1.5",
- "remove-trailing-separator": "^1.0.1",
- "to-absolute-glob": "^2.0.0",
- "unique-stream": "^2.0.2"
- },
- "dependencies": {
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "dev": true,
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- }
- },
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "glob-watcher": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz",
- "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==",
- "dev": true,
- "requires": {
- "anymatch": "^2.0.0",
- "async-done": "^1.2.0",
- "chokidar": "^2.0.0",
- "is-negated-glob": "^1.0.0",
- "just-debounce": "^1.0.0",
- "normalize-path": "^3.0.0",
- "object.defaults": "^1.1.0"
- }
- },
- "global-modules": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
- "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
- "dev": true,
- "requires": {
- "global-prefix": "^1.0.1",
- "is-windows": "^1.0.1",
- "resolve-dir": "^1.0.0"
- }
- },
- "global-prefix": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
- "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
- "dev": true,
- "requires": {
- "expand-tilde": "^2.0.2",
- "homedir-polyfill": "^1.0.1",
- "ini": "^1.3.4",
- "is-windows": "^1.0.1",
- "which": "^1.2.14"
- },
- "dependencies": {
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
- "globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
- "dev": true,
- "requires": {
- "type-fest": "^0.8.1"
- }
- },
- "glogg": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz",
- "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==",
- "dev": true,
- "requires": {
- "sparkles": "^1.0.0"
- }
- },
- "graceful-fs": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
- "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
- "dev": true
- },
- "gulp": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz",
- "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==",
- "dev": true,
- "requires": {
- "glob-watcher": "^5.0.3",
- "gulp-cli": "^2.2.0",
- "undertaker": "^1.2.1",
- "vinyl-fs": "^3.0.0"
- },
- "dependencies": {
- "ansi-colors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
- "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==",
- "dev": true,
- "requires": {
- "ansi-wrap": "^0.1.0"
- }
- },
- "gulp-cli": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz",
- "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==",
- "dev": true,
- "requires": {
- "ansi-colors": "^1.0.1",
- "archy": "^1.0.0",
- "array-sort": "^1.0.0",
- "color-support": "^1.1.3",
- "concat-stream": "^1.6.0",
- "copy-props": "^2.0.1",
- "fancy-log": "^1.3.2",
- "gulplog": "^1.0.0",
- "interpret": "^1.4.0",
- "isobject": "^3.0.1",
- "liftoff": "^3.1.0",
- "matchdep": "^2.0.0",
- "mute-stdout": "^1.0.0",
- "pretty-hrtime": "^1.0.0",
- "replace-homedir": "^1.0.0",
- "semver-greatest-satisfied-range": "^1.1.0",
- "v8flags": "^3.2.0",
- "yargs": "^7.1.0"
- }
- }
- }
- },
- "gulplog": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
- "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
- "dev": true,
- "requires": {
- "glogg": "^1.0.0"
- }
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "dev": true
- },
- "has-symbols": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
- "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
- },
- "has-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
- "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.6",
- "has-values": "^1.0.0",
- "isobject": "^3.0.0"
- }
- },
- "has-values": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
- "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
- "dev": true,
- "requires": {
- "is-number": "^3.0.0",
- "kind-of": "^4.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "homedir-polyfill": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
- "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
- "dev": true,
- "requires": {
- "parse-passwd": "^1.0.0"
- }
- },
- "hosted-git-info": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
- "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
- "dev": true
- },
- "ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
- "dev": true
- },
- "import-fresh": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
- "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
- "dev": true,
- "requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
- "dev": true
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "dev": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "ini": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
- "dev": true
- },
- "interpret": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
- "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
- "dev": true
- },
- "invert-kv": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
- "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
- "dev": true
- },
- "is-absolute": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
- "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
- "dev": true,
- "requires": {
- "is-relative": "^1.0.0",
- "is-windows": "^1.0.1"
- }
- },
- "is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
- "dev": true
- },
- "is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
- "dev": true,
- "requires": {
- "binary-extensions": "^1.0.0"
- }
- },
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
- "dev": true
- },
- "is-callable": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
- "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
- "dev": true
- },
- "is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-date-object": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
- "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
- "dev": true
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
- }
- },
- "is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
- "dev": true
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true
- },
- "is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-negated-glob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
- "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=",
- "dev": true
- },
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "is-plain-object": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
- "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
- "dev": true,
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "is-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
- "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "is-relative": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
- "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
- "dev": true,
- "requires": {
- "is-unc-path": "^1.0.0"
- }
- },
- "is-string": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
- "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
- "dev": true
- },
- "is-symbol": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
- "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.1"
- }
- },
- "is-unc-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
- "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
- "dev": true,
- "requires": {
- "unc-path-regex": "^0.1.2"
- }
- },
- "is-utf8": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
- "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
- "dev": true
- },
- "is-valid-glob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
- "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=",
- "dev": true
- },
- "is-windows": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
- "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
- "dev": true
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
- "dev": true
- },
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
- },
- "js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
- },
- "js-yaml": {
- "version": "3.14.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
- "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
- "dev": true,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
- "dev": true
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
- "dev": true
- },
- "json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.0"
- }
- },
- "just-debounce": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz",
- "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=",
- "dev": true
- },
- "kind-of": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true
- },
- "last-run": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz",
- "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=",
- "dev": true,
- "requires": {
- "default-resolution": "^2.0.0",
- "es6-weak-map": "^2.0.1"
- }
- },
- "lazystream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
- "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
- "dev": true,
- "requires": {
- "readable-stream": "^2.0.5"
- }
- },
- "lcid": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
- "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
- "dev": true,
- "requires": {
- "invert-kv": "^1.0.0"
- }
- },
- "lead": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz",
- "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=",
- "dev": true,
- "requires": {
- "flush-write-stream": "^1.0.2"
- }
- },
- "levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- }
- },
- "liftoff": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz",
- "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==",
- "dev": true,
- "requires": {
- "extend": "^3.0.0",
- "findup-sync": "^3.0.0",
- "fined": "^1.0.1",
- "flagged-respawn": "^1.0.0",
- "is-plain-object": "^2.0.4",
- "object.map": "^1.0.0",
- "rechoir": "^0.6.2",
- "resolve": "^1.1.7"
- }
- },
- "load-json-file": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
- "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
- "strip-bom": "^3.0.0"
- }
- },
- "locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
- "dev": true,
- "requires": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "lodash": {
- "version": "4.17.19",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
- "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
- "dev": true
- },
- "make-iterator": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
- "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.2"
- }
- },
- "map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
- "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
- "dev": true
- },
- "map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
- "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
- "dev": true,
- "requires": {
- "object-visit": "^1.0.0"
- }
- },
- "matchdep": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz",
- "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=",
- "dev": true,
- "requires": {
- "findup-sync": "^2.0.0",
- "micromatch": "^3.0.4",
- "resolve": "^1.4.0",
- "stack-trace": "0.0.10"
- },
- "dependencies": {
- "findup-sync": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
- "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
- "dev": true,
- "requires": {
- "detect-file": "^1.0.0",
- "is-glob": "^3.1.0",
- "micromatch": "^3.0.4",
- "resolve-dir": "^1.0.1"
- }
- },
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- }
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
- "dev": true
- },
- "mixin-deep": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
- "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
- "dev": true,
- "requires": {
- "for-in": "^1.0.2",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.5"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "mute-stdout": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz",
- "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==",
- "dev": true
- },
- "nan": {
- "version": "2.14.1",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
- "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==",
- "dev": true,
- "optional": true
- },
- "nanomatch": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
- "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
- "dev": true,
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "fragment-cache": "^0.2.1",
- "is-windows": "^1.0.2",
- "kind-of": "^6.0.2",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- }
- },
- "natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
- "dev": true
- },
- "next-tick": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
- "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
- "dev": true
- },
- "normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "requires": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- },
- "dependencies": {
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- }
- }
- },
- "normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true
- },
- "now-and-later": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz",
- "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==",
- "dev": true,
- "requires": {
- "once": "^1.3.2"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
- },
- "object-copy": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
- "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
- "dev": true,
- "requires": {
- "copy-descriptor": "^0.1.0",
- "define-property": "^0.2.5",
- "kind-of": "^3.0.3"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "object-inspect": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
- "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
- "dev": true
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- },
- "object-visit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
- "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.0"
- }
- },
- "object.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.2",
- "function-bind": "^1.1.1",
- "has-symbols": "^1.0.0",
- "object-keys": "^1.0.11"
- }
- },
- "object.defaults": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
- "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=",
- "dev": true,
- "requires": {
- "array-each": "^1.0.1",
- "array-slice": "^1.0.0",
- "for-own": "^1.0.0",
- "isobject": "^3.0.0"
- }
- },
- "object.entries": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz",
- "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5",
- "has": "^1.0.3"
- }
- },
- "object.map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
- "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=",
- "dev": true,
- "requires": {
- "for-own": "^1.0.0",
- "make-iterator": "^1.0.0"
- }
- },
- "object.pick": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
- "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
- "dev": true,
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "object.reduce": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz",
- "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=",
- "dev": true,
- "requires": {
- "for-own": "^1.0.0",
- "make-iterator": "^1.0.0"
- }
- },
- "object.values": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
- "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.0-next.1",
- "function-bind": "^1.1.1",
- "has": "^1.0.3"
- }
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "dev": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
- "dev": true,
- "requires": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
- }
- },
- "ordered-read-streams": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
- "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=",
- "dev": true,
- "requires": {
- "readable-stream": "^2.0.1"
- }
- },
- "os-locale": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
- "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
- "dev": true,
- "requires": {
- "lcid": "^1.0.0"
- }
- },
- "p-limit": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
- "dev": true,
- "requires": {
- "p-try": "^1.0.0"
- }
- },
- "p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
- "dev": true,
- "requires": {
- "p-limit": "^1.1.0"
- }
- },
- "p-try": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
- "dev": true
- },
- "parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "requires": {
- "callsites": "^3.0.0"
- }
- },
- "parse-filepath": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
- "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=",
- "dev": true,
- "requires": {
- "is-absolute": "^1.0.0",
- "map-cache": "^0.2.0",
- "path-root": "^0.1.1"
- }
- },
- "parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
- "dev": true,
- "requires": {
- "error-ex": "^1.2.0"
- }
- },
- "parse-node-version": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
- "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
- "dev": true
- },
- "parse-passwd": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
- "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
- "dev": true
- },
- "pascalcase": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
- "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
- "dev": true
- },
- "path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
- "dev": true
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
- "dev": true
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
- },
- "path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true
- },
- "path-parse": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
- "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
- "dev": true
- },
- "path-root": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
- "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=",
- "dev": true,
- "requires": {
- "path-root-regex": "^0.1.0"
- }
- },
- "path-root-regex": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
- "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=",
- "dev": true
- },
- "path-type": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
- "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
- "dev": true,
- "requires": {
- "pify": "^2.0.0"
- }
- },
- "pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
- },
- "pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
- "dev": true
- },
- "pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
- "dev": true,
- "requires": {
- "pinkie": "^2.0.0"
- }
- },
- "pkg-dir": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
- "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
- "dev": true,
- "requires": {
- "find-up": "^2.1.0"
- }
- },
- "posix-character-classes": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
- "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
- "dev": true
- },
- "prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true
- },
- "pretty-hrtime": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
- "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
- "dev": true
- },
- "process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true
- },
- "progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "dev": true
- },
- "pump": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
- "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "pumpify": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
- "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
- "dev": true,
- "requires": {
- "duplexify": "^3.6.0",
- "inherits": "^2.0.3",
- "pump": "^2.0.0"
- }
- },
- "punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "dev": true
- },
- "read-pkg": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
- "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
- "dev": true,
- "requires": {
- "load-json-file": "^2.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^2.0.0"
- }
- },
- "read-pkg-up": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
- "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
- "dev": true,
- "requires": {
- "find-up": "^2.0.0",
- "read-pkg": "^2.0.0"
- }
- },
- "readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
- "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
- }
- },
- "rechoir": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
- "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
- "dev": true,
- "requires": {
- "resolve": "^1.1.6"
- }
- },
- "regex-not": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
- "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
- "dev": true,
- "requires": {
- "extend-shallow": "^3.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "regexpp": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
- "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
- "dev": true
- },
- "remove-bom-buffer": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz",
- "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5",
- "is-utf8": "^0.2.1"
- }
- },
- "remove-bom-stream": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz",
- "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=",
- "dev": true,
- "requires": {
- "remove-bom-buffer": "^3.0.0",
- "safe-buffer": "^5.1.0",
- "through2": "^2.0.3"
- }
- },
- "remove-trailing-separator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
- "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
- "dev": true
- },
- "repeat-element": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
- "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
- "dev": true
- },
- "repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
- "dev": true
- },
- "replace-ext": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz",
- "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==",
- "dev": true
- },
- "replace-homedir": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz",
- "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=",
- "dev": true,
- "requires": {
- "homedir-polyfill": "^1.0.1",
- "is-absolute": "^1.0.0",
- "remove-trailing-separator": "^1.1.0"
- }
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
- },
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
- "dev": true
- },
- "resolve": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
- "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
- "dev": true,
- "requires": {
- "path-parse": "^1.0.6"
- }
- },
- "resolve-dir": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
- "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
- "dev": true,
- "requires": {
- "expand-tilde": "^2.0.0",
- "global-modules": "^1.0.0"
- }
- },
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
- },
- "resolve-options": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz",
- "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=",
- "dev": true,
- "requires": {
- "value-or-function": "^3.0.0"
- }
- },
- "resolve-url": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
- "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
- "dev": true
- },
- "ret": {
- "version": "0.1.15",
- "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
- "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
- "dev": true
- },
- "rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
- "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- },
- "safe-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
- "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
- "dev": true,
- "requires": {
- "ret": "~0.1.10"
- }
- },
- "semver": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
- "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
- "dev": true
- },
- "semver-greatest-satisfied-range": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz",
- "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=",
- "dev": true,
- "requires": {
- "sver-compat": "^1.5.0"
- }
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
- "dev": true
- },
- "set-value": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
- "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
- "dev": true,
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.3",
- "split-string": "^3.0.1"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true
- },
- "slice-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
- "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
- "dev": true,
- "requires": {
- "ansi-styles": "^3.2.0",
- "astral-regex": "^1.0.0",
- "is-fullwidth-code-point": "^2.0.0"
- }
- },
- "snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
- "dev": true,
- "requires": {
- "base": "^0.11.1",
- "debug": "^2.2.0",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "map-cache": "^0.2.2",
- "source-map": "^0.5.6",
- "source-map-resolve": "^0.5.0",
- "use": "^3.1.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
- "dev": true
- }
- }
- },
- "snapdragon-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
- "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
- "dev": true,
- "requires": {
- "define-property": "^1.0.0",
- "isobject": "^3.0.0",
- "snapdragon-util": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "snapdragon-util": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
- "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
- "dev": true,
- "requires": {
- "kind-of": "^3.2.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
- },
- "source-map-resolve": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
- "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
- "dev": true,
- "requires": {
- "atob": "^2.1.2",
- "decode-uri-component": "^0.2.0",
- "resolve-url": "^0.2.1",
- "source-map-url": "^0.4.0",
- "urix": "^0.1.0"
- }
- },
- "source-map-url": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
- "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
- "dev": true
- },
- "sparkles": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
- "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==",
- "dev": true
- },
- "spdx-correct": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
- "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
- "dev": true,
- "requires": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
- },
- "spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "requires": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "spdx-license-ids": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
- "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
- "dev": true
- },
- "split-string": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
- "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
- "dev": true,
- "requires": {
- "extend-shallow": "^3.0.0"
- }
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
- "dev": true
- },
- "stack-trace": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
- "dev": true
- },
- "static-extend": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
- "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
- "dev": true,
- "requires": {
- "define-property": "^0.2.5",
- "object-copy": "^0.1.0"
- },
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
- }
- },
- "stream-exhaust": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz",
- "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==",
- "dev": true
- },
- "stream-shift": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
- "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
- "dev": true
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "string.prototype.trimend": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
- "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- }
- },
- "string.prototype.trimstart": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
- "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3",
- "es-abstract": "^1.17.5"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
- "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
- "dev": true,
- "requires": {
- "ansi-regex": "^5.0.0"
- }
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
- "dev": true
- },
- "strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true
- },
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "sver-compat": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz",
- "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=",
- "dev": true,
- "requires": {
- "es6-iterator": "^2.0.1",
- "es6-symbol": "^3.1.1"
- }
- },
- "table": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
- "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
- "dev": true,
- "requires": {
- "ajv": "^6.10.2",
- "lodash": "^4.17.14",
- "slice-ansi": "^2.1.0",
- "string-width": "^3.0.0"
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
- "dev": true
- },
- "through2": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
- "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
- "dev": true,
- "requires": {
- "readable-stream": "~2.3.6",
- "xtend": "~4.0.1"
- }
- },
- "through2-filter": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
- "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
- "dev": true,
- "requires": {
- "through2": "~2.0.0",
- "xtend": "~4.0.0"
- }
- },
- "time-stamp": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
- "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
- "dev": true
- },
- "to-absolute-glob": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
- "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=",
- "dev": true,
- "requires": {
- "is-absolute": "^1.0.0",
- "is-negated-glob": "^1.0.0"
- }
- },
- "to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
- "dev": true
- },
- "to-object-path": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
- "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
- "dev": true,
- "requires": {
- "kind-of": "^3.0.2"
- },
- "dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "to-regex": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
- "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
- "dev": true,
- "requires": {
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "regex-not": "^1.0.2",
- "safe-regex": "^1.1.0"
- }
- },
- "to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
- "dev": true,
- "requires": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
- }
- },
- "to-through": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz",
- "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=",
- "dev": true,
- "requires": {
- "through2": "^2.0.3"
- }
- },
- "tsconfig-paths": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz",
- "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==",
- "dev": true,
- "requires": {
- "@types/json5": "^0.0.29",
- "json5": "^1.0.1",
- "minimist": "^1.2.0",
- "strip-bom": "^3.0.0"
- }
- },
- "type": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
- "dev": true
- },
- "type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1"
- }
- },
- "type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
- "dev": true
- },
- "typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
- "dev": true
- },
- "unc-path-regex": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
- "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
- "dev": true
- },
- "undertaker": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz",
- "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.0.1",
- "arr-map": "^2.0.0",
- "bach": "^1.0.0",
- "collection-map": "^1.0.0",
- "es6-weak-map": "^2.0.1",
- "last-run": "^1.1.0",
- "object.defaults": "^1.0.0",
- "object.reduce": "^1.0.0",
- "undertaker-registry": "^1.0.0"
- }
- },
- "undertaker-registry": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz",
- "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=",
- "dev": true
- },
- "union-value": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
- "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
- "dev": true,
- "requires": {
- "arr-union": "^3.1.0",
- "get-value": "^2.0.6",
- "is-extendable": "^0.1.1",
- "set-value": "^2.0.1"
- }
- },
- "unique-stream": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
- "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
- "dev": true,
- "requires": {
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "through2-filter": "^3.0.0"
- }
- },
- "unset-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
- "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
- "dev": true,
- "requires": {
- "has-value": "^0.3.1",
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "dev": true,
- "requires": {
- "isarray": "1.0.0"
- }
- }
- }
- },
- "has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
- "dev": true
- }
- }
- },
- "upath": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
- "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
- "dev": true
- },
- "uri-js": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
- "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
- "urix": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
- "dev": true
- },
- "use": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
- "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
- "dev": true
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true
- },
- "v8-compile-cache": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
- "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
- "dev": true
- },
- "v8flags": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
- "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
- "dev": true,
- "requires": {
- "homedir-polyfill": "^1.0.1"
- }
- },
- "validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "requires": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "value-or-function": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz",
- "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=",
- "dev": true
- },
- "vinyl": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
- "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
- "dev": true,
- "requires": {
- "clone": "^2.1.1",
- "clone-buffer": "^1.0.0",
- "clone-stats": "^1.0.0",
- "cloneable-readable": "^1.0.0",
- "remove-trailing-separator": "^1.0.1",
- "replace-ext": "^1.0.0"
- }
- },
- "vinyl-fs": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz",
- "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==",
- "dev": true,
- "requires": {
- "fs-mkdirp-stream": "^1.0.0",
- "glob-stream": "^6.1.0",
- "graceful-fs": "^4.0.0",
- "is-valid-glob": "^1.0.0",
- "lazystream": "^1.0.0",
- "lead": "^1.0.0",
- "object.assign": "^4.0.4",
- "pumpify": "^1.3.5",
- "readable-stream": "^2.3.3",
- "remove-bom-buffer": "^3.0.0",
- "remove-bom-stream": "^1.2.0",
- "resolve-options": "^1.1.0",
- "through2": "^2.0.0",
- "to-through": "^2.0.0",
- "value-or-function": "^3.0.0",
- "vinyl": "^2.0.0",
- "vinyl-sourcemap": "^1.1.0"
- }
- },
- "vinyl-sourcemap": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz",
- "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=",
- "dev": true,
- "requires": {
- "append-buffer": "^1.0.2",
- "convert-source-map": "^1.5.0",
- "graceful-fs": "^4.1.6",
- "normalize-path": "^2.1.1",
- "now-and-later": "^2.0.0",
- "remove-bom-buffer": "^3.0.0",
- "vinyl": "^2.0.0"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
- }
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "which-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
- "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
- "dev": true
- },
- "word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "dev": true
- },
- "wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "dev": true,
- "requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- }
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
- "dev": true
- },
- "write": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
- "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
- "dev": true,
- "requires": {
- "mkdirp": "^0.5.1"
- }
- },
- "xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true
- },
- "y18n": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
- "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
- "dev": true
- },
- "yargs": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz",
- "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==",
- "dev": true,
- "requires": {
- "camelcase": "^3.0.0",
- "cliui": "^3.2.0",
- "decamelize": "^1.1.1",
- "get-caller-file": "^1.0.1",
- "os-locale": "^1.4.0",
- "read-pkg-up": "^1.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
- "set-blocking": "^2.0.0",
- "string-width": "^1.0.2",
- "which-module": "^1.0.0",
- "y18n": "^3.2.1",
- "yargs-parser": "5.0.0-security.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
- },
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "dev": true,
- "requires": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "dev": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "load-json-file": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
- "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "strip-bom": "^2.0.0"
- }
- },
- "path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
- "dev": true,
- "requires": {
- "pinkie-promise": "^2.0.0"
- }
- },
- "path-type": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
- "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- }
- },
- "read-pkg": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
- "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
- "dev": true,
- "requires": {
- "load-json-file": "^1.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^1.0.0"
- }
- },
- "read-pkg-up": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
- "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
- "dev": true,
- "requires": {
- "find-up": "^1.0.0",
- "read-pkg": "^1.0.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "dev": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "dev": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "strip-bom": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
- "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
- "dev": true,
- "requires": {
- "is-utf8": "^0.2.0"
- }
- }
- }
- },
- "yargs-parser": {
- "version": "5.0.0-security.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz",
- "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==",
- "dev": true,
- "requires": {
- "camelcase": "^3.0.0",
- "object.assign": "^4.1.0"
- }
- }
- }
-}
diff --git a/package.json b/package.json
index 39e4f2e..342f479 100644
--- a/package.json
+++ b/package.json
@@ -1,27 +1,92 @@
{
- "name": "simplefog",
- "version": "0.1.6",
- "description": "Simple fog of war for foundryvtt",
- "main": "foundry.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/VanceCole/simplefog.git"
- },
- "author": "Vance Cole",
- "license": "ISC",
- "bugs": {
- "url": "https://github.com/VanceCole/simple-fog/issues"
- },
- "homepage": "https://github.com/VanceCole/simplefog#readme",
- "devDependencies": {
- "babel-eslint": "^10.1.0",
- "eslint": "^7.5.0",
- "eslint-config-airbnb-base": "^14.2.0",
- "eslint-plugin-import": "^2.22.0",
- "gulp": "^4.0.2"
- },
- "dependencies": {}
+ "name": "simplefog",
+ "title": "Simplefog - Manual Fog of War",
+ "description": "Simplefog allows you to draw fog of war manually, optionally automatically hiding and revealing tokens underneath based on opacity. It provides a number of tools to quickly draw and erase fog in various shapes - brush, rectangles, ellipses, polygons or to reveal tiles you click/drag on the grid.",
+ "version": "0.3.4",
+ "main": "main.js",
+ "scripts": {
+ "publish": "gulp publish --update",
+ "package": "gulp package",
+ "build": "gulp build --dbg",
+ "build:link": "gulp build --dbg && gulp link",
+ "build:test": "gulp build --dbg && gulp link && npm test",
+ "build:prod": "gulp bundle && npm test",
+ "build:watch": "gulp watch",
+ "clean": "gulp clean && gulp link --clean",
+ "test": "jest",
+ "prettier-format": "prettier --config .prettierrc.js --write \"./src/**/*.{ts,js,json,scss,css}\" \"./*.{ts,js,json,scss,css}\""
+ },
+ "keywords": [
+ "foundryvtt",
+ "fvtt",
+ "module"
+ ],
+ "author": "",
+ "license": "SEE LICENSE IN LICENSE",
+ "devDependencies": {
+ "@babel/core": "^7.15.0",
+ "@babel/eslint-parser": "^7.15.4",
+ "@rollup/plugin-node-resolve": "^13.3.0",
+ "@types/archiver": "^5.1.1",
+ "@types/browserify": "^12.0.37",
+ "@types/color": "^3.0.2",
+ "@types/gulp": "^4.0.9",
+ "@types/gulp-less": "^0.0.32",
+ "@types/jest": "^27.4.0",
+ "@types/jquery": "^3.5.14",
+ "@types/yargs": "^17.0.2",
+ "@typescript-eslint/eslint-plugin": "^5.42.1",
+ "@typescript-eslint/parser": "^5.42.1",
+ "@typhonjs-fvtt/eslint-config-foundry.js": "^0.8.0",
+ "archiver": "^5.3.0",
+ "babelify": "^10.0.0",
+ "browserify": "^17.0.0",
+ "color": "3.2.1",
+ "eslint": "^7.32.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-jsdoc": "^39.3.3",
+ "eslint-plugin-json": "^3.1.0",
+ "fancy-log": "^2.0.0",
+ "fs": "^0.0.1-security",
+ "gulp": "^4.0.0",
+ "gulp-bro": "^2.0.0",
+ "gulp-changed": "^4.0.3",
+ "gulp-eslint-new": "^1.5.1",
+ "gulp-eslint7": "^0.3.1",
+ "gulp-git": "^2.10.1",
+ "gulp-if": "^3.0.0",
+ "gulp-less": "^5.0.0",
+ "gulp-rename": "^2.0.0",
+ "gulp-replace": "^1.1.3",
+ "gulp-sass": "^5.1.0",
+ "gulp-sourcemaps": "^3.0.0",
+ "gulp-typescript": "^6.0.0-alpha.1",
+ "gulp-uglify": "^3.0.2",
+ "jest": "^27.5.1",
+ "json-stringify-pretty-compact": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "nedb": "^1.8.0",
+ "path": "^0.12.7",
+ "rollup": "^2.77.0",
+ "sass": "^1.49.11",
+ "through2": "^4.0.2",
+ "ts-jest": "^27.1.3",
+ "ts-node": "^10.2.1",
+ "typescript": "^4.8.4",
+ "typescript-eslint": "^0.0.1-alpha.0",
+ "uglifyify": "^5.0.2",
+ "vinyl-buffer": "^1.0.1",
+ "vinyl-source-stream": "^2.0.0",
+ "yargs": "^17.1.1"
+ },
+ "dependencies": {
+ "build": "^0.1.4",
+ "csv-parse": "^4.16.3",
+ "gulp-jest": "^4.0.4",
+ "node-sass": "^7.0.1",
+ "prettier": "^2.7.1",
+ "prettier-format": "^3.1.0",
+ "tsify": "^5.0.4"
+ }
}
diff --git a/src/classes/BrushControls.js b/src/classes/BrushControls.js
new file mode 100644
index 0000000..8ca20c7
--- /dev/null
+++ b/src/classes/BrushControls.js
@@ -0,0 +1,52 @@
+import { hexToPercent, percentToHex } from "../js/helpers.js";
+
+export default class BrushControls extends FormApplication {
+ static get defaultOptions() {
+ return mergeObject(super.defaultOptions, {
+ classes: ["form"],
+ closeOnSubmit: false,
+ submitOnChange: true,
+ submitOnClose: true,
+ popOut: false,
+ editable: game.user.isGM,
+ template: "modules/simplefog/templates/brush-controls.html",
+ id: "filter-config",
+ title: game.i18n.localize("Simplefog Options"),
+ });
+ }
+
+ /* -------------------------------------------- */
+
+ /**
+ * Obtain module metadata and merge it with game settings which track current module visibility
+ * @return {Object} The data provided to the template when rendering the form
+ */
+ getData() {
+ // Return data to the template
+ return {
+ brushSize: canvas.simplefog.getUserSetting("brushSize"),
+ brushOpacity: hexToPercent(canvas.simplefog.getUserSetting("brushOpacity")),
+ };
+ }
+
+ /* -------------------------------------------- */
+ /* Event Listeners and Handlers */
+ /* -------------------------------------------- */
+
+ /** @override */
+ activateListeners(html) {
+ super.activateListeners(html);
+ }
+
+ /**
+ * This method is called upon form submission after form data is validated
+ * @param event {Event} The initial triggering submission event
+ * @param formData {Object} The object of validated form data with which to update the object
+ * @private
+ */
+ async _updateObject(event, formData) {
+ canvas.simplefog.setUserSetting("brushSize", formData.brushSize);
+ await canvas.simplefog.setUserSetting("brushOpacity", percentToHex(formData.brushOpacity));
+ canvas.simplefog.setPreviewTint();
+ }
+}
diff --git a/src/classes/MaskLayer.js b/src/classes/MaskLayer.js
new file mode 100644
index 0000000..dbcb2d2
--- /dev/null
+++ b/src/classes/MaskLayer.js
@@ -0,0 +1,590 @@
+/* MaskLayer extends CanvasLayer
+ *
+ * Creates an interactive layer which has an alpha channel mask
+ * that can be rendered to and history for syncing between players
+ * and replaying the mask / undo etc.
+ */
+
+import { simplefogLog, simplefogLogDebug } from "../js/helpers.js";
+
+export default class MaskLayer extends InteractionLayer {
+ constructor(layername) {
+ super();
+ this.lock = false;
+ this.layername = layername;
+ this.historyBuffer = [];
+ this.pointer = 0;
+ this.gridLayout = {};
+ this.dragStart = { x: 0, y: 0 };
+ // Not actually used, just to prevent foundry from complaining
+ this.history = [];
+ this.BRUSH_TYPES = {
+ ELLIPSE: 0,
+ BOX: 1,
+ ROUNDED_RECT: 2,
+ POLYGON: 3,
+ };
+ this.DEFAULTS = {
+ visible: false,
+ blurEnable: true,
+ blurQuality: 2,
+ blurRadius: 5,
+ gmColorAlpha: 0.6,
+ gmColorTint: "0x000000",
+ playerColorAlpha: 1,
+ playerColorTint: "0x000000",
+ fogImageOverlayFilePath: "",
+ fogImageOverlayGMAlpha: 0.6,
+ fogImageOverlayPlayerAlpha: 1,
+ fogImageOverlayZIndex: 6000,
+ layerZindex: 220,
+ };
+ }
+
+ static get layerOptions() {
+ //@ts-ignore
+ return mergeObject(super.layerOptions, {
+ // ToDo: is ugly hack still needed?
+ // Ugly hack - render at very high zindex and then re-render at layer init with layerZindex value
+ zIndex: game.settings.get("simplefog", "zIndex"),
+ });
+ }
+
+ /* -------------------------------------------- */
+ /* Init */
+ /* -------------------------------------------- */
+
+ /**
+ * Called on canvas init, creates the canvas layers and various objects and registers listeners
+ *
+ * Important objects:
+ *
+ * layer - PIXI Sprite which holds all the mask elements
+ * filters - Holds filters such as blur applied to the layer
+ * fogColorLayer - PIXI Sprite wrapping the renderable mask
+ * maskTexture - renderable texture that holds the actual mask data
+ * fogImageOverlayLayer - PIXI Sprite that holds the image applied over the fog color
+ */
+ initMask() {
+ simplefogLogDebug("MaskLayer.initMask");
+ // Check if masklayer is flagged visible
+ let v = this.getSetting("visible");
+ if (v === undefined) v = false;
+ this.visible = v;
+ simplefogLogDebug("MaskLayer.initMask - visible", this.visible);
+
+ // The layer is the primary sprite to be displayed
+ this.fogColorLayer = MaskLayer.getCanvasSprite();
+ this.setColorTint(this.getTint());
+ this.setColorAlpha(this.getColorAlpha(), true);
+
+ this.blur = new PIXI.filters.BlurFilter();
+ this.blur.padding = 0;
+ this.blur.repeatEdgePixels = true;
+ this.blur.blur = this.getSetting("blurRadius");
+ this.blur.quality = this.getSetting("blurQuality");
+
+ // Filters
+ if (this.getSetting("blurEnable")) {
+ this.fogColorLayer.filters = [this.blur];
+ } else {
+ this.fogColorLayer.filters = [];
+ }
+
+ //So you can hit escape on the keyboard and it will bring up the menu
+ this._controlled = {};
+
+ this.maskTexture = MaskLayer.getMaskTexture();
+ this.maskSprite = new PIXI.Sprite(this.maskTexture);
+
+ this.fogColorLayer.mask = this.maskSprite;
+ this.setFill();
+
+ // Allow zIndex prop to function for items on this layer
+ this.sortableChildren = true;
+
+ // Render entire history stack
+ this.renderStack(undefined, 0, undefined, true);
+
+ // apply image overlay to fog layer after we renderStack to prevent revealing the map
+ this.fogImageOverlayLayer = new PIXI.Sprite();
+ this.fogImageOverlayLayer.position.set(canvas.dimensions.sceneRect.x, canvas.dimensions.sceneRect.y);
+ this.fogImageOverlayLayer.width = canvas.dimensions.sceneRect.width;
+ this.fogImageOverlayLayer.height = canvas.dimensions.sceneRect.height;
+ this.fogImageOverlayLayer.mask = this.maskSprite;
+ this.setFogImageOverlayZIndex(this.getSetting("fogImageOverlayZIndex"));
+ this.setFogImageOverlayTexture();
+ this.setFogImageOverlayAlpha(this.getFogImageOverlayAlpha(), true);
+ }
+
+ /* -------------------------------------------- */
+ /* Getters and setters for layer props */
+ /* -------------------------------------------- */
+
+ // Tint & Alpha have special cases because they can differ between GM & Players
+ // And alpha can be animated for transition effects
+
+ getColorAlpha() {
+ let alpha;
+ if (game.user.isGM) alpha = this.getSetting("gmColorAlpha");
+ else alpha = this.getSetting("playerColorAlpha");
+ if (!alpha) {
+ if (game.user.isGM) alpha = this.DEFAULTS.gmColorAlpha;
+ else alpha = this.DEFAULTS.playerColorAlpha;
+ }
+ return alpha;
+ }
+
+ /**
+ * Sets the scene's alpha for the primary layer.
+ * @param alpha {Number} 0-1 opacity representation
+ * @param skip {Boolean} Optional override to skip using animated transition
+ */
+ async setColorAlpha(alpha, skip = false) {
+ simplefogLogDebug("MaskLayer.setColorAlpha");
+ // If skip is false, do not transition and just set alpha immediately
+ if (skip || !this.getSetting("transition")) {
+ this.fogColorLayer.alpha = alpha;
+ }
+ // Loop until transition is complete
+ else {
+ const start = this.fogColorLayer.alpha;
+ const dist = start - alpha;
+ const fps = 60;
+ const speed = this.getSetting("transitionSpeed");
+ const frame = 1000 / fps;
+ const rate = dist / ((fps * speed) / 1000);
+ let f = (fps * speed) / 1000;
+ while (f > 0) {
+ // Delay 1 frame before updating again
+ // eslint-disable-next-line no-await-in-loop
+ await new Promise((resolve) => setTimeout(resolve, frame));
+ this.fogColorLayer.alpha -= rate;
+ f -= 1;
+ }
+ // Reset target alpha in case loop overshot a bit
+ this.fogColorLayer.alpha = alpha;
+ }
+ }
+
+ getTint() {
+ let tint;
+ if (game.user.isGM) tint = this.getSetting("gmColorTint");
+ else tint = this.getSetting("playerColorTint");
+ if (!tint) {
+ if (game.user.isGM) tint = this.gmColorTintDefault;
+ else tint = this.playerColorTintDefault;
+ }
+ return tint;
+ }
+
+ setColorTint(tint) {
+ this.fogColorLayer.tint = tint;
+ }
+
+ static getMaskTexture() {
+ simplefogLogDebug("MaskLayer.getMaskTexture");
+ const d = canvas.dimensions;
+ let res = 1.0;
+ if (d.width * d.height > 16000 ** 2) res = 0.25;
+ else if (d.width * d.height > 8000 ** 2) res = 0.5;
+
+ // Create the mask elements
+ const tex = PIXI.RenderTexture.create({
+ width: canvas.dimensions.width,
+ height: canvas.dimensions.height,
+ resolution: res,
+ });
+ return tex;
+ }
+
+ /* -------------------------------------------- */
+ /* Player Fog Image Overlay */
+ /* -------------------------------------------- */
+ async setFogImageOverlayTexture(fogImageOverlayFilePath = this.getSetting("fogImageOverlayFilePath")) {
+ if (fogImageOverlayFilePath) {
+ const texture = await loadTexture(fogImageOverlayFilePath);
+ this.fogImageOverlayLayer.texture = texture;
+ // If player, don't set tint
+ //if (!game.user.isGM) canvas[this.layername].setColorTint(null);
+ } else {
+ this.fogImageOverlayLayer.texture = undefined;
+ }
+ }
+
+ getFogImageOverlayAlpha() {
+ let alpha;
+ if (game.user.isGM) alpha = this.getSetting("fogImageOverlayGMAlpha");
+ else alpha = this.getSetting("fogImageOverlayPlayerAlpha");
+ if (!alpha) {
+ if (game.user.isGM) alpha = this.DEFAULTS.fogImageOverlayGMAlpha;
+ else alpha = this.DEFAULTS.fogImageOverlayAlpha;
+ }
+ return alpha;
+ }
+
+ async setFogImageOverlayAlpha(alpha, skip = false) {
+ // If skip is false, do not transition and just set alpha immediately
+ if (skip || !this.getSetting("transition")) {
+ this.fogImageOverlayLayer.alpha = alpha;
+ }
+ // Loop until transition is complete
+ else {
+ const start = this.fogImageOverlayLayer.alpha;
+ const dist = start - alpha;
+ const fps = 60;
+ const speed = this.getSetting("transitionSpeed");
+ const frame = 1000 / fps;
+ const rate = dist / ((fps * speed) / 1000);
+ let f = (fps * speed) / 1000;
+ while (f > 0) {
+ // Delay 1 frame before updating again
+ // eslint-disable-next-line no-await-in-loop
+ await new Promise((resolve) => setTimeout(resolve, frame));
+ this.fogImageOverlayLayer.alpha -= rate;
+ f -= 1;
+ }
+ // Reset target alpha in case loop overshot a bit
+ this.fogImageOverlayLayer.alpha = alpha;
+ }
+ }
+
+ async setFogImageOverlayZIndex(zIndex) {
+ this.fogImageOverlayLayer.zIndex = zIndex;
+ }
+
+ /**
+ * Gets and sets various layer wide properties
+ * Some properties have different values depending on if user is a GM or player
+ */
+
+ getSetting(name) {
+ let setting = canvas.scene.getFlag(this.layername, name);
+ if (setting === undefined) setting = this.getUserSetting(name);
+ if (setting === undefined) setting = this.DEFAULTS[name];
+ return setting;
+ }
+
+ async setSetting(name, value) {
+ const v = await canvas.scene.setFlag(this.layername, name, value);
+ return v;
+ }
+
+ getUserSetting(name) {
+ let setting = game.user.getFlag(this.layername, name);
+ if (setting === undefined) setting = this.DEFAULTS[name];
+ return setting;
+ }
+
+ async setUserSetting(name, value) {
+ const v = await game.user.setFlag(this.layername, name, value);
+ return v;
+ }
+
+ /**
+ * Renders the history stack to the mask
+ * @param history {Array} A collection of history events
+ * @param start {Number} The position in the history stack to begin rendering from
+ * @param start {Number} The position in the history stack to stop rendering
+ */
+ renderStack(
+ history = canvas.scene.getFlag(this.layername, "history"),
+ start = this.pointer,
+ stop = canvas.scene.getFlag(this.layername, "history.pointer"),
+ isInit = false
+ ) {
+ simplefogLogDebug("MaskLayer.renderStack");
+ history = history || { events: [], pointer: 0 };
+ // If history is blank, do nothing
+ if (history === undefined && !isInit) {
+ simplefogLogDebug("MaskLayer.renderStack - set visible to autoEnableSceneFog");
+ this.visible = game.settings.get("simplefog", "autoEnableSceneFog");
+ return;
+ }
+ // If history is zero, reset scene fog
+ if (history.events.length === 0) this.resetMask(false);
+ if (start === undefined) start = 0;
+ if (stop === undefined) stop = history.events.length;
+ // If pointer preceeds the stop, reset and start from 0
+ if (stop <= this.pointer) {
+ this.resetMask(false);
+ start = 0;
+ }
+
+ simplefogLog(`Rendering from: ${start} to ${stop}`);
+ // Render all ops starting from pointer
+ for (let i = start; i < stop; i += 1) {
+ for (let j = 0; j < history.events[i].length; j += 1) {
+ this.renderBrush(history.events[i][j], false);
+ }
+ }
+ // Update local pointer
+ this.pointer = stop;
+ // Prevent calling update when no lights loaded
+ if (!canvas.sight?.light?.los?.geometry) return;
+ // Update sight layer
+ //ToDo: Determine replacement for canvas.sight.refresh()
+ canvas.perception.refresh();
+ }
+
+ /**
+ * Add buffered history stack to scene flag and clear buffer
+ */
+ async commitHistory() {
+ simplefogLogDebug("MaskLayer.commitHistory");
+ // Do nothing if no history to be committed, otherwise get history
+ if (this.historyBuffer.length === 0) return;
+ if (this.lock) return;
+ this.lock = true;
+ let history = canvas.scene.getFlag(this.layername, "history");
+ // If history storage doesnt exist, create it
+ if (!history) {
+ history = {
+ events: [],
+ pointer: 0,
+ };
+ }
+ // If pointer is less than history length (f.x. user undo), truncate history
+ history.events = history.events.slice(0, history.pointer);
+ // Push the new history buffer to the scene
+ history.events.push(this.historyBuffer);
+ history.pointer = history.events.length;
+ await canvas.scene.unsetFlag(this.layername, "history");
+ await this.setSetting("history", history);
+ simplefogLog(`Pushed ${this.historyBuffer.length} updates.`);
+ // Clear the history buffer
+ this.historyBuffer = [];
+ this.lock = false;
+ }
+
+ /**
+ * Resets the mask of the layer
+ * @param save {Boolean} If true, also resets the layer history
+ */
+ async resetMask(save = true) {
+ simplefogLogDebug("MaskLayer.resetMask");
+ // Fill fog layer with solid
+ this.setFill();
+ // If save, also unset history and reset pointer
+ if (save) {
+ await canvas.scene.unsetFlag(this.layername, "history");
+ await canvas.scene.setFlag(this.layername, "history", {
+ events: [],
+ pointer: 0,
+ });
+ this.pointer = 0;
+ }
+ }
+
+ /**
+ * Resets the mask of the layer
+ * @param save {Boolean} If true, also resets the layer history
+ */
+ async blankMask() {
+ simplefogLogDebug("MaskLayer.blankMask");
+ await this.resetMask();
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.BOX,
+ x: 0,
+ y: 0,
+ width: this.width,
+ height: this.height,
+ fill: 0x000000,
+ });
+ this.commitHistory();
+ }
+
+ /**
+ * Steps the history buffer back X steps and redraws
+ * @param steps {Integer} Number of steps to undo, default 1
+ */
+ async undo(steps = 1) {
+ simplefogLogDebug("MaskLayer.undo");
+ simplefogLog(`Undoing ${steps} steps.`);
+ // Grab existing history
+ // Todo: this could probably just grab and set the pointer for a slight performance improvement
+ let history = canvas.scene.getFlag(this.layername, "history");
+ if (!history) {
+ history = {
+ events: [],
+ pointer: 0,
+ };
+ }
+ let newpointer = this.pointer - steps;
+ if (newpointer < 0) newpointer = 0;
+ // Set new pointer & update history
+ history.pointer = newpointer;
+ await canvas.scene.unsetFlag(this.layername, "history");
+ await canvas.scene.setFlag(this.layername, "history", history);
+ }
+
+ /* -------------------------------------------- */
+ /* Shapes, sprites and PIXI objs */
+ /* -------------------------------------------- */
+
+ /**
+ * Creates a PIXI graphic using the given brush parameters
+ * @param data {Object} A collection of brush parameters
+ * @returns {Object} PIXI.Graphics() instance
+ *
+ * @example
+ * const myBrush = this.brush({
+ * shape: "ellipse",
+ * x: 0,
+ * y: 0,
+ * fill: 0x000000,
+ * width: 50,
+ * height: 50,
+ * alpha: 1,
+ * visible: true
+ * });
+ */
+ brush(data) {
+ // Get new graphic & begin filling
+ const alpha = typeof data.alpha === "undefined" ? 1 : data.alpha;
+ const visible = typeof data.visible === "undefined" ? true : data.visible;
+ const brush = new PIXI.Graphics();
+ brush.beginFill(data.fill);
+ // Draw the shape depending on type of brush
+ switch (data.shape) {
+ case this.BRUSH_TYPES.ELLIPSE:
+ brush.drawEllipse(0, 0, data.width, data.height);
+ break;
+ case this.BRUSH_TYPES.BOX:
+ brush.drawRect(0, 0, data.width, data.height);
+ break;
+ case this.BRUSH_TYPES.ROUNDED_RECT:
+ brush.drawRoundedRect(0, 0, data.width, data.height, 10);
+ break;
+ case this.BRUSH_TYPES.POLYGON:
+ brush.drawPolygon(data.vertices);
+ break;
+ default:
+ break;
+ }
+ // End fill and set the basic props
+ brush.endFill();
+ brush.alpha = alpha;
+ brush.visible = visible;
+ brush.x = data.x;
+ brush.y = data.y;
+ brush.zIndex = data.zIndex;
+ return brush;
+ }
+
+ /**
+ * Gets a brush using the given parameters, renders it to mask and saves the event to history
+ * @param data {Object} A collection of brush parameters
+ * @param save {Boolean} If true, will add the operation to the history buffer
+ */
+ renderBrush(data, save = true) {
+ const brush = this.brush(data);
+ this.composite(brush);
+ brush.destroy();
+ if (save) this.historyBuffer.push(data);
+ }
+
+ /**
+ * Renders the given brush to the layer mask
+ * @param data {Object} PIXI Object to be used as brush
+ */
+ composite(brush) {
+ if (isNewerVersion(game.version, "10.999")) {
+ const opt = {
+ renderTexture: this.maskTexture,
+ clear: false,
+ transform: null,
+ skipUpdateTransform: false
+ }
+ canvas.app.renderer.render(brush, opt);
+ }
+ else {
+ canvas.app.renderer.render(brush, this.maskTexture, false, null, false);
+ }
+ }
+
+ /**
+ * Returns a blank PIXI Sprite of canvas dimensions
+ */
+ static getCanvasSprite() {
+ simplefogLogDebug("MaskLayer.getCanvasSprite");
+ const sprite = new PIXI.Sprite(PIXI.Texture.WHITE);
+ const d = canvas.dimensions;
+ sprite.width = d.width;
+ sprite.height = d.height;
+ sprite.x = 0;
+ sprite.y = 0;
+ sprite.zIndex = 5000;
+ return sprite;
+ }
+
+ /**
+ * Fills the mask layer with solid white
+ */
+ setFill() {
+ simplefogLogDebug("MaskLayer.setFill");
+ const fill = new PIXI.Graphics();
+ fill.beginFill(0xffffff);
+ fill.drawRect(0, 0, canvas.dimensions.width, canvas.dimensions.height);
+ fill.endFill();
+ this.composite(fill);
+ fill.destroy();
+ }
+
+ /**
+ * Toggles visibility of primary layer
+ */
+ toggle() {
+ simplefogLogDebug("MaskLayer.toggle");
+ const v = this.getSetting("visible");
+ this.visible = !v;
+ this.setSetting("visible", !v);
+
+ //If first time, set autofog to opposite so it doesn't reapply it.
+ let history = canvas.scene.getFlag(this.layername, "history");
+
+ if (history === undefined) {
+ this.setSetting("autoFog", !v);
+ return;
+ }
+ }
+
+ /**
+ * Actions upon layer becoming active
+ */
+ activate() {
+ simplefogLogDebug("MaskLayer.activate");
+ super.activate();
+ if (isNewerVersion(game.version, "10.999")) {
+ this.eventMode = "static";
+ } else {
+ this.interactive = true;
+ }
+ }
+
+ /**
+ * Actions upon layer becoming inactive
+ */
+ deactivate() {
+ simplefogLogDebug("MaskLayer.deactivate");
+ super.deactivate();
+ if (isNewerVersion(game.version, "10.999")) {
+ this.eventMode = "passive";
+ } else {
+ this.interactive = false;
+ }
+ }
+
+ async draw() {
+ simplefogLogDebug("MaskLayer.draw");
+ super.draw();
+ this.initMask();
+ this.addChild(canvas.simplefog.fogImageOverlayLayer);
+ this.addChild(this.fogColorLayer);
+ this.addChild(this.fogColorLayer.mask);
+ }
+
+ refreshZIndex() {
+ canvas.simplefog.zIndex = game.settings.get("simplefog", "zIndex");
+ }
+}
diff --git a/src/classes/SimplefogConfig.js b/src/classes/SimplefogConfig.js
new file mode 100644
index 0000000..9f96ab6
--- /dev/null
+++ b/src/classes/SimplefogConfig.js
@@ -0,0 +1,96 @@
+import { webToHex, hexToWeb } from "../js/helpers.js";
+
+export default class SimplefogConfig extends FormApplication {
+ static get defaultOptions() {
+ return mergeObject(super.defaultOptions, {
+ classes: ["form"],
+ closeOnSubmit: false,
+ submitOnChange: true,
+ submitOnClose: true,
+ popOut: true,
+ editable: game.user.isGM,
+ width: 500,
+ template: "modules/simplefog/templates/scene-config.html",
+ id: "simplefog-scene-config",
+ title: game.i18n.localize("Simplefog Options"),
+ });
+ }
+
+ /* -------------------------------------------- */
+
+ /**
+ * Obtain module metadata and merge it with game settings which track current module visibility
+ * @return {Object} The data provided to the template when rendering the form
+ */
+ getData() {
+ // Return data to the template
+ return {
+ gmColorAlpha: Math.round(canvas.simplefog.getSetting("gmColorAlpha") * 100),
+ gmColorTint: hexToWeb(canvas.simplefog.getSetting("gmColorTint")),
+ playerColorAlpha: Math.round(canvas.simplefog.getSetting("playerColorAlpha") * 100),
+ playerColorTint: hexToWeb(canvas.simplefog.getSetting("playerColorTint")),
+ transition: canvas.simplefog.getSetting("transition"),
+ transitionSpeed: canvas.simplefog.getSetting("transitionSpeed"),
+ blurEnable: canvas.simplefog.getSetting("blurEnable"),
+ blurRadius: canvas.simplefog.getSetting("blurRadius"),
+ blurQuality: canvas.simplefog.getSetting("blurQuality"),
+ autoVisibility: canvas.simplefog.getSetting("autoVisibility"),
+ autoVisGM: canvas.simplefog.getSetting("autoVisGM"),
+ vThreshold: Math.round(canvas.simplefog.getSetting("vThreshold") * 100),
+ fogImageOverlayFilePath: canvas.simplefog.getSetting("fogImageOverlayFilePath"),
+ fogImageOverlayGMAlpha: Math.round(canvas.simplefog.getSetting("fogImageOverlayGMAlpha") * 100),
+ fogImageOverlayPlayerAlpha: Math.round(canvas.simplefog.getSetting("fogImageOverlayPlayerAlpha") * 100),
+ fogImageOverlayZIndex: canvas.simplefog.getSetting("fogImageOverlayZIndex"),
+ fogImageOverlayZIndexOptions: {
+ 4000: "Color Tint Above Overlay Image",
+ 6000: "Overlay Image Above Color Tint",
+ },
+ versionNotification: canvas.simplefog.getSetting("versionNotification"),
+ };
+ }
+
+ /* -------------------------------------------- */
+ /* Event Listeners and Handlers */
+ /* -------------------------------------------- */
+
+ /**
+ * This method is called upon form submission after form data is validated
+ * @param event {Event} The initial triggering submission event
+ * @param formData {Object} The object of validated form data with which to update the object
+ * @private
+ */
+ async _updateObject(event, formData) {
+ Object.entries(formData).forEach(async ([key, val]) => {
+ // If setting is an opacity slider, convert from 1-100 to 0-1
+ if (
+ [
+ "gmColorAlpha",
+ "playerColorAlpha",
+ "vThreshold",
+ "fogImageOverlayGMAlpha",
+ "fogImageOverlayPlayerAlpha",
+ ].includes(key)
+ )
+ val /= 100;
+ // If setting is a color value, convert webcolor to hex before saving
+ if (["gmColorTint", "playerColorTint"].includes(key)) val = webToHex(val);
+ // Save settings to scene
+ await canvas.simplefog.setSetting(key, val);
+ // If saveDefaults button clicked, also save to user's defaults
+ if (event.submitter?.name === "saveDefaults") {
+ canvas.simplefog.setUserSetting(key, val);
+ }
+ });
+
+ // If save button was clicked, close app
+ if (event.submitter?.name === "submit") {
+ Object.values(ui.windows).forEach((val) => {
+ if (val.id === "simplefog-scene-config") val.close();
+ });
+ }
+
+ // Update sight layer
+ //ToDo: Determine replacement for canvas.sight.refresh()
+ canvas.perception.refresh();
+ }
+}
diff --git a/src/classes/SimplefogHUDControlLayer.js b/src/classes/SimplefogHUDControlLayer.js
new file mode 100644
index 0000000..bec108a
--- /dev/null
+++ b/src/classes/SimplefogHUDControlLayer.js
@@ -0,0 +1,15 @@
+/* SimplefogHUDControlLayer extends CanvasLayer
+ *
+ * Used as layer directly below simplefog for object HUD controls
+ */
+
+export default class SimplefogHUDControlLayer extends InteractionLayer {
+ constructor(layername) {
+ super();
+ }
+
+ static get layerOptions() {
+ //@ts-ignore
+ return super.layerOptions;
+ }
+}
diff --git a/src/classes/SimplefogLayer.js b/src/classes/SimplefogLayer.js
new file mode 100644
index 0000000..bc24e89
--- /dev/null
+++ b/src/classes/SimplefogLayer.js
@@ -0,0 +1,730 @@
+/* SimplefogLayer extends MaskLayer
+ *
+ * Implements tools for manipulating the MaskLayer
+ */
+
+import MaskLayer from "./MaskLayer.js";
+import { Layout } from "../libs/hexagons.js";
+import { hexObjsToArr, hexToPercent, simplefogLog, simplefogLogDebug } from "../js/helpers.js";
+
+export default class SimplefogLayer extends MaskLayer {
+ constructor() {
+ simplefogLogDebug("SimplefogLayer.constructor");
+ super("simplefog");
+
+ // Register event listerenrs
+ Hooks.on("ready", () => {
+ this._registerMouseListeners();
+ this._registerKeyboardListeners();
+ });
+
+ this.DEFAULTS = Object.assign(this.DEFAULTS, {
+ transition: true,
+ transitionSpeed: 800,
+ previewColor: "0x00FFFF",
+ handlefill: "0xff6400",
+ handlesize: 20,
+ previewAlpha: 0.4,
+ brushSize: 50,
+ brushOpacity: 1,
+ autoVisibility: false,
+ autoVisGM: false,
+ vThreshold: 1,
+ hotKeyTool: "Brush",
+ });
+
+ /* // React to canvas zoom
+ Hooks.on('canvasPan', (canvas, dimensions) => {
+ // Scale blur filter radius to account for zooming
+ //this.blur.blur = this.getSetting('blurRadius') * dimensions.scale;
+ });*/
+
+ // React to changes to current scene
+ Hooks.on("updateScene", (scene, data) => this._updateScene(scene, data));
+
+ // Canvas expects the options.name property to be set
+ this.options = this.constructor.layerOptions;
+ }
+
+ initSimplefog() {
+ simplefogLogDebug("SimplefogLayer.init");
+ // Preview brush objects
+ this.boxPreview = this.brush({
+ shape: this.BRUSH_TYPES.BOX,
+ x: 0,
+ y: 0,
+ fill: 0xffffff,
+ alpha: this.DEFAULTS.previewAlpha,
+ width: 100,
+ height: 100,
+ visible: false,
+ zIndex: 10,
+ });
+ this.ellipsePreview = this.brush({
+ shape: this.BRUSH_TYPES.ELLIPSE,
+ x: 0,
+ y: 0,
+ fill: 0xffffff,
+ alpha: this.DEFAULTS.previewAlpha,
+ width: 100,
+ height: 100,
+ visible: false,
+ zIndex: 10,
+ });
+ this.polygonPreview = this.brush({
+ shape: this.BRUSH_TYPES.POLYGON,
+ x: 0,
+ y: 0,
+ vertices: [],
+ fill: 0xffffff,
+ alpha: this.DEFAULTS.previewAlpha,
+ visible: false,
+ zIndex: 10,
+ });
+ this.polygonHandle = this.brush({
+ shape: this.BRUSH_TYPES.BOX,
+ x: 0,
+ y: 0,
+ fill: this.DEFAULTS.handlefill,
+ width: this.DEFAULTS.handlesize * 2,
+ height: this.DEFAULTS.handlesize * 2,
+ alpha: this.DEFAULTS.previewAlpha,
+ visible: false,
+ zIndex: 15,
+ });
+ }
+
+ canvasInit() {
+ simplefogLogDebug("SimplefogLayer.canvasInit");
+ // Set default flags if they dont exist already
+ Object.keys(this.DEFAULTS).forEach((key) => {
+ if (!game.user.isGM) return;
+ // Check for existing scene specific setting
+ if (this.getSetting(key) !== undefined) return;
+ // Check for custom default
+ const def = this.getUserSetting(key);
+ // If user has custom default, set it for scene
+ if (def !== undefined) this.setSetting(key, def);
+ // Otherwise fall back to module default
+ else this.setSetting(key, this.DEFAULTS[key]);
+ });
+ //this.setColorAlpha(this.getColorAlpha(), true);
+ }
+
+ /* -------------------------------------------- */
+ /* Event Listeners and Handlers */
+ /* -------------------------------------------- */
+
+ /**
+ * React to updates of canvas.scene flags
+ */
+ _updateScene(scene, data) {
+ // Check if update applies to current viewed scene
+ if (!scene._view) return;
+ // React to visibility change
+ if (hasProperty(data, `flags.${this.layername}.visible`)) {
+ canvas[this.layername].visible = data.flags[this.layername].visible;
+ }
+ // React to composite history change
+ if (hasProperty(data, `flags.${this.layername}.blurEnable`)) {
+ if (this.fogColorLayer !== undefined) {
+ if (this.getSetting("blurEnable")) {
+ this.fogColorLayer.filters = [this.blur];
+ } else {
+ this.fogColorLayer.filters = [];
+ }
+ }
+ }
+ if (hasProperty(data, `flags.${this.layername}.blurRadius`)) {
+ canvas[this.layername].blur.blur = this.getSetting("blurRadius");
+ }
+ // React to composite history change
+ if (hasProperty(data, `flags.${this.layername}.blurQuality`)) {
+ canvas[this.layername].blur.quality = this.getSetting("blurQuality");
+ }
+ // React to composite history change
+ if (hasProperty(data, `flags.${this.layername}.history`)) {
+ canvas[this.layername].renderStack(data.flags[this.layername].history);
+
+ //ToDo: Determine replacement for canvas.sight.refresh()
+ canvas.perception.refresh();
+ }
+ // React to autoVisibility setting changes
+ if (
+ hasProperty(data, `flags.${this.layername}.autoVisibility`) ||
+ hasProperty(data, `flags.${this.layername}.vThreshold`)
+ ) {
+ //ToDo: Determine replacement for canvas.sight.refresh()
+ canvas.perception.refresh();
+ }
+ // React to alpha/tint changes
+ if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.playerColorAlpha`)) {
+ canvas[this.layername].setColorAlpha(data.flags[this.layername].playerColorAlpha);
+ }
+ if (game.user.isGM && hasProperty(data, `flags.${this.layername}.gmColorAlpha`)) {
+ canvas[this.layername].setColorAlpha(data.flags[this.layername].gmColorAlpha);
+ }
+ if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.playerColorTint`)) {
+ canvas[this.layername].setColorTint(data.flags[this.layername].playerColorTint);
+ }
+ if (game.user.isGM && hasProperty(data, `flags.${this.layername}.gmColorTint`)) {
+ canvas[this.layername].setColorTint(data.flags[this.layername].gmColorTint);
+ }
+
+ // React to Image Overylay file changes
+ if (hasProperty(data, `flags.${this.layername}.fogImageOverlayFilePath`)) {
+ canvas[this.layername].setFogImageOverlayTexture(data.flags[this.layername].fogImageOverlayFilePath);
+ } else {
+ canvas[this.layername].setFogImageOverlayTexture(undefined);
+ }
+
+ if (game.user.isGM && hasProperty(data, `flags.${this.layername}.fogImageOverlayGMAlpha`)) {
+ canvas[this.layername].setFogImageOverlayAlpha(data.flags[this.layername].fogImageOverlayGMAlpha);
+ }
+ if (!game.user.isGM && hasProperty(data, `flags.${this.layername}.fogImageOverlayPlayerAlpha`)) {
+ canvas[this.layername].setFogImageOverlayAlpha(data.flags[this.layername].fogImageOverlayPlayerAlpha);
+ }
+ if (hasProperty(data, `flags.${this.layername}.fogImageOverlayZIndex`))
+ canvas[this.layername].setFogImageOverlayZIndex(data.flags[this.layername].fogImageOverlayZIndex);
+ }
+
+ /**
+ * Adds the mouse listeners to the layer
+ */
+ _registerMouseListeners() {
+ this.addListener("pointerdown", this._pointerDown);
+ this.addListener("pointerup", this._pointerUp);
+ this.addListener("pointermove", this._pointerMove);
+ this.dragging = false;
+ this.brushing = false;
+ }
+
+ /**
+ * Adds the keyboard listeners to the layer
+ */
+ _registerKeyboardListeners() {
+ $(document).keydown((event) => {
+ // Only react if simplefog layer is active
+ if (ui.controls.activeControl !== this.layername) return;
+ // Don't react if game body isn't target
+ if (!event.target.tagName === "BODY") return;
+ if (event.which === 219 && this.activeTool === "brush") {
+ const s = this.getUserSetting("brushSize");
+ this.setBrushSize(s * 0.8);
+ }
+ if (event.which === 221 && this.activeTool === "brush") {
+ const s = this.getUserSetting("brushSize");
+ this.setBrushSize(s * 1.25);
+ }
+ // React to ctrl+z
+ if (event.which === 90 && event.ctrlKey) {
+ event.stopPropagation();
+ this.undo();
+ }
+ });
+ }
+
+ /**
+ * Sets the active tool & shows preview for brush & grid tools
+ */
+ setActiveTool(tool) {
+ simplefogLogDebug("SimplefogLayer.setActiveTool");
+ this.clearActiveTool();
+ this.activeTool = tool;
+ this.setPreviewTint();
+ const currentTool = $("#simplefog-brush-controls #brush-size-container");
+ if (currentTool.length) {
+ if (tool === "brush") {
+ this.ellipsePreview.visible = true;
+ $("#simplefog-brush-controls #brush-size-container").show();
+ } else {
+ $("#simplefog-brush-controls #brush-size-container").hide();
+ }
+ }
+ if (tool === "grid") {
+ if (canvas.scene.grid.type === 1) {
+ this.boxPreview.width = canvas.scene.grid.size;
+ this.boxPreview.height = canvas.scene.grid.size;
+ this.boxPreview.visible = true;
+ } else if ([2, 3, 4, 5].includes(canvas.scene.grid.type)) {
+ this._initGrid();
+ this.polygonPreview.visible = true;
+ }
+ }
+ }
+
+ setPreviewTint() {
+ const vt = this.getSetting("vThreshold");
+ const bo = hexToPercent(this.getUserSetting("brushOpacity")) / 100;
+ let tint = 0xff0000;
+ if (bo < vt) tint = 0x00ff00;
+ this.ellipsePreview.tint = tint;
+ this.boxPreview.tint = tint;
+ this.polygonPreview.tint = tint;
+ }
+
+ /**
+ * Sets the active tool & shows preview for brush & grid tools
+ * @param {Number} Size in pixels
+ */
+ async setBrushSize(s) {
+ await this.setUserSetting("brushSize", s);
+ const p = { x: this.ellipsePreview.x, y: this.ellipsePreview.y };
+ this._pointerMoveBrush(p);
+ }
+
+ /**
+ * Aborts any active drawing tools
+ */
+ clearActiveTool() {
+ try {
+ // Box preview
+ this.boxPreview.visible = false;
+ } catch (err) {}
+ try {
+ // Ellipse Preview
+ this.ellipsePreview.visible = false;
+ } catch (err) {}
+ try {
+ // Shape preview
+ this.polygonPreview.clear();
+ this.polygonPreview.visible = false;
+ this.polygonHandle.visible = false;
+ this.polygon = [];
+ } catch (err) {}
+ try {
+ // Cancel op flag
+ this.op = false;
+ } catch (err) {}
+ try {
+ // Clear history buffer
+ this.historyBuffer = [];
+ } catch (err) {}
+ }
+
+ /**
+ * Mouse handlers for canvas layer interactions
+ */
+ _pointerDown(e) {
+ // Don't allow new action if history push still in progress
+ if (this.historyBuffer.length > 0) return;
+ // On left mouse button
+ if (e.data.button === 0) {
+ const p = e.data.getLocalPosition(canvas.app.stage);
+ // Round positions to nearest pixel
+ p.x = Math.round(p.x);
+ p.y = Math.round(p.y);
+ this.op = true;
+ // Check active tool
+ switch (this.activeTool) {
+ case "brush":
+ this._pointerDownBrush(p, e);
+ break;
+ case "grid":
+ this._pointerDownGrid(p, e);
+ break;
+ case "box":
+ this._pointerDownBox(p, e);
+ break;
+ case "ellipse":
+ this._pointerDownEllipse(p, e);
+ break;
+ case "polygon":
+ this._pointerDownPolygon(p, e);
+ break;
+ default: // Do nothing
+ break;
+ }
+ // Call _pointermove so single click will still draw brush if mouse does not move
+ this._pointerMove(e);
+ }
+ // On right button, cancel action
+ else if (e.data.button === 2) {
+ // Todo: Not sure why this doesnt trigger when drawing ellipse & box
+ if (["polygon", "box", "ellipse"].includes(this.activeTool)) {
+ this.clearActiveTool();
+ }
+ }
+ }
+
+ _pointerMove(e) {
+ // Get mouse position translated to canvas coords
+ const p = e.data.getLocalPosition(canvas.app.stage);
+ // Round positions to nearest pixel
+ p.x = Math.round(p.x);
+ p.y = Math.round(p.y);
+ switch (this.activeTool) {
+ case "brush":
+ this._pointerMoveBrush(p, e);
+ break;
+ case "box":
+ this._pointerMoveBox(p, e);
+ break;
+ case "grid":
+ this._pointerMoveGrid(p, e);
+ break;
+ case "ellipse":
+ this._pointerMoveEllipse(p, e);
+ break;
+ default:
+ break;
+ }
+ }
+
+ _pointerUp(e) {
+ // Only react to left mouse button
+ if (e.data.button === 0) {
+ // Translate click to canvas position
+ const p = e.data.getLocalPosition(canvas.app.stage);
+ // Round positions to nearest pixel
+ p.x = Math.round(p.x);
+ p.y = Math.round(p.y);
+ switch (this.op) {
+ case "box":
+ this._pointerUpBox(p, e);
+ break;
+ case "ellipse":
+ this._pointerUpEllipse(p, e);
+ break;
+ default: // Do nothing
+ break;
+ }
+ // Reset operation
+ this.op = false;
+ // Push the history buffer
+ this.commitHistory();
+ }
+ }
+
+ /**
+ * Brush Tool
+ */
+ _pointerDownBrush() {
+ this.op = true;
+ }
+
+ _pointerMoveBrush(p) {
+ const size = this.getUserSetting("brushSize");
+ this.ellipsePreview.width = size * 2;
+ this.ellipsePreview.height = size * 2;
+ this.ellipsePreview.x = p.x;
+ this.ellipsePreview.y = p.y;
+ // If drag operation has started
+ if (this.op) {
+ // Send brush movement events to renderbrush to be drawn and added to history stack
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.ELLIPSE,
+ x: p.x,
+ y: p.y,
+ fill: this.getUserSetting("brushOpacity"),
+ width: this.getUserSetting("brushSize"),
+ height: this.getUserSetting("brushSize"),
+ });
+ }
+ }
+
+ /*
+ * Box Tool
+ */
+ _pointerDownBox(p) {
+ // Set active drag operation
+ this.op = "box";
+ // Set drag start coords
+ this.dragStart.x = p.x;
+ this.dragStart.y = p.y;
+ // Reveal the preview shape
+ this.boxPreview.visible = true;
+ this.boxPreview.x = p.x;
+ this.boxPreview.y = p.y;
+ }
+
+ _pointerMoveBox(p, e) {
+ // If drag operation has started
+ if (this.op) {
+ // update the preview shape
+ const d = this._getDragBounds(p, e);
+ this.boxPreview.width = d.w;
+ this.boxPreview.height = d.h;
+ }
+ }
+
+ _pointerUpBox(p, e) {
+ // update the preview shape
+ const d = this._getDragBounds(p, e);
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.BOX,
+ x: this.dragStart.x,
+ y: this.dragStart.y,
+ width: d.w,
+ height: d.h,
+ fill: this.getUserSetting("brushOpacity"),
+ });
+ this.boxPreview.visible = false;
+ }
+
+ /*
+ * Ellipse Tool
+ */
+ _pointerDownEllipse(p) {
+ // Set active drag operation
+ this.op = "ellipse";
+ // Set drag start coords
+ this.dragStart.x = p.x;
+ this.dragStart.y = p.y;
+ // Reveal the preview shape
+ this.ellipsePreview.x = p.x;
+ this.ellipsePreview.y = p.y;
+ this.ellipsePreview.visible = true;
+ }
+
+ _pointerMoveEllipse(p, e) {
+ // If drag operation has started
+ const d = this._getDragBounds(p, e);
+ if (this.op) {
+ // Just update the preview shape
+ this.ellipsePreview.width = d.w * 2;
+ this.ellipsePreview.height = d.h * 2;
+ }
+ }
+
+ _pointerUpEllipse(p, e) {
+ const d = this._getDragBounds(p, e);
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.ELLIPSE,
+ x: this.dragStart.x,
+ y: this.dragStart.y,
+ width: Math.abs(d.w),
+ height: Math.abs(d.h),
+ fill: this.getUserSetting("brushOpacity"),
+ });
+ this.ellipsePreview.visible = false;
+ }
+
+ /*
+ * Polygon Tool
+ */
+ _pointerDownPolygon(p) {
+ if (!this.polygon) this.polygon = [];
+ const x = Math.floor(p.x);
+ const y = Math.floor(p.y);
+ // If this is not the first vertex...
+ if (this.polygon.length) {
+ // Check if new point is close enough to start to close the polygon
+ const xo = Math.abs(this.polygon[0].x - x);
+ const yo = Math.abs(this.polygon[0].y - y);
+ if (xo < this.DEFAULTS.handlesize && yo < this.DEFAULTS.handlesize) {
+ const verts = hexObjsToArr(this.polygon);
+ // render the new shape to history
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.POLYGON,
+ x: 0,
+ y: 0,
+ vertices: verts,
+ fill: this.getUserSetting("brushOpacity"),
+ });
+ // Reset the preview shape
+ this.polygonPreview.clear();
+ this.polygonPreview.visible = false;
+ this.polygonHandle.visible = false;
+ this.polygon = [];
+ return;
+ }
+ }
+ // If this is first vertex...
+ else {
+ // Draw shape handle
+ this.polygonHandle.x = x - this.DEFAULTS.handlesize;
+ this.polygonHandle.y = y - this.DEFAULTS.handlesize;
+ this.polygonHandle.visible = true;
+ }
+ // If intermediate vertex, add it to array and redraw the preview
+ this.polygon.push({ x, y });
+ this.polygonPreview.clear();
+ this.polygonPreview.beginFill(0xffffff);
+ this.polygonPreview.drawPolygon(hexObjsToArr(this.polygon));
+ this.polygonPreview.endFill();
+ this.polygonPreview.visible = true;
+ }
+
+ /**
+ * Grid Tool
+ */
+ _pointerDownGrid() {
+ // Set active drag operation
+ this.op = "grid";
+ this._initGrid();
+ }
+
+ _pointerMoveGrid(p) {
+ const gridSize = canvas.scene.grid.size;
+ const gridType = canvas.scene.grid.type;
+ // Square grid
+ if (gridType === 1) {
+ const gridx = Math.floor(p.x / gridSize);
+ const gridy = Math.floor(p.y / gridSize);
+ const x = gridx * gridSize;
+ const y = gridy * gridSize;
+ const coord = `${x},${y}`;
+ this.boxPreview.x = x;
+ this.boxPreview.y = y;
+ this.boxPreview.width = gridSize;
+ this.boxPreview.height = gridSize;
+ if (this.op) {
+ if (!this.dupes.includes(coord)) {
+ // Flag cell as drawn in dupes
+ this.dupes.push(coord);
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.BOX,
+ x,
+ y,
+ width: gridSize,
+ height: gridSize,
+ fill: this.getUserSetting("brushOpacity"),
+ });
+ }
+ }
+ }
+ // Hex Grid
+ else if ([2, 3, 4, 5].includes(gridType)) {
+ // Convert pixel coord to hex coord
+ const qr = this.gridLayout.pixelToHex(p).round();
+ // Get current grid coord verts
+ const vertices = this.gridLayout.polygonCorners({ q: qr.q, r: qr.r });
+ // Convert to array of individual verts
+ const vertexArray = hexObjsToArr(vertices);
+ // Update the preview shape
+ this.polygonPreview.clear();
+ this.polygonPreview.beginFill(0xffffff);
+ this.polygonPreview.drawPolygon(vertexArray);
+ this.polygonPreview.endFill();
+ // If drag operation has started
+ if (this.op) {
+ const coord = `${qr.q},${qr.r}`;
+ // Check if this grid cell was already drawn
+ if (!this.dupes.includes(coord)) {
+ // Get the vert coords for the hex
+ this.renderBrush({
+ shape: this.BRUSH_TYPES.POLYGON,
+ vertices: vertexArray,
+ x: 0,
+ y: 0,
+ fill: this.getUserSetting("brushOpacity"),
+ });
+ // Flag cell as drawn in dupes
+ this.dupes.push(`${qr.q},${qr.r}`);
+ }
+ }
+ }
+ }
+
+ /*
+ * Returns height and width given a pointer coord and event for modifer keys
+ */
+ _getDragBounds(p, e) {
+ let h = p.y - this.dragStart.y;
+ let w = p.x - this.dragStart.x;
+ if (e.data.originalEvent.shiftKey) {
+ const ws = Math.sign(w);
+ const hs = Math.sign(h);
+ if (Math.abs(h) > Math.abs(w)) w = Math.abs(h) * ws;
+ else h = Math.abs(w) * hs;
+ }
+ return { w, h };
+ }
+
+ /*
+ * Checks grid type, creates a dupe detection matrix & if hex grid init a layout
+ */
+ _initGrid() {
+ const gridSize = canvas.scene.grid.size;
+ this.dupes = [];
+ if (canvas.scene.flags.core?.legacyHex) {
+ switch (canvas.scene.grid.type) {
+ // Square grid
+ // Pointy Hex Odd
+ case 2:
+ this.gridLayout = new Layout(
+ Layout.pointy,
+ { x: gridSize / 2, y: gridSize / 2 },
+ { x: 0, y: gridSize / 2 }
+ );
+ break;
+ // Pointy Hex Even
+ case 3:
+ this.gridLayout = new Layout(
+ Layout.pointy,
+ { x: gridSize / 2, y: gridSize / 2 },
+ { x: (Math.sqrt(3) * gridSize) / 4, y: gridSize / 2 }
+ );
+ break;
+ // Flat Hex Odd
+ case 4:
+ this.gridLayout = new Layout(
+ Layout.flat,
+ { x: gridSize / 2, y: gridSize / 2 },
+ { x: gridSize / 2, y: 0 }
+ );
+ break;
+ // Flat Hex Even
+ case 5:
+ this.gridLayout = new Layout(
+ Layout.flat,
+ { x: gridSize / 2, y: gridSize / 2 },
+ { x: gridSize / 2, y: (Math.sqrt(3) * gridSize) / 4 }
+ );
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (canvas.scene.grid.type) {
+ // Square grid
+ // Pointy Hex Odd
+ case 2:
+ this.gridLayout = new Layout(
+ Layout.pointy,
+ { x: gridSize / Math.sqrt(3), y: gridSize / Math.sqrt(3) },
+ { x: 0, y: gridSize / Math.sqrt(3) }
+ );
+ break;
+ // Pointy Hex Even
+ case 3:
+ this.gridLayout = new Layout(
+ Layout.pointy,
+ { x: gridSize / Math.sqrt(3), y: gridSize / Math.sqrt(3) },
+ { x: gridSize / 2, y: gridSize / Math.sqrt(3) }
+ );
+ break;
+ // Flat Hex Odd
+ case 4:
+ this.gridLayout = new Layout(
+ Layout.flat,
+ { x: gridSize / Math.sqrt(3), y: gridSize / Math.sqrt(3) },
+ { x: gridSize / Math.sqrt(3), y: 0 }
+ );
+ break;
+ // Flat Hex Even
+ case 5:
+ this.gridLayout = new Layout(
+ Layout.flat,
+ { x: gridSize / Math.sqrt(3), y: gridSize / Math.sqrt(3) },
+ { x: gridSize / Math.sqrt(3), y: gridSize / 2 }
+ );
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ async draw() {
+ simplefogLogDebug("SimplefogLayer.draw");
+ super.draw();
+ this.initSimplefog();
+
+ this.addChild(this.boxPreview);
+ this.addChild(this.ellipsePreview);
+ this.addChild(this.polygonPreview);
+ this.addChild(this.polygonHandle);
+ }
+}
diff --git a/src/classes/SimplefogMigrations.js b/src/classes/SimplefogMigrations.js
new file mode 100644
index 0000000..8ad66f5
--- /dev/null
+++ b/src/classes/SimplefogMigrations.js
@@ -0,0 +1,119 @@
+/*
+ * Provides for the ability to check and run migration code for changes to data
+ */
+/* eslint-disable max-len */
+import { dmToGM, simplefogLog, simplefogLogDebug } from "../js/helpers.js";
+
+export default class SimplefogMigrations {
+ static check() {
+ simplefogLogDebug("SimplefogMigrations.check");
+ if (!game.user.isGM) return;
+ simplefogLog("Checking migrations");
+ const ver = game.settings.get("simplefog", "migrationVersion");
+ if (ver === 1) {
+ SimplefogMigrations.migration2();
+ } else if (ver < 1) SimplefogMigrations.migration1();
+ }
+
+ /*
+ * Tidys up some messy data storage from early versions
+ * - Converts string based shape names to integers
+ * - Rounds any decimal x / y / height / width values
+ * - Deletes any unnecessary visible & alpha props
+ */
+ static migration1() {
+ simplefogLog("Performing migration #1", true);
+ game.scenes.forEach(async (s) => {
+ // Check if scene has simplefog history
+ if (s.data.flags?.simplefog?.history?.events) {
+ const { history } = s.data.flags.simplefog;
+ // Loop through all events to check for old data
+ for (let i = 0; i < history.events.length; i += 1) {
+ for (let j = 0; j < history.events[i].length; j += 1) {
+ // Update shape props to use integers instead of strings
+ switch (history.events[i][j].shape) {
+ case "ellipse":
+ history.events[i][j].shape = 0;
+ break;
+ case "box":
+ history.events[i][j].shape = 1;
+ break;
+ case "shape":
+ history.events[i][j].shape = 3;
+ break;
+ case "polygon":
+ history.events[i][j].shape = 3;
+ break;
+ default:
+ break;
+ }
+ // Round decimal values
+ if (history.events[i][j].x) history.events[i][j].x = Math.round(history.events[i][j].x);
+ if (history.events[i][j].x) history.events[i][j].y = Math.round(history.events[i][j].y);
+ if (history.events[i][j].height)
+ history.events[i][j].height = Math.round(history.events[i][j].height);
+ if (history.events[i][j].width)
+ history.events[i][j].width = Math.round(history.events[i][j].width);
+ // Remove unnecessary visible & alpha props
+ if (history.events[i][j].visible) delete history.events[i][j].visible;
+ if (history.events[i][j].alpha) delete history.events[i][j].alpha;
+ }
+ }
+ await s.unsetFlag("simplefog", "history");
+ s.setFlag("simplefog", "history", history);
+ game.settings.set("simplefog", "migrationVersion", 1);
+ }
+ });
+ }
+
+ /*
+ * Major data changes from v9 to v10
+ */
+ static migration2() {
+ simplefogLog("Performing migration #2", true);
+ game.scenes.forEach(async (s) => {
+ // Migrate all variables to new names, otherwise set to defaults
+ if (s.flags?.simplefog?.gmAlpha) {
+ s.setFlag("simplefog", "gmColorAlpha", s.data.flags.simplefog.gmAlpha);
+ await s.unsetFlag("simplefog", "gmAlpha");
+ } else if (s.getFlag("simplefog", "gmColorAlpha") === undefined) {
+ s.setFlag("simplefog", "gmColorAlpha", canvas.simplefog.DEFAULTS.gmColorAlpha);
+ }
+
+ if (s.flags?.simplefog?.gmTint) {
+ s.setFlag("simplefog", "gmColorTint", s.data.flags.simplefog.gmTint);
+ await s.unsetFlag("simplefog", "gmTint");
+ } else if (s.getFlag("simplefog", "gmColorTint") === undefined) {
+ s.setFlag("simplefog", "gmColorTint", canvas.simplefog.DEFAULTS.gmColorTint);
+ }
+
+ if (s.flags?.simplefog?.playerAlpha) {
+ s.setFlag("simplefog", "playerColorAlpha", s.data.flags.simplefog.playerAlpha);
+ await s.unsetFlag("simplefog", "playerAlpha");
+ } else if (s.getFlag("simplefog", "playerColorAlpha") === undefined) {
+ s.setFlag("simplefog", "playerColorAlpha", canvas.simplefog.DEFAULTS.playerColorAlpha);
+ }
+
+ if (s.flags?.simplefog?.playerTint) {
+ s.setFlag("simplefog", "playerColorTint", s.data.flags.simplefog.playerTint);
+ await s.unsetFlag("simplefog", "playerTint");
+ } else if (s.getFlag("simplefog", "playerColorTint") === undefined) {
+ s.setFlag("simplefog", "playerColorTint", canvas.simplefog.DEFAULTS.playerColorTint);
+ }
+
+ if (s.flags?.simplefog?.layerZindex) {
+ s.setFlag("simplefog", "fogImageOverlayZIndex", s.data.flags.simplefog.layerZindex);
+ await s.unsetFlag("simplefog", "layerZindex");
+ } else if (s.getFlag("simplefog", "fogImageOverlayZIndex") === undefined) {
+ s.setFlag("simplefog", "fogImageOverlayZIndex", canvas.simplefog.DEFAULTS.fogImageOverlayZIndex);
+ }
+
+ if (s.flags?.simplefog?.fogTextureFilePath) {
+ s.setFlag("simplefog", "fogImageOverlayFilePath", s.data.flags.simplefog.fogTextureFilePath);
+ await s.unsetFlag("simplefog", "fogTextureFilePath");
+ }
+ });
+ dmToGM(game.i18n.localize("SIMPLEFOG.migration2Notification"), undefined);
+ game.settings.set("simplefog", "migrationVersion", 2);
+ }
+}
diff --git a/src/classes/SimplefogNotification.js b/src/classes/SimplefogNotification.js
new file mode 100644
index 0000000..d690494
--- /dev/null
+++ b/src/classes/SimplefogNotification.js
@@ -0,0 +1,30 @@
+/*
+ * Provides a mechanism to send whisper to GM when new version installed.
+ */
+import { dmToGM } from "../js/helpers.js";
+
+export default class SimplefogNotification {
+ constructor() {}
+ static checkVersion() {
+ let packageVersion;
+
+ if (isNewerVersion(game.version, "9")) {
+ packageVersion = game.modules.get("simplefog").version;
+ }
+ else {
+ packageVersion = game.modules.get("simplefog").data.version;
+ }
+
+ if (
+ game.user.isGM &&
+ game.user.getFlag("simplefog", "versionNotification") !== packageVersion
+ ) {
+ // GM has never seen current version message
+
+ dmToGM(game.i18n.localize("SIMPLEFOG.versionNotification"), undefined);
+
+ // Update the saved version
+ game.user.setFlag("simplefog", "versionNotification", packageVersion);
+ }
+ }
+}
diff --git a/src/css/brush-controls.css b/src/css/brush-controls.css
new file mode 100644
index 0000000..58eacf1
--- /dev/null
+++ b/src/css/brush-controls.css
@@ -0,0 +1,43 @@
+#simplefog-brush-controls {
+ position: absolute;
+ left: 120px;
+ width: 180px;
+ text-align: center;
+}
+
+#simplefog-brush-controls h3,
+#simplefog-brush-controls .label {
+ color: #fff;
+ text-shadow: 1px 1px 0 #000;
+}
+
+#simplefog-brush-controls .label {
+ position: absolute;
+ top: 22px;
+}
+#simplefog-brush-controls .brush-opacity {
+ position: relative;
+}
+#simplefog-brush-controls .right-label {
+ right: 0;
+}
+#simplefog-brush-controls .left-label {
+ left: 0;
+}
+
+/* Webkit browsers */
+#simplefog-brush-controls input[type="range"]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ height: 24px;
+ margin-top: -10px;
+}
+
+/* Firefox */
+#simplefog-brush-controls input[type="range"]::-moz-range-thumb {
+ height: 24px;
+}
+
+/* IE */
+#simplefog-brush-controls input[type="range"]::-ms-thumb {
+ height: 24px;
+}
diff --git a/src/js/api.js b/src/js/api.js
new file mode 100644
index 0000000..a1a50f1
--- /dev/null
+++ b/src/js/api.js
@@ -0,0 +1,4 @@
+const API = {
+ // TODO this is useful for others module as well
+};
+export default API;
diff --git a/src/js/config.js b/src/js/config.js
new file mode 100644
index 0000000..7f09bfb
--- /dev/null
+++ b/src/js/config.js
@@ -0,0 +1,16 @@
+/*
+ * Global SimpleFog Configuration Options
+ */
+
+export default [
+ {
+ name: "migrationVersion",
+ data: {
+ name: "Simplefog Migration Version",
+ scope: "world",
+ config: false,
+ type: Number,
+ default: 0,
+ },
+ },
+];
diff --git a/src/js/constants.js b/src/js/constants.js
new file mode 100644
index 0000000..16521e1
--- /dev/null
+++ b/src/js/constants.js
@@ -0,0 +1,6 @@
+const CONSTANTS = {
+ MODULE_NAME: "simplefog",
+ PATH: `modules/simplefog/`,
+};
+CONSTANTS.PATH = `modules/${CONSTANTS.MODULE_NAME}/`;
+export default CONSTANTS;
diff --git a/src/js/controls.js b/src/js/controls.js
new file mode 100644
index 0000000..b64f4ef
--- /dev/null
+++ b/src/js/controls.js
@@ -0,0 +1,175 @@
+import SimplefogConfig from "../classes/SimplefogConfig.js";
+import BrushControls from "../classes/BrushControls.js";
+import { simplefogLogDebug } from "./helpers.js";
+
+/**
+ * Add control buttons
+ */
+Hooks.on("getSceneControlButtons", (controls) => {
+ simplefogLogDebug("controls.getSceneControlButtons");
+ if (!game.user.isGM) return;
+ controls.push({
+ name: "simplefog",
+ title: game.i18n.localize("SIMPLEFOG.sf"),
+ icon: "fas fa-cloud",
+ layer: "simplefog",
+ tools: [
+ {
+ name: "simplefogtoggle",
+ title: game.i18n.localize("SIMPLEFOG.onoff"),
+ icon: "fas fa-eye",
+ onClick: () => toggleSimpleFog(),
+ active: canvas.simplefog?.visible,
+ toggle: true,
+ },
+ {
+ name: "brush",
+ title: game.i18n.localize("SIMPLEFOG.brushTool"),
+ icon: "fas fa-paint-brush",
+ },
+ {
+ name: "grid",
+ title: game.i18n.localize("SIMPLEFOG.gridTool"),
+ icon: "fas fa-border-none",
+ },
+ {
+ name: "polygon",
+ title: game.i18n.localize("SIMPLEFOG.polygonTool"),
+ icon: "fas fa-draw-polygon",
+ },
+ {
+ name: "box",
+ title: game.i18n.localize("SIMPLEFOG.boxTool"),
+ icon: "far fa-square",
+ },
+ {
+ name: "ellipse",
+ title: game.i18n.localize("SIMPLEFOG.ellipseTool"),
+ icon: "far fa-circle",
+ },
+ // {
+ // name: "image",
+ // title: "Image Tool",
+ // icon: "far fa-image",
+ // },
+ {
+ name: "sceneConfig",
+ title: game.i18n.localize("SIMPLEFOG.sceneConfig"),
+ icon: "fas fa-cog",
+ onClick: () => {
+ new SimplefogConfig().render(true);
+ },
+ button: true,
+ },
+ {
+ name: "clearfog",
+ title: game.i18n.localize("SIMPLEFOG.reset"),
+ icon: "fas fa-trash",
+ onClick: () => {
+ const dg = new Dialog({
+ title: game.i18n.localize("SIMPLEFOG.reset"),
+ content: game.i18n.localize("SIMPLEFOG.confirmReset"),
+ buttons: {
+ reset: {
+ icon: '',
+ label: "Reset",
+ callback: () => canvas.simplefog.resetMask(),
+ },
+ blank: {
+ icon: '',
+ label: "Blank",
+ callback: () => canvas.simplefog.blankMask(),
+ },
+ cancel: {
+ icon: '',
+ label: "Cancel",
+ },
+ },
+ default: "reset",
+ });
+ dg.render(true);
+ },
+ button: true,
+ },
+ ],
+ activeTool: "brush",
+ });
+});
+
+/**
+ * Handles adding the custom brush controls pallet
+ * and switching active brush flag
+ */
+Hooks.on("renderSceneControls", (controls) => {
+ simplefogLogDebug("controls.renderSceneControls");
+ // Switching to layer
+ if (canvas.simplefog != null) {
+ if (controls.activeControl == "simplefog" && controls.activeTool != undefined) {
+ // Open brush tools if not already open
+ if (!$("#simplefog-brush-controls").length) new BrushControls().render(true);
+ // Set active tool
+ canvas.simplefog.setActiveTool(controls.activeTool);
+ }
+ // Switching away from layer
+ else {
+ // Clear active tool
+ canvas.simplefog.clearActiveTool();
+ // Remove brush tools if open
+ const bc = $("#simplefog-brush-controls")[0];
+ if (bc) bc.remove();
+ }
+ }
+});
+
+/**
+ * Sets Y position of the brush controls to account for scene navigation buttons
+ */
+function setBrushControlPos() {
+ const brushControl = $("#simplefog-brush-controls");
+ const navigation = $("#navigation");
+ if (brushControl.length && navigation.length) {
+ const h = navigation.height();
+ brushControl.css({ top: `${h + 30}px` });
+ canvas.simplefog.setActiveTool(canvas.simplefog.activeTool);
+ }
+}
+
+/**
+ * Toggle Simple Fog
+ */
+function toggleSimpleFog() {
+ simplefogLogDebug("controls.toggleSimpleFog");
+ if (game.settings.get("simplefog", "confirmFogDisable") && canvas.simplefog.getSetting("visible")) {
+ let dg = Dialog.confirm({
+ title: game.i18n.localize("SIMPLEFOG.disableFog"),
+ content: game.i18n.localize("SIMPLEFOG.confirmDisableFog"),
+ yes: () => toggleOffSimpleFog(),
+ no: () => cancelToggleSimpleFog(),
+ defaultYes: false,
+ rejectClose: true,
+ });
+ dg.then(undefined, cancelToggleSimpleFog);
+ } else {
+ toggleOffSimpleFog();
+ }
+}
+
+function toggleOffSimpleFog() {
+ canvas.simplefog.toggle();
+
+ //ToDo: Determine replacement for canvas.sight.refresh()
+ canvas.perception.refresh();
+}
+
+function cancelToggleSimpleFog(result = undefined) {
+ ui.controls.controls.find(({ name }) => name === "simplefog").tools[0].active = true;
+ ui.controls.render();
+}
+
+// Reset position when brush controls are rendered or sceneNavigation changes
+Hooks.on("renderBrushControls", setBrushControlPos);
+Hooks.on("renderSceneNavigation", setBrushControlPos);
+
+// Moved to simplefog.ready
+// addSimplefogControlToggleListener();
+// addSimplefogOpacityToggleListener();
diff --git a/src/js/helpers.js b/src/js/helpers.js
new file mode 100644
index 0000000..cb12572
--- /dev/null
+++ b/src/js/helpers.js
@@ -0,0 +1,245 @@
+import CONSTANTS from "./constants.js";
+
+// ======================================
+// LOGGER UTILITY
+// =======================================
+
+/**
+ * Prints formatted console msg if string, otherwise dumps object
+ * @param data {String | Object} Output to be dumped
+ * @param force {Boolean} Log output even if CONFIG.debug.simplefog = false
+ */
+export function simplefogLog(data, force = false) {
+ try {
+ const isDebugging = game.modules.get("_dev-mode")?.api?.getPackageDebugValue(CONSTANTS.MODULE_NAME);
+ if (force || isDebugging) {
+ // eslint-disable-next-line no-console
+ if (typeof data === "string") console.log(`Simplefog | ${data}`);
+ // eslint-disable-next-line no-console
+ else console.log("Simplefog |", data);
+ }
+ } catch (e) {}
+}
+
+export function simplefogLogDebug(...args) {
+ if (game.settings.get(CONSTANTS.MODULE_NAME, "debug")) {
+ console.debug("Simplefog-DEBUG |", ...args);
+ }
+}
+
+// ======================================
+// PIXI UTILITY
+// =======================================
+
+/**
+ * Converts web colors to base 16
+ * @param n {Hex} Web format color, f.x. #FF0000
+ * @return {Hex} Base 16 format color, f.x. 0xFF0000
+ */
+export function webToHex(n) {
+ return n.replace("#", "0x");
+}
+
+/**
+ * Converts a base16 color into a web color
+ * @param n {Hex} Base 16 Color, f.x. 0xFF0000
+ * @return {Hex} Web format color, f.x. #FF0000
+ */
+export function hexToWeb(n) {
+ return `${n}`.replace("0x", "#");
+}
+
+/**
+ * Converts a hexadecimal color to an integer percentage
+ * @param n {Hex} Base 16 Color, f.x. 0x000000
+ * @return {Integer} f.x 0
+ */
+export function hexToPercent(n) {
+ return Math.ceil((n / 0xffffff) * 100);
+}
+
+/**
+ * Converts an integer percent (0-100) to a hexadecimal greyscale color
+ * @param n {Number} 0-100 numeric input
+ * @return {Hex} Base 16 format color, f.x. 0xFFFFFF
+ */
+export function percentToHex(n) {
+ let c = Math.ceil(n * 2.55).toString(16);
+ if (c.length === 1) c = `0${c}`;
+ c = `0x${c}${c}${c}`;
+ return c;
+}
+
+/**
+ * Converts an object containing coordinate pair arrays into a single array of points for PIXI
+ * @param hex {Object} An object containing a set of [x,y] pairs
+ */
+export function hexObjsToArr(hex) {
+ const a = [];
+ hex.forEach((point) => {
+ a.push(point.x);
+ a.push(point.y);
+ });
+ // Append first point to end of array to complete the shape
+ a.push(hex[0].x);
+ a.push(hex[0].y);
+ return a;
+}
+
+/**
+ * Dumps a render of a given pixi container or texture to a new tab
+ */
+export function pixiDump(tgt = null) {
+ canvas.app.render();
+ const data = canvas.app.renderer.extract.base64(tgt);
+ const win = window.open();
+ win.document.write(`
`);
+}
+
+/**
+ * Gets a single pixel of texture data from GPU
+ * @param target {Object} PIXI Object to read from
+ * @param x {Integer} X Position to read
+ * @param y {Integer} Y Position to read
+ */
+export function readPixel(target, x = 0, y = 0) {
+ const { renderer } = canvas.app;
+ let resolution;
+ let renderTexture;
+ let generated = false;
+ if (target instanceof PIXI.RenderTexture) {
+ renderTexture = target;
+ } else {
+ renderTexture = renderer.generateTexture(target);
+ generated = true;
+ }
+ if (renderTexture) {
+ resolution = renderTexture.baseTexture.resolution;
+ renderer.renderTexture.bind(renderTexture);
+ }
+ const pixel = new Uint8Array(4);
+ // read pixels to the array
+ const { gl } = renderer;
+ gl.readPixels(x * resolution, y * resolution, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+ if (generated) {
+ renderTexture.destroy(true);
+ }
+ return pixel;
+}
+
+export function addSimplefogControlToggleListener() {
+ window.addEventListener("keydown", (event) => {
+ if (!areHotkeysEnabled() || !toggleControls(event) || !isOnCanvas(event)) {
+ return;
+ }
+
+ let controlName = getNewControlName();
+ let toolName = game.settings.get("simplefog", "toolHotKeys");
+
+ $("li.scene-control[data-control=" + controlName + "]")?.click();
+ setTimeout(function () {
+ $("ol.sub-controls.active li.control-tool[data-tool=" + toolName + "]")?.click();
+ }, 500);
+ });
+}
+
+/**
+ * @returns bool
+ */
+function areHotkeysEnabled() {
+ return game.settings.get("simplefog", "enableHotKeys");
+}
+
+/**
+ * @param {Event} event
+ * @returns bool
+ */
+function toggleControls(event) {
+ return event.key === "s" && event.ctrlKey;
+}
+
+/**
+ * @param {Event} event
+ * @returns bool
+ */
+function isOnCanvas(event) {
+ let $path = $(event.path[0]);
+ let allowedClasses = ["vtt", "game"];
+
+ for (let allowedClass of allowedClasses) {
+ if (!$path.hasClass(allowedClass)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * @returns string
+ */
+function getNewControlName() {
+ return isActiveControl() ? "token" : "simplefog";
+}
+
+/**
+ * @returns bool
+ */
+function isActiveControl() {
+ return getActiveControlName() === "simplefog";
+}
+
+/**
+ * @returns string
+ */
+function getActiveControlName() {
+ return ui.controls.activeControl;
+}
+
+export function addSimplefogOpacityToggleListener() {
+ window.addEventListener("keydown", (event) => {
+ if (!areHotkeysEnabled() || !toggleOpacity(event) || !isOnCanvas(event) || !isActiveControl()) {
+ return;
+ }
+
+ toggleSliderAndSubmitForm();
+ });
+}
+
+/**
+ * @param {Event} event
+ * @returns bool
+ */
+function toggleOpacity(event) {
+ return event.key === "t";
+}
+
+function toggleSliderAndSubmitForm() {
+ let $slider = $("input[name=brushOpacity]");
+ let brushOpacity = $slider.val();
+ $slider.val(brushOpacity === "100" ? 0 : 100);
+ $("form#simplefog-brush-controls-form").submit();
+}
+
+export function dmToGM(message) {
+ let whisper_to_dm = ChatMessage.create({
+ whisper: [game.user.id],
+ blind: true,
+ content: message,
+ });
+}
+
+export function dmToAllGM(message) {
+ var dm_ids = [];
+ for (let indexA = 0; indexA < game.users.length; indexA++) {
+ if (game.users[indexA].value.isGM) {
+ dm_ids.push(game.users[indexA].key);
+ }
+ }
+
+ let whisper_to_dm = ChatMessage.create({
+ whisper: dm_ids,
+ blind: true,
+ content: message,
+ });
+}
diff --git a/src/js/settings.js b/src/js/settings.js
new file mode 100644
index 0000000..7aa4f04
--- /dev/null
+++ b/src/js/settings.js
@@ -0,0 +1,194 @@
+import API from "./api.js";
+import CONSTANTS from "./constants.js";
+import config from "./config.js";
+import SimplefogLayer from "../classes/SimplefogLayer.js";
+export const registerSettings = function () {
+ game.settings.registerMenu(CONSTANTS.MODULE_NAME, "resetAllSettings", {
+ name: `${CONSTANTS.MODULE_NAME}.setting.reset.name`,
+ hint: `${CONSTANTS.MODULE_NAME}.setting.reset.hint`,
+ icon: "fas fa-coins",
+ type: ResetSettingsDialog,
+ restricted: true,
+ });
+ // =====================================================================
+ // Register global module settings
+ config.forEach((cfg) => {
+ game.settings.register("simplefog", cfg.name, cfg.data);
+ });
+
+ // Register global config settings
+ game.settings.register("simplefog", "confirmFogDisable", {
+ name: "Confirm Disabling of Scene Simplefog",
+ hint: "When enabled, a confirmation dialog will be displayed before Simplefog can be toggled off for a scene",
+ scope: "world",
+ config: true,
+ default: true,
+ type: Boolean,
+ });
+ game.settings.register("simplefog", "autoEnableSceneFog", {
+ name: "Auto Enable Scene Fog",
+ hint: "When enabled, Simplefog will automatically be enabled for a scene when it is first created.",
+ scope: "world",
+ config: true,
+ default: true,
+ type: Boolean,
+ });
+ game.settings.register("simplefog", "enableHotKeys", {
+ name: "Enable Simplefog Hotkeys",
+ hint: "When enabled, you will be able to quickly swap to the Simplefog control by using Ctrl+S and toggle the opacity using the hotkey 'T'",
+ scope: "world",
+ config: true,
+ default: false,
+ type: Boolean,
+ });
+ game.settings.register("simplefog", "toolHotKeys", {
+ name: "Hotkey Tool",
+ hint: "When Hotkeys is enabled, define which tool will be selected by using Ctrl+S",
+ scope: "world",
+ config: true,
+ default: "brush",
+ type: String,
+ choices: {
+ brush: "Brush",
+ grid: "Grid",
+ polygon: "Polygon",
+ box: "Box",
+ ellipse: "Ellipse",
+ },
+ });
+ game.settings.register("simplefog", "zIndex", {
+ name: "Simplefog Z-Index",
+ hint: "The z-index determines the order in which various layers are rendered within the Foundry canvas. A higher number will be rendered on top of lower numbered layers (and the objects on that layer). This allows for the adjustment of the z-index to allow for Simple Fog to be rendered above/below other layers; particularly ones added by other modules. Going below 200 will intermingle with Foundry layers such as the foreground image (200), tokens (100), etc... (Default: 220)",
+ scope: "world",
+ config: true,
+ default: 220,
+ type: Number,
+ onChange: SimplefogLayer.refreshZIndex,
+ });
+ // ========================================================================
+ game.settings.register(CONSTANTS.MODULE_NAME, "debug", {
+ name: `${CONSTANTS.MODULE_NAME}.setting.debug.name`,
+ hint: `${CONSTANTS.MODULE_NAME}.setting.debug.hint`,
+ scope: "client",
+ config: true,
+ default: false,
+ type: Boolean,
+ });
+ // const settings = defaultSettings();
+ // for (const [settingName, settingValue] of Object.entries(settings)) {
+ // game.settings.register(CONSTANTS.MODULE_NAME, settingName, settingValue);
+ // }
+ for (const [settingName, settingValue] of Object.entries(otherSettings)) {
+ game.settings.register(CONSTANTS.MODULE_NAME, settingName, settingValue);
+ }
+};
+class ResetSettingsDialog extends FormApplication {
+ constructor(...args) {
+ //@ts-ignore
+ super(...args);
+ //@ts-ignore
+ return new Dialog({
+ title: game.i18n.localize(`${CONSTANTS.MODULE_NAME}.dialogs.resetsettings.title`),
+ content:
+ '
' + + game.i18n.localize(`${CONSTANTS.MODULE_NAME}.dialogs.resetsettings.content`) + + "
", + buttons: { + confirm: { + icon: '', + label: game.i18n.localize(`${CONSTANTS.MODULE_NAME}.dialogs.resetsettings.confirm`), + callback: async () => { + await applyDefaultSettings(); + window.location.reload(); + }, + }, + cancel: { + icon: '', + label: game.i18n.localize(`${CONSTANTS.MODULE_NAME}.dialogs.resetsettings.cancel`), + }, + }, + default: "cancel", + }); + } + async _updateObject(event, formData) { + // do nothing + } +} +async function applyDefaultSettings() { + const settings = defaultSettings(true); + // for (const [name, data] of Object.entries(settings)) { + // await game.settings.set(CONSTANTS.MODULE_NAME, name, data.default); + // } + const settings2 = otherSettings(true); + for (const [name, data] of Object.entries(settings2)) { + //@ts-ignore + await game.settings.set(CONSTANTS.MODULE_NAME, name, data.default); + } +} +function defaultSettings(apply = false) { + return { + // TODO this is usually useful for maintain some hidden settings between versions + }; +} +function otherSettings(apply = false) { + return { + // Register global config settings + confirmFogDisable: { + name: "Confirm Disabling of Scene Simplefog", + hint: "When enabled, a confirmation dialog will be displayed before Simplefog can be toggled off for a scene", + scope: "world", + config: true, + default: true, + type: Boolean, + }, + autoEnableSceneFog: { + name: "Auto Enable Scene Fog", + hint: "When enabled, Simplefog will automatically be enabled for a scene when it is first created.", + scope: "world", + config: true, + default: true, + type: Boolean, + }, + enableHotKeys: { + name: "Enable Simplefog Hotkeys", + hint: "When enabled, you will be able to quickly swap to the Simplefog control by using Ctrl+S and toggle the opacity using the hotkey 'T'", + scope: "world", + config: true, + default: false, + type: Boolean, + }, + toolHotKeys: { + name: "Hotkey Tool", + hint: "When Hotkeys is enabled, define which tool will be selected by using Ctrl+S", + scope: "world", + config: true, + default: "brush", + type: String, + choices: { + brush: "Brush", + grid: "Grid", + polygon: "Polygon", + box: "Box", + ellipse: "Ellipse", + }, + }, + zIndex: { + name: "Simplefog Z-Index", + hint: "The z-index determines the order in which various layers are rendered within the Foundry canvas. A higher number will be rendered on top of lower numbered layers (and the objects on that layer). This allows for the adjustment of the z-index to allow for Simple Fog to be rendered above/below other layers; particularly ones added by other modules. Going below 200 will intermingle with Foundry layers such as the foreground image (200), tokens (100), etc... (Default: 220)", + scope: "world", + config: true, + default: 220, + type: Number, + onChange: SimplefogLayer.refreshZIndex, + }, + debug: { + name: `${CONSTANTS.MODULE_NAME}.setting.debug.name`, + hint: `${CONSTANTS.MODULE_NAME}.setting.debug.hint`, + scope: "client", + config: true, + default: false, + type: Boolean, + }, + // + }; +} diff --git a/src/js/sightLayerUpdate.js b/src/js/sightLayerUpdate.js new file mode 100644 index 0000000..43c9315 --- /dev/null +++ b/src/js/sightLayerUpdate.js @@ -0,0 +1,68 @@ +/* + * Monkeypatch for core canvas.sight.update() that implements autovisibility + */ +import { readPixel } from "./helpers.js"; + +/* + * The token's worldTransform is not updated yet when this is called + * probably because the token will be animated, so we need to convert + * the token's grid position to world coords since grid position updates + * immediately + * + * If there is a more straight forward way to do this it would be nice! + */ +function _getCanvasCoords(placeable) { + const { grid } = canvas.scene.data; + // Check if placeable is a door + const p = placeable.data.door ? placeable.doorControl : placeable.data; + + try { + return { + x: Math.round(grid / 2 + p.x), + y: Math.round(grid / 2 + p.y), + }; + } catch (error) { + return { + x: Math.round(grid / 2), + y: Math.round(grid / 2), + }; + } +} + +/* + * Checks mask opacity at location of placeable and sets visibility + */ +function _setPlaceableVisibility(placeable) { + if (placeable.observer && !game.user.isGM) return; + const pos = _getCanvasCoords(placeable); + const p = readPixel(canvas.simplefog.maskTexture, pos.x, pos.y); + const pAvg = (p[0] + p[1] + p[2]) / 3; + const v = pAvg / 255 < canvas.scene.getFlag("simplefog", "vThreshold"); + // if this is a door, we set vis on it's control object instead + if (placeable.data.door) placeable.doorControl.visible = v; + else placeable.visible = v; +} + +/* + * Extends canvas.sight.update() to set visibility for placeables based on simplefog + */ +export default function sightLayerUpdate() { + // Skip checking placeables if simplefog not visible anyway + if (!canvas.simplefog.visible) return; + // Skip if autoVisibility not enabled for this scene + if (!canvas.scene.getFlag("simplefog", "autoVisibility")) return; + // Skip if user is GM and autoVisGM Disabled + if (game.user.isGM && !canvas.scene.getFlag("simplefog", "autoVisGM")) return; + // loop through placeables + canvas.tokens.placeables.forEach((placeable) => { + _setPlaceableVisibility(placeable); + }); + canvas.notes.placeables.forEach((placeable) => { + _setPlaceableVisibility(placeable); + }); + canvas.walls.placeables.forEach((placeable) => { + if (placeable.data.door) { + _setPlaceableVisibility(placeable); + } + }); +} diff --git a/src/js/simplefog.js b/src/js/simplefog.js new file mode 100644 index 0000000..f6f6494 --- /dev/null +++ b/src/js/simplefog.js @@ -0,0 +1,114 @@ +import SimplefogLayer from "../classes/SimplefogLayer.js"; +import SimplefogMigrations from "../classes/SimplefogMigrations.js"; +import config from "./config.js"; +import { + simplefogLog, + simplefogLogDebug, + addSimplefogControlToggleListener, + addSimplefogOpacityToggleListener, +} from "./helpers.js"; +import SimplefogHUDControlLayer from "../classes/SimplefogHUDControlLayer.js"; +import SimplefogNotification from "../classes/SimplefogNotification.js"; +import API from "./api.js"; +import { setApi } from "../main.js"; + +export const initHooks = () => { + // eslint-disable-next-line no-console + simplefogLog("Initializing simplefog", true); + + if (isNewerVersion(game.version, "10")) { + CONFIG.Canvas.layers.simplefog = { group: "interface", layerClass: SimplefogLayer }; + CONFIG.Canvas.layers.simplefogHUDControls = { group: "interface", layerClass: SimplefogHUDControlLayer }; + + Object.defineProperty(canvas, "simplefog", { + value: new SimplefogLayer(), + configurable: true, + writable: true, + enumerable: false, + }); + Object.defineProperty(canvas, "simplefogHUDControls", { + value: new SimplefogHUDControlLayer(), + configurable: true, + writable: true, + enumerable: false, + }); + } +}; + +export const setupHooks = () => { + // Set api the standard league way + //@ts-ignore + setApi(API); +}; + +/* + * Apply compatibility patches + */ +export const readyHooks = async () => { + // Check if any migrations need to be performed + SimplefogMigrations.check(); + + // Fix simplefog zIndex + + canvas.simplefog.refreshZIndex(); + // ToDo: why is this set below??? + //canvas.simplefogHUDControls.zIndex = canvas.simplefog.getSetting('layerZindex') - 1; + + // Move object hud to tokens layer + game.canvas.controls.hud.setParent(game.canvas.simplefogHUDControls); + + // Check if new version; if so send DM to GM + SimplefogNotification.checkVersion(); + + //Hooks.on('sightRefresh', sightLayerUpdate); + + //ToDo: Determine replacement for canvas.sight.refresh() + canvas.perception.refresh(); + + addSimplefogControlToggleListener(); + addSimplefogOpacityToggleListener(); +}; + +Hooks.once("canvasInit", () => { + simplefogLogDebug("simplefog.canvasInit"); + if (isNewerVersion(game.version, "10")) { + canvas.simplefog.canvasInit(); + } else if (isNewerVersion(game.version, "9")) { + CONFIG.Canvas.layers["simplefog"] = { + layerClass: SimplefogLayer, + group: "primary", + }; + CONFIG.Canvas.layers["simplefogHUDControls"] = { + layerClass: SimplefogHUDControlLayer, + group: "primary", + }; + Object.defineProperty(canvas, "simplefog", { + value: new SimplefogLayer(), + configurable: true, + writable: true, + enumerable: false, + }); + Object.defineProperty(canvas, "simplefogHUDControls", { + value: new SimplefogHUDControlLayer(), + configurable: true, + writable: true, + enumerable: false, + }); + canvas.primary.addChild(canvas.simplefog); + canvas.primary.addChild(canvas.simplefogHUDControls); + } else { + canvas.simplefog = new SimplefogLayer(); + canvas.stage.addChild(canvas.simplefog); + canvas.simplefogHUDControls = new simplefogHUDControls(); + canvas.stage.addChild(canvas.simplefogHUDControls); + + let theLayers = Canvas.layers; + theLayers.simplefog = SimplefogLayer; + theLayers.simplefogHUDControls = SimplefogHUDControlLayer; + Object.defineProperty(Canvas, "layers", { + get: function () { + return theLayers; + }, + }); + } +}); diff --git a/src/languages/.DS_Store b/src/languages/.DS_Store new file mode 100644 index 0000000..d756364 Binary files /dev/null and b/src/languages/.DS_Store differ diff --git a/src/languages/en.json b/src/languages/en.json new file mode 100644 index 0000000..7fa50ef --- /dev/null +++ b/src/languages/en.json @@ -0,0 +1,72 @@ +{ + "SIMPLEFOG.brushOpacity": "Brush Opacity", + "SIMPLEFOG.brushSize": "Brush Size", + "SIMPLEFOG.hide": "Hide", + "SIMPLEFOG.reveal": "Reveal", + + "SIMPLEFOG.gmFogSettings": "GM Fog Settings", + "SIMPLEFOG.gmColorTint": "Color", + "SIMPLEFOG.gmColorAlpha": "Color Opacity", + + "SIMPLEFOG.playerFogSettings": "Player Fog Settings", + "SIMPLEFOG.playerColorTint": "Color", + "SIMPLEFOG.playerColorAlpha": "Color Opacity", + + "SIMPLEFOG.fogImageOverlaySettings": "Fog Overlay Image", + "SIMPLEFOG.fogImageOverlay": "Image", + "SIMPLEFOG.fogImageOverlayNotes": "Selected image will display above/below the tint color. This image should be the same height and width of the scene background image.", + "SIMPLEFOG.fogImageOverlayGMAlpha": "GM Image Opacity", + "SIMPLEFOG.fogImageOverlayPlayerAlpha": "Player Image Opacity", + "SIMPLEFOG.fogImageOverlayZIndex": "Mask Sorting Order", + + "SIMPLEFOG.filterSettings": "Filter Settings", + "SIMPLEFOG.blurEnable": "Enable Reveal Blur", + "SIMPLEFOG.blurRadius": "Blur Radius", + "SIMPLEFOG.blurQuality": "Blur Quality", + "SIMPLEFOG.blurQualityDesc": "Higher blur quality improves the appearance of the blur effect, but may cause slower performance.", + "SIMPLEFOG.transitionSettings": "Transition Settings", + "SIMPLEFOG.enableTransitions": "Enable Transitions", + "SIMPLEFOG.transitionSpeed": "Transition Speed", + "SIMPLEFOG.visibilitySettings": "Visibility Settings", + "SIMPLEFOG.enableAutovis": "Enable Automatic Visibility", + "SIMPLEFOG.enableForGM": "Enable for GM", + "SIMPLEFOG.enableAutoFog": "Enable fog Automatically for new scenes", + "SIMPLEFOG.visThreshold": "Visibility Threshold", + "SIMPLEFOG.saveAsDef": "Save current settings as default", + "SIMPLEFOG.ok": "OK", + "SIMPLEFOG.sf": "Simple Fog", + "SIMPLEFOG.onoff": "Enable/Disable Simple Fog", + + "SIMPLEFOG.brushTool": "Brush Tool", + "SIMPLEFOG.gridTool": "Grid Tool", + "SIMPLEFOG.polygonTool": "Polygon Tool", + "SIMPLEFOG.boxTool": "Box Tool", + "SIMPLEFOG.ellipseTool": "Ellipse Tool", + "SIMPLEFOG.sceneConfig": "Scene Configuration", + "SIMPLEFOG.reset": "Reset Simple Fog", + "SIMPLEFOG.confirmReset": "Are you sure? Fog of war will be reset.", + "SIMPLEFOG.autoFogSettings": "AutoFog Settings", + "SIMPLEFOG.autoFogNotes": "When enabled AND saved as default, fog will automatically render when you create a scene. Please check box and click 'Save current setings as defualt' in order to enable. Do the same to disable", + + "SIMPLEFOG.advancedSettings": "Advanced Settings", + "SIMPLEFOG.configurableZindex": "Simple Fog Z-Index", + "SIMPLEFOG.configurableZindexNotes": "The z-index determines the order in which various layers are rendered within the Foundry canvas. A higher number will be rendered on top of lower numbered layers (and the objects on that layer). This allows for the adjustment of the z-index to allow for Simple Fog to be rendered above/below other layers; particularly ones added by other modules. Going below 200 will intermingle with Foundry layers such as the foreground image (200), tokens (100), etc... (Default: 220)", + + "SIMPLEFOG.confirmDisablingFogSettings": "Toggle Confirmation Settings", + "SIMPLEFOG.confirmDisablingFog": "Enable confirmation to disable Simple Fog.", + "SIMPLEFOG.confirmDisablingFogNotes": "When disabling Simple Fog for a scene, present a dialog to confirm disabling before doing so.", + "SIMPLEFOG.confirmDisableFog": "Are you sure you want to toggle off Simple Fog for this scene?", + "SIMPLEFOG.disableFog": "Disable Simple Fog", + + "SIMPLEFOG.hotkeySettings": "Hotkey Settings", + "SIMPLEFOG.enableHotkeys": "Enable hotkeys", + "SIMPLEFOG.hotkeyNotes": "When enabled, you will be able to quickly swap to the simplefog control by using Ctrl+S and toggle the opacity using the hotkey 'T'", + "SIMPLEFOG.hotKeyToolDesc": "Hotkey Tool", + "SIMPLEFOG.hotKeyToolNotes": "Determine which tool will be selected when hotkey is activated.", + + "SIMPLEFOG.autoVisNotes": "When enabled, Automatic Visibility will show/hide tokens based on fog opacity level at their location based on the threshold setting. Brush color changes to green/red to indicate whether a token would be visible.", + + "SIMPLEFOG.versionNotification": "Simple Fog 0.3.4This release includes:
", + + "SIMPLEFOG.migration2Notification": "Simple Fog Data MigrationThe Simple Fog data has been migrated to a format supporting v3. It is HIGHLY recommended to review all scenes and fog visibility, both from a GM and a Player view before showing the scene to players." +} diff --git a/src/languages/es.json b/src/languages/es.json new file mode 100644 index 0000000..2f19bbc --- /dev/null +++ b/src/languages/es.json @@ -0,0 +1,75 @@ +{ + "I18N.LANGUAGE": "Español", + "I18N.MAINTAINERS": "@Viriato139ac#0342", + + "SIMPLEFOG.brushOpacity": "Opacidad del pincel", + "SIMPLEFOG.brushSize": "Tamaño del pincel", + "SIMPLEFOG.hide": "Ocultar", + "SIMPLEFOG.reveal": "Mostrar", + + "SIMPLEFOG.gmFogSettings": "Ajustes de niebla del GM", + "SIMPLEFOG.gmColorTint": "Color", + "SIMPLEFOG.gmColorAlpha": "Opacidad", + + "SIMPLEFOG.playerFogSettings": "Ajustes de niebla del jugador", + "SIMPLEFOG.playerColorTint": "Color", + "SIMPLEFOG.playerColorAlpha": "Color Opacidad", + + "SIMPLEFOG.fogImageOverlaySettings": "Imagen de superposición de niebla", + "SIMPLEFOG.fogImageOverlay": "Imagen", + "SIMPLEFOG.fogImageOverlayNotes": "La imagen seleccionada se mostrará arriba/abajo del color del tinte. Esta imagen debe tener la misma altura y anchura que la imagen de fondo de la escena.", + "SIMPLEFOG.fogImageOverlayGMAlpha": "Opacidad de imagen GM", + "SIMPLEFOG.fogImageOverlayPlayerAlpha": "Opacidad de la imagen del jugador", + "SIMPLEFOG.fogImageOverlayZIndex": "Orden de clasificación de máscaras", + + "SIMPLEFOG.filterSettings": "Ajustes del filtro", + "SIMPLEFOG.blurEnable": "Habilitar Revelar desenfoque", + "SIMPLEFOG.blurRadius": "Radio del difuminado", + "SIMPLEFOG.blurQuality": "Calidad del difuminado", + "SIMPLEFOG.blurQualityDesc": "Cuanto mayor sea la calidad mejor será la apariencia del efecto de difuminado, sin embargo, puede causar en que baje el rendimiento", + "SIMPLEFOG.transitionSettings": "Ajustes de transición", + "SIMPLEFOG.enableTransitions": "Habilitar transiciones", + "SIMPLEFOG.transitionSpeed": "Velocidad de la transición", + "SIMPLEFOG.visibilitySettings": "Ajustes de visibilidad", + "SIMPLEFOG.enableAutovis": "Habilitar visibilidad automática", + "SIMPLEFOG.enableForGM": "Habilitar para el GM", + "SIMPLEFOG.enableAutoFog": "Habilitar la niebla automáticamente para las nuevas escenas", + "SIMPLEFOG.visThreshold": "Umbral de visibilidad", + "SIMPLEFOG.saveAsDef": "Guardar como por defecto los ajustes actuales", + "SIMPLEFOG.ok": "OK", + "SIMPLEFOG.sf": "Simple Fog", + "SIMPLEFOG.onoff": "Habilitar/deshabilitar Simple Fog", + + "SIMPLEFOG.brushTool": "Herramienta pincel", + "SIMPLEFOG.gridTool": "Herramienta rejilla", + "SIMPLEFOG.polygonTool": "Herramienta polígono", + "SIMPLEFOG.boxTool": "Herramienta rectángulo", + "SIMPLEFOG.ellipseTool": "Herramienta elipse", + "SIMPLEFOG.sceneConfig": "Configuración de la escena", + "SIMPLEFOG.reset": "Reiniciar niebla", + "SIMPLEFOG.confirmReset": "¿Está seguro? Se reiniciará la niebla de guerra", + "SIMPLEFOG.autoFogSettings": "Ajustes de niebla automática", + "SIMPLEFOG.autoFogNotes": "Cuando se activa y se guarda por defecto, la niebla se generará automáticamente cuando cree la escena. Por favor, active esta opción y pulse 'Guardar como por defecto los ajustes actuales' para habilitarlo. Realice el mismo proceso, pero al contrario, para deshabilitarlo", + + "SIMPLEFOG.advancedSettings": "Ajustes avanzados", + "SIMPLEFOG.configurableZindex": "Índice Z de niebla simple", + "SIMPLEFOG.configurableZindexNotes": "El índice z determina el orden en el que se representan varias capas dentro del lienzo de Foundry. Se representará un número más alto sobre las capas con números más bajos (y los objetos en esa capa). Esto permite el ajuste del índice z para permitir que Simple Fog se represente por encima o por debajo de otras capas; particularmente los agregados por otros módulos. Ir por debajo de 200 se entremezclará con las capas de Foundry, como la imagen de primer plano (200), tokens (100), etc. (Predeterminado: 220)", + + "SIMPLEFOG.confirmDisablingFogSettings": "Confirmar la desactivación de la niebla simple", + "SIMPLEFOG.confirmDisablingFog": "Habilite la confirmación para deshabilitar la niebla simple.", + "SIMPLEFOG.confirmDisablingFogNotes": "Al deshabilitar niebla para una escena, presente un cuadro de diálogo para confirmar la desactivación antes de hacerlo.", + "SIMPLEFOG.confirmDisableFog": "¿Estás seguro de que quieres desactivar Simple Fog para esta escena?", + "SIMPLEFOG.disableFog": "Desactivar niebla", + + "SIMPLEFOG.hotkeySettings": "Configuración de teclas de acceso rápido", + "SIMPLEFOG.enableHotkeys": "Habilitar teclas de acceso rápido", + "SIMPLEFOG.hotkeyNotes": "Cuando esté habilitado, podrá cambiar rápidamente al control de niebla simple usando Ctrl + S y alternar la opacidad usando la tecla de acceso directo 'T'", + "SIMPLEFOG.hotKeyToolDesc": "Herramienta de teclas de acceso directo", + "SIMPLEFOG.hotKeyToolNotes": "Determine qué herramienta se seleccionará cuando se active la tecla de acceso directo.", + + "SIMPLEFOG.autoVisNotes": "Cuando se activa, la visibilidad automática mostrará/ocultará los iconos en base al nivel de opacidad de la niebla en su localización y el umbral que se especifique. El color del pincel cambia a verde/rojo para indicar si el token es visible", + + "SIMPLEFOG.versionNotification": "Simple Fog 0.3.4
Esta versión incluye:
", + + "SIMPLEFOG.migration2Notification": "Migración de datos de Simple FogLos datos de Simple Fog se han migrado a un formato compatible con v3. Se recomienda MUY revisar todas las escenas y la visibilidad de la niebla, tanto desde la vista del DJ como del jugador, antes de mostrar la escena a los jugadores." +} diff --git a/src/languages/ja.json b/src/languages/ja.json new file mode 100644 index 0000000..7ee2ed7 --- /dev/null +++ b/src/languages/ja.json @@ -0,0 +1,72 @@ +{ + "SIMPLEFOG.brushOpacity": "ブラシの濃度", + "SIMPLEFOG.brushSize": "ブラシサイズ", + "SIMPLEFOG.hide": "濃い", + "SIMPLEFOG.reveal": "薄い", + + "SIMPLEFOG.gmFogSettings": "霧の設定(GM用)", + "SIMPLEFOG.gmColorTint": "色", + "SIMPLEFOG.gmColorAlpha": "濃度", + + "SIMPLEFOG.playerFogSettings": "霧の設定(プレイヤー用)", + "SIMPLEFOG.playerColorTint": "色", + "SIMPLEFOG.playerColorAlpha": "色の不透明度", + + "SIMPLEFOG.fogImageOverlaySettings": "フォグ オーバーレイ イメージ", + "SIMPLEFOG.fogImageOverlay": "画像", + "SIMPLEFOG.fogImageOverlayNotes": "選択した画像は、色合いの上/下に表示されます。 この画像は、シーンの背景画像と同じ高さと幅である必要があります。", + "SIMPLEFOG.fogImageOverlayGMAlpha": "GM 画像の不透明度", + "SIMPLEFOG.fogImageOverlayPlayerAlpha": "プレーヤー画像の不透明度", + "SIMPLEFOG.fogImageOverlayZIndex": "マスクのソート順", + + "SIMPLEFOG.filterSettings": "フィルター設定", + "SIMPLEFOG.blurEnable": "リビールブラーを有効にする", + "SIMPLEFOG.blurRadius": "ぼかし半径", + "SIMPLEFOG.blurQuality": "ぼかし品質", + "SIMPLEFOG.blurQualityDesc": "ぼかし品質が高いと見た目は良くなりますが、パフォーマンスの低下を招くことがあります。", + "SIMPLEFOG.transitionSettings": "トランジション設定", + "SIMPLEFOG.enableTransitions": "トランジションを有効にする", + "SIMPLEFOG.transitionSpeed": "トランジション速度", + "SIMPLEFOG.visibilitySettings": "可視性の設定", + "SIMPLEFOG.enableAutovis": "自動可視化を有効にする", + "SIMPLEFOG.enableForGM": "GMにも適用する", + "SIMPLEFOG.enableAutoFog": "新しいシーンでフォグを自動的に有効にします。", + "SIMPLEFOG.visThreshold": "視認性の閾値", + "SIMPLEFOG.saveAsDef": "この設定をデフォルトに保存", + "SIMPLEFOG.ok": "適用", + "SIMPLEFOG.sf": "Simple Fog", + "SIMPLEFOG.onoff": "霧のオン/オフ", + + "SIMPLEFOG.brushTool": "ブラシツール", + "SIMPLEFOG.gridTool": "グリッドツール", + "SIMPLEFOG.polygonTool": "多角形ツール", + "SIMPLEFOG.boxTool": "ボックスツール", + "SIMPLEFOG.ellipseTool": "楕円ツール", + "SIMPLEFOG.sceneConfig": "シーン設定", + "SIMPLEFOG.reset": "霧のリセット", + "SIMPLEFOG.confirmReset": "霧が初期化されます。本当によろしいですか?", + "SIMPLEFOG.autoFogSettings": "オートフォグ設定", + "SIMPLEFOG.autoFogNotes": "この機能を有効にしてデフォルトで保存すると、シーンを作成時にフォグが自動的にレンダリングされます。有効にするにはチェックボックスにチェックを入れ、「この設定をデフォルトに保存」をクリックしてください。無効にする場合も同様です。", + + "SIMPLEFOG.advancedSettings": "高度な設定", + "SIMPLEFOG.configurableZindex": "シンプルフォグZインデックス", + "SIMPLEFOG.configurableZindexNotes": "z-indexは、Foundryキャンバス内でさまざまなレイヤーがレンダリングされる順序を決定します。 番号の小さいレイヤー(およびそのレイヤー上のオブジェクト)の上に、番号の大きいものがレンダリングされます。 これにより、z-indexを調整して、SimpleFogを他のレイヤーの上/下にレンダリングできるようになります。 特に他のモジュールによって追加されたもの。 200を下回ると、前景画像(200)、トークン(100)などのFoundryレイヤーと混ざり合います...(デフォルト:220)", + + "SIMPLEFOG.confirmDisablingFogSettings": "シンプルフォグの無効化を確認する", + "SIMPLEFOG.confirmDisablingFog": "確認を有効にして、シンプルフォグを無効にします。", + "SIMPLEFOG.confirmDisablingFogNotes": "シーンのシンプルフォグを無効にする場合は、無効にする前に無効を確認するダイアログを表示します。", + "SIMPLEFOG.confirmDisableFog": "このシーンでSimpleFogをオフにしてよろしいですか?", + "SIMPLEFOG.disableFog": "シンプルフォグを無効にする", + + "SIMPLEFOG.hotkeySettings": "ホットキー設定", + "SIMPLEFOG.enableHotkeys": "ホットキーを有効にする", + "SIMPLEFOG.hotkeyNotes": "有効にすると、Ctrl + Sを使用してsimplefogコントロールにすばやく切り替え、ホットキー「T」を使用して不透明度を切り替えることができます。", + "SIMPLEFOG.hotKeyToolDesc": "ホットキーツール", + "SIMPLEFOG.hotKeyToolNotes": "ホットキーがアクティブ化されたときに選択されるツールを決定します。", + + "SIMPLEFOG.autoVisNotes": "自動可視化を有効にすると、その場所のトークンの表示/非表示が、閾値として設定した霧の濃度に基づいて決定されるようになります。非表示となる濃度では、ブラシの色が緑から赤に変化してそれを知らせます。", + + "SIMPLEFOG.versionNotification": "Simple Fog 0.3.4
このリリースには以下が含まれます:
", + + "SIMPLEFOG.migration2Notification": "Simple Fog データの移行Simple Fog データは、v3 をサポートする形式に移行されました。 プレーヤーにシーンを表示する前に、GM ビューとプレーヤー ビューの両方から、すべてのシーンと霧の可視性を確認することを強くお勧めします。" +} diff --git a/src/libs/hexagons.js b/src/libs/hexagons.js new file mode 100644 index 0000000..47b0b13 --- /dev/null +++ b/src/libs/hexagons.js @@ -0,0 +1,236 @@ +/* eslint-disable */ +// Generated code -- CC0 -- No Rights Reserved -- http://www.redblobgames.com/grids/hexagons/ +export class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } +} +export class Hex { + constructor(q, r, s) { + this.q = q; + this.r = r; + this.s = s; + if (Math.round(q + r + s) !== 0) throw "q + r + s must be 0"; + } + add(b) { + return new Hex(this.q + b.q, this.r + b.r, this.s + b.s); + } + subtract(b) { + return new Hex(this.q - b.q, this.r - b.r, this.s - b.s); + } + scale(k) { + return new Hex(this.q * k, this.r * k, this.s * k); + } + rotateLeft() { + return new Hex(-this.s, -this.q, -this.r); + } + rotateRight() { + return new Hex(-this.r, -this.s, -this.q); + } + static direction(direction) { + return Hex.directions[direction]; + } + neighbor(direction) { + return this.add(Hex.direction(direction)); + } + diagonalNeighbor(direction) { + return this.add(Hex.diagonals[direction]); + } + len() { + return (Math.abs(this.q) + Math.abs(this.r) + Math.abs(this.s)) / 2; + } + distance(b) { + return this.subtract(b).len(); + } + round() { + var qi = Math.round(this.q); + var ri = Math.round(this.r); + var si = Math.round(this.s); + var q_diff = Math.abs(qi - this.q); + var r_diff = Math.abs(ri - this.r); + var s_diff = Math.abs(si - this.s); + if (q_diff > r_diff && q_diff > s_diff) { + qi = -ri - si; + } else if (r_diff > s_diff) { + ri = -qi - si; + } else { + si = -qi - ri; + } + return new Hex(qi, ri, si); + } + lerp(b, t) { + return new Hex(this.q * (1.0 - t) + b.q * t, this.r * (1.0 - t) + b.r * t, this.s * (1.0 - t) + b.s * t); + } + linedraw(b) { + var N = this.distance(b); + var a_nudge = new Hex(this.q + 1e-6, this.r + 1e-6, this.s - 2e-6); + var b_nudge = new Hex(b.q + 1e-6, b.r + 1e-6, b.s - 2e-6); + var results = []; + var step = 1.0 / Math.max(N, 1); + for (var i = 0; i <= N; i++) { + results.push(a_nudge.lerp(b_nudge, step * i).round()); + } + return results; + } +} +Hex.directions = [ + new Hex(1, 0, -1), + new Hex(1, -1, 0), + new Hex(0, -1, 1), + new Hex(-1, 0, 1), + new Hex(-1, 1, 0), + new Hex(0, 1, -1), +]; +Hex.diagonals = [ + new Hex(2, -1, -1), + new Hex(1, -2, 1), + new Hex(-1, -1, 2), + new Hex(-2, 1, 1), + new Hex(-1, 2, -1), + new Hex(1, 1, -2), +]; +export class OffsetCoord { + constructor(col, row) { + this.col = col; + this.row = row; + } + static qoffsetFromCube(offset, h) { + var col = h.q; + var row = h.r + (h.q + offset * (h.q & 1)) / 2; + if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) { + throw "offset must be EVEN (+1) or ODD (-1)"; + } + return new OffsetCoord(col, row); + } + static qoffsetToCube(offset, h) { + var q = h.col; + var r = h.row - (h.col + offset * (h.col & 1)) / 2; + var s = -q - r; + if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) { + throw "offset must be EVEN (+1) or ODD (-1)"; + } + return new Hex(q, r, s); + } + static roffsetFromCube(offset, h) { + var col = h.q + (h.r + offset * (h.r & 1)) / 2; + var row = h.r; + if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) { + throw "offset must be EVEN (+1) or ODD (-1)"; + } + return new OffsetCoord(col, row); + } + static roffsetToCube(offset, h) { + var q = h.col - (h.row + offset * (h.row & 1)) / 2; + var r = h.row; + var s = -q - r; + if (offset !== OffsetCoord.EVEN && offset !== OffsetCoord.ODD) { + throw "offset must be EVEN (+1) or ODD (-1)"; + } + return new Hex(q, r, s); + } +} +OffsetCoord.EVEN = 1; +OffsetCoord.ODD = -1; +export class DoubledCoord { + constructor(col, row) { + this.col = col; + this.row = row; + } + static qdoubledFromCube(h) { + var col = h.q; + var row = 2 * h.r + h.q; + return new DoubledCoord(col, row); + } + qdoubledToCube() { + var q = this.col; + var r = (this.row - this.col) / 2; + var s = -q - r; + return new Hex(q, r, s); + } + static rdoubledFromCube(h) { + var col = 2 * h.q + h.r; + var row = h.r; + return new DoubledCoord(col, row); + } + rdoubledToCube() { + var q = (this.col - this.row) / 2; + var r = this.row; + var s = -q - r; + return new Hex(q, r, s); + } +} +export class Orientation { + constructor(f0, f1, f2, f3, b0, b1, b2, b3, start_angle) { + this.f0 = f0; + this.f1 = f1; + this.f2 = f2; + this.f3 = f3; + this.b0 = b0; + this.b1 = b1; + this.b2 = b2; + this.b3 = b3; + this.start_angle = start_angle; + } +} +export class Layout { + constructor(orientation, size, origin) { + this.orientation = orientation; + this.size = size; + this.origin = origin; + } + hexToPixel(h) { + var M = this.orientation; + var size = this.size; + var origin = this.origin; + var x = (M.f0 * h.q + M.f1 * h.r) * size.x; + var y = (M.f2 * h.q + M.f3 * h.r) * size.y; + return new Point(x + origin.x, y + origin.y); + } + pixelToHex(p) { + var M = this.orientation; + var size = this.size; + var origin = this.origin; + var pt = new Point((p.x - origin.x) / size.x, (p.y - origin.y) / size.y); + var q = M.b0 * pt.x + M.b1 * pt.y; + var r = M.b2 * pt.x + M.b3 * pt.y; + return new Hex(q, r, -q - r); + } + hexCornerOffset(corner) { + var M = this.orientation; + var size = this.size; + var angle = (2.0 * Math.PI * (M.start_angle - corner)) / 6.0; + return new Point(size.x * Math.cos(angle), size.y * Math.sin(angle)); + } + polygonCorners(h) { + var corners = []; + var center = this.hexToPixel(h); + for (var i = 0; i < 6; i++) { + var offset = this.hexCornerOffset(i); + corners.push(new Point(center.x + offset.x, center.y + offset.y)); + } + return corners; + } +} +Layout.pointy = new Orientation( + Math.sqrt(3.0), + Math.sqrt(3.0) / 2.0, + 0.0, + 3.0 / 2.0, + Math.sqrt(3.0) / 3.0, + -1.0 / 3.0, + 0.0, + 2.0 / 3.0, + 0.5 +); +Layout.flat = new Orientation( + 3.0 / 2.0, + 0.0, + Math.sqrt(3.0) / 2.0, + Math.sqrt(3.0), + 2.0 / 3.0, + 0.0, + -1.0 / 3.0, + Math.sqrt(3.0) / 3.0, + 0.0 +); diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..9f1f9ed --- /dev/null +++ b/src/main.js @@ -0,0 +1,86 @@ +/** + * This is your TypeScript entry file for Foundry VTT. + * Register custom settings, sheets, and constants using the Foundry API. + * Change this heading to be more descriptive to your module, or remove it. + * Author: [your name] + * Content License: [copyright and-or license] If using an existing system + * you may want to put a (link to a) license or copyright + * notice here (e.g. the OGL). + * Software License: [your license] Put your desired license here, which + * determines how others may use and modify your module + */ + +import CONSTANTS from "./js/constants.js"; +import { registerSettings } from "./js/settings.js"; +import { initHooks, setupHooks, readyHooks } from "./js/simplefog.js"; + +/* ------------------------------------ */ +/* Initialize module */ +/* ------------------------------------ */ +Hooks.once("init", async () => { + console.log(`${CONSTANTS.MODULE_NAME} | Initializing ${CONSTANTS.MODULE_NAME}`); + // Register custom module settings + registerSettings(); + initHooks(); + // Preload Handlebars templates + //await preloadTemplates(); +}); +/* ------------------------------------ */ +/* Setup module */ +/* ------------------------------------ */ +Hooks.once("setup", function () { + // Do anything after initialization but before ready + setupHooks(); +}); +/* ------------------------------------ */ +/* When ready */ +/* ------------------------------------ */ +Hooks.once("ready", async () => { + // // Do anything once the module is ready + // if (!game.modules.get('lib-wrapper')?.active && game.user?.isGM) { + // error(`The '${CONSTANTS.MODULE_NAME}' module requires to install and activate the 'libWrapper' module.`, true); + // return; + // } + readyHooks(); +}); + +/* ------------------------------------ */ +/* Other Hooks */ +/* ------------------------------------ */ + +Hooks.once("devModeReady", ({ registerPackageDebugFlag }) => { + registerPackageDebugFlag("simplefog"); +}); + +/** + * Initialization helper, to set API. + * @param api to set to game module. + */ +export function setApi(api) { + const data = game.modules.get(CONSTANTS.MODULE_NAME); + data.api = api; +} +/** + * Returns the set API. + * @returns Api from games module. + */ +export function getApi() { + const data = game.modules.get(CONSTANTS.MODULE_NAME); + return data.api; +} +/** + * Initialization helper, to set Socket. + * @param socket to set to game module. + */ +export function setSocket(socket) { + const data = game.modules.get(CONSTANTS.MODULE_NAME); + data.socket = socket; +} +/* + * Returns the set socket. + * @returns Socket from games module. + */ +export function getSocket() { + const data = game.modules.get(CONSTANTS.MODULE_NAME); + return data.socket; +} diff --git a/src/module.json b/src/module.json new file mode 100644 index 0000000..73b85ae --- /dev/null +++ b/src/module.json @@ -0,0 +1,153 @@ +{ + "id": "simplefog", + "title": "Simplefog - Manual Fog of War", + "description": "Simplefog allows you to draw fog of war manually, optionally automatically hiding and revealing tokens underneath based on opacity. It provides a number of tools to quickly draw and erase fog in various shapes - brush, rectangles, ellipses, polygons or to reveal tiles you click/drag on the grid.", + "version": "0.3.4", + "authors": [ + { + "name": "Vance Cole", + "url": "", + "discord": "", + "twitter": "", + "patreon": "", + "github": "", + "ko-fi": "", + "reddit": "", + "email": "" + }, + { + "name": "Chris Hampton", + "url": "", + "discord": "", + "twitter": "", + "patreon": "", + "github": "", + "ko-fi": "", + "reddit": "", + "email": "" + }, + { + "name": "Jeremy", + "url": "https://github.com/UranusBytes", + "discord": "", + "twitter": "", + "patreon": "", + "github": "UranusBytes", + "ko-fi": "", + "reddit": "", + "email": "" + }, + { + "name": "p4535992", + "url": "https://github.com/p4535992", + "discord": "", + "twitter": "", + "patreon": "", + "github": "p4535992", + "ko-fi": "", + "reddit": "", + "email": "" + }, + { + "name": "cirrahn", + "url": "https://github.com/cirrahn", + "discord": "", + "twitter": "", + "patreon": "cirrahn", + "github": "cirrahn", + "ko-fi": "", + "reddit": "", + "email": "" + }, + { + "name": "macskay", + "url": "https://github.com/macskay", + "discord": "", + "twitter": "", + "patreon": "", + "github": "macskay", + "ko-fi": "", + "reddit": "", + "email": "" + }, + { + "name": "mattd", + "url": "https://github.com/mattd", + "discord": "", + "twitter": "", + "patreon": "", + "github": "mattd", + "ko-fi": "", + "reddit": "", + "email": "" + } + ], + "type": "module", + "socket": true, + "includes": [ + "./assets/**", + "./lang/**", + "./languages/**", + "./scripts/**", + "./styles/**", + "./templates/**", + "./module.json", + "./README.md", + "./icons/**", + "./packs/**" + ], + "media": [ + { + "type": "icon", + "location": "" + }, + { + "type": "cover", + "location": "" + }, + { + "type": "screenshot", + "location": "" + } + ], + "languages": [ + { + "lang": "en", + "name": "English", + "path": "languages/en.json" + }, + { + "lang": "es", + "name": "Español", + "path": "languages/es.json" + }, + { + "lang": "ja", + "name": "日本語 (Japanese)", + "path": "languages/ja.json" + } + ], + "packs": [], + "systems": [], + "scripts": [], + "esmodules": ["main.js", "js/controls.js"], + "styles": ["css/brush-controls.css"], + "compatibility": { + "minimum": 10, + "verified": 11.306, + "maximum": 11 + }, + "manifestPlusVersion": "1.2.1", + "url": "https://github.com/League-of-Foundry-Developers/simplefog", + "manifest": "https://github.com/League-of-Foundry-Developers/simplefog/releases/latest/download/module.json", + "download": "https://github.com/League-of-Foundry-Developers/simplefog/releases/latest/download/module.zip", + "readme": "https://github.com/League-of-Foundry-Developers/simplefog/blob/v0.3.4/README.md", + "changelog": "https://github.com/League-of-Foundry-Developers/simplefog/blob/v0.3.4/CHANGELOG.md", + "bugs": "https://github.com/League-of-Foundry-Developers/simplefog/issues", + "allowBugReporter": true, + "relationships": { + "systems": [], + "requires": [], + "conflicts": [] + } +} diff --git a/templates/brush-controls.html b/src/templates/brush-controls.html similarity index 100% rename from templates/brush-controls.html rename to src/templates/brush-controls.html diff --git a/src/templates/scene-config.html b/src/templates/scene-config.html new file mode 100644 index 0000000..d5b1999 --- /dev/null +++ b/src/templates/scene-config.html @@ -0,0 +1,111 @@ +
diff --git a/templates/scene-config.html b/templates/scene-config.html deleted file mode 100644 index a5d1076..0000000 --- a/templates/scene-config.html +++ /dev/null @@ -1,76 +0,0 @@ - diff --git a/testing/caverns-007.jpg b/testing/caverns-007.jpg new file mode 100644 index 0000000..651f67d Binary files /dev/null and b/testing/caverns-007.jpg differ diff --git a/testing/caverns-007bw.jpg b/testing/caverns-007bw.jpg new file mode 100644 index 0000000..57259cc Binary files /dev/null and b/testing/caverns-007bw.jpg differ diff --git a/testing/caverns_config.txt b/testing/caverns_config.txt new file mode 100644 index 0000000..09d4cf2 --- /dev/null +++ b/testing/caverns_config.txt @@ -0,0 +1,6 @@ +Grid +***************************** + +Background Image Scale: 2.25 +Grid Size: 54 +Background Image Offset: 52x40 diff --git a/testing/druids_circle001.jpg b/testing/druids_circle001.jpg new file mode 100644 index 0000000..a58afe2 Binary files /dev/null and b/testing/druids_circle001.jpg differ diff --git a/testing/license.txt b/testing/license.txt new file mode 100644 index 0000000..03cc8d1 --- /dev/null +++ b/testing/license.txt @@ -0,0 +1,16 @@ +druids_circle001.jpg +by Tim Hartin under Creative Commons Attribution-Noncommercial-Share Alike 2.5 Canada License +http://www.paratime.ca/cartography/colour_buildings.html + +template004.jpg +by Tim Hartin under Creative Commons Attribution-Noncommercial-Share Alike 2.5 Canada License +http://www.paratime.ca/cartography/colour_buildings.html + +caverns-007.jpg +by Tim Hartin under Creative Commons Attribution-Noncommercial-Share Alike 2.5 Canada License +http://www.paratime.ca/cartography/colour_caverns.html + +caverns-007bw.jpg +by Tim Hartin under Creative Commons Attribution-Noncommercial-Share Alike 2.5 Canada License +http://www.paratime.ca/cartography/colour_caverns.html + diff --git a/testing/temple004.jpg b/testing/temple004.jpg new file mode 100644 index 0000000..330773b Binary files /dev/null and b/testing/temple004.jpg differ diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..2041b95 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "noImplicitAny": false, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "forceConsistentCasingInFileNames": true, + "outDir": "dist", + "declaration": true + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.spec.ts", "node_modules"] +}