[{"data":1,"prerenderedAt":1607},["ShallowReactive",2],{"navigation_docs":3,"-guides-clone-types":158,"-guides-clone-types-surround":1604},[4,50,67,103,125,141,146],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fgetting-started","1.getting-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Configuration","\u002Fgetting-started\u002Fconfiguration","1.getting-started\u002F4.configuration","i-lucide-settings",{"title":26,"path":27,"stem":28,"icon":29},"Supported Formats","\u002Fgetting-started\u002Fsupported-formats","1.getting-started\u002F5.supported-formats","i-lucide-file-code",{"title":31,"path":32,"stem":33,"icon":34},"Agent Skill","\u002Fgetting-started\u002Fagent-skill","1.getting-started\u002F6.agent-skill","i-lucide-cpu",{"title":36,"path":37,"stem":38,"icon":39},"Changelog","\u002Fgetting-started\u002Fchangelog","1.getting-started\u002F7.changelog","i-lucide-scroll-text",{"title":41,"path":42,"stem":43,"icon":44},"Migrating from v4 to v5","\u002Fgetting-started\u002Fmigration","1.getting-started\u002F8.migration","i-lucide-arrow-right-left",{"title":46,"path":47,"stem":48,"icon":49},"jscpd v4 (TypeScript)","\u002Fgetting-started\u002Fv4","1.getting-started\u002F9.v4","i-simple-icons-typescript",{"title":51,"path":52,"stem":53,"children":54,"icon":6},"CI & Hooks","\u002Fci-and-hooks","2.ci-and-hooks\u002F1.index",[55,57,62],{"title":51,"path":52,"stem":53,"icon":56},"i-lucide-git-pull-request",{"title":58,"path":59,"stem":60,"icon":61},"Use jscpd in CI","\u002Fci-and-hooks\u002Fci","2.ci-and-hooks\u002F2.ci","i-lucide-github",{"title":63,"path":64,"stem":65,"icon":66},"Use jscpd in Pre-Commit Hook","\u002Fci-and-hooks\u002Fpre-commit","2.ci-and-hooks\u002F3.pre-commit","i-lucide-git-commit",{"title":68,"path":69,"stem":70,"children":71,"icon":73},"Reporters","\u002Freporters","3.reporters\u002F1.index",[72,74,78,83,88,93,98],{"title":68,"path":69,"stem":70,"icon":73},"i-lucide-file-chart-column",{"title":75,"path":76,"stem":77,"icon":29},"HTML Reporter","\u002Freporters\u002Fhtml","3.reporters\u002F2.html",{"title":79,"path":80,"stem":81,"icon":82},"JSON Reporter","\u002Freporters\u002Fjson","3.reporters\u002F3.json","i-lucide-braces",{"title":84,"path":85,"stem":86,"icon":87},"Badge Reporter","\u002Freporters\u002Fbadge","3.reporters\u002F4.badge","i-lucide-award",{"title":89,"path":90,"stem":91,"icon":92},"SARIF Reporter","\u002Freporters\u002Fsarif","3.reporters\u002F5.sarif","i-lucide-shield-check",{"title":94,"path":95,"stem":96,"icon":97},"CodeClimate \u002F GitLab Reporter","\u002Freporters\u002Fcodeclimate","3.reporters\u002F6.codeclimate","i-lucide-flag-triangle-right",{"title":99,"path":100,"stem":101,"icon":102},"OpenMetrics Reporter","\u002Freporters\u002Fopenmetrics","3.reporters\u002F7.openmetrics","i-lucide-activity",{"title":104,"path":105,"stem":106,"children":107,"icon":6},"Benchmarks","\u002Fbenchmarks","4.benchmarks\u002F1.index",[108,110,115,120],{"title":104,"path":105,"stem":106,"icon":109},"i-lucide-gauge",{"title":111,"path":112,"stem":113,"icon":114},"Detection Speed","\u002Fbenchmarks\u002Fdetection-speed","4.benchmarks\u002F2.detection-speed","i-lucide-zap",{"title":116,"path":117,"stem":118,"icon":119},"Multi-Format Detection","\u002Fbenchmarks\u002Fcross-format","4.benchmarks\u002F3.cross-format","i-lucide-layers",{"title":121,"path":122,"stem":123,"icon":124},"AI Token Efficiency","\u002Fbenchmarks\u002Fai-token-efficiency","4.benchmarks\u002F4.ai-token-efficiency","i-lucide-sparkles",{"title":126,"path":127,"stem":128,"children":129,"icon":131},"API","\u002Fapi","5.api\u002F1.index",[130,132,137],{"title":126,"path":127,"stem":128,"icon":131},"i-lucide-code",{"title":133,"path":134,"stem":135,"icon":136},"Rust Crates (v5)","\u002Fapi\u002Fcore","5.api\u002F2.core","i-lucide-box",{"title":138,"path":139,"stem":140,"icon":136},"MCP Server","\u002Fapi\u002Fmcp-server","5.api\u002F4.mcp-server",{"title":142,"path":143,"stem":144,"icon":145},"Trending","\u002Ftrending","6.trending","i-lucide-trending-up",{"title":147,"path":148,"stem":149,"children":150,"icon":6},"Guides","\u002Fguides","7.guides\u002F1.index",[151,153],{"title":147,"path":148,"stem":149,"icon":152},"i-lucide-book-open",{"title":154,"path":155,"stem":156,"icon":157},"Types of Code Clones","\u002Fguides\u002Fclone-types","7.guides\u002F2.clone-types","i-lucide-copy",{"id":159,"title":154,"body":160,"description":1595,"extension":1596,"links":1597,"meta":1598,"navigation":1599,"path":155,"seo":1600,"stem":156,"__hash__":1603},"docs\u002F7.guides\u002F2.clone-types.md",{"type":161,"value":162,"toc":1588},"minimark",[163,167,266,271,274,501,508,537,545,549,552,843,846,933,967,1006,1014,1027,1039,1043,1046,1301,1310,1339,1391,1417,1440,1490,1509,1513,1523,1527,1584],[164,165,166],"p",{},"\"Duplicated code\" covers more than copy and paste. Clone-detection research sorts duplicates into four types by how much the copies have drifted apart, and every detector, jscpd included, draws its line somewhere in that scale. Knowing the types tells you what a scan can and cannot show, and which flag to reach for.",[168,169,170,189],"table",{},[171,172,173],"thead",{},[174,175,176,180,183,186],"tr",{},[177,178,179],"th",{},"Type",[177,181,182],{},"Also called",[177,184,185],{},"The copies differ in",[177,187,188],{},"jscpd",[190,191,192,207,231,252],"tbody",{},[174,193,194,198,201,204],{},[195,196,197],"td",{},"Type-1",[195,199,200],{},"exact clone",[195,202,203],{},"whitespace, layout, comments",[195,205,206],{},"default",[174,208,209,212,215,218],{},[195,210,211],{},"Type-2",[195,213,214],{},"renamed, parameterized clone",[195,216,217],{},"identifier names, literal values, annotations",[195,219,220,224,225,224,228],{},[221,222,223],"code",{},"--ignore-identifiers",", ",[221,226,227],{},"--ignore-literals",[221,229,230],{},"--ignore-annotations",[174,232,233,236,239,242],{},[195,234,235],{},"Type-3",[195,237,238],{},"near-miss, gapped clone",[195,240,241],{},"added, removed or changed statements",[195,243,244,247,248,251],{},[221,245,246],{},"--max-gap-lines N"," merges the pieces around a gap; ",[221,249,250],{},"--similarity RATIO"," compares whole JS\u002FTS functions by syntax tree",[174,253,254,257,260,263],{},[195,255,256],{},"Type-4",[195,258,259],{},"semantic clone",[195,261,262],{},"everything but the behavior",[195,264,265],{},"out of scope for token-based detection",[267,268,270],"h2",{"id":269},"type-1-exact-clones","Type-1: exact clones",[164,272,273],{},"Two fragments are Type-1 clones when their tokens are identical. Whitespace, line breaks and, depending on the mode, comments do not count.",[275,276,281],"pre",{"className":277,"code":278,"language":279,"meta":280,"style":280},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F a.js\nfunction total(items) {\n  let sum = 0;\n  for (const item of items) { sum += item.price; }\n  return sum;\n}\n\n\u002F\u002F b.js\nfunction total(items) {\n  let sum = 0;   \u002F\u002F running total\n  for (const item of items) {\n    sum += item.price;\n  }\n  return sum;\n}\n","javascript","",[221,282,283,292,317,337,385,395,401,408,414,429,445,465,481,487,496],{"__ignoreMap":280},[284,285,288],"span",{"class":286,"line":287},"line",1,[284,289,291],{"class":290},"sHwdD","\u002F\u002F a.js\n",[284,293,295,299,303,307,311,314],{"class":286,"line":294},2,[284,296,298],{"class":297},"spNyl","function",[284,300,302],{"class":301},"s2Zo4"," total",[284,304,306],{"class":305},"sMK4o","(",[284,308,310],{"class":309},"sHdIc","items",[284,312,313],{"class":305},")",[284,315,316],{"class":305}," {\n",[284,318,320,323,327,330,334],{"class":286,"line":319},3,[284,321,322],{"class":297},"  let",[284,324,326],{"class":325},"sTEyZ"," sum",[284,328,329],{"class":305}," =",[284,331,333],{"class":332},"sbssI"," 0",[284,335,336],{"class":305},";\n",[284,338,340,344,348,351,354,357,360,363,366,368,371,373,376,379,382],{"class":286,"line":339},4,[284,341,343],{"class":342},"s7zQu","  for",[284,345,347],{"class":346},"swJcz"," (",[284,349,350],{"class":297},"const",[284,352,353],{"class":325}," item",[284,355,356],{"class":305}," of",[284,358,359],{"class":325}," items",[284,361,362],{"class":346},") ",[284,364,365],{"class":305},"{",[284,367,326],{"class":325},[284,369,370],{"class":305}," +=",[284,372,353],{"class":325},[284,374,375],{"class":305},".",[284,377,378],{"class":325},"price",[284,380,381],{"class":305},";",[284,383,384],{"class":305}," }\n",[284,386,388,391,393],{"class":286,"line":387},5,[284,389,390],{"class":342},"  return",[284,392,326],{"class":325},[284,394,336],{"class":305},[284,396,398],{"class":286,"line":397},6,[284,399,400],{"class":305},"}\n",[284,402,404],{"class":286,"line":403},7,[284,405,407],{"emptyLinePlaceholder":406},true,"\n",[284,409,411],{"class":286,"line":410},8,[284,412,413],{"class":290},"\u002F\u002F b.js\n",[284,415,417,419,421,423,425,427],{"class":286,"line":416},9,[284,418,298],{"class":297},[284,420,302],{"class":301},[284,422,306],{"class":305},[284,424,310],{"class":309},[284,426,313],{"class":305},[284,428,316],{"class":305},[284,430,432,434,436,438,440,442],{"class":286,"line":431},10,[284,433,322],{"class":297},[284,435,326],{"class":325},[284,437,329],{"class":305},[284,439,333],{"class":332},[284,441,381],{"class":305},[284,443,444],{"class":290},"   \u002F\u002F running total\n",[284,446,448,450,452,454,456,458,460,462],{"class":286,"line":447},11,[284,449,343],{"class":342},[284,451,347],{"class":346},[284,453,350],{"class":297},[284,455,353],{"class":325},[284,457,356],{"class":305},[284,459,359],{"class":325},[284,461,362],{"class":346},[284,463,464],{"class":305},"{\n",[284,466,468,471,473,475,477,479],{"class":286,"line":467},12,[284,469,470],{"class":325},"    sum",[284,472,370],{"class":305},[284,474,353],{"class":325},[284,476,375],{"class":305},[284,478,378],{"class":325},[284,480,336],{"class":305},[284,482,484],{"class":286,"line":483},13,[284,485,486],{"class":305},"  }\n",[284,488,490,492,494],{"class":286,"line":489},14,[284,491,390],{"class":342},[284,493,326],{"class":325},[284,495,336],{"class":305},[284,497,499],{"class":286,"line":498},15,[284,500,400],{"class":305},[164,502,503,504,507],{},"jscpd finds these by default. The ",[221,505,506],{},"--mode"," option decides what \"identical\" ignores:",[509,510,511,518,524],"ul",{},[512,513,514,517],"li",{},[221,515,516],{},"mild"," (default) drops whitespace, so layout changes are invisible.",[512,519,520,523],{},[221,521,522],{},"weak"," also drops comments, so a re-commented copy still matches.",[512,525,526,529,530,533,534,375],{},[221,527,528],{},"strict"," keeps everything except blocks marked with ",[221,531,532],{},"jscpd:ignore-start"," \u002F ",[221,535,536],{},"jscpd:ignore-end",[164,538,539,540,375],{},"Type-1 is the category to gate in CI: an exact clone is nearly always a copy that should be a shared function, and the result is stable enough for a ",[541,542,544],"a",{"href":543},"\u002Fgetting-started\u002Fconfiguration#gate-on-new-duplication-only","baseline",[267,546,548],{"id":547},"type-2-renamed-clones","Type-2: renamed clones",[164,550,551],{},"A Type-2 clone is a Type-1 clone whose identifiers, literals or annotations were changed while the structure stayed the same. This is what a copy looks like after someone adapted it to a second use.",[275,553,555],{"className":277,"code":554,"language":279,"meta":280,"style":280},"\u002F\u002F cart.js\nexport function cartTotal(items, taxRate) {\n  let subtotal = 0;\n  for (const item of items) {\n    subtotal += item.price * item.quantity;\n  }\n  const tax = subtotal * taxRate;\n  return { subtotal, tax, total: subtotal + tax };\n}\n\n\u002F\u002F basket.js\nexport function basketTotal(entries, vatRate) {\n  let net = 0;\n  for (const entry of entries) {\n    net += entry.price * entry.quantity;\n  }\n  const vat = net * vatRate;\n  return { net, vat, gross: net + vat };\n}\n",[221,556,557,562,587,600,618,643,647,665,695,699,703,708,731,744,764,787,792,810,838],{"__ignoreMap":280},[284,558,559],{"class":286,"line":287},[284,560,561],{"class":290},"\u002F\u002F cart.js\n",[284,563,564,567,570,573,575,577,580,583,585],{"class":286,"line":294},[284,565,566],{"class":342},"export",[284,568,569],{"class":297}," function",[284,571,572],{"class":301}," cartTotal",[284,574,306],{"class":305},[284,576,310],{"class":309},[284,578,579],{"class":305},",",[284,581,582],{"class":309}," taxRate",[284,584,313],{"class":305},[284,586,316],{"class":305},[284,588,589,591,594,596,598],{"class":286,"line":319},[284,590,322],{"class":297},[284,592,593],{"class":325}," subtotal",[284,595,329],{"class":305},[284,597,333],{"class":332},[284,599,336],{"class":305},[284,601,602,604,606,608,610,612,614,616],{"class":286,"line":339},[284,603,343],{"class":342},[284,605,347],{"class":346},[284,607,350],{"class":297},[284,609,353],{"class":325},[284,611,356],{"class":305},[284,613,359],{"class":325},[284,615,362],{"class":346},[284,617,464],{"class":305},[284,619,620,623,625,627,629,631,634,636,638,641],{"class":286,"line":387},[284,621,622],{"class":325},"    subtotal",[284,624,370],{"class":305},[284,626,353],{"class":325},[284,628,375],{"class":305},[284,630,378],{"class":325},[284,632,633],{"class":305}," *",[284,635,353],{"class":325},[284,637,375],{"class":305},[284,639,640],{"class":325},"quantity",[284,642,336],{"class":305},[284,644,645],{"class":286,"line":397},[284,646,486],{"class":305},[284,648,649,652,655,657,659,661,663],{"class":286,"line":403},[284,650,651],{"class":297},"  const",[284,653,654],{"class":325}," tax",[284,656,329],{"class":305},[284,658,593],{"class":325},[284,660,633],{"class":305},[284,662,582],{"class":325},[284,664,336],{"class":305},[284,666,667,669,672,674,676,678,680,682,685,687,690,692],{"class":286,"line":410},[284,668,390],{"class":342},[284,670,671],{"class":305}," {",[284,673,593],{"class":325},[284,675,579],{"class":305},[284,677,654],{"class":325},[284,679,579],{"class":305},[284,681,302],{"class":346},[284,683,684],{"class":305},":",[284,686,593],{"class":325},[284,688,689],{"class":305}," +",[284,691,654],{"class":325},[284,693,694],{"class":305}," };\n",[284,696,697],{"class":286,"line":416},[284,698,400],{"class":305},[284,700,701],{"class":286,"line":431},[284,702,407],{"emptyLinePlaceholder":406},[284,704,705],{"class":286,"line":447},[284,706,707],{"class":290},"\u002F\u002F basket.js\n",[284,709,710,712,714,717,719,722,724,727,729],{"class":286,"line":467},[284,711,566],{"class":342},[284,713,569],{"class":297},[284,715,716],{"class":301}," basketTotal",[284,718,306],{"class":305},[284,720,721],{"class":309},"entries",[284,723,579],{"class":305},[284,725,726],{"class":309}," vatRate",[284,728,313],{"class":305},[284,730,316],{"class":305},[284,732,733,735,738,740,742],{"class":286,"line":483},[284,734,322],{"class":297},[284,736,737],{"class":325}," net",[284,739,329],{"class":305},[284,741,333],{"class":332},[284,743,336],{"class":305},[284,745,746,748,750,752,755,757,760,762],{"class":286,"line":489},[284,747,343],{"class":342},[284,749,347],{"class":346},[284,751,350],{"class":297},[284,753,754],{"class":325}," entry",[284,756,356],{"class":305},[284,758,759],{"class":325}," entries",[284,761,362],{"class":346},[284,763,464],{"class":305},[284,765,766,769,771,773,775,777,779,781,783,785],{"class":286,"line":498},[284,767,768],{"class":325},"    net",[284,770,370],{"class":305},[284,772,754],{"class":325},[284,774,375],{"class":305},[284,776,378],{"class":325},[284,778,633],{"class":305},[284,780,754],{"class":325},[284,782,375],{"class":305},[284,784,640],{"class":325},[284,786,336],{"class":305},[284,788,790],{"class":286,"line":789},16,[284,791,486],{"class":305},[284,793,795,797,800,802,804,806,808],{"class":286,"line":794},17,[284,796,651],{"class":297},[284,798,799],{"class":325}," vat",[284,801,329],{"class":305},[284,803,737],{"class":325},[284,805,633],{"class":305},[284,807,726],{"class":325},[284,809,336],{"class":305},[284,811,813,815,817,819,821,823,825,828,830,832,834,836],{"class":286,"line":812},18,[284,814,390],{"class":342},[284,816,671],{"class":305},[284,818,737],{"class":325},[284,820,579],{"class":305},[284,822,799],{"class":325},[284,824,579],{"class":305},[284,826,827],{"class":346}," gross",[284,829,684],{"class":305},[284,831,737],{"class":325},[284,833,689],{"class":305},[284,835,799],{"class":325},[284,837,694],{"class":305},[284,839,841],{"class":286,"line":840},19,[284,842,400],{"class":305},[164,844,845],{},"A default scan reports nothing here, because every other token differs. jscpd 5.2 adds three flags that normalize token classes before hashing:",[168,847,848,861],{},[171,849,850],{},[174,851,852,855,858],{},[177,853,854],{},"Flag",[177,856,857],{},"Config key",[177,859,860],{},"Effect",[190,862,863,887,909],{},[174,864,865,869,874],{},[195,866,867],{},[221,868,223],{},[195,870,871],{},[221,872,873],{},"ignoreIdentifiers",[195,875,876,877,880,881,884,885],{},"every identifier hashes as ",[221,878,879],{},"$id","; keywords are kept, so ",[221,882,883],{},"for"," still has to match ",[221,886,883],{},[174,888,889,893,898],{},[195,890,891],{},[221,892,227],{},[195,894,895],{},[221,896,897],{},"ignoreLiterals",[195,899,900,901,904,905,908],{},"strings hash as ",[221,902,903],{},"$str",", numbers as ",[221,906,907],{},"$num","; a string never matches a number",[174,910,911,915,920],{},[195,912,913],{},[221,914,230],{},[195,916,917],{},[221,918,919],{},"ignoreAnnotations",[195,921,922,224,925,928,929,932],{},[221,923,924],{},"@Name",[221,926,927],{},"@a.b.Name"," and ",[221,930,931],{},"@Name(...)"," are dropped in Java, Kotlin, Scala, Groovy, Python, Dart, Swift, JavaScript and TypeScript",[275,934,938],{"className":935,"code":936,"language":937,"meta":280,"style":280},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","jscpd --ignore-identifiers src\u002F\n# Clone found (javascript, renamed)\n#  - basket.js [1:1 - 9:2] (9 lines, 57 tokens)\n#    cart.js [1:1 - 9:2]\n","bash",[221,939,940,952,957,962],{"__ignoreMap":280},[284,941,942,945,949],{"class":286,"line":287},[284,943,188],{"class":944},"sBMFI",[284,946,948],{"class":947},"sfazB"," --ignore-identifiers",[284,950,951],{"class":947}," src\u002F\n",[284,953,954],{"class":286,"line":294},[284,955,956],{"class":290},"# Clone found (javascript, renamed)\n",[284,958,959],{"class":286,"line":319},[284,960,961],{"class":290},"#  - basket.js [1:1 - 9:2] (9 lines, 57 tokens)\n",[284,963,964],{"class":286,"line":339},[284,965,966],{"class":290},"#    cart.js [1:1 - 9:2]\n",[164,968,969,970,973,974,977,978,981,982,985,986,989,990,993,994,997,998,1001,1002,1005],{},"Clones found this way are labelled so they never blend into the exact ones. Every clone carries a ",[221,971,972],{},"kind",": ",[221,975,976],{},"exact"," when the raw tokens match, ",[221,979,980],{},"renamed"," when they match only after normalization. The console prints ",[221,983,984],{},"Clone found (javascript, renamed)",", the ",[541,987,988],{"href":80},"JSON report"," has a ",[221,991,992],{},"\"kind\""," field, and the ",[541,995,996],{"href":90},"SARIF report"," files renamed clones under the rule ",[221,999,1000],{},"jscpd\u002Fsimilar-code"," instead of ",[221,1003,1004],{},"jscpd\u002Fduplicate-code",", so GitHub code scanning shows them as a separate rule.",[1007,1008,1009,1010,1013],"note",{},"Normalized runs find more and longer clones than exact runs, so their fingerprints differ. Keep a separate ",[221,1011,1012],{},"--baseline"," file for a normalized configuration rather than reusing the one from an exact scan.",[164,1015,1016,1019,1020,928,1023,1026],{},[221,1017,1018],{},"--ignore-case"," is a much smaller step in the same direction: it folds ",[221,1021,1022],{},"Total",[221,1024,1025],{},"total"," together and nothing else.",[164,1028,1029,1030,1038],{},"The repository ships a runnable demo of each flag in ",[541,1031,1035],{"href":1032,"rel":1033},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Ftree\u002Fmaster\u002Ffixtures\u002Ftype2-demo",[1034],"nofollow",[221,1036,1037],{},"fixtures\u002Ftype2-demo",", with the expected output of every command.",[267,1040,1042],{"id":1041},"type-3-near-miss-clones","Type-3: near-miss clones",[164,1044,1045],{},"Type-3 clones are copies with statements added, removed or changed in the middle: a validation line inserted here, a logging call dropped there.",[275,1047,1049],{"className":277,"code":1048,"language":279,"meta":280,"style":280},"\u002F\u002F original                          \u002F\u002F copy with an inserted check\nfunction save(user) {                function save(user) {\n  const row = toRow(user);             const row = toRow(user);\n  row.updatedAt = Date.now();          if (!row.id) throw new Error('id');\n  db.put(row);                         row.updatedAt = Date.now();\n  audit('save', row.id);               db.put(row);\n}                                      audit('save', row.id);\n                                     }\n",[221,1050,1051,1059,1088,1125,1190,1227,1268,1296],{"__ignoreMap":280},[284,1052,1053,1056],{"class":286,"line":287},[284,1054,1055],{"class":290},"\u002F\u002F original",[284,1057,1058],{"class":290},"                          \u002F\u002F copy with an inserted check\n",[284,1060,1061,1063,1066,1068,1071,1073,1075,1078,1080,1082,1084,1086],{"class":286,"line":294},[284,1062,298],{"class":297},[284,1064,1065],{"class":301}," save",[284,1067,306],{"class":305},[284,1069,1070],{"class":309},"user",[284,1072,313],{"class":305},[284,1074,671],{"class":305},[284,1076,1077],{"class":297},"                function",[284,1079,1065],{"class":301},[284,1081,306],{"class":305},[284,1083,1070],{"class":309},[284,1085,313],{"class":305},[284,1087,316],{"class":305},[284,1089,1090,1092,1095,1097,1100,1102,1104,1106,1108,1111,1113,1115,1117,1119,1121,1123],{"class":286,"line":319},[284,1091,651],{"class":297},[284,1093,1094],{"class":325}," row",[284,1096,329],{"class":305},[284,1098,1099],{"class":301}," toRow",[284,1101,306],{"class":346},[284,1103,1070],{"class":325},[284,1105,313],{"class":346},[284,1107,381],{"class":305},[284,1109,1110],{"class":297},"             const",[284,1112,1094],{"class":325},[284,1114,329],{"class":305},[284,1116,1099],{"class":301},[284,1118,306],{"class":346},[284,1120,1070],{"class":325},[284,1122,313],{"class":346},[284,1124,336],{"class":305},[284,1126,1127,1130,1132,1135,1137,1140,1142,1145,1148,1150,1153,1155,1158,1161,1163,1166,1168,1171,1174,1177,1179,1182,1184,1186,1188],{"class":286,"line":339},[284,1128,1129],{"class":325},"  row",[284,1131,375],{"class":305},[284,1133,1134],{"class":325},"updatedAt",[284,1136,329],{"class":305},[284,1138,1139],{"class":325}," Date",[284,1141,375],{"class":305},[284,1143,1144],{"class":301},"now",[284,1146,1147],{"class":346},"()",[284,1149,381],{"class":305},[284,1151,1152],{"class":342},"          if",[284,1154,347],{"class":346},[284,1156,1157],{"class":305},"!",[284,1159,1160],{"class":325},"row",[284,1162,375],{"class":305},[284,1164,1165],{"class":325},"id",[284,1167,362],{"class":346},[284,1169,1170],{"class":342},"throw",[284,1172,1173],{"class":305}," new",[284,1175,1176],{"class":301}," Error",[284,1178,306],{"class":346},[284,1180,1181],{"class":305},"'",[284,1183,1165],{"class":947},[284,1185,1181],{"class":305},[284,1187,313],{"class":346},[284,1189,336],{"class":305},[284,1191,1192,1195,1197,1200,1202,1204,1206,1208,1211,1213,1215,1217,1219,1221,1223,1225],{"class":286,"line":387},[284,1193,1194],{"class":325},"  db",[284,1196,375],{"class":305},[284,1198,1199],{"class":301},"put",[284,1201,306],{"class":346},[284,1203,1160],{"class":325},[284,1205,313],{"class":346},[284,1207,381],{"class":305},[284,1209,1210],{"class":325},"                         row",[284,1212,375],{"class":305},[284,1214,1134],{"class":325},[284,1216,329],{"class":305},[284,1218,1139],{"class":325},[284,1220,375],{"class":305},[284,1222,1144],{"class":301},[284,1224,1147],{"class":346},[284,1226,336],{"class":305},[284,1228,1229,1232,1234,1236,1239,1241,1243,1245,1247,1249,1251,1253,1256,1258,1260,1262,1264,1266],{"class":286,"line":397},[284,1230,1231],{"class":301},"  audit",[284,1233,306],{"class":346},[284,1235,1181],{"class":305},[284,1237,1238],{"class":947},"save",[284,1240,1181],{"class":305},[284,1242,579],{"class":305},[284,1244,1094],{"class":325},[284,1246,375],{"class":305},[284,1248,1165],{"class":325},[284,1250,313],{"class":346},[284,1252,381],{"class":305},[284,1254,1255],{"class":325},"               db",[284,1257,375],{"class":305},[284,1259,1199],{"class":301},[284,1261,306],{"class":346},[284,1263,1160],{"class":325},[284,1265,313],{"class":346},[284,1267,336],{"class":305},[284,1269,1270,1273,1276,1278,1280,1282,1284,1286,1288,1290,1292,1294],{"class":286,"line":403},[284,1271,1272],{"class":305},"}",[284,1274,1275],{"class":301},"                                      audit",[284,1277,306],{"class":346},[284,1279,1181],{"class":305},[284,1281,1238],{"class":947},[284,1283,1181],{"class":305},[284,1285,579],{"class":305},[284,1287,1094],{"class":325},[284,1289,375],{"class":305},[284,1291,1165],{"class":325},[284,1293,313],{"class":346},[284,1295,336],{"class":305},[284,1297,1298],{"class":286,"line":410},[284,1299,1300],{"class":305},"                                     }\n",[164,1302,1303,1304,928,1307,375],{},"A token-window detector sees this as two shorter exact clones with a gap between them, and that is what a default jscpd run reports, provided each side of the gap still clears ",[221,1305,1306],{},"--min-tokens",[221,1308,1309],{},"--min-lines",[164,1311,1312,1313,1315,1316,1319,1320,1323,1324,1327,1328,1331,1332,1335,1336,684],{},"From jscpd 5.2, ",[221,1314,246],{}," (config key ",[221,1317,1318],{},"maxGapLines",") merges clones of the same file pair whose fragments follow each other in both files with at most ",[221,1321,1322],{},"N"," unmatched lines between them into one clone of kind ",[221,1325,1326],{},"similar",". Its ",[221,1329,1330],{},"tokens"," value is the number of matched tokens and ",[221,1333,1334],{},"similarity"," is that number divided by the tokens of the longer merged span, so one inserted line in a 150-token block reads as roughly ",[221,1337,1338],{},"0.9",[275,1340,1342],{"className":935,"code":1341,"language":937,"meta":280,"style":280},"jscpd src\u002F\n# Found 2 clones.\n\njscpd --max-gap-lines 1 src\u002F\n# Clone found (javascript, similar (gap) ~0.91)\n#  - save-account.js [1:1 - 12:2] (12 lines, 157 tokens)\n#    save-user.js [1:1 - 11:2]\n# Found 1 clones.\n",[221,1343,1344,1350,1355,1359,1371,1376,1381,1386],{"__ignoreMap":280},[284,1345,1346,1348],{"class":286,"line":287},[284,1347,188],{"class":944},[284,1349,951],{"class":947},[284,1351,1352],{"class":286,"line":294},[284,1353,1354],{"class":290},"# Found 2 clones.\n",[284,1356,1357],{"class":286,"line":319},[284,1358,407],{"emptyLinePlaceholder":406},[284,1360,1361,1363,1366,1369],{"class":286,"line":339},[284,1362,188],{"class":944},[284,1364,1365],{"class":947}," --max-gap-lines",[284,1367,1368],{"class":332}," 1",[284,1370,951],{"class":947},[284,1372,1373],{"class":286,"line":387},[284,1374,1375],{"class":290},"# Clone found (javascript, similar (gap) ~0.91)\n",[284,1377,1378],{"class":286,"line":397},[284,1379,1380],{"class":290},"#  - save-account.js [1:1 - 12:2] (12 lines, 157 tokens)\n",[284,1382,1383],{"class":286,"line":403},[284,1384,1385],{"class":290},"#    save-user.js [1:1 - 11:2]\n",[284,1387,1388],{"class":286,"line":410},[284,1389,1390],{"class":290},"# Found 1 clones.\n",[164,1392,1393,1394,1397,1398,1401,1402,1405,1406,1409,1410,375],{},"The merge only joins clones the exact run already found, so it cannot invent a match; it removes fragmentation. It is off at the default of ",[221,1395,1396],{},"0",", and the JSON report carries ",[221,1399,1400],{},"\"kind\": \"similar\""," with the ",[221,1403,1404],{},"\"similarity\""," value, while SARIF files these under ",[221,1407,1408],{},"jscpd\u002Fnear-miss-code",". A runnable pair lives in ",[541,1411,1414],{"href":1412,"rel":1413},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Ftree\u002Fmaster\u002Ffixtures\u002Ftype3-demo",[1034],[221,1415,1416],{},"fixtures\u002Ftype3-demo",[164,1418,1419,1420,1422,1423,1425,1426,1429,1430,1433,1434,1436,1437,684],{},"Edits spread through a function rather than concentrated in one gap still escape a token window. For JavaScript and TypeScript, ",[221,1421,250],{}," compares whole functions by structure instead: each function, method or arrow function is summarized by the 4-grams of its syntax-tree node types, and two functions are reported as one ",[221,1424,1326],{}," clone when the weighted Jaccard index of those bags reaches ",[221,1427,1428],{},"RATIO",". Names and values are not part of the summary, so a renamed copy scores ",[221,1431,1432],{},"1.0",", one inserted line about ",[221,1435,1338],{},", and two inserted statements plus renames about ",[221,1438,1439],{},"0.75",[275,1441,1443],{"className":935,"code":1442,"language":937,"meta":280,"style":280},"jscpd --similarity 0.85 src\u002F     # near-identical structure\njscpd --similarity 0.7 src\u002F      # a couple of added or removed statements\n# Clone found (javascript, similar (ast) ~0.75)\n#  - credit-note.js [1:8 - 19:2] (19 lines, 126 tokens)\n#    invoice.js [1:8 - 17:2]\n",[221,1444,1445,1461,1475,1480,1485],{"__ignoreMap":280},[284,1446,1447,1449,1452,1455,1458],{"class":286,"line":287},[284,1448,188],{"class":944},[284,1450,1451],{"class":947}," --similarity",[284,1453,1454],{"class":332}," 0.85",[284,1456,1457],{"class":947}," src\u002F",[284,1459,1460],{"class":290},"     # near-identical structure\n",[284,1462,1463,1465,1467,1470,1472],{"class":286,"line":294},[284,1464,188],{"class":944},[284,1466,1451],{"class":947},[284,1468,1469],{"class":332}," 0.7",[284,1471,1457],{"class":947},[284,1473,1474],{"class":290},"      # a couple of added or removed statements\n",[284,1476,1477],{"class":286,"line":319},[284,1478,1479],{"class":290},"# Clone found (javascript, similar (ast) ~0.75)\n",[284,1481,1482],{"class":286,"line":339},[284,1483,1484],{"class":290},"#  - credit-note.js [1:8 - 19:2] (19 lines, 126 tokens)\n",[284,1486,1487],{"class":286,"line":387},[284,1488,1489],{"class":290},"#    invoice.js [1:8 - 17:2]\n",[164,1491,1492,1493,928,1495,1497,1498,1501,1502,375],{},"Functions must clear ",[221,1494,1306],{},[221,1496,1309],{}," on their own, and a pair already reported as an exact or merged clone is not repeated. The same ratio is accepted by the MCP ",[221,1499,1500],{},"check_duplication"," tool, which then lists the project functions structurally similar to a snippet. Both options are off by default. A runnable pair lives in ",[541,1503,1506],{"href":1504,"rel":1505},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Ftree\u002Fmaster\u002Ffixtures\u002Ftype3-demo\u002Fsimilar-functions",[1034],[221,1507,1508],{},"fixtures\u002Ftype3-demo\u002Fsimilar-functions",[267,1510,1512],{"id":1511},"type-4-semantic-clones","Type-4: semantic clones",[164,1514,1515,1516,1518,1519,1522],{},"Type-4 clones compute the same thing with different code: a ",[221,1517,883],{}," loop and a ",[221,1520,1521],{},"reduce"," call that both sum prices, or two sorting routines. No token-based tool detects them, and jscpd does not try. They are the domain of program-dependence-graph and AST-similarity research, and in practice of code review.",[267,1524,1526],{"id":1525},"which-type-to-look-for","Which type to look for",[509,1528,1529,1541,1554,1567],{},[512,1530,1531,1535,1536,928,1538,1540],{},[1532,1533,1534],"strong",{},"In CI, gate on Type-1."," Exact clones are unambiguous and stable across runs, which is what a failing check needs. Use ",[221,1537,1306],{},[221,1539,1309],{}," to set the size, and a baseline to fail only on new duplication.",[512,1542,1543,1546,1547,1550,1551,1553],{},[1532,1544,1545],{},"When refactoring, scan for Type-2."," Run ",[221,1548,1549],{},"--ignore-identifiers --ignore-literals"," on the area you are about to change; renamed copies are where a shared helper pays off most. Read the ",[221,1552,980],{}," results as leads, not defects, since some parametric similarity is idiomatic.",[512,1555,1556,1559,1560,1563,1564,1566],{},[1532,1557,1558],{},"Treat adjacent Type-1 findings as a pair."," Two clones between the same files a few lines apart usually are one near-miss clone with an edit in between. Rerun with ",[221,1561,1562],{},"--max-gap-lines 2"," to see them as one and read the ",[221,1565,1334],{}," value.",[512,1568,1569,1575,1576,1579,1580,1583],{},[1532,1570,1571,1572,375],{},"Hunt Type-3 in JS\u002FTS with ",[221,1573,1574],{},"--similarity"," Start at ",[221,1577,1578],{},"0.85"," to catch near-identical functions, lower it towards ",[221,1581,1582],{},"0.7"," to see heavier edits. Treat the score as a ranking, not a verdict.",[1585,1586,1587],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":280,"searchDepth":294,"depth":294,"links":1589},[1590,1591,1592,1593,1594],{"id":269,"depth":294,"text":270},{"id":547,"depth":294,"text":548},{"id":1041,"depth":294,"text":1042},{"id":1511,"depth":294,"text":1512},{"id":1525,"depth":294,"text":1526},"Exact, renamed, near-miss and semantic clones, and which of them jscpd finds.","md",null,{},{"icon":157},{"title":1601,"description":1602},"Types of Code Clones (Type-1 to Type-4) and What jscpd Detects","The four clone types from clone-detection research, with examples, and how jscpd's modes and --ignore-identifiers \u002F --ignore-literals \u002F --ignore-annotations flags map onto them.","Zv6yOP2Lb-3KDYnXXGkv8VdYZBIpJVt_KIvpeSQ3T7A",[1605,1597],{"title":147,"path":148,"stem":149,"description":1606,"icon":152,"children":-1},"Longer reads on duplicate detection and how to use jscpd well.",1788884728664]