From 0d1401bd6c02ea34f9f82180f010e5836c89817b Mon Sep 17 00:00:00 2001 From: SimonShiki Date: Sun, 29 Oct 2023 14:01:25 +0000 Subject: [PATCH] :fire: chore: goodbye prettier Signed-off-by: SimonShiki --- .eslintrc.json | 16 +++++++ package.json | 2 - src/frontend/index.ts | 6 +-- src/injector/inject.ts | 48 +++++++++---------- src/loader/dispatch/central-dispatch.ts | 14 +++--- src/loader/dispatch/shared-dispatch.ts | 22 ++++----- src/loader/dispatch/worker-dispatch.ts | 10 ++-- src/loader/loader.ts | 34 +++++++------- src/loader/make-ctx.ts | 4 +- src/loader/sandbox.worker.ts | 4 +- src/util/cast.ts | 22 ++++----- src/util/color.ts | 22 ++++----- src/util/log.ts | 6 +-- src/util/settings.ts | 61 +++++++++++++++++++++++++ yarn.lock | 5 -- 15 files changed, 173 insertions(+), 103 deletions(-) create mode 100644 src/util/settings.ts diff --git a/.eslintrc.json b/.eslintrc.json index d9a14f0..c0efe0c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -28,11 +28,27 @@ "no-var": "error", "comma-spacing": "error", "func-call-spacing": "error", + "space-before-function-paren": "error", "dot-location": ["error", "property"], "no-whitespace-before-property": "error", "space-unary-ops": ["error", { "words": true, "nonwords": false + }], + "quotes": [2, "single", { + "allowTemplateLiterals": true, + "avoidEscape": true + }], + "no-unneeded-ternary": [2], + "eol-last": [2, "always"], + "key-spacing": [2, { + "beforeColon": false, + "afterColon": true, + "mode": "strict" + }], + "keyword-spacing": [2, { + "before": true, + "after": true }] } } diff --git a/package.json b/package.json index d7e6dcf..bb7cc13 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "scripts": { "build": "NODE_ENV=production webpack --color --bail", "lint": "eslint ./src/ --ext .js,.ts,tsx,jsx", - "format": "prettier -w --config .prettierrc.json ./src", "typecheck": "tsc --watch --noEmit" }, "devDependencies": { @@ -24,7 +23,6 @@ "eslint": "^8.49.0", "html-webpack-plugin": "^5.5.3", "mini-svg-data-uri": "^1.4.4", - "prettier": "^3.0.3", "webpack": "^5.88.2", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1", diff --git a/src/frontend/index.ts b/src/frontend/index.ts index 75349ca..c3cc4a2 100644 --- a/src/frontend/index.ts +++ b/src/frontend/index.ts @@ -23,7 +23,7 @@ type MothDispatched = MothDispatchedAllocate | MothDispatchedLoad; * Get all extensions. * @returns Extensions. */ -function getExtensionInfo() { +function getExtensionInfo () { const processedExtInfo: MothExtensionInfo[] = []; for (const [extId, ext] of window.chibi.loader.loadedScratchExtension.entries()) { processedExtInfo.push({ @@ -37,7 +37,7 @@ function getExtensionInfo() { * Handle messages from the frontend (popup window). * @param event Event from the frontend. */ -async function messageHandler(event: MessageEvent) { +async function messageHandler (event: MessageEvent) { if (event.origin !== 'https://chibi.codingclip.cc') return; if (!('type' in event.data)) return; switch ((event.data as MothDispatched).type) { @@ -86,7 +86,7 @@ window.addEventListener('message', messageHandler); * Open the popup (?) window. * @param open window.open function (compatible with ccw). */ -function openFrontend(open: typeof window.open) { +function openFrontend (open: typeof window.open) { dashboardWindow = open( 'https://chibi.codingclip.cc/#manage', 'Chibi', diff --git a/src/injector/inject.ts b/src/injector/inject.ts index 2302879..15fc6d4 100644 --- a/src/injector/inject.ts +++ b/src/injector/inject.ts @@ -32,9 +32,9 @@ const MAX_LISTENING_MS = 30 * 1000; * @param vm Virtual machine instance. For some reasons we cannot use VM here. * @returns Blockly instance. */ -function getBlocklyInstance(vm: any): any | undefined { - // hijack Function.prototype.apply to get React element instance. - function hijack(fn: (...args: unknown[]) => void): any { +function getBlocklyInstance (vm: any): any | undefined { + // Hijack Function.prototype.apply to get React element instance. + function hijack (fn: (...args: unknown[]) => void): any { const _orig = Function.prototype.apply; Function.prototype.apply = function (thisArg: any) { return thisArg; @@ -46,11 +46,11 @@ function getBlocklyInstance(vm: any): any | undefined { const events = vm._events?.EXTENSION_ADDED; if (events) { if (events instanceof Function) { - // it is a function, just hijack it. + // It is a function, just hijack it. const result = hijack(events); if (result && result.ScratchBlocks) return result.ScratchBlocks; } else { - // it is an array, hijack every listeners. + // It is an array, hijack every listeners. for (const value of events) { const result = hijack(value); if (result && result.ScratchBlocks) return result.ScratchBlocks; @@ -65,7 +65,7 @@ function getBlocklyInstance(vm: any): any | undefined { * @param open window.open function (compatible with ccw). * @return Callback promise. After that you could use window.chibi.vm to get the virtual machine. */ -export function trap(open: typeof window.open): Promise { +export function trap (open: typeof window.open): Promise { window.chibi = { // @ts-expect-error defined in webpack define plugin version: __CHIBI_VERSION__, @@ -106,11 +106,11 @@ export function trap(open: typeof window.open): Promise { * Inject into the original virtual machine. * @param vm {ChibiCompatibleVM} Original virtual machine instance. */ -export function inject(vm: ChibiCompatibleVM) { +export function inject (vm: ChibiCompatibleVM) { const loader = (window.chibi.loader = new ChibiLoader(vm)); const originalLoadFunc = vm.extensionManager.loadExtensionURL; const getLocale = vm.getLocale; - let format = formatMessage.namespace(); + const format = formatMessage.namespace(); format.setup({ locale: getLocale ? getLocale.call(vm) : 'en', missingTranslation: 'ignore', @@ -126,26 +126,26 @@ export function inject(vm: ChibiCompatibleVM) { try { const res = env ? confirm( - format('chibi.tryLoadInEnv', { - extensionURL, - url, - env - }) - ) + format('chibi.tryLoadInEnv', { + extensionURL, + url, + env + }) + ) : confirm( - format('chibi.tryLoadInEnv', { - extensionURL, - url - }) - ); + format('chibi.tryLoadInEnv', { + extensionURL, + url + }) + ); if (res) { await loader.load( url, (env ? env : confirm(format('chibi.loadInSandbox')) - ? 'sandboxed' - : 'unsandboxed') as 'unsandboxed' | 'sandboxed' + ? 'sandboxed' + : 'unsandboxed') as 'unsandboxed' | 'sandboxed' ); const extensionId = loader.getIdByUrl(url); // @ts-expect-error internal hack @@ -214,8 +214,8 @@ export function inject(vm: ChibiCompatibleVM) { return result; }; // TODO: compiler support - const originalArgReporterBooleanFunc = vm.runtime._primitives['argument_reporter_boolean']; - vm.runtime._primitives['argument_reporter_boolean'] = function ( + const originalArgReporterBooleanFunc = vm.runtime._primitives.argument_reporter_boolean; + vm.runtime._primitives.argument_reporter_boolean = function ( args: Record, ...otherArgs: unknown[] ) { @@ -256,7 +256,7 @@ export function inject(vm: ChibiCompatibleVM) { // Blockly stuffs setTimeout(() => { const blockly = (window.chibi.blockly = getBlocklyInstance(vm)); - // deprecated: this method will be removed in the future. + // Deprecated: this method will be removed in the future. if (!blockly) { warn('Cannot find real blockly instance, try alternative method...'); const originalProcedureCallback = diff --git a/src/loader/dispatch/central-dispatch.ts b/src/loader/dispatch/central-dispatch.ts index db3b74b..051575e 100644 --- a/src/loader/dispatch/central-dispatch.ts +++ b/src/loader/dispatch/central-dispatch.ts @@ -19,7 +19,7 @@ class _CentralDispatch extends SharedDispatch { */ workers: Worker[] = []; _onMessage!: (worker: Worker, event: MessageEvent) => void; - constructor() { + constructor () { super(); /** * Map of channel name to worker or local service provider. @@ -38,7 +38,7 @@ class _CentralDispatch extends SharedDispatch { * @param {*} [args] - the arguments to be copied to the method, if any. * @returns {*} - the return value of the service method. */ - callSync(service: string, method: string, ...args: unknown[]) { + callSync (service: string, method: string, ...args: unknown[]) { const { provider, isRemote } = this._getServiceProvider(service); if (provider) { if (isRemote) { @@ -54,7 +54,7 @@ class _CentralDispatch extends SharedDispatch { * @param {string} service - a globally unique string identifying this service. Examples: 'vm', 'gui', 'extension9'. * @param {object} provider - a local object which provides this service. */ - setServiceSync(service: string, provider: any) { + setServiceSync (service: string, provider: any) { if (this.services.hasOwnProperty(service)) { console.warn(`Central dispatch replacing existing service provider for ${service}`); } @@ -67,7 +67,7 @@ class _CentralDispatch extends SharedDispatch { * @param {object} provider - a local object which provides this service. * @returns {Promise} - a promise which will resolve once the service is registered. */ - setService(service: string, provider: any) { + setService (service: string, provider: any) { /** Return a promise for consistency with {@link WorkerDispatch#setService} */ try { this.setServiceSync(service, provider); @@ -81,7 +81,7 @@ class _CentralDispatch extends SharedDispatch { * The dispatcher will immediately attempt to "handshake" with the worker. * @param {Worker} worker - the worker to add into the dispatch system. */ - addWorker(worker: Worker) { + addWorker (worker: Worker) { if (this.workers.indexOf(worker) === -1) { this.workers.push(worker); worker.onmessage = this._onMessage.bind(this, worker); @@ -99,7 +99,7 @@ class _CentralDispatch extends SharedDispatch { * @returns {{provider:(object|Worker), isRemote:boolean}} - the means to contact the service, if found * @protected */ - _getServiceProvider(service: string) { + _getServiceProvider (service: string) { const provider = this.services[service]; return ( provider && { @@ -118,7 +118,7 @@ class _CentralDispatch extends SharedDispatch { * @returns {Promise|undefined} - a promise for the results of this operation, if appropriate * @protected */ - _onDispatchMessage(worker: Worker, message: DispatchCallMessage) { + _onDispatchMessage (worker: Worker, message: DispatchCallMessage) { let promise; switch (message.method) { case 'setService': diff --git a/src/loader/dispatch/shared-dispatch.ts b/src/loader/dispatch/shared-dispatch.ts index 305734f..5527b84 100644 --- a/src/loader/dispatch/shared-dispatch.ts +++ b/src/loader/dispatch/shared-dispatch.ts @@ -73,7 +73,7 @@ class SharedDispatch { * @param {*} [args] - the arguments to be copied to the method, if any. * @returns {Promise} - a promise for the return value of the service method. */ - call(service: string, method: string, ...args: unknown[]) { + call (service: string, method: string, ...args: unknown[]) { return this.transferCall(service, method, null, ...args); } /** @@ -91,7 +91,7 @@ class SharedDispatch { * @param {*} [args] - the arguments to be copied to the method, if any. * @returns {Promise} - a promise for the return value of the service method. */ - transferCall(service: string, method: string, transfer: unknown, ...args: unknown[]) { + transferCall (service: string, method: string, transfer: unknown, ...args: unknown[]) { try { // @ts-expect-error TS(2339): It's not implemented. const { provider, isRemote } = this._getServiceProvider(service); @@ -113,7 +113,7 @@ class SharedDispatch { * @returns {boolean} - true if the service is remote (calls must cross a Worker boundary), false otherwise. * @private */ - _isRemoteService(service: string): boolean { + _isRemoteService (service: string): boolean { // @ts-expect-error TS(2339): It's not implemented. return this._getServiceProvider(service).isRemote; } @@ -125,7 +125,7 @@ class SharedDispatch { * @param {*} [args] - the arguments to be copied to the method, if any. * @returns {Promise} - a promise for the return value of the service method. */ - _remoteCall( + _remoteCall ( provider: any, service: string, method: string, @@ -142,7 +142,7 @@ class SharedDispatch { * @param {*} [args] - the arguments to be copied to the method, if any. * @returns {Promise} - a promise for the return value of the service method. */ - _remoteTransferCall( + _remoteTransferCall ( provider: Worker, service: string, method: string, @@ -168,7 +168,7 @@ class SharedDispatch { * @returns {*} - a unique response ID for this set of callbacks. See {@link _deliverResponse}. * @protected */ - _storeCallbacks(resolve: (value: unknown) => void, reject: (value: unknown) => void) { + _storeCallbacks (resolve: (value: unknown) => void, reject: (value: unknown) => void) { const responseId = this.nextResponseId++; this.callbacks[responseId] = [resolve, reject]; return responseId; @@ -179,7 +179,7 @@ class SharedDispatch { * @param {DispatchResponseMessage} message - the message containing the response value(s). * @protected */ - _deliverResponse(responseId: number, message: DispatchResponseMessage) { + _deliverResponse (responseId: number, message: DispatchResponseMessage) { try { const [resolve, reject] = this.callbacks[responseId]; delete this.callbacks[responseId]; @@ -198,7 +198,7 @@ class SharedDispatch { * @param {MessageEvent} event - the message event to be handled. * @protected */ - _onMessage(worker: Worker, event: MessageEvent) { + _onMessage (worker: Worker, event: MessageEvent) { /** @type {DispatchMessage} */ const message = event.data; message.args = message.args || []; @@ -244,7 +244,7 @@ class SharedDispatch { * @returns {{provider:(object|Worker), isRemote:boolean}} - the means to contact the service, if found * @protected */ - _getServiceProvider(service: string) { + _getServiceProvider (service: string) { throw new Error( `Could not get provider for ${service}: _getServiceProvider not implemented` ); @@ -257,7 +257,7 @@ class SharedDispatch { * @returns {Promise|undefined} - a promise for the results of this operation, if appropriate * @private */ - _onDispatchMessage(worker: Worker, message: DispatchCallMessage) { + _onDispatchMessage (worker: Worker, message: DispatchCallMessage) { throw new Error( `Unimplemented dispatch message handler cannot handle ${message.method} method` ); @@ -268,7 +268,7 @@ class SharedDispatch { * @param {obj} object - The Object that need to be purified. * @returns {object} - purified object. */ - _purifyObject(obj: unknown, visited = new Set(), depth = 1): unknown { + _purifyObject (obj: unknown, visited = new Set(), depth = 1): unknown { if (typeof obj === 'function' || typeof obj === 'symbol') { return undefined; } diff --git a/src/loader/dispatch/worker-dispatch.ts b/src/loader/dispatch/worker-dispatch.ts index a246a95..e6b3b72 100644 --- a/src/loader/dispatch/worker-dispatch.ts +++ b/src/loader/dispatch/worker-dispatch.ts @@ -26,7 +26,7 @@ class _WorkerDispatch extends SharedDispatch { _onConnect!: (value?: unknown) => void; // @ts-expect-error _onMessage!: (worker: window & globalThis, event: MessageEvent) => void; - constructor() { + constructor () { super(); this._connectionPromise = new Promise((resolve) => { @@ -48,7 +48,7 @@ class _WorkerDispatch extends SharedDispatch { * dispatch.call('myService', 'hello'); * }) */ - get waitForConnection() { + get waitForConnection () { return this._connectionPromise; } @@ -59,7 +59,7 @@ class _WorkerDispatch extends SharedDispatch { * @param {object} provider - a local object which provides this service. * @returns {Promise} - a promise which will resolve once the service is registered. */ - setService(service: string, provider: unknown) { + setService (service: string, provider: unknown) { if (this.services.hasOwnProperty(service)) { console.warn(`Worker dispatch replacing existing service provider for ${service}`); } @@ -76,7 +76,7 @@ class _WorkerDispatch extends SharedDispatch { * @returns {{provider:(object|Worker), isRemote:boolean}} - the means to contact the service, if found * @protected */ - _getServiceProvider(service: string) { + _getServiceProvider (service: string) { // If we don't have a local service by this name, contact central dispatch by calling `postMessage` on self const provider = this.services[service]; return { @@ -93,7 +93,7 @@ class _WorkerDispatch extends SharedDispatch { * @returns {Promise|undefined} - a promise for the results of this operation, if appropriate * @protected */ - _onDispatchMessage(worker: Worker, message: DispatchCallMessage) { + _onDispatchMessage (worker: Worker, message: DispatchCallMessage) { let promise; switch (message.method) { case 'handshake': diff --git a/src/loader/loader.ts b/src/loader/loader.ts index f9c2ed1..b188d55 100644 --- a/src/loader/loader.ts +++ b/src/loader/loader.ts @@ -69,7 +69,7 @@ class ChibiLoader { */ loadedScratchExtension = new Map(); - constructor(vm: VM) { + constructor (vm: VM) { this.vm = vm; this.inlinedCtx = typeof window.Scratch === 'object'; if (!this.inlinedCtx) { @@ -89,7 +89,7 @@ class ChibiLoader { * @param {ExtensionClass | string} ext - Extension's data. * @param {'sandboxed' | 'unsandboxed'} env - Extension's running environment. */ - async load(ext: string | ExtensionClass, env: 'sandboxed' | 'unsandboxed' = 'sandboxed') { + async load (ext: string | ExtensionClass, env: 'sandboxed' | 'unsandboxed' = 'sandboxed') { if (typeof ext === 'string') { switch (env) { case 'sandboxed': @@ -131,7 +131,7 @@ class ChibiLoader { * Reload a scratch-standard extension. * @param {string} extensionId - Extension's ID */ - async reload(extensionId: string) { + async reload (extensionId: string) { const targetExt = this.loadedScratchExtension.get(extensionId); if (!targetExt) { throw new Error(`Cannot locate extension ${extensionId}.`); @@ -154,7 +154,7 @@ class ChibiLoader { /** * Get all sideloaded extension infos. */ - getLoadedInfo() { + getLoadedInfo () { const extensionURLs: Record = {}; const extensionEnv: Record = {}; for (const [extId, ext] of this.loadedScratchExtension.entries()) { @@ -164,7 +164,7 @@ class ChibiLoader { return [extensionURLs, extensionEnv]; } - getIdByUrl(url: string) { + getIdByUrl (url: string) { for (const [extId, ext] of this.loadedScratchExtension.entries()) { if (ext.url === url) { return extId; @@ -178,7 +178,7 @@ class ChibiLoader { * original extension manager to reload locales. It should * be replaced when there's a better solution. */ - reloadAll() { + reloadAll () { const allPromises: Promise[] = []; for (const [extId] of this.loadedScratchExtension.entries()) { allPromises.push(this.reload(extId)); @@ -193,7 +193,7 @@ class ChibiLoader { * @param {string} serviceName - the name of the service hosting the extension * @private */ - private _registerExtensionInfo( + private _registerExtensionInfo ( extensionObject: ExtensionClass | null, extensionInfo: ExtensionMetadata, extensionURL: string, @@ -225,7 +225,7 @@ class ChibiLoader { * @returns {string} - the sanitized text * @private */ - private _sanitizeID(text: string) { + private _sanitizeID (text: string) { return text.toString().replace(/[<"&]/, '_'); } @@ -238,7 +238,7 @@ class ChibiLoader { * @returns {ExtensionInfo} - a new extension info object with cleaned-up values * @private */ - private _prepareExtensionInfo( + private _prepareExtensionInfo ( extensionObject: ExtensionClass | null, extensionInfo: ExtensionMetadata, serviceName?: string @@ -296,7 +296,7 @@ class ChibiLoader { * @returns {Array.} - a menuInfo object with all preprocessing done. * @private */ - private _prepareMenuInfo( + private _prepareMenuInfo ( extensionObject: ExtensionClass | null, menus: Record, serviceName?: string @@ -343,7 +343,7 @@ class ChibiLoader { * @returns {Array} menu items ready for scratch-blocks. * @private */ - private _getExtensionMenuItems( + private _getExtensionMenuItems ( extensionObject: ExtensionClass, menuItemFunctionName: string, serviceName?: string @@ -389,7 +389,7 @@ class ChibiLoader { * @returns {ExtensionBlockMetadata} - a new block info object which has values for all relevant optional fields. * @private */ - private _prepareBlockInfo( + private _prepareBlockInfo ( extensionObject: ExtensionClass | null, blockInfo: ExtensionBlockMetadata, serviceName?: string @@ -474,7 +474,7 @@ class ChibiLoader { return blockInfo; } - async updateLocales() { + async updateLocales () { await this.reloadAll(); } @@ -482,11 +482,11 @@ class ChibiLoader { * Regenerate blockinfo for any loaded extensions * @returns {Promise} resolved once all the extensions have been reinitialized */ - async refreshBlocks() { + async refreshBlocks () { await this.reloadAll(); } - allocateWorker() { + allocateWorker () { const workerInfo = this.pendingExtensions.shift(); if (!workerInfo) { warn('pending extension queue is empty'); @@ -501,7 +501,7 @@ class ChibiLoader { * Collect extension metadata from the specified service and begin the extension registration process. * @param {string} serviceName - the name of the service hosting the extension. */ - async registerExtensionService(extensionURL: string, serviceName: string) { + async registerExtensionService (extensionURL: string, serviceName: string) { const info = await dispatch.call(serviceName, 'getInfo'); this._registerExtensionInfo(null, info, extensionURL, serviceName); } @@ -511,7 +511,7 @@ class ChibiLoader { * @param {int} id - the worker ID. * @param {*?} e - the error encountered during initialization, if any. */ - onWorkerInit(id: number, e?: Error) { + onWorkerInit (id: number, e?: Error) { const workerInfo = this.pendingWorkers[id]; delete this.pendingWorkers[id]; if (e) { diff --git a/src/loader/make-ctx.ts b/src/loader/make-ctx.ts index 298db22..e42cc42 100644 --- a/src/loader/make-ctx.ts +++ b/src/loader/make-ctx.ts @@ -30,7 +30,7 @@ export interface Context { * @param vm Virtual machine instance. Optional. * @returns Something like Scratch.translate. */ -function createTranslate(vm?: VM) { +function createTranslate (vm?: VM) { const namespace = formatMessage.namespace(); const translate = (message: Message, args?: object) => { @@ -84,7 +84,7 @@ function createTranslate(vm?: VM) { * @param vm Virtual machine instance. * @returns The context. */ -export function makeCtx(vm?: VM) { +export function makeCtx (vm?: VM) { const ctx: Context = { ArgumentType: ArgumentType, BlockType: BlockType, diff --git a/src/loader/sandbox.worker.ts b/src/loader/sandbox.worker.ts index d1a7378..1dbcedf 100644 --- a/src/loader/sandbox.worker.ts +++ b/src/loader/sandbox.worker.ts @@ -15,7 +15,7 @@ class ExtensionWorker { extensions: unknown[] = []; workerId?: number; extensionURL = ''; - constructor() { + constructor () { dispatch.waitForConnection.then(() => { dispatch.call('loader', 'allocateWorker').then((x) => { const [id, url] = x; @@ -40,7 +40,7 @@ class ExtensionWorker { this.extensions = []; } - register(extensionObject: unknown) { + register (extensionObject: unknown) { const extensionId = this.nextExtensionId++; this.extensions.push(extensionObject); const serviceName = `extension.${this.workerId}.${extensionId}`; diff --git a/src/util/cast.ts b/src/util/cast.ts index c91141f..6dd3545 100644 --- a/src/util/cast.ts +++ b/src/util/cast.ts @@ -44,7 +44,7 @@ class Cast { * @param {*} value Value to cast to number. * @return {number} The Scratch-casted number value. */ - static toNumber(value: unknown): number { + static toNumber (value: unknown): number { /* * If value is already a number we don't need to coerce it with * Number(). @@ -77,7 +77,7 @@ class Cast { * @param {*} value Value to cast to boolean. * @return {boolean} The Scratch-casted boolean value. */ - static toBoolean(value: unknown): boolean { + static toBoolean (value: unknown): boolean { // Already a boolean? if (typeof value === 'boolean') { return value; @@ -99,7 +99,7 @@ class Cast { * @param {*} value Value to cast to string. * @return {string} The Scratch-casted string value. */ - static toString(value: unknown) { + static toString (value: unknown) { return String(value); } @@ -108,7 +108,7 @@ class Cast { * @param {*} value Value to convert to RGB color array. * @return {Array.} [r,g,b], values between 0-255. */ - static toRgbColorList(value: unknown): [number, number, number] { + static toRgbColorList (value: unknown): [number, number, number] { const color = Cast.toRgbColorObject(value); return [color.r, color.g, color.b]; } @@ -118,7 +118,7 @@ class Cast { * @param {*} value Value to convert to RGB color object. * @return {RGBObject} [r,g,b], values between 0-255. */ - static toRgbColorObject(value: unknown): RGBObject { + static toRgbColorObject (value: unknown): RGBObject { let color; if (typeof value === 'string' && value.substring(0, 1) === '#') { color = Color.hexToRgb(value); @@ -136,7 +136,7 @@ class Cast { * @param {*} val value to check. * @return {boolean} True if the argument is all white spaces or null / empty. */ - static isWhiteSpace(val: unknown) { + static isWhiteSpace (val: unknown) { return val === null || (typeof val === 'string' && val.trim().length === 0); } @@ -147,7 +147,7 @@ class Cast { * @param {*} v2 Second value to compare. * @returns {number} Negative number if v1 < v2; 0 if equal; positive otherwise. */ - static compare(v1: unknown, v2: unknown): number { + static compare (v1: unknown, v2: unknown): number { let n1 = Number(v1); let n2 = Number(v2); if (n1 === 0 && isNotActuallyZero(v1)) { @@ -182,7 +182,7 @@ class Cast { * @param {*} val Value to check. * @return {boolean} True if number looks like an integer. */ - static isInt(val: unknown): boolean { + static isInt (val: unknown): boolean { // Values that are already numbers. if (typeof val === 'number') { if (isNaN(val)) { @@ -201,11 +201,11 @@ class Cast { return false; } - static get LIST_INVALID() { + static get LIST_INVALID () { return 'INVALID'; } - static get LIST_ALL() { + static get LIST_ALL () { return 'ALL'; } @@ -219,7 +219,7 @@ class Cast { * @param {boolean} acceptAll Whether it should accept "all" or not. * @return {(number|string)} 1-based index for list, LIST_ALL, or LIST_INVALID. */ - static toListIndex(index: ListIndex, length: number, acceptAll: boolean) { + static toListIndex (index: ListIndex, length: number, acceptAll: boolean) { if (typeof index !== 'number') { if (index === 'all') { return acceptAll ? Cast.LIST_ALL : Cast.LIST_INVALID; diff --git a/src/util/color.ts b/src/util/color.ts index 3ca1df8..b577f71 100644 --- a/src/util/color.ts +++ b/src/util/color.ts @@ -26,12 +26,12 @@ class Color { */ /** @type {RGBObject} */ - static get RGB_BLACK() { + static get RGB_BLACK () { return { r: 0, g: 0, b: 0 }; } /** @type {RGBObject} */ - static get RGB_WHITE() { + static get RGB_WHITE () { return { r: 255, g: 255, b: 255 }; } @@ -40,7 +40,7 @@ class Color { * @param {number} decimal RGB color as a decimal. * @return {string} RGB color as #RRGGBB hex string. */ - static decimalToHex(decimal: number) { + static decimalToHex (decimal: number) { if (decimal < 0) { decimal += 0xffffff + 1; } @@ -54,7 +54,7 @@ class Color { * @param {number} decimal RGB color as decimal. * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. */ - static decimalToRgb(decimal: number) { + static decimalToRgb (decimal: number) { const a = (decimal >> 24) & 0xff; const r = (decimal >> 16) & 0xff; const g = (decimal >> 8) & 0xff; @@ -67,7 +67,7 @@ class Color { * @param {!string} hex Hex representation of the color. * @return {RGBObject | null} null on failure, or rgb: {r: red [0,255], g: green [0,255], b: blue [0,255]}. */ - static hexToRgb(hex: string): RGBObject | null { + static hexToRgb (hex: string): RGBObject | null { if (hex.startsWith('#')) { hex = hex.substring(1); } @@ -99,7 +99,7 @@ class Color { * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. * @return {!string} Hex representation of the color. */ - static rgbToHex(rgb: RGBObject) { + static rgbToHex (rgb: RGBObject) { return Color.decimalToHex(Color.rgbToDecimal(rgb)); } @@ -108,7 +108,7 @@ class Color { * @param {RGBObject | null} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. * @return {!number} Number representing the color. */ - static rgbToDecimal(rgb: RGBObject | null) { + static rgbToDecimal (rgb: RGBObject | null) { if (rgb === null) throw new Error('rgb must be an RGBObject'); return (rgb.r << 16) + (rgb.g << 8) + rgb.b; } @@ -118,7 +118,7 @@ class Color { * @param {!string} hex Hex representation of the color. * @return {!number} Number representing the color. */ - static hexToDecimal(hex: string) { + static hexToDecimal (hex: string) { return Color.rgbToDecimal(Color.hexToRgb(hex)); } @@ -127,7 +127,7 @@ class Color { * @param {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]} * @return {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. */ - static hsvToRgb(hsv: HSVObject) { + static hsvToRgb (hsv: HSVObject) { let h = hsv.h % 360; if (h < 0) h += 360; const s = Math.max(0, Math.min(hsv.s, 1)); @@ -189,7 +189,7 @@ class Color { * @param {RGBObject} rgb - {r: red [0,255], g: green [0,255], b: blue [0,255]}. * @return {HSVObject} hsv - {h: hue [0,360), s: saturation [0,1], v: value [0,1]} */ - static rgbToHsv(rgb: RGBObject) { + static rgbToHsv (rgb: RGBObject) { const r = rgb.r / 255; const g = rgb.g / 255; const b = rgb.b / 255; @@ -216,7 +216,7 @@ class Color { * @param {number} fraction1 - the interpolation parameter. If this is 0.5, for example, mix the two colors equally. * @return {RGBObject} the interpolated color. */ - static mixRgb(rgb0: RGBObject, rgb1: RGBObject, fraction1: number) { + static mixRgb (rgb0: RGBObject, rgb1: RGBObject, fraction1: number) { if (fraction1 <= 0) return rgb0; if (fraction1 >= 1) return rgb1; const fraction0 = 1 - fraction1; diff --git a/src/util/log.ts b/src/util/log.ts index 99f4c79..887e512 100644 --- a/src/util/log.ts +++ b/src/util/log.ts @@ -2,7 +2,7 @@ * Output general messages. * @param params The message. */ -export function log(...params: unknown[]) { +export function log (...params: unknown[]) { console.log( '%c😎 Chibi', ` background-color: #f7c7bb; border-radius: 1rem; margin-right: 0.25rem; padding: 0 0.5rem; color: #271919;`, @@ -13,7 +13,7 @@ export function log(...params: unknown[]) { * Output warning messages. * @param params The message. */ -export function warn(...params: unknown[]) { +export function warn (...params: unknown[]) { console.warn( '%c😨 Chibi', ` background-color: #f7c7bb; border-radius: 1rem; margin-right: 0.25rem; padding: 0 0.5rem; color: #271919;`, @@ -24,7 +24,7 @@ export function warn(...params: unknown[]) { * Output error (exception) messages. * @param params The message. */ -export function error(...params: unknown[]) { +export function error (...params: unknown[]) { console.error( '%c😵 Chibi', ` background-color: #f7c7bb; border-radius: 1rem; margin-right: 0.25rem; padding: 0 0.5rem; color: #271919;`, diff --git a/src/util/settings.ts b/src/util/settings.ts new file mode 100644 index 0000000..4fe5c1f --- /dev/null +++ b/src/util/settings.ts @@ -0,0 +1,61 @@ +export interface Settings { + convertProcCall: boolean; + dontExposeCtx: boolean; + noConfirmDialog: boolean; + takeOverUrlLoadRequest: boolean; +} + +const puppet: Settings = { + convertProcCall: true, + dontExposeCtx: false, + noConfirmDialog: false, + takeOverUrlLoadRequest: false +}; + +const SETTINGS_KEY = '$CHIBI_SETTINGS'; + +if (!window.localStorage.getItem(SETTINGS_KEY)) { + window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(puppet)); +} + +function getSettingsFromStorage () { + try { + const item = window.localStorage.getItem(SETTINGS_KEY); + if (!item) return null; + return JSON.parse(item); + } catch (_: unknown) { + return null; + } +} + +function saveSettingsToStorage (prop: string, value: string) { + try { + const item = window.localStorage.getItem(SETTINGS_KEY); + if (!item) throw 'missing item'; + const obj = JSON.parse(item); + obj[prop] = value; + window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(obj)); + } catch (_: unknown) { + const newObject = Object.assign({}, puppet, { + [prop]: value + }); + window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(newObject)); + } +} + +export const settings = new Proxy(puppet, { + get (target, prop) { + const storage = getSettingsFromStorage(); + if (!storage || !(prop in storage)) return target[prop as keyof Settings]; + return storage[prop]; + }, + set (target, prop, value) { + let storage = getSettingsFromStorage(); + if (!storage) { + storage = Object.assign({}, puppet); + } + storage[prop] = value; + window.localStorage.setItem(SETTINGS_KEY, JSON.stringify(storage)); + return true; + } +}); diff --git a/yarn.lock b/yarn.lock index b0be598..7b84378 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3454,11 +3454,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" - integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== - pretty-error@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6"