{"id":13459154,"url":"https://github.com/danielstjules/jsinspect","last_synced_at":"2025-05-14T02:08:09.319Z","repository":{"id":20753439,"uuid":"24037954","full_name":"danielstjules/jsinspect","owner":"danielstjules","description":"Detect copy-pasted and structurally similar code","archived":false,"fork":false,"pushed_at":"2024-03-20T04:23:04.000Z","size":223,"stargazers_count":3580,"open_issues_count":25,"forks_count":128,"subscribers_count":55,"default_branch":"master","last_synced_at":"2025-05-09T10:02:16.808Z","etag":null,"topics":["clean-code","code-analysis","duplication","javascript","refactoring"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danielstjules.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-09-15T01:08:46.000Z","updated_at":"2025-05-07T09:11:39.000Z","dependencies_parsed_at":"2024-01-05T21:06:33.179Z","dependency_job_id":"468eee10-acad-494c-845b-d5dde39f336f","html_url":"https://github.com/danielstjules/jsinspect","commit_stats":{"total_commits":213,"total_committers":13,"mean_commits":"16.384615384615383","dds":0.07511737089201875,"last_synced_commit":"0ef1691fc04934cc4d9dfcaf0e18cc80350ae3a9"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielstjules%2Fjsinspect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielstjules%2Fjsinspect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielstjules%2Fjsinspect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielstjules%2Fjsinspect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danielstjules","download_url":"https://codeload.github.com/danielstjules/jsinspect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254052960,"owners_count":22006717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clean-code","code-analysis","duplication","javascript","refactoring"],"created_at":"2024-07-31T09:01:06.744Z","updated_at":"2025-05-14T02:08:04.298Z","avatar_url":"https://github.com/danielstjules.png","language":"JavaScript","readme":"![jsinspect](http://danielstjules.com/github/jsinspect-logo.png)\n\nDetect copy-pasted and structurally similar JavaScript code. Requires Node.js\n6.0+, and supports ES6, JSX as well as Flow. Note: the project has been mostly\nrewritten for the 0.10 release and saw several breaking changes.\n\n[![Build Status](https://travis-ci.org/danielstjules/jsinspect.svg?branch=master)](https://travis-ci.org/danielstjules/jsinspect)\n\n* [Overview](#overview)\n* [Installation](#installation)\n* [Usage](#usage)\n* [Integration](#integration)\n* [Reporters](#reporters)\n\n## Overview\n\nWe've all had to deal with code smell, and duplicate code is a common source.\nWhile some instances are easy to spot, this type of searching is the perfect\nuse-case for a helpful CLI tool.\n\nExisting solutions do exist for this purpose, but some struggle with code\nthat has wildly varying identifiers or literals, and others have lackluster\nsupport for the JS ecosystem: ES6, JSX, Flow, ignoring module declarations\nand imports, etc.\n\nAnd copy-pasted code is but one type of code duplication. Common boilerplate\nand repeated logic can be identified as well using jsinspect, since it\ndoesn't operate directly on tokens - it uses the ASTs of the parsed code.\n\nYou have the freedom to specify a threshold determining the smallest subset of\nnodes to analyze. This will identify code with a similar structure, based\non the AST node types, e.g. BlockStatement, VariableDeclaration,\nObjectExpression, etc. By default, it searches nodes with matching identifiers\nand literals for copy-paste oriented detection, but this can be disabled.\nFor context, identifiers include the names of variables, methods, properties,\netc, while literals are strings, numbers, etc.\n\nThe tool accepts a list of paths to parse and prints any found matches. Any\ndirectories among the paths are walked recursively, and only `.js` and `.jsx`\nfiles are analyzed. You can explicitly pass file paths that include a different\nextension as well. Any `node_modules` and `bower_components` dirs are also\nignored.\n\n![screenshot](https://cloud.githubusercontent.com/assets/817212/24126139/bd151a34-0da2-11e7-94a8-9742279c8566.png)\n\n## Installation\n\nIt can be installed via `npm` using:\n\n``` bash\nnpm install -g jsinspect\n```\n\n## Usage\n\n```\nUsage: jsinspect [options] \u003cpaths ...\u003e\n\n\nDetect copy-pasted and structurally similar JavaScript code\nExample use: jsinspect -I -L -t 20 --ignore \"test\" ./path/to/src\n\n\nOptions:\n\n  -h, --help                         output usage information\n  -V, --version                      output the version number\n  -t, --threshold \u003cnumber\u003e           number of nodes (default: 30)\n  -m, --min-instances \u003cnumber\u003e       min instances for a match (default: 2)\n  -c, --config [config]              path to config file (default: .jsinspectrc)\n  -r, --reporter [default|json|pmd]  specify the reporter to use\n  -I, --no-identifiers               do not match identifiers\n  -L, --no-literals                  do not match literals\n  -C, --no-color                     disable colors\n  --ignore \u003cpattern\u003e                 ignore paths matching a regex\n  --truncate \u003cnumber\u003e                length to truncate lines (default: 100, off: 0)\n  --debug                            print debug information\n```\n\nIf a `.jsinspectrc` file is located in the project directory, its values will\nbe used in place of the defaults listed above. For example:\n\n``` javascript\n{\n  \"threshold\":     30,\n  \"identifiers\":   true,\n  \"literals\":      true,\n  \"color\":         true,\n  \"minInstances\":  2,\n  \"ignore\":        \"test|spec|mock\",\n  \"reporter\":      \"json\",\n  \"truncate\":      100,\n}\n```\n\nOn first use with a project, you may want to run the tool with the following\noptions, while running explicitly on the lib/src directories, and not the\ntest/spec dir.\n\n```\njsinspect -t 50 --ignore \"test\" ./path/to/src\n```\n\nFrom there, feel free to try decreasing the threshold, ignoring identifiers\nusing the `-I` flag and ignoring literals with `-L`. A lower threshold may lead\nyou to discover new areas of interest for refactoring or cleanup.\n\n## Integration\n\nIt's simple to run jsinspect on your library source as part of a build\nprocess. It will exit with an error code of 0 when no matches are found,\nresulting in a passing step, and a positive error code corresponding to its\nfailure. For example, with Travis CI, you could add the following entries\nto your `.travis.yml`:\n\n``` yaml\nbefore_script:\n  - \"npm install -g jsinspect\"\n\nscript:\n  - \"jsinspect ./path/to/src\"\n```\n\nNote that in the above example, we're using a threshold of 30 for detecting\nstructurally similar code. A higher threshold may be appropriate as well.\n\nTo have jsinspect run with each job, but not block or fail the build, you can\nuse something like the following:\n\n``` yaml\nscript:\n  - \"jsinspect ./path/to/src || true\"\n```\n\n## Reporters\n\nAside from the default reporter, both JSON and PMD CPD-style XML reporters are\navailable. Note that in the JSON example below, indentation and formatting\nhas been applied. Furthermore, the id property available in these reporters is\nuseful for parsing by automatic scripts to determine whether or not duplicate\ncode has changed between builds.\n\n#### JSON\n\n``` json\n[{\n  \"id\":\"6ceb36d5891732db3835c4954d48d1b90368a475\",\n  \"instances\":[\n    {\n      \"path\":\"spec/fixtures/intersection.js\",\n      \"lines\":[1,5],\n      \"code\":\"function intersectionA(array1, array2) {\\n  array1.filter(function(n) {\\n    return array2.indexOf(n) != -1;\\n  });\\n}\"\n    },\n    {\n      \"path\":\"spec/fixtures/intersection.js\",\n      \"lines\":[7,11],\n      \"code\":\"function intersectionB(arrayA, arrayB) {\\n  arrayA.filter(function(n) {\\n    return arrayB.indexOf(n) != -1;\\n  });\\n}\"\n    }\n  ]\n}]\n```\n\n#### PMD CPD XML\n\n``` xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cpmd-cpd\u003e\n\u003cduplication lines=\"10\" id=\"6ceb36d5891732db3835c4954d48d1b90368a475\"\u003e\n\u003cfile path=\"/jsinspect/spec/fixtures/intersection.js\" line=\"1\"/\u003e\n\u003cfile path=\"/jsinspect/spec/fixtures/intersection.js\" line=\"7\"/\u003e\n\u003ccodefragment\u003e\nspec/fixtures/intersection.js:1,5\nfunction intersectionA(array1, array2) {\n  array1.filter(function(n) {\n    return array2.indexOf(n) != -1;\n  });\n}\n\nspec/fixtures/intersection.js:7,11\nfunction intersectionB(arrayA, arrayB) {\n  arrayA.filter(function(n) {\n    return arrayB.indexOf(n) != -1;\n  });\n}\n\u003c/codefragment\u003e\n\u003c/duplication\u003e\n\u003c/pmd-cpd\u003e\n```\n","funding_links":[],"categories":["JavaScript","QA Tools","Tool","QA Tools [🔝](#readme)","Packages","QA 工具","包","Quality Checks"],"sub_categories":["Runner","Command-line apps","运行器","命令行应用","运行器e2e测试","A11y (accessibility)"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielstjules%2Fjsinspect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielstjules%2Fjsinspect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielstjules%2Fjsinspect/lists"}