浏览代码

ref: switch to NodeNext module resolution thanks to a cool eslint plugin

Sv443 10 月之前
父节点
当前提交
83b9bc99f5

+ 2 - 0
.eslintrc.cjs

@@ -14,6 +14,7 @@ module.exports = {
   extends: [
     "eslint:recommended",
     "plugin:@typescript-eslint/recommended",
+    "plugin:require-extensions/recommended",
   ],
   globals: {
     Atomics: "readonly",
@@ -31,6 +32,7 @@ module.exports = {
   },
   plugins: [
     "@typescript-eslint",
+    "require-extensions",
   ],
   rules: {
     "no-unreachable": "off",

+ 13 - 0
package-lock.json

@@ -28,6 +28,7 @@
         "concurrently": "^8.1.0",
         "dotenv": "^16.4.1",
         "eslint": "^8.51.0",
+        "eslint-plugin-require-extensions": "^0.1.3",
         "express": "^4.18.2",
         "knip": "^5.15.1",
         "nodemon": "^3.0.1",
@@ -1842,6 +1843,18 @@
         "url": "https://opencollective.com/eslint"
       }
     },
+    "node_modules/eslint-plugin-require-extensions": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-require-extensions/-/eslint-plugin-require-extensions-0.1.3.tgz",
+      "integrity": "sha512-T3c1PZ9PIdI3hjV8LdunfYI8gj017UQjzAnCrxuo3wAjneDbTPHdE3oNWInOjMA+z/aBkUtlW5vC0YepYMZIug==",
+      "dev": true,
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "eslint": "*"
+      }
+    },
     "node_modules/eslint-scope": {
       "version": "7.2.2",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",

+ 1 - 0
package.json

@@ -79,6 +79,7 @@
     "concurrently": "^8.1.0",
     "dotenv": "^16.4.1",
     "eslint": "^8.51.0",
+    "eslint-plugin-require-extensions": "^0.1.3",
     "express": "^4.18.2",
     "knip": "^5.15.1",
     "nodemon": "^3.0.1",

+ 4 - 4
src/components/BytmDialog.ts

@@ -1,8 +1,8 @@
 // hoist the class declaration because either rollup or babel is being a hoe
-import { NanoEmitter } from "../utils/NanoEmitter";
-import { addStyle, clearInner, getDomain, getResourceUrl, onInteraction, warn } from "../utils";
-import { t } from "../utils/translations";
-import { emitInterface } from "../interface";
+import { NanoEmitter } from "../utils/NanoEmitter.js";
+import { addStyle, clearInner, getDomain, getResourceUrl, onInteraction, warn } from "../utils/index.js";
+import { t } from "../utils/translations.js";
+import { emitInterface } from "../interface.js";
 import "./BytmDialog.css";
 
 export interface BytmDialogOptions {

+ 2 - 2
src/components/circularButton.ts

@@ -1,5 +1,5 @@
-import { getResourceUrl, onInteraction } from "../utils";
-import type { ResourceKey } from "../types";
+import { getResourceUrl, onInteraction } from "../utils/index.js";
+import type { ResourceKey } from "../types.js";
 
 type CircularBtnOptions = (
   | {

+ 3 - 3
src/components/hotkeyInput.ts

@@ -1,6 +1,6 @@
-import { siteEvents } from "../siteEvents";
-import { onInteraction, t } from "../utils";
-import type { HotkeyObj } from "../types";
+import { siteEvents } from "../siteEvents.js";
+import { onInteraction, t } from "../utils/index.js";
+import type { HotkeyObj } from "../types.js";
 import "./hotkeyInput.css";
 
 interface HotkeyInputProps {

+ 7 - 7
src/components/index.ts

@@ -1,7 +1,7 @@
-export * from "./BytmDialog";
-export * from "./circularButton";
-export * from "./hotkeyInput";
-export * from "./longButton";
-export * from "./ripple";
-export * from "./toast";
-export * from "./toggleInput";
+export * from "./BytmDialog.js";
+export * from "./circularButton.js";
+export * from "./hotkeyInput.js";
+export * from "./longButton.js";
+export * from "./ripple.js";
+export * from "./toast.js";
+export * from "./toggleInput.js";

+ 2 - 2
src/components/longButton.ts

@@ -1,5 +1,5 @@
-import { onInteraction, resourceToHTMLString } from "../utils";
-import type { ResourceKey } from "../types";
+import { onInteraction, resourceToHTMLString } from "../utils/index.js";
+import type { ResourceKey } from "../types.js";
 
 type LongBtnOptions = (
   | {

+ 3 - 3
src/components/toast.ts

@@ -1,7 +1,7 @@
 import { pauseFor } from "@sv443-network/userutils";
-import { info, resourceToHTMLString } from "../utils";
-import { getFeature } from "../config";
-import type { ResourceKey } from "../types";
+import { info, resourceToHTMLString } from "../utils/index.js";
+import { getFeature } from "../config.js";
+import type { ResourceKey } from "../types.js";
 import "./toast.css";
 
 type ToastPos = "tl" | "tr" | "bl" | "br";

+ 1 - 1
src/components/toggleInput.ts

@@ -1,5 +1,5 @@
 import { randomId } from "@sv443-network/userutils";
-import { t } from "../utils";
+import { t } from "../utils/index.js";
 import "./toggleInput.css";
 
 export interface ToggleInputProps {

+ 7 - 7
src/config.ts

@@ -1,11 +1,11 @@
 import { DataStore, compress, type DataMigrationsDict, decompress } from "@sv443-network/userutils";
-import { disableBeforeUnload, featInfo } from "./features/index";
-import { compressionSupported, error, getVideoTime, info, log, t } from "./utils";
-import { emitSiteEvent } from "./siteEvents";
-import { compressionFormat, mode } from "./constants";
-import { emitInterface } from "./interface";
-import { closeCfgMenu } from "./menu/menu_old";
-import type { FeatureConfig, FeatureKey } from "./types";
+import { disableBeforeUnload, featInfo } from "./features/index.js";
+import { compressionSupported, error, getVideoTime, info, log, t } from "./utils/index.js";
+import { emitSiteEvent } from "./siteEvents.js";
+import { compressionFormat, mode } from "./constants.js";
+import { emitInterface } from "./interface.js";
+import { closeCfgMenu } from "./menu/menu_old.js";
+import type { FeatureConfig, FeatureKey } from "./types.js";
 
 /** If this number is incremented, the features object data will be migrated to the new format */
 export const formatVersion = 6;

+ 1 - 1
src/constants.ts

@@ -1,5 +1,5 @@
 import { randomId } from "@sv443-network/userutils";
-import { LogLevel } from "./types";
+import { LogLevel } from "./types.js";
 
 const modeRaw = "#{{MODE}}";
 const branchRaw = "#{{BRANCH}}";

+ 4 - 4
src/dialogs/autoLike.ts

@@ -1,8 +1,8 @@
 import { debounce } from "@sv443-network/userutils";
-import { getDomain, log, onInteraction, parseChannelIdFromUrl, t } from "../utils";
-import { BytmDialog, createCircularBtn, createToggleInput } from "../components";
-import { autoLikeStore, initAutoLikeStore } from "../features";
-import { siteEvents } from "../siteEvents";
+import { getDomain, log, onInteraction, parseChannelIdFromUrl, t } from "../utils/index.js";
+import { BytmDialog, createCircularBtn, createToggleInput } from "../components/index.js";
+import { autoLikeStore, initAutoLikeStore } from "../features/index.js";
+import { siteEvents } from "../siteEvents.js";
 
 let autoLikeDialog: BytmDialog | null = null;
 

+ 3 - 3
src/dialogs/changelog.ts

@@ -1,6 +1,6 @@
-import { getChangelogHtmlWithDetails, t } from "../utils";
-import { BytmDialog } from "../components";
-import { scriptInfo } from "../constants";
+import { getChangelogHtmlWithDetails, t } from "../utils/index.js";
+import { BytmDialog } from "../components/index.js";
+import { scriptInfo } from "../constants.js";
 
 let changelogDialog: BytmDialog | null = null;
 

+ 4 - 4
src/dialogs/exportCfg.ts

@@ -1,8 +1,8 @@
 import { compress } from "@sv443-network/userutils";
-import { compressionSupported, copyToClipboard, onInteraction, t } from "../utils";
-import { BytmDialog } from "../components";
-import { compressionFormat, scriptInfo } from "../constants";
-import { formatVersion, getFeatures } from "../config";
+import { compressionSupported, copyToClipboard, onInteraction, t } from "../utils/index.js";
+import { BytmDialog } from "../components/index.js";
+import { compressionFormat, scriptInfo } from "../constants.js";
+import { formatVersion, getFeatures } from "../config.js";
 import { siteEvents } from "src/siteEvents";
 
 let exportDialog: BytmDialog | null = null;

+ 4 - 4
src/dialogs/featHelp.ts

@@ -1,7 +1,7 @@
-import { resourceToHTMLString, t } from "../utils";
-import { BytmDialog } from "../components";
-import { featInfo } from "../features";
-import type { FeatureKey } from "../types";
+import { resourceToHTMLString, t } from "../utils/index.js";
+import { BytmDialog } from "../components/index.js";
+import { featInfo } from "../features/index.js";
+import type { FeatureKey } from "../types.js";
 
 let featHelpDialog: BytmDialog | null = null;
 let curFeatKey: FeatureKey | null = null;

+ 6 - 6
src/dialogs/importCfg.ts

@@ -1,10 +1,10 @@
 import { decompress } from "@sv443-network/userutils";
-import { error, t, warn } from "../utils";
-import { BytmDialog } from "../components";
-import { compressionFormat, scriptInfo } from "../constants";
-import { emitSiteEvent } from "../siteEvents";
-import { formatVersion, getFeatures, migrations, setFeatures } from "../config";
-import { disableBeforeUnload } from "../features";
+import { error, t, warn } from "../utils/index.js";
+import { BytmDialog } from "../components/index.js";
+import { compressionFormat, scriptInfo } from "../constants.js";
+import { emitSiteEvent } from "../siteEvents.js";
+import { formatVersion, getFeatures, migrations, setFeatures } from "../config.js";
+import { disableBeforeUnload } from "../features/index.js";
 
 let importDialog: BytmDialog | null = null;
 

+ 8 - 8
src/dialogs/index.ts

@@ -1,10 +1,10 @@
 import "./dialogs.css";
 
-export * from "./autoLike";
-export * from "./changelog";
-export * from "./exportCfg";
-export * from "./featConfig";
-export * from "./featHelp";
-export * from "./importCfg";
-export * from "./versionNotif";
-export * from "./welcome";
+export * from "./autoLike.js";
+export * from "./changelog.js";
+export * from "./exportCfg.js";
+export * from "./featConfig.js";
+export * from "./featHelp.js";
+export * from "./importCfg.js";
+export * from "./versionNotif.js";
+export * from "./welcome.js";

+ 4 - 4
src/dialogs/versionNotif.ts

@@ -1,7 +1,7 @@
-import { host, mode, scriptInfo } from "../constants";
-import { getChangelogMd, getResourceUrl, onInteraction, parseMarkdown, t } from "../utils";
-import { BytmDialog, createToggleInput } from "../components";
-import { getFeatures, setFeatures } from "../config";
+import { host, mode, scriptInfo } from "../constants.js";
+import { getChangelogMd, getResourceUrl, onInteraction, parseMarkdown, t } from "../utils/index.js";
+import { BytmDialog, createToggleInput } from "../components/index.js";
+import { getFeatures, setFeatures } from "../config.js";
 import pkg from "../../package.json" with { type: "json" };
 import { siteEvents } from "src/siteEvents";
 

+ 6 - 6
src/dialogs/welcome.ts

@@ -1,9 +1,9 @@
-import { getResourceUrl, initTranslations, setLocale, t, warn, type TrLocale } from "../utils";
-import { BytmDialog } from "../components";
-import { openCfgMenu } from "../menu/menu_old";
-import { mode, scriptInfo } from "../constants";
-import { getFeatures, setFeatures } from "../config";
-import { getChangelogDialog } from ".";
+import { getResourceUrl, initTranslations, setLocale, t, warn, type TrLocale } from "../utils/index.js";
+import { BytmDialog } from "../components/index.js";
+import { openCfgMenu } from "../menu/menu_old.js";
+import { mode, scriptInfo } from "../constants.js";
+import { getFeatures, setFeatures } from "../config.js";
+import { getChangelogDialog } from "./index.js";
 import pkg from "../../package.json" with { type: "json" };
 import locales from "../../assets/locales.json" with { type: "json" };
 

+ 5 - 5
src/features/behavior.ts

@@ -1,9 +1,9 @@
 import { clamp, interceptWindowEvent, pauseFor } from "@sv443-network/userutils";
-import { domLoaded, error, getDomain, getVideoTime, getWatchId, info, log, getVideoSelector, waitVideoElementReady } from "../utils";
-import { getFeatures } from "../config";
-import { addSelectorListener } from "../observers";
-import { initialParams } from "../constants";
-import { LogLevel } from "../types";
+import { domLoaded, error, getDomain, getVideoTime, getWatchId, info, log, getVideoSelector, waitVideoElementReady } from "../utils/index.js";
+import { getFeatures } from "../config.js";
+import { addSelectorListener } from "../observers.js";
+import { initialParams } from "../constants.js";
+import { LogLevel } from "../types.js";
 
 //#region beforeunload popup
 

+ 17 - 17
src/features/index.ts

@@ -1,22 +1,22 @@
-import { getPreferredLocale, getResourceUrl, resourceToHTMLString, t, tp } from "../utils";
-import { clearLyricsCache, getLyricsCache } from "./lyricsCache";
-import { doVersionCheck } from "./versionCheck";
-import { getFeatures, promptResetConfig } from "../config";
-import { FeatureInfo, type ResourceKey, type SiteSelection, type SiteSelectionOrNone } from "../types";
-import { emitSiteEvent } from "../siteEvents";
+import { getPreferredLocale, getResourceUrl, resourceToHTMLString, t, tp } from "../utils/index.js";
+import { clearLyricsCache, getLyricsCache } from "./lyricsCache.js";
+import { doVersionCheck } from "./versionCheck.js";
+import { getFeatures, promptResetConfig } from "../config.js";
+import { FeatureInfo, type ResourceKey, type SiteSelection, type SiteSelectionOrNone } from "../types.js";
+import { emitSiteEvent } from "../siteEvents.js";
 import langMapping from "../../assets/locales.json" with { type: "json" };
-import { getAutoLikeDialog } from "../dialogs";
-import { showIconToast } from "../components";
-import { mode } from "../constants";
+import { getAutoLikeDialog } from "../dialogs/index.js";
+import { showIconToast } from "../components/index.js";
+import { mode } from "../constants.js";
 
-export * from "./layout";
-export * from "./behavior";
-export * from "./input";
-export * from "./lyrics";
-export * from "./lyricsCache";
-export * from "./songLists";
-export * from "./versionCheck";
-export * from "./volume";
+export * from "./layout.js";
+export * from "./behavior.js";
+export * from "./input.js";
+export * from "./lyrics.js";
+export * from "./lyricsCache.js";
+export * from "./songLists.js";
+export * from "./versionCheck.js";
+export * from "./volume.js";
 
 interface SelectOption<TValue = number | string> {
   value: TValue;

+ 13 - 13
src/features/input.ts

@@ -1,15 +1,15 @@
 import { DataStore, clamp, compress, decompress } from "@sv443-network/userutils";
-import { error, getVideoTime, info, log, warn, getVideoSelector, getDomain, compressionSupported, t, clearNode, resourceToHTMLString, getCurrentChannelId } from "../utils";
-import type { Domain } from "../types";
-import { isCfgMenuOpen } from "../menu/menu_old";
-import { disableBeforeUnload } from "./behavior";
-import { siteEvents } from "../siteEvents";
-import { featInfo } from "./index";
-import { getFeature } from "../config";
-import { compressionFormat } from "../constants";
-import { addSelectorListener } from "../observers";
-import { createLongBtn, showIconToast } from "../components";
-import { getAutoLikeDialog } from "../dialogs";
+import { error, getVideoTime, info, log, warn, getVideoSelector, getDomain, compressionSupported, t, clearNode, resourceToHTMLString, getCurrentChannelId } from "../utils/index.js";
+import type { Domain } from "../types.js";
+import { isCfgMenuOpen } from "../menu/menu_old.js";
+import { disableBeforeUnload } from "./behavior.js";
+import { siteEvents } from "../siteEvents.js";
+import { featInfo } from "./index.js";
+import { getFeature } from "../config.js";
+import { compressionFormat } from "../constants.js";
+import { addSelectorListener } from "../observers.js";
+import { createLongBtn, showIconToast } from "../components/index.js";
+import { getAutoLikeDialog } from "../dialogs/index.js";
 import "./input.css";
 
 export const inputIgnoreTagNames = ["INPUT", "TEXTAREA", "SELECT", "BUTTON", "A"];
@@ -270,7 +270,7 @@ export async function initAutoLike() {
         if(!location.pathname.startsWith("/watch"))
           return;
         timeout = setTimeout(() => {
-          addSelectorListener<HTMLAnchorElement, "yt">("watchMetadata", "#owner ytd-channel-name yt-formatted-string a", {
+          addSelectorListener<HTMLAnchorElement, "yt">("ytWatchMetadata", "#owner ytd-channel-name yt-formatted-string a", {
             listener(chanElem) {
               const chanElemId = chanElem.href.split("/").pop()?.split("/")[0] ?? null;
 
@@ -278,7 +278,7 @@ export async function initAutoLike() {
               if(!likeChan || !likeChan.enabled)
                 return;
 
-              addSelectorListener<0, "yt">("watchMetadata", "#actions ytd-menu-renderer like-button-view-model button", {
+              addSelectorListener<0, "yt">("ytWatchMetadata", "#actions ytd-menu-renderer like-button-view-model button", {
                 listener(likeBtn) {
                   if(likeBtn.getAttribute("aria-pressed") !== "true") {
                     likeBtn.click();

+ 8 - 8
src/features/layout.ts

@@ -1,12 +1,12 @@
 import { addParent, autoPlural, debounce, fetchAdvanced, pauseFor } from "@sv443-network/userutils";
-import { getFeatures } from "../config";
-import { siteEvents } from "../siteEvents";
-import { addSelectorListener } from "../observers";
-import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource } from "../utils";
-import { mode, scriptInfo } from "../constants";
-import { openCfgMenu } from "../menu/menu_old";
-import { createCircularBtn } from "../components";
-import type { ResourceKey } from "../types";
+import { getFeatures } from "../config.js";
+import { siteEvents } from "../siteEvents.js";
+import { addSelectorListener } from "../observers.js";
+import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource } from "../utils/index.js";
+import { mode, scriptInfo } from "../constants.js";
+import { openCfgMenu } from "../menu/menu_old.js";
+import { createCircularBtn } from "../components/index.js";
+import type { ResourceKey } from "../types.js";
 import "./layout.css";
 
 //#region cfg menu buttons

+ 6 - 6
src/features/lyrics.ts

@@ -1,11 +1,11 @@
 import { autoPlural, fetchAdvanced } from "@sv443-network/userutils";
 import Fuse from "fuse.js";
-import { error, getResourceUrl, info, log, warn, t, tp, currentMediaType, constructUrl } from "../utils";
-import { emitInterface } from "../interface";
-import { mode, scriptInfo } from "../constants";
-import { getFeature } from "../config";
-import { addLyricsCacheEntryBest, addLyricsCacheEntryPenalized, getLyricsCacheEntry } from "./lyricsCache";
-import type { LyricsCacheEntry } from "../types";
+import { error, getResourceUrl, info, log, warn, t, tp, currentMediaType, constructUrl } from "../utils/index.js";
+import { emitInterface } from "../interface.js";
+import { mode, scriptInfo } from "../constants.js";
+import { getFeature } from "../config.js";
+import { addLyricsCacheEntryBest, addLyricsCacheEntryPenalized, getLyricsCacheEntry } from "./lyricsCache.js";
+import type { LyricsCacheEntry } from "../types.js";
 import { addSelectorListener } from "src/observers";
 
 /** Ratelimit budget timeframe in seconds - should reflect what's in geniURL's docs */

+ 5 - 5
src/features/lyricsCache.ts

@@ -1,9 +1,9 @@
 import { DataStore, clamp, compress, decompress } from "@sv443-network/userutils";
-import { compressionFormat } from "../constants";
-import { compressionSupported, log } from "../utils";
-import { emitInterface } from "../interface";
-import { getFeatures } from "../config";
-import type { LyricsCacheEntry } from "../types";
+import { compressionFormat } from "../constants.js";
+import { compressionSupported, log } from "../utils/index.js";
+import { emitInterface } from "../interface.js";
+import { getFeatures } from "../config.js";
+import type { LyricsCacheEntry } from "../types.js";
 
 export type LyricsCache = {
   cache: LyricsCacheEntry[];

+ 8 - 8
src/features/songLists.ts

@@ -1,12 +1,12 @@
 import { autoPlural, pauseFor } from "@sv443-network/userutils";
-import { clearInner, error, getResourceUrl, log, onInteraction, openInTab, t } from "../utils";
-import { SiteEventsMap, siteEvents } from "../siteEvents";
-import { emitInterface } from "../interface";
-import { fetchLyricsUrlTop, createLyricsBtn, sanitizeArtists, sanitizeSong, splitVideoTitle } from "./lyrics";
-import { getLyricsCacheEntry } from "./lyricsCache";
-import type { LyricsCacheEntry } from "../types";
-import { addSelectorListener } from "../observers";
-import { getFeatures } from "../config";
+import { clearInner, error, getResourceUrl, log, onInteraction, openInTab, t } from "../utils/index.js";
+import { SiteEventsMap, siteEvents } from "../siteEvents.js";
+import { emitInterface } from "../interface.js";
+import { fetchLyricsUrlTop, createLyricsBtn, sanitizeArtists, sanitizeSong, splitVideoTitle } from "./lyrics.js";
+import { getLyricsCacheEntry } from "./lyricsCache.js";
+import type { LyricsCacheEntry } from "../types.js";
+import { addSelectorListener } from "../observers.js";
+import { getFeatures } from "../config.js";
 import "./songLists.css";
 
 /** Initializes the queue buttons */

+ 5 - 5
src/features/versionCheck.ts

@@ -1,9 +1,9 @@
-import { scriptInfo } from "../constants";
-import { getFeatures } from "../config";
-import { error, info, sendRequest, t } from "../utils";
-import { getVersionNotifDialog } from "../dialogs";
+import { scriptInfo } from "../constants.js";
+import { getFeatures } from "../config.js";
+import { error, info, sendRequest, t } from "../utils/index.js";
+import { getVersionNotifDialog } from "../dialogs/index.js";
 import { compare } from "compare-versions";
-import { LogLevel } from "../types";
+import { LogLevel } from "../types.js";
 
 const releaseURL = "https://github.com/Sv443/BetterYTM/releases/latest";
 

+ 4 - 4
src/features/volume.ts

@@ -1,8 +1,8 @@
 import { addParent, type Stringifiable } from "@sv443-network/userutils";
-import { getFeatures } from "../config";
-import { addStyleFromResource, error, log, resourceToHTMLString, t, waitVideoElementReady } from "../utils";
-import { siteEvents } from "../siteEvents";
-import { featInfo } from ".";
+import { getFeatures } from "../config.js";
+import { addStyleFromResource, error, log, resourceToHTMLString, t, waitVideoElementReady } from "../utils/index.js";
+import { siteEvents } from "../siteEvents.js";
+import { featInfo } from "./index.js";
 import "./volume.css";
 import { addSelectorListener } from "src/observers";
 

+ 10 - 10
src/index.ts

@@ -1,13 +1,13 @@
 import { compress, decompress, pauseFor, type Stringifiable } from "@sv443-network/userutils";
-import { addStyleFromResource, domLoaded, warn } from "./utils";
-import { clearConfig, fixMissingCfgKeys, getFeatures, initConfig, setFeatures } from "./config";
-import { buildNumber, compressionFormat, defaultLogLevel, mode, scriptInfo } from "./constants";
-import { error, getDomain, info, getSessionId, log, setLogLevel, initTranslations, setLocale } from "./utils";
-import { initSiteEvents } from "./siteEvents";
-import { emitInterface, initInterface, initPlugins } from "./interface";
-import { initObservers, addSelectorListener, globservers } from "./observers";
-import { getWelcomeDialog } from "./dialogs";
-import type { FeatureConfig } from "./types";
+import { addStyleFromResource, domLoaded, warn } from "./utils/index.js";
+import { clearConfig, fixMissingCfgKeys, getFeatures, initConfig, setFeatures } from "./config.js";
+import { buildNumber, compressionFormat, defaultLogLevel, mode, scriptInfo } from "./constants.js";
+import { error, getDomain, info, getSessionId, log, setLogLevel, initTranslations, setLocale } from "./utils/index.js";
+import { initSiteEvents } from "./siteEvents.js";
+import { emitInterface, initInterface, initPlugins } from "./interface.js";
+import { initObservers, addSelectorListener, globservers } from "./observers.js";
+import { getWelcomeDialog } from "./dialogs/index.js";
+import type { FeatureConfig } from "./types.js";
 import {
   // layout
   addWatermark, removeUpgradeTab, initRemShareTrackParam, fixSpacing, initThumbnailOverlay, initHideCursorOnIdle, fixHdrIssues,
@@ -25,7 +25,7 @@ import {
   addConfigMenuOptionYT, addConfigMenuOptionYTM,
   // general
   initVersionCheck,
-} from "./features";
+} from "./features/index.js";
 
 //#region console watermark
 

+ 8 - 8
src/interface.ts

@@ -1,13 +1,13 @@
 import * as UserUtils from "@sv443-network/userutils";
 import * as compareVersions from "compare-versions";
-import { mode, branch, host, buildNumber, compressionFormat, scriptInfo } from "./constants";
-import { getResourceUrl, getSessionId, getVideoTime, log, setLocale, getLocale, hasKey, hasKeyFor, NanoEmitter, t, tp, type TrLocale, info, error, onInteraction, getThumbnailUrl, getBestThumbnailUrl } from "./utils";
-import { addSelectorListener } from "./observers";
-import { getFeatures, setFeatures } from "./config";
-import { featInfo, fetchLyricsUrlTop, getLyricsCacheEntry, sanitizeArtists, sanitizeSong } from "./features";
-import { allSiteEvents, type SiteEventsMap } from "./siteEvents";
-import { LogLevel, type FeatureConfig, type FeatureInfo, type LyricsCacheEntry, type PluginDef, type PluginInfo, type PluginRegisterResult, type PluginDefResolvable, type PluginEventMap, type PluginItem, type BytmObject } from "./types";
-import { BytmDialog, createCircularBtn, createHotkeyInput, createRipple, createToggleInput, showIconToast, showToast } from "./components";
+import { mode, branch, host, buildNumber, compressionFormat, scriptInfo } from "./constants.js";
+import { getResourceUrl, getSessionId, getVideoTime, log, setLocale, getLocale, hasKey, hasKeyFor, NanoEmitter, t, tp, type TrLocale, info, error, onInteraction, getThumbnailUrl, getBestThumbnailUrl } from "./utils/index.js";
+import { addSelectorListener } from "./observers.js";
+import { getFeatures, setFeatures } from "./config.js";
+import { featInfo, fetchLyricsUrlTop, getLyricsCacheEntry, sanitizeArtists, sanitizeSong } from "./features/index.js";
+import { allSiteEvents, type SiteEventsMap } from "./siteEvents.js";
+import { LogLevel, type FeatureConfig, type FeatureInfo, type LyricsCacheEntry, type PluginDef, type PluginInfo, type PluginRegisterResult, type PluginDefResolvable, type PluginEventMap, type PluginItem, type BytmObject } from "./types.js";
+import { BytmDialog, createCircularBtn, createHotkeyInput, createRipple, createToggleInput, showIconToast, showToast } from "./components/index.js";
 
 const { getUnsafeWindow, randomId } = UserUtils;
 

+ 8 - 8
src/menu/menu_old.ts

@@ -1,13 +1,13 @@
 import { debounce, isScrollable, type Stringifiable } from "@sv443-network/userutils";
-import { defaultData, getFeatures, setFeatures } from "../config";
-import { buildNumber, host, mode, scriptInfo } from "../constants";
-import { featInfo, disableBeforeUnload } from "../features/index";
-import { error, getResourceUrl, info, log, resourceToHTMLString, getLocale, hasKey, initTranslations, setLocale, t, arrayWithSeparators, tp, type TrKey, onInteraction, getDomain, copyToClipboard } from "../utils";
-import { siteEvents } from "../siteEvents";
-import { getChangelogDialog, getExportDialog, getFeatHelpDialog, getImportDialog } from "../dialogs";
-import type { FeatureCategory, FeatureKey, FeatureConfig, HotkeyObj, FeatureInfo } from "../types";
+import { defaultData, getFeatures, setFeatures } from "../config.js";
+import { buildNumber, host, mode, scriptInfo } from "../constants.js";
+import { featInfo, disableBeforeUnload } from "../features/index.js";
+import { error, getResourceUrl, info, log, resourceToHTMLString, getLocale, hasKey, initTranslations, setLocale, t, arrayWithSeparators, tp, type TrKey, onInteraction, getDomain, copyToClipboard } from "../utils/index.js";
+import { siteEvents } from "../siteEvents.js";
+import { getChangelogDialog, getExportDialog, getFeatHelpDialog, getImportDialog } from "../dialogs/index.js";
+import type { FeatureCategory, FeatureKey, FeatureConfig, HotkeyObj, FeatureInfo } from "../types.js";
 import "./menu_old.css";
-import { createHotkeyInput, createToggleInput, openDialogs, setCurrentDialogId } from "../components";
+import { createHotkeyInput, createToggleInput, openDialogs, setCurrentDialogId } from "../components/index.js";
 import pkg from "../../package.json" with { type: "json" };
 
 //#region create menu

+ 4 - 4
src/siteEvents.ts

@@ -1,7 +1,7 @@
-import { NanoEmitter, error, getDomain, info } from "./utils";
-import { FeatureConfig } from "./types";
-import { emitInterface } from "./interface";
-import { addSelectorListener } from "./observers";
+import { NanoEmitter, error, getDomain, info } from "./utils/index.js";
+import { FeatureConfig } from "./types.js";
+import { emitInterface } from "./interface.js";
+import { addSelectorListener } from "./observers.js";
 
 export interface SiteEventsMap {
   // misc:

+ 1 - 1
src/tools/gen-readme.ts

@@ -1,7 +1,7 @@
 import { readFile, writeFile } from "node:fs/promises";
 import { join } from "node:path";
 import { fileURLToPath } from "node:url";
-import type { PluginDef } from "../types";
+import type { PluginDef } from "../types.js";
 import locales from "../../assets/locales.json" with { type: "json" };
 import pluginsJson from "../../assets/plugins.json" with { type: "json" };
 import pkgJson from "../../package.json" with { type: "json" };

+ 1 - 1
src/tools/post-build.ts

@@ -7,7 +7,7 @@ import "dotenv/config";
 import { outputDir as rollupCfgOutputDir, outputFile as rollupCfgOutputFile } from "../../rollup.config.mjs";
 import locales from "../../assets/locales.json" with { type: "json" };
 import pkg from "../../package.json" with { type: "json" };
-import type { RollupArgs } from "../types";
+import type { RollupArgs } from "../types.js";
 
 /** Any type that is either a string or can be implicitly converted to one by having a .toString() method */
 type Stringifiable = string | { toString(): string; };

+ 1 - 1
src/tools/tr-format.ts

@@ -1,5 +1,5 @@
 import { readFile, writeFile } from "node:fs/promises";
-import type { TrLocale } from "../utils";
+import type { TrLocale } from "../utils/index.js";
 import locales from "../../assets/locales.json" with { type: "json" };
 
 const prepTranslate = process.argv.find((v) => v.match(/--prep(are)?/) || v.toLowerCase() === "-p");

+ 1 - 1
src/tools/tr-progress.ts

@@ -2,7 +2,7 @@ import { autoPlural, mapRange } from "@sv443-network/userutils";
 import { readFile, writeFile } from "node:fs/promises";
 import { join, relative, resolve } from "node:path";
 import { fileURLToPath } from "node:url";
-import type { TrLocale } from "../utils";
+import type { TrLocale } from "../utils/index.js";
 import locales from "../../assets/locales.json" with { type: "json" };
 
 const { exit } = process;

+ 7 - 7
src/types.ts

@@ -1,12 +1,12 @@
-import type * as consts from "./constants";
-import type { scriptInfo } from "./constants";
-import type { addSelectorListener } from "./observers";
+import type * as consts from "./constants.js";
+import type { scriptInfo } from "./constants.js";
+import type { addSelectorListener } from "./observers.js";
 import type resources from "../assets/resources.json";
 import type locales from "../assets/locales.json";
-import type { getResourceUrl, getSessionId, getVideoTime, TrLocale, t, tp, NanoEmitter } from "./utils";
-import type { getFeatures, setFeatures } from "./config";
-import type { SiteEventsMap } from "./siteEvents";
-import type { InterfaceEventsMap } from "./interface";
+import type { getResourceUrl, getSessionId, getVideoTime, TrLocale, t, tp, NanoEmitter } from "./utils/index.js";
+import type { getFeatures, setFeatures } from "./config.js";
+import type { SiteEventsMap } from "./siteEvents.js";
+import type { InterfaceEventsMap } from "./interface.js";
 
 /** Custom CLI args passed to rollup */
 export type RollupArgs = Partial<{

+ 3 - 3
src/utils/dom.ts

@@ -1,7 +1,7 @@
 import { addGlobalStyle, getUnsafeWindow, randomId, type Stringifiable } from "@sv443-network/userutils";
-import { error, fetchCss, getDomain, t } from ".";
-import { addSelectorListener } from "../observers";
-import type { ResourceKey } from "../types";
+import { error, fetchCss, getDomain, t } from "./index.js";
+import { addSelectorListener } from "../observers.js";
+import type { ResourceKey } from "../types.js";
 import { siteEvents } from "src/siteEvents";
 
 /** Whether the DOM has finished loading and elements can be added or modified */

+ 6 - 6
src/utils/index.ts

@@ -1,6 +1,6 @@
-export * from "./dom";
-export * from "./logging";
-export * from "./misc";
-export * from "./NanoEmitter";
-export * from "./translations";
-export * from "./xhr";
+export * from "./dom.js";
+export * from "./logging.js";
+export * from "./misc.js";
+export * from "./NanoEmitter.js";
+export * from "./translations.js";
+export * from "./xhr.js";

+ 3 - 3
src/utils/logging.ts

@@ -1,7 +1,7 @@
 import { clamp } from "@sv443-network/userutils";
-import { scriptInfo } from "../constants";
-import { setGlobalProp } from "../interface";
-import { LogLevel } from "../types";
+import { scriptInfo } from "../constants.js";
+import { setGlobalProp } from "../interface.js";
+import { LogLevel } from "../types.js";
 
 let curLogLevel = LogLevel.Info;
 

+ 3 - 3
src/utils/misc.ts

@@ -1,8 +1,8 @@
 import { compress, fetchAdvanced, openInNewTab, randomId } from "@sv443-network/userutils";
 import { marked } from "marked";
-import { branch, compressionFormat, repo } from "../constants";
-import { type Domain, type ResourceKey } from "../types";
-import { error, type TrLocale, warn, sendRequest } from ".";
+import { branch, compressionFormat, repo } from "../constants.js";
+import { type Domain, type ResourceKey } from "../types.js";
+import { error, type TrLocale, warn, sendRequest } from "./index.js";
 import langMapping from "../../assets/locales.json" with { type: "json" };
 
 //#region misc

+ 3 - 3
src/utils/translations.ts

@@ -1,7 +1,7 @@
 import { tr, Stringifiable, fetchAdvanced, FetchAdvancedOpts } from "@sv443-network/userutils";
-import { error, getResourceUrl, info } from ".";
-import { emitInterface, setGlobalProp } from "../interface";
-import { getFeature } from "../config";
+import { error, getResourceUrl, info } from "./index.js";
+import { emitInterface, setGlobalProp } from "../interface.js";
+import { getFeature } from "../config.js";
 import langMapping from "../../assets/locales.json" with { type: "json" };
 import type tr_enUS from "../../assets/translations/en_US.json";
 

+ 2 - 2
src/utils/xhr.ts

@@ -1,7 +1,7 @@
 import { fetchAdvanced, type Stringifiable } from "@sv443-network/userutils";
 import type { ResourceKey } from "src/types";
-import { getResourceUrl } from "./misc";
-import { error } from "./logging";
+import { getResourceUrl } from "./misc.js";
+import { error } from "./logging.js";
 
 /**
  * Constructs a URL from a base URL and a record of query parameters.  

+ 2 - 2
tsconfig.json

@@ -1,7 +1,7 @@
 {
   "compilerOptions": {
-    "module": "ESNext",
-    "moduleResolution": "node",
+    "module": "NodeNext",
+    "moduleResolution": "NodeNext",
     "target": "ES2016",
     "outDir": "dist/out",
     "lib": [