Plugins
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
Boilerplate
- Append your plugin to the
pluginsrecord insrc/utils/storage.ts
export const plugins: Record<Types.PluginId, Types.PluginData> = {
// ...
<nameCamelCase>: createPlugin(
"<nameCamelCase>",
"<name>", // the Title Case name of your plugin
"<description>", // a short description of what your plugin does, please use punctuation and end with a full stop
true, // whether your plugin should be enabled by defualt
),
// ...
}You can also have settings for your plugin, this will be covered in the settings section.
- Import your plugin in
src/entrypoints/plugins.content.ts
// ...
import <nameCamelCase> from "./plugins/<nameCamelCase>";
export default defineContentScript({
matches: ["<all_urls>"],
runAt: "document_start",
excludeMatches: EXCLUDE_MATCHES,
async main() {
// ...
<nameCamelCase>();
},
});- Create your plugin function in
src/entrypoints/pluginswith the name of your plugin in camelCase- If you are planning to include CSS, HTML, or Svelte alongside your TypeScript:
- Create a new directory in
src/entrypoints/pluginscalled<nameCamelCase> - Inside this folder, you can create a
index.tsfile for your TypeScript, and any other files you need (e.g.styles.css)
- Create a new directory in
- If you are only planning to include TypeScript:
- Create a new file in
src/entrypoints/pluginscalled<nameCamelCase>.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:
export default function init() {
defineStPlugin(
"<nameCamelCase>",
() => {
// Your code here
},
[<targets>],
);
} Plugin Settings
Under your plugin storage item in src/utils/storage.ts there is a 5th optional parameter of the createPlugin which expects an Object with settings components.
At the time of writing, the following components are available for configuration:
- slider: a range slider (between a given minimum and maximum)
- toggle: a boolean toggle
It's easier to include an example, so here's an example for the plugin scrollPeriod that has one toggle and one slider:
scrollPeriod: createPlugin("scrollPeriod", "Scroll Period", "Scrolls to the current period on the timetable.", true, {
toggle: {
resetCooldownOnMouseMove: {
toggle: new StorageState(
storage.defineItem<Types.ToggleSetting>("local:plugin-scrollPeriod-resetCooldownOnMouseMove", {
fallback: {
toggle: true,
},
}),
),
info: {
name: "Reset on mouse move",
description: "Whether to reset the scrolling cooldown when you move your mouse.",
},
},
},
slider: {
cooldownDuration: {
slider: new StorageState(
storage.defineItem<Types.SliderSetting>("local:plugin-scrollPeriod-cooldownDuration", {
fallback: {
min: 1,
max: 60,
value: 10,
},
}),
),
info: {
name: "Cooldown duration (s)",
description: "How long to wait before scrolling.",
},
},
},
}),At the moment, the way of accessing the values of these settings is a bit convoluted, I plan on making this neater in the future but for now refer to the following example:
// the value of the cooldownDuration slider
const cooldownDuration = await data.settings?.slider?.cooldownDuration?.slider?.storage?.getValue();
// the value of the resetCooldownOnMouseMove slider
const resetCooldownOnMouseMove = await data.settings?.toggle?.resetCooldownOnMouseMove?.toggle?.storage?.getValue();Code!
Now that you have finished setting up the plugin storage, you can start working on the logic. This is located in src/entrypoints/plugins/<nameCamelCase>.ts or src/entrypoints/plugins/<nameCamelCase>/index.ts, depending on which one you chose.
You can put your code inside the arrow function, which will run whenever a Schoolbox page is loaded. For a simple example you can look at src/entrypoints/plugins/tabTitle.ts.
NOTE
You can access the plugin ID (<nameCamelCase>) and plugin data through the arguments of the arrow function.
id:<nameCamelCase>data: plugins[<nameCamelCase>]
export default function init() {
defineStPlugin(
"<nameCamelCase>",
() => {
(id, data) => {
// ...
}
)