From 817bbd19ca56d07c6737239e4e5648ebc1023914 Mon Sep 17 00:00:00 2001 From: Joe Maddalone <> Date: Sat, 16 Dec 2023 15:52:32 -0600 Subject: [PATCH] feat(types): adds generation of type definition file --- package-lock.json | 78 +++++++++++++++++++ package.json | 3 + rollup.config.js | 9 ++- scripts/makeDefinitions.mjs | 144 ++++++++++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 scripts/makeDefinitions.mjs diff --git a/package-lock.json b/package-lock.json index 4cc206b..0590882 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,8 @@ "@rollup/plugin-commonjs": "^19.0.0", "@rollup/plugin-node-resolve": "^13.0.0", "@testing-library/react": "^11.2.7", + "@types/react": "^18.0.35", + "@types/react-dom": "^18.0.11", "babel-eslint": "10.1.0", "babel-plugin-syntax-dynamic-import": "^6.18.0", "commitizen": "^4.2.4", @@ -4772,12 +4774,38 @@ "integrity": "sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w==", "dev": true }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, "node_modules/@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==", "dev": true }, + "node_modules/@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -4793,6 +4821,12 @@ "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "dev": true }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "dev": true + }, "node_modules/@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -8394,6 +8428,12 @@ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, "node_modules/cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -34298,12 +34338,38 @@ "integrity": "sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w==", "dev": true }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, "@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==", "dev": true }, + "@types/react": { + "version": "18.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.35.tgz", + "integrity": "sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -34319,6 +34385,12 @@ "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "dev": true }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "dev": true + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -37197,6 +37269,12 @@ } } }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", diff --git a/package.json b/package.json index 226a6c4..c79c1a6 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "main": "dist/index.cjs.js", "module": "dist/index.esm.js", "browser": "dist/index.js", + "types": "dist/react-svg-path.d.ts", "engines": { "node": ">=10" }, @@ -43,6 +44,8 @@ "@rollup/plugin-commonjs": "^19.0.0", "@rollup/plugin-node-resolve": "^13.0.0", "@testing-library/react": "^11.2.7", + "@types/react": "^18.0.35", + "@types/react-dom": "^18.0.11", "babel-eslint": "10.1.0", "babel-plugin-syntax-dynamic-import": "^6.18.0", "commitizen": "^4.2.4", diff --git a/rollup.config.js b/rollup.config.js index d523db1..11c2a11 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -2,6 +2,7 @@ import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import babel from '@rollup/plugin-babel'; import { terser } from 'rollup-plugin-terser'; +import makeDefinitions from './scripts/makeDefinitions.mjs'; import pkg from './package.json'; const INPUT_FILE_PATH = 'src/index.js'; @@ -31,7 +32,13 @@ const PLUGINS = [ ] }), commonjs(), - terser() + terser(), + { + name: 'makeDefs', + buildEnd() { + makeDefinitions(); + } + } ]; // https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers diff --git a/scripts/makeDefinitions.mjs b/scripts/makeDefinitions.mjs new file mode 100644 index 0000000..480cd2d --- /dev/null +++ b/scripts/makeDefinitions.mjs @@ -0,0 +1,144 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { basicShapes, curves } from '../src/docs/docs.mjs'; + +const makeDefinitions = () => { + console.log('Generating type definitions...'); + const mapType = (t) => { + switch (t) { + case '2d-array': + return 'any[][]'; + case 'point-array': + return 'number[][]'; + default: + return t; + } + }; + + const definitions = []; + for (const doc in basicShapes) { + const shape = basicShapes[doc]; + const props = shape.props; + definitions.push( + `export interface ${shape.Component}Props extends SVGAttributes {` + ); + for (const prop in props) { + const p = props[prop]; + definitions.push(` ${prop}?: ${mapType(p.type)};`); + } + definitions.push(`}`); + definitions.push(``); + definitions.push( + `export declare const ${shape.Component}: React.FC<${shape.Component}Props>;` + ); + definitions.push(``); + } + + for (const doc in curves) { + const shape = curves[doc]; + const props = shape.props; + definitions.push( + `export interface ${shape.Component}Props extends SVGAttributes {` + ); + for (const prop in props) { + const p = props[prop]; + definitions.push(` ${prop}?: ${mapType(p.type)};`); + } + definitions.push(`}`); + definitions.push(``); + definitions.push( + `export declare const ${shape.Component}: React.FC<${shape.Component}Props>;` + ); + definitions.push(``); + } + + definitions.unshift(`import { SVGAttributes } from "react";`); + + const content = definitions.join('\n'); + + // read the contents of ../node_modules/@joemaddalone/path/dist/path.d.ts + const pathContent = ` + export declare class Path { + pathData: string[]; + attributes: object[]; + static angleInRadians(angle: number): number; + static polarToCartesian(cx: number, cy: number, radius: number, angle: number): any; + static clockwisePoint(cx: number, cy: number, radius: number, angle: number): any; + static radialPoints(radius: number, cx: number, cy: number, numOfPoints: number, offsetAngle: number, vertexSkip?: number): object[]; + static positionByArray(size: number, shape: any[], sx: number, sy: number): object[]; + static macro(name: string, fn: (...params: any[]) => any): (...params: any[]) => any; + static attr(key: string, val: any): void; + fill(val: string | number): Path; + stroke(val: string): Path; + strokeWidth(val: string | number): Path; + style(val: string): Path; + m(x: number, y: number): Path; + M(x: number, y: number): Path; + moveTo(x: number, y: number, relative?: boolean): Path; + l(x: number, y: number): Path; + L(x: number, y: number): Path; + lineTo(x: number, y: number, relative?: boolean): Path; + H(x: number): Path; + h(x: number): Path; + horizontalTo(x: number, relative?: boolean): Path; + V(y: number): Path; + v(y: number): Path; + verticalTo(y: number, relative?: boolean): Path; + Q(cx: number, cy: number, ex: number, ey: number): Path; + q(cx: number, cy: number, ex: number, ey: number): Path; + qCurve(cx: number, cy: number, ex: number, ey: number, relative?: boolean): Path; + T(x: number, y: number): Path; + t(x: number, y: number): Path; + tCurveTo(x: number, y: number, relative?: boolean): Path; + C(cx1: number, cy1: number, cx2: number, cy2: number, ex: number, ey: number): Path; + c(cx1: number, cy1: number, cx2: number, cy2: number, ex: number, ey: number): Path; + cCurve(cx1: number, cy1: number, cx2: number, cy2: number, ex: number, ey: number, relative?: boolean): Path; + S(cx: number, cy: number, ex: number, ey: number): Path; + s(cx: number, cy: number, ex: number, ey: number): Path; + sCurveTo(cx: number, cy: number, ex: number, ey: number, relative?: boolean): Path; + A(rx: number, ry: number, rotation: number, arc: boolean, sweep: boolean, ex: number, ey: number): Path; + a(rx: number, ry: number, rotation: number, arc: boolean, sweep: boolean, ex: number, ey: number): Path; + arc(rx: number, ry: number, rotation: number, arc: boolean, sweep: boolean, ex: number, ey: number, relative?: boolean): Path; + down(px: number): Path; + up(px: number): Path; + right(px: number): Path; + left(px: number): Path; + toArray(): Path; + toArray(): Path; + toString(): string; + toCommands(): any[][]; + toAnnotatedCommands(): object[]; + toElement(attributes?: any): Element; + circle(size: number, cx: number, cy: number, centerEnd?: boolean): Path; + cross(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + ellipse(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + lens(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + omino(size: number, shape: any[], sx: number, sy: number, lined?: boolean): Path; + polygon(points: number[]): Path; + polygram(size: number, points: number[], cx: number, cy: number, vertexSkip?: number, centerEnd?: boolean): Path; + polyline(points: number[], relative?: boolean): Path; + radialLines(outerSize: number, innerSize: number, points: number, cx: number[], cy: number, centerEnd?: boolean): Path; + rect(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + regPolygon(size: number, sides: number, cx: number, cy: number, centerEnd?: boolean): Path; + roundedRect(width: number, height: number, radius: number, cx: number, cy: number, centerEnd?: boolean): Path; + roundedSquare(size: number, radius: number, cx: number, cy: number, centerEnd?: boolean): Path; + sector(cx: number, cy: number, size: number, startAngle: number, endAngle: number, centerEnd?: boolean): Path; + segment(cx: number, cy: number, size: number, startAngle: number, endAngle: number, centerEnd?: boolean): Path; + square(size: number, cx: number, cy: number, centerEnd?: boolean): Path; + star(outerSize: number, innerSize: number, points: number[], cx: number, cy: number, centerEnd?: boolean): Path; + symH(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + symI(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + symX(width: number, height: number, cx: number, cy: number, centerEnd?: boolean): Path; + triangle(size: number, cx: number, cy: number, centerEnd?: boolean): Path; + }`; + + const fileContent = `${content}\n\n${pathContent}`; + // write fileContent to ../src/components/definitions.d.ts + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(__filename); + const filePath = path.join(__dirname, '../dist/react-svg-path.d.ts'); + fs.writeFileSync(filePath, fileContent); +}; + +export default makeDefinitions;