update BiomeJS

This commit is contained in:
imperosol
2026-02-13 14:07:46 +01:00
parent e71f76ea91
commit 84033f37cf
41 changed files with 124 additions and 95 deletions

View File

@@ -12,7 +12,7 @@ repos:
rev: v0.6.1
hooks:
- id: biome-check
additional_dependencies: ["@biomejs/biome@1.9.4"]
additional_dependencies: ["@biomejs/biome@2.3.14"]
- repo: https://github.com/rtts/djhtml
rev: 3.0.10
hooks:

View File

@@ -7,20 +7,34 @@
},
"files": {
"ignoreUnknown": false,
"ignore": ["*.min.*", "staticfiles/generated"]
"includes": ["**/static/**"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"lineWidth": 88
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"all": true
"recommended": true,
"style": {
"useNamingConvention": "error"
},
"performance": {
"noNamespaceImport": "error"
},
"suspicious": {
"noConsole": {
"level": "error",
"options": { "allow": ["error", "warn"] }
}
},
"correctness": {
"noUnusedVariables": "error",
"noUndeclaredVariables": "error",
"noUndeclaredDependencies": "error"
}
}
},
"javascript": {

View File

@@ -1,7 +1,7 @@
import { AjaxSelect } from "#core:core/components/ajax-select-base";
import { registerComponent } from "#core:utils/web-components";
import type { TomOption } from "tom-select/dist/types/types";
import type { escape_html } from "tom-select/dist/types/utils";
import { AjaxSelect } from "#core:core/components/ajax-select-base.ts";
import { registerComponent } from "#core:utils/web-components.ts";
import { type ClubSchema, clubSearchClub } from "#openapi";
@registerComponent("club-ajax-select")

View File

@@ -1,5 +1,3 @@
import { makeUrl } from "#core:utils/api";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
import { Calendar, type EventClickArg, type EventContentArg } from "@fullcalendar/core";
import type { EventImpl } from "@fullcalendar/core/internal";
import enLocale from "@fullcalendar/core/locales/en-gb";
@@ -8,6 +6,8 @@ import dayGridPlugin from "@fullcalendar/daygrid";
import iCalendarPlugin from "@fullcalendar/icalendar";
import listPlugin from "@fullcalendar/list";
import { type HTMLTemplateResult, html, render } from "lit-html";
import { makeUrl } from "#core:utils/api.ts";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components.ts";
import {
calendarCalendarInternal,
calendarCalendarUnpublished,
@@ -95,6 +95,7 @@ export class IcsCalendar extends inheritHtmlElement("div") {
.split("/")
.filter((s) => s) // Remove blank characters
.pop(),
10,
);
}

View File

@@ -1,4 +1,4 @@
import { exportToHtml } from "#core:utils/globals";
import { exportToHtml } from "#core:utils/globals.ts";
import { newsDeleteNews, newsFetchNewsDates, newsPublishNews } from "#openapi";
// This will be used in jinja templates,

View File

@@ -1,7 +1,7 @@
import { limitedChoices } from "#core:alpine/limited-choices";
import { alpinePlugin as notificationPlugin } from "#core:utils/notifications";
import sort from "@alpinejs/sort";
import Alpine from "alpinejs";
import { limitedChoices } from "#core:alpine/limited-choices.ts";
import { alpinePlugin as notificationPlugin } from "#core:utils/notifications.ts";
Alpine.plugin([sort, limitedChoices]);
Alpine.magic("notifications", notificationPlugin);

View File

@@ -56,7 +56,7 @@ export function limitedChoices(Alpine: AlpineType) {
effect(() => {
getMaxChoices((value: string) => {
const previousValue = maxChoices;
maxChoices = Number.parseInt(value);
maxChoices = Number.parseInt(value, 10);
if (maxChoices < previousValue) {
// The maximum number of selectable items has been lowered.
// Some currently selected elements may need to be removed

View File

@@ -1,4 +1,3 @@
import { inheritHtmlElement } from "#core:utils/web-components";
import TomSelect from "tom-select";
import type {
RecursivePartial,
@@ -7,6 +6,7 @@ import type {
TomSettings,
} from "tom-select/dist/types/types";
import type { escape_html } from "tom-select/dist/types/utils";
import { inheritHtmlElement } from "#core:utils/web-components.ts";
export class AutoCompleteSelectBase extends inheritHtmlElement("select") {
static observedAttributes = [
@@ -29,7 +29,7 @@ export class AutoCompleteSelectBase extends inheritHtmlElement("select") {
) {
switch (name) {
case "delay": {
this.delay = Number.parseInt(newValue) ?? null;
this.delay = Number.parseInt(newValue, 10) ?? null;
break;
}
case "placeholder": {
@@ -37,11 +37,11 @@ export class AutoCompleteSelectBase extends inheritHtmlElement("select") {
break;
}
case "max": {
this.max = Number.parseInt(newValue) ?? null;
this.max = Number.parseInt(newValue, 10) ?? null;
break;
}
case "min-characters-for-search": {
this.minCharNumberForSearch = Number.parseInt(newValue) ?? 0;
this.minCharNumberForSearch = Number.parseInt(newValue, 10) ?? 0;
break;
}
default: {

View File

@@ -1,20 +1,19 @@
import "tom-select/dist/css/tom-select.default.css";
import { registerComponent } from "#core:utils/web-components";
import type { TomOption } from "tom-select/dist/types/types";
import type { escape_html } from "tom-select/dist/types/utils";
import {
type GroupSchema,
type SithFileSchema,
type UserProfileSchema,
groupSearchGroup,
sithfileSearchFiles,
userSearchUsers,
} from "#openapi";
import {
AjaxSelect,
AutoCompleteSelectBase,
} from "#core:core/components/ajax-select-base";
} from "#core:core/components/ajax-select-base.ts";
import { registerComponent } from "#core:utils/web-components.ts";
import {
type GroupSchema,
groupSearchGroup,
type SithFileSchema,
sithfileSearchFiles,
type UserProfileSchema,
userSearchUsers,
} from "#openapi";
@registerComponent("autocomplete-select")
export class AutoCompleteSelect extends AutoCompleteSelectBase {}

View File

@@ -1,14 +1,14 @@
// biome-ignore lint/correctness/noUndeclaredDependencies: shipped by easymde
import "codemirror/lib/codemirror.css";
import "easymde/src/css/easymde.css";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
// biome-ignore lint/correctness/noUndeclaredDependencies: Imported by EasyMDE
import type CodeMirror from "codemirror";
// biome-ignore lint/style/useNamingConvention: This is how they called their namespace
import EasyMDE from "easymde";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components.ts";
import {
type UploadUploadImageErrors,
markdownRenderMarkdown,
type UploadUploadImageErrors,
uploadUploadImage,
} from "#openapi";

View File

@@ -1,4 +1,4 @@
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components.ts";
/**
* Web component used to import css files only once

View File

@@ -1,4 +1,4 @@
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components.ts";
@registerComponent("nfc-input")
export class NfcInput extends inheritHtmlElement("input") {

View File

@@ -1,6 +1,6 @@
import { registerComponent } from "#core:utils/web-components";
import { html, render } from "lit-html";
import { unsafeHTML } from "lit-html/directives/unsafe-html.js";
import { registerComponent } from "#core:utils/web-components.ts";
@registerComponent("ui-tab")
export class Tab extends HTMLElement {

View File

@@ -1,4 +1,4 @@
import { exportToHtml } from "#core:utils/globals";
import { exportToHtml } from "#core:utils/globals.ts";
exportToHtml("showMenu", () => {
const navbar = document.getElementById("navbar-content");

View File

@@ -26,7 +26,7 @@ function showMore(element: HTMLElement) {
const fullContent = element.innerHTML;
const clippedContent = clip(
element.innerHTML,
Number.parseInt(element.getAttribute("show-more") as string),
Number.parseInt(element.getAttribute("show-more") as string, 10),
{
html: true,
},

View File

@@ -1,9 +1,9 @@
import {
type Placement,
autoPlacement,
computePosition,
flip,
offset,
type Placement,
size,
} from "@floating-ui/dom";

View File

@@ -1,6 +1,6 @@
import { exportToHtml } from "#core:utils/globals";
// biome-ignore lint/style/noNamespaceImport: this is the recommended way from the documentation
// biome-ignore lint/performance/noNamespaceImport: this is the recommended way from the documentation
import * as Sentry from "@sentry/browser";
import { exportToHtml } from "#core:utils/globals.ts";
interface LoggedUser {
name: string;

View File

@@ -1,4 +1,3 @@
import { History, initialUrlParams, updateQueryString } from "#core:utils/history";
import cytoscape, {
type ElementDefinition,
type NodeSingular,
@@ -6,7 +5,8 @@ import cytoscape, {
} from "cytoscape";
import cxtmenu from "cytoscape-cxtmenu";
import klay, { type KlayLayoutOptions } from "cytoscape-klay";
import { type UserProfileSchema, familyGetFamilyGraph } from "#openapi";
import { History, initialUrlParams, updateQueryString } from "#core:utils/history.ts";
import { familyGetFamilyGraph, type UserProfileSchema } from "#openapi";
cytoscape.use(klay);
cytoscape.use(cxtmenu);
@@ -200,7 +200,7 @@ document.addEventListener("alpine:init", () => {
isZoomEnabled: !isMobile(),
getInitialDepth(prop: string) {
const value = Number.parseInt(initialUrlParams.get(prop));
const value = Number.parseInt(initialUrlParams.get(prop), 10);
if (Number.isNaN(value) || value < config.depthMin || value > config.depthMax) {
return defaultDepth;
}

View File

@@ -1,5 +1,5 @@
import { client, type Options } from "#openapi";
import type { Client, RequestResult, TDataShape } from "#openapi:client";
import { type Options, client } from "#openapi";
export interface PaginatedResponse<T> {
count: number;

View File

@@ -1,4 +1,4 @@
import type { NestedKeyOf } from "#core:utils/types";
import type { NestedKeyOf } from "#core:utils/types.ts";
interface StringifyOptions<T extends object> {
/** The columns to include in the resulting CSV. */

View File

@@ -10,7 +10,6 @@ export function registerComponent(name: string, options?: ElementDefinitionOptio
window.customElements.define(name, component, options);
} catch (e) {
if (e instanceof DOMException) {
// biome-ignore lint/suspicious/noConsole: it's handy to troobleshot
console.warn(e.message);
return;
}

View File

@@ -1,4 +1,4 @@
import type { Product } from "#counter:counter/types";
import type { Product } from "#counter:counter/types.ts";
export class BasketItem {
quantity: number;

View File

@@ -1,14 +1,14 @@
import { AjaxSelect } from "#core:core/components/ajax-select-base";
import { registerComponent } from "#core:utils/web-components";
import type { TomOption } from "tom-select/dist/types/types";
import type { escape_html } from "tom-select/dist/types/utils";
import { AjaxSelect } from "#core:core/components/ajax-select-base.ts";
import { registerComponent } from "#core:utils/web-components.ts";
import {
type CounterSchema,
type ProductTypeSchema,
type SimpleProductSchema,
counterSearchCounter,
type ProductTypeSchema,
productSearchProducts,
producttypeFetchAll,
type SimpleProductSchema,
} from "#openapi";
@registerComponent("product-ajax-select")

View File

@@ -1,13 +1,13 @@
import { AutoCompleteSelectBase } from "#core:core/components/ajax-select-base";
import { registerComponent } from "#core:utils/web-components";
import type { RecursivePartial, TomSettings } from "tom-select/dist/types/types";
import { AutoCompleteSelectBase } from "#core:core/components/ajax-select-base.ts";
import { registerComponent } from "#core:utils/web-components.ts";
const productParsingRegex = /^(\d+x)?(.*)/i;
const codeParsingRegex = / \((\w+)\)$/;
function parseProduct(query: string): [number, string] {
const parsed = productParsingRegex.exec(query);
return [Number.parseInt(parsed[1] || "1"), parsed[2]];
return [Number.parseInt(parsed[1] || "1", 10), parsed[2]];
}
@registerComponent("counter-product-select")
@@ -80,9 +80,9 @@ export class CounterProductSelect extends AutoCompleteSelectBase {
// We need to manually set weights or it results on an inconsistent
// behavior between production and development environment
searchField: [
// @ts-ignore documentation says it's fine, specified type is wrong
// @ts-expect-error documentation says it's fine, specified type is wrong
{ field: "code", weight: 2 },
// @ts-ignore documentation says it's fine, specified type is wrong
// @ts-expect-error documentation says it's fine, specified type is wrong
{ field: "text", weight: 0.5 },
],
};

View File

@@ -1,6 +1,6 @@
import { AlertMessage } from "#core:utils/alert-message";
import { BasketItem } from "#counter:counter/basket";
import type { CounterConfig, ErrorMessage } from "#counter:counter/types";
import { AlertMessage } from "#core:utils/alert-message.ts";
import { BasketItem } from "#counter:counter/basket.ts";
import type { CounterConfig, ErrorMessage } from "#counter:counter/types.ts";
import type { CounterProductSelect } from "./components/counter-product-select-index.ts";
document.addEventListener("alpine:init", () => {

View File

@@ -1,9 +1,13 @@
import { paginated } from "#core:utils/api";
import { csv } from "#core:utils/csv";
import { History, getCurrentUrlParams, updateQueryString } from "#core:utils/history";
import type { NestedKeyOf } from "#core:utils/types";
import { showSaveFilePicker } from "native-file-system-adapter";
import type TomSelect from "tom-select";
import { paginated } from "#core:utils/api.ts";
import { csv } from "#core:utils/csv.ts";
import {
getCurrentUrlParams,
History,
updateQueryString,
} from "#core:utils/history.ts";
import type { NestedKeyOf } from "#core:utils/types.ts";
import {
type ProductSchema,
type ProductSearchProductsDetailedData,

View File

@@ -1,5 +1,5 @@
import { AlertMessage } from "#core:utils/alert-message";
import Alpine from "alpinejs";
import { AlertMessage } from "#core:utils/alert-message.ts";
import { producttypeReorder } from "#openapi";
document.addEventListener("alpine:init", () => {
@@ -22,7 +22,7 @@ document.addEventListener("alpine:init", () => {
const productTypes = this.$refs.productTypes
.childNodes as NodeListOf<HTMLLIElement>;
const getId = (elem: HTMLLIElement) =>
Number.parseInt(elem.getAttribute("x-sort:item"));
Number.parseInt(elem.getAttribute("x-sort:item"), 10);
const query =
newPosition === 0
? { above: getId(productTypes.item(1)) }

View File

@@ -21,7 +21,7 @@ document.addEventListener("alpine:init", () => {
if (lastPurchaseTime !== null && localStorage.basketTimestamp !== undefined) {
if (
new Date(lastPurchaseTime) >=
new Date(Number.parseInt(localStorage.basketTimestamp))
new Date(Number.parseInt(localStorage.basketTimestamp, 10))
) {
this.basket = [];
}

View File

@@ -18,7 +18,9 @@
#basket {
min-width: 300px;
border-radius: 8px;
box-shadow: rgb(60 64 67 / 30%) 0 1px 3px 0, rgb(60 64 67 / 15%) 0 4px 8px 3px;
box-shadow:
rgb(60 64 67 / 30%) 0 1px 3px 0,
rgb(60 64 67 / 15%) 0 4px 8px 3px;
padding: 10px;
}

View File

@@ -1,6 +1,6 @@
import { default as ForceGraph3D } from "3d-force-graph";
import { forceX, forceY, forceZ } from "d3-force-3d";
// biome-ignore lint/style/noNamespaceImport: This is how it should be imported
// biome-ignore lint/performance/noNamespaceImport: This is how it should be imported
import * as Three from "three";
import SpriteText from "three-spritetext";

View File

@@ -15,7 +15,9 @@
"keywords": [],
"author": "",
"license": "GPL-3.0-only",
"sideEffects": [".css"],
"sideEffects": [
".css"
],
"imports": {
"#openapi": "./staticfiles/generated/openapi/client/index.ts",
"#core:*": "./core/static/bundled/*",

View File

@@ -1,4 +1,8 @@
import { History, getCurrentUrlParams, updateQueryString } from "#core:utils/history";
import {
getCurrentUrlParams,
History,
updateQueryString,
} from "#core:utils/history.ts";
import { ueFetchUeList } from "#openapi";
const pageDefault = 1;
@@ -31,8 +35,8 @@ document.addEventListener("alpine:init", () => {
const url = getCurrentUrlParams();
this.pushstate = History.Replace;
this.page = Number.parseInt(url.get("page")) || pageDefault;
this.page_size = Number.parseInt(url.get("page_size")) || pageSizeDefault;
this.page = Number.parseInt(url.get("page"), 10) || pageDefault;
this.page_size = Number.parseInt(url.get("page_size"), 10) || pageSizeDefault;
this.search = url.get("search") || "";
this.department = url.getAll("department");
this.credit_type = url.getAll("credit_type");

View File

@@ -1,12 +1,12 @@
import { paginated } from "#core:utils/api";
import { History, initialUrlParams, updateQueryString } from "#core:utils/history";
import { paginated } from "#core:utils/api.ts";
import { History, initialUrlParams, updateQueryString } from "#core:utils/history.ts";
import {
type AlbumFetchAlbumData,
type AlbumSchema,
albumFetchAlbum,
type PictureSchema,
type PicturesFetchPicturesData,
type PicturesUploadPictureErrors,
albumFetchAlbum,
picturesFetchPictures,
picturesUploadPicture,
} from "#openapi";
@@ -23,7 +23,7 @@ interface SubAlbumsConfig {
document.addEventListener("alpine:init", () => {
Alpine.data("pictures", (config: AlbumPicturesConfig) => ({
pictures: [] as PictureSchema[],
page: Number.parseInt(initialUrlParams.get("page")) || 1,
page: Number.parseInt(initialUrlParams.get("page"), 10) || 1,
pushstate: History.Push /* Used to avoid pushing a state on a back action */,
loading: false,
@@ -38,7 +38,10 @@ document.addEventListener("alpine:init", () => {
window.addEventListener("popstate", () => {
this.pushstate = History.Replace;
this.page =
Number.parseInt(new URLSearchParams(window.location.search).get("page")) || 1;
Number.parseInt(
new URLSearchParams(window.location.search).get("page"),
10,
) || 1;
});
},

View File

@@ -1,7 +1,7 @@
import { AjaxSelect } from "#core:core/components/ajax-select-base";
import { registerComponent } from "#core:utils/web-components";
import type { TomOption } from "tom-select/dist/types/types";
import type { escape_html } from "tom-select/dist/types/utils";
import { AjaxSelect } from "#core:core/components/ajax-select-base.ts";
import { registerComponent } from "#core:utils/web-components.ts";
import { type AlbumAutocompleteSchema, albumAutocompleteAlbum } from "#openapi";
@registerComponent("album-ajax-select")

View File

@@ -31,7 +31,7 @@ document.addEventListener("alpine:init", () => {
await Promise.all(
this.downloadPictures.map((p: PictureSchema) => {
const imgName = `${p.album.name}/IMG_${p.id}_${p.date.replace(/[:\-]/g, "_")}${p.name.slice(p.name.lastIndexOf("."))}`;
const imgName = `${p.album.name}/IMG_${p.id}_${p.date.replace(/[:-]/g, "_")}${p.name.slice(p.name.lastIndexOf("."))}`;
return zipWriter.add(imgName, new HttpReader(p.full_size_url), {
level: 9,
lastModDate: new Date(p.date),

View File

@@ -1,4 +1,4 @@
import { paginated } from "#core:utils/api";
import { paginated } from "#core:utils/api.ts";
import {
type PictureSchema,
type PicturesFetchPicturesData,
@@ -27,7 +27,7 @@ document.addEventListener("alpine:init", () => {
const lastCachedNumber = localStorage.getItem(localStorageInvalidationKey);
if (
lastCachedNumber !== null &&
Number.parseInt(lastCachedNumber) === config.nbPictures
Number.parseInt(lastCachedNumber, 10) === config.nbPictures
) {
return JSON.parse(localStorage.getItem(localStorageKey));
}

View File

@@ -1,21 +1,21 @@
import type { UserAjaxSelect } from "#core:core/components/ajax-select-index";
import { paginated } from "#core:utils/api";
import { exportToHtml } from "#core:utils/globals";
import { History } from "#core:utils/history";
import type TomSelect from "tom-select";
import type { UserAjaxSelect } from "#core:core/components/ajax-select-index.ts";
import { paginated } from "#core:utils/api.ts";
import { exportToHtml } from "#core:utils/globals.ts";
import { History } from "#core:utils/history.ts";
import {
type IdentifiedUserSchema,
type ModerationRequestSchema,
type PictureSchema,
type PicturesFetchIdentificationsResponse,
type PicturesFetchPicturesData,
type UserProfileSchema,
picturesDeletePicture,
picturesFetchIdentifications,
picturesFetchModerationRequests,
picturesFetchPictures,
picturesIdentifyUsers,
picturesModeratePicture,
type UserProfileSchema,
usersidentifiedDeleteRelation,
} from "#openapi";
@@ -208,7 +208,8 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
}
this.pushstate = History.Replace;
this.currentPicture = this.pictures.find(
(i: PictureSchema) => i.id === Number.parseInt(event.state.sasPictureId),
(i: PictureSchema) =>
i.id === Number.parseInt(event.state.sasPictureId, 10),
);
});
this.pushstate = History.Replace; /* Avoid first url push */
@@ -301,7 +302,7 @@ exportToHtml("loadViewer", (config: ViewerConfig) => {
// biome-ignore lint/style/useNamingConvention: api is in snake_case
picture_id: this.currentPicture.id,
},
body: widget.items.map((i: string) => Number.parseInt(i)),
body: widget.items.map((i: string) => Number.parseInt(i, 10)),
});
// refresh the identified users list
await this.currentPicture.loadIdentifications({ forceReload: true });

View File

@@ -8,9 +8,9 @@ document.addEventListener("alpine:init", () => {
async init() {
const userSelect = document.getElementById("id_member") as HTMLSelectElement;
userSelect.addEventListener("change", async () => {
await this.loadProfile(Number.parseInt(userSelect.value));
await this.loadProfile(Number.parseInt(userSelect.value, 10));
});
await this.loadProfile(Number.parseInt(userSelect.value));
await this.loadProfile(Number.parseInt(userSelect.value, 10));
},
async loadProfile(userId: number) {

View File

@@ -1,4 +1,5 @@
import { BarController, BarElement, CategoryScale, Chart, LinearScale } from "chart.js";
Chart.register(BarController, BarElement, CategoryScale, LinearScale);
function getRandomColor() {
@@ -18,13 +19,11 @@ function getRandomColorUniq(list: string[]) {
}
function hexToRgb(hex: string) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
// biome-ignore lint/performance/useTopLevelRegex: Performance impact is minimal
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
const hexrgb = hex.replace(shorthandRegex, (_m, r, g, b) => {
return r + r + g + g + b + b;
});
// biome-ignore lint/performance/useTopLevelRegex: Performance impact is minimal
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexrgb);
return result
? {

View File

@@ -63,10 +63,10 @@ function parseSlots(s: string): TimetableSlot[] {
}
const [startHour, startMin] = parsed.groups.startHour
.split(":")
.map((i) => Number.parseInt(i));
.map((i) => Number.parseInt(i, 10));
const [endHour, endMin] = parsed.groups.endHour
.split(":")
.map((i) => Number.parseInt(i));
.map((i) => Number.parseInt(i, 10));
return {
...parsed.groups,
startSlot: Math.floor((startHour * 60 + startMin) / MINUTES_PER_SLOT),
@@ -157,6 +157,7 @@ document.addEventListener("alpine:init", () => {
.map((c: TimetableSlot) => c.startHour)
.reduce((res: string, hour: string) => (hour < res ? hour : res), "24:00")
.split(":")[0],
10,
);
const res: [string, object][] = [];
for (let i = 0; i <= this.endSlot - this.startSlot; i += 60 / MINUTES_PER_SLOT) {

View File

@@ -2,8 +2,8 @@
import { parse, resolve } from "node:path";
import inject from "@rollup/plugin-inject";
import { glob } from "glob";
import { type AliasOptions, type UserConfig, defineConfig } from "vite";
import type { Rollup } from "vite";
import { type AliasOptions, defineConfig, type UserConfig } from "vite";
import tsconfig from "./tsconfig.json";
const outDir = resolve(__dirname, "./staticfiles/generated/bundled");