Plugins
WARNING
These steps are based off the upcoming v4.0.0
release of Schooltape. If you are planning on contributing, please base your changes off the v4.0.0
branch.
Breaking changes may occur before the release.
IMPORTANT
For CSS only modifications, see snippets
First, you will need these things:
name
: The name of your plugin (e.g.My New Plugin
)nameCamelCase
: The name of your plugin in camelCase (e.g.myNewPlugin
)description
: A brief description of what your plugin does, without a period at the end (e.g.Adds a new button to the top bar
)targets
(optional): An array of CSS selectors which Schooltape will wait for to load into the DOM before injecting the plugin (e.g.[".timetable"]
)
Throughout this guide, you will see these between <angle brackets>
. Replace them with the appropriate values.
Creating a Plugin
INFO
For a real life example, see this commit!
Boilerplate
- Append your plugin
nameCamelCase
to the union typePluginId
insrc/utils/constants.ts
ts
export type PluginId =
| "subheader"
| "scrollSegments"
// ...
| "<nameCamelCase>";
- Append your plugin information to the
PLUGIN_INFO
object insrc/utils/constants.ts
ts
export const PLUGIN_INFO: Record<Types.PluginId, Types.PluginInfo> = {
subheader: {
name: "Subheader Revamp",
description: "Adds a clock and current period info to the subheader",
},
scrollSegments: {
name: "Scroll Segments",
description: "Segments the Schoolbox page into scrollable sections",
},
// ...
<nameCamelCase>: {
name: "<name>",
description: "<description>",
},
};
- Append your plugin settings to the
plugins
record insrc/utils/storage.ts
ts
export const plugins: Record<Types.PluginId, WxtStorageItem<Types.PluginGeneric, any>> = {
subheader: storage.defineItem<Types.PluginGeneric>("local:plugin-subheader", {
fallback: {
toggle: true,
},
}),
scrollSegments: storage.defineItem<Types.PluginGeneric>("local:plugin-scrollSegments", {
fallback: {
toggle: true,
},
}),
// ...
<nameCamelCase>: storage.defineItem<Types.PluginGeneric>("local:plugin-<nameCamelCase>", {
fallback: {
// here you can define the default settings for your plugin
toggle: true,
},
}),
};
- Import your plugin in
src/entrypoints/plugins.content.ts
ts
// @ts-ignore
import subheader from "./plugins/subheader";
import scrollSegments from "./plugins/scrollSegments";
// ...
import <nameCamelCase> from "./plugins/<nameCamelCase>";
export default defineContentScript({
matches: ["<all_urls>"],
runAt: "document_start",
excludeMatches: EXCLUDE_MATCHES,
async main() {
subheader();
scrollSegments();
// ...
<nameCamelCase>();
},
});
- Create your plugin function in
src/entrypoints/plugins
with the name of your plugin in camelCase- If you are planning to include CSS, HTML, or Svelte alongside your TypeScript:
- Create a new folder in
src/entrypoints/plugins
with the name of your plugin in camelCase (e.g.myNewPlugin
). - Inside this folder, you can create a
index.ts
file for your TypeScript, and any other files you need (e.g.styles.css
)
- Create a new folder in
- If you are only planning to include TypeScript:
- Create a new file in
src/entrypoints/plugins
with the name of your plugin in camelCase (e.g.myNewPlugin.ts
)
- Create a new file in
- If you are planning to include CSS, HTML, or Svelte alongside your TypeScript:
Now, in your TypeScript file, copy the following boilerplate:
ts
export default function init() {
defineStPlugin(
"<nameCamelCase>",
() => {
// Your code here
},
[<targets>],
);
}
Code!
Now that you have dealt with all that boilerplate, you can start actually building your plugin!