Skip to content

Instantly share code, notes, and snippets.

@YuraKostin
Last active December 21, 2021 12:25
Show Gist options
  • Save YuraKostin/d939117ee7057809d24b2ac68f91b87a to your computer and use it in GitHub Desktop.
Save YuraKostin/d939117ee7057809d24b2ac68f91b87a to your computer and use it in GitHub Desktop.
const fs = require('fs');
const util = require('util');
const glob = require('glob');
// UTILS
// join :: string -> [string] -> string
const join = (glue: string) => (xs: string[]): string => xs.join(glue);
// concatString :: string -> string -> string
const concatString = (a: string) => (b: string): string => a + b;
// mapSecond :: (b -> c) -> [a, b] -> [a, c]
const mapSecond = <A, B, B1>(f: (b: B) => B1) => ([a, b]: [A, B]) => [a, f(b)];
// compose2 :: (b -> c) -> (a -> b) -> a -> c
const compose2 = <A, B, C>(f: (b: B) => C, g: (a: A) => B) => (a: A) => f(g(a));
const pair = <A, B>(a: A) => (b: B): readonly [A, B] => [a, b];
// FUNCTIONS
// readFile :: string -> Promise<string>
const readFile = (path: string) => util.promisify(fs.readFile)(path, 'utf8');
// matchSource :: Promise<string> -> RegExp -> RegExpMatchArray
const matchSource = (source: Promise<string>) => (regExp: RegExp) => {
const matchByRegExp = (r: RegExp) => (s: string) => s.match(r);
return source.then(matchByRegExp(regExp))
};
// count :: Promise<string[] | null> -> Promise<number>
const count = (promise: Promise<string[] | null>): Promise<number> => promise.then(values => (values || []).length);
// message :: Promise<number> -> Promise<string>
const message = ([promise, name]: [Promise<number>, string]) => promise
.then(String)
.then(concatString(`Total ${name}: `));
// rows :: RegExp -> string -> Promise<string[]>
const rows = (pairs: Array<[string, RegExp]>): Promise<string>[] =>
pairs
.map(mapSecond(compose2(count, matchFilesContent)))
.map(message)
// counterReport :: string -> Input -> Promise<string>
const countersReport = (title: string, input: Input): Promise<string> =>
Promise.all(rows(Object.entries(input)))
.then(pair(title))
.then(mapSecond(join('\n')))
.then(join('\n'));
// CONFIGS
const fileExtension = ['/**/*.php','/**/*.tsx','/**/*.vue'];
// INPUT
type ComponentKey
= 'checkbox'
| 'radio'
| 'input'
| 'select'
| 'button'
type Input = Record<ComponentKey, RegExp>;
const htmlInput: Input = {
checkbox: /type="checkbox"/g,
radio: /type="radio"/g,
input: /<input/g,
select: /<select/g,
button: /<button/g,
};
const reactInput: Input = {
checkbox: /<Checkbox/g,
radio: /<Radio/g,
input: /<Input/g,
select: /<Select/g,
button: /<([A-Z][a-z]+)?Button/g,
};
// PROGRAM
const filesList: string[] = glob.sync(`${__dirname}/../..{${fileExtension.join(',')}}`);
const filesContents = Promise.all(filesList.map(readFile)).then(join(''));
const matchFilesContent = matchSource(filesContents);
// RUN
countersReport('HTML', htmlInput).then(console.log);
countersReport('REACT', reactInput).then(console.log);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment