Quick install for HTML-based projects:
npm install --save-dev
webpack \
clean-webpack-plugin \
css-minimizer-webpack-plugin \
html-webpack-plugin \
html-loader
type Digit = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "0"; | |
type EveryOfType<A extends readonly any[], T> = keyof { | |
[P in Exclude<keyof A, keyof any[]> as A[P] extends T ? never : P]: P; | |
} extends never | |
? true | |
: false; | |
type SplitString< | |
T extends string, |
var PropertyLock = (() => { | |
let locked = false; | |
let timeout = 0; | |
const store = PropertiesService.getScriptProperties(); | |
const propertyName = "locked"; | |
const triggerName = "PropertyLock.releaseLock"; |
/** | |
* Promise-friendly google.script.run call | |
* @param {String} funcName | |
* @param {...*} params | |
* @returns {Promise} | |
*/ | |
const asyncGAPI = (funcName, ...params) => { | |
return new Promise((res, rej) => { | |
google.script.run | |
.withSuccessHandler(data => res(data)) |
type Invert<T> = { [ P in keyof T as Extract<T[P], string | number | symbol> ] : P }; | |
type test1 = Invert<{ a: "ia", b: "ib", c: 1 }>; //{ ia: "a"; ib: "b"; 1: "c"; } | |
type DeepPath<T extends string[], U> = T extends [infer F, ...infer L] | |
? F extends string | |
? { [P in F]: L extends string[] ? DeepPath<L,U> : never } | |
: {} | |
: U; |
//@see https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887 | |
type swithcNever<T, A, B> = [T] extends [never] ? A : B; | |
//@see https://stackoverflow.com/a/63568058/11407695 | |
type Flatten<T extends any[]> = T extends [infer U, ...infer R] | |
? U extends any[] | |
? [...Flatten<U>, ...Flatten<R>] | |
: [U, ...Flatten<R>] | |
: []; |
export const remClasses = ( | |
{ classList }: { classList: DOMTokenList }, | |
...classes: string[] | |
) => classList.remove(...classes); | |
export const addClasses = ( | |
{ classList }: { classList: DOMTokenList }, | |
...classes: string[] | |
) => classList.add(...classes); |
/** | |
* @summary extracts values from select | |
* @param {HTMLSelectElement} sel | |
* @return {string[]} | |
*/ | |
const getSelectVals = ({ options }) => | |
Array.from(options).map(({ value }) => value); | |
/** | |
* @summary checks if select has a value |
import { BaseEncodingOptions } from "fs"; | |
import { appendFile, mkdir } from "fs/promises"; | |
import { parse, sep } from "path"; | |
const recursiveAppend = async ( | |
path: string, | |
encoding: BaseEncodingOptions["encoding"] = "utf-8" | |
) => { | |
const parts = path.split(sep); |
Quick install for HTML-based projects:
npm install --save-dev
webpack \
clean-webpack-plugin \
css-minimizer-webpack-plugin \
html-webpack-plugin \
html-loader
/** | |
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics} | |
* @summary measure text width | |
* @param {CanvasRenderingContext2D} ctx drawing context | |
* @returns {number} | |
*/ | |
const measureWidth = (ctx, text) => { | |
const measurement = ctx.measureText(text); | |