If you want to have a general introduction how to write such a codemod have a look at this Gist from me.
Place the usage.js and prettiermod.js in the root of the project. Run:
$ pnpm add globby@^11.0.0 @babel/traverse| // it's like setTimeout as a hook, but with a small twist: | |
| // you can make multiple subsequent calls and can increase or decrease | |
| // the delay (e.g. useful to create polling like functionality) | |
| type Options = { | |
| delay: number; | |
| multiplier?: number; | |
| }; | |
| type State = { |
If you want to have a general introduction how to write such a codemod have a look at this Gist from me.
Place the usage.js and prettiermod.js in the root of the project. Run:
$ pnpm add globby@^11.0.0 @babel/traverseEvery now and then I'd like to apply a so called codemod to my a codebase. A codemod is a piece of code which modifies other code. Very often this is done by running some transformation on the abstract syntax tree (AST).
Whenever I need to do this I look for "What is the best way to apply a codemod on my TS code base right now?", because when I only do this every couple of month I either have forgotten about how to do it or tools have changed and my old way stopped working... or both. Surprisingly every time I search for that I found the existing tools bloated or quirky or not matching my workflow.
As I already use Babel to compile our source code I would like to create a Babel plugin which transforms my code. Sadly Babel alone is not good in preserving whitespace and formatting. Thankfully I use Prettier for that and because Prettier uses Babel internally I can create a Babel visitor to transform my source code.
The actually easiest and _most r
| function getNiceUpperBound(value: number) { | |
| const zeroCount = String(Math.round(value)).length - 1; | |
| const factor = Math.pow(10, zeroCount); | |
| return Math.ceil(value / factor) * factor; | |
| } | |
| const upperBound = getNiceUpperBound(3464634); // 4000000 |
| import { DependencyList, useState, useEffect, useRef } from 'react'; | |
| // use this instead of useMemo of you need a stable value | |
| // see https://twitter.com/0xca0a/status/1314326386555924480 | |
| export function useStableMemo<T>(factory: () => T, deps: DependencyList): T { | |
| const [value, setValue] = useState<T>(factory); | |
| const firstRun = useRef(true); | |
| useEffect( | |
| () => { |
| import { useState, useEffect } from 'react'; | |
| import { useLocation, useHistory } from 'react-router-dom'; | |
| import { useSessionStorage } from './use-storage'; // see https://gist.github.com/donaldpipowitch/7310d7b9e4b6d467134c425e8732adc6 | |
| type UseLocationStateOptions<T> = { | |
| defaultValue?: T; | |
| scope?: string; | |
| filter?: (value: T) => boolean; | |
| }; |
| import React, { FC, useMemo } from 'react'; | |
| import { | |
| LocalStorageProvider, | |
| SessionStorageProvider, | |
| } from './use-storage'; | |
| // this is just a dumb mock of the storage interface | |
| class MemoryStorage implements Storage { | |
| private data: Record<string, string> = {}; |
| // @ts-check | |
| /** @type {import("eslint").Rule.RuleModule} */ | |
| const rule = { | |
| meta: { | |
| docs: { | |
| description: `If you use a Jest test name like "hello (world)" you can't run \`$ jest -t "hello (world)"\` to select this test.`, | |
| }, | |
| fixable: 'code', | |
| }, |
| // @ts-check | |
| /** @type {import("eslint").Rule.RuleModule} */ | |
| const rule = { | |
| meta: { | |
| docs: { | |
| description: `You can export a type and a value with the same name in the same file, but that confuses refactoring tools.`, | |
| }, | |
| }, | |
| create(context) { |
Know your brackets!
( ) – parentheses, round brackets, first brackets
{ } – braces, curly brackets, second brackets, moustache brackets 👨🏻
[ ] – square brackets, third brackets
⟨ ⟩ - angle brackets (aka. _not_ less-than/greater-than signs 👀)
‹ › - angle quotes (aka. _not_ less-than/greater-than signs 👀)
< > - less-than/greater-than signs