diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8720f41b..437f4ec3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,6 +29,7 @@ jobs: ${{ runner.os }}-node-${{ env.NODE }}-${{ hashFiles('package-lock.json') }} - run: npm ci - run: npm run lint + - run: npm run typecheck test: name: Node.js ${{ matrix.node-version }} runs-on: ubuntu-latest diff --git a/lib/css-tools.js b/lib/css-tools.js index 715f696c..ba8708bc 100644 --- a/lib/css-tools.js +++ b/lib/css-tools.js @@ -8,7 +8,7 @@ var csstree = require('css-tree'), /** * Flatten a CSS AST to a selectors list. * - * @param {Object} cssAst css-tree AST to flatten + * @param {import('css-tree').CssNode} cssAst css-tree AST to flatten * @return {Array} selectors */ function flattenToSelectors(cssAst) { @@ -29,7 +29,7 @@ function flattenToSelectors(cssAst) { item: selectorItem, atrule: atrule, rule: rule, - pseudos: [], + pseudos: /** @type {{item: any; list: any[]}[]} */ ([]), }; selectorNode.children.each(function ( @@ -108,7 +108,7 @@ function filterByPseudos(selectors, usePseudos) { * Remove pseudo-elements and/or -classes from the selectors for proper matching. * * @param {Array} selectors to clean - * @return {Array} Selectors without pseudo-elements and/or -classes + * @return {void} */ function cleanPseudos(selectors) { selectors.forEach(function (selector) { @@ -124,7 +124,7 @@ function cleanPseudos(selectors) { * * @param {Array} aSpecificity Specificity of selector A * @param {Array} bSpecificity Specificity of selector B - * @return {Number} Score of selector specificity A compared to selector specificity B + * @return {number} Score of selector specificity A compared to selector specificity B */ function compareSpecificity(aSpecificity, bSpecificity) { for (var i = 0; i < 4; i += 1) { @@ -143,7 +143,7 @@ function compareSpecificity(aSpecificity, bSpecificity) { * * @param {Object} aSimpleSelectorNode Simple selector A * @param {Object} bSimpleSelectorNode Simple selector B - * @return {Number} Score of selector A compared to selector B + * @return {number} Score of selector A compared to selector B */ function compareSimpleSelectorNode(aSimpleSelectorNode, bSimpleSelectorNode) { var aSpecificity = specificity(aSimpleSelectorNode), @@ -168,7 +168,7 @@ function sortSelectors(selectors) { /** * Convert a css-tree AST style declaration to CSSStyleDeclaration property. * - * @param {Object} declaration css-tree style declaration + * @param {import('css-tree').CssNode} declaration css-tree style declaration * @return {Object} CSSStyleDeclaration property */ function csstreeToStyleDeclaration(declaration) { @@ -185,8 +185,8 @@ function csstreeToStyleDeclaration(declaration) { /** * Gets the CSS string of a style element * - * @param {Object} element style element - * @return {String|Array} CSS string or empty array if no styles are set + * @param {Object} elem style element + * @return {string|Array} CSS string or empty array if no styles are set */ function getCssStr(elem) { return elem.content[0].text || elem.content[0].cdata || []; @@ -195,8 +195,8 @@ function getCssStr(elem) { /** * Sets the CSS string of a style element * - * @param {Object} element style element - * @param {String} CSS string to be set + * @param {Object} elem style element + * @param {string} css string to be set * @return {Object} reference to field with CSS */ function setCssStr(elem, css) { diff --git a/lib/svgo/css-style-declaration.js b/lib/svgo/css-style-declaration.js index 6d07952d..3bffcf9c 100644 --- a/lib/svgo/css-style-declaration.js +++ b/lib/svgo/css-style-declaration.js @@ -139,7 +139,7 @@ CSSStyleDeclaration.prototype._loadCssText = function () { /** * Get the textual representation of the declaration block (equivalent to .cssText attribute). * - * @return {String} Textual representation of the declaration block (empty string for no properties) + * @return {string} Textual representation of the declaration block (empty string for no properties) */ CSSStyleDeclaration.prototype.getCssText = function () { var properties = this.getProperties(); @@ -183,8 +183,8 @@ CSSStyleDeclaration.prototype._getProperty = function (propertyName) { /** * Return the optional priority, "important". * - * @param {String} propertyName representing the property name to be checked. - * @return {String} priority that represents the priority (e.g. "important") if one exists. If none exists, returns the empty string. + * @param {string} propertyName representing the property name to be checked. + * @return {string} priority that represents the priority (e.g. "important") if one exists. If none exists, returns the empty string. */ CSSStyleDeclaration.prototype.getPropertyPriority = function (propertyName) { var property = this._getProperty(propertyName); @@ -194,8 +194,8 @@ CSSStyleDeclaration.prototype.getPropertyPriority = function (propertyName) { /** * Return the property value given a property name. * - * @param {String} propertyName representing the property name to be checked. - * @return {String} value containing the value of the property. If not set, returns the empty string. + * @param {string} propertyName representing the property name to be checked. + * @return {string} value containing the value of the property. If not set, returns the empty string. */ CSSStyleDeclaration.prototype.getPropertyValue = function (propertyName) { var property = this._getProperty(propertyName); @@ -205,8 +205,8 @@ CSSStyleDeclaration.prototype.getPropertyValue = function (propertyName) { /** * Return a property name. * - * @param {Number} index of the node to be fetched. The index is zero-based. - * @return {String} propertyName that is the name of the CSS property at the specified index. + * @param {number} index of the node to be fetched. The index is zero-based. + * @return {string} propertyName that is the name of the CSS property at the specified index. */ CSSStyleDeclaration.prototype.item = function (index) { if (typeof index === 'undefined') { @@ -234,8 +234,8 @@ CSSStyleDeclaration.prototype.getProperties = function () { /** * Remove a property from the CSS declaration block. * - * @param {String} propertyName representing the property name to be removed. - * @return {String} oldValue equal to the value of the CSS property before it was removed. + * @param {string} propertyName representing the property name to be removed. + * @return {string} oldValue equal to the value of the CSS property before it was removed. */ CSSStyleDeclaration.prototype.removeProperty = function (propertyName) { if (typeof propertyName === 'undefined') { @@ -255,10 +255,10 @@ CSSStyleDeclaration.prototype.removeProperty = function (propertyName) { /** * Modify an existing CSS property or creates a new CSS property in the declaration block. * - * @param {String} propertyName representing the CSS property name to be modified. - * @param {String} [value] containing the new property value. If not specified, treated as the empty string. value must not contain "!important" -- that should be set using the priority parameter. - * @param {String} [priority] allowing the "important" CSS priority to be set. If not specified, treated as the empty string. - * @return {undefined} + * @param {string} propertyName representing the CSS property name to be modified. + * @param {string} value containing the new property value. If not specified, treated as the empty string. value must not contain "!important" -- that should be set using the priority parameter. + * @param {string} priority allowing the "important" CSS priority to be set. If not specified, treated as the empty string. + * @return {{value: string, priority: string}} */ CSSStyleDeclaration.prototype.setProperty = function ( propertyName, diff --git a/lib/svgo/plugins.js b/lib/svgo/plugins.js index b4b32e06..f99e7fe9 100644 --- a/lib/svgo/plugins.js +++ b/lib/svgo/plugins.js @@ -7,7 +7,7 @@ * * @param {Object} data input data * @param {Object} info extra information - * @param {Object} plugins plugins object from config + * @param {Array} plugins plugins object from config * @return {Object} output data */ module.exports = function (data, info, plugins) { @@ -45,7 +45,7 @@ module.exports = function (data, info, plugins) { * @param {Object} data input data * @param {Object} info extra information * @param {Array} plugins plugins list to process - * @param {Boolean} [reverse] reverse pass? + * @param {boolean} [reverse] reverse pass? * @return {Object} output data */ function perItem(data, info, plugins, reverse) { diff --git a/lib/svgo/tools.js b/lib/svgo/tools.js index ec183209..f52e9c81 100644 --- a/lib/svgo/tools.js +++ b/lib/svgo/tools.js @@ -3,9 +3,9 @@ /** * Encode plain SVG data string into Data URI string. * - * @param {String} str input string - * @param {String} type Data URI type - * @return {String} output string + * @param {string} str input string + * @param {string} type Data URI type + * @return {string} output string */ exports.encodeSVGDatauri = function (str, type) { var prefix = 'data:image/svg+xml'; @@ -27,7 +27,7 @@ exports.encodeSVGDatauri = function (str, type) { * Decode SVG Data URI string into plain SVG string. * * @param {string} str input string - * @return {String} output string + * @return {string} output string */ exports.decodeSVGDatauri = function (str) { var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/; @@ -51,6 +51,10 @@ exports.decodeSVGDatauri = function (str) { return str; }; +/** + * @param {any[]} a + * @param {any[]} b + */ exports.intersectArrays = function (a, b) { return a.filter(function (n) { return b.indexOf(n) > -1; @@ -65,7 +69,7 @@ exports.intersectArrays = function (a, b) { * * @param {number[]} data * @param {Object} params - * @param {string?} command path data instruction + * @param {string} [command] path data instruction * @return {string} */ exports.cleanupOutData = function (data, params, command) { @@ -90,22 +94,22 @@ exports.cleanupOutData = function (data, params, command) { // remove floating-point numbers leading zeros // 0.5 → .5 // -0.5 → -.5 - if (params.leadingZero) { - item = removeLeadingZero(item); - } + const itemStr = params.leadingZero + ? removeLeadingZero(item) + : item.toString(); // no extra space in front of negative number or // in front of a floating number if a previous number is floating too if ( params.negativeExtraSpace && delimiter != '' && - (item < 0 || (String(item).charCodeAt(0) == 46 && prev % 1 !== 0)) + (item < 0 || (itemStr.charCodeAt(0) == 46 && prev % 1 !== 0)) ) { delimiter = ''; } // save prev item value prev = item; - str += delimiter + item; + str += delimiter + itemStr; }); return str; }; @@ -119,9 +123,9 @@ exports.cleanupOutData = function (data, params, command) { * @example * -0.5 → -.5 * - * @param {Float} num input number + * @param {number} num input number * - * @return {String} output number as string + * @return {string} output number as string */ var removeLeadingZero = function (num) { var strNum = num.toString(); diff --git a/package-lock.json b/package-lock.json index cd75a172..16f97769 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2337,6 +2337,12 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, + "typescript": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.2.tgz", + "integrity": "sha512-tbb+NVrLfnsJy3M59lsDgrzWIflR4d4TIUjz+heUnHZwdF7YsrMTKoRERiIvI2lvBG95dfpLxB21WZhys1bgaQ==", + "dev": true + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index ce218867..a1bf522d 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "scripts": { "test": "c8 --reporter=html --reporter=text mocha \"test/*/_index.js\" \"**/*.test.js\" --ignore=\"node_modules/**\"", "lint": "eslint .", + "typecheck": "tsc", "test-browser": "rollup -c && node ./test/browser.js", "prepublishOnly": "rm -rf dist && rollup -c" }, @@ -113,7 +114,8 @@ "mock-stdin": "^1.0.0", "playwright": "^1.8.1", "prettier": "^2.2.1", - "rollup": "^2.39.0" + "rollup": "^2.39.0", + "typescript": "^4.2.2" }, "engines": { "node": ">=10.13.0" diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..72e9c13c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "noEmit": true, + "module": "commonjs", + "target": "es2018", + "lib": ["es2018"], + "allowJs": true, + "checkJs": true, + "strict": true, + "resolveJsonModule": true, + "noImplicitAny": false + }, + "include": [ + "lib/css-tools.js", + "lib/svgo/css-class-list.js", + "lib/svgo/css-select-adapter.js", + "lib/svgo/css-style-declaration.js", + "lib/svgo/plugins.js", + "lib/svgo/tools.js" + ] +}