diff --git a/.dependency-cruiser.cjs b/.dependency-cruiser.cjs
index bfd1a67d..6d8d3fb6 100644
--- a/.dependency-cruiser.cjs
+++ b/.dependency-cruiser.cjs
@@ -2,87 +2,83 @@
module.exports = {
forbidden: [
{
- name: 'no-circular',
- severity: 'warn',
+ name: "no-circular",
+ severity: "warn",
comment:
- 'This dependency is part of a circular relationship. You might want to revise ' +
- 'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ',
+ "This dependency is part of a circular relationship. You might want to revise " +
+ "your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
from: {},
to: {
- circular: true
- }
+ circular: true,
+ },
},
{
- name: 'no-orphans',
+ name: "no-orphans",
comment:
"This is an orphan module - it's likely not used (anymore?). Either use it or " +
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
"add an exception for it in your dependency-cruiser configuration. By default " +
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
- severity: 'warn',
+ severity: "warn",
from: {
orphan: true,
pathNot: [
- '(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$', // dot files
- '[.]d[.]ts$', // TypeScript declaration files
- '(^|/)tsconfig[.]json$', // TypeScript config
- '(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$' // other configs
- ]
+ "(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$", // dot files
+ "[.]d[.]ts$", // TypeScript declaration files
+ "(^|/)tsconfig[.]json$", // TypeScript config
+ "(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
+ ],
},
to: {},
},
{
- name: 'no-deprecated-core',
+ name: "no-deprecated-core",
comment:
- 'A module depends on a node core module that has been deprecated. Find an alternative - these are ' +
+ "A module depends on a node core module that has been deprecated. Find an alternative - these are " +
"bound to exist - node doesn't deprecate lightly.",
- severity: 'warn',
+ severity: "warn",
from: {},
to: {
- dependencyTypes: [
- 'core'
- ],
+ dependencyTypes: ["core"],
path: [
- '^v8/tools/codemap$',
- '^v8/tools/consarray$',
- '^v8/tools/csvparser$',
- '^v8/tools/logreader$',
- '^v8/tools/profile_view$',
- '^v8/tools/profile$',
- '^v8/tools/SourceMap$',
- '^v8/tools/splaytree$',
- '^v8/tools/tickprocessor-driver$',
- '^v8/tools/tickprocessor$',
- '^node-inspect/lib/_inspect$',
- '^node-inspect/lib/internal/inspect_client$',
- '^node-inspect/lib/internal/inspect_repl$',
- '^async_hooks$',
- '^punycode$',
- '^domain$',
- '^constants$',
- '^sys$',
- '^_linklist$',
- '^_stream_wrap$'
+ "^v8/tools/codemap$",
+ "^v8/tools/consarray$",
+ "^v8/tools/csvparser$",
+ "^v8/tools/logreader$",
+ "^v8/tools/profile_view$",
+ "^v8/tools/profile$",
+ "^v8/tools/SourceMap$",
+ "^v8/tools/splaytree$",
+ "^v8/tools/tickprocessor-driver$",
+ "^v8/tools/tickprocessor$",
+ "^node-inspect/lib/_inspect$",
+ "^node-inspect/lib/internal/inspect_client$",
+ "^node-inspect/lib/internal/inspect_repl$",
+ "^async_hooks$",
+ "^punycode$",
+ "^domain$",
+ "^constants$",
+ "^sys$",
+ "^_linklist$",
+ "^_stream_wrap$",
],
- }
+ },
},
{
- name: 'not-to-deprecated',
+ name: "not-to-deprecated",
comment:
- 'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' +
- 'version of that module, or find an alternative. Deprecated modules are a security risk.',
- severity: 'warn',
+ "This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later " +
+ "version of that module, or find an alternative. Deprecated modules are a security risk.",
+ severity: "warn",
from: {},
to: {
- dependencyTypes: [
- 'deprecated'
- ]
- }
+ dependencyTypes: ["deprecated"],
+ },
},
{
- name: 'no-non-package-json',
- severity: 'error',
+ name: "no-non-package-json",
+ severity: "error",
comment:
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
@@ -90,84 +86,75 @@ module.exports = {
"in your package.json.",
from: {},
to: {
- dependencyTypes: [
- 'npm-no-pkg',
- 'npm-unknown'
- ]
- }
+ dependencyTypes: ["npm-no-pkg", "npm-unknown"],
+ },
},
{
- name: 'not-to-unresolvable',
+ name: "not-to-unresolvable",
comment:
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
- 'module: add it to your package.json. In all other cases you likely already know what to do.',
- severity: 'error',
+ "module: add it to your package.json. In all other cases you likely already know what to do.",
+ severity: "error",
from: {},
to: {
- couldNotResolve: true
- }
+ couldNotResolve: true,
+ },
},
{
- name: 'no-duplicate-dep-types',
+ name: "no-duplicate-dep-types",
comment:
"Likely this module depends on an external ('npm') package that occurs more than once " +
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
"maintenance problems later on.",
- severity: 'warn',
+ severity: "warn",
from: {},
to: {
moreThanOneDependencyType: true,
- // as it's pretty common to have a type import be a type only import
+ // as it's pretty common to have a type import be a type only import
// _and_ (e.g.) a devDependency - don't consider type-only dependency
// types for this rule
- dependencyTypesNot: ["type-only"]
- }
+ dependencyTypesNot: ["type-only"],
+ },
},
/* rules you might want to tweak for your specific situation: */
-
+
{
- name: 'not-to-spec',
+ name: "not-to-spec",
comment:
- 'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' +
+ "This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. " +
"If there's something in a spec that's of use to other modules, it doesn't have that single " +
- 'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.',
- severity: 'error',
+ "responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.",
+ severity: "error",
from: {},
to: {
- path: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$'
- }
+ path: "[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$",
+ },
},
{
- name: 'not-to-dev-dep',
- severity: 'error',
+ name: "not-to-dev-dep",
+ severity: "error",
comment:
"This module depends on an npm package from the 'devDependencies' section of your " +
- 'package.json. It looks like something that ships to production, though. To prevent problems ' +
+ "package.json. It looks like something that ships to production, though. To prevent problems " +
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
- 'section of your package.json. If this module is development only - add it to the ' +
- 'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration',
+ "section of your package.json. If this module is development only - add it to the " +
+ "from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration",
from: {
- path: '^(src)',
- pathNot: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$'
+ path: "^(src)",
+ pathNot: "[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$",
},
to: {
- dependencyTypes: [
- 'npm-dev',
- ],
+ dependencyTypes: ["npm-dev"],
// type only dependencies are not a problem as they don't end up in the
// production code or are ignored by the runtime.
- dependencyTypesNot: [
- 'type-only'
- ],
- pathNot: [
- 'node_modules/@types/'
- ]
- }
+ dependencyTypesNot: ["type-only"],
+ pathNot: ["node_modules/@types/"],
+ },
},
{
- name: 'optional-deps-used',
- severity: 'info',
+ name: "optional-deps-used",
+ severity: "info",
comment:
"This module depends on an npm package that is declared as an optional dependency " +
"in your package.json. As this makes sense in limited situations only, it's flagged here. " +
@@ -175,33 +162,28 @@ module.exports = {
"dependency-cruiser configuration.",
from: {},
to: {
- dependencyTypes: [
- 'npm-optional'
- ]
- }
+ dependencyTypes: ["npm-optional"],
+ },
},
{
- name: 'peer-deps-used',
+ name: "peer-deps-used",
comment:
"This module depends on an npm package that is declared as a peer dependency " +
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
"add an exception to your dependency-cruiser configuration.",
- severity: 'warn',
+ severity: "warn",
from: {},
to: {
- dependencyTypes: [
- 'npm-peer'
- ]
- }
- }
+ dependencyTypes: ["npm-peer"],
+ },
+ },
],
options: {
-
/* Which modules not to follow further when encountered */
doNotFollow: {
/* path: an array of regular expressions in strings to match against */
- path: ['node_modules']
+ path: ["node_modules"],
},
/* Which modules to exclude */
@@ -224,7 +206,7 @@ module.exports = {
As in practice only commonjs ('cjs') and ecmascript modules ('es6')
are widely used, you can limit the moduleSystems to those.
*/
-
+
// moduleSystems: ['cjs', 'es6'],
/*
@@ -249,7 +231,7 @@ module.exports = {
"specify": for each dependency identify whether it only exists before compilation or also after
*/
tsPreCompilationDeps: true,
-
+
/* list of extensions to scan that aren't javascript or compile-to-javascript.
Empty by default. Only put extensions in here that you want to take into
account that are _not_ parsable.
@@ -274,7 +256,7 @@ module.exports = {
defaults to './tsconfig.json'.
*/
tsConfig: {
- fileName: 'tsconfig.json'
+ fileName: "tsconfig.json",
},
/* Webpack configuration to use to get resolve options from.
@@ -306,7 +288,7 @@ module.exports = {
a hack.
*/
// exoticRequireStrings: [],
-
+
/* options to pass on to enhanced-resolve, the package dependency-cruiser
uses to resolve module references to disk. The values below should be
suitable for most situations
@@ -315,7 +297,7 @@ module.exports = {
there will override the ones specified here.
*/
enhancedResolveOptions: {
- /* What to consider as an 'exports' field in package.jsons */
+ /* What to consider as an 'exports' field in package.jsons */
exportsFields: ["exports"],
/* List of conditions to check for in the exports field.
Only works when the 'exportsFields' array is non-empty.
@@ -348,13 +330,13 @@ module.exports = {
for details
*/
skipAnalysisNotInRules: true,
-
+
/* List of built-in modules to use on top of the ones node declares.
See https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#builtinmodules-influencing-what-to-consider-built-in--core-modules
for details
*/
- builtInModules: {
+ builtInModules: {
add: [
"bun",
"bun:ffi",
@@ -364,8 +346,8 @@ module.exports = {
"bun:wrap",
"detect-libc",
"undici",
- "ws"
- ]
+ "ws",
+ ],
},
reporterOptions: {
@@ -375,7 +357,7 @@ module.exports = {
collapses everything in node_modules to one folder deep so you see
the external modules, but their innards.
*/
- collapsePattern: 'node_modules/(?:@[^/]+/[^/]+|[^/]+)',
+ collapsePattern: "node_modules/(?:@[^/]+/[^/]+|[^/]+)",
/* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions
@@ -397,7 +379,8 @@ module.exports = {
dependency graph reporter (`archi`) you probably want to tweak
this collapsePattern to your situation.
*/
- collapsePattern: '^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)',
+ collapsePattern:
+ "^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)",
/* Options to tweak the appearance of your graph. If you don't specify a
theme for 'archi' dependency-cruiser will use the one specified in the
@@ -405,10 +388,10 @@ module.exports = {
*/
// theme: { },
},
- "text": {
- "highlightFocused": true
+ text: {
+ highlightFocused: true,
},
- }
- }
+ },
+ },
};
// generated: dependency-cruiser@16.10.0 on 2025-02-16T22:32:01.621Z
diff --git a/.eslintrc.json b/.eslintrc.json
index f6cc10d1..c41b1538 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -12,12 +12,15 @@
},
"rules": {
// allow importing ts extensions
- "sort-imports": ["error", {
- "ignoreCase": true,
- "ignoreDeclarationSort": true,
- "ignoreMemberSort": false,
- "memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
- }],
+ "sort-imports": [
+ "error",
+ {
+ "ignoreCase": true,
+ "ignoreDeclarationSort": true,
+ "ignoreMemberSort": false,
+ "memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
+ }
+ ],
"import/extensions": [
"error",
"ignorePackages",
@@ -29,4 +32,4 @@
]
},
"plugins": ["import"]
-}
\ No newline at end of file
+}
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 27bc218d..dad93afc 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -3,54 +3,54 @@ description: Report an issue with the modpack in its unmodified state. For other
labels: bug
title: "[BUG]"
body:
-- type: markdown
- attributes:
- value: |
- Before reporting an issue, [please search](https://github.com/BetterSEQTA/BetterSEQTA-Plus/issues) to make sure it has not already been reported (make sure to search closed issues as well!).
+ - type: markdown
+ attributes:
+ value: |
+ Before reporting an issue, [please search](https://github.com/BetterSEQTA/BetterSEQTA-Plus/issues) to make sure it has not already been reported (make sure to search closed issues as well!).
-- type: textarea
- attributes:
- label: Describe the bug
- description: Describe your issue. For general issues and questions you'll get a faster answer [from our Discord.](https://discord.gg/YzmbnCDkat)
- validations:
- required: true
+ - type: textarea
+ attributes:
+ label: Describe the bug
+ description: Describe your issue. For general issues and questions you'll get a faster answer [from our Discord.](https://discord.gg/YzmbnCDkat)
+ validations:
+ required: true
-- type: input
- attributes:
- label: Extension version
- description: What version of the extension are you using?
- placeholder: Find it by opening the config menu and clicking the about icon in the top right.
- validations:
- required: true
+ - type: input
+ attributes:
+ label: Extension version
+ description: What version of the extension are you using?
+ placeholder: Find it by opening the config menu and clicking the about icon in the top right.
+ validations:
+ required: true
-- type: dropdown
- attributes:
- label: Browser
- description: Which Browser are you using?
- options:
- - Chrome
- - Firefox
- - Brave
- - Safari
- - DuckDuckGO
- - Microsoft Edge
- - Other Chromium-Based Browser
- - Other Non-Chromium-Based Browser
- validations:
- required: true
+ - type: dropdown
+ attributes:
+ label: Browser
+ description: Which Browser are you using?
+ options:
+ - Chrome
+ - Firefox
+ - Brave
+ - Safari
+ - DuckDuckGO
+ - Microsoft Edge
+ - Other Chromium-Based Browser
+ - Other Non-Chromium-Based Browser
+ validations:
+ required: true
-- type: checkboxes
- attributes:
- label: Confirm
- options:
- - label: This bug report is about an issue with the extension itself. I have not modified the extension nor added any unsupported plugins. If this is not the case, I know that I should post the issue to the extension's Discord support channel instead.
- required: true
-
-- type: textarea
- attributes:
- label: Additional context
- description: Screenshots, video or any other information. Include photos of the console if possible
- placeholder: |
- Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
- validations:
- required: false
+ - type: checkboxes
+ attributes:
+ label: Confirm
+ options:
+ - label: This bug report is about an issue with the extension itself. I have not modified the extension nor added any unsupported plugins. If this is not the case, I know that I should post the issue to the extension's Discord support channel instead.
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Additional context
+ description: Screenshots, video or any other information. Include photos of the console if possible
+ placeholder: |
+ Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index d2907c21..0d4d98ae 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -3,52 +3,49 @@ description: Suggest a new Feature to be added or replaced in BetterSeqtaPLUS
labels: enhancement
title: "[FR]"
body:
+ - type: checkboxes
+ attributes:
+ label: Confirm
+ options:
+ - label: "Is this feature request related to a Bug report?"
+ required: false
-- type: checkboxes
- attributes:
- label: Confirm
- options:
- - label: "Is this feature request related to a Bug report?"
- required: false
-
-- type: input
- attributes:
+ - type: input
+ attributes:
label: Bug report link
description: "If this feature request is related to a bug report, please insert the link to the bug report here"
placeholder: "https://github.com/BetterSEQTA/BetterSEQTA-Plus/issues/..."
- validations:
+ validations:
required: false
-- type: markdown
- attributes:
- value: |
- ## Feature details
- Before you request a feature, [please search](https://github.com/BetterSEQTA/BetterSEQTA-Plus/issues) if it has already been requested. (Make sure to check closed issues as well!)
+ - type: markdown
+ attributes:
+ value: |
+ ## Feature details
+ Before you request a feature, [please search](https://github.com/BetterSEQTA/BetterSEQTA-Plus/issues) if it has already been requested. (Make sure to check closed issues as well!)
-
-- type: dropdown
- attributes:
- label: Feature type
- multiple: false
- options:
- - Graphical
- - Functional
- - Not Sure
- validations:
- required: true
-
+ - type: dropdown
+ attributes:
+ label: Feature type
+ multiple: false
+ options:
+ - Graphical
+ - Functional
+ - Not Sure
+ validations:
+ required: true
-- type: input
- attributes:
- label: Feature Details
- description: Please write, with as much detail as possible, what you would like to see from this feature.
- placeholder: it would be cool if
- validations:
- required: false
+ - type: input
+ attributes:
+ label: Feature Details
+ description: Please write, with as much detail as possible, what you would like to see from this feature.
+ placeholder: it would be cool if
+ validations:
+ required: false
-- type: textarea
- attributes:
- label: Additional details
- description: Anything else that would help describe your vision (reference images, descriptions, etc)
- validations:
- required: false
+ - type: textarea
+ attributes:
+ label: Additional details
+ description: Anything else that would help describe your vision (reference images, descriptions, etc)
+ validations:
+ required: false
diff --git a/.github/workflows/mvp.yml b/.github/workflows/mvp.yml
index cccf8204..d2e7bc14 100644
--- a/.github/workflows/mvp.yml
+++ b/.github/workflows/mvp.yml
@@ -2,9 +2,9 @@ name: NodeJS Build
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
pull_request:
- branches: [ "main" ]
+ branches: ["main"]
jobs:
build:
@@ -15,24 +15,24 @@ jobs:
node-version: [20.x]
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ matrix.node-version }}
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
- - name: Build
- run: |
- npm install --legacy-peer-deps
- npm run build
+ - name: Build
+ run: |
+ npm install --legacy-peer-deps
+ npm run build
- - name: Zip dist folder
- run: |
- zip -r dist.zip dist
+ - name: Zip dist folder
+ run: |
+ zip -r dist.zip dist
- - name: Upload artifact
- uses: actions/upload-artifact@v4
- with:
- name: dist-zip
- path: dist.zip
\ No newline at end of file
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: dist-zip
+ path: dist.zip
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 51405645..60c06fef 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our
community include:
-* Demonstrating empathy and kindness toward other people
-* Being respectful of differing opinions, viewpoints, and experiences
-* Giving and gracefully accepting constructive feedback
-* Accepting responsibility and apologizing to those affected by our mistakes,
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
-* Focusing on what is best not just for us as individuals, but for the
+- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
-* The use of sexualized language or imagery, and sexual attention or
+- The use of sexualized language or imagery, and sexual attention or
advances of any kind
-* Trolling, insulting or derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or email
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or email
address, without their explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
+- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
-standards, including sustained inappropriate behavior, harassment of an
+standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
diff --git a/README.md b/README.md
index 5f6faca1..2d2e69e2 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
-
-#
+#
@@ -53,7 +52,7 @@
## Creating Custom Themes
-If you are looking to create custom themes, I would recommend you start at the official documentation [here](https://betterseqta.gitbook.io/betterseqta-docs). You can see some premade examples along with a compilation script that can be used to allow for CSS frameworks and libraries such as SCSS to be used [here](https://github.com/BetterSEQTA/BetterSEQTA-Theme-Generator).
+If you are looking to create custom themes, I would recommend you start at the official documentation [here](https://betterseqta.gitbook.io/betterseqta-docs). You can see some premade examples along with a compilation script that can be used to allow for CSS frameworks and libraries such as SCSS to be used [here](https://github.com/BetterSEQTA/BetterSEQTA-Theme-Generator).
Don't worry- if you get stuck feel free to ask around in the [discord](https://discord.gg/YzmbnCDkat). We're open and happy to help out! Happy creating :)
@@ -65,8 +64,6 @@ Don't worry- if you get stuck feel free to ask around in the [discord](https://d
git clone https://github.com/BetterSEQTA/BetterSEQTA-Plus
```
-
-
1. Install dependencies
You may install the dependencies like below:
@@ -75,20 +72,20 @@ You may install the dependencies like below:
npm install # or your preferred package manager like pnpm or yarn
```
-But it is recommended to do it like this:
+But it is recommended to do it like this:
```
npm install --legacy-peer-deps # Only NPM supported
```
+
### Running Development
+
2. Run the dev script (it updates as you save files)
```
npm run dev # or use your perferred package manager
```
-
-
### Building for production
2. Run the build script
@@ -102,6 +99,7 @@ npm run build # or use your perferred package manager
```
npm run zip # This REQUIRES 7-Zip to be installed in order to work. You can also use your perferred package manager
```
+
3. Load the extension into chrome
- Go to `chrome://extensions`
@@ -116,7 +114,7 @@ Just remember, in order to update changes to the extension if you are running in
The folder structure is as follows:
- The `src` folder contains source files that are compiled to the build directory.
--
+-
- The `src/plugins` folder contains vital loaders required for BetterSEQTA+ functionality.
- The `src/interface` folder contains source React & Svelte files that are required for the Settings page.
@@ -130,6 +128,7 @@ The folder structure is as follows:
Want to contribute? [Click Here!](https://github.com/BetterSEQTA/BetterSEQTA-Plus/blob/main/CONTRIBUTING.md)
+
## Credits
This extension was initially developed by [Nulkem](https://github.com/Nulkem/betterseqta), was ported to manifest V3 by [MEGA-Dawg68](https://github.com/MEGA-Dawg68) and is currently under active development by [SethBurkart123](https://github.com/SethBurkart123) and [Crazypersonalph](https://github.com/Crazypersonalph)
diff --git a/SECURITY.md b/SECURITY.md
index 95316bd1..f884bbf3 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -4,12 +4,13 @@
Below here is the supported versions of BetterSEQTA+. Anything older than this is not supported and contains bugs.
-| Version | Supported |
-| ------- | ------------------ |
-| 3.4.3 | ✅ |
-| < 3.4.3 | :x: |
+| Version | Supported |
+| ------- | --------- |
+| 3.4.3 | ✅ |
+| < 3.4.3 | :x: |
`*` May not work on other devices.
+
## Reporting a Vulnerability
If you find vulnerabilities, REPORT IT IMMEDIATELY. open the [advisories tab](https://github.com/BetterSEQTA/BetterSEQTA-Plus/security/advisories) on the left and click the green "report a vulnerability" button or use [this quick-link](https://github.com/BetterSEQTA/BetterSEQTA-Plus/security/advisories/new) to create a new report
diff --git a/docs/README.md b/docs/README.md
index 11d005e9..40628322 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -7,11 +7,13 @@ Welcome to the BetterSEQTA+ documentation! This documentation will help you unde
## Table of Contents
### Getting Started
+
- [Project Overview](./README.md) - This file
- [Installation Guide](./installation.md) - How to install and set up BetterSEQTA+
- [Contributing Guide](../CONTRIBUTING.md) - How to contribute to BetterSEQTA+
### Plugin System
+
- [Creating Your First Plugin](./plugins/README.md) - A comprehensive, beginner-friendly guide to creating plugins
- [Plugin API Reference](./plugins/api-reference.md) - Detailed technical documentation of the plugin APIs
@@ -47,4 +49,4 @@ To contribute to the documentation:
## License
-BetterSEQTA+ is licensed under the [MIT License](../LICENSE).
\ No newline at end of file
+BetterSEQTA+ is licensed under the [MIT License](../LICENSE).
diff --git a/docs/contributing.md b/docs/contributing.md
index 8a624a9e..4f5334e3 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -22,6 +22,7 @@ Thank you for your interest in contributing to BetterSEQTA+! This document provi
BetterSEQTA+ is committed to providing a welcoming and inclusive environment for all contributors. We expect all participants to adhere to our Code of Conduct, which promotes respectful and harassment-free interaction.
Key points:
+
- Be respectful and inclusive
- Focus on what is best for the community
- Show empathy towards other community members
@@ -105,6 +106,7 @@ git checkout -b feature/my-new-feature
2. **Write Clear Commit Messages**
Follow the conventional commits format:
+
```
feat: add new feature
fix: resolve bug with timetable
@@ -118,6 +120,7 @@ git checkout -b feature/my-new-feature
4. **Run Tests**
Make sure all tests pass before submitting your PR:
+
```bash
npm test
```
@@ -157,6 +160,7 @@ We follow TypeScript best practices and have a consistent code style:
5. **Use Linters**
We use ESLint and Prettier. Run them before submitting your PR:
+
```bash
npm run lint
npm run format
@@ -173,6 +177,7 @@ If you find a bug, please report it by creating an issue on GitHub:
2. **Use the Bug Report Template**
Fill in all sections of the bug report template:
+
- Description
- Steps to reproduce
- Expected behavior
@@ -195,6 +200,7 @@ We welcome feature suggestions! To suggest a new feature:
2. **Use the Feature Request Template**
Fill in all sections of the feature request template:
+
- Description
- Use case
- Potential implementation
@@ -259,4 +265,4 @@ If you have any questions about contributing, please:
2. Ask in the Discord server
3. Open a GitHub Discussion
-Thank you for contributing to BetterSEQTA+! Your efforts help make SEQTA better for students and teachers everywhere.
\ No newline at end of file
+Thank you for contributing to BetterSEQTA+! Your efforts help make SEQTA better for students and teachers everywhere.
diff --git a/docs/installation.md b/docs/installation.md
index 10404c68..0e5c8514 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -132,6 +132,7 @@ bun install
#### Extension not appearing in SEQTA
Make sure:
+
- You're visiting a SEQTA Learn page
- The extension is enabled
- You've refreshed the page after installing the extension
@@ -139,6 +140,7 @@ Make sure:
#### Development build not updating
Try:
+
1. Stopping the development server
2. Clearing your browser cache
3. Removing the extension from your browser
@@ -177,4 +179,4 @@ bun run dev
Now that you have BetterSEQTA+ installed, you can:
- [Getting Started with Plugins](./plugins/getting-started.md)
-- [Contribute to the project](../CONTRIBUTING.md)
\ No newline at end of file
+- [Contribute to the project](../CONTRIBUTING.md)
diff --git a/docs/plugins/README.md b/docs/plugins/README.md
index 1af78b4e..23e9ce68 100644
--- a/docs/plugins/README.md
+++ b/docs/plugins/README.md
@@ -5,6 +5,7 @@ Hey there! 👋 So you want to create a plugin for BetterSEQTA+? That's awesome!
## What is a Plugin?
In BetterSEQTA+, a plugin is like a mini-app that adds new features to SEQTA. Think of it as a piece of LEGO that you can snap onto SEQTA to make it do new things. For example, you could create a plugin that:
+
- Changes how SEQTA looks
- Adds new buttons or features
- Shows extra information on your timetable
@@ -16,40 +17,40 @@ In BetterSEQTA+, a plugin is like a mini-app that adds new features to SEQTA. Th
Let's create a super simple plugin together. We'll make one that adds a friendly message to the SEQTA homepage. Here's what we'll need:
```typescript
-import type { Plugin } from '@/plugins/core/types';
+import type { Plugin } from "@/plugins/core/types";
const myFirstPlugin: Plugin = {
// Every plugin needs these basic details
- id: 'my-first-plugin',
- name: 'My First Plugin',
- description: 'Adds a friendly message to SEQTA',
- version: '1.0.0',
-
+ id: "my-first-plugin",
+ name: "My First Plugin",
+ description: "Adds a friendly message to SEQTA",
+ version: "1.0.0",
+
// This tells BetterSEQTA+ that users can turn our plugin on/off
disableToggle: true,
-
- // This is where the magic happens!
+
+ // This is where the magic happens!
run: async (api) => {
// Wait for the homepage to load
- api.seqta.onMount('.home-page', (homePage) => {
+ api.seqta.onMount(".home-page", (homePage) => {
// Create our message
- const message = document.createElement('div');
- message.textContent = 'Hello from my first plugin! 🎉';
- message.style.padding = '20px';
- message.style.backgroundColor = '#e9f5ff';
- message.style.borderRadius = '8px';
- message.style.margin = '20px';
-
+ const message = document.createElement("div");
+ message.textContent = "Hello from my first plugin! 🎉";
+ message.style.padding = "20px";
+ message.style.backgroundColor = "#e9f5ff";
+ message.style.borderRadius = "8px";
+ message.style.margin = "20px";
+
// Add it to the page
homePage.prepend(message);
});
-
+
// Return a cleanup function that removes our message when the plugin is disabled
return () => {
- const message = document.querySelector('.home-page > div');
+ const message = document.querySelector(".home-page > div");
message?.remove();
};
- }
+ },
};
export default myFirstPlugin;
@@ -79,13 +80,13 @@ This helps you interact with SEQTA's pages:
```typescript
// Wait for an element to appear on the page
-api.seqta.onMount('.some-class', (element) => {
+api.seqta.onMount(".some-class", (element) => {
// Do something with the element
});
// Know when the user changes pages
api.seqta.onPageChange((page) => {
- console.log('User went to:', page);
+ console.log("User went to:", page);
});
// Get the current page
@@ -97,8 +98,12 @@ const currentPage = api.seqta.getCurrentPage();
Want to let users customize your plugin? Use settings!
```typescript
-import { BasePlugin } from '@/plugins/core/settings';
-import { booleanSetting, defineSettings, Setting } from '@/plugins/core/settingsHelpers';
+import { BasePlugin } from "@/plugins/core/settings";
+import {
+ booleanSetting,
+ defineSettings,
+ Setting,
+} from "@/plugins/core/settingsHelpers";
// Define your settings
const settings = defineSettings({
@@ -106,7 +111,7 @@ const settings = defineSettings({
default: true,
title: "Show Welcome Message",
description: "Show a friendly message on the homepage",
- })
+ }),
});
// Create a class for your plugin
@@ -121,22 +126,22 @@ const settingsInstance = new MyPluginClass();
const myPlugin: Plugin = {
// ... other plugin details ...
settings: settingsInstance.settings,
-
+
run: async (api) => {
// Use the setting
if (api.settings.showMessage) {
// Show the message
}
-
+
// Listen for setting changes
- api.settings.onChange('showMessage', (newValue) => {
+ api.settings.onChange("showMessage", (newValue) => {
if (newValue) {
// Show the message
} else {
// Hide the message
}
});
- }
+ },
};
```
@@ -146,14 +151,14 @@ Need to save some data? The storage API has got you covered:
```typescript
// Save some data
-await api.storage.set('lastVisit', new Date().toISOString());
+await api.storage.set("lastVisit", new Date().toISOString());
// Get it back later
-const lastVisit = await api.storage.get('lastVisit');
+const lastVisit = await api.storage.get("lastVisit");
// Listen for changes
-api.storage.onChange('lastVisit', (newValue) => {
- console.log('Last visit updated:', newValue);
+api.storage.onChange("lastVisit", (newValue) => {
+ console.log("Last visit updated:", newValue);
});
```
@@ -163,12 +168,12 @@ Want your plugin to be able to interface with other plugins? Then use events!
```typescript
// Listen for an event
-api.events.on('myCustomEvent', (data) => {
- console.log('Got event:', data);
+api.events.on("myCustomEvent", (data) => {
+ console.log("Got event:", data);
});
// Send an event
-api.events.emit('myCustomEvent', { some: 'data' });
+api.events.emit("myCustomEvent", { some: "data" });
```
## Adding Styles
@@ -178,7 +183,7 @@ Want to make your plugin look pretty? You can add CSS styles:
```typescript
const myPlugin: Plugin = {
// ... other plugin details ...
-
+
// Add your CSS here
styles: `
.my-plugin-message {
@@ -196,10 +201,10 @@ const myPlugin: Plugin = {
to { transform: translateY(0); opacity: 1; }
}
`,
-
+
run: async (api) => {
// Your plugin code here
- }
+ },
};
```
@@ -208,28 +213,31 @@ const myPlugin: Plugin = {
Here are some tips to make your plugin awesome:
1. **Always Clean Up**: When your plugin is disabled, clean up any changes you made:
+
```typescript
run: async (api) => {
// Add stuff to the page
- const element = document.createElement('div');
+ const element = document.createElement("div");
document.body.appendChild(element);
-
+
// Return a cleanup function
return () => {
element.remove();
};
- }
+ };
```
2. **Use TypeScript**: It helps catch errors before they happen and makes your code easier to understand.
3. **Test Your Plugin**: Make sure it works in different situations:
+
- When SEQTA is loading
- When the user switches pages
- When the plugin is enabled/disabled
- When settings are changed
4. **Keep It Fast**: Don't slow down SEQTA:
+
- Use `onMount` instead of intervals or timeouts
- Clean up event listeners when they're not needed
- Don't do heavy calculations on the main thread
@@ -242,6 +250,7 @@ Here are some tips to make your plugin awesome:
## Examples
Want to see more examples? Check out our built-in plugins:
+
- [themes](../../src/plugins/built-in/themes/index.ts): Shows how to change SEQTA's appearance
- [notificationCollector](../../src/plugins/built-in/notificationCollector/index.ts): Shows how to work with SEQTA's notifications
- [timetable](../../src/plugins/built-in/timetable/index.ts): Shows how to modify SEQTA's timetable view
@@ -250,8 +259,9 @@ Want to see more examples? Check out our built-in plugins:
## Need Help?
Got stuck? No worries! Here's where you can get help:
+
- Join our [Discord server](https://discord.gg/YzmbnCDkat)
- Check out the built-in plugins in the `src/plugins/built-in` folder
- Open an issue on our [GitHub page](https://github.com/betterseqta/betterseqta-plus/issues)
-Happy coding and feel free to checkout the api reference [here](./api-reference.md)
\ No newline at end of file
+Happy coding and feel free to checkout the api reference [here](./api-reference.md)
diff --git a/docs/plugins/api-reference.md b/docs/plugins/api-reference.md
index c90c3529..c2613205 100644
--- a/docs/plugins/api-reference.md
+++ b/docs/plugins/api-reference.md
@@ -7,9 +7,13 @@ This document provides detailed technical information about BetterSEQTA+'s plugi
Here's how a plugin is structured:
```typescript
-import type { Plugin } from '@/plugins/core/types';
-import { BasePlugin } from '@/plugins/core/settings';
-import { booleanSetting, defineSettings, Setting } from '@/plugins/core/settingsHelpers';
+import type { Plugin } from "@/plugins/core/types";
+import { BasePlugin } from "@/plugins/core/settings";
+import {
+ booleanSetting,
+ defineSettings,
+ Setting,
+} from "@/plugins/core/settingsHelpers";
// First, define your settings
const settings = defineSettings({
@@ -17,7 +21,7 @@ const settings = defineSettings({
default: true,
title: "Enable Feature",
description: "Turn this feature on or off",
- })
+ }),
});
// Create a class to handle your settings
@@ -31,28 +35,28 @@ const settingsInstance = new MyPluginClass();
// Create your plugin
const myPlugin: Plugin = {
- id: 'my-plugin',
- name: 'My Plugin',
- description: 'A cool plugin that does things',
- version: '1.0.0',
+ id: "my-plugin",
+ name: "My Plugin",
+ description: "A cool plugin that does things",
+ version: "1.0.0",
settings: settingsInstance.settings,
disableToggle: true,
run: async (api) => {
- console.log('Plugin is running!');
-
+ console.log("Plugin is running!");
+
// Do stuff when settings change
- api.settings.onChange('enabled', (enabled) => {
+ api.settings.onChange("enabled", (enabled) => {
if (enabled) {
- console.log('Feature enabled!');
+ console.log("Feature enabled!");
}
});
// Return a cleanup function
return () => {
- console.log('Plugin cleanup');
+ console.log("Plugin cleanup");
};
- }
+ },
};
export default myPlugin;
@@ -63,27 +67,30 @@ export default myPlugin;
The SEQTA API helps you interact with SEQTA's pages:
```typescript
-import type { Plugin } from '@/plugins/core/types';
+import type { Plugin } from "@/plugins/core/types";
const seqtaPlugin: Plugin = {
- id: 'seqta-example',
- name: 'SEQTA Example',
- description: 'Shows how to use the SEQTA API',
- version: '1.0.0',
+ id: "seqta-example",
+ name: "SEQTA Example",
+ description: "Shows how to use the SEQTA API",
+ version: "1.0.0",
settings: {},
disableToggle: true,
run: async (api) => {
// Wait for elements to appear
- const { unregister: timetableUnregister } = api.seqta.onMount('.timetable', (timetable) => {
- const button = document.createElement('button');
- button.textContent = 'Export';
- timetable.appendChild(button);
- });
+ const { unregister: timetableUnregister } = api.seqta.onMount(
+ ".timetable",
+ (timetable) => {
+ const button = document.createElement("button");
+ button.textContent = "Export";
+ timetable.appendChild(button);
+ },
+ );
// Track page changes
const { unregister: pageUnregister } = api.seqta.onPageChange((page) => {
- console.log('User went to:', page);
+ console.log("User went to:", page);
});
// Clean up when disabled
@@ -91,7 +98,7 @@ const seqtaPlugin: Plugin = {
timetableUnregister();
pageUnregister();
};
- }
+ },
};
export default seqtaPlugin;
@@ -102,22 +109,29 @@ export default seqtaPlugin;
Here's how to add settings to your plugin:
```typescript
-import type { Plugin } from '@/plugins/core/types';
-import { BasePlugin } from '@/plugins/core/settings';
-import { booleanSetting, stringSetting, numberSetting, selectSetting, defineSettings, Setting } from '@/plugins/core/settingsHelpers';
+import type { Plugin } from "@/plugins/core/types";
+import { BasePlugin } from "@/plugins/core/settings";
+import {
+ booleanSetting,
+ stringSetting,
+ numberSetting,
+ selectSetting,
+ defineSettings,
+ Setting,
+} from "@/plugins/core/settingsHelpers";
// Define your settings
const settings = defineSettings({
darkMode: booleanSetting({
default: false,
title: "Dark Mode",
- description: "Enable dark mode"
+ description: "Enable dark mode",
}),
userName: stringSetting({
default: "",
title: "User Name",
description: "Your display name",
- placeholder: "Enter your name..."
+ placeholder: "Enter your name...",
}),
theme: selectSetting({
default: "light",
@@ -125,9 +139,9 @@ const settings = defineSettings({
description: "Choose your theme",
options: [
{ value: "light", label: "Light" },
- { value: "dark", label: "Dark" }
- ]
- })
+ { value: "dark", label: "Dark" },
+ ],
+ }),
});
// Create your settings class
@@ -144,29 +158,29 @@ class ThemePluginClass extends BasePlugin {
// Create the plugin
const themePlugin: Plugin = {
- id: 'theme-example',
- name: 'Theme Example',
- description: 'Shows how to use settings',
- version: '1.0.0',
+ id: "theme-example",
+ name: "Theme Example",
+ description: "Shows how to use settings",
+ version: "1.0.0",
settings: new ThemePluginClass().settings,
disableToggle: true,
run: async (api) => {
// Apply initial settings
if (api.settings.darkMode) {
- document.body.classList.add('dark');
+ document.body.classList.add("dark");
}
// Listen for changes
- const { unregister } = api.settings.onChange('darkMode', (enabled) => {
- document.body.classList.toggle('dark', enabled);
+ const { unregister } = api.settings.onChange("darkMode", (enabled) => {
+ document.body.classList.toggle("dark", enabled);
});
return () => {
unregister();
- document.body.classList.remove('dark');
+ document.body.classList.remove("dark");
};
- }
+ },
};
export default themePlugin;
@@ -177,13 +191,13 @@ export default themePlugin;
Here's how to use storage in your plugin:
```typescript
-import type { Plugin } from '@/plugins/core/types';
+import type { Plugin } from "@/plugins/core/types";
const storagePlugin: Plugin = {
- id: 'storage-example',
- name: 'Storage Example',
- description: 'Shows how to use storage',
- version: '1.0.0',
+ id: "storage-example",
+ name: "Storage Example",
+ description: "Shows how to use storage",
+ version: "1.0.0",
settings: {},
disableToggle: true,
@@ -192,21 +206,21 @@ const storagePlugin: Plugin = {
await api.storage.loaded;
// Save some data
- await api.storage.set('lastVisit', new Date().toISOString());
-
+ await api.storage.set("lastVisit", new Date().toISOString());
+
// Get saved data
- const lastVisit = await api.storage.get('lastVisit');
- console.log('Last visit:', lastVisit);
+ const lastVisit = await api.storage.get("lastVisit");
+ console.log("Last visit:", lastVisit);
// Listen for changes
- const { unregister } = api.storage.onChange('lastVisit', (newValue) => {
- console.log('Last visit updated:', newValue);
+ const { unregister } = api.storage.onChange("lastVisit", (newValue) => {
+ console.log("Last visit updated:", newValue);
});
return () => {
unregister();
};
- }
+ },
};
export default storagePlugin;
@@ -217,33 +231,39 @@ export default storagePlugin;
Here's how to use events in your plugin:
```typescript
-import type { Plugin } from '@/plugins/core/types';
+import type { Plugin } from "@/plugins/core/types";
const eventsPlugin: Plugin = {
- id: 'events-example',
- name: 'Events Example',
- description: 'Shows how to use events',
- version: '1.0.0',
+ id: "events-example",
+ name: "Events Example",
+ description: "Shows how to use events",
+ version: "1.0.0",
settings: {},
disableToggle: true,
run: async (api) => {
// Listen for theme changes
- const { unregister: themeListener } = api.events.on('theme.changed', (theme) => {
- console.log('Theme changed to:', theme);
- });
+ const { unregister: themeListener } = api.events.on(
+ "theme.changed",
+ (theme) => {
+ console.log("Theme changed to:", theme);
+ },
+ );
// Listen for notifications
- const { unregister: notifyListener } = api.events.on('notification.new', (notification) => {
- console.log('New notification:', notification);
- });
+ const { unregister: notifyListener } = api.events.on(
+ "notification.new",
+ (notification) => {
+ console.log("New notification:", notification);
+ },
+ );
// Clean up listeners
return () => {
themeListener();
notifyListener();
};
- }
+ },
};
export default eventsPlugin;
@@ -254,20 +274,20 @@ export default eventsPlugin;
Here's how to write efficient plugins:
```typescript
-import type { Plugin } from '@/plugins/core/types';
+import type { Plugin } from "@/plugins/core/types";
const efficientPlugin: Plugin = {
- id: 'efficient-example',
- name: 'Efficient Example',
- description: 'Shows performance best practices',
- version: '1.0.0',
+ id: "efficient-example",
+ name: "Efficient Example",
+ description: "Shows performance best practices",
+ version: "1.0.0",
settings: {},
disableToggle: true,
run: async (api) => {
// ✅ Good: Use onMount
- const { unregister } = api.seqta.onMount('.timetable', (el) => {
- el.classList.add('enhanced');
+ const { unregister } = api.seqta.onMount(".timetable", (el) => {
+ el.classList.add("enhanced");
});
// ❌ Bad: Don't use intervals
@@ -277,7 +297,7 @@ const efficientPlugin: Plugin = {
// }, 100);
// ✅ Good: Cache DOM elements
- const header = document.querySelector('.header');
+ const header = document.querySelector(".header");
if (header) {
// Reuse header instead of querying again
}
@@ -285,7 +305,7 @@ const efficientPlugin: Plugin = {
// ✅ Good: Batch DOM updates
const fragment = document.createDocumentFragment();
for (let i = 0; i < 10; i++) {
- const div = document.createElement('div');
+ const div = document.createElement("div");
fragment.appendChild(div);
}
document.body.appendChild(fragment);
@@ -294,13 +314,14 @@ const efficientPlugin: Plugin = {
unregister();
// clearInterval(interval); // If you used the bad approach
};
- }
+ },
};
export default efficientPlugin;
```
Each plugin should be in its own file and exported as the default export. The plugin should:
+
1. Import necessary types and helpers
2. Define settings if needed
3. Create a settings class if using settings
@@ -308,7 +329,8 @@ Each plugin should be in its own file and exported as the default export. The pl
5. Export the plugin as default
Remember to always:
+
- Use proper TypeScript types
- Clean up when your plugin is disabled
- Handle errors gracefully
-- Follow the plugin structure shown above
\ No newline at end of file
+- Follow the plugin structure shown above
diff --git a/lib/base64loader.ts b/lib/base64loader.ts
index b62a7eef..6ab172a2 100644
--- a/lib/base64loader.ts
+++ b/lib/base64loader.ts
@@ -7,10 +7,10 @@ export const base64Loader = {
const [filePath, query] = id.split("?");
if (query !== "base64") return null;
- const data = fs.readFileSync(filePath, { encoding: 'base64' });
+ const data = fs.readFileSync(filePath, { encoding: "base64" });
const mimeType = mime.lookup(filePath);
const dataURL = `data:${mimeType};base64,${data}`;
return `export default '${dataURL}';`;
},
-};
\ No newline at end of file
+};
diff --git a/lib/closePlugin.ts b/lib/closePlugin.ts
index fe864ae2..016910f0 100644
--- a/lib/closePlugin.ts
+++ b/lib/closePlugin.ts
@@ -1,25 +1,25 @@
// ref: https://stackoverflow.com/a/76920975
-import type { Plugin } from 'vite';
+import type { Plugin } from "vite";
export default function ClosePlugin(): Plugin {
return {
- name: 'ClosePlugin', // required, will show up in warnings and errors
+ name: "ClosePlugin", // required, will show up in warnings and errors
// use this to catch errors when building
buildEnd(error) {
- if(error) {
- console.error('Error bundling')
- console.error(error)
- process.exit(1)
+ if (error) {
+ console.error("Error bundling");
+ console.error(error);
+ process.exit(1);
} else {
- console.log('Build ended')
+ console.log("Build ended");
}
},
// use this to catch the end of a build without errors
closeBundle() {
- console.log('Bundle closed')
- process.exit(0)
+ console.log("Bundle closed");
+ process.exit(0);
},
- }
+ };
}
diff --git a/lib/createManifest.ts b/lib/createManifest.ts
index 11392a49..74843e86 100644
--- a/lib/createManifest.ts
+++ b/lib/createManifest.ts
@@ -1,5 +1,5 @@
-import type { Browser, BuildTarget, Manifest } from './types'
-import type { AnyCase } from './utils'
+import type { Browser, BuildTarget, Manifest } from "./types";
+import type { AnyCase } from "./utils";
/**
*
*
@@ -15,7 +15,7 @@ export function createManifest(
return {
manifest,
browser,
- }
+ };
}
/**
@@ -29,5 +29,5 @@ export function createManifest(
* @return {*} {@link Manifest}
*/
export function createManifestBase(manifest: Manifest): Manifest {
- return manifest
-}
\ No newline at end of file
+ return manifest;
+}
diff --git a/lib/inlineWorker.ts b/lib/inlineWorker.ts
index e493125d..628c420e 100644
--- a/lib/inlineWorker.ts
+++ b/lib/inlineWorker.ts
@@ -1,26 +1,26 @@
// vite-plugin-inline-worker-dev.ts
-import { Plugin } from 'vite'
-import fs from 'fs/promises'
-import { build, transform } from 'esbuild'
+import { Plugin } from "vite";
+import fs from "fs/promises";
+import { build, transform } from "esbuild";
export default function InlineWorkerDevPlugin(): Plugin {
return {
- name: 'vite:inline-worker-dev',
+ name: "vite:inline-worker-dev",
async load(id) {
- if (id.includes('?inlineWorker')) {
- const [cleanPath] = id.split('?')
- console.log('cleanPath', cleanPath)
- const code = await fs.readFile(cleanPath, 'utf-8')
+ if (id.includes("?inlineWorker")) {
+ const [cleanPath] = id.split("?");
+ console.log("cleanPath", cleanPath);
+ const code = await fs.readFile(cleanPath, "utf-8");
const result = await build({
entryPoints: [cleanPath],
bundle: true,
write: false,
- platform: 'browser',
- format: 'iife',
- target: 'esnext',
- })
-
- const workerCode = result.outputFiles[0].text
+ platform: "browser",
+ format: "iife",
+ target: "esnext",
+ });
+
+ const workerCode = result.outputFiles[0].text;
const workerBlobCode = `
const code = ${JSON.stringify(workerCode)};
@@ -28,10 +28,10 @@ export default function InlineWorkerDevPlugin(): Plugin {
const blob = new Blob([code], { type: 'application/javascript' });
return new Worker(URL.createObjectURL(blob), { type: 'module' });
}
- `
- return workerBlobCode
+ `;
+ return workerBlobCode;
}
- return null
- }
- }
+ return null;
+ },
+ };
}
diff --git a/lib/publish.js b/lib/publish.js
index 0d5bea50..b4154a1b 100644
--- a/lib/publish.js
+++ b/lib/publish.js
@@ -1,49 +1,63 @@
-const glob = require('glob');
-const semver = require('semver');
-const { execSync } = require('child_process');
-const path = require('path');
+const glob = require("glob");
+const semver = require("semver");
+const { execSync } = require("child_process");
+const path = require("path");
function getLatestVersion(files) {
- console.log('Files passed to getLatestVersion:', files);
+ console.log("Files passed to getLatestVersion:", files);
- const versions = files.map(file => {
- const match = file.match(/@([\d\.]+)-/);
- console.log('Matching file:', file, 'Version found:', match ? match[1] : 'None');
+ const versions = files
+ .map((file) => {
+ const match = file.match(/@([\d\.]+)-/);
+ console.log(
+ "Matching file:",
+ file,
+ "Version found:",
+ match ? match[1] : "None",
+ );
- if (!match) return null;
+ if (!match) return null;
- const fullVersion = match[1]; // Original version (e.g., 3.4.5.1)
- const semverVersion = fullVersion.split('.').slice(0, 3).join('.'); // Trim to 3.4.5
+ const fullVersion = match[1]; // Original version (e.g., 3.4.5.1)
+ const semverVersion = fullVersion.split(".").slice(0, 3).join("."); // Trim to 3.4.5
- return { fullVersion, semverVersion };
- }).filter(Boolean);
+ return { fullVersion, semverVersion };
+ })
+ .filter(Boolean);
- console.log('Extracted versions:', versions.map(v => v.semverVersion));
+ console.log(
+ "Extracted versions:",
+ versions.map((v) => v.semverVersion),
+ );
// Find latest version using the trimmed semver format
- const latestSemver = semver.maxSatisfying(versions.map(v => v.semverVersion), '*');
- console.log('Latest SemVer-compatible version:', latestSemver);
+ const latestSemver = semver.maxSatisfying(
+ versions.map((v) => v.semverVersion),
+ "*",
+ );
+ console.log("Latest SemVer-compatible version:", latestSemver);
// Get the full version that matches the latest SemVer version
- const latestVersion = versions.find(v => v.semverVersion === latestSemver)?.fullVersion || null;
+ const latestVersion =
+ versions.find((v) => v.semverVersion === latestSemver)?.fullVersion || null;
- console.log('Final selected latest version:', latestVersion);
+ console.log("Final selected latest version:", latestVersion);
return latestVersion;
}
function getLatestFiles(browser) {
const pattern = `dist/betterseqtaplus@*-*${browser}.zip`;
- console.log('Glob pattern:', pattern);
-
+ console.log("Glob pattern:", pattern);
+
const files = glob.sync(pattern);
- console.log('Files found for browser', browser, ':', files);
-
+ console.log("Files found for browser", browser, ":", files);
+
const latestVersion = getLatestVersion(files);
// Find the exact file by matching the original full version
- const latestFile = files.find(file => file.includes(`@${latestVersion}-`));
+ const latestFile = files.find((file) => file.includes(`@${latestVersion}-`));
- console.log('Latest file for browser', browser, ':', latestFile);
+ console.log("Latest file for browser", browser, ":", latestFile);
return latestFile;
}
@@ -51,44 +65,53 @@ function zipSources() {
const zipFileName = `dist/betterseqtaplus@latest-sources.zip`;
const excludePatterns = [
- 'node_modules',
- 'dist',
- '.env*',
- '.git',
- '.github',
- '.vscode',
- 'LICENSE',
- 'package.json'
- ].map(pattern => `-x!${pattern}`).join(' ');
+ "node_modules",
+ "dist",
+ ".env*",
+ ".git",
+ ".github",
+ ".vscode",
+ "LICENSE",
+ "package.json",
+ ]
+ .map((pattern) => `-x!${pattern}`)
+ .join(" ");
const zipCommand = `7z a ${zipFileName} . ${excludePatterns}`;
- console.log('Zipping project sources with command:', zipCommand);
- execSync(zipCommand, { stdio: 'inherit' });
+ console.log("Zipping project sources with command:", zipCommand);
+ execSync(zipCommand, { stdio: "inherit" });
return zipFileName;
}
function runPublishCommand(browsers) {
- const chromeZip = browsers.includes('chrome') ? getLatestFiles('chrome') : null;
- const firefoxZip = browsers.includes('firefox') ? getLatestFiles('firefox') : null;
- const firefoxSourcesZip = browsers.includes('firefox') ? zipSources() : null;
+ const chromeZip = browsers.includes("chrome")
+ ? getLatestFiles("chrome")
+ : null;
+ const firefoxZip = browsers.includes("firefox")
+ ? getLatestFiles("firefox")
+ : null;
+ const firefoxSourcesZip = browsers.includes("firefox") ? zipSources() : null;
- console.log('Chrome zip:', chromeZip);
- console.log('Firefox zip:', firefoxZip);
- console.log('Firefox sources zip:', firefoxSourcesZip);
+ console.log("Chrome zip:", chromeZip);
+ console.log("Firefox zip:", firefoxZip);
+ console.log("Firefox sources zip:", firefoxSourcesZip);
if (browsers.length === 0) {
- console.log('No browsers specified. Exiting.');
+ console.log("No browsers specified. Exiting.");
process.exit(0);
}
- if ((browsers.includes('chrome') && !chromeZip) || (browsers.includes('firefox') && (!firefoxZip || !firefoxSourcesZip))) {
- console.error('Could not find required zip files for specified browsers.');
+ if (
+ (browsers.includes("chrome") && !chromeZip) ||
+ (browsers.includes("firefox") && (!firefoxZip || !firefoxSourcesZip))
+ ) {
+ console.error("Could not find required zip files for specified browsers.");
process.exit(1);
}
- let command = 'publish-extension';
+ let command = "publish-extension";
if (chromeZip) {
command += ` --chrome-zip ${chromeZip}`;
}
@@ -96,13 +119,13 @@ function runPublishCommand(browsers) {
command += ` --firefox-zip ${firefoxZip} --firefox-sources-zip ${firefoxSourcesZip}`;
}
- console.log('Running command:', command);
- execSync(command, { stdio: 'inherit' });
+ console.log("Running command:", command);
+ execSync(command, { stdio: "inherit" });
}
// Parse command-line arguments
const args = process.argv.slice(2);
-const browserIndex = args.indexOf('--b');
+const browserIndex = args.indexOf("--b");
const browsers = browserIndex !== -1 ? args.slice(browserIndex + 1) : [];
-runPublishCommand(browsers);
\ No newline at end of file
+runPublishCommand(browsers);
diff --git a/lib/touchGlobalCSS.ts b/lib/touchGlobalCSS.ts
index d01db686..644ec3fe 100644
--- a/lib/touchGlobalCSS.ts
+++ b/lib/touchGlobalCSS.ts
@@ -1,17 +1,17 @@
-import fs from 'fs';
+import fs from "fs";
export default function touchGlobalCSSPlugin() {
return {
- name: 'touch-global-css',
+ name: "touch-global-css",
handleHotUpdate({ modules }) {
// log all of the staticImportedUrls
- const importers = modules[0]._clientModule.importers
+ const importers = modules[0]._clientModule.importers;
importers.forEach((importer) => {
- if (importer.file.includes('.css')) {
- console.log("touching", importer.file)
- fs.utimesSync(importer.file, new Date(), new Date())
+ if (importer.file.includes(".css")) {
+ console.log("touching", importer.file);
+ fs.utimesSync(importer.file, new Date(), new Date());
}
- })
- }
+ });
+ },
};
}
diff --git a/lib/types.ts b/lib/types.ts
index ed8e3752..7d06f5a9 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -1,104 +1,104 @@
-import type { ManifestV3Export } from '@crxjs/vite-plugin'
-import { type AnyCase, createEnum } from './utils'
+import type { ManifestV3Export } from "@crxjs/vite-plugin";
+import { type AnyCase, createEnum } from "./utils";
export const FrameworkEnum = {
- React: 'React',
- Vanilla: 'Vanilla',
- Preact: 'Preact',
- Lit: 'Lit',
- Svelte: 'Svelte',
- Vue: 'Vue',
-} as const
+ React: "React",
+ Vanilla: "Vanilla",
+ Preact: "Preact",
+ Lit: "Lit",
+ Svelte: "Svelte",
+ Vue: "Vue",
+} as const;
export const BrowserEnum = {
- Chrome: 'Chrome',
- Brave: 'Brave',
- Opera: 'Opera',
- Edge: 'Edge',
- Firefox: 'Firefox',
- Safari: 'Safari',
-} as const
+ Chrome: "Chrome",
+ Brave: "Brave",
+ Opera: "Opera",
+ Edge: "Edge",
+ Firefox: "Firefox",
+ Safari: "Safari",
+} as const;
const LanguageEnum = {
- TypeScript: 'TypeScript',
- JavaScript: 'JavaScript',
-} as const
+ TypeScript: "TypeScript",
+ JavaScript: "JavaScript",
+} as const;
export const StyleEnum = {
- Tailwind: 'Tailwind',
-} as const
+ Tailwind: "Tailwind",
+} as const;
export const PackageManagerEnum = {
- Bun: 'Bun',
- PnPm: 'PnPm',
- Npm: 'Npm',
- Yarn: 'Yarn',
-} as const
+ Bun: "Bun",
+ PnPm: "PnPm",
+ Npm: "Npm",
+ Yarn: "Yarn",
+} as const;
// see: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/firefox-webext-browser/index.d.ts
export type BrowserSpecificSettings = {
browser_specific_settings?: {
gecko?: {
- id: string
- strict_min_version?: string
- strict_max_version?: string
- }
- }
-}
+ id: string;
+ strict_min_version?: string;
+ strict_max_version?: string;
+ };
+ };
+};
-export type Manifest = ManifestV3Export
-export type ManifestIcons = chrome.runtime.ManifestIcons
-export type ManifestBackground = chrome.runtime.ManifestV3['background']
+export type Manifest = ManifestV3Export;
+export type ManifestIcons = chrome.runtime.ManifestIcons;
+export type ManifestBackground = chrome.runtime.ManifestV3["background"];
export type ManifestContentScripts =
- chrome.runtime.ManifestV3['content_scripts']
+ chrome.runtime.ManifestV3["content_scripts"];
export type ManifestWebAccessibleResources =
- chrome.runtime.ManifestV3['web_accessible_resources']
-export type ManifestCommands = chrome.runtime.ManifestV3['commands']
-export type ManifestAction = chrome.runtime.ManifestV3['action']
-export type ManifestPermissions = chrome.runtime.ManifestV3['permissions']
-export type ManifestOptionsUI = chrome.runtime.ManifestV3['options_ui']
+ chrome.runtime.ManifestV3["web_accessible_resources"];
+export type ManifestCommands = chrome.runtime.ManifestV3["commands"];
+export type ManifestAction = chrome.runtime.ManifestV3["action"];
+export type ManifestPermissions = chrome.runtime.ManifestV3["permissions"];
+export type ManifestOptionsUI = chrome.runtime.ManifestV3["options_ui"];
export type ManifestURLOverrides =
- chrome.runtime.ManifestV3['chrome_url_overrides']
+ chrome.runtime.ManifestV3["chrome_url_overrides"];
-export type BrowserName = Capitalize | Lowercase
+export type BrowserName = Capitalize | Lowercase;
export type BrowserEnumType = {
- [browser in BrowserName]: BrowserName
-}
+ [browser in BrowserName]: BrowserName;
+};
-export type BuildMode = AnyCase
+export type BuildMode = AnyCase;
export type BuildTarget = {
- manifest: Manifest
- browser: AnyCase
-}
+ manifest: Manifest;
+ browser: AnyCase;
+};
export type BuildConfig = {
- command?: 'build' | 'serve'
- mode?: AnyCase | string | undefined
-}
+ command?: "build" | "serve";
+ mode?: AnyCase | string | undefined;
+};
export interface Repository {
- type: string
- url?: string
- bugs?: Bugs
+ type: string;
+ url?: string;
+ bugs?: Bugs;
}
export interface Bugs {
- url?: string
- email?: string
+ url?: string;
+ email?: string;
}
-export type Browser = (typeof BrowserEnum)[keyof typeof BrowserEnum]
-export const Browser: AnyCase = createEnum(BrowserEnum)
+export type Browser = (typeof BrowserEnum)[keyof typeof BrowserEnum];
+export const Browser: AnyCase = createEnum(BrowserEnum);
export type PackageManager =
- (typeof PackageManagerEnum)[keyof typeof PackageManagerEnum]
+ (typeof PackageManagerEnum)[keyof typeof PackageManagerEnum];
export const PackageManager: AnyCase =
- createEnum(PackageManagerEnum)
+ createEnum(PackageManagerEnum);
-export type Framework = (typeof FrameworkEnum)[keyof typeof FrameworkEnum]
-export const Framework: AnyCase = createEnum(FrameworkEnum)
+export type Framework = (typeof FrameworkEnum)[keyof typeof FrameworkEnum];
+export const Framework: AnyCase = createEnum(FrameworkEnum);
-export type Style = (typeof StyleEnum)[keyof typeof StyleEnum]
-export const Style: AnyCase
${loadingSpinner}