From 04f08a9952284638f5c699aebbfc695f8dd5fb4e Mon Sep 17 00:00:00 2001 From: Isaac Wolkerstorfer Date: Thu, 26 Oct 2017 16:45:17 +0200 Subject: [PATCH] Add typedefs for grasp (graspjs.com) (#21007) * Add typedefs for grasp (graspjs.com) * Add package.json to specify dependencies * Incorporate PR feedback --- types/grasp/grasp-tests.ts | 50 ++++++++++++++++++++++++++ types/grasp/index.d.ts | 72 ++++++++++++++++++++++++++++++++++++++ types/grasp/tsconfig.json | 16 +++++++++ types/grasp/tslint.json | 1 + 4 files changed, 139 insertions(+) create mode 100644 types/grasp/grasp-tests.ts create mode 100644 types/grasp/index.d.ts create mode 100644 types/grasp/tsconfig.json create mode 100644 types/grasp/tslint.json diff --git a/types/grasp/grasp-tests.ts b/types/grasp/grasp-tests.ts new file mode 100644 index 0000000000..647f57d8fd --- /dev/null +++ b/types/grasp/grasp-tests.ts @@ -0,0 +1,50 @@ +import fs = require("fs"); +import * as grasp from "grasp"; + +grasp(); // $ExpectError +grasp({ args: [] }); // $ExpectType void + +// $ExpectType void +grasp({ + args: [], + error: console.error, + callback: console.log, + exit: process.exit, + console, + stdin: process.stdin, + fs, + input: "foo bar" +}); + +// $ExpectError +grasp({ + args: [], + textFormat: { cyan: "cyan" } +}); + +// $ExpectType string +grasp.VERSION; + +const fooquery = grasp.search("fooquery"); // $ExpectError +const equery = grasp.search("equery"); +const squery = grasp.search("squery"); + +// $ExpectType Node[] +grasp.search("equery", "pattern", "input"); + +// $ExpectType Node[] +equery("pattern")("input"); + +// $ExpectType (input: string) => Node[] +squery("pattern"); + +const replacer = grasp.replace("equery", "pattern"); + +// $ExpectType string +replacer("replacement", "input"); + +// $ExpectType string +replacer((getRaw, node, query, named) => { + getRaw(node); // $ExpectType string + return "foo"; +}, "input"); diff --git a/types/grasp/index.d.ts b/types/grasp/index.d.ts new file mode 100644 index 0000000000..bafaac5fdb --- /dev/null +++ b/types/grasp/index.d.ts @@ -0,0 +1,72 @@ +// Type definitions for grasp 0.6 +// Project: http://graspjs.com +// Definitions by: Isaac Wolkerstorfer +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.1 + +/// + +import * as fs from "fs"; +import * as cliColor from "cli-color"; +// Though Grasp does not use esprima, the parser it uses (flow-parser) has a compatible Node type and existing typedefs +import { Node } from "estree"; + +export = grasp; + +declare function grasp(options: { + args: string[] | Record | string; + error?: (message: string) => void; + callback?: (result: string) => void; + exit?: (code: number) => void; + input?: string; + + // The following are "overrides" for defaults, such as console, cli-color, + // process.stdin, or fs. In most cases grasp only makes use of a small + // surface area of the types, but I think if someone really wants to pass a + // fake fs that only implements the subset of methods they think grasp uses, + // it should be up to them to use a cast rather than the typedef to be + // overly lenient. We never know if grasp might change their internal use of + // fs, after all. + fs?: typeof fs; + console?: typeof console; + textFormat?: typeof cliColor; + stdin?: typeof process.stdin; +}): void; + +declare namespace grasp { + const VERSION: string; + + // Both the search and replace functions are curryable, which leads to quite + // a bit of noise. Using generic currying will discard variable name + // information, so we hand-roll it here + + function search(engine: QueryEngineType, selector: string, input: string): Node[]; + function search(engine: QueryEngineType, selector: string): (input: string) => Node[]; + function search(engine: QueryEngineType): GraspSearchWithQueryEngine; + + function replace(engine: QueryEngineType, selector: string, replacement: Replacement, input: string): string; + function replace(engine: QueryEngineType, selector: string, replacement: Replacement): (input: string) => string; + function replace(engine: QueryEngineType, selector: string): GraspReplaceWithSelector; + function replace(engine: QueryEngineType): GraspReplaceWithQueryEngine; + + type QueryEngineType = "squery" | "equery"; + + type Replacement = + | string + | (( + getRaw: (node: Node) => string, + node: Node, + query: (q: string) => Node[], + named: { [key: string]: string | Node } + ) => string); + + type GraspSearchWithQueryEngine = ((selector: string, input: string) => Node[]) & + ((selector: string) => (input: string) => Node[]); + + type GraspReplaceWithQueryEngine = ((selector: string) => GraspReplaceWithSelector) & + ((selector: string, replacement: Replacement) => (input: string) => string) & + ((selector: string, replacement: Replacement, input: string) => string); + + type GraspReplaceWithSelector = ((replacement: Replacement) => (input: string) => string) & + ((replacement: Replacement, input: string) => string); +} diff --git a/types/grasp/tsconfig.json b/types/grasp/tsconfig.json new file mode 100644 index 0000000000..e0996e4408 --- /dev/null +++ b/types/grasp/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": ["es6"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": ["../"], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["index.d.ts", "grasp-tests.ts"] +} diff --git a/types/grasp/tslint.json b/types/grasp/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/grasp/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }