Fix auto update (win tested) and add stylus

This commit is contained in:
oxmc
2025-02-13 06:34:03 -08:00
parent ab6fe350d3
commit b32fcbd8f1
17 changed files with 1570 additions and 406 deletions

View File

@@ -1,65 +1,64 @@
name: Bug name: Bug
description: Make sure you complete the template. Otherwise, it will be closed without further explanation! description: Make sure you complete the template. Otherwise, it will be closed without further explanation!
title: "[v<replace_this_with_your_bsky-desktop_version>] Replace this with your title" title: "[v<replace_this_with_your_bsky-desktop_version>] Replace this with your title"
labels: bug labels: [bug]
body: body:
- type: checkboxes - type: checkboxes
attributes: attributes:
label: Is there an existing issue for this? label: Is there an existing issue for this?
description: _Please check the [**issues**](https://github.com/oxmc/bsky-desktop/issues) page to see if someone has already reported the bug. **I DIDN\'T MAKE THIS CHECKBOX FOR COSMETIC.**_ description: _Please check the [**issues**](https://github.com/oxmc/bsky-desktop/issues) page to see if someone has already reported the bug. **I DIDN\'T MAKE THIS CHECKBOX FOR COSMETIC.**_
options: options:
- label: I have searched the existing issues - label: I have searched the existing issues
required: true required: true
- type: textarea - type: textarea
attributes: attributes:
label: Device information label: Device information
description: description: "_Please provide the following information:_"
value: | value: |
- OS: - OS:
- Hardware Specs: - Hardware Specs:
- Etc: - Etc:
validations: validations:
required: true required: true
- type: textarea - type: textarea
attributes: attributes:
label: Describe the issue label: Describe the issue
description: _Please attach videos or screenshots if possible_ description: _Please attach videos or screenshots if possible_
validations: validations:
required: true required: true
- type: textarea - type: textarea
attributes: attributes:
label: Steps to reproduce label: Steps to reproduce
description: _Please attach videos or screenshots if possible_ description: _Please attach videos or screenshots if possible_
value: | value: |
1. 1.
2. 2.
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: logs id: logs
attributes: attributes:
label: Crash log label: Crash log
description: _If the app crashes, **please provide the crash log**. description: _If the app crashes, **please provide the crash log**.
render: shell render: shell
- type: dropdown - type: dropdown
attributes: attributes:
label: Are you using the latest version of bsky-destop? If not, why? label: Are you using the latest version of bsky-destop? If not, why?
description: _Developers spent loads of time and effort to fix bugs & make improvements with every release. You might want to try and update to the [latest version](https://github.com/oxmc/bsky-desktop/releases) before reporting an issue._ description: _Developers spent loads of time and effort to fix bugs & make improvements with every release. You might want to try and update to the [latest version](https://github.com/oxmc/bsky-desktop/releases) before reporting an issue._
multiple: false multiple: false
options: options:
- ✅ Yes, I'm using the latest version of bsky-desktop - ✅ Yes, I'm using the latest version of bsky-desktop
- ❌ No, I'll explain with additional information below - ❌ No, I'll explain with additional information below
validations: validations:
required: true required: true
- type: textarea
attributes:
label: Additional information
validations:
required: false
- type: textarea
attributes:
label: Additional information
validations:
required: false

View File

@@ -10,6 +10,7 @@ const args = process.argv.slice(2);
const carch = args.includes('--arch') ? args[args.indexOf('--arch') + 1] : null; const carch = args.includes('--arch') ? args[args.indexOf('--arch') + 1] : null;
const cplatform = args.includes('--platform') ? args[args.indexOf('--platform') + 1] : null; const cplatform = args.includes('--platform') ? args[args.indexOf('--platform') + 1] : null;
const pack = args.includes('--pack'); // Keep track of --pack as a boolean flag const pack = args.includes('--pack'); // Keep track of --pack as a boolean flag
const nobc = args.includes('--no-bc'); // Keep track of --nobc as a boolean flag
// Determine platform // Determine platform
let platform; let platform;
@@ -59,14 +60,38 @@ if (pack) {
buildArgs.push('--dir'); buildArgs.push('--dir');
} }
// Read build-config.json // Default build configuration (used when --no-bc is passed) [Default values are for bskyDesktop]
const defaultBuildConfig = {
"appId": "com.oxmc.bskyDesktop",
"productName": "bskyDesktop",
"asarUnpack": [
"./node_modules/node-notifier/**/*"
],
"win": {
"icon": "src/ui/images/logo.ico",
},
"mac": {
"icon": "src/ui/images/mac.icns",
},
"linux": {
"icon": "src/ui/images/icons",
},
};
// Read build-config.json if it exists and --no-bc is not present
const buildConfigPath = path.join(__dirname, 'build-config.json'); const buildConfigPath = path.join(__dirname, 'build-config.json');
let buildConfig; let buildConfig = defaultBuildConfig;
try { if (!nobc) {
buildConfig = require(buildConfigPath); if (!require('fs').existsSync(buildConfigPath)) {
} catch (err) { console.error('build-config.json not found');
console.error(`Failed to read build-config.json: ${err.message}`); process.exit(1);
process.exit(1); }
try {
buildConfig = require(buildConfigPath);
} catch (err) {
console.error(`Failed to read build-config.json: ${err.message}`);
process.exit(1);
}
} }
// Generate artifact name // Generate artifact name
@@ -84,12 +109,12 @@ const options = {
oneClick: true, oneClick: true,
perMachine: false perMachine: false
}, },
dmg: { /*dmg: {
contents: [ contents: [
{ type: 'file', x: 255, y: 85 }, { type: 'file', x: 255, y: 85 },
{ type: 'link', path: '/Applications', x: 253, y: 325 } { type: 'link', path: '/Applications', x: 253, y: 325 }
] ]
}, },*/
...buildConfig ...buildConfig
}; };

309
package-lock.json generated
View File

@@ -13,19 +13,26 @@
"@electron/remote": "^2.1.2", "@electron/remote": "^2.1.2",
"adm-zip": "^0.5.12", "adm-zip": "^0.5.12",
"axios": "^1.6.8", "axios": "^1.6.8",
"electron-window-state": "^5.0.3",
"less": "^4.2.1", "less": "^4.2.1",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"node-notifier": "^10.0.0", "node-notifier": "^10.0.0",
"semver": "^7.6.3", "semver": "^7.6.3",
"stylus": "^0.64.0",
"usercss-meta": "^0.12.0", "usercss-meta": "^0.12.0",
"v8-compile-cache": "^2.3.0" "v8-compile-cache": "^2.3.0",
"winreg": "^1.2.5"
}, },
"devDependencies": { "devDependencies": {
"electron": "^29.4.6", "electron": "^29.4.6",
"electron-builder": "^24.13.3" "electron-builder": "^24.13.3"
} }
}, },
"node_modules/@adobe/css-tools": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz",
"integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==",
"license": "MIT"
},
"node_modules/@develar/schema-utils": { "node_modules/@develar/schema-utils": {
"version": "2.6.5", "version": "2.6.5",
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
@@ -254,7 +261,6 @@
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"string-width": "^5.1.2", "string-width": "^5.1.2",
@@ -272,7 +278,6 @@
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -285,7 +290,6 @@
"version": "6.2.1", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -298,14 +302,12 @@
"version": "9.2.2", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@isaacs/cliui/node_modules/string-width": { "node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"eastasianwidth": "^0.2.0", "eastasianwidth": "^0.2.0",
@@ -323,7 +325,6 @@
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-regex": "^6.0.1" "ansi-regex": "^6.0.1"
@@ -339,7 +340,6 @@
"version": "8.1.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-styles": "^6.1.0", "ansi-styles": "^6.1.0",
@@ -425,7 +425,6 @@
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"engines": { "engines": {
@@ -637,7 +636,6 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -647,7 +645,6 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
@@ -1191,7 +1188,6 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"color-name": "~1.1.4" "color-name": "~1.1.4"
@@ -1204,7 +1200,6 @@
"version": "1.1.4", "version": "1.1.4",
"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==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/combined-stream": { "node_modules/combined-stream": {
@@ -1389,7 +1384,6 @@
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
@@ -1588,7 +1582,6 @@
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/ejs": { "node_modules/ejs": {
@@ -1682,22 +1675,10 @@
"mime": "^2.5.2" "mime": "^2.5.2"
} }
}, },
"node_modules/electron-window-state": {
"version": "5.0.3",
"license": "MIT",
"dependencies": {
"jsonfile": "^4.0.0",
"mkdirp": "^0.5.1"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/end-of-stream": { "node_modules/end-of-stream": {
@@ -1903,7 +1884,6 @@
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cross-spawn": "^7.0.0", "cross-spawn": "^7.0.0",
@@ -1920,7 +1900,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=14" "node": ">=14"
@@ -2377,7 +2356,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -2428,7 +2406,6 @@
"version": "3.4.3", "version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"@isaacs/cliui": "^8.0.2" "@isaacs/cliui": "^8.0.2"
@@ -2779,13 +2756,13 @@
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.6", "version": "1.2.6",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/minipass": { "node_modules/minipass": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -2818,16 +2795,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/mkdirp": {
"version": "0.5.6",
"license": "MIT",
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"license": "MIT" "license": "MIT"
@@ -2920,7 +2887,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true,
"license": "BlueOak-1.0.0" "license": "BlueOak-1.0.0"
}, },
"node_modules/parse-node-version": { "node_modules/parse-node-version": {
@@ -2943,7 +2909,6 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -2953,7 +2918,6 @@
"version": "1.11.1", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"lru-cache": "^10.2.0", "lru-cache": "^10.2.0",
@@ -2970,7 +2934,6 @@
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/pend": { "node_modules/pend": {
@@ -3057,10 +3020,11 @@
} }
}, },
"node_modules/punycode": { "node_modules/punycode": {
"version": "2.1.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -3232,7 +3196,6 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
"devOptional": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/semver": { "node_modules/semver": {
@@ -3273,7 +3236,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"shebang-regex": "^3.0.0" "shebang-regex": "^3.0.0"
@@ -3286,7 +3248,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@@ -3449,7 +3410,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
@@ -3465,7 +3425,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
@@ -3480,7 +3439,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
@@ -3494,7 +3452,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
@@ -3503,6 +3460,90 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/stylus": {
"version": "0.64.0",
"resolved": "https://registry.npmjs.org/stylus/-/stylus-0.64.0.tgz",
"integrity": "sha512-ZIdT8eUv8tegmqy1tTIdJv9We2DumkNZFdCF5mz/Kpq3OcTaxSuCAYZge6HKK2CmNC02G1eJig2RV7XTw5hQrA==",
"license": "MIT",
"dependencies": {
"@adobe/css-tools": "~4.3.3",
"debug": "^4.3.2",
"glob": "^10.4.5",
"sax": "~1.4.1",
"source-map": "^0.7.3"
},
"bin": {
"stylus": "bin/stylus"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://opencollective.com/stylus"
}
},
"node_modules/stylus/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/stylus/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/stylus/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/stylus/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/stylus/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/sumchecker": { "node_modules/sumchecker": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
@@ -3739,6 +3780,12 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/winreg": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.5.tgz",
"integrity": "sha512-uf7tHf+tw0B1y+x+mKTLHkykBgK2KMs3g+KlzmyMbLvICSHQyB/xOFjTT8qZ3oeTFyU7Bbj4FzXitGG6jvKhYw==",
"license": "BSD-2-Clause"
},
"node_modules/wrap-ansi": { "node_modules/wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -3762,7 +3809,6 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-styles": "^4.0.0", "ansi-styles": "^4.0.0",
@@ -3883,6 +3929,11 @@
} }
}, },
"dependencies": { "dependencies": {
"@adobe/css-tools": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz",
"integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ=="
},
"@develar/schema-utils": { "@develar/schema-utils": {
"version": "2.6.5", "version": "2.6.5",
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
@@ -4046,7 +4097,6 @@
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"requires": { "requires": {
"string-width": "^5.1.2", "string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0", "string-width-cjs": "npm:string-width@^4.2.0",
@@ -4059,26 +4109,22 @@
"ansi-regex": { "ansi-regex": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="
"dev": true
}, },
"ansi-styles": { "ansi-styles": {
"version": "6.2.1", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
"dev": true
}, },
"emoji-regex": { "emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
"dev": true
}, },
"string-width": { "string-width": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"requires": { "requires": {
"eastasianwidth": "^0.2.0", "eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2", "emoji-regex": "^9.2.2",
@@ -4089,7 +4135,6 @@
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^6.0.1" "ansi-regex": "^6.0.1"
} }
@@ -4098,7 +4143,6 @@
"version": "8.1.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"requires": { "requires": {
"ansi-styles": "^6.1.0", "ansi-styles": "^6.1.0",
"string-width": "^5.0.1", "string-width": "^5.0.1",
@@ -4156,7 +4200,6 @@
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"optional": true "optional": true
}, },
"@sindresorhus/is": { "@sindresorhus/is": {
@@ -4317,14 +4360,12 @@
"ansi-regex": { "ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
"dev": true
}, },
"ansi-styles": { "ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": { "requires": {
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
} }
@@ -4718,7 +4759,6 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": { "requires": {
"color-name": "~1.1.4" "color-name": "~1.1.4"
} }
@@ -4726,8 +4766,7 @@
"color-name": { "color-name": {
"version": "1.1.4", "version": "1.1.4",
"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=="
"dev": true
}, },
"combined-stream": { "combined-stream": {
"version": "1.0.8", "version": "1.0.8",
@@ -4860,7 +4899,6 @@
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"requires": { "requires": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
"shebang-command": "^2.0.0", "shebang-command": "^2.0.0",
@@ -4988,8 +5026,7 @@
"eastasianwidth": { "eastasianwidth": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
"dev": true
}, },
"ejs": { "ejs": {
"version": "3.1.10", "version": "3.1.10",
@@ -5057,18 +5094,10 @@
"mime": "^2.5.2" "mime": "^2.5.2"
} }
}, },
"electron-window-state": {
"version": "5.0.3",
"requires": {
"jsonfile": "^4.0.0",
"mkdirp": "^0.5.1"
}
},
"emoji-regex": { "emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"dev": true
}, },
"end-of-stream": { "end-of-stream": {
"version": "1.4.4", "version": "1.4.4",
@@ -5210,7 +5239,6 @@
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"dev": true,
"requires": { "requires": {
"cross-spawn": "^7.0.0", "cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1" "signal-exit": "^4.0.1"
@@ -5219,8 +5247,7 @@
"signal-exit": { "signal-exit": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
"dev": true
} }
} }
}, },
@@ -5515,8 +5542,7 @@
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
"dev": true
}, },
"is-what": { "is-what": {
"version": "3.14.1", "version": "3.14.1",
@@ -5549,7 +5575,6 @@
"version": "3.4.3", "version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
"requires": { "requires": {
"@isaacs/cliui": "^8.0.2", "@isaacs/cliui": "^8.0.2",
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
@@ -5805,13 +5830,13 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.6" "version": "1.2.6",
"dev": true
}, },
"minipass": { "minipass": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="
"dev": true
}, },
"minizlib": { "minizlib": {
"version": "2.1.2", "version": "2.1.2",
@@ -5834,12 +5859,6 @@
} }
} }
}, },
"mkdirp": {
"version": "0.5.6",
"requires": {
"minimist": "^1.2.6"
}
},
"ms": { "ms": {
"version": "2.1.2" "version": "2.1.2"
}, },
@@ -5901,8 +5920,7 @@
"package-json-from-dist": { "package-json-from-dist": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
"dev": true
}, },
"parse-node-version": { "parse-node-version": {
"version": "1.0.1", "version": "1.0.1",
@@ -5915,14 +5933,12 @@
"path-key": { "path-key": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
"dev": true
}, },
"path-scurry": { "path-scurry": {
"version": "1.11.1", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"requires": { "requires": {
"lru-cache": "^10.2.0", "lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
@@ -5931,8 +5947,7 @@
"lru-cache": { "lru-cache": {
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
"dev": true
} }
} }
}, },
@@ -5999,9 +6014,9 @@
} }
}, },
"punycode": { "punycode": {
"version": "2.1.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true "dev": true
}, },
"quick-lru": { "quick-lru": {
@@ -6130,8 +6145,7 @@
"sax": { "sax": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
"devOptional": true
}, },
"semver": { "semver": {
"version": "7.6.3", "version": "7.6.3",
@@ -6157,7 +6171,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": { "requires": {
"shebang-regex": "^3.0.0" "shebang-regex": "^3.0.0"
} }
@@ -6165,8 +6178,7 @@
"shebang-regex": { "shebang-regex": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
"dev": true
}, },
"shellwords": { "shellwords": {
"version": "0.1.1" "version": "0.1.1"
@@ -6277,7 +6289,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": { "requires": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -6288,7 +6299,6 @@
"version": "npm:string-width@4.2.3", "version": "npm:string-width@4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": { "requires": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -6299,7 +6309,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
} }
@@ -6308,11 +6317,63 @@
"version": "npm:strip-ansi@6.0.1", "version": "npm:strip-ansi@6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
} }
}, },
"stylus": {
"version": "0.64.0",
"resolved": "https://registry.npmjs.org/stylus/-/stylus-0.64.0.tgz",
"integrity": "sha512-ZIdT8eUv8tegmqy1tTIdJv9We2DumkNZFdCF5mz/Kpq3OcTaxSuCAYZge6HKK2CmNC02G1eJig2RV7XTw5hQrA==",
"requires": {
"@adobe/css-tools": "~4.3.3",
"debug": "^4.3.2",
"glob": "^10.4.5",
"sax": "~1.4.1",
"source-map": "^0.7.3"
},
"dependencies": {
"brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"requires": {
"balanced-match": "^1.0.0"
}
},
"glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"requires": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
}
},
"minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"requires": {
"brace-expansion": "^2.0.1"
}
},
"minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
},
"source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="
}
}
},
"sumchecker": { "sumchecker": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
@@ -6479,6 +6540,11 @@
"isexe": "^2.0.0" "isexe": "^2.0.0"
} }
}, },
"winreg": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.5.tgz",
"integrity": "sha512-uf7tHf+tw0B1y+x+mKTLHkykBgK2KMs3g+KlzmyMbLvICSHQyB/xOFjTT8qZ3oeTFyU7Bbj4FzXitGG6jvKhYw=="
},
"wrap-ansi": { "wrap-ansi": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -6494,7 +6560,6 @@
"version": "npm:wrap-ansi@7.0.0", "version": "npm:wrap-ansi@7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": { "requires": {
"ansi-styles": "^4.0.0", "ansi-styles": "^4.0.0",
"string-width": "^4.1.0", "string-width": "^4.1.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "bsky-desktop", "name": "bsky-desktop",
"version": "1.1.1", "version": "1.1.3",
"description": "A desktop app of bsky.app", "description": "A desktop app of bsky.app",
"main": "src/app/main.js", "main": "src/app/main.js",
"scripts": { "scripts": {
@@ -24,12 +24,13 @@
"@electron/remote": "^2.1.2", "@electron/remote": "^2.1.2",
"adm-zip": "^0.5.12", "adm-zip": "^0.5.12",
"axios": "^1.6.8", "axios": "^1.6.8",
"electron-window-state": "^5.0.3",
"less": "^4.2.1", "less": "^4.2.1",
"log4js": "^6.9.1", "log4js": "^6.9.1",
"node-notifier": "^10.0.0", "node-notifier": "^10.0.0",
"semver": "^7.6.3", "semver": "^7.6.3",
"stylus": "^0.64.0",
"usercss-meta": "^0.12.0", "usercss-meta": "^0.12.0",
"v8-compile-cache": "^2.3.0" "v8-compile-cache": "^2.3.0",
"winreg": "^1.2.5"
} }
} }

View File

@@ -1,30 +1,26 @@
const { app, BrowserWindow, BrowserView, globalShortcut, ipcMain, Tray, Menu, protocol, session, dialog } = require("electron"); const { app, BrowserWindow, BrowserView, globalShortcut, ipcMain, Tray, Menu, protocol, session, dialog } = require("electron");
const electronremote = require("@electron/remote/main"); const electronremote = require("@electron/remote/main");
//const asar = require('@electron/asar'); //const asar = require('@electron/asar');
const windowStateKeeper = require("electron-window-state"); const windowStateKeeper = require("./window-state/index");
const { setupTitlebar, attachTitlebarToWindow } = require("./titlebar/main"); const { setupTitlebar, attachTitlebarToWindow } = require("./titlebar/main");
const openAboutWindow = require("./about-window/src/index").default; const openAboutWindow = require("./about-window/src/index").default;
const badge = require('./badge'); const badge = require('./badge');
const nodeNotifier = require('node-notifier');
const contextMenu = require('./context-menu'); const contextMenu = require('./context-menu');
const autoUpdater = require('./utils/auto-update'); const autoUpdater = require('./utils/auto-update');
const loadCRX = require('./utils/loadCRX'); const loadCRX = require('./utils/loadCRX');
const userStyles = require('./utils/userStyles'); const userStyles = require('./utils/userStyles');
const log4js = require("log4js"); const log4js = require("log4js");
//const axios = require("axios");
const path = require("path"); const path = require("path");
const fs = require("fs"); const fs = require("fs");
const os = require("os"); const os = require("os");
require('v8-compile-cache'); require('v8-compile-cache');
// Load package.json and contributors.json
const packageJson = require(path.join(__dirname, '..', '..', 'package.json')); const packageJson = require(path.join(__dirname, '..', '..', 'package.json'));
const contributors = require(path.join(__dirname, 'contributors.json')); const contributors = require(path.join(__dirname, 'contributors.json'));
// Check if app is ran from the installer dmg (macOS)
if (process.platform === 'darwin' && app.isPackaged && app.isInApplicationsFolder()) {
// Creeate a dialog to ask the user to move the app to the Applications folder
dialog.showErrorBox('Move to Applications folder', 'Please move the app to the Applications folder to ensure it works correctly.');
app.quit();
};
// isUpdaing: // isUpdaing:
global.isUpdating = false; global.isUpdating = false;
@@ -44,9 +40,10 @@ global.paths = {
home: os.homedir(), home: os.homedir(),
temp: path.join(os.tmpdir(), global.appInfo.name), temp: path.join(os.tmpdir(), global.appInfo.name),
}; };
global.paths.updateDir = path.join(global.paths.data, 'update'); global.paths.user = path.join(global.paths.data, 'user');
global.paths.extensions = path.join(global.paths.data, 'extensions'); global.paths.updateDir = path.join(global.paths.user, 'update');
global.paths.userstyles = path.join(global.paths.data, 'userstyles'); global.paths.extensions = path.join(global.paths.user, 'extensions');
global.paths.userstyles = path.join(global.paths.user, 'userstyles');
// URLs: // URLs:
global.urls = { global.urls = {
@@ -61,6 +58,36 @@ global.settings.account = `${global.settings.general}/account`;
global.settings.appearance = `${global.settings.general}/appearance`; global.settings.appearance = `${global.settings.general}/appearance`;
global.settings.privacy = `${global.settings.general}/privacy-and-security`; global.settings.privacy = `${global.settings.general}/privacy-and-security`;
// Check if app is run from the installer dmg (macOS)
if (process.platform === 'darwin' && app.isPackaged && !app.isInApplicationsFolder()) {
const response = dialog.showMessageBoxSync({
type: 'question',
buttons: ['Yes', 'No'],
title: 'Move to Applications folder',
message: 'Please move the app to the Applications folder to ensure it works correctly. Would you like to move it now?'
});
if (response === 0) { // User clicked 'Yes'
const appPath = app.getPath('exe');
const applicationsFolder = '/Applications';
const appName = path.basename(appPath);
const destinationPath = path.join(applicationsFolder, appName);
// Try to move the app
fs.rename(appPath, destinationPath, (err) => {
if (err) {
dialog.showErrorBox('Move Failed', 'Failed to move the app to the Applications folder.');
} else {
dialog.showInformationBox({ message: 'The app has been moved to the Applications folder. Please restart it.' });
app.quit();
}
});
} else {
dialog.showErrorBox('Move to Applications folder', 'Please move the app to the Applications folder to ensure it works correctly.');
app.quit();
}
}
// Badge options: // Badge options:
const badgeOptions = { const badgeOptions = {
fontColor: '#FFFFFF', // The font color fontColor: '#FFFFFF', // The font color
@@ -124,10 +151,10 @@ if (!fs.existsSync(global.paths.temp)) {
fs.mkdirSync(global.paths.temp, { recursive: true }); fs.mkdirSync(global.paths.temp, { recursive: true });
}; };
// Create update directory if it does not exist: // Create user directory if it does not exist:
if (!fs.existsSync(global.paths.updateDir)) { if (!fs.existsSync(global.paths.data, 'user')) {
logger.info("Creating Update Directory"); logger.info("Creating User Directory");
fs.mkdirSync(global.paths.updateDir, { recursive: true }); fs.mkdirSync(global.paths.user, { recursive: true });
}; };
// Create extensions directory if it does not exist: // Create extensions directory if it does not exist:
@@ -142,6 +169,12 @@ if (!fs.existsSync(global.paths.userstyles)) {
fs.mkdirSync(global.paths.userstyles, { recursive: true }); fs.mkdirSync(global.paths.userstyles, { recursive: true });
}; };
// Create update directory if it does not exist:
if (!fs.existsSync(global.paths.updateDir)) {
logger.info("Creating Update Directory");
fs.mkdirSync(global.paths.updateDir, { recursive: true });
};
// improve performance on linux? // improve performance on linux?
if (process.platform !== "win32" && process.platform !== "darwin") { if (process.platform !== "win32" && process.platform !== "darwin") {
logger.log("Disabling Hardware Acceleration and Transparent Visuals"); logger.log("Disabling Hardware Acceleration and Transparent Visuals");
@@ -156,16 +189,16 @@ setupTitlebar();
// Disable reload and F5 if not in dev mode: // Disable reload and F5 if not in dev mode:
if (process.env.NODE_ENV !== 'development') { if (process.env.NODE_ENV !== 'development') {
app.on('browser-window-focus', function () { app.on('browser-window-focus', function () {
globalShortcut.register("CommandOrControl+R", () => { /*globalShortcut.register("CommandOrControl+R", () => {
//console.log("CommandOrControl+R is pressed: Shortcut Disabled"); //console.log("CommandOrControl+R is pressed: Shortcut Disabled");
}); });
globalShortcut.register("F5", () => { globalShortcut.register("F5", () => {
//console.log("F5 is pressed: Shortcut Disabled"); //console.log("F5 is pressed: Shortcut Disabled");
}); });*/
}); });
app.on('browser-window-blur', function () { app.on('browser-window-blur', function () {
globalShortcut.unregister('CommandOrControl+R'); /*globalShortcut.unregister('CommandOrControl+R');
globalShortcut.unregister('F5'); globalShortcut.unregister('F5');*/
}); });
}; };
@@ -228,14 +261,14 @@ function createWindow() {
PageView.setBounds({ PageView.setBounds({
x: 0, x: 0,
y: 30, y: 30,
width: mainWindow.getBounds().width, width: mainWindow.isMaximized() ? mainWindow.getBounds().width - 16 : mainWindow.getBounds().width,
height: mainWindow.getBounds().height - 30, height: mainWindow.getBounds().height - 30,
}); });
mainWindow.on("resize", () => { mainWindow.on("resize", () => {
PageView.setBounds({ PageView.setBounds({
x: 0, x: 0,
y: 30, y: 30,
width: mainWindow.getBounds().width, width: mainWindow.isMaximized() ? mainWindow.getBounds().width - 16 : mainWindow.getBounds().width,
height: mainWindow.getBounds().height - 30, height: mainWindow.getBounds().height - 30,
}); });
}); });
@@ -505,81 +538,198 @@ app.whenReady().then(() => {
// Set session: // Set session:
global.session = ses; global.session = ses;
// Initialize the updater:
logger.log("Initializing Updater");
autoUpdater();
// Handle ipc for render: // Handle ipc for render:
ipcMain.on('close-app', (event, arg) => { ipcMain.on('close-app', (event, arg) => {
app.quit(); app.quit();
}); });
ipcMain.on('app:restart', (event, arg) => {
app.relaunch();
app.quit();
});
// Create windows and tray:
createWindow(); createWindow();
createTray(); createTray();
// Load extensions (.crx files): // Wait for splash screen to load before checking for updates, loading extensions and userstyles
logger.log("Checking for extensions"); global.splash.webContents.on('did-finish-load', async () => {
const extensions = fs.readdirSync(global.paths.extensions).filter((file) => file.endsWith('.crx')); // Check for internet connection:
if (extensions.length > 0) { logger.log("Checking for internet connection");
logger.log(`Unpacking ${extensions.length} extensions and loading them`); require('dns').lookup('google.com', err => {
extensions.forEach((extension) => { if (err) {
loadCRX(path.join(global.paths.extensions, extension)); logger.log('No internet connection, showing not connected message');
}); global.PageView.webContents.loadFile(path.join(global.paths.app, 'ui', 'offline.html'));
} else { return;
// Check for unpacked extensions: }
const unpackedExtensions = fs.readdirSync(global.paths.extensions).filter((file) => fs.lstatSync(path.join(global.paths.extensions, file)).isDirectory()); logger.log('Internet available, checking for updates');
// Initialize the updater:
logger.log("Initializing Updater");
global.splash.webContents.send('ui:progtext', { title: 'Checking for updates...', subtitle: 'Awaiting response' });
autoUpdater.checkForUpdates().then(async (result) => {
//console.log(result);
switch (result.code) {
case 'update-available':
global.isUpdating = true;
logger.log("Update available, downloading");
global.splash.webContents.send('ui:progtext', { title: 'Update available', subtitle: 'Downloading update' });
try {
const update = await autoUpdater.downloadUpdate();
//console.log(update);
if (update.err && update.err.code === 'unpackaged') {
logger.warn("Update failed to download, unpackaged app");
global.splash.webContents.send('ui:progtext', { title: 'Not downloading update', subtitle: 'Unpackaged app' });
global.isUpdating = false;
} else {
if (update.err) {
logger.error("Update failed to download");
console.log(update.err);
global.splash.webContents.send('ui:progtext', { title: 'Failed to download update', subtitle: 'Continuing as normal...' });
};
switch (update.code) {
case 'downloaded':
logger.log("Update downloaded, installing");
global.splash.webContents.send('ui:progtext', { title: 'Update downloaded', subtitle: 'Installing update' });
try {
const install = await autoUpdater.installUpdate(update.path);
//console.log(install);
if (install.err) {
logger.error("Failed to install update");
console.log(install.err);
global.splash.webContents.send('ui:progtext', { title: 'Failed to install update', subtitle: 'Continuing as normal...' });
} else {
if (install.code === 'update-installed') {
logger.log("Update installed, restarting");
global.splash.webContents.send('ui:progtext', { title: 'Update installed', subtitle: 'Restarting...' });
app.relaunch();
app.quit();
} else {
logger.error("Failed to install update");
global.splash.webContents.send('ui:progtext', { title: 'Failed to install update', subtitle: 'Continuing as normal...' });
};
};
} catch (error) {
logger.error(`Error installing update:`, error);
global.splash.webContents.send('ui:progtext', { title: 'Error installing update', subtitle: ' ' });
};
break;
case 'download-failed':
logger.error("Failed to download update");
global.splash.webContents.send('ui:progtext', { title: 'Failed to download update', subtitle: 'Continuing as normal...' });
global.isUpdating = false;
global.mainWindow.show();
global.splash.destroy();
break;
default:
logger.error("Unknown update download status");
global.splash.webContents.send('ui:progtext', { title: 'Unknown update download status', subtitle: ' ' });
break;
};
};
} catch (error) {
logger.error(`Error downloading update:`, error);
global.splash.webContents.send('ui:progtext', { title: 'Error downloading update', subtitle: ' ' });
};
break;
case 'no-update':
logger.log("No update available");
global.splash.webContents.send('ui:progtext', { title: 'Checking for updates...', subtitle: 'Up to date!' });
break;
case 'check-failed':
logger.warn("Failed to check for updates");
global.splash.webContents.send('ui:progtext', { title: 'Failed to check for updates', subtitle: ' ' });
break;
case 'old-os':
logger.warn("Old OS, unable to update");
global.splash.webContents.send('ui:progtext', { title: 'Update not available', subtitle: 'Old OS' });
break;
default:
logger.warn("Unknown update status");
global.splash.webContents.send('ui:progtext', { title: 'Unknown update status', subtitle: ' ' });
break;
};
}).catch((error) => {
logger.error(`Error checking for updates: ${error}`);
global.splash.webContents.send('ui:progtext', { title: 'Error checking for updates', subtitle: ' ' });
}).finally(async () => {
// Load extensions (.crx files):
logger.log("Checking for extensions");
global.splash.webContents.send('ui:progtext', { title: 'Checking for extensions', subtitle: ' ' });
const extensions = fs.readdirSync(global.paths.extensions).filter((file) => file.endsWith('.crx'));
if (extensions.length > 0) {
logger.log(`Unpacking ${extensions.length} extensions and loading them`);
global.splash.webContents.send('ui:progtext', { title: `Unpacking ${extensions.length} extensions` });
extensions.forEach((extension) => {
logger.log(`Loading extension: ${extension}`);
global.splash.webContents.send('ui:progtext', { title: `Loading extension: ${extension}` });
loadCRX(path.join(global.paths.extensions, extension));
});
} else {
// Check for unpacked extensions:
const unpackedExtensions = fs.readdirSync(global.paths.extensions).filter((file) => fs.lstatSync(path.join(global.paths.extensions, file)).isDirectory());
// Check if the directory contains a manifest.json file // Check if the directory contains a manifest.json file
unpackedExtensions.forEach((extension) => { unpackedExtensions.forEach((extension) => {
const manifestPath = path.join(global.paths.extensions, extension, 'manifest.json'); const manifestPath = path.join(global.paths.extensions, extension, 'manifest.json');
if (fs.existsSync(manifestPath)) { if (fs.existsSync(manifestPath)) {
logger.log(`Loading unpacked extension: ${extension}`); logger.log(`Loading unpacked extension: ${extension}`);
session.defaultSession.loadExtension(path.join(global.paths.extensions, extension)).then(({ id }) => { global.splash.webContents.send('ui:progtext', { title: `Loading unpacked extension: ${extension}` });
logger.log(`Extension loaded with ID: ${id}`); session.defaultSession.loadExtension(path.join(global.paths.extensions, extension)).then(({ id }) => {
}).catch((error) => { logger.log(`Extension loaded with ID: ${id}`);
logger.error(`Failed to load extension: ${error}`); }).catch((error) => {
}); logger.error(`Failed to load extension: ${error}`);
} else { });
logger.warn(`Skipping directory ${extension} as it does not contain a manifest.json file`); } else {
}; logger.warn(`Skipping directory ${extension} as it does not contain a manifest.json file`);
}); };
}; });
};
// Load userstyles // Load userstyles
logger.log("Checking for userstyles"); logger.log("Checking for userstyles");
const userStylesDir = path.join(global.paths.userstyles); global.splash.webContents.send('ui:progtext', { title: 'Checking for userstyles' });
if (fs.existsSync(userStylesDir)) { const userStylesDir = path.join(global.paths.userstyles);
const files = fs.readdirSync(userStylesDir); if (fs.existsSync(userStylesDir)) {
if (files.length > 0) { const files = fs.readdirSync(userStylesDir).filter((file) => file.endsWith('.css'));
const userStylePromises = files.map(async file => { if (files.length > 0) {
const cssFile = path.join(userStylesDir, file); logger.log(`Loading ${files.length} userstyles`);
// Parse the CSS file const userStylePromises = files.map(async file => {
try { const cssFile = path.join(userStylesDir, file);
const cssContent = fs.readFileSync(cssFile, 'utf-8'); // Parse the CSS file
const result = await userStyles.parseCSS(cssContent); try {
const cssContent = fs.readFileSync(cssFile, 'utf-8');
const result = await userStyles.parseCSS(cssContent);
logger.info(`Loading userstyle: ${result.metadata.name}`); logger.info(`Loading userstyle: ${result.metadata.name}`);
// Compile the userstyle // Compile the userstyle
const compiled = await userStyles.compileStyle(result.css, result.metadata); const compiled = await userStyles.compileStyle(result.css, result.metadata);
// Check if the site 'bsky.app' is defined // Check if the site 'bsky.app' is defined
if (compiled.sites?.['bsky.app']) { if (compiled.sites?.['bsky.app']) {
// Apply the userstyle to the PageView // Apply the userstyle to the PageView
await PageView.webContents.insertCSS(compiled.sites['bsky.app']); await PageView.webContents.insertCSS(compiled.sites['bsky.app']);
logger.info(`Applied userstyle: ${result.metadata.name}`); logger.info(`Applied userstyle: ${result.metadata.name}`);
} else { global.splash.webContents.send('ui:progtext', { title: `Applied userstyle: ${result.metadata.name}` });
logger.warn(`Userstyle ${result.metadata.name} does not target 'bsky.app'`); } else {
if (compiled.error) {
logger.warn(`Error loading userstyle: ${compiled.error.message}`);
} else {
logger.warn(`Userstyle ${result.metadata.name} does not target 'bsky.app'`);
}
}
} catch (error) {
logger.error(`Error loading userstyle: ${file}`, error);
}
});
await Promise.all(userStylePromises);
} }
} catch (error) {
logger.error(`Error loading userstyle: ${file}`, error);
} }
}); });
});
Promise.all(userStylePromises); });
}
}
} else { } else {
logger.log("Failed to get singleInstanceLock, Quitting"); logger.log("Failed to get singleInstanceLock, Quitting");
app.quit(); app.quit();

View File

@@ -90,7 +90,7 @@ class Updater extends EventEmitter {
}; };
this.options = Object.assign({}, def, options); this.options = Object.assign({}, def, options);
this.options.cacheDirectory = path.resolve(this.options.tmpdir, this.options.name); this.options.cacheDirectory = path.resolve(this.options.tmpdir, this.options.name);
this.options.headers['user-agent'] = this.options.headers['user-agent'] || 'asar-updater/v0.0.2 (https://github.com/zce/asar-updater)'; this.options.headers['user-agent'] = this.options.headers['user-agent'] || 'Mozilla/5.0 asar-updater/v0.3.3 (https://github.com/zce/asar-updater)';
fs.existsSync(this.options.cacheDirectory) || fs.mkdirSync(this.options.cacheDirectory); fs.existsSync(this.options.cacheDirectory) || fs.mkdirSync(this.options.cacheDirectory);
} }
@@ -207,7 +207,7 @@ class Updater extends EventEmitter {
quitAndInstall(timeout) { quitAndInstall(timeout) {
setTimeout(() => { setTimeout(() => {
app.relaunch({ args: process.argv.slice(1) + ['--relaunch'] }); app.relaunch({ args: process.argv.slice(1) + ['--relaunch', '--update-installed'] });
app.exit(0); app.exit(0);
}, timeout || 100); }, timeout || 100);
} }

View File

@@ -1,9 +1,11 @@
const path = require('path');
const os = require('os');
const fs = require('fs');
const childProcess = require('child_process'); const childProcess = require('child_process');
const { app } = require('electron'); const { app } = require('electron');
const log4js = require('log4js'); const log4js = require('log4js');
const SemVer = require('semver');
const axios = require('axios');
const path = require('path');
const os = require('os');
const fs = require('fs');
// import the asarUpdater module // import the asarUpdater module
const asarUpdater = require('./asarUpdater'); const asarUpdater = require('./asarUpdater');
@@ -14,9 +16,73 @@ const SystemInfo = require('./sysInfo');
// Get the current system platform // Get the current system platform
const sys = new SystemInfo(); const sys = new SystemInfo();
// Detect the app install type
const installType = require('./installType');
// Setup the logger // Setup the logger
const logger = log4js.getLogger("bskydesktop"); const logger = log4js.getLogger("bskydesktop");
// System architecture / Platform
const systemArch = sys.isARM64() ? 'arm64' : sys.isX64() ? '64' : sys.isX86() ? '86' : 'unknown';
const systemPlatform = sys.isWin() ? 'win' : sys.isMac() ? 'mac' : sys.isLinux() ? 'linux' : 'unknown';
// Download url: (arch, platform, installer)
const downloadUrl = 'https://cdn.oxmc.me/apps/bsky-desktop/dl';
// Installer path (used to save the installer)
var installerPath = '';
var installerType = '';
async function detectInstallerType() {
let installerType = 'unknown';
// First check if the app is paclaged
if (!app.isPackaged) {
logger.warn('App is not packaged, cannot detect installer type.');
return 'unpackaged';
}
try {
// Check if system is Windows
if (sys.isWin()) {
//console.log('Checking for Windows installer type...');
const res = await installType.getUninstallEntries({ DisplayName: 'bskyDesktop' });
//console.log(res);
// Ensure result is valid before checking properties
if (res.length > 0) {
installerType = res[0].WindowsInstaller === 'MSI' ? 'msi' : 'exe';
} else {
// Default to exe if no installer type is found
installerType = 'exe';
}
}
// Check if system is macOS
if (sys.isMac()) {
const res = await installType.checkAppInstallationMethod();
switch (res.type) { // Use res.type instead of res directly
case 'MAS':
installerType = 'mas';
break;
case 'PKG':
installerType = 'pkg';
break;
case 'ZIP/DMG':
installerType = 'dmg';
break;
}
}
} catch (err) {
logger.error('Failed to detect installer type:', err);
}
return installerType;
}
// Asar updater
function asarUpdate() { function asarUpdate() {
asarUpdater.init(); asarUpdater.init();
@@ -62,7 +128,7 @@ function asarUpdate() {
// Set the feed URL (only works in packaged app): // Set the feed URL (only works in packaged app):
if (app.isPackaged) { if (app.isPackaged) {
logger.log("Setting Feed URL for app.asar"); logger.log("Setting Feed URL for app.asar");
asarUpdater.setFeedURL(path.join(global.paths.app_root), 'https://cdn.oxmc.me/internal/bsky-desktop/update/core'); asarUpdater.setFeedURL(path.join(global.paths.app_root), 'https://cdn.oxmc.me/apps/bsky-desktop/update/core');
}; };
//Check for updates: //Check for updates:
@@ -70,88 +136,379 @@ function asarUpdate() {
if (app.isPackaged) { if (app.isPackaged) {
const UPDATE_CHECK = 1000 * 60 * 60 * 4 // 4 hours const UPDATE_CHECK = 1000 * 60 * 60 * 4 // 4 hours
setInterval(() => { setInterval(() => {
//asarUpdater.checkForUpdates(); asarUpdater.checkForUpdates();
}, UPDATE_CHECK); }, UPDATE_CHECK);
//asarUpdater.checkForUpdates(); asarUpdater.checkForUpdates();
} else { } else {
logger.warn("Not checking for updates as app is not packaged"); logger.warn("Not checking for updates as app is not packaged");
}; };
} }
function checkForUpdates() { // Check for updates
// Current system information async function checkForUpdates() {
logger.log('Current system information:', sys.platform, sys.getVersion(), sys.arch); return new Promise((resolve, reject) => {
// Current system information
logger.log('Current system information:', sys.platform, sys.getVersion(), sys.arch);
// Check if the current system is Windows // Check if the current system is Windows
if (sys.isWin()) { if (sys.isWin()) {
// Check if the system is before Windows 10 // Check if the system is before Windows 10
if (sys.earlierThan('10.0.0')) { if (sys.earlierThan('10.0.0')) {
// Windows 10 and above are supported, but windows 7 and 8 are not supported // Windows 10 and above are supported, but windows 7 and 8 are not supported
logger.error('Windows 7 and 8 are not supported, please upgrade to Windows 10 or above, not updating...'); logger.error('Windows 7 and 8 are not supported, please upgrade to Windows 10 or above, not updating...');
} else { resolve({ err: 'old-os', msg: 'Windows 7 and 8 are not supported, please upgrade to Windows 10 or above, not updating...' });
// Check for updates, and if there are updates, download and install them
logger.log('Checking for updates (win)...');
}
}
// Check if the current system is macOS
if (sys.isMac()) {
let macArch = '';
// Check the current version of macOS, and whether we can use the pkg installer
if (sys.laterThan('10.0.0')) {
// Check if system is after macOS 10 (11, 12, etc.)
if (sys.laterThan('11.0.0')) {
// macOS 11 and above support ARM64, check if system is ARM64
logger.log('Checkking system architecture...');
if (sys.isARM64()) {
// System is ARM64 (mac-arm64)
macArch = 'arm64';
} else {
// System is x64 (mac-x64)
macArch = 'x64';
}
} else { } else {
// macOS 10 is mostly x64, but some versions are ARM64 // Check for updates, and if there are updates, download and install them
macArch = 'x64'; logger.log('Checking for updates (win)...');
axios.get('https://cdn.oxmc.me/apps/bsky-desktop/update/core').then((res) => {
//console.log(res.data);
const latestVersion = res.data.version;
const currentVersion = app.getVersion();
if (SemVer.gt(latestVersion, currentVersion)) {
//logger.log('Update available:', latestVersion);
global.PageView.webContents.send('ui:notif', JSON.stringify({ title: 'Update', message: 'An update is available' }));
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Update Available', subtitle: 'An update is available! Downloading...' });
resolve({ code: 'update-available', msg: 'An update is available.', info: { latest: latestVersion, current: currentVersion, response: res.data } });
} else {
//logger.log('No updates available.');
resolve({ code: 'no-update', msg: 'No updates available.' });
}
}).catch((err) => {
logger.error('Failed to check for updates:', err);
resolve({ code: 'check-failed', msg: 'Failed to check for updates.' });
});
} }
logger.log('System architecture:', macArch);
// Check for updates, and if there are updates, download and install them
logger.log('Checking for updates (mac)...');
// Run the .pkg installer
const pkgPath = path.join(global.paths.updateDir, 'bsky-desktop.pkg');
const command = `sudo installer -pkg ${pkgPath} -target /`;
// Spawn a new shell
/*const shellProcess = spawn('sh', ['-c', command], {
stdio: 'inherit', // Pipe input/output to/from the shell
});
shellProcess.on('error', (err) => {
console.error('Failed to spawn shell:', err);
});
shellProcess.on('close', (code) => {
if (code === 0) {
console.log('Update installed successfully.');
} else {
console.error(`Shell process exited with code ${code}.`);
}
});*/
} else {
// macOS versions before 10 are not supported
logger.error('macOS versions before 10 are not supported, not updating...');
} }
}
// Check if the current system is Linux // Check if the current system is macOS
if (sys.isLinux()) { if (sys.isMac()) {
// Check for updates, and if there are updates, download and install them (no system version check) // Check the current version of macOS, and whether we can use the pkg installer
// Linux versions use AppImage, so we instead need to check for a new asar file so that the app can if (sys.laterThan('10.0.0')) {
// load the new asar instead of the packaged one (or even just delete the old appimage and download a new one) // Check for updates, and if there are updates, download and install them
logger.log('Checking for updates (linux)...'); logger.log('Checking for updates (mac)...');
asarUpdate();
} // Check for updates
axios.get('https://cdn.oxmc.me/apps/bsky-desktop/update/core').then((res) => {
//console.log(res.data);
const latestVersion = res.data.version;
const currentVersion = app.getVersion();
if (SemVer.gt(latestVersion, currentVersion)) {
//logger.log('Update available:', latestVersion);
global.PageView.webContents.send('ui:notif', JSON.stringify({ title: 'Update', message: 'An update is available' }));
if (global.splash) global.splash.webContents.send('ui:progtext', { title: 'Update Available', subtitle: 'An update is available! Downloading...' });
resolve({ code: 'update-available', msg: 'An update is available.', info: { latest: latestVersion, current: currentVersion, response: res.data } });
} else {
//logger.log('No updates available.');
resolve({ code: 'no-update', msg: 'No updates available.' });
}
}).catch((err) => {
logger.error('Failed to check for updates:', err);
resolve({ code: 'check-failed', msg: 'Failed to check for updates.' });
});
} else {
// macOS versions before 10 are not supported
logger.error('macOS versions before 10 are not supported, not updating...');
resolve({ err: 'old-os', msg: 'macOS versions before 10 are not supported, not updating...' });
}
}
// Check if the current system is Linux
if (sys.isLinux()) {
// Check for updates, and if there are updates, download and install them (no system version check)
// Linux versions use AppImage, so we instead need to check for a new asar file so that the app can
// load the new asar instead of the packaged one (or even just delete the old appimage and download a new one)
logger.log('Checking for updates (linux)...');
asarUpdate();
}
}).catch((err) => {
logger.error('Failed to check for updates:', err);
});
} }
module.exports = checkForUpdates; // Download the update installer
async function downloadUpdate() {
return new Promise(async (resolve, reject) => {
// download the update installer
//logger.log('Downloading update...');
// Create the update directory if it doesn't exist
if (!fs.existsSync(global.paths.updateDir)) {
fs.mkdirSync(global.paths.updateDir);
}
// Get the installer name
const installerName = `bsky-desktop-${sys.platform}-${systemArch}.exe`;
installerPath = path.join(global.paths.updateDir, installerName);
// Detect the installer type
installerType = await detectInstallerType();
//installerType = 'exe'; // For testing purposes
//logger.info('Installer type:', installerType);
// if the installer type is unknown, return an error
if (installerType === 'unknown') {
//logger.error('Failed to detect installer type:', installerType);
reject({ code: 'unknown-installer', msg: 'Failed to detect installer type.', err: installerType });
return;
}
// If the installer type is unpackaged, return and continue
if (installerType === 'unpackaged') {
//logger.warn('App is not packaged, cannot download update.');
reject({ code: 'unpackaged', msg: 'App is not packaged, cannot download update.' });
return;
}
// download the installer as a stream
const installerStream = fs.createWriteStream(installerPath);
// download the installer
axios({
method: 'get',
url: downloadUrl,
responseType: 'stream',
headers: {
"x-platform": systemPlatform,
"x-arch": systemArch,
"x-installMethod": installerType
}
}).then((res) => {
// pipe the installer stream to the installer file
res.data.pipe(installerStream);
// close the installer stream
installerStream.on('finish', () => {
installerStream.close();
// resolve the promise
resolve({ code: 'downloaded', msg: 'Update downloaded successfully.', path: installerPath });
});
// handle errors
installerStream.on('error', (err) => {
//logger.error('Failed to download and save update:', err);
reject({ code: 'download-save-failed', msg: 'Failed to download and save update.', err: err });
});
// handle close
installerStream.on('close', () => {
//logger.log('Installer stream closed.');
});
}).catch((err) => {
logger.error('Failed to download and save update:', err);
reject({ code: 'download-failed', msg: 'Failed to download update.', err: err });
});
}).catch((err) => {
//logger.error('Failed to download update:', err);
return { code: 'download-failed', msg: 'Failed to download update.', err: err };
});
}
async function installUpdate(installer) {
return new Promise((resolve, reject) => {
try {
// Current system information
//logger.log('Current system information:', sys.platform, sys.getVersion(), sys.arch);
// Check if the current system is Windows
if (sys.isWin()) {
// Check if the system is before Windows 10
if (sys.earlierThan('10.0.0')) {
// Windows 10 and above are supported, but windows 7 and 8 are not supported
logger.error('Windows 7 and 8 are not supported, please upgrade to Windows 10 or above, not installing updating...');
reject({ err: 'old-os', msg: 'Windows 7 and 8 are not supported, please upgrade to Windows 10 or above, not installing update...' });
} else {
// Install the update
logger.log('Installing update (win)...');
// Check if the installer path is valid
installerPath = path.resolve(installer);
if (!fs.existsSync(installerPath)) {
logger.error('Installer path is invalid:', installerPath);
reject({ code: 'invalid-installer', msg: 'Installer path is invalid.', path: installerPath });
}
// Create the log file
const logStream = fs.createWriteStream(path.join(global.paths.updateDir, 'install.log'), { flags: 'a' });
// Run the installer (msi or exe)
switch (installerType) {
case 'msi':
// Run the msi installer /passive, /quiet, /qn, /norestart
const msiExec = childProcess.spawn('cmd.exe', ['/c', 'msiexec', '/i "${installerPath}"', '/qn', '/norestart', `/log ${path.join(global.paths.updateDir, 'installer-exec.log')}`], {
detached: true,
stdio: ['ignore', 'pipe', 'pipe']
});
msiExec.on('error', (err) => {
//console.error('Failed to start process:', err);
reject({ code: 'process-failed', msg: 'Failed to start installation process.', err: err });
});
msiExec.on('exit', (code, signal) => {
if (code === 0) {
//console.log('Update installed successfully.');
resolve({ code: 'update-installed', msg: 'Update installed successfully.' });
} else {
//console.error(`Installer process exited with code: ${code}, signal: ${signal}`);
reject({ code: 'install-failed', msg: 'Installer process failed.', exitCode: code, signal: signal });
}
});
msiExec.stdout.on('data', (data) => {
//console.log(`stdout: ${data}`);
logStream.write(data);
});
msiExec.stderr.on('data', (data) => {
//console.error(`stderr: ${data}`);
logStream.write(data);
});
app.quit();
break;
case 'exe':
// Run the exe installer /s
const exeExec = childProcess.spawn('cmd.exe', ['/c', installerPath], {
detached: true,
stdio: ['ignore', 'pipe', 'pipe']
});
exeExec.on('error', (err) => {
//console.error('Failed to start process:', err);
reject({ code: 'process-failed', msg: 'Failed to start installation process.', err: err });
});
exeExec.on('exit', (code, signal) => {
if (code === 0) {
//console.log('Update installed successfully.');
resolve({ code: 'update-installed', msg: 'Update installed successfully.' });
} else {
//console.error(`Installer process exited with code: ${code}, signal: ${signal}`);
reject({ code: 'install-failed', msg: 'Installer process failed.', exitCode: code, signal: signal });
}
});
exeExec.stdout.on('data', (data) => {
//console.log(`stdout: ${data}`);
logStream.write(data);
});
exeExec.stderr.on('data', (data) => {
//console.error(`stderr: ${data}`);
logStream.write(data);
});
app.quit();
break;
default:
//logger.error('Installer type is invalid:', installerType);
reject({ code: 'invalid-installer-type', msg: 'Installer type is invalid.', type: installerType });
break;
}
}
}
// Check if the current system is macOS
if (sys.isMac()) {
// Check the current version of macOS, and whether we can use the pkg installer
if (sys.laterThan('10.0.0')) {
// Install the update
logger.log('Installing update (mac)...');
// Check if the installer path is valid
installerPath = path.resolve(installer);
if (!fs.existsSync(installerPath)) {
logger.error('Installer path is invalid:', installerPath);
reject({ code: 'invalid-installer', msg: 'Installer path is invalid.', path: installerPath });
}
// Create the log file
const logStream = fs.createWriteStream(path.join(global.paths.updateDir, 'install.log'), { flags: 'a' });
// Run the .pkg installer
const command = `sudo installer -pkg ${installerPath} -target /`;
const shellProcess = childProcess.spawn('sh', ['-c', command], {
detached: true,
stdio: ['ignore', 'pipe', 'pipe']
});
shellProcess.on('error', (err) => {
//console.error('Failed to start process:', err);
reject({ code: 'process-failed', msg: 'Failed to start installation process.', err: err });
});
shellProcess.on('exit', (code, signal) => {
if (code === 0) {
//console.log('Update installed successfully.');
resolve({ code: 'update-installed', msg: 'Update installed successfully.' });
} else {
//console.error(`Installer process exited with code: ${code}, signal: ${signal}`);
reject({ code: 'install-failed', msg: 'Installer process failed.', exitCode: code, signal: signal });
}
});
shellProcess.stdout.on('data', (data) => {
//console.log(`stdout: ${data}`);
logStream.write(data);
});
shellProcess.stderr.on('data', (data) => {
//console.error(`stderr: ${data}`);
logStream.write(data);
});
} else {
// macOS versions before 10 are not supported
logger.error('macOS versions before 10 are not supported, not installing update...');
reject({ err: 'old-os', msg: 'macOS versions before 10 are not supported, not installing update...' });
}
}
// Check if the current system is Linux (This should be handled via asarUpdater)
if (sys.isLinux()) {
// Check for updates, and if there are updates, download and install them (no system version check)
// Linux versions use AppImage, so we instead need to check for a new asar file so that the app can
// load the new asar instead of the packaged one (or even just delete the old appimage and download a new one)
//logger.log('Checking for updates (linux)...');
logger.log('This is not implemented yet, please update manually.');
//asarUpdate();
}
} catch (err) {
logger.error('Failed to install update:', err);
reject({ code: 'install-failed', msg: 'Failed to install update.', err: err });
}
});
};
async function downloadAndInstall() {
return new Promise((resolve, reject) => {
// Download the update installer
downloadUpdate().then((res) => {
if (res.code === 'downloaded') {
// Install the update
installUpdate(res.path).then((res) => {
if (res.code === 'install-failed') {
//logger.error('Failed to install update:', res.err);
reject({ code: 'install-failed', msg: 'Failed to install update.', err: res.err });
} else {
//logger.log('Update installed successfully.');
resolve({ code: 'update-installed', msg: 'Update installed successfully.' });
}
});
} else {
//logger.error('Failed to download update:', res.err);
reject({ code: 'download-failed', msg: 'Failed to download update.', err: res.err });
}
}).catch((err) => {
//logger.error('Failed to download and install update:', err);
reject({ code: 'download-install-failed', msg: 'Failed to download and install update.', err: err });
});
});
}
module.exports = {
checkForUpdates,
downloadUpdate,
installUpdate,
downloadAndInstall
};

View File

@@ -0,0 +1,121 @@
const path = require('path');
const { exec } = require('child_process');
const os = require('os');
const fs = require('fs');
// Get system information
const SystemInfo = require('./sysInfo');
// Get the current system platform
const sys = new SystemInfo();
// Only import the registry package if the system is Windows
let Registry;
if (sys.platform === 'win32') {
Registry = require('winreg');
}
// Get the uninstall entries from the registry
async function getUninstallEntries(filter = {}) {
if (sys.platform !== 'win32') {
console.error('This function only works on Windows.');
return [];
}
const registryPaths = [
'HKLM\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall',
'HKLM\\\\Software\\\\Wow6432Node\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall'
];
let results = [];
for (const regPath of registryPaths) {
const regKey = new Registry({ hive: Registry.HKLM, key: regPath });
try {
const subkeys = await new Promise((resolve, reject) => {
regKey.keys((err, keys) => {
if (err) reject(err);
else resolve(keys);
});
});
for (const subkey of subkeys) {
const values = await new Promise((resolve, reject) => {
subkey.values((err, items) => {
if (err) reject(err);
else resolve(items);
});
});
let entry = {};
values.forEach(item => {
if (item.name === 'DisplayName') entry.DisplayName = item.value;
if (item.name === 'Publisher') entry.Publisher = item.value;
if (item.name === 'InstallDate') entry.InstallDate = item.value;
if (item.name === 'DisplayVersion') entry.DisplayVersion = item.value;
if (item.name === 'HelpLink') entry.HelpLink = item.value;
if (item.name === 'UninstallString') entry.UninstallString = item.value;
if (item.name === 'WindowsInstaller') entry.WindowsInstaller = item.value === '1' ? 'MSI' : 'EXE';
});
if (entry.DisplayName && entry.UninstallString) {
// If WindowsInstaller value is missing, check UninstallString
if (!entry.WindowsInstaller) {
entry.WindowsInstaller = entry.UninstallString.includes('msiexec') ? 'MSI' : 'EXE';
}
results.push(entry);
}
}
} catch (error) {
console.error(`Error accessing registry path ${regPath}:`, error);
}
}
results.sort((a, b) => a.DisplayName.localeCompare(b.DisplayName));
// Filter results based on the provided filter (e.g., { DisplayName: 'bskyDesktop' })
if (filter.DisplayName) {
return results.filter(entry => entry.DisplayName?.includes(filter.DisplayName));
}
//console.log(results);
return results;
}
async function checkAppInstallationMethod(appPath, bundleId) {
if (!fs.existsSync(appPath)) {
return { error: "App does not exist at the specified path." };
}
try {
// Check for Mac App Store receipt
const { stdout: masOutput } = await execPromise(`mdls -name kMDItemAppStoreReceiptURL "${appPath}"`);
if (!masOutput.includes("(null)")) {
return { type: "MAS" };
}
// Check for PKG installation
try {
const { stdout: pkgOutput } = await execPromise(`pkgutil --pkg-info "${bundleId}"`);
return { type: "PKG", stdout: pkgOutput };
} catch {
// Ignore error; means PKG is not found
}
// Check if manually installed (ZIP/DMG)
const receiptPath = path.join(appPath, 'Contents', '_MASReceipt', 'receipt');
if (!fs.existsSync(receiptPath)) {
return { type: "ZIP/DMG" };
}
} catch (error) {
return { error: error.message };
}
}
module.exports = {
getUninstallEntries,
checkAppInstallationMethod
};

View File

@@ -61,6 +61,16 @@ class SystemInfo {
return !this.laterThan(compareVersion); return !this.laterThan(compareVersion);
} }
// Get edition of the os
getEdition() {
if (this.isWin()) {
const edition = childProcess.execSync('wmic os get Caption').toString().trim();
return edition.split('\n')[1].trim();
} else {
return 'N/A';
}
}
// Private: Parse version strings (e.g., "10.0.19045" -> [10, 0, 19045]) // Private: Parse version strings (e.g., "10.0.19045" -> [10, 0, 19045])
_parseVersion(version) { _parseVersion(version) {
return version.split('.').map((num) => parseInt(num, 10) || 0); return version.split('.').map((num) => parseInt(num, 10) || 0);

View File

@@ -1,5 +1,6 @@
const usercssMeta = require('usercss-meta'); const usercssMeta = require('usercss-meta');
const less = require('less'); const less = require('less');
const stylus = require('stylus');
/** /**
* Extracts all global variable and mixin definitions from CSS. * Extracts all global variable and mixin definitions from CSS.
@@ -72,8 +73,8 @@ function parseDomainRule(css, startPos) {
if (!match) return null; if (!match) return null;
const domains = match[0] const domains = match[0]
.match(/'[^']+'/g) // Extract all single-quoted domain values .match(/['"][^'"]+['"]/g) // Extract all single- or double-quoted domain values
.map(domain => domain.replace(/'/g, '').trim()); .map(domain => domain.replace(/['"]/g, '').trim()); // Remove quotes and trim whitespace
return { return {
domains, domains,
@@ -90,17 +91,26 @@ function parseMozRules(css) {
const rules = {}; const rules = {};
let currentPos = 0; let currentPos = 0;
// Helper to extract global definitions (CSS outside @-moz-document)
const globalCode = extractGlobalDefinitions(css); const globalCode = extractGlobalDefinitions(css);
while (true) { while (currentPos < css.length) {
const domainRule = parseDomainRule(css, currentPos); // Match @-moz-document syntax and extract domains
if (!domainRule) break; const domainMatch = css.slice(currentPos).match(/@-moz-document\s+(.*?){/s);
if (!domainMatch) break;
const bracedContent = extractBracedContent(css, domainRule.ruleStart); const domainsStr = domainMatch[1];
const ruleStart = currentPos + domainMatch.index + domainMatch[0].length - 1;
// Extract the content inside the braces for this @-moz-document rule
const bracedContent = extractBracedContent(css, ruleStart);
if (!bracedContent) break; if (!bracedContent) break;
// Add the CSS to all matched domains // Parse the domains and add the CSS to each
for (const domain of domainRule.domains) { const domainList = domainsStr.match(/domain\("([^"]+)"\)/g) || [];
const domains = domainList.map((d) => d.match(/domain\("([^"]+)"\)/)[1]);
for (const domain of domains) {
rules[domain] = `${globalCode}\n${bracedContent.content}`; rules[domain] = `${globalCode}\n${bracedContent.content}`;
} }
@@ -155,10 +165,17 @@ async function compileStyle(code, metadata, userVars = {}) {
switch (metadata?.preprocessor?.toLowerCase()) { switch (metadata?.preprocessor?.toLowerCase()) {
case 'less': case 'less':
compiledCode = await compileLess(fullCode); compiledCode = await compileLess(fullCode, vars);
break; break;
case 'stylus':
compiledCode = await compileStylus(fullCode, vars);
break;
case 'sass':
throw Error('SASS preprocessor not supported yet. Skipping compilation.');
case 'scss':
throw Error('SCSS preprocessor not supported yet. Skipping compilation.');
default: default:
compiledCode = code; // Return unmodified for unknown preprocessors compiledCode = code; // Return unmodified for plain CSS/unknown preprocessor
} }
// Parse domain rules // Parse domain rules
@@ -167,10 +184,15 @@ async function compileStyle(code, metadata, userVars = {}) {
// Compile each domain's CSS if needed // Compile each domain's CSS if needed
const compiledRules = {}; const compiledRules = {};
for (const [domain, css] of Object.entries(domainRules)) { for (const [domain, css] of Object.entries(domainRules)) {
if (metadata.preprocessor === 'less') { switch (metadata.preprocessor?.toLowerCase()) {
compiledRules[domain] = await compileLess(css, vars); case 'less':
} else { compiledRules[domain] = await compileLess(css, vars);
compiledRules[domain] = css; break;
case 'stylus':
compiledRules[domain] = await compileStylus(css, vars);
break;
default:
compiledRules[domain] = css;
} }
} }
@@ -181,27 +203,55 @@ async function compileStyle(code, metadata, userVars = {}) {
return { return {
compiledCss: combinedCss, compiledCss: combinedCss,
sites: compiledRules // Map of domains to their CSS sites: compiledRules, // Map of domains to their CSS
}; };
} catch (error) { } catch (error) {
console.error('Style compilation error:', error); //console.error('Style compilation error:', error);
throw error; return {
error
};
} }
} }
/** /**
* Compiles LESS code to CSS. * Compiles LESS code to CSS.
* @param {string} code - The LESS code. * @param {string} code - The LESS code.
* @param {object} vars - User-defined variables.
* @returns {Promise<string>} The compiled CSS. * @returns {Promise<string>} The compiled CSS.
*/ */
async function compileLess(code) { async function compileLess(code, vars = {}) {
const { css } = await less.render(code, { return new Promise((resolve, reject) => {
math: 'parens-division', less.render(code, {
javascriptEnabled: true, math: 'parens-division',
compress: false javascriptEnabled: true,
compress: false,
globalVars: vars
}, (err, output) => {
if (err) return reject(err);
resolve(output.css);
});
});
}
/**
* Compiles Stylus code to CSS.
* @param {string} code - The Stylus code.
* @returns {Promise<string>} The compiled CSS.
*/
async function compileStylus(code, vars = {}) {
console.log(vars, code);
return new Promise((resolve, reject) => {
var stlus = stylus(code);
stlus.set('compress', false);
for (const [key, value] of Object.entries(vars)) {
stlus.define(key, value);
}
stlus.render((err, output) => {
if (err) return reject(err);
resolve(output);
});
}); });
return css;
} }
module.exports = { module.exports = {

View File

@@ -0,0 +1,224 @@
'use strict';
const path = require('path');
const fs = require('fs');
const electron = require('electron');
let remote;
try {
remote = require('@electron/remote');
} catch (err) {
remote = electron.remote; // Fallback for older Electron versions
}
module.exports = function (options) {
const app = electron.app || (remote ? remote.app : null);
const screen = electron.screen || (remote ? remote.screen : null);
let state;
let winRef;
let stateChangeTimer;
const eventHandlingDelay = 100;
const config = Object.assign({
file: 'window-state.json',
path: app.getPath('userData'),
maximize: true,
fullScreen: true
}, options);
const fullStoreFileName = path.join(config.path, config.file);
function isNormal(win) {
return !win.isMaximized() && !win.isMinimized() && !win.isFullScreen();
}
function hasBounds() {
return state &&
Number.isInteger(state.x) &&
Number.isInteger(state.y) &&
Number.isInteger(state.width) && state.width > 0 &&
Number.isInteger(state.height) && state.height > 0;
}
function resetStateToDefault() {
const displayBounds = screen.getPrimaryDisplay().bounds;
// Reset state to default values on the primary display
state = {
width: config.defaultWidth || 800,
height: config.defaultHeight || 600,
x: 0,
y: 0,
displayBounds
};
}
function windowWithinBounds(bounds) {
return (
state.x >= bounds.x &&
state.y >= bounds.y &&
state.x + state.width <= bounds.x + bounds.width &&
state.y + state.height <= bounds.y + bounds.height
);
}
function ensureWindowVisibleOnSomeDisplay() {
const visible = screen.getAllDisplays().some(display => {
return windowWithinBounds(display.bounds);
});
if (!visible) {
// Window is partially or fully not visible now.
// Reset it to safe defaults.
return resetStateToDefault();
}
}
function validateState() {
const isValid = state && (hasBounds() || state.isMaximized || state.isFullScreen);
if (!isValid) {
state = null;
return;
}
if (hasBounds() && state.displayBounds) {
ensureWindowVisibleOnSomeDisplay();
}
}
function updateState(win) {
win = win || winRef;
if (!win || !state) return;
// Don't throw an error when window was closed
try {
const winBounds = win.getBounds();
if (isNormal(win)) {
state.x = winBounds.x;
state.y = winBounds.y;
state.width = winBounds.width;
state.height = winBounds.height;
}
state.isMaximized = win.isMaximized();
state.isFullScreen = win.isFullScreen();
state.displayBounds = screen.getDisplayMatching(winBounds).bounds;
} catch (err) { }
}
function saveState(win) {
// Update window state only if it was provided
if (win) {
updateState(win);
}
// Save state
try {
fs.mkdirSync(path.dirname(fullStoreFileName), { recursive: true });
fs.writeFileSync(fullStoreFileName, JSON.stringify(state));
} catch (err) {
// Don't care
}
}
function stateChangeHandler() {
// Handles both 'resize' and 'move'
clearTimeout(stateChangeTimer);
stateChangeTimer = setTimeout(() => saveState(winRef), eventHandlingDelay);
}
function closeHandler() {
updateState();
}
function closedHandler() {
// Unregister listeners and save state
unmanage();
saveState();
}
function manage(win) {
if (config.maximize && state.isMaximized) {
win.maximize();
}
if (config.fullScreen && state.isFullScreen) {
win.setFullScreen(true);
}
function resizeBrowserView() {
try {
const view = win.getBrowserView();
if (view) {
const windowBounds = win.getBounds(); // Full window size
const screenBounds = screen.getPrimaryDisplay().bounds; // Screen size
// Calculate the usable area by subtracting window chrome and any borders
const width = windowBounds.width; // Width of the full window
const height = windowBounds.height; // Height of the full window
// Ensure BrowserView fits within the screen size and window size
view.setBounds({
x: 0,
y: 0,
width: Math.min(width, screenBounds.width), // Prevent overflow horizontally
height: Math.min(height, screenBounds.height) // Prevent overflow vertically
});
}
} catch (err) {
// Ignore errors if BrowserView is not present
}
}
function stateChangeHandlerWithBrowserView() {
stateChangeHandler(); // Preserve original behavior
resizeBrowserView(); // Resize BrowserView if applicable
}
win.on('resize', stateChangeHandler);
win.on('move', stateChangeHandler);
win.on('close', closeHandler);
win.on('closed', closedHandler);
// Initial BrowserView resize in case window is already open
resizeBrowserView();
winRef = win;
}
function unmanage() {
if (winRef) {
winRef.removeListener('resize', stateChangeHandler);
winRef.removeListener('move', stateChangeHandler);
clearTimeout(stateChangeTimer);
winRef.removeListener('close', closeHandler);
winRef.removeListener('closed', closedHandler);
winRef = null;
}
}
// Load previous state
try {
state = JSON.parse(fs.readFileSync(fullStoreFileName, 'utf8'));
} catch (err) {
// Don't care
}
// Check state validity
validateState();
// Set state fallback values
state = Object.assign({
width: config.defaultWidth || 800,
height: config.defaultHeight || 600
}, state || {});
return {
get x() { return state.x; },
get y() { return state.y; },
get width() { return state.width; },
get height() { return state.height; },
get displayBounds() { return state.displayBounds; },
get isMaximized() { return state.isMaximized; },
get isFullScreen() { return state.isFullScreen; },
saveState,
unmanage,
manage,
resetStateToDefault
};
};

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Jakub Szwacz
Copyright (c) Marcel Wiehle <marcel@wiehle.me> (http://marcel.wiehle.me)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

105
src/ui/css/offline.css Normal file
View File

@@ -0,0 +1,105 @@
html,
body {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden; /* Prevent overflow from the body */
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
background-color: #082032;
color: white;
}
.container {
display: flex;
justify-content: center;
align-items: flex-start; /* Align items to the top */
height: 100vh; /* Full viewport height */
overflow-y: auto; /* Allow vertical scrolling */
margin: 0;
}
.divround {
background-color: #2c394b;
height: auto; /* Let it grow with content */
width: 90vw; /* or set a max-width if preferred */
max-width: 510px; /* Fixed width for your content */
margin: auto;
padding: 2.375vh; /* Converted from 19px to vh */
border-radius: 0.5em;
box-shadow: 2px 3px 7px 2px rgba(0, 0, 0, 0.02);
text-align: center;
overflow-y: auto; /* Allow scrolling inside the element if needed */
}
.circular {
border-radius: 125px;
-webkit-border-radius: 125px;
-moz-border-radius: 125px;
background-size: cover;
display: inline-block;
width: 250px;
height: 250px;
}
.btn {
background-color: DodgerBlue;
border: none;
color: white;
padding: 10px 20px;
cursor: pointer;
font-size: 20px;
border-radius: 8px;
}
/* Non-rounded border */
.btn.nr {
border-radius: 0px;
}
/* Full width */
.btn.fw {
width: 100%
}
/* Darker background on mouse-over */
.btn:hover {
background-color: RoyalBlue;
}
/* Success btn */
.btn.success {
background-color: #a6efb8e6;
}
/* Danger btn */
.btn.danger {
background-color: #ffafb4e6;
}
/* Warning btn */
.btn.warning {
background-color: #ffefb4e6;
}
/* Info btn */
.btn.info {
background-color: #b4e4f9e6;
}
/* button (input style) */
.btn.input {
background-color: rgb(82, 124, 165);
}
/* Darker on mouse-over */
.btn.input:hover {
background-color: rgb(72, 109, 146);
}
/* Darker on active */
.btn.input:active {
background-color: rgb(66, 111, 155);
}

View File

@@ -6,6 +6,7 @@
-webkit-user-drag: none; -webkit-user-drag: none;
/* Disable selection */ /* Disable selection */
-webkit-user-select: none; -webkit-user-select: none;
user-select: none;
} }
html, html,

31
src/ui/offline.html Normal file
View File

@@ -0,0 +1,31 @@
<html>
<head>
<title>No internet connection</title>
<link rel="stylesheet" href="./css/offline.css">
<link rel="stylesheet" href="./css/fa/6.7.1/css/all.min.css">
</head>
<body>
<div class="container">
<div class="divround" style="width: 510px;">
<h1>No internet connection</h1>
<p>We couldn't detect an internet connection. Please check your network and try again.</p>
<button class="btn" id="refresh-app"><i class="fa fa-refresh"></i> Reload</button>
</div>
</div>
<script>
// When the reload button is clicked, send a message to the main process to reload the app
document.getElementById('refresh-app').addEventListener('click', () => {
// Check for internet connection before reloading
if (navigator.onLine) {
window.ipc.send('app:restart');
return;
} else {
alert('Please check your network and try again.');
};
});
</script>
</body>
</html>

View File

@@ -1,33 +1,37 @@
const { contextBridge, ipcRenderer } = require('electron'); const { contextBridge, ipcRenderer } = require('electron');
// Expose IPC methods // Expose protected methods that allow the renderer process to use
const allowedChannels = ["ui:badgeCount", "ui:notif", "ui:settings", "ui:openSettings", "app:restart"];
// Expose ipcRenderer to the renderer process
contextBridge.exposeInMainWorld("ipc", { contextBridge.exposeInMainWorld("ipc", {
send: (channel, data) => { send: (channel, data) => {
ipcRenderer.send(channel, data); if (allowedChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
}, },
on: (channel, callback) => { on: (channel, callback) => {
ipcRenderer.on(channel, (event, ...args) => callback(...args)); if (allowedChannels.includes(channel)) {
ipcRenderer.on(channel, (event, ...args) => callback(...args));
}
}, },
}); });
contextBridge.exposeInMainWorld("badge", { // Load a script asynchronously
update: (badgeNumber) => { function loadScriptAsync(src) {
ipcRenderer.send('ui:badgeCount', badgeNumber); return new Promise((resolve, reject) => {
} const script = document.createElement("script");
}); script.src = src;
script.onload = () => {
// Helper to dynamically load a script and append it to the DOM console.log(`Loaded script: ${src}`);
function loadScript(src, callback) { resolve();
const script = document.createElement('script'); };
script.src = src; script.onerror = (error) => {
script.onload = () => { console.error(`Failed to load script: ${src}`, error);
console.log(`Loaded script: ${src}`); reject(error);
if (callback) callback(); };
}; document.body.appendChild(script);
script.onerror = (error) => { });
console.error(`Failed to load script: ${src}`, error);
};
document.body.appendChild(script);
} }
// Inject CSS into the DOM // Inject CSS into the DOM
@@ -39,22 +43,19 @@ function injectCSS(href) {
console.log(`Injected CSS: ${href}`); console.log(`Injected CSS: ${href}`);
} }
document.addEventListener('DOMContentLoaded', () => { document.addEventListener("DOMContentLoaded", async () => {
// Inject CSS injectCSS("ui:///lib/izitoast.min.css");
injectCSS('ui:///lib/izitoast.min.css'); injectCSS("ui:///rend/extra-themes.css");
injectCSS('ui:///rend/extra-themes.css'); injectCSS("ui:///css/fa/6.7.1/css/all.min.css");
injectCSS('ui:///css/fa/6.7.1/css/all.min.css');
// Load jQuery first try {
loadScript('ui:///lib/jquery-3.3.1.min.js', () => { await loadScriptAsync("ui:///lib/jquery-3.3.1.min.js");
// Load confetti and iziToast after jQuery (ui libs) await loadScriptAsync("ui:///lib/confetti-1.9.3-browser.min.js");
loadScript('ui:///lib/confetti-1.9.3-browser.min.js'); await loadScriptAsync("ui:///lib/izitoast.min.js");
loadScript('ui:///lib/izitoast.min.js', () => { await loadScriptAsync("ui:///rend/register-handles.js");
// Load app specific scripts await loadScriptAsync("ui:///rend/bsky-ext.js");
loadScript('ui:///rend/register-handles.js'); await loadScriptAsync("ui:///rend/specialAnimations.js");
// Load custom implementations } catch (error) {
loadScript('ui:///rend/bsky-ext.js'); console.error("Failed to load one or more scripts.", error);
loadScript('ui:///rend/specialAnimations.js'); }
});
});
}); });

View File

@@ -36,6 +36,8 @@ document.addEventListener('DOMContentLoaded', () => {
ipcRenderer.on('ui:progtext', (event, other) => { ipcRenderer.on('ui:progtext', (event, other) => {
console.log('Updating progress text:', other); console.log('Updating progress text:', other);
infotext.innerText = other.title; infotext.innerText = other.title;
progtext.innerText = other.subtitle; if (other.subtitle) {
progtext.innerText = other.subtitle;
};
}); });
}); });