Original commit: 03bac5867a
This commit is contained in:
Wojciech Daniło 2020-04-23 23:06:17 +02:00 committed by GitHub
parent e1973c3ae9
commit 23cb61d611
14 changed files with 1443 additions and 301 deletions

View File

@ -7,14 +7,14 @@ class Logo {
this.size = 64 this.size = 64
this.compatibleMode = compatibleMode this.compatibleMode = compatibleMode
this.borderMax = 10 this.borderMax = 10
this.borderSpread = 0 this.borderSpread = 2
this.init() this.init()
} }
init() { init() {
var scaleStop = 128 var scaleStop = 128
var scaleLog = Math.log2(scaleStop) var scaleLog = Math.log2(scaleStop)
this.borderWidth = 6 this.borderWidth = 7
this.topRadius = 32 this.topRadius = 32
this.borderOffset = this.borderWidth - this.borderSpread this.borderOffset = this.borderWidth - this.borderSpread
this.innerRadius = this.topRadius - this.borderWidth - this.borderOffset this.innerRadius = this.topRadius - this.borderWidth - this.borderOffset
@ -84,24 +84,26 @@ class Logo {
${this.defs} ${this.defs}
</defs> </defs>
<g transform="scale(${this.scale})"> <use ${this.ref}="#final"/> </g> ${this.main()}
</svg> </svg>
` `
} }
main() {
return `<g transform="scale(${this.scale})"> <use ${this.ref}="#final"/> </g>`
}
} }
class MinimalWhiteLogo extends Logo { class AppLogo extends Logo {
constructor(size, compatibleMode) { constructor(size, compatibleMode) {
super(size, compatibleMode) super(size, compatibleMode)
this.borderMax = 10
this.borderSpread = 0
this.init() this.init()
} }
} }
fastGenerate = (cons) => (...args) => new cons(...args).generate() fastGenerate = (cons) => (...args) => new cons(...args).generate()
exports.generateMinimalWhiteLogo = fastGenerate(MinimalWhiteLogo) exports.generateMinimalWhiteLogo = fastGenerate(AppLogo)
const fss = require('fs') const fss = require('fs')

View File

@ -10,12 +10,12 @@
"integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA==" "integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA=="
}, },
"@develar/schema-utils": { "@develar/schema-utils": {
"version": "2.1.0", "version": "2.6.5",
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
"integrity": "sha512-qjCqB4ctMig9Gz5bd6lkdFr3bO6arOdQqptdBSpF1ZpCnjofieCciEzkoS9ujY9cMGyllYSCSmBJ3x9OKHXzoA==", "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==",
"requires": { "requires": {
"ajv": "^6.1.0", "ajv": "^6.12.0",
"ajv-keywords": "^3.1.0" "ajv-keywords": "^3.4.1"
} }
}, },
"@electron/get": { "@electron/get": {
@ -1046,12 +1046,12 @@
} }
}, },
"@octokit/endpoint": { "@octokit/endpoint": {
"version": "6.0.0", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.1.tgz",
"integrity": "sha512-3nx+MEYoZeD0uJ+7F/gvELLvQJzLXhep2Az0bBSXagbApDvDW0LWwpnAIY/hb0Jwe17A0fJdz0O12dPh05cj7A==", "integrity": "sha512-pOPHaSz57SFT/m3R5P8MUu4wLPszokn5pXcB/pzavLTQf2jbU+6iayTvzaY6/BiotuRS0qyEUkx3QglT4U958A==",
"dev": true, "dev": true,
"requires": { "requires": {
"@octokit/types": "^2.0.0", "@octokit/types": "^2.11.1",
"is-plain-object": "^3.0.0", "is-plain-object": "^3.0.0",
"universal-user-agent": "^5.0.0" "universal-user-agent": "^5.0.0"
}, },
@ -1114,14 +1114,14 @@
} }
}, },
"@octokit/request": { "@octokit/request": {
"version": "5.4.0", "version": "5.4.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.2.tgz",
"integrity": "sha512-uAJO6GI8z8VHBqtY7VTL9iFy1Y+UTp5ShpI97tY5z0qBfYKE9rZCRsCm23VmF00x+IoNJ7a0nuVITs/+wS9/mg==", "integrity": "sha512-zKdnGuQ2TQ2vFk9VU8awFT4+EYf92Z/v3OlzRaSh4RIP0H6cvW1BFPXq4XYvNez+TPQjqN+0uSkCYnMFFhcFrw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@octokit/endpoint": "^6.0.0", "@octokit/endpoint": "^6.0.1",
"@octokit/request-error": "^2.0.0", "@octokit/request-error": "^2.0.0",
"@octokit/types": "^2.8.2", "@octokit/types": "^2.11.1",
"deprecation": "^2.0.0", "deprecation": "^2.0.0",
"is-plain-object": "^3.0.0", "is-plain-object": "^3.0.0",
"node-fetch": "^2.3.0", "node-fetch": "^2.3.0",
@ -1202,9 +1202,9 @@
} }
}, },
"@octokit/types": { "@octokit/types": {
"version": "2.9.0", "version": "2.12.1",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.9.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.12.1.tgz",
"integrity": "sha512-IzptUpoDsFlXF+AOys+KnfItIVY3EK+eH9Akv+lJYELnMSGkJnIcClt6Cm0QRR4ecsUTsmFJWn10iFgJ9BQqIQ==", "integrity": "sha512-LRLR1tjbcCfAmUElvTmMvLEzstpx6Xt/aQVTg2xvd+kHA2Ekp1eWl5t+gU7bcwjXHYEAzh4hH4WH+kS3vh+wRw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": ">= 8" "@types/node": ">= 8"
@ -1283,178 +1283,177 @@
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw=="
}, },
"@webassemblyjs/ast": { "@webassemblyjs/ast": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
"integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/helper-module-context": "1.9.0",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5", "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
"@webassemblyjs/wast-parser": "1.8.5" "@webassemblyjs/wast-parser": "1.9.0"
} }
}, },
"@webassemblyjs/floating-point-hex-parser": { "@webassemblyjs/floating-point-hex-parser": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
"integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
"dev": true "dev": true
}, },
"@webassemblyjs/helper-api-error": { "@webassemblyjs/helper-api-error": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
"integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
"dev": true "dev": true
}, },
"@webassemblyjs/helper-buffer": { "@webassemblyjs/helper-buffer": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
"integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
"dev": true "dev": true
}, },
"@webassemblyjs/helper-code-frame": { "@webassemblyjs/helper-code-frame": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
"integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/wast-printer": "1.8.5" "@webassemblyjs/wast-printer": "1.9.0"
} }
}, },
"@webassemblyjs/helper-fsm": { "@webassemblyjs/helper-fsm": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
"integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
"dev": true "dev": true
}, },
"@webassemblyjs/helper-module-context": { "@webassemblyjs/helper-module-context": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
"integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0"
"mamacro": "^0.0.3"
} }
}, },
"@webassemblyjs/helper-wasm-bytecode": { "@webassemblyjs/helper-wasm-bytecode": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
"integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
"dev": true "dev": true
}, },
"@webassemblyjs/helper-wasm-section": { "@webassemblyjs/helper-wasm-section": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
"integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/helper-buffer": "1.8.5", "@webassemblyjs/helper-buffer": "1.9.0",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5", "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
"@webassemblyjs/wasm-gen": "1.8.5" "@webassemblyjs/wasm-gen": "1.9.0"
} }
}, },
"@webassemblyjs/ieee754": { "@webassemblyjs/ieee754": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
"integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@xtuc/ieee754": "^1.2.0" "@xtuc/ieee754": "^1.2.0"
} }
}, },
"@webassemblyjs/leb128": { "@webassemblyjs/leb128": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
"integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@xtuc/long": "4.2.2" "@xtuc/long": "4.2.2"
} }
}, },
"@webassemblyjs/utf8": { "@webassemblyjs/utf8": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
"integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==",
"dev": true "dev": true
}, },
"@webassemblyjs/wasm-edit": { "@webassemblyjs/wasm-edit": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
"integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/helper-buffer": "1.8.5", "@webassemblyjs/helper-buffer": "1.9.0",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5", "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
"@webassemblyjs/helper-wasm-section": "1.8.5", "@webassemblyjs/helper-wasm-section": "1.9.0",
"@webassemblyjs/wasm-gen": "1.8.5", "@webassemblyjs/wasm-gen": "1.9.0",
"@webassemblyjs/wasm-opt": "1.8.5", "@webassemblyjs/wasm-opt": "1.9.0",
"@webassemblyjs/wasm-parser": "1.8.5", "@webassemblyjs/wasm-parser": "1.9.0",
"@webassemblyjs/wast-printer": "1.8.5" "@webassemblyjs/wast-printer": "1.9.0"
} }
}, },
"@webassemblyjs/wasm-gen": { "@webassemblyjs/wasm-gen": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
"integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5", "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
"@webassemblyjs/ieee754": "1.8.5", "@webassemblyjs/ieee754": "1.9.0",
"@webassemblyjs/leb128": "1.8.5", "@webassemblyjs/leb128": "1.9.0",
"@webassemblyjs/utf8": "1.8.5" "@webassemblyjs/utf8": "1.9.0"
} }
}, },
"@webassemblyjs/wasm-opt": { "@webassemblyjs/wasm-opt": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
"integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/helper-buffer": "1.8.5", "@webassemblyjs/helper-buffer": "1.9.0",
"@webassemblyjs/wasm-gen": "1.8.5", "@webassemblyjs/wasm-gen": "1.9.0",
"@webassemblyjs/wasm-parser": "1.8.5" "@webassemblyjs/wasm-parser": "1.9.0"
} }
}, },
"@webassemblyjs/wasm-parser": { "@webassemblyjs/wasm-parser": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
"integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/helper-api-error": "1.8.5", "@webassemblyjs/helper-api-error": "1.9.0",
"@webassemblyjs/helper-wasm-bytecode": "1.8.5", "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
"@webassemblyjs/ieee754": "1.8.5", "@webassemblyjs/ieee754": "1.9.0",
"@webassemblyjs/leb128": "1.8.5", "@webassemblyjs/leb128": "1.9.0",
"@webassemblyjs/utf8": "1.8.5" "@webassemblyjs/utf8": "1.9.0"
} }
}, },
"@webassemblyjs/wast-parser": { "@webassemblyjs/wast-parser": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
"integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/floating-point-hex-parser": "1.8.5", "@webassemblyjs/floating-point-hex-parser": "1.9.0",
"@webassemblyjs/helper-api-error": "1.8.5", "@webassemblyjs/helper-api-error": "1.9.0",
"@webassemblyjs/helper-code-frame": "1.8.5", "@webassemblyjs/helper-code-frame": "1.9.0",
"@webassemblyjs/helper-fsm": "1.8.5", "@webassemblyjs/helper-fsm": "1.9.0",
"@xtuc/long": "4.2.2" "@xtuc/long": "4.2.2"
} }
}, },
"@webassemblyjs/wast-printer": { "@webassemblyjs/wast-printer": {
"version": "1.8.5", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
"integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/wast-parser": "1.8.5", "@webassemblyjs/wast-parser": "1.9.0",
"@xtuc/long": "4.2.2" "@xtuc/long": "4.2.2"
} }
}, },
@ -1670,34 +1669,34 @@
} }
}, },
"app-builder-bin": { "app-builder-bin": {
"version": "3.5.5", "version": "3.5.6",
"resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.5.tgz", "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.5.6.tgz",
"integrity": "sha512-ZcHzJ9Xl+azPqdKzXZKdRZmkNmbxHHZyl4cbobNf8qMQpoPChpcov8riVrZSbu/0cT/JqJ8LOwJjy1OAwbChaQ==" "integrity": "sha512-gY9ABoV5jh67IrPEwF81R8l9LwE3RqHUyU3rIKitwqMpKhplN5OZC6WEHOXO3XhwiLCIlr9LLI6OPhr3bmtQIg=="
}, },
"app-builder-lib": { "app-builder-lib": {
"version": "22.4.1", "version": "22.5.1",
"resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.4.1.tgz", "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.5.1.tgz",
"integrity": "sha512-epwUzIM+2pcdy/If9koTP74CKx4v7xGPj75a2Z5cM4rrGN9yVZ3eDUBbfF0e0qE4Qmcv5pd0BAZJ26bGm8NWsQ==", "integrity": "sha512-VtB/PD8actR1317D/0uGzuJIYbpw4pRrfMB6IyTLwGynUd3ihqiCFjejVWHjCwopgCct2kE0MvLwo8P49xHIeQ==",
"requires": { "requires": {
"7zip-bin": "~5.0.3", "7zip-bin": "~5.0.3",
"@develar/schema-utils": "~2.1.0", "@develar/schema-utils": "~2.6.5",
"async-exit-hook": "^2.0.1", "async-exit-hook": "^2.0.1",
"bluebird-lst": "^1.0.9", "bluebird-lst": "^1.0.9",
"builder-util": "22.4.1", "builder-util": "22.5.1",
"builder-util-runtime": "8.6.2", "builder-util-runtime": "8.7.0",
"chromium-pickle-js": "^0.2.0", "chromium-pickle-js": "^0.2.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"ejs": "^3.0.1", "ejs": "^3.0.2",
"electron-publish": "22.4.1", "electron-publish": "22.5.1",
"fs-extra": "^8.1.0", "fs-extra": "^9.0.0",
"hosted-git-info": "^3.0.4", "hosted-git-info": "^3.0.4",
"is-ci": "^2.0.0", "is-ci": "^2.0.0",
"isbinaryfile": "^4.0.4", "isbinaryfile": "^4.0.5",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"lazy-val": "^1.0.4", "lazy-val": "^1.0.4",
"minimatch": "^3.0.4", "minimatch": "^3.0.4",
"normalize-package-data": "^2.5.0", "normalize-package-data": "^2.5.0",
"read-config-file": "5.0.2", "read-config-file": "6.0.0",
"sanitize-filename": "^1.6.3", "sanitize-filename": "^1.6.3",
"semver": "^7.1.3", "semver": "^7.1.3",
"temp-file": "^3.3.7" "temp-file": "^3.3.7"
@ -1711,6 +1710,17 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"fs-extra": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
"integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"hosted-git-info": { "hosted-git-info": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.4.tgz", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.4.tgz",
@ -1719,10 +1729,24 @@
"lru-cache": "^5.1.1" "lru-cache": "^5.1.1"
} }
}, },
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"semver": { "semver": {
"version": "7.3.2", "version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
} }
} }
}, },
@ -1908,6 +1932,11 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
}, },
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"atob": { "atob": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
@ -2430,19 +2459,19 @@
"dev": true "dev": true
}, },
"builder-util": { "builder-util": {
"version": "22.4.1", "version": "22.5.1",
"resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.4.1.tgz", "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.5.1.tgz",
"integrity": "sha512-+ysLc7cC4w6P7rBxmZ5X2aU3QvcwFoWCl1us+mcUKdsGmJAtFUMPJqueeptdxjyPrPShIUOKHzA8uk5A3d1fHg==", "integrity": "sha512-CelDTP3+fvDfZfbwy3PXif7mudPaWankJ8vrRg/NtCGvL+hXnwycnJZr46d5EQL7AgQcpJ27o9LTdfu61cxTFw==",
"requires": { "requires": {
"7zip-bin": "~5.0.3", "7zip-bin": "~5.0.3",
"@types/debug": "^4.1.5", "@types/debug": "^4.1.5",
"@types/fs-extra": "^8.1.0", "@types/fs-extra": "^8.1.0",
"app-builder-bin": "3.5.5", "app-builder-bin": "3.5.6",
"bluebird-lst": "^1.0.9", "bluebird-lst": "^1.0.9",
"builder-util-runtime": "8.6.2", "builder-util-runtime": "8.7.0",
"chalk": "^3.0.0", "chalk": "^3.0.0",
"debug": "^4.1.1", "debug": "^4.1.1",
"fs-extra": "^8.1.0", "fs-extra": "^9.0.0",
"is-ci": "^2.0.0", "is-ci": "^2.0.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"source-map-support": "^0.5.16", "source-map-support": "^0.5.16",
@ -2489,11 +2518,31 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"fs-extra": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
"integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"has-flag": { "has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}, },
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"supports-color": { "supports-color": {
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
@ -2501,13 +2550,18 @@
"requires": { "requires": {
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
} }
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
} }
} }
}, },
"builder-util-runtime": { "builder-util-runtime": {
"version": "8.6.2", "version": "8.7.0",
"resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.6.2.tgz", "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.0.tgz",
"integrity": "sha512-9QnIBISfhgQ2BxtRLidVqf/v5HD73vSKZDllpUmGd2L6VORGQk7cZAPmPtw4HQM3gPBelyVJ5yIjMNZ8xjmd1A==", "integrity": "sha512-G1AqqVM2vYTrSFR982c1NNzwXKrGLQjVjaZaWQdn4O6Z3YKjdMDofw88aD9jpyK9ZXkrCxR0tI3Qe9wNbyTlXg==",
"requires": { "requires": {
"debug": "^4.1.1", "debug": "^4.1.1",
"sax": "^1.2.4" "sax": "^1.2.4"
@ -3114,9 +3168,9 @@
} }
}, },
"schema-utils": { "schema-utils": {
"version": "2.6.5", "version": "2.6.6",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.5.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.6.tgz",
"integrity": "sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ==", "integrity": "sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA==",
"requires": { "requires": {
"ajv": "^6.12.0", "ajv": "^6.12.0",
"ajv-keywords": "^3.4.1" "ajv-keywords": "^3.4.1"
@ -3190,9 +3244,9 @@
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
}, },
"make-dir": { "make-dir": {
"version": "3.0.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"requires": { "requires": {
"semver": "^6.0.0" "semver": "^6.0.0"
} }
@ -4005,19 +4059,29 @@
} }
}, },
"dmg-builder": { "dmg-builder": {
"version": "22.4.1", "version": "22.5.1",
"resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.4.1.tgz", "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.5.1.tgz",
"integrity": "sha512-hEemh7n0zoVt7zPPwvn7iOttP03oENjJ4ApttPmt8oDnX8T4q42MjGWyDlLkPMplMJfoTxkkNqmm296f0OYM8Q==", "integrity": "sha512-AwIiyGwgqhA8Ty/YnEU20aSzfrWZns6suOBTqddD+rLDI4jEASKGQadfvcXRSWgaK/VQW0GrhheXrhJpzZzt3g==",
"requires": { "requires": {
"app-builder-lib": "~22.4.1", "app-builder-lib": "22.5.1",
"bluebird-lst": "^1.0.9", "builder-util": "22.5.1",
"builder-util": "~22.4.1", "fs-extra": "^9.0.0",
"fs-extra": "^8.1.0",
"iconv-lite": "^0.5.1", "iconv-lite": "^0.5.1",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"sanitize-filename": "^1.6.3" "sanitize-filename": "^1.6.3"
}, },
"dependencies": { "dependencies": {
"fs-extra": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
"integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"iconv-lite": { "iconv-lite": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.1.tgz",
@ -4025,6 +4089,20 @@
"requires": { "requires": {
"safer-buffer": ">= 2.1.2 < 3" "safer-buffer": ">= 2.1.2 < 3"
} }
},
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
} }
} }
}, },
@ -4136,31 +4214,31 @@
}, },
"dependencies": { "dependencies": {
"@types/node": { "@types/node": {
"version": "12.12.35", "version": "12.12.37",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.35.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.37.tgz",
"integrity": "sha512-ASYsaKecA7TUsDrqIGPNk3JeEox0z/0XR/WsJJ8BIX/9+SkMSImQXKWfU/yBrSyc7ZSE/NPqLu36Nur0miCFfQ==" "integrity": "sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg=="
} }
} }
}, },
"electron-builder": { "electron-builder": {
"version": "22.4.1", "version": "22.5.1",
"resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.4.1.tgz", "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.5.1.tgz",
"integrity": "sha512-13CjZcGeJS+c3EKRwFT/Oty5Niif5g1FwDioBLEbjkPCPQgxdtDsr+rJtCu9qxkiKDYpAoPS+t/clNk0efONvQ==", "integrity": "sha512-7gnHN8Ml5zecDerN8/ljAwUKtE+hhGLuT/X2/zO0FJM2q2hlLx/6ZgzESFILKqnPQFEBRxQ8SL1OxjdIY0HIrw==",
"requires": { "requires": {
"@types/yargs": "^15.0.4", "@types/yargs": "^15.0.4",
"app-builder-lib": "22.4.1", "app-builder-lib": "22.5.1",
"bluebird-lst": "^1.0.9", "bluebird-lst": "^1.0.9",
"builder-util": "22.4.1", "builder-util": "22.5.1",
"builder-util-runtime": "8.6.2", "builder-util-runtime": "8.7.0",
"chalk": "^3.0.0", "chalk": "^3.0.0",
"dmg-builder": "22.4.1", "dmg-builder": "22.5.1",
"fs-extra": "^8.1.0", "fs-extra": "^9.0.0",
"is-ci": "^2.0.0", "is-ci": "^2.0.0",
"lazy-val": "^1.0.4", "lazy-val": "^1.0.4",
"read-config-file": "5.0.2", "read-config-file": "6.0.0",
"sanitize-filename": "^1.6.3", "sanitize-filename": "^1.6.3",
"update-notifier": "^4.1.0", "update-notifier": "^4.1.0",
"yargs": "^15.1.0" "yargs": "^15.3.1"
}, },
"dependencies": { "dependencies": {
"ansi-styles": { "ansi-styles": {
@ -4194,11 +4272,31 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}, },
"fs-extra": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
"integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"has-flag": { "has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}, },
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"supports-color": { "supports-color": {
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
@ -4206,6 +4304,11 @@
"requires": { "requires": {
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
} }
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
} }
} }
}, },
@ -4215,16 +4318,16 @@
"integrity": "sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw==" "integrity": "sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw=="
}, },
"electron-publish": { "electron-publish": {
"version": "22.4.1", "version": "22.5.1",
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.4.1.tgz", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.5.1.tgz",
"integrity": "sha512-nwKNum3KXm+01rtWX2pc1jhazdzDy2zYnQx+zmXphZchjd6UOMX3ZN0xyZUCKugw5ZliflT6LkgbrcBXBtYD3A==", "integrity": "sha512-g5bwLAHZT6A++yU1+Et+fncnFAdXXgkRao9rzTFAvhQ0QJBsmLiyOd0Ta2RI/EQcVoy6jyHtxFs7CWIXE5aZOA==",
"requires": { "requires": {
"@types/fs-extra": "^8.1.0", "@types/fs-extra": "^8.1.0",
"bluebird-lst": "^1.0.9", "bluebird-lst": "^1.0.9",
"builder-util": "~22.4.1", "builder-util": "22.5.1",
"builder-util-runtime": "8.6.2", "builder-util-runtime": "8.7.0",
"chalk": "^3.0.0", "chalk": "^3.0.0",
"fs-extra": "^8.1.0", "fs-extra": "^9.0.0",
"lazy-val": "^1.0.4", "lazy-val": "^1.0.4",
"mime": "^2.4.4" "mime": "^2.4.4"
}, },
@ -4260,11 +4363,31 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}, },
"fs-extra": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz",
"integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"has-flag": { "has-flag": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
}, },
"jsonfile": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz",
"integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^1.0.0"
}
},
"mime": { "mime": {
"version": "2.4.4", "version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
@ -4277,6 +4400,11 @@
"requires": { "requires": {
"has-flag": "^4.0.0" "has-flag": "^4.0.0"
} }
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
} }
} }
}, },
@ -4988,9 +5116,9 @@
} }
}, },
"make-dir": { "make-dir": {
"version": "3.0.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"requires": { "requires": {
"semver": "^6.0.0" "semver": "^6.0.0"
} }
@ -6903,9 +7031,9 @@
} }
}, },
"is-function": { "is-function": {
"version": "1.0.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
"integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
}, },
"is-glob": { "is-glob": {
"version": "4.0.1", "version": "4.0.1",
@ -7506,12 +7634,6 @@
"ssri": "^6.0.0" "ssri": "^6.0.0"
} }
}, },
"mamacro": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz",
"integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==",
"dev": true
},
"map-age-cleaner": { "map-age-cleaner": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
@ -7887,9 +8009,9 @@
} }
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.4", "version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": { "requires": {
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
@ -8024,9 +8146,9 @@
"dev": true "dev": true
}, },
"node-abi": { "node-abi": {
"version": "2.15.0", "version": "2.16.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.15.0.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz",
"integrity": "sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg==", "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
}, },
@ -9198,15 +9320,14 @@
} }
}, },
"read-config-file": { "read-config-file": {
"version": "5.0.2", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-5.0.2.tgz", "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.0.0.tgz",
"integrity": "sha512-tVt1lsiSjs+FtL/vtfCivqtKR1UNk3BB3uPJQvJqkgtAYDvZjo0xyXFYSVmzaTcO+Jdi5G7O2K2vDV+p1M/oug==", "integrity": "sha512-PHjROSdpceKUmqS06wqwP92VrM46PZSTubmNIMJ5DrMwg1OgenSTSEHIkCa6TiOJ+y/J0xnG1fFwG3M+Oi1aNA==",
"requires": { "requires": {
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"dotenv-expand": "^5.1.0", "dotenv-expand": "^5.1.0",
"fs-extra": "^8.1.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"json5": "^2.1.1", "json5": "^2.1.2",
"lazy-val": "^1.0.4" "lazy-val": "^1.0.4"
}, },
"dependencies": { "dependencies": {
@ -9515,9 +9636,9 @@
} }
}, },
"resolve": { "resolve": {
"version": "1.15.1", "version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"requires": { "requires": {
"path-parse": "^1.0.6" "path-parse": "^1.0.6"
} }
@ -10326,9 +10447,9 @@
} }
}, },
"source-map-support": { "source-map-support": {
"version": "0.5.16", "version": "0.5.18",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.18.tgz",
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "integrity": "sha512-9luZr/BZ2QeU6tO2uG8N2aZpVSli4TSAOAqFOyTO51AJcD9P99c0K1h6dD6r6qo5dyT44BR5exweOaLLeldTkQ==",
"requires": { "requires": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
"source-map": "^0.6.0" "source-map": "^0.6.0"
@ -10357,9 +10478,9 @@
} }
}, },
"spdx-exceptions": { "spdx-exceptions": {
"version": "2.2.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
}, },
"spdx-expression-parse": { "spdx-expression-parse": {
"version": "3.0.0", "version": "3.0.0",
@ -11094,9 +11215,9 @@
} }
}, },
"uglify-js": { "uglify-js": {
"version": "3.9.0", "version": "3.9.1",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.0.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.1.tgz",
"integrity": "sha512-j5wNQBWaql8gr06dOUrfaohHlscboQZ9B8sNsoK5o4sBjm7Ht9dxSbrMXyktQpA16Acaij8AcoozteaPYZON0g==", "integrity": "sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==",
"dev": true, "dev": true,
"optional": true, "optional": true,
"requires": { "requires": {
@ -11483,16 +11604,16 @@
"dev": true "dev": true
}, },
"webpack": { "webpack": {
"version": "4.42.0", "version": "4.43.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
"integrity": "sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==", "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.8.5", "@webassemblyjs/ast": "1.9.0",
"@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/helper-module-context": "1.9.0",
"@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-edit": "1.9.0",
"@webassemblyjs/wasm-parser": "1.8.5", "@webassemblyjs/wasm-parser": "1.9.0",
"acorn": "^6.2.1", "acorn": "^6.4.1",
"ajv": "^6.10.2", "ajv": "^6.10.2",
"ajv-keywords": "^3.4.1", "ajv-keywords": "^3.4.1",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
@ -11503,13 +11624,13 @@
"loader-utils": "^1.2.3", "loader-utils": "^1.2.3",
"memory-fs": "^0.4.1", "memory-fs": "^0.4.1",
"micromatch": "^3.1.10", "micromatch": "^3.1.10",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.3",
"neo-async": "^2.6.1", "neo-async": "^2.6.1",
"node-libs-browser": "^2.2.1", "node-libs-browser": "^2.2.1",
"schema-utils": "^1.0.0", "schema-utils": "^1.0.0",
"tapable": "^1.1.3", "tapable": "^1.1.3",
"terser-webpack-plugin": "^1.4.3", "terser-webpack-plugin": "^1.4.3",
"watchpack": "^1.6.0", "watchpack": "^1.6.1",
"webpack-sources": "^1.4.1" "webpack-sources": "^1.4.1"
} }
}, },
@ -12309,9 +12430,9 @@
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "18.1.2", "version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"requires": { "requires": {
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
"decamelize": "^1.2.0" "decamelize": "^1.2.0"

View File

@ -7,4 +7,6 @@ pub mod function;
pub mod seq; pub mod seq;
pub mod theme; pub mod theme;
pub use data::hash_map_tree::HashMapTree;
pub use data::index::Index;
pub use data::opt_vec::OptVec; pub use data::opt_vec::OptVec;

View File

@ -9,6 +9,7 @@ pub mod render;
pub mod scene; pub mod scene;
pub mod shape; pub mod shape;
pub mod symbol; pub mod symbol;
pub mod style;
pub mod world; pub mod world;

View File

@ -0,0 +1,583 @@
//! This module defines a cascading style sheet registry and related style management utilities.
pub mod data;
pub mod path;
use crate::prelude::*;
use crate::data::HashMapTree;
use crate::data::Index;
use crate::data::OptVec;
pub use self::data::Data;
pub use self::data::data;
pub use self::path::Path;
// ===========
// === Var ===
// ===========
/// Data of a style variable. Variables are associated with a style path like 'panel.button.size'
/// and are automatically bound to the most specific style sheet as soon as it gets defined. By
/// most specific, we mean the one with the longest path. For example, the 'panel.button.size' var
/// will be bound to one of 'panel.button.size', 'button.size', or 'size' if defined, in that order.
#[derive(Debug)]
pub struct Var {
/// Index of the var in the style var map.
index : Index<Var>,
/// Set of all `Sheet` indexes which are potential matches of this var. For example, for a var
/// 'panel.button.size', all of the following sheets will be included here: 'panel.button.size',
/// 'button.size', and 'size'.
matches : Vec<Index<Sheet>>,
/// Index of the most specific `Sheet` from `matches` which has a defined value if any.
binding : Option<Index<Sheet>>,
/// List of all `Sheet`s which use this var in their expressions.
usages : HashSet<Index<Sheet>>,
}
impl Var {
/// Constructor.
pub fn new(index:Index<Var>) -> Self {
let matches = default();
let binding = default();
let usages = default();
Self {index,matches,binding,usages}
}
}
// =============
// === Sheet ===
// =============
/// A node in the style sheet tree. Style sheets are associated with a style path like
/// 'panel.button.size' and each node keeps a `Data` value. The value can either be set explicitly,
/// or computed automatically if the style sheet is defined with en `Expression`. Please note that
/// although `Sheet` contains a single value, it is in fact a node in a tree defined in `Registry`,
/// so it can be interpreted as a set of hierarchical values instead.
#[derive(Debug)]
pub struct Sheet {
/// Index of the style sheet in the style sheet map.
index : Index<Sheet>,
/// Value of this style sheet node. Style sheets without value behave like if they do not exist.
value : Option<Data>,
/// Expression used to update the value.
expr : Option<Expression>,
/// Indexes of all `Var`s that are potential matches with this style sheet.
matches : HashSet<Index<Var>>,
/// Indexes of all `Var`s that are bound (best matches) with this style sheet.
bindings : HashSet<Index<Var>>,
}
impl Sheet {
/// Constructor.
pub fn new(index:Index<Sheet>) -> Self {
let value = default();
let expr = default();
let matches = default();
let bindings = default();
Self {index,value,expr,matches,bindings}
}
/// Checks whether the style sheet exist. Style sheets without value are considered templates
/// and are kept in the graph for optimization purposes only.
pub fn exists(&self) -> bool {
self.value.is_some()
}
}
// ==================
// === Expression ===
// ==================
/// Expression of a style sheet.
#[derive(Derivative)]
#[derivative(Debug)]
pub struct Expression {
/// Indexes of all vars which are used as sources to the function of this expression.
sources : Vec<Index<Var>>,
/// Function used to compute the new value of the style sheet.
#[derivative(Debug="ignore")]
function : Box<dyn Fn(&[&Data])->Data>
}
// =============
// === Types ===
// =============
// === Types ===
#[allow(missing_docs)]
mod types {
use super::*;
pub type VarVec = OptVec<Var,Index<Var>>;
pub type SheetVec = OptVec<Sheet,Index<Sheet>>;
pub type VarMap = HashMapTree<String,Option<Index<Var>>>;
pub type SheetMap = HashMapTree<String,Index<Sheet>>;
}
use types::*;
trait NewInstance<K> {
fn new_instance(&mut self) -> K;
}
impl NewInstance<Index<Var>> for VarVec {
fn new_instance(&mut self) -> Index<Var> {
self.insert_with_ix(Var::new)
}
}
impl NewInstance<Index<Sheet>> for SheetVec {
fn new_instance(&mut self) -> Index<Sheet> {
self.insert_with_ix(Sheet::new)
}
}
// ================
// === Registry ===
// ================
/// Style sheet registry. Could be named "Cascading Style Sheets" but then the name will be
/// confusing with CSS used in web development. Defines a set of cascading style sheets. Each
/// style sheet can be assigned with a value of type `Data` or an expression to compute one. It
/// also allows creating variables which are automatically bound to the most specific style sheet.
/// See `Var` and `Sheet` to learn more.
#[derive(Debug)]
pub struct Registry {
/// Set of all variables.
pub vars : VarVec,
/// Set of all style sheets.
pub sheets : SheetVec,
/// Association of a path like 'button' -> 'size' to a variable.
pub var_map : VarMap,
/// Association of a path like 'button' -> 'size' to a style sheet.
pub sheet_map : SheetMap,
}
// === Constructors ===
impl Registry {
/// Constructor.
pub fn new() -> Self {
let vars = default();
let mut sheets = OptVec::<Sheet,Index<Sheet>>::new();
let var_map = default();
let root_sheet_id = sheets.new_instance();
let sheet_map = SheetMap::from_value(root_sheet_id);
Self {vars,sheets,var_map,sheet_map}
}
/// Access variable by the given path or create new one if missing.
///
/// Implementation note: under the hood, a `Sheet` for each sub-path will be created. For
/// example, when creating "panel.button.size" variable, three sheets will be created as well:
/// "panel.button.size", "button.size", and "size". This way we keep track of all possible
/// matches and we can create high-performance value binding algorithms.
pub fn var<P:Into<Path>>(&mut self, path:P) -> Index<Var> {
let path = path.into();
let vars = &mut self.vars;
let sheets = &mut self.sheets;
let var_map_node = self.var_map.get_node(&path.rev_segments);
let var_id = *var_map_node.value_or_set_with(||vars.new_instance());
let mut var_matches = Vec::new();
self.sheet_map.get_node_traversing_with(&path.rev_segments,||{sheets.new_instance()}, |t| {
var_matches.push(t.value)
});
var_matches.reverse();
for sheet_id in &var_matches {
self.sheets[*sheet_id].matches.insert(var_id);
}
self.vars[var_id].matches = var_matches;
self.rebind_var(var_id);
var_id
}
/// Access style sheet by the given path or create new one if missing.
fn sheet<P:Into<Path>>(&mut self, path:P) -> Index<Sheet> {
let path = path.into();
let sheets = &mut self.sheets;
let node = self.sheet_map.get_node_with(&path.rev_segments,|| sheets.new_instance());
node.value
}
}
// === Getters ===
impl Registry {
/// Reads the value of the variable.
pub fn value(&self, var_id:Index<Var>) -> Option<&Data> {
self.vars.safe_index(var_id).as_ref().and_then(|var| {
var.binding.and_then(|sheet_id| {
self.sheets[sheet_id].value.as_ref()
})
})
}
}
// === Setters ===
impl Registry {
/// Set a style sheet value. Please note that it will remove expression assigned to the target
/// style sheet if any.
pub fn set_value<P:Into<Path>>(&mut self, path:P, data:Data) {
self.set_value_to(path,Some(data))
}
/// Removes a style sheet value. Please note that it will remove expression assigned to the
/// target style sheet if any.
pub fn remove_value<P:Into<Path>>(&mut self, path:P) {
self.set_value_to(path,None)
}
/// Set or unset a style sheet value. Please note that it will remove expression assigned to the
/// target style sheet if any.
pub fn set_value_to<P:Into<Path>>(&mut self, path:P, data:Option<Data>) {
let path = path.into();
self.remove_expression(&path);
let sheet_id = self.sheet(&path);
let sheet = &mut self.sheets[sheet_id];
sheet.value = data;
for var_id in sheet.matches.clone() {
self.rebind_var(var_id)
}
for sheet_id in self.sheet_topo_sort(sheet_id) {
self.recompute(sheet_id);
}
}
/// Set a style sheet expression which will be used to automatically compute values whenever any
/// of the provided dependencies will change.
pub fn set_expression<P,F>(&mut self, path:P, args:&[Index<Var>], function:F)
where P:Into<Path>, F:'static+Fn(&[&Data])->Data {
let sheet_id = self.sheet(path);
let sheet = &mut self.sheets[sheet_id];
let sources = args.to_vec();
let function = Box::new(function);
sheet.expr = Some(Expression {sources,function});
for var_id in args {
self.vars[*var_id].usages.insert(sheet_id);
}
self.rebind_and_recompute(sheet_id);
}
}
// === Utils ===
impl Registry {
/// Check all potential candidates (sheets) this variable matches to and choose the most
/// specific one from those which exist (have a value).
fn rebind_var(&mut self, var_id:Index<Var>) {
let mut found = false;
let var = &self.vars[var_id];
for sheet_id in var.matches.clone() {
let sheet = &self.sheets[sheet_id];
if sheet.exists() {
if let Some(sheet_id) = var.binding {
self.sheets[sheet_id].bindings.remove(&var_id);
}
let var = &mut self.vars[var_id];
let sheet = &mut self.sheets[sheet_id];
var.binding = Some(sheet_id);
sheet.bindings.insert(var_id);
found = true;
break
}
}
if !found { self.unbind_var(var_id) }
}
/// Removes all binding information from var and related style sheets.
fn unbind_var(&mut self, var_id:Index<Var>) {
let var = &self.vars[var_id];
var.binding.for_each(|sheet_id| {
self.sheets[sheet_id].bindings.remove(&var_id);
});
let var = &mut self.vars[var_id];
var.binding = None;
}
/// Internal utility for removing style sheet expression.
fn remove_expression<P>(&mut self, path:P)
where P:Into<Path> {
let sheet_id = self.sheet(path);
let sheet = &mut self.sheets[sheet_id];
if sheet.expr.is_some() {
sheet.value = None;
let opt_expr = mem::take(&mut sheet.expr);
if let Some(expr) = opt_expr {
for var_id in expr.sources {
self.vars[var_id].usages.remove(&sheet_id);
}
}
self.rebind_and_recompute(sheet_id);
}
}
/// Internal utility which recomputes the provided style sheet, rebinds related variables, and
/// recomputes all dependent style sheets.
fn rebind_and_recompute(&mut self, sheet_id:Index<Sheet>) {
self.recompute(sheet_id);
let sheet = &mut self.sheets[sheet_id];
for var_id in sheet.matches.clone() {
self.rebind_var(var_id)
}
for sheet_id in self.sheet_topo_sort(sheet_id) {
self.recompute(sheet_id);
}
}
/// Recomputes the value of the provided sheet if the sheet was assigned with an expression.
fn recompute(&mut self, sheet_id:Index<Sheet>) {
let sheet = &self.sheets[sheet_id];
let value = sheet.expr.as_ref().and_then(|expr| {
let mut opt_values : Vec<Option<&Data>> = Vec::new();
for var_id in &expr.sources {
opt_values.push(self.value(*var_id));
}
let values : Option<Vec<&Data>> = opt_values.into_iter().collect();
values.map(|v| (expr.function)(&v) )
});
let sheet_mut = &mut self.sheets[sheet_id];
value.for_each(|v| sheet_mut.value = Some(v));
}
/// Traverses all sheets whose value depend on the value of the provided sheet and sorts them
/// in a topological order. This is used mainly for efficient implementation of sheet
/// recomputation mechanism.
fn sheet_topo_sort(&self, changed_sheet_id:Index<Sheet>) -> Vec<Index<Sheet>> {
let mut sheet_ref_count = HashMap::<Index<Sheet>,usize>::new();
let mut sorted_sheets = vec![changed_sheet_id];
self.with_all_sheet_deps(changed_sheet_id, |sheet_id| {
*sheet_ref_count.entry(sheet_id).or_default() += 1;
});
self.with_all_sheet_deps(changed_sheet_id, |sheet_id| {
let ref_count = sheet_ref_count.entry(sheet_id).or_default();
*ref_count -= 1;
if *ref_count == 0 {
sorted_sheets.push(sheet_id);
}
});
sorted_sheets
}
/// Runs the provided callback with all sheet indexes whose value depend on the value of the
/// provided sheet.
fn with_all_sheet_deps<F>(&self, target:Index<Sheet>, mut callback:F)
where F:FnMut(Index<Sheet>) {
let mut sheets_to_visit = vec![target];
while !sheets_to_visit.is_empty() {
if let Some(current_sheet_id) = sheets_to_visit.pop() {
let sheet = &self.sheets[current_sheet_id];
for var_id in &sheet.bindings {
let var = &self.vars[*var_id];
for sheet_id in &var.usages {
callback(*sheet_id);
sheets_to_visit.push(*sheet_id);
}
}
}
}
}
}
// === Debug ===
impl Registry {
/// Visualizes the network in the GraphViz Dot language. Use `visualize` to automatically
/// display it in a new browser tab.
pub fn to_graphviz(&self) -> String {
let mut dot = String::new();
Self::sheet_map_to_graphviz(&mut dot,&self.sheet_map);
Self::var_map_to_graphviz(&mut dot,&mut vec![],&self.var_map);
let s = &mut dot;
for var in &self.vars {
for sheet in &var.matches {Self::var_sheet_link(s,var.index,*sheet,"[style=dashed]")}
for sheet in &var.binding {Self::var_sheet_link(s,var.index,*sheet,"[color=red]")}
for sheet in &var.usages {Self::var_sheet_link(s,var.index,*sheet,"[color=blue]")}
}
for sheet in &self.sheets {
for var in &sheet.matches {Self::sheet_var_link(s,sheet.index,*var,"[style=dashed]")}
for var in &sheet.bindings {Self::sheet_var_link(s,sheet.index,*var,"[color=red]")}
for expr in &sheet.expr {
for var in &expr.sources {Self::sheet_var_link(s,sheet.index,*var,"[color=blue]")}
}
}
format!("digraph G {{\nnode [shape=box style=rounded]\n{}\n}}",dot)
}
fn sheet_map_to_graphviz(dot:&mut String, sheet_map:&SheetMap) {
let sheet_id = sheet_map.value;
dot.push_str(&iformat!("sheet_{sheet_id}\n"));
for (path,child) in sheet_map {
Self::sheet_sheet_link(dot,sheet_id,child.value,iformat!("[label=\"{path}\"]"));
Self::sheet_map_to_graphviz(dot,child);
}
}
fn var_map_to_graphviz(dot:&mut String, path:&mut Vec<String>, var_map:&VarMap) {
var_map.value.for_each(|var_id| {
let real_path = path.iter().rev().join(".");
dot.push_str(&iformat!("var_{var_id} [label=\"Var({real_path})\"]\n"));
});
for (segment,child) in var_map {
path.push(segment.into());
Self::var_map_to_graphviz(dot,path,child);
path.pop();
}
}
fn var_sheet_link<S>(dot:&mut String, var_id:Index<Var>, sheet_id:Index<Sheet>, s:S)
where S:Into<String> {
Self::link(dot,"var","sheet",var_id,sheet_id,s)
}
fn sheet_var_link<S>(dot:&mut String, sheet_id:Index<Sheet>, var_id:Index<Var>, s:S)
where S:Into<String> {
Self::link(dot,"sheet","var",sheet_id,var_id,s)
}
fn sheet_sheet_link<S>(dot:&mut String, sheet_id_1:Index<Sheet>, sheet_id_2:Index<Sheet>, s:S)
where S:Into<String> {
Self::link(dot,"sheet","sheet",sheet_id_1,sheet_id_2,s)
}
fn link<Src,Tgt,S>(dot:&mut String, src_pfx:&str, tgt_pfx:&str, src:Src, tgt:Tgt, s:S)
where Src:Display, Tgt:Display, S:Into<String> {
dot.push_str(&format!("{}_{} -> {}_{} {}\n",src_pfx,src,tgt_pfx,tgt,s.into()));
}
}
// === Impls ===
impl Default for Registry {
fn default() -> Self {
Self::new()
}
}
// =============
// === Tests ===
// =============
/// Interactive testing utility. To be removed in the future.
pub fn test() {
let mut style = Registry::new();
let var_size = style.var("size");
let var_button_size = style.var("button.size");
let var_graph_button_size = style.var("graph.button.size");
let _var = style.var("scene.background.color");
let _var = style.var("application.text.color");
let _var = style.var("application.text.size");
let _var = style.var("button.text.size");
let _var = style.var("node.text.color");
let _var = style.var("node.text.size");
let _var = style.var("application.background.color");
let _var = style.var("node.background.color");
assert!(style.value(var_graph_button_size).is_none());
style.set_value("size",data(1.0));
style.set_expression("graph.button.size",&[var_button_size],|args| args[0] + &data(100.0));
style.set_expression("button.size",&[var_size],|args| args[0] + &data(10.0));
style.set_value("button.size",data(3.0));
println!("{}",style.to_graphviz());
println!("{:?}", style.value(var_graph_button_size));
println!("{:?}", style.value(var_button_size));
println!("{:?}", style.vars[var_graph_button_size]);
println!("{:?}", style.sheets[style.vars[var_graph_button_size].binding.unwrap()]);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn simple_var_binding_1() {
let mut style = Registry::new();
let var1 = style.var(&["size"]);
assert!(style.value(var1).is_none());
style.set_value(&["size"],data(1.0));
assert_eq!(style.value(var1),Some(&data(1.0)));
}
#[test]
pub fn simple_var_binding_2() {
let mut style = Registry::new();
style.set_value(&["size"],data(1.0));
let var1 = style.var(&["size"]);
assert_eq!(style.value(var1),Some(&data(1.0)));
}
#[test]
pub fn hierarchical_var_binding() {
let mut style = Registry::new();
let var1 = style.var("graph.button.size");
assert!(style.value(var1).is_none());
style.set_value("size",data(1.0));
assert_eq!(style.value(var1),Some(&data(1.0)));
style.set_value("button.size",data(2.0));
assert_eq!(style.value(var1),Some(&data(2.0)));
style.set_value("graph.button.size",data(3.0));
assert_eq!(style.value(var1),Some(&data(3.0)));
style.remove_value("graph.button.size");
assert_eq!(style.value(var1),Some(&data(2.0)));
style.remove_value("button.size");
assert_eq!(style.value(var1),Some(&data(1.0)));
style.remove_value("size");
assert_eq!(style.value(var1),None);
}
#[test]
pub fn expr_bindings_1() {
let mut style = Registry::new();
let var_size = style.var("size");
let var_button_size = style.var("button.size");
let var_graph_button_size = style.var("graph.button.size");
assert!(style.value(var_graph_button_size).is_none());
style.set_value("size",data(1.0));
assert_eq!(style.value(var_graph_button_size),Some(&data(1.0)));
style.set_expression("graph.button.size",&[var_button_size],|args| args[0] + &data(10.0));
assert_eq!(style.value(var_graph_button_size),Some(&data(11.0)));
style.set_expression("button.size",&[var_size],|args| args[0] + &data(100.0));
assert_eq!(style.value(var_graph_button_size),Some(&data(111.0)));
style.set_value("size",data(2.0));
assert_eq!(style.value(var_graph_button_size),Some(&data(112.0)));
style.set_value("button.size",data(3.0));
assert_eq!(style.value(var_graph_button_size),Some(&data(13.0)));
style.set_value("button.size",data(4.0));
assert_eq!(style.value(var_graph_button_size),Some(&data(14.0)));
}
#[test]
pub fn expr_circular() {
let mut style = Registry::new();
let var_a = style.var("a");
let var_b = style.var("b");
style.set_expression("a",&[var_b],|args| args[0].clone());
style.set_expression("b",&[var_a],|args| args[0].clone());
assert!(style.value(var_a).is_none());
}
}

View File

@ -0,0 +1,117 @@
//! Definition of style sheet values.
use crate::prelude::*;
use crate::data::color;
// ============
// === Data ===
// ============
/// Type of values in the style sheet.
#[derive(Debug,Clone,PartialEq)]
#[allow(missing_docs)]
pub enum Data {
Invalid(String),
Number(f32),
Rgba(color::LinSrgba),
}
// === Constructors ===
/// Smart constructor for `Data`.
pub fn data<T:Into<Data>>(t:T) -> Data {
t.into()
}
impl From<f32> for Data {
fn from(t:f32) -> Data {
Data::Number(t)
}
}
// === Impls ===
//impl Eq for Data {}
impl Display for Data {
fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Invalid(s) => write!(f,"{}",s),
Self::Number(t) => write!(f,"Number({})",t),
Self::Rgba(t) => write!(f,"Color({:?})",t),
}
}
}
impl Data {
/// Lighten the color by `amount`.
pub fn lighten(&self, amount:f32) -> Self {
match self {
Data::Invalid(s) => Data::Invalid(s.clone()),
Data::Rgba(t) => Data::Rgba(palette::Shade::lighten(t,amount)),
this => Data::Invalid(format!("Cannot use method lighten on {}.",this))
}
}
}
// === Color Getters ===
macro_rules! define_color_getter {
($($name:ident),*) => {$(
impl Data {
/// Component getter.
pub fn $name(&self) -> Data {
match self {
Data::Invalid(s) => Data::Invalid(s.clone()),
Data::Rgba(t) => Data::Number(t.$name),
this => Data::Invalid (format!
(concat!("Cannot access ",stringify!($name)," property of {}."),this))
}
}
}
)*};
}
define_color_getter!(red,green,blue,alpha);
// === Operators ===
macro_rules! define_binary_number_operator {
($($toks:tt)*) => {
_define_binary_number_operator! { [&Data] [&Data] $($toks)* }
_define_binary_number_operator! { [ Data] [&Data] $($toks)* }
_define_binary_number_operator! { [&Data] [ Data] $($toks)* }
_define_binary_number_operator! { [ Data] [ Data] $($toks)* }
};
}
macro_rules! _define_binary_number_operator {
([$($t1:tt)*] [$($t2:tt)*] $name:ident :: $fn:ident, $($err:tt)*) => {
impl $name<$($t2)*> for $($t1)* {
type Output = Data;
#[allow(clippy::redundant_closure_call)]
fn $fn(self, rhs:$($t2)*) -> Self::Output {
match(self,rhs) {
(Data::Invalid(t),_) => Data::Invalid(t.clone()),
(_,Data::Invalid(t)) => Data::Invalid(t.clone()),
(Data::Number(lhs),Data::Number(rhs)) => Data::Number(lhs.$fn(rhs)),
(lhs,rhs) => Data::Invalid(($($err)*)(lhs,rhs))
}
}
}
};
}
define_binary_number_operator!(Mul::mul,|lhs,rhs| format!("Cannot multiply {} by {}.",lhs,rhs));
define_binary_number_operator!(Div::div,|lhs,rhs| format!("Cannot divide {} by {}.",lhs,rhs));
define_binary_number_operator!(Add::add,|lhs,rhs| format!("Cannot add {} to {}.",lhs,rhs));
define_binary_number_operator!(Sub::sub,|lhs,rhs| format!("Cannot subtract {} from {}.",rhs,lhs));

View File

@ -0,0 +1,63 @@
//! Path implementation used to navigate in the cascading style sheet hierarchy.
use crate::prelude::*;
// ============
// === Path ===
// ============
/// Path is a set of strings which describes how the variable or style sheet is nested in the
/// cascading style sheet map.
#[derive(Clone,Debug)]
#[allow(missing_docs)]
pub struct Path {
pub rev_segments : Vec<String>
}
impl Path {
/// Builds the path from the provided segment iterator. Please note that the internal path
/// representation is reversed, as the style sheet dependencies in the style sheet map tree are
/// also kept in a reversed order. Please use the `visualize` utility to inspect the internal
/// structure and learn more.
pub fn from_segments<T,I,Item>(t:T) -> Self
where T : IntoIterator<IntoIter=I,Item=Item>,
I : DoubleEndedIterator + Iterator<Item=Item>,
Item : Into<String> {
Self::from_rev_segments(t.into_iter().rev())
}
/// Builds the path from reversed segment iterator. See `from_segments` to learn more.
pub fn from_rev_segments<T,Item>(t:T) -> Self
where T : IntoIterator<Item=Item>,
Item : Into<String> {
let rev_segments = t.into_iter().map(|s|s.into()).collect();
Self {rev_segments}
}
}
impl From<&str> for Path {
fn from(t:&str) -> Self {
Self::from_rev_segments(t.rsplit('.'))
}
}
impl From<&Path> for Path {
fn from(t:&Path) -> Self {
t.clone()
}
}
macro_rules! gen_var_path_conversions {
($($($num:tt)?),*) => {$(
impl<T:?Sized> From<&[&T$(;$num)?]> for Path
where for <'t> &'t T : Into<String> {
fn from(t:&[&T$(;$num)?]) -> Self {
Self::from_segments(t.into_iter().map(|s|*s))
}
}
)*};
}
gen_var_path_conversions!(1,2,3,4,5,6,7,8,9,10,);

View File

@ -10,6 +10,7 @@
#![feature(cell_update)] #![feature(cell_update)]
#![feature(drain_filter)] #![feature(drain_filter)]
#![feature(overlapping_marker_traits)] #![feature(overlapping_marker_traits)]
#![feature(slice_patterns)]
#![feature(specialization)] #![feature(specialization)]
#![feature(fn_traits)] #![feature(fn_traits)]
#![feature(trait_alias)] #![feature(trait_alias)]

View File

@ -81,7 +81,7 @@ impl {
let name = name.as_ref().to_string(); let name = name.as_ref().to_string();
let buffer_dirty = self.buffer_dirty.clone(); let buffer_dirty = self.buffer_dirty.clone();
let shape_dirty = self.shape_dirty.clone(); let shape_dirty = self.shape_dirty.clone();
let ix = self.buffers.reserve_ix(); let ix = self.buffers.reserve_index();
group!(self.logger, "Adding buffer '{name}' at index {ix}.", { group!(self.logger, "Adding buffer '{name}' at index {ix}.", {
let on_set = Box::new(move || { buffer_dirty.set(ix) }); let on_set = Box::new(move || { buffer_dirty.set(ix) });
let on_resize = Box::new(move || { shape_dirty.set() }); let on_resize = Box::new(move || { shape_dirty.set() });

View File

@ -0,0 +1,113 @@
//! A tree structure build on top of the `HashMap`.
use crate::prelude::*;
// ===================
// === HashMapTree ===
// ===================
/// A tree build on top of the `HashMap`. Each node in the tree can have zero or more branches
/// accessible by the given key type.
#[derive(Derivative)]
#[derivative(Debug (bound="K:Eq+Hash+Debug , T:Debug"))]
#[derivative(Default (bound="K:Eq+Hash , T:Default"))]
pub struct HashMapTree<K,T> {
/// Value of the current tree node.
pub value : T,
/// Branches of the current tree node.
pub branches : HashMap<K,HashMapTree<K,T>>
}
impl<K,T> HashMapTree<K,T>
where K:Eq+Hash {
/// Constructor.
pub fn new() -> Self where T:Default {
default()
}
/// Constructor with explicit root value.
pub fn from_value(value:T) -> Self {
let branches = default();
Self {value,branches}
}
/// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case
/// the branch does not exist, a default instance will be created. Returns mutable reference to
/// the target tree node.
#[inline]
pub fn get_node<P,I>(&mut self, path:P) -> &mut HashMapTree<K,T>
where P:IntoIterator<Item=I>, T:Default, I:Into<K> {
self.get_node_with(path,default)
}
/// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case
/// the branch does not exist, uses `cons` to construct it. Returns mutable reference to the
/// target tree node.
#[inline]
pub fn get_node_with<P,I,F>(&mut self, path:P, f:F) -> &mut HashMapTree<K,T>
where P:IntoIterator<Item=I>, I:Into<K>, F:FnMut()->T {
self.get_node_traversing_with(path,f,|_|{})
}
/// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case
/// the branch does not exist, uses `cons` to construct it. Moreover, for each traversed branch
/// the `callback` is evaluated. Returns mutable reference to the target tree node.
#[inline]
pub fn get_node_traversing_with<P,I,F,M>
(&mut self, path:P, mut cons:F, mut callback:M) -> &mut HashMapTree<K,T>
where P:IntoIterator<Item=I>, I:Into<K>, F:FnMut()->T, M:FnMut(&mut HashMapTree<K,T>) {
path.into_iter().fold(self,|map,t| {
let key = t.into();
let node = map.branches.entry(key).or_insert_with(|| HashMapTree::from_value(cons()));
callback(node);
node
})
}
}
impl<K,T> HashMapTree<K,Option<T>>
where K:Eq+Hash {
/// Gets the current value or creates new default one if missing.
pub fn value_or_default(&mut self) -> &mut T where T:Default {
self.value_or_set_with(default)
}
/// Gets the current value or creates new one if missing.
pub fn value_or_set(&mut self, val:T) -> &mut T {
self.value_or_set_with(move || val)
}
/// Gets the current value or creates new one if missing.
pub fn value_or_set_with<F>(&mut self, cons:F) -> &mut T
where F:FnOnce()->T {
if self.value.is_none() {
self.value = Some(cons());
};
self.value.as_mut().unwrap()
}
}
// === Impls ===
impl<'a,K,T> IntoIterator for &'a HashMapTree<K,T> {
type Item = (&'a K, &'a HashMapTree<K,T>);
type IntoIter = std::collections::hash_map::Iter<'a,K,HashMapTree<K,T>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.branches.iter()
}
}
impl<'a,K,T> IntoIterator for &'a mut HashMapTree<K,T> {
type Item = (&'a K, &'a mut HashMapTree<K,T>);
type IntoIter = std::collections::hash_map::IterMut<'a,K,HashMapTree<K,T>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.branches.iter_mut()
}
}

View File

@ -0,0 +1,84 @@
//! This module defines a typed index struct. Useful to introduce type safety when using indexes
//! several indexable containers.
use crate::prelude::*;
// =============
// === Index ===
// =============
/// Typed newtype for `usize` meant to be used as a typed index.
pub struct Index<T> {
/// Raw value.
pub raw : usize,
phantom : PhantomData<T>
}
impl<T> Index<T> {
/// Constructor
pub fn new(raw:usize) -> Self {
let phantom = default();
Self {raw,phantom}
}
}
// === Impls ===
impl<T> Copy for Index<T> {}
impl<T> Eq for Index<T> {}
impl<T> Clone for Index<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Hash for Index<T> {
fn hash<H:std::hash::Hasher>(&self, state:&mut H) {
self.raw.hash(state)
}
}
impl<T> PartialEq for Index<T> {
fn eq(&self, other:&Self) -> bool {
self.raw == other.raw
}
}
impl<T> From<Index<T>> for usize {
fn from(t:Index<T>) -> Self {
t.raw
}
}
impl<T> From<&Index<T>> for usize {
fn from(t:&Index<T>) -> Self {
t.raw
}
}
impl<T> From<usize> for Index<T> {
fn from(t:usize) -> Self {
Self::new(t)
}
}
impl<T> From<&usize> for Index<T> {
fn from(t:&usize) -> Self {
Self::new(*t)
}
}
impl<T> Debug for Index<T> {
fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,"{}",self.raw)
}
}
impl<T> Display for Index<T> {
fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,"{}",self.raw)
}
}

View File

@ -1,10 +1,14 @@
//! Library of general data structures. //! Library of general data structures.
#![feature(trait_alias)]
#![warn(unsafe_code)] #![warn(unsafe_code)]
#![warn(missing_copy_implementations)] #![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)] #![warn(missing_debug_implementations)]
#![warn(missing_docs)] #![warn(missing_docs)]
pub mod hash_map_tree;
pub mod index;
pub mod opt_vec; pub mod opt_vec;
pub mod text; pub mod text;

View File

@ -1,90 +1,62 @@
#![allow(missing_docs)] //! A sparse vector implementation.
use crate::prelude::*; use crate::prelude::*;
use std::iter::FilterMap; use std::iter::FilterMap;
use std::slice; use std::slice;
// ============== // ==============
// === OptVec === // === OptVec ===
// ============== // ==============
// === Definition ===
/// A contiguous growable sparse array type. Similar to `Vec<T>`, but allowing missing values. /// A contiguous growable sparse array type. Similar to `Vec<T>`, but allowing missing values.
/// After a value is removed, it remembers the index for reuse in the future. /// After a value is removed, it remembers the index for reuse in the future. Unlike `Vec`, it is
/// parametrized with optional `Index` type variable which will be used for indexing the vector.
/// Index have to implement the `Index` trait.
#[derive(Derivative)] #[derive(Derivative)]
#[derivative(Default(bound = ""))] #[derivative(Default(bound=""))]
#[derive(Clone,Debug,Shrinkwrap)] #[derive(Clone,Debug,Shrinkwrap)]
pub struct OptVec<T> { pub struct OptVec<T,Index=usize> {
#[shrinkwrap(main_field)] #[shrinkwrap(main_field)]
pub items: Vec<Option<T>>, items : Vec<Option<T>>,
pub free_ixs: SmallVec<[Ix; 128]>, free_ixs : SmallVec<[Index; 128]>,
} }
pub type Ix = usize;
pub type Iter <'t, T> = FilterMap<slice::Iter <'t, Option<T>>, OptionAsRef <T>>;
pub type IterMut <'t, T> = FilterMap<slice::IterMut<'t, Option<T>>, OptionAsRefMut<T>>;
pub type OptionAsRef <T> = for<'r> fn(&'r Option<T>) -> Option<&'r T>;
pub type OptionAsRefMut <T> = for<'r> fn(&'r mut Option<T>) -> Option<&'r mut T>;
impl<T> OptVec<T> { // === Types ===
/// A trait for any vector index type.
pub trait Index = Debug + Copy + Into<usize> where usize : Into<Self>;
/// Iterator type of this vector.
pub type Iter<'t,T> = FilterMap<slice::Iter<'t,Option<T>>, OptionAsRef<T>>;
/// Mutable iterator type of this vector.
pub type IterMut<'t,T> = FilterMap<slice::IterMut<'t, Option<T>>, OptionAsRefMut<T>>;
/// Subtype of `Iter`.
pub type OptionAsRef <T> = for<'r> fn(&'r Option<T>) -> Option<&'r T>;
/// Subtype of `IterMut`.
pub type OptionAsRefMut <T> = for<'r> fn(&'r mut Option<T>) -> Option<&'r mut T>;
// === Construction ===
impl<T,I:Index> OptVec<T,I> {
/// Constructs a new, empty `Vec<T>`. It will not allocate until elements are pushed onto it. /// Constructs a new, empty `Vec<T>`. It will not allocate until elements are pushed onto it.
pub fn new() -> Self { pub fn new() -> Self {
default() default()
} }
}
/// Inserts the provided element to the vector. It reuses free indexes if any.
pub fn insert(&mut self, item: T) -> Ix {
self.insert_with_ix(|_| item)
}
/// Iterator. // === Status Checks ===
pub fn iter(&self) -> Iter<T> {
self.items.iter().filter_map(Option::as_ref)
}
/// Mutable iterator.
pub fn iter_mut(&mut self) -> IterMut<T> {
self.items.iter_mut().filter_map(Option::as_mut)
}
/// Finds a free index and inserts the element. The index is re-used in case the array is sparse
/// or is added in case of no free places.
pub fn insert_with_ix<F: FnOnce(Ix) -> T>(&mut self, f: F) -> Ix {
match self.free_ixs.pop() {
None => {
let ix = self.items.len();
self.items.push(Some(f(ix)));
ix
}
Some(ix) => {
self.items[ix] = Some(f(ix));
ix
}
}
}
/// Reserve an index for further reuse. Please remember that you cannot use the index to read
/// values unless the value is set.
pub fn reserve_ix(&mut self) -> Ix {
self.free_ixs.pop().unwrap_or_else(|| {
let ix = self.items.len();
self.items.push(None);
ix
})
}
/// Sets the value at given index. Panics if the index was already freed.
pub fn set(&mut self, ix:Ix, t:T) {
self.items[ix] = Some(t);
}
/// Removes the element at provided index and marks the index to be reused. Does nothing if the
/// index was already empty. Panics if the index was out of bounds.
pub fn remove(&mut self, ix: Ix) -> Option<T> {
let item = self.items[ix].take();
item.iter().for_each(|_| self.free_ixs.push(ix));
item
}
impl<T,I:Index> OptVec<T,I> {
/// Returns the number of elements in the vector, including reserved indexes. Also referred to /// Returns the number of elements in the vector, including reserved indexes. Also referred to
/// as its 'length'. /// as its 'length'.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
@ -98,35 +70,110 @@ impl<T> OptVec<T> {
} }
// === Indexing === // === Modifiers ===
impl<T> Index<usize> for OptVec<T> { impl<T,I:Index> OptVec<T,I> {
type Output = T; /// Inserts the provided element to the vector. It reuses free indexes if any.
fn index(&self, ix: usize) -> &Self::Output { pub fn insert(&mut self, item: T) -> I {
self.items.index(ix).as_ref().unwrap() self.insert_with_ix(|_| item)
}
/// Finds a free index and inserts the element. The index is re-used in case the array is sparse
/// or is added in case of no free places.
pub fn insert_with_ix<F:FnOnce(I) -> T>(&mut self, f: F) -> I {
match self.free_ixs.pop() {
None => {
let index = self.items.len().into();
self.items.push(Some(f(index)));
index
}
Some(index) => {
self.items[index.into()] = Some(f(index));
index
}
}
}
/// Reserve an index for further reuse. Please remember that you cannot use the index to read
/// values unless the value is set.
pub fn reserve_index(&mut self) -> I {
self.free_ixs.pop().unwrap_or_else(|| {
let index = self.items.len().into();
self.items.push(None);
index
})
}
/// Sets the value at given index. Panics if the index was already freed.
pub fn set(&mut self, index:I, t:T) {
self.items[index.into()] = Some(t);
}
/// Removes the element at provided index and marks the index to be reused. Does nothing if the
/// index was already empty. Panics if the index was out of bounds.
pub fn remove(&mut self, index:I) -> Option<T> {
let item = self.items[index.into()].take();
item.iter().for_each(|_| self.free_ixs.push(index));
item
} }
} }
impl<T> IndexMut<usize> for OptVec<T> {
fn index_mut(&mut self, ix: usize) -> &mut Self::Output { // === Indexing ===
self.items.index_mut(ix).as_mut().unwrap()
impl<T,I:Index> OptVec<T,I> {
/// Index into vector. Returns `None` if the key was already freed.
pub fn safe_index(&self, index:I) -> Option<&T> {
self.items[index.into()].as_ref()
}
/// Index into vector. Returns `None` if the key was already freed.
pub fn safe_index_mut(&mut self, index:I) -> Option<&mut T> {
self.items[index.into()].as_mut()
}
}
impl<T,I:Index> std::ops::Index<I> for OptVec<T,I> {
type Output = T;
fn index(&self, index:I) -> &Self::Output {
let error = || panic!(format!("Trying to access removed index `{:?}`.",index));
self.items.index(index.into()).as_ref().unwrap_or_else(error)
}
}
impl<T,I:Index> std::ops::IndexMut<I> for OptVec<T,I> {
fn index_mut(&mut self, index:I) -> &mut Self::Output {
let error = || panic!(format!("Trying to access removed index `{:?}`.",index));
self.items.index_mut(index.into()).as_mut().unwrap_or_else(error)
} }
} }
// === Iterators === // === Iterators ===
impl<'a, T> IntoIterator for &'a OptVec<T> { impl<T,I:Index> OptVec<T,I> {
/// Iterator.
pub fn iter(&self) -> Iter<T> {
self.items.iter().filter_map(Option::as_ref)
}
/// Mutable iterator.
pub fn iter_mut(&mut self) -> IterMut<T> {
self.items.iter_mut().filter_map(Option::as_mut)
}
}
impl<'a,T,I:Index> IntoIterator for &'a OptVec<T,I> {
type Item = &'a T; type Item = &'a T;
type IntoIter = Iter<'a, T>; type IntoIter = Iter<'a,T>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.iter() self.iter()
} }
} }
impl<'a, T> IntoIterator for &'a mut OptVec<T> { impl<'a,T,I:Index> IntoIterator for &'a mut OptVec<T,I> {
type Item = &'a mut T; type Item = &'a mut T;
type IntoIter = IterMut<'a, T>; type IntoIter = IterMut<'a,T>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.iter_mut() self.iter_mut()
} }
@ -144,7 +191,7 @@ mod tests {
#[test] #[test]
fn test_add() { fn test_add() {
let mut v = OptVec::new(); let mut v = OptVec::<usize>::new();
assert!(v.is_empty()); assert!(v.is_empty());
let ix1 = v.insert(1); let ix1 = v.insert(1);
@ -174,7 +221,7 @@ mod tests {
#[test] #[test]
fn test_iter() { fn test_iter() {
let mut v = OptVec::new(); let mut v = OptVec::<usize>::new();
let ix1 = v.insert(0); let ix1 = v.insert(0);
let _ix2 = v.insert(1); let _ix2 = v.insert(1);
@ -194,7 +241,7 @@ mod tests {
#[test] #[test]
fn test_iter_mut() { fn test_iter_mut() {
let mut v = OptVec::new(); let mut v = OptVec::<usize>::new();
let ix1 = v.insert(0); let ix1 = v.insert(0);
let _ix2 = v.insert(1); let _ix2 = v.insert(1);

View File

@ -13,6 +13,8 @@ use graph_editor::GraphEditor;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use ensogl::display::object::ObjectOps; use ensogl::display::object::ObjectOps;
use ensogl::display::style;
#[wasm_bindgen] #[wasm_bindgen]
#[allow(dead_code)] #[allow(dead_code)]
@ -53,4 +55,6 @@ fn init(app:&Application) {
} }
was_rendered = true; was_rendered = true;
}).forget(); }).forget();
style::test();
} }