[{"data":1,"prerenderedAt":3774},["ShallowReactive",2],{"navigation_docs":3,"-guides-compare":202,"-guides-compare-surround":3769},[4,50,92,109,145,171,187,192,197],{"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 Skills","\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},"Guides","\u002Fguides","2.guides\u002F1.index",[55,57,62,67,72,77,82,87],{"title":51,"path":52,"stem":53,"icon":56},"i-lucide-book-open",{"title":58,"path":59,"stem":60,"icon":61},"Types of Code Clones","\u002Fguides\u002Fclone-types","2.guides\u002F2.clone-types","i-lucide-copy",{"title":63,"path":64,"stem":65,"icon":66},"How Detection Works","\u002Fguides\u002Fhow-detection-works","2.guides\u002F3.how-detection-works","i-lucide-scan-search",{"title":68,"path":69,"stem":70,"icon":71},"Duplication Trend over Git History","\u002Fguides\u002Fhistory","2.guides\u002F4.history","i-lucide-chart-no-axes-combined",{"title":73,"path":74,"stem":75,"icon":76},"Project Dashboard","\u002Fguides\u002Fdashboard","2.guides\u002F5.dashboard","i-lucide-layout-dashboard",{"title":78,"path":79,"stem":80,"icon":81},"Project Health Score","\u002Fguides\u002Fhealth","2.guides\u002F6.health","i-lucide-heart-pulse",{"title":83,"path":84,"stem":85,"icon":86},"Semantic Clones","\u002Fguides\u002Fsemantic-clones","2.guides\u002F7.semantic-clones","i-lucide-brain-circuit",{"title":88,"path":89,"stem":90,"icon":91},"Comparing Two Codebases","\u002Fguides\u002Fcompare","2.guides\u002F8.compare","i-lucide-git-compare-arrows",{"title":93,"path":94,"stem":95,"children":96,"icon":6},"CI & Hooks","\u002Fci-and-hooks","3.ci-and-hooks\u002F1.index",[97,99,104],{"title":93,"path":94,"stem":95,"icon":98},"i-lucide-git-pull-request",{"title":100,"path":101,"stem":102,"icon":103},"Use jscpd in CI","\u002Fci-and-hooks\u002Fci","3.ci-and-hooks\u002F2.ci","i-lucide-github",{"title":105,"path":106,"stem":107,"icon":108},"Use jscpd in Pre-Commit Hook","\u002Fci-and-hooks\u002Fpre-commit","3.ci-and-hooks\u002F3.pre-commit","i-lucide-git-commit",{"title":110,"path":111,"stem":112,"children":113,"icon":115},"Reporters","\u002Freporters","4.reporters\u002F1.index",[114,116,120,125,130,135,140],{"title":110,"path":111,"stem":112,"icon":115},"i-lucide-file-chart-column",{"title":117,"path":118,"stem":119,"icon":29},"HTML Reporter","\u002Freporters\u002Fhtml","4.reporters\u002F2.html",{"title":121,"path":122,"stem":123,"icon":124},"JSON Reporter","\u002Freporters\u002Fjson","4.reporters\u002F3.json","i-lucide-braces",{"title":126,"path":127,"stem":128,"icon":129},"Badge Reporter","\u002Freporters\u002Fbadge","4.reporters\u002F4.badge","i-lucide-award",{"title":131,"path":132,"stem":133,"icon":134},"SARIF Reporter","\u002Freporters\u002Fsarif","4.reporters\u002F5.sarif","i-lucide-shield-check",{"title":136,"path":137,"stem":138,"icon":139},"CodeClimate \u002F GitLab Reporter","\u002Freporters\u002Fcodeclimate","4.reporters\u002F6.codeclimate","i-lucide-flag-triangle-right",{"title":141,"path":142,"stem":143,"icon":144},"OpenMetrics Reporter","\u002Freporters\u002Fopenmetrics","4.reporters\u002F7.openmetrics","i-lucide-activity",{"title":146,"path":147,"stem":148,"children":149,"icon":6},"Benchmarks","\u002Fbenchmarks","5.benchmarks\u002F1.index",[150,152,157,162,167],{"title":146,"path":147,"stem":148,"icon":151},"i-lucide-gauge",{"title":153,"path":154,"stem":155,"icon":156},"Detection Speed","\u002Fbenchmarks\u002Fdetection-speed","5.benchmarks\u002F2.detection-speed","i-lucide-zap",{"title":158,"path":159,"stem":160,"icon":161},"Multi-Format Detection","\u002Fbenchmarks\u002Fcross-format","5.benchmarks\u002F3.cross-format","i-lucide-layers",{"title":163,"path":164,"stem":165,"icon":166},"AI Token Efficiency","\u002Fbenchmarks\u002Fai-token-efficiency","5.benchmarks\u002F4.ai-token-efficiency","i-lucide-sparkles",{"title":168,"path":169,"stem":170,"icon":86},"Embedding Models","\u002Fbenchmarks\u002Fembedding-models","5.benchmarks\u002F5.embedding-models",{"title":172,"path":173,"stem":174,"children":175,"icon":177},"API","\u002Fapi","6.api\u002F1.index",[176,178,183],{"title":172,"path":173,"stem":174,"icon":177},"i-lucide-code",{"title":179,"path":180,"stem":181,"icon":182},"Rust Crates (v5)","\u002Fapi\u002Fcore","6.api\u002F2.core","i-lucide-box",{"title":184,"path":185,"stem":186,"icon":182},"MCP Server","\u002Fapi\u002Fmcp-server","6.api\u002F4.mcp-server",{"title":188,"path":189,"stem":190,"icon":191},"Trending","\u002Ftrending","7.trending","i-lucide-trending-up",{"title":193,"path":194,"stem":195,"icon":196},"Research","\u002Fresearch","8.research","i-lucide-graduation-cap",{"title":198,"path":199,"stem":200,"icon":201},"Articles","\u002Farticles","9.articles","i-lucide-newspaper",{"id":203,"title":88,"body":204,"description":3761,"extension":2973,"links":3762,"meta":3763,"navigation":3764,"path":89,"seo":3765,"stem":90,"__hash__":3768},"docs\u002F2.guides\u002F8.compare.md",{"type":205,"value":206,"toc":3733},"minimark",[207,223,233,252,270,275,339,344,439,457,461,472,624,631,657,661,669,692,697,703,707,710,740,751,755,783,787,803,807,858,873,877,910,913,917,938,943,949,965,998,1002,1005,1069,1091,1095,1118,1138,2705,2820,2824,2837,2840,2844,2850,2916,2922,2935,2939,2962,2968,3211,3218,3222,3244,3253,3263,3266,3270,3273,3297,3306,3310,3319,3330,3334,3337,3341,3357,3510,3518,3568,3571,3575,3601,3617,3620,3649,3652,3655,3661,3664,3672,3676,3729],[208,209,210,214,215,218,219,222],"p",{},[211,212,213],"code",{},"jscpd --compare A B"," pairs every function of folder ",[211,216,217],{},"A"," with the function of folder ",[211,220,221],{},"B"," that does the same job, in one language or across two. One report answers two questions:",[224,225,226,230],"ul",{},[227,228,229],"li",{},"During a port, such as a library moving to another language or an iOS app moving to Android, which functions of the source already have a version in the target, and which are still to port?",[227,231,232],{},"For two implementations of one app, such as the Android and the iOS one, what do both have, and what does only one of them have?",[208,234,235,236,239,240,246,247,251],{},"This page runs ",[211,237,238],{},"--compare"," on a small port and goes through every report it writes. To follow along in a browser, open ",[241,242,245],"a",{"href":243,"target":244},"\u002Fexamples\u002Fcompare-demo.html","_blank","the demo's migration map",", or ",[241,248,250],{"href":249,"target":244},"\u002Fexamples\u002Fcompare-tauri.html","a larger one"," that compares ten Tauri plugins across Android and iOS.",[253,254,255,256,260,261,263,264,269],"note",{},"Available from jscpd ",[257,258,259],"strong",{},"5.4.0"," and experimental. ",[211,262,238],{}," pairs functions with the code embedding model of ",[241,265,266],{"href":84},[211,267,268],{},"--semantic",", which runs inside jscpd after a one-time download.",[271,272,274],"h2",{"id":273},"quick-start","Quick start",[276,277,283],"pre",{"className":278,"code":279,"filename":280,"language":281,"meta":282,"style":282},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","jscpd --semantic-download                     # once: fetches the model, 548 MB\njscpd --compare python\u002F typescript\u002F           # the source first, the target second\njscpd --compare python\u002F typescript\u002F -r html   # writes the migration map to report\u002F\n","Terminal","bash","",[211,284,285,302,319],{"__ignoreMap":282},[286,287,290,294,298],"span",{"class":288,"line":289},"line",1,[286,291,293],{"class":292},"sBMFI","jscpd",[286,295,297],{"class":296},"sfazB"," --semantic-download",[286,299,301],{"class":300},"sHwdD","                     # once: fetches the model, 548 MB\n",[286,303,305,307,310,313,316],{"class":288,"line":304},2,[286,306,293],{"class":292},[286,308,309],{"class":296}," --compare",[286,311,312],{"class":296}," python\u002F",[286,314,315],{"class":296}," typescript\u002F",[286,317,318],{"class":300},"           # the source first, the target second\n",[286,320,322,324,326,328,330,333,336],{"class":288,"line":321},3,[286,323,293],{"class":292},[286,325,309],{"class":296},[286,327,312],{"class":296},[286,329,315],{"class":296},[286,331,332],{"class":296}," -r",[286,334,335],{"class":296}," html",[286,337,338],{"class":300},"   # writes the migration map to report\u002F\n",[208,340,341,343],{},[211,342,238],{}," takes exactly two paths. In a port the first is the source, the code you port from, and the second is the target. For two implementations of one app the order only decides which side the reports list first and which side the map draws on the left.",[345,346,347,363],"table",{},[348,349,350],"thead",{},[351,352,353,357,360],"tr",{},[354,355,356],"th",{},"Reporter",[354,358,359],{},"Writes",[354,361,362],{},"Use it for",[364,365,366,381,394,409,424],"tbody",{},[351,367,368,375,378],{},[369,370,371,374],"td",{},[211,372,373],{},"console"," (default)",[369,376,377],{},"the summary, in the terminal",[369,379,380],{},"reading the result",[351,382,383,388,391],{},[369,384,385],{},[211,386,387],{},"console-full",[369,389,390],{},"the summary plus every pair",[369,392,393],{},"checking each pair",[351,395,396,401,406],{},[369,397,398],{},[211,399,400],{},"json",[369,402,403],{},[211,404,405],{},"jscpd-compare.json",[369,407,408],{},"scripts, CI and agents",[351,410,411,416,421],{},[369,412,413],{},[211,414,415],{},"markdown",[369,417,418],{},[211,419,420],{},"jscpd-compare.md",[369,422,423],{},"a pull request, an issue or a wiki page",[351,425,426,431,436],{},[369,427,428],{},[211,429,430],{},"html",[369,432,433],{},[211,434,435],{},"jscpd-compare.html",[369,437,438],{},"the migration map and the table of pairs",[208,440,441,444,445,448,449,452,453,456],{},[211,442,443],{},"-r"," takes several reporters at once, as in ",[211,446,447],{},"-r console,json,html",", and ",[211,450,451],{},"-o"," names the folder for the files, ",[211,454,455],{},"report\u002F"," by default. jscpd ignores other reporters with a warning. The exit code is 0 unless the run fails.",[271,458,460],{"id":459},"the-example","The example",[208,462,463,471],{},[241,464,468],{"href":465,"rel":466},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Ftree\u002Fmaster\u002Ffixtures\u002Fcompare-demo",[467],"nofollow",[211,469,470],{},"fixtures\u002Fcompare-demo"," in the jscpd repository holds a billing module halfway through its port from Python to TypeScript:",[345,473,474,487],{},[348,475,476],{},[351,477,478,481,484],{},[354,479,480],{},"File",[354,482,483],{},"Functions",[354,485,486],{},"What happened in the port",[364,488,489,508,523,535,547,562,573,588,609],{},[351,490,491,496,505],{},[369,492,493],{},[211,494,495],{},"python\u002Fbilling.py",[369,497,498,501,502],{},[211,499,500],{},"line_total",", ",[211,503,504],{},"apply_discount",[369,506,507],{},"ported under the same names, in camelCase",[351,509,510,512,517],{},[369,511],{},[369,513,514],{},[211,515,516],{},"tax_for_region",[369,518,519,520],{},"ported as ",[211,521,522],{},"salesTax",[351,524,525,527,532],{},[369,526],{},[369,528,529],{},[211,530,531],{},"format_invoice_number",[369,533,534],{},"ported as a one-line arrow function",[351,536,537,539,544],{},[369,538],{},[369,540,541],{},[211,542,543],{},"due_date",[369,545,546],{},"not ported yet",[351,548,549,554,559],{},[369,550,551],{},[211,552,553],{},"python\u002Fshipping.py",[369,555,556],{},[211,557,558],{},"shipping_cost",[369,560,561],{},"ported",[351,563,564,566,571],{},[369,565],{},[369,567,568],{},[211,569,570],{},"estimate_delivery_days",[369,572,546],{},[351,574,575,580,585],{},[369,576,577],{},[211,578,579],{},"typescript\u002Fbilling.ts",[369,581,582],{},[211,583,584],{},"toCurrency",[369,586,587],{},"new in TypeScript, with no Python original",[351,589,590,595,598],{},[369,591,592],{},[211,593,594],{},"python\u002Ftest_billing.py",[369,596,597],{},"three pytest tests",[369,599,600,601,604,605,608],{},"ported to ",[211,602,603],{},"typescript\u002Fbilling.test.ts"," as ",[211,606,607],{},"it('…', () => …)"," cases",[351,610,611,613,618],{},[369,612],{},[369,614,615],{},[211,616,617],{},"test_due_date_skips_the_weekend",[369,619,620,621,623],{},"not ported yet, like ",[211,622,543],{}," itself",[208,625,626,627,630],{},"Every report below comes from this folder. Run the commands from inside it, since from the repository root jscpd would also load the repository's ",[211,628,629],{},".jscpd.json",":",[276,632,634],{"className":278,"code":633,"filename":280,"language":281,"meta":282,"style":282},"cd fixtures\u002Fcompare-demo\njscpd --compare python typescript\n",[211,635,636,645],{"__ignoreMap":282},[286,637,638,642],{"class":288,"line":289},[286,639,641],{"class":640},"s2Zo4","cd",[286,643,644],{"class":296}," fixtures\u002Fcompare-demo\n",[286,646,647,649,651,654],{"class":288,"line":304},[286,648,293],{"class":292},[286,650,309],{"class":296},[286,652,653],{"class":296}," python",[286,655,656],{"class":296}," typescript\n",[271,658,660],{"id":659},"the-console-report","The console report",[276,662,667],{"className":663,"code":665,"language":666,"meta":282},[664],"language-text","Code\n 71% 5 of 7 functions in python have a counterpart in typescript\n 80% 4 of 5 functions in typescript have a counterpart in python\n\npython\n  file         paired  similarity  counterpart\n  billing.py   4 \u002F 5   0.89        billing.ts\n  shipping.py  1 \u002F 2   0.91        shipping.ts\n\ntypescript\n  file         paired  similarity  counterpart\n  billing.ts   3 \u002F 4   0.90        billing.py\n  shipping.ts  1 \u002F 1   0.91        shipping.py\n\nPaired under other names (1):\n  python                        typescript              similarity\n  billing.py:28 tax_for_region  billing.ts:27 salesTax  0.87 high\n\nOnly in python (2):\n  billing.py (1)\n    46  due_date                6 lines\n  shipping.py (1)\n    18  estimate_delivery_days  8 lines\n\nOnly in typescript (1):\n  billing.ts (1)\n    39  toCurrency  8 lines\n\nTests\n 75% 3 of 4 tests in python have a counterpart in typescript\n100% 3 of 3 tests in typescript have a counterpart in python\n\npython\n  file             paired  similarity  counterpart\n  test_billing.py  3 \u002F 4   0.87        billing.test.ts\n\ntypescript\n  file             paired  similarity  counterpart\n  billing.test.ts  3 \u002F 3   0.87        test_billing.py\n\nOnly in python (1):\n  test_billing.py (1)\n    30  test_due_date_skips_the_weekend  7 lines\n","text",[211,668,665],{"__ignoreMap":282},[208,670,671,672,675,676,679,680,683,684,687,688,691],{},"The report has a block for the code and a block for the tests, and you read both the same way. In a terminal it is in color: levels are green for ",[211,673,674],{},"high",", yellow for ",[211,677,678],{},"medium"," and red for ",[211,681,682],{},"low",", and shares and ",[211,685,686],{},"paired"," counts are green when every function has a counterpart, yellow when some do and red when none do. ",[211,689,690],{},"--no-colors"," prints the plain text shown here.",[693,694,696],"h3",{"id":695},"the-two-share-lines","The two share lines",[208,698,699,700,702],{},"The first line of a block counts the functions of the source that have a counterpart in the target. Here 5 of the 7 Python functions have a TypeScript version, and during a port that line is your progress. The second line counts the other way: 4 of the 5 TypeScript functions have a Python original, and the fifth, ",[211,701,584],{},", is new. For a parity check, read both lines: each says how much of one side the other covers.",[693,704,706],{"id":705},"the-file-tables","The file tables",[208,708,709],{},"Each side gets a table with a row per file:",[224,711,712,722,734],{},[227,713,714,716,717,721],{},[211,715,686],{}," is how many of the file's functions have a counterpart, out of the functions that ",[241,718,720],{"href":719},"#what-counts-as-a-function","count",".",[227,723,724,727,728,730,731,721],{},[211,725,726],{},"similarity"," is the mean similarity of those pairs. When some of them are ",[211,729,682],{},", the column says how many, as in ",[211,732,733],{},"0.62, 1 low",[227,735,736,739],{},[211,737,738],{},"counterpart"," is the file on the other side that holds most of the counterparts.",[208,741,742,743,746,747,750],{},"So 4 of the 5 functions in ",[211,744,745],{},"billing.py"," have a counterpart in ",[211,748,749],{},"billing.ts",", at a mean similarity of 0.89. A file with no pairs leaves the last two columns empty.",[693,752,754],{"id":753},"paired-under-other-names","Paired under other names",[208,756,757,758,760,761,763,764,767,768,771,772,767,775,778,779,721],{},"These are the pairs whose names differ even when case and underscores are ignored. The demo has one: ",[211,759,516],{},", ported as ",[211,762,522],{},". Nobody finds these pairs by searching for a name, so the default report shows them. Renamed ports, constructors (",[211,765,766],{},"QrCode"," and ",[211,769,770],{},"__init__",") and platform names (",[211,773,774],{},"startWatch",[211,776,777],{},"watchPosition",") end up here. Each pair has its similarity and a ",[241,780,782],{"href":781},"#similarity-levels","level",[693,784,786],{"id":785},"only-in-python-only-in-typescript","Only in python, only in typescript",[208,788,789,790,767,792,794,795,797,798,802],{},"These lists hold the functions without a counterpart, grouped by file, each with its first line, name and length. In a port, \"Only in python\" is the work left: ",[211,791,543],{},[211,793,570],{},". \"Only in typescript\" is code that exists only in the target, here ",[211,796,584],{},". A function in these lists is either missing on the other side or has a counterpart that jscpd did not recognize, so ",[241,799,801],{"href":800},"#before-you-trust-the-numbers","check it"," before you call it missing.",[693,804,806],{"id":805},"the-tests-block","The tests block",[208,808,809,810,812,813,815,816,819,820,823,824,501,827,767,830,833,834,501,837,767,840,843,844,847,848,851,852,857],{},"jscpd measures tests apart from code and pairs a test only with a test, so the tests of ",[211,811,500],{}," never count as ",[211,814,500],{}," itself. It tells a test by the conventions of its language: ",[211,817,818],{},"test_billing.py"," is a pytest file and ",[211,821,822],{},"billing.test.ts"," a Vitest one. It also knows names such as ",[211,825,826],{},"*_test.go",[211,828,829],{},"*.spec.js",[211,831,832],{},"*Tests.swift",", folders such as ",[211,835,836],{},"tests\u002F",[211,838,839],{},"__tests__\u002F",[211,841,842],{},"src\u002Ftest\u002F",", and Rust's ",[211,845,846],{},"#[test]"," functions and ",[211,849,850],{},"#[cfg(test)]"," modules. The ",[241,853,856],{"href":854,"rel":855},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fblob\u002Fmaster\u002Fdocs\u002Frust.md#comparing-two-codebases-with---compare-experimental",[467],"full list"," is in the reference. When neither side has tests, the report shows the code alone, without the two headings.",[208,859,860,861,864,865,868,869,872],{},"The TypeScript tests are ",[211,862,863],{},"it('line total sums quantity times price', () => …)"," callbacks. jscpd names such a test case after its title and compares test names without case, underscores, spaces, punctuation and a leading ",[211,866,867],{},"test_",". The title meets the pytest function ",[211,870,871],{},"test_line_total_sums_quantity_times_price",", and the report does not list the pair as renamed.",[693,874,876],{"id":875},"what-counts-as-a-function","What counts as a function",[208,878,879,880,882,883,886,887,890,891,894,895,898,899,501,901,903,904,906,907,909],{},"The ",[211,881,749],{}," row says ",[211,884,885],{},"3 \u002F 4",", though the file holds five functions. The fifth, ",[211,888,889],{},"formatInvoiceNumber",", is a one-line arrow function, shorter than the bar for counting. A side's totals count the functions of at least ",[211,892,893],{},"--min-tokens"," tokens and ",[211,896,897],{},"--min-lines"," lines, the first and the last line included. With ",[211,900,238],{},[211,902,893],{}," defaults to 30 instead of 50, because a function worth porting is often shorter than a clone worth reporting, and ",[211,905,897],{}," stays at 5. A shorter function still shows up as the partner of one that counts, as ",[211,908,889],{}," does in the next section.",[208,911,912],{},"Anonymous functions, such as callbacks and closures, take no part. JavaScript and TypeScript test cases are the exception, since they go by their titles.",[271,914,916],{"id":915},"every-pair-console-full","Every pair: console-full",[276,918,920],{"className":278,"code":919,"filename":280,"language":281,"meta":282,"style":282},"jscpd --compare python typescript -r console-full\n",[211,921,922],{"__ignoreMap":282},[286,923,924,926,928,930,933,935],{"class":288,"line":289},[286,925,293],{"class":292},[286,927,309],{"class":296},[286,929,653],{"class":296},[286,931,932],{"class":296}," typescript",[286,934,332],{"class":296},[286,936,937],{"class":296}," console-full\n",[208,939,940,942],{},[211,941,387],{}," prints the console report and ends each block with the list of every pair:",[276,944,947],{"className":945,"code":946,"language":666,"meta":282},[664],"Code\n...\nPairs (5):\n  python                               typescript                         similarity\n  billing.py:8 line_total              billing.ts:10 lineTotal            0.89 high\n  billing.py:18 apply_discount         billing.ts:19 applyDiscount        0.93 high\n  billing.py:28 tax_for_region         billing.ts:27 salesTax             0.87 high\n  billing.py:38 format_invoice_number  billing.ts:36 formatInvoiceNumber  0.89 high   by name\n  shipping.py:6 shipping_cost          shipping.ts:5 shippingCost         0.91 high\n\nTests\n...\nPairs (3):\n  python                                                       typescript                                              similarity\n  test_billing.py:8 test_line_total_sums_quantity_times_price  billing.test.ts:6 line total sums quantity times price  0.84 high\n  test_billing.py:15 test_line_total_rejects_a_zero_quantity   billing.test.ts:13 line total rejects a zero quantity   0.91 high\n  test_billing.py:23 test_discount_is_capped                   billing.test.ts:19 discount is capped                   0.84 high\n",[211,948,946],{"__ignoreMap":282},[208,950,951,952,954,955,959,960,767,962,964],{},"jscpd finds pairs in two steps. The first pairs functions by their code with the rule of ",[211,953,268],{},": each function is the other's closest match or close to it, their similarity reaches the threshold, and it ",[241,956,958],{"href":957},"\u002Fguides\u002Fsemantic-clones#the-z-score","stands out"," from each function's similarities to the rest of the other side. ",[211,961,516],{},[211,963,522],{}," paired in this step, on their code alone.",[208,966,967,968,501,971,501,974,977,978,980,981,767,984,987,988,990,991,993,994,997],{},"The second step takes the functions left over and pairs two whose names are the same apart from case and underscores (",[211,969,970],{},"encodeBinary",[211,972,973],{},"encode_binary",[211,975,976],{},"_encode_binary","), if their similarity reaches the ",[211,979,678],{}," level. That bar keeps namesakes such as ",[211,982,983],{},"load",[211,985,986],{},"init"," from pairing whatever they do. The step takes functions of any size, since a port often makes a function shorter, so ",[211,989,889],{}," pairs with ",[211,992,531],{}," here and the list marks the pair ",[211,995,996],{},"by name",". A name pair also stays within the modules that the code pairs link, such as one plugin's Android and iOS folders.",[693,999,1001],{"id":1000},"similarity-levels","Similarity levels",[208,1003,1004],{},"Every pair has its cosine similarity and a level. The level is on the scale of the model, since a cosine that is high for one model is low for another. For the default model, CodeRankEmbed:",[345,1006,1007,1023],{},[348,1008,1009],{},[351,1010,1011,1014,1017,1020],{},[354,1012,1013],{},"Level",[354,1015,1016],{},"Across languages",[354,1018,1019],{},"Within one language",[354,1021,1022],{},"What it means",[364,1024,1025,1039,1054],{},[351,1026,1027,1031,1034,1036],{},[369,1028,1029],{},[211,1030,674],{},[369,1032,1033],{},"0.7125 and up",[369,1035,1033],{},[369,1037,1038],{},"almost always the same function",[351,1040,1041,1045,1048,1051],{},[369,1042,1043],{},[211,1044,678],{},[369,1046,1047],{},"0.5625 to 0.7125",[369,1049,1050],{},"0.675 to 0.7125",[369,1052,1053],{},"usually the same function, restructured",[351,1055,1056,1060,1063,1066],{},[369,1057,1058],{},[211,1059,682],{},[369,1061,1062],{},"0.4125 to 0.5625",[369,1064,1065],{},"0.6375 to 0.675",[369,1067,1068],{},"read both: related code pairs here too",[208,1070,1071,1073,1074,1076,1077,1079,1080,1082,1083,1086,1087,1090],{},[211,1072,682],{}," starts at the pair threshold, the lowest similarity at which jscpd pairs two functions. ",[211,1075,674],{}," starts at the group floor of the ",[211,1078,268],{}," rules, or at the threshold when a model's threshold is higher, and ",[211,1081,678],{}," starts halfway between the two. Another model has other numbers. ",[241,1084,83],{"href":1085},"\u002Fguides\u002Fsemantic-clones#thresholds"," explains the thresholds, and ",[211,1088,1089],{},"jscpd --semantic-models"," lists them for each model.",[271,1092,1094],{"id":1093},"the-json-report","The JSON report",[276,1096,1098],{"className":278,"code":1097,"filename":280,"language":281,"meta":282,"style":282},"jscpd --compare python typescript -r json   # writes report\u002Fjscpd-compare.json\n",[211,1099,1100],{"__ignoreMap":282},[286,1101,1102,1104,1106,1108,1110,1112,1115],{"class":288,"line":289},[286,1103,293],{"class":292},[286,1105,309],{"class":296},[286,1107,653],{"class":296},[286,1109,932],{"class":296},[286,1111,332],{"class":296},[286,1113,1114],{"class":296}," json",[286,1116,1117],{"class":300},"   # writes report\u002Fjscpd-compare.json\n",[208,1119,1120,1121,1123,1124,767,1126,1129,1130,1133,1134,1137],{},"The JSON report holds everything ",[211,1122,387],{}," shows, plus the functions ready to port, in two sections of the same shape, ",[211,1125,211],{},[211,1127,1128],{},"tests",". Each section has the two ",[211,1131,1132],{},"sides",", the source first, and the ",[211,1135,1136],{},"pairs",". This is the code section of the demo, cut to two of its five pairs:",[276,1139,1143],{"className":1140,"code":1141,"filename":1142,"language":400,"meta":282,"style":282},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"code\": {\n    \"sides\": [\n      {\n        \"path\": \"python\",\n        \"functions\": 7,\n        \"matched\": 5,\n        \"percentage\": 71.43,\n        \"files\": [\n          { \"file\": \"billing.py\", \"functions\": 5, \"matched\": 4, \"counterpart\": \"billing.ts\", \"similarity\": 0.89, \"lowPairs\": 0 },\n          { \"file\": \"shipping.py\", \"functions\": 2, \"matched\": 1, \"counterpart\": \"shipping.ts\", \"similarity\": 0.91, \"lowPairs\": 0 }\n        ],\n        \"unmatched\": [\n          { \"file\": \"billing.py\", \"name\": \"due_date\", \"start\": 46, \"end\": 51 },\n          { \"file\": \"shipping.py\", \"name\": \"estimate_delivery_days\", \"start\": 18, \"end\": 25 }\n        ],\n        \"readyToPort\": [\n          { \"file\": \"billing.py\", \"name\": \"due_date\", \"start\": 46, \"end\": 51, \"callers\": 1 },\n          { \"file\": \"shipping.py\", \"name\": \"estimate_delivery_days\", \"start\": 18, \"end\": 25, \"callers\": 0 }\n        ]\n      },\n      {\n        \"path\": \"typescript\",\n        \"functions\": 5,\n        \"matched\": 4,\n        \"percentage\": 80.0,\n        \"files\": [\n          { \"file\": \"billing.ts\", \"functions\": 4, \"matched\": 3, \"counterpart\": \"billing.py\", \"similarity\": 0.9, \"lowPairs\": 0 },\n          { \"file\": \"shipping.ts\", \"functions\": 1, \"matched\": 1, \"counterpart\": \"shipping.py\", \"similarity\": 0.91, \"lowPairs\": 0 }\n        ],\n        \"unmatched\": [\n          { \"file\": \"billing.ts\", \"name\": \"toCurrency\", \"start\": 39, \"end\": 46 }\n        ],\n        \"readyToPort\": [\n          { \"file\": \"billing.ts\", \"name\": \"toCurrency\", \"start\": 39, \"end\": 46, \"callers\": 0 }\n        ]\n      }\n    ],\n    \"pairs\": [\n      {\n        \"a\": { \"file\": \"billing.py\", \"name\": \"tax_for_region\", \"start\": 28, \"end\": 35 },\n        \"b\": { \"file\": \"billing.ts\", \"name\": \"salesTax\", \"start\": 27, \"end\": 34 },\n        \"similarity\": 0.868,\n        \"level\": \"high\",\n        \"renamed\": true,\n        \"matchedBy\": \"code\"\n      },\n      {\n        \"a\": { \"file\": \"billing.py\", \"name\": \"format_invoice_number\", \"start\": 38, \"end\": 43 },\n        \"b\": { \"file\": \"billing.ts\", \"name\": \"formatInvoiceNumber\", \"start\": 36, \"end\": 37 },\n        \"similarity\": 0.889,\n        \"level\": \"high\",\n        \"renamed\": false,\n        \"matchedBy\": \"name\"\n      }\n    ]\n  }\n}\n","report\u002Fjscpd-compare.json",[211,1144,1145,1151,1167,1181,1187,1212,1229,1246,1263,1277,1371,1462,1468,1482,1548,1611,1616,1630,1704,1777,1783,1789,1794,1814,1829,1844,1860,1873,1960,2045,2050,2063,2125,2130,2143,2216,2221,2227,2233,2246,2251,2323,2395,2411,2430,2445,2464,2469,2474,2545,2616,2632,2651,2665,2682,2687,2693,2699],{"__ignoreMap":282},[286,1146,1147],{"class":288,"line":289},[286,1148,1150],{"class":1149},"sMK4o","{\n",[286,1152,1153,1156,1159,1162,1164],{"class":288,"line":304},[286,1154,1155],{"class":1149},"  \"",[286,1157,211],{"class":1158},"spNyl",[286,1160,1161],{"class":1149},"\"",[286,1163,630],{"class":1149},[286,1165,1166],{"class":1149}," {\n",[286,1168,1169,1172,1174,1176,1178],{"class":288,"line":321},[286,1170,1171],{"class":1149},"    \"",[286,1173,1132],{"class":292},[286,1175,1161],{"class":1149},[286,1177,630],{"class":1149},[286,1179,1180],{"class":1149}," [\n",[286,1182,1184],{"class":288,"line":1183},4,[286,1185,1186],{"class":1149},"      {\n",[286,1188,1190,1193,1197,1199,1201,1204,1207,1209],{"class":288,"line":1189},5,[286,1191,1192],{"class":1149},"        \"",[286,1194,1196],{"class":1195},"sbssI","path",[286,1198,1161],{"class":1149},[286,1200,630],{"class":1149},[286,1202,1203],{"class":1149}," \"",[286,1205,1206],{"class":296},"python",[286,1208,1161],{"class":1149},[286,1210,1211],{"class":1149},",\n",[286,1213,1215,1217,1220,1222,1224,1227],{"class":288,"line":1214},6,[286,1216,1192],{"class":1149},[286,1218,1219],{"class":1195},"functions",[286,1221,1161],{"class":1149},[286,1223,630],{"class":1149},[286,1225,1226],{"class":1195}," 7",[286,1228,1211],{"class":1149},[286,1230,1232,1234,1237,1239,1241,1244],{"class":288,"line":1231},7,[286,1233,1192],{"class":1149},[286,1235,1236],{"class":1195},"matched",[286,1238,1161],{"class":1149},[286,1240,630],{"class":1149},[286,1242,1243],{"class":1195}," 5",[286,1245,1211],{"class":1149},[286,1247,1249,1251,1254,1256,1258,1261],{"class":288,"line":1248},8,[286,1250,1192],{"class":1149},[286,1252,1253],{"class":1195},"percentage",[286,1255,1161],{"class":1149},[286,1257,630],{"class":1149},[286,1259,1260],{"class":1195}," 71.43",[286,1262,1211],{"class":1149},[286,1264,1266,1268,1271,1273,1275],{"class":288,"line":1265},9,[286,1267,1192],{"class":1149},[286,1269,1270],{"class":1195},"files",[286,1272,1161],{"class":1149},[286,1274,630],{"class":1149},[286,1276,1180],{"class":1149},[286,1278,1280,1283,1285,1289,1291,1293,1295,1297,1299,1302,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1325,1327,1329,1331,1333,1335,1337,1339,1341,1343,1345,1347,1349,1351,1354,1356,1358,1361,1363,1365,1368],{"class":288,"line":1279},10,[286,1281,1282],{"class":1149},"          {",[286,1284,1203],{"class":1149},[286,1286,1288],{"class":1287},"swJcz","file",[286,1290,1161],{"class":1149},[286,1292,630],{"class":1149},[286,1294,1203],{"class":1149},[286,1296,745],{"class":296},[286,1298,1161],{"class":1149},[286,1300,1301],{"class":1149},",",[286,1303,1203],{"class":1149},[286,1305,1219],{"class":1287},[286,1307,1161],{"class":1149},[286,1309,630],{"class":1149},[286,1311,1243],{"class":1195},[286,1313,1301],{"class":1149},[286,1315,1203],{"class":1149},[286,1317,1236],{"class":1287},[286,1319,1161],{"class":1149},[286,1321,630],{"class":1149},[286,1323,1324],{"class":1195}," 4",[286,1326,1301],{"class":1149},[286,1328,1203],{"class":1149},[286,1330,738],{"class":1287},[286,1332,1161],{"class":1149},[286,1334,630],{"class":1149},[286,1336,1203],{"class":1149},[286,1338,749],{"class":296},[286,1340,1161],{"class":1149},[286,1342,1301],{"class":1149},[286,1344,1203],{"class":1149},[286,1346,726],{"class":1287},[286,1348,1161],{"class":1149},[286,1350,630],{"class":1149},[286,1352,1353],{"class":1195}," 0.89",[286,1355,1301],{"class":1149},[286,1357,1203],{"class":1149},[286,1359,1360],{"class":1287},"lowPairs",[286,1362,1161],{"class":1149},[286,1364,630],{"class":1149},[286,1366,1367],{"class":1195}," 0",[286,1369,1370],{"class":1149}," },\n",[286,1372,1374,1376,1378,1380,1382,1384,1386,1389,1391,1393,1395,1397,1399,1401,1404,1406,1408,1410,1412,1414,1417,1419,1421,1423,1425,1427,1429,1432,1434,1436,1438,1440,1442,1444,1447,1449,1451,1453,1455,1457,1459],{"class":288,"line":1373},11,[286,1375,1282],{"class":1149},[286,1377,1203],{"class":1149},[286,1379,1288],{"class":1287},[286,1381,1161],{"class":1149},[286,1383,630],{"class":1149},[286,1385,1203],{"class":1149},[286,1387,1388],{"class":296},"shipping.py",[286,1390,1161],{"class":1149},[286,1392,1301],{"class":1149},[286,1394,1203],{"class":1149},[286,1396,1219],{"class":1287},[286,1398,1161],{"class":1149},[286,1400,630],{"class":1149},[286,1402,1403],{"class":1195}," 2",[286,1405,1301],{"class":1149},[286,1407,1203],{"class":1149},[286,1409,1236],{"class":1287},[286,1411,1161],{"class":1149},[286,1413,630],{"class":1149},[286,1415,1416],{"class":1195}," 1",[286,1418,1301],{"class":1149},[286,1420,1203],{"class":1149},[286,1422,738],{"class":1287},[286,1424,1161],{"class":1149},[286,1426,630],{"class":1149},[286,1428,1203],{"class":1149},[286,1430,1431],{"class":296},"shipping.ts",[286,1433,1161],{"class":1149},[286,1435,1301],{"class":1149},[286,1437,1203],{"class":1149},[286,1439,726],{"class":1287},[286,1441,1161],{"class":1149},[286,1443,630],{"class":1149},[286,1445,1446],{"class":1195}," 0.91",[286,1448,1301],{"class":1149},[286,1450,1203],{"class":1149},[286,1452,1360],{"class":1287},[286,1454,1161],{"class":1149},[286,1456,630],{"class":1149},[286,1458,1367],{"class":1195},[286,1460,1461],{"class":1149}," }\n",[286,1463,1465],{"class":288,"line":1464},12,[286,1466,1467],{"class":1149},"        ],\n",[286,1469,1471,1473,1476,1478,1480],{"class":288,"line":1470},13,[286,1472,1192],{"class":1149},[286,1474,1475],{"class":1195},"unmatched",[286,1477,1161],{"class":1149},[286,1479,630],{"class":1149},[286,1481,1180],{"class":1149},[286,1483,1485,1487,1489,1491,1493,1495,1497,1499,1501,1503,1505,1508,1510,1512,1514,1516,1518,1520,1522,1525,1527,1529,1532,1534,1536,1539,1541,1543,1546],{"class":288,"line":1484},14,[286,1486,1282],{"class":1149},[286,1488,1203],{"class":1149},[286,1490,1288],{"class":1287},[286,1492,1161],{"class":1149},[286,1494,630],{"class":1149},[286,1496,1203],{"class":1149},[286,1498,745],{"class":296},[286,1500,1161],{"class":1149},[286,1502,1301],{"class":1149},[286,1504,1203],{"class":1149},[286,1506,1507],{"class":1287},"name",[286,1509,1161],{"class":1149},[286,1511,630],{"class":1149},[286,1513,1203],{"class":1149},[286,1515,543],{"class":296},[286,1517,1161],{"class":1149},[286,1519,1301],{"class":1149},[286,1521,1203],{"class":1149},[286,1523,1524],{"class":1287},"start",[286,1526,1161],{"class":1149},[286,1528,630],{"class":1149},[286,1530,1531],{"class":1195}," 46",[286,1533,1301],{"class":1149},[286,1535,1203],{"class":1149},[286,1537,1538],{"class":1287},"end",[286,1540,1161],{"class":1149},[286,1542,630],{"class":1149},[286,1544,1545],{"class":1195}," 51",[286,1547,1370],{"class":1149},[286,1549,1551,1553,1555,1557,1559,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579,1581,1583,1585,1587,1589,1591,1593,1596,1598,1600,1602,1604,1606,1609],{"class":288,"line":1550},15,[286,1552,1282],{"class":1149},[286,1554,1203],{"class":1149},[286,1556,1288],{"class":1287},[286,1558,1161],{"class":1149},[286,1560,630],{"class":1149},[286,1562,1203],{"class":1149},[286,1564,1388],{"class":296},[286,1566,1161],{"class":1149},[286,1568,1301],{"class":1149},[286,1570,1203],{"class":1149},[286,1572,1507],{"class":1287},[286,1574,1161],{"class":1149},[286,1576,630],{"class":1149},[286,1578,1203],{"class":1149},[286,1580,570],{"class":296},[286,1582,1161],{"class":1149},[286,1584,1301],{"class":1149},[286,1586,1203],{"class":1149},[286,1588,1524],{"class":1287},[286,1590,1161],{"class":1149},[286,1592,630],{"class":1149},[286,1594,1595],{"class":1195}," 18",[286,1597,1301],{"class":1149},[286,1599,1203],{"class":1149},[286,1601,1538],{"class":1287},[286,1603,1161],{"class":1149},[286,1605,630],{"class":1149},[286,1607,1608],{"class":1195}," 25",[286,1610,1461],{"class":1149},[286,1612,1614],{"class":288,"line":1613},16,[286,1615,1467],{"class":1149},[286,1617,1619,1621,1624,1626,1628],{"class":288,"line":1618},17,[286,1620,1192],{"class":1149},[286,1622,1623],{"class":1195},"readyToPort",[286,1625,1161],{"class":1149},[286,1627,630],{"class":1149},[286,1629,1180],{"class":1149},[286,1631,1633,1635,1637,1639,1641,1643,1645,1647,1649,1651,1653,1655,1657,1659,1661,1663,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683,1685,1687,1689,1691,1693,1696,1698,1700,1702],{"class":288,"line":1632},18,[286,1634,1282],{"class":1149},[286,1636,1203],{"class":1149},[286,1638,1288],{"class":1287},[286,1640,1161],{"class":1149},[286,1642,630],{"class":1149},[286,1644,1203],{"class":1149},[286,1646,745],{"class":296},[286,1648,1161],{"class":1149},[286,1650,1301],{"class":1149},[286,1652,1203],{"class":1149},[286,1654,1507],{"class":1287},[286,1656,1161],{"class":1149},[286,1658,630],{"class":1149},[286,1660,1203],{"class":1149},[286,1662,543],{"class":296},[286,1664,1161],{"class":1149},[286,1666,1301],{"class":1149},[286,1668,1203],{"class":1149},[286,1670,1524],{"class":1287},[286,1672,1161],{"class":1149},[286,1674,630],{"class":1149},[286,1676,1531],{"class":1195},[286,1678,1301],{"class":1149},[286,1680,1203],{"class":1149},[286,1682,1538],{"class":1287},[286,1684,1161],{"class":1149},[286,1686,630],{"class":1149},[286,1688,1545],{"class":1195},[286,1690,1301],{"class":1149},[286,1692,1203],{"class":1149},[286,1694,1695],{"class":1287},"callers",[286,1697,1161],{"class":1149},[286,1699,630],{"class":1149},[286,1701,1416],{"class":1195},[286,1703,1370],{"class":1149},[286,1705,1707,1709,1711,1713,1715,1717,1719,1721,1723,1725,1727,1729,1731,1733,1735,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771,1773,1775],{"class":288,"line":1706},19,[286,1708,1282],{"class":1149},[286,1710,1203],{"class":1149},[286,1712,1288],{"class":1287},[286,1714,1161],{"class":1149},[286,1716,630],{"class":1149},[286,1718,1203],{"class":1149},[286,1720,1388],{"class":296},[286,1722,1161],{"class":1149},[286,1724,1301],{"class":1149},[286,1726,1203],{"class":1149},[286,1728,1507],{"class":1287},[286,1730,1161],{"class":1149},[286,1732,630],{"class":1149},[286,1734,1203],{"class":1149},[286,1736,570],{"class":296},[286,1738,1161],{"class":1149},[286,1740,1301],{"class":1149},[286,1742,1203],{"class":1149},[286,1744,1524],{"class":1287},[286,1746,1161],{"class":1149},[286,1748,630],{"class":1149},[286,1750,1595],{"class":1195},[286,1752,1301],{"class":1149},[286,1754,1203],{"class":1149},[286,1756,1538],{"class":1287},[286,1758,1161],{"class":1149},[286,1760,630],{"class":1149},[286,1762,1608],{"class":1195},[286,1764,1301],{"class":1149},[286,1766,1203],{"class":1149},[286,1768,1695],{"class":1287},[286,1770,1161],{"class":1149},[286,1772,630],{"class":1149},[286,1774,1367],{"class":1195},[286,1776,1461],{"class":1149},[286,1778,1780],{"class":288,"line":1779},20,[286,1781,1782],{"class":1149},"        ]\n",[286,1784,1786],{"class":288,"line":1785},21,[286,1787,1788],{"class":1149},"      },\n",[286,1790,1792],{"class":288,"line":1791},22,[286,1793,1186],{"class":1149},[286,1795,1797,1799,1801,1803,1805,1807,1810,1812],{"class":288,"line":1796},23,[286,1798,1192],{"class":1149},[286,1800,1196],{"class":1195},[286,1802,1161],{"class":1149},[286,1804,630],{"class":1149},[286,1806,1203],{"class":1149},[286,1808,1809],{"class":296},"typescript",[286,1811,1161],{"class":1149},[286,1813,1211],{"class":1149},[286,1815,1817,1819,1821,1823,1825,1827],{"class":288,"line":1816},24,[286,1818,1192],{"class":1149},[286,1820,1219],{"class":1195},[286,1822,1161],{"class":1149},[286,1824,630],{"class":1149},[286,1826,1243],{"class":1195},[286,1828,1211],{"class":1149},[286,1830,1832,1834,1836,1838,1840,1842],{"class":288,"line":1831},25,[286,1833,1192],{"class":1149},[286,1835,1236],{"class":1195},[286,1837,1161],{"class":1149},[286,1839,630],{"class":1149},[286,1841,1324],{"class":1195},[286,1843,1211],{"class":1149},[286,1845,1847,1849,1851,1853,1855,1858],{"class":288,"line":1846},26,[286,1848,1192],{"class":1149},[286,1850,1253],{"class":1195},[286,1852,1161],{"class":1149},[286,1854,630],{"class":1149},[286,1856,1857],{"class":1195}," 80.0",[286,1859,1211],{"class":1149},[286,1861,1863,1865,1867,1869,1871],{"class":288,"line":1862},27,[286,1864,1192],{"class":1149},[286,1866,1270],{"class":1195},[286,1868,1161],{"class":1149},[286,1870,630],{"class":1149},[286,1872,1180],{"class":1149},[286,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896,1898,1900,1902,1904,1906,1908,1910,1912,1914,1917,1919,1921,1923,1925,1927,1929,1931,1933,1935,1937,1939,1941,1943,1946,1948,1950,1952,1954,1956,1958],{"class":288,"line":1875},28,[286,1877,1282],{"class":1149},[286,1879,1203],{"class":1149},[286,1881,1288],{"class":1287},[286,1883,1161],{"class":1149},[286,1885,630],{"class":1149},[286,1887,1203],{"class":1149},[286,1889,749],{"class":296},[286,1891,1161],{"class":1149},[286,1893,1301],{"class":1149},[286,1895,1203],{"class":1149},[286,1897,1219],{"class":1287},[286,1899,1161],{"class":1149},[286,1901,630],{"class":1149},[286,1903,1324],{"class":1195},[286,1905,1301],{"class":1149},[286,1907,1203],{"class":1149},[286,1909,1236],{"class":1287},[286,1911,1161],{"class":1149},[286,1913,630],{"class":1149},[286,1915,1916],{"class":1195}," 3",[286,1918,1301],{"class":1149},[286,1920,1203],{"class":1149},[286,1922,738],{"class":1287},[286,1924,1161],{"class":1149},[286,1926,630],{"class":1149},[286,1928,1203],{"class":1149},[286,1930,745],{"class":296},[286,1932,1161],{"class":1149},[286,1934,1301],{"class":1149},[286,1936,1203],{"class":1149},[286,1938,726],{"class":1287},[286,1940,1161],{"class":1149},[286,1942,630],{"class":1149},[286,1944,1945],{"class":1195}," 0.9",[286,1947,1301],{"class":1149},[286,1949,1203],{"class":1149},[286,1951,1360],{"class":1287},[286,1953,1161],{"class":1149},[286,1955,630],{"class":1149},[286,1957,1367],{"class":1195},[286,1959,1370],{"class":1149},[286,1961,1963,1965,1967,1969,1971,1973,1975,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995,1997,1999,2001,2003,2005,2007,2009,2011,2013,2015,2017,2019,2021,2023,2025,2027,2029,2031,2033,2035,2037,2039,2041,2043],{"class":288,"line":1962},29,[286,1964,1282],{"class":1149},[286,1966,1203],{"class":1149},[286,1968,1288],{"class":1287},[286,1970,1161],{"class":1149},[286,1972,630],{"class":1149},[286,1974,1203],{"class":1149},[286,1976,1431],{"class":296},[286,1978,1161],{"class":1149},[286,1980,1301],{"class":1149},[286,1982,1203],{"class":1149},[286,1984,1219],{"class":1287},[286,1986,1161],{"class":1149},[286,1988,630],{"class":1149},[286,1990,1416],{"class":1195},[286,1992,1301],{"class":1149},[286,1994,1203],{"class":1149},[286,1996,1236],{"class":1287},[286,1998,1161],{"class":1149},[286,2000,630],{"class":1149},[286,2002,1416],{"class":1195},[286,2004,1301],{"class":1149},[286,2006,1203],{"class":1149},[286,2008,738],{"class":1287},[286,2010,1161],{"class":1149},[286,2012,630],{"class":1149},[286,2014,1203],{"class":1149},[286,2016,1388],{"class":296},[286,2018,1161],{"class":1149},[286,2020,1301],{"class":1149},[286,2022,1203],{"class":1149},[286,2024,726],{"class":1287},[286,2026,1161],{"class":1149},[286,2028,630],{"class":1149},[286,2030,1446],{"class":1195},[286,2032,1301],{"class":1149},[286,2034,1203],{"class":1149},[286,2036,1360],{"class":1287},[286,2038,1161],{"class":1149},[286,2040,630],{"class":1149},[286,2042,1367],{"class":1195},[286,2044,1461],{"class":1149},[286,2046,2048],{"class":288,"line":2047},30,[286,2049,1467],{"class":1149},[286,2051,2053,2055,2057,2059,2061],{"class":288,"line":2052},31,[286,2054,1192],{"class":1149},[286,2056,1475],{"class":1195},[286,2058,1161],{"class":1149},[286,2060,630],{"class":1149},[286,2062,1180],{"class":1149},[286,2064,2066,2068,2070,2072,2074,2076,2078,2080,2082,2084,2086,2088,2090,2092,2094,2096,2098,2100,2102,2104,2106,2108,2111,2113,2115,2117,2119,2121,2123],{"class":288,"line":2065},32,[286,2067,1282],{"class":1149},[286,2069,1203],{"class":1149},[286,2071,1288],{"class":1287},[286,2073,1161],{"class":1149},[286,2075,630],{"class":1149},[286,2077,1203],{"class":1149},[286,2079,749],{"class":296},[286,2081,1161],{"class":1149},[286,2083,1301],{"class":1149},[286,2085,1203],{"class":1149},[286,2087,1507],{"class":1287},[286,2089,1161],{"class":1149},[286,2091,630],{"class":1149},[286,2093,1203],{"class":1149},[286,2095,584],{"class":296},[286,2097,1161],{"class":1149},[286,2099,1301],{"class":1149},[286,2101,1203],{"class":1149},[286,2103,1524],{"class":1287},[286,2105,1161],{"class":1149},[286,2107,630],{"class":1149},[286,2109,2110],{"class":1195}," 39",[286,2112,1301],{"class":1149},[286,2114,1203],{"class":1149},[286,2116,1538],{"class":1287},[286,2118,1161],{"class":1149},[286,2120,630],{"class":1149},[286,2122,1531],{"class":1195},[286,2124,1461],{"class":1149},[286,2126,2128],{"class":288,"line":2127},33,[286,2129,1467],{"class":1149},[286,2131,2133,2135,2137,2139,2141],{"class":288,"line":2132},34,[286,2134,1192],{"class":1149},[286,2136,1623],{"class":1195},[286,2138,1161],{"class":1149},[286,2140,630],{"class":1149},[286,2142,1180],{"class":1149},[286,2144,2146,2148,2150,2152,2154,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174,2176,2178,2180,2182,2184,2186,2188,2190,2192,2194,2196,2198,2200,2202,2204,2206,2208,2210,2212,2214],{"class":288,"line":2145},35,[286,2147,1282],{"class":1149},[286,2149,1203],{"class":1149},[286,2151,1288],{"class":1287},[286,2153,1161],{"class":1149},[286,2155,630],{"class":1149},[286,2157,1203],{"class":1149},[286,2159,749],{"class":296},[286,2161,1161],{"class":1149},[286,2163,1301],{"class":1149},[286,2165,1203],{"class":1149},[286,2167,1507],{"class":1287},[286,2169,1161],{"class":1149},[286,2171,630],{"class":1149},[286,2173,1203],{"class":1149},[286,2175,584],{"class":296},[286,2177,1161],{"class":1149},[286,2179,1301],{"class":1149},[286,2181,1203],{"class":1149},[286,2183,1524],{"class":1287},[286,2185,1161],{"class":1149},[286,2187,630],{"class":1149},[286,2189,2110],{"class":1195},[286,2191,1301],{"class":1149},[286,2193,1203],{"class":1149},[286,2195,1538],{"class":1287},[286,2197,1161],{"class":1149},[286,2199,630],{"class":1149},[286,2201,1531],{"class":1195},[286,2203,1301],{"class":1149},[286,2205,1203],{"class":1149},[286,2207,1695],{"class":1287},[286,2209,1161],{"class":1149},[286,2211,630],{"class":1149},[286,2213,1367],{"class":1195},[286,2215,1461],{"class":1149},[286,2217,2219],{"class":288,"line":2218},36,[286,2220,1782],{"class":1149},[286,2222,2224],{"class":288,"line":2223},37,[286,2225,2226],{"class":1149},"      }\n",[286,2228,2230],{"class":288,"line":2229},38,[286,2231,2232],{"class":1149},"    ],\n",[286,2234,2236,2238,2240,2242,2244],{"class":288,"line":2235},39,[286,2237,1171],{"class":1149},[286,2239,1136],{"class":292},[286,2241,1161],{"class":1149},[286,2243,630],{"class":1149},[286,2245,1180],{"class":1149},[286,2247,2249],{"class":288,"line":2248},40,[286,2250,1186],{"class":1149},[286,2252,2254,2256,2258,2260,2262,2265,2267,2269,2271,2273,2275,2277,2279,2281,2283,2285,2287,2289,2291,2293,2295,2297,2299,2301,2303,2305,2308,2310,2312,2314,2316,2318,2321],{"class":288,"line":2253},41,[286,2255,1192],{"class":1149},[286,2257,241],{"class":1195},[286,2259,1161],{"class":1149},[286,2261,630],{"class":1149},[286,2263,2264],{"class":1149}," {",[286,2266,1203],{"class":1149},[286,2268,1288],{"class":1287},[286,2270,1161],{"class":1149},[286,2272,630],{"class":1149},[286,2274,1203],{"class":1149},[286,2276,745],{"class":296},[286,2278,1161],{"class":1149},[286,2280,1301],{"class":1149},[286,2282,1203],{"class":1149},[286,2284,1507],{"class":1287},[286,2286,1161],{"class":1149},[286,2288,630],{"class":1149},[286,2290,1203],{"class":1149},[286,2292,516],{"class":296},[286,2294,1161],{"class":1149},[286,2296,1301],{"class":1149},[286,2298,1203],{"class":1149},[286,2300,1524],{"class":1287},[286,2302,1161],{"class":1149},[286,2304,630],{"class":1149},[286,2306,2307],{"class":1195}," 28",[286,2309,1301],{"class":1149},[286,2311,1203],{"class":1149},[286,2313,1538],{"class":1287},[286,2315,1161],{"class":1149},[286,2317,630],{"class":1149},[286,2319,2320],{"class":1195}," 35",[286,2322,1370],{"class":1149},[286,2324,2326,2328,2331,2333,2335,2337,2339,2341,2343,2345,2347,2349,2351,2353,2355,2357,2359,2361,2363,2365,2367,2369,2371,2373,2375,2377,2380,2382,2384,2386,2388,2390,2393],{"class":288,"line":2325},42,[286,2327,1192],{"class":1149},[286,2329,2330],{"class":1195},"b",[286,2332,1161],{"class":1149},[286,2334,630],{"class":1149},[286,2336,2264],{"class":1149},[286,2338,1203],{"class":1149},[286,2340,1288],{"class":1287},[286,2342,1161],{"class":1149},[286,2344,630],{"class":1149},[286,2346,1203],{"class":1149},[286,2348,749],{"class":296},[286,2350,1161],{"class":1149},[286,2352,1301],{"class":1149},[286,2354,1203],{"class":1149},[286,2356,1507],{"class":1287},[286,2358,1161],{"class":1149},[286,2360,630],{"class":1149},[286,2362,1203],{"class":1149},[286,2364,522],{"class":296},[286,2366,1161],{"class":1149},[286,2368,1301],{"class":1149},[286,2370,1203],{"class":1149},[286,2372,1524],{"class":1287},[286,2374,1161],{"class":1149},[286,2376,630],{"class":1149},[286,2378,2379],{"class":1195}," 27",[286,2381,1301],{"class":1149},[286,2383,1203],{"class":1149},[286,2385,1538],{"class":1287},[286,2387,1161],{"class":1149},[286,2389,630],{"class":1149},[286,2391,2392],{"class":1195}," 34",[286,2394,1370],{"class":1149},[286,2396,2398,2400,2402,2404,2406,2409],{"class":288,"line":2397},43,[286,2399,1192],{"class":1149},[286,2401,726],{"class":1195},[286,2403,1161],{"class":1149},[286,2405,630],{"class":1149},[286,2407,2408],{"class":1195}," 0.868",[286,2410,1211],{"class":1149},[286,2412,2414,2416,2418,2420,2422,2424,2426,2428],{"class":288,"line":2413},44,[286,2415,1192],{"class":1149},[286,2417,782],{"class":1195},[286,2419,1161],{"class":1149},[286,2421,630],{"class":1149},[286,2423,1203],{"class":1149},[286,2425,674],{"class":296},[286,2427,1161],{"class":1149},[286,2429,1211],{"class":1149},[286,2431,2433,2435,2438,2440,2442],{"class":288,"line":2432},45,[286,2434,1192],{"class":1149},[286,2436,2437],{"class":1195},"renamed",[286,2439,1161],{"class":1149},[286,2441,630],{"class":1149},[286,2443,2444],{"class":1149}," true,\n",[286,2446,2448,2450,2453,2455,2457,2459,2461],{"class":288,"line":2447},46,[286,2449,1192],{"class":1149},[286,2451,2452],{"class":1195},"matchedBy",[286,2454,1161],{"class":1149},[286,2456,630],{"class":1149},[286,2458,1203],{"class":1149},[286,2460,211],{"class":296},[286,2462,2463],{"class":1149},"\"\n",[286,2465,2467],{"class":288,"line":2466},47,[286,2468,1788],{"class":1149},[286,2470,2472],{"class":288,"line":2471},48,[286,2473,1186],{"class":1149},[286,2475,2477,2479,2481,2483,2485,2487,2489,2491,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513,2515,2517,2519,2521,2523,2525,2527,2530,2532,2534,2536,2538,2540,2543],{"class":288,"line":2476},49,[286,2478,1192],{"class":1149},[286,2480,241],{"class":1195},[286,2482,1161],{"class":1149},[286,2484,630],{"class":1149},[286,2486,2264],{"class":1149},[286,2488,1203],{"class":1149},[286,2490,1288],{"class":1287},[286,2492,1161],{"class":1149},[286,2494,630],{"class":1149},[286,2496,1203],{"class":1149},[286,2498,745],{"class":296},[286,2500,1161],{"class":1149},[286,2502,1301],{"class":1149},[286,2504,1203],{"class":1149},[286,2506,1507],{"class":1287},[286,2508,1161],{"class":1149},[286,2510,630],{"class":1149},[286,2512,1203],{"class":1149},[286,2514,531],{"class":296},[286,2516,1161],{"class":1149},[286,2518,1301],{"class":1149},[286,2520,1203],{"class":1149},[286,2522,1524],{"class":1287},[286,2524,1161],{"class":1149},[286,2526,630],{"class":1149},[286,2528,2529],{"class":1195}," 38",[286,2531,1301],{"class":1149},[286,2533,1203],{"class":1149},[286,2535,1538],{"class":1287},[286,2537,1161],{"class":1149},[286,2539,630],{"class":1149},[286,2541,2542],{"class":1195}," 43",[286,2544,1370],{"class":1149},[286,2546,2548,2550,2552,2554,2556,2558,2560,2562,2564,2566,2568,2570,2572,2574,2576,2578,2580,2582,2584,2586,2588,2590,2592,2594,2596,2598,2601,2603,2605,2607,2609,2611,2614],{"class":288,"line":2547},50,[286,2549,1192],{"class":1149},[286,2551,2330],{"class":1195},[286,2553,1161],{"class":1149},[286,2555,630],{"class":1149},[286,2557,2264],{"class":1149},[286,2559,1203],{"class":1149},[286,2561,1288],{"class":1287},[286,2563,1161],{"class":1149},[286,2565,630],{"class":1149},[286,2567,1203],{"class":1149},[286,2569,749],{"class":296},[286,2571,1161],{"class":1149},[286,2573,1301],{"class":1149},[286,2575,1203],{"class":1149},[286,2577,1507],{"class":1287},[286,2579,1161],{"class":1149},[286,2581,630],{"class":1149},[286,2583,1203],{"class":1149},[286,2585,889],{"class":296},[286,2587,1161],{"class":1149},[286,2589,1301],{"class":1149},[286,2591,1203],{"class":1149},[286,2593,1524],{"class":1287},[286,2595,1161],{"class":1149},[286,2597,630],{"class":1149},[286,2599,2600],{"class":1195}," 36",[286,2602,1301],{"class":1149},[286,2604,1203],{"class":1149},[286,2606,1538],{"class":1287},[286,2608,1161],{"class":1149},[286,2610,630],{"class":1149},[286,2612,2613],{"class":1195}," 37",[286,2615,1370],{"class":1149},[286,2617,2619,2621,2623,2625,2627,2630],{"class":288,"line":2618},51,[286,2620,1192],{"class":1149},[286,2622,726],{"class":1195},[286,2624,1161],{"class":1149},[286,2626,630],{"class":1149},[286,2628,2629],{"class":1195}," 0.889",[286,2631,1211],{"class":1149},[286,2633,2635,2637,2639,2641,2643,2645,2647,2649],{"class":288,"line":2634},52,[286,2636,1192],{"class":1149},[286,2638,782],{"class":1195},[286,2640,1161],{"class":1149},[286,2642,630],{"class":1149},[286,2644,1203],{"class":1149},[286,2646,674],{"class":296},[286,2648,1161],{"class":1149},[286,2650,1211],{"class":1149},[286,2652,2654,2656,2658,2660,2662],{"class":288,"line":2653},53,[286,2655,1192],{"class":1149},[286,2657,2437],{"class":1195},[286,2659,1161],{"class":1149},[286,2661,630],{"class":1149},[286,2663,2664],{"class":1149}," false,\n",[286,2666,2668,2670,2672,2674,2676,2678,2680],{"class":288,"line":2667},54,[286,2669,1192],{"class":1149},[286,2671,2452],{"class":1195},[286,2673,1161],{"class":1149},[286,2675,630],{"class":1149},[286,2677,1203],{"class":1149},[286,2679,1507],{"class":296},[286,2681,2463],{"class":1149},[286,2683,2685],{"class":288,"line":2684},55,[286,2686,2226],{"class":1149},[286,2688,2690],{"class":288,"line":2689},56,[286,2691,2692],{"class":1149},"    ]\n",[286,2694,2696],{"class":288,"line":2695},57,[286,2697,2698],{"class":1149},"  }\n",[286,2700,2702],{"class":288,"line":2701},58,[286,2703,2704],{"class":1149},"}\n",[345,2706,2707,2717],{},[348,2708,2709],{},[351,2710,2711,2714],{},[354,2712,2713],{},"Field",[354,2715,2716],{},"What it holds",[364,2718,2719,2728,2741,2755,2764,2773,2786,2797,2806],{},[351,2720,2721,2725],{},[369,2722,2723],{},[211,2724,1196],{},[369,2726,2727],{},"the path as given on the command line",[351,2729,2730,2738],{},[369,2731,2732,501,2734,501,2736],{},[211,2733,1219],{},[211,2735,1236],{},[211,2737,1253],{},[369,2739,2740],{},"the share line: the functions that count, those with a counterpart, and the share in percent",[351,2742,2743,2747],{},[369,2744,2745],{},[211,2746,1270],{},[369,2748,2749,2750,2752,2753],{},"the file table; a file with no pairs has no ",[211,2751,738],{}," and no ",[211,2754,726],{},[351,2756,2757,2761],{},[369,2758,2759],{},[211,2760,1475],{},[369,2762,2763],{},"the \"Only in\" list, with the first and the last line of each function",[351,2765,2766,2770],{},[369,2767,2768],{},[211,2769,1623],{},[369,2771,2772],{},"the functions with no counterpart whose callees all have one, most called first",[351,2774,2775,2783],{},[369,2776,2777,501,2780],{},[211,2778,2779],{},"pairs[].a",[211,2781,2782],{},"pairs[].b",[369,2784,2785],{},"the function on the first side and its counterpart on the second",[351,2787,2788,2794],{},[369,2789,2790,501,2792],{},[211,2791,726],{},[211,2793,782],{},[369,2795,2796],{},"the cosine similarity and its level",[351,2798,2799,2803],{},[369,2800,2801],{},[211,2802,2437],{},[369,2804,2805],{},"whether the names differ when case and underscores are ignored",[351,2807,2808,2812],{},[369,2809,2810],{},[211,2811,2452],{},[369,2813,2814,2816,2817,2819],{},[211,2815,211],{}," for a pair from the first step, ",[211,2818,1507],{}," for one from the second",[693,2821,2823],{"id":2822},"ready-to-port","Ready to port",[208,2825,2826,2827,2830,2831,2833,2834,2836],{},"A function is ready to port when it has no counterpart yet and everything it calls has one, so porting it waits for nothing. jscpd finds calls by name: a name followed by ",[211,2828,2829],{},"("," in a function's code calls the functions of the same side with that name, in a language that can call it. A function in the caller's own file wins, and jscpd does not follow a name that more than three functions carry. Two unported functions that call each other wait for each other, so neither is ready. ",[211,2832,1695],{}," counts the functions and tests that call it: ",[211,2835,543],{}," has one, its test.",[208,2838,2839],{},"Each side has its own list. In a port you work through the source's list, and in a parity check each list holds what could move to the other side next.",[693,2841,2843],{"id":2842},"reading-it-from-a-script","Reading it from a script",[208,2845,2846,2847,630],{},"A CI job or an agent reads the JSON between two steps of a port, for example with ",[211,2848,2849],{},"jq",[276,2851,2853],{"className":278,"code":2852,"filename":280,"language":281,"meta":282,"style":282},"# the port's progress, in percent\njq '.code.sides[0].percentage' report\u002Fjscpd-compare.json\n# what to port next, one function per line\njq -r '.code.sides[0].readyToPort[] | \"\\(.file):\\(.start) \\(.name)\"' report\u002Fjscpd-compare.json\n# the pairs under other names, to check by hand\njq -r '.code.pairs[] | select(.renamed) | \"\\(.a.name) -> \\(.b.name) \\(.similarity) \\(.level)\"' report\u002Fjscpd-compare.json\n",[211,2854,2855,2860,2876,2881,2896,2901],{"__ignoreMap":282},[286,2856,2857],{"class":288,"line":289},[286,2858,2859],{"class":300},"# the port's progress, in percent\n",[286,2861,2862,2864,2867,2870,2873],{"class":288,"line":304},[286,2863,2849],{"class":292},[286,2865,2866],{"class":1149}," '",[286,2868,2869],{"class":296},".code.sides[0].percentage",[286,2871,2872],{"class":1149},"'",[286,2874,2875],{"class":296}," report\u002Fjscpd-compare.json\n",[286,2877,2878],{"class":288,"line":321},[286,2879,2880],{"class":300},"# what to port next, one function per line\n",[286,2882,2883,2885,2887,2889,2892,2894],{"class":288,"line":1183},[286,2884,2849],{"class":292},[286,2886,332],{"class":296},[286,2888,2866],{"class":1149},[286,2890,2891],{"class":296},".code.sides[0].readyToPort[] | \"\\(.file):\\(.start) \\(.name)\"",[286,2893,2872],{"class":1149},[286,2895,2875],{"class":296},[286,2897,2898],{"class":288,"line":1189},[286,2899,2900],{"class":300},"# the pairs under other names, to check by hand\n",[286,2902,2903,2905,2907,2909,2912,2914],{"class":288,"line":1214},[286,2904,2849],{"class":292},[286,2906,332],{"class":296},[286,2908,2866],{"class":1149},[286,2910,2911],{"class":296},".code.pairs[] | select(.renamed) | \"\\(.a.name) -> \\(.b.name) \\(.similarity) \\(.level)\"",[286,2913,2872],{"class":1149},[286,2915,2875],{"class":296},[276,2917,2920],{"className":2918,"code":2919,"language":666,"meta":282},[664],"71.43\nbilling.py:46 due_date\nshipping.py:18 estimate_delivery_days\ntax_for_region -> salesTax 0.868 high\n",[211,2921,2919],{"__ignoreMap":282},[208,2923,879,2924,2928,2929,2931,2932,2934],{},[241,2925,2927],{"href":2926},"\u002Fgetting-started\u002Fagent-skill#code-migration","code-migration skill"," runs this loop for an agent. It ports the tests first, then the code one function at a time, starting with ",[211,2930,1623],{},", and reruns ",[211,2933,238],{}," after each step to see the function leave the unmatched list and pair with the right counterpart.",[271,2936,2938],{"id":2937},"the-markdown-report","The Markdown report",[276,2940,2942],{"className":278,"code":2941,"filename":280,"language":281,"meta":282,"style":282},"jscpd --compare python typescript -r markdown   # writes report\u002Fjscpd-compare.md\n",[211,2943,2944],{"__ignoreMap":282},[286,2945,2946,2948,2950,2952,2954,2956,2959],{"class":288,"line":289},[286,2947,293],{"class":292},[286,2949,309],{"class":296},[286,2951,653],{"class":296},[286,2953,932],{"class":296},[286,2955,332],{"class":296},[286,2957,2958],{"class":296}," markdown",[286,2960,2961],{"class":300},"   # writes report\u002Fjscpd-compare.md\n",[208,2963,2964,2965,2967],{},"The Markdown report has the tables of ",[211,2966,387],{}," for a pull request description, an issue or a wiki page that tracks a port. The demo's report starts like this:",[276,2969,2974],{"className":2970,"code":2971,"filename":2972,"language":2973,"meta":282,"style":282},"language-md shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# `python` compared with `typescript`\n\n## Code\n\n| Side | Functions | With a counterpart | % |\n|---|--:|--:|--:|\n| `python` | 7 | 5 | 71.43 |\n| `typescript` | 5 | 4 | 80 |\n\n### `python`\n\n| File | With a counterpart | Similarity | Counterpart file |\n|---|--:|--:|---|\n| `billing.py` | 4 \u002F 5 | 0.89 | `billing.ts` |\n| `shipping.py` | 1 \u002F 2 | 0.91 | `shipping.ts` |\n","report\u002Fjscpd-compare.md","md",[211,2975,2976,2998,3004,3012,3016,3043,3048,3077,3103,3107,3118,3122,3145,3150,3181],{"__ignoreMap":282},[286,2977,2978,2981,2984,2986,2988,2991,2993,2995],{"class":288,"line":289},[286,2979,2980],{"class":1149},"# ",[286,2982,2983],{"class":1149},"`",[286,2985,1206],{"class":296},[286,2987,2983],{"class":1149},[286,2989,2990],{"class":292}," compared with ",[286,2992,2983],{"class":1149},[286,2994,1809],{"class":296},[286,2996,2997],{"class":1149},"`\n",[286,2999,3000],{"class":288,"line":304},[286,3001,3003],{"emptyLinePlaceholder":3002},true,"\n",[286,3005,3006,3009],{"class":288,"line":321},[286,3007,3008],{"class":1149},"## ",[286,3010,3011],{"class":292},"Code\n",[286,3013,3014],{"class":288,"line":1183},[286,3015,3003],{"emptyLinePlaceholder":3002},[286,3017,3018,3021,3025,3027,3030,3032,3035,3037,3040],{"class":288,"line":1189},[286,3019,3020],{"class":1149},"|",[286,3022,3024],{"class":3023},"sTEyZ"," Side ",[286,3026,3020],{"class":1149},[286,3028,3029],{"class":3023}," Functions ",[286,3031,3020],{"class":1149},[286,3033,3034],{"class":3023}," With a counterpart ",[286,3036,3020],{"class":1149},[286,3038,3039],{"class":3023}," % ",[286,3041,3042],{"class":1149},"|\n",[286,3044,3045],{"class":288,"line":1214},[286,3046,3047],{"class":1149},"|---|--:|--:|--:|\n",[286,3049,3050,3052,3055,3057,3059,3062,3065,3067,3070,3072,3075],{"class":288,"line":1231},[286,3051,3020],{"class":1149},[286,3053,3054],{"class":1149}," `",[286,3056,1206],{"class":296},[286,3058,2983],{"class":1149},[286,3060,3061],{"class":1149}," |",[286,3063,3064],{"class":3023}," 7 ",[286,3066,3020],{"class":1149},[286,3068,3069],{"class":3023}," 5 ",[286,3071,3020],{"class":1149},[286,3073,3074],{"class":3023}," 71.43 ",[286,3076,3042],{"class":1149},[286,3078,3079,3081,3083,3085,3087,3089,3091,3093,3096,3098,3101],{"class":288,"line":1248},[286,3080,3020],{"class":1149},[286,3082,3054],{"class":1149},[286,3084,1809],{"class":296},[286,3086,2983],{"class":1149},[286,3088,3061],{"class":1149},[286,3090,3069],{"class":3023},[286,3092,3020],{"class":1149},[286,3094,3095],{"class":3023}," 4 ",[286,3097,3020],{"class":1149},[286,3099,3100],{"class":3023}," 80 ",[286,3102,3042],{"class":1149},[286,3104,3105],{"class":288,"line":1265},[286,3106,3003],{"emptyLinePlaceholder":3002},[286,3108,3109,3112,3114,3116],{"class":288,"line":1279},[286,3110,3111],{"class":1149},"### ",[286,3113,2983],{"class":1149},[286,3115,1206],{"class":296},[286,3117,2997],{"class":1149},[286,3119,3120],{"class":288,"line":1373},[286,3121,3003],{"emptyLinePlaceholder":3002},[286,3123,3124,3126,3129,3131,3133,3135,3138,3140,3143],{"class":288,"line":1464},[286,3125,3020],{"class":1149},[286,3127,3128],{"class":3023}," File ",[286,3130,3020],{"class":1149},[286,3132,3034],{"class":3023},[286,3134,3020],{"class":1149},[286,3136,3137],{"class":3023}," Similarity ",[286,3139,3020],{"class":1149},[286,3141,3142],{"class":3023}," Counterpart file ",[286,3144,3042],{"class":1149},[286,3146,3147],{"class":288,"line":1470},[286,3148,3149],{"class":1149},"|---|--:|--:|---|\n",[286,3151,3152,3154,3156,3158,3160,3162,3165,3167,3170,3172,3174,3176,3178],{"class":288,"line":1484},[286,3153,3020],{"class":1149},[286,3155,3054],{"class":1149},[286,3157,745],{"class":296},[286,3159,2983],{"class":1149},[286,3161,3061],{"class":1149},[286,3163,3164],{"class":3023}," 4 \u002F 5 ",[286,3166,3020],{"class":1149},[286,3168,3169],{"class":3023}," 0.89 ",[286,3171,3020],{"class":1149},[286,3173,3054],{"class":1149},[286,3175,749],{"class":296},[286,3177,2983],{"class":1149},[286,3179,3180],{"class":1149}," |\n",[286,3182,3183,3185,3187,3189,3191,3193,3196,3198,3201,3203,3205,3207,3209],{"class":288,"line":1550},[286,3184,3020],{"class":1149},[286,3186,3054],{"class":1149},[286,3188,1388],{"class":296},[286,3190,2983],{"class":1149},[286,3192,3061],{"class":1149},[286,3194,3195],{"class":3023}," 1 \u002F 2 ",[286,3197,3020],{"class":1149},[286,3199,3200],{"class":3023}," 0.91 ",[286,3202,3020],{"class":1149},[286,3204,3054],{"class":1149},[286,3206,1431],{"class":296},[286,3208,2983],{"class":1149},[286,3210,3180],{"class":1149},[208,3212,3213,3214,3217],{},"It goes on with the table of the other side, then \"Only in\" tables with each function's place and length, the pairs under other names, and every pair with its similarity, level and the step that matched it. The ",[211,3215,3216],{},"## Tests"," section repeats the same tables for the tests.",[271,3219,3221],{"id":3220},"the-html-report-the-migration-map","The HTML report: the migration map",[276,3223,3225],{"className":278,"code":3224,"filename":280,"language":281,"meta":282,"style":282},"jscpd --compare python typescript -r html   # writes report\u002Fjscpd-compare.html\n",[211,3226,3227],{"__ignoreMap":282},[286,3228,3229,3231,3233,3235,3237,3239,3241],{"class":288,"line":289},[286,3230,293],{"class":292},[286,3232,309],{"class":296},[286,3234,653],{"class":296},[286,3236,932],{"class":296},[286,3238,332],{"class":296},[286,3240,335],{"class":296},[286,3242,3243],{"class":300},"   # writes report\u002Fjscpd-compare.html\n",[208,3245,3246,3248,3249,3252],{},[211,3247,435],{}," is one file with its styles, script and data inside, so it opens offline and can travel as a CI artifact or a ticket attachment. It shows the comparison as a map and as a table, with one set of filters for both. Open ",[241,3250,3251],{"href":243,"target":244},"the demo's report"," and click around while you read.",[3254,3255],"report-screenshot",{":height":3256,":width":3257,"alt":3258,"caption":3259,"dark":3260,"href":243,"light":3261,"link-text":3262},"1403","1560","The migration map of the demo: the Python side on the left with ported functions lining a central channel, dotted bridges to their TypeScript counterparts on the right, due_date and estimate_delivery_days at the far left with a dark ring, and toCurrency at the far right.","Python on the left, TypeScript on the right, a dotted bridge for every pair.","\u002Fimages\u002Fcompare\u002Fdemo-map-dark.webp","\u002Fimages\u002Fcompare\u002Fdemo-map-light.webp","Open the demo's map",[208,3264,3265],{},"The header gives both shares, the tests below them and the number of pairs in the middle. Under it, \"One mark per\" picks folders, files or functions, and the search box finds a file or a function. When the comparison has tests, \"Show\" picks code, tests or both, and the page opens with both.",[693,3267,3269],{"id":3268},"the-map","The map",[208,3271,3272],{},"The map draws the two sides as dependency graphs facing each other across a channel, the source in orange on the left and the target in green on the right. The labels across the top name the four bands: source functions not ported yet, ported ones lining the channel, target functions with a counterpart, and functions only in the target.",[224,3274,3275,3278,3281,3284,3291,3294],{},[227,3276,3277],{},"A mark is a function, a file or a folder. The page picks the level by the size of the comparison, and past 1,500 marks it asks for bigger marks or the table.",[227,3279,3280],{},"Code is a circle and a test is a square. With both shown, thin lines tie each test to the code it calls.",[227,3282,3283],{},"A mark fills from the bottom as its functions find counterparts. It is empty when none has one and full when all have.",[227,3285,3286,3287,767,3289,721],{},"A dark ring marks the source functions that are ready to port, here ",[211,3288,543],{},[211,3290,570],{},[227,3292,3293],{},"A dotted bridge stands for the pairs between two marks. Its color is their mean similarity, light blue at 0.40 and dark blue at 1.00, and it is thicker for more pairs. The dark theme turns the blue scale around, so the closest pairs stay the easiest to see.",[227,3295,3296],{},"Thin gray lines are calls within a side.",[208,3298,3299,3300,3302,3303,3305],{},"Hover a mark to light up what it calls and what it pairs with. Click it to list its functions with their counterparts, calls and callers: the panel for ",[211,3301,543],{}," says it is ready to port and that ",[211,3304,617],{}," calls it. Drag to move the map, and zoom with the − and + buttons or with Ctrl or ⌘ held while you scroll.",[693,3307,3309],{"id":3308},"the-table","The table",[3254,3311],{":height":3312,":width":3257,"alt":3313,"caption":3314,"dark":3315,"href":3316,"light":3317,"link-text":3318},"1227","The Table tab of the demo with Show set to Code: five ported pairs with their similarity, due_date and estimate_delivery_days marked Ready to port with No counterpart, and toCurrency marked Only in the target.","The Table tab with Show set to Code.","\u002Fimages\u002Fcompare\u002Fdemo-table-dark.webp","\u002Fexamples\u002Fcompare-demo.html#table","\u002Fimages\u002Fcompare\u002Fdemo-table-light.webp","Open the table",[208,3320,3321,3322,3325,3326,3329],{},"The Table tab lists the same bridges as rows: the source mark on the left, the similarity in the middle, the target mark on the right, and a status of ported, partly ported, ready to port, not ported or only in the target. A mark with no bridge gets a row of its own. Click a column header to sort the table. Click a row to open the pairs behind it and what its source mark still lacks, or, for a function, its pairs, calls and callers. The address keeps the tab, so a link that ends in ",[211,3323,3324],{},"#table",", like ",[241,3327,3328],{"href":3316,"target":244},"this one",", opens the table.",[693,3331,3333],{"id":3332},"below-the-map-and-the-table","Below the map and the table",[208,3335,3336],{},"Three more sections follow, for whatever the filters select. \"Ready to port\" lists those functions with the number of callers of each. \"How alike the pairs are\" charts the pairs by similarity in steps of 0.05, colored by level, with a switch to show the counts as a table. \"Progress by folder\" gives the share of each folder's functions that have a counterpart, on both sides.",[271,3338,3340],{"id":3339},"a-larger-map-android-and-ios","A larger map: Android and iOS",[208,3342,3343,3348,3349,3352,3353,3356],{},[241,3344,3347],{"href":3345,"rel":3346},"https:\u002F\u002Fgithub.com\u002Ftauri-apps\u002Fplugins-workspace",[467],"tauri-apps\u002Fplugins-workspace"," has ten plugins written for both Android, in Kotlin, and iOS, in Swift. ",[241,3350,3351],{"href":249,"target":244},"This report"," compares the two platforms as a parity check. jscpd 5.4.0 made it from commit ",[211,3354,3355],{},"d4835d0"," of 2026-09-30:",[276,3358,3360],{"className":278,"code":3359,"filename":280,"language":281,"meta":282,"style":282},"git clone https:\u002F\u002Fgithub.com\u002Ftauri-apps\u002Fplugins-workspace\ngit -C plugins-workspace checkout d4835d0\nmkdir android ios\nfor p in barcode-scanner biometric clipboard-manager dialog geolocation haptics nfc notification opener shell; do\n  cp -R plugins-workspace\u002Fplugins\u002F$p\u002Fandroid android\u002F$p\n  cp -R plugins-workspace\u002Fplugins\u002F$p\u002Fios ios\u002F$p\ndone\njscpd --compare android ios -r html\n",[211,3361,3362,3373,3389,3400,3448,3471,3489,3494],{"__ignoreMap":282},[286,3363,3364,3367,3370],{"class":288,"line":289},[286,3365,3366],{"class":292},"git",[286,3368,3369],{"class":296}," clone",[286,3371,3372],{"class":296}," https:\u002F\u002Fgithub.com\u002Ftauri-apps\u002Fplugins-workspace\n",[286,3374,3375,3377,3380,3383,3386],{"class":288,"line":304},[286,3376,3366],{"class":292},[286,3378,3379],{"class":296}," -C",[286,3381,3382],{"class":296}," plugins-workspace",[286,3384,3385],{"class":296}," checkout",[286,3387,3388],{"class":296}," d4835d0\n",[286,3390,3391,3394,3397],{"class":288,"line":321},[286,3392,3393],{"class":292},"mkdir",[286,3395,3396],{"class":296}," android",[286,3398,3399],{"class":296}," ios\n",[286,3401,3402,3406,3409,3412,3415,3418,3421,3424,3427,3430,3433,3436,3439,3442,3445],{"class":288,"line":1183},[286,3403,3405],{"class":3404},"s7zQu","for",[286,3407,3408],{"class":3023}," p ",[286,3410,3411],{"class":3404},"in",[286,3413,3414],{"class":296}," barcode-scanner",[286,3416,3417],{"class":296}," biometric",[286,3419,3420],{"class":296}," clipboard-manager",[286,3422,3423],{"class":296}," dialog",[286,3425,3426],{"class":296}," geolocation",[286,3428,3429],{"class":296}," haptics",[286,3431,3432],{"class":296}," nfc",[286,3434,3435],{"class":296}," notification",[286,3437,3438],{"class":296}," opener",[286,3440,3441],{"class":296}," shell",[286,3443,3444],{"class":1149},";",[286,3446,3447],{"class":3404}," do\n",[286,3449,3450,3453,3456,3459,3462,3465,3468],{"class":288,"line":1189},[286,3451,3452],{"class":292},"  cp",[286,3454,3455],{"class":296}," -R",[286,3457,3458],{"class":296}," plugins-workspace\u002Fplugins\u002F",[286,3460,3461],{"class":3023},"$p",[286,3463,3464],{"class":296},"\u002Fandroid",[286,3466,3467],{"class":296}," android\u002F",[286,3469,3470],{"class":3023},"$p\n",[286,3472,3473,3475,3477,3479,3481,3484,3487],{"class":288,"line":1214},[286,3474,3452],{"class":292},[286,3476,3455],{"class":296},[286,3478,3458],{"class":296},[286,3480,3461],{"class":3023},[286,3482,3483],{"class":296},"\u002Fios",[286,3485,3486],{"class":296}," ios\u002F",[286,3488,3470],{"class":3023},[286,3490,3491],{"class":288,"line":1231},[286,3492,3493],{"class":3404},"done\n",[286,3495,3496,3498,3500,3502,3505,3507],{"class":288,"line":1248},[286,3497,293],{"class":292},[286,3499,309],{"class":296},[286,3501,3396],{"class":296},[286,3503,3504],{"class":296}," ios",[286,3506,332],{"class":296},[286,3508,3509],{"class":296}," html\n",[3254,3511],{":height":3512,":width":3257,"alt":3513,"caption":3514,"dark":3515,"href":249,"light":3516,"link-text":3517},"1178","The migration map of ten Tauri plugins with one mark per folder: each Android plugin folder on the left joined by dotted bridges to the iOS folder of the same plugin on the right, with marks half filled.","Ten Tauri plugins, Android against iOS, one mark per folder.","\u002Fimages\u002Fcompare\u002Ftauri-map-dark.webp","\u002Fimages\u002Fcompare\u002Ftauri-map-light.webp","Open the Tauri map",[208,3519,3520,3521,3523,3524,3526,3527,3529,3530,767,3532,3534,3535,767,3538,3541,3542,3544,3545,3548,3549,3552,3553,3555,3556,3559,3560,3563,3564,3567],{},"Of the 147 Android functions, 60 have a counterpart on iOS, and 58 of the 106 iOS functions have one on Android. They make 63 pairs: 38 ",[211,3522,674],{},", 16 ",[211,3525,678],{}," and 9 ",[211,3528,682],{},". In 17 of them the two platforms name the function differently, such as ",[211,3531,774],{},[211,3533,777],{}," in geolocation or ",[211,3536,3537],{},"writeTag",[211,3539,3540],{},"writeNDEFTag"," in nfc, and all 9 ",[211,3543,682],{}," pairs are among those 17. One pair crosses plugins: ",[211,3546,3547],{},"permissionState"," of notification on Android with ",[211,3550,3551],{},"getPermissionState"," of barcode-scanner on iOS, at 0.485, marked ",[211,3554,682],{},". The \"Only in\" lists include the six functions of barcode-scanner's ",[211,3557,3558],{},"GraphicOverlay.kt"," on Android, the three of its ",[211,3561,3562],{},"CameraView.swift"," on iOS, and ",[211,3565,3566],{},"createChannel",", which builds an Android notification channel for the notification plugin.",[208,3569,3570],{},"The map labels the first path \"Source\" and the second \"Target\" whatever the comparison is. In a parity check that only sets which platform the map draws on the left.",[271,3572,3574],{"id":3573},"before-you-trust-the-numbers","Before you trust the numbers",[208,3576,3577,3578,3580,3581,3584,3585,3588,3589,3592,3593,3596,3597,3600],{},"Point ",[211,3579,238],{}," at the code, not at the repository roots. It walks every file under both paths that jscpd finds functions in, so the functions of build scripts, examples and benchmarks count too. Keep vendored dependencies and build output out of both paths as well. Inside a git repository jscpd reads ",[211,3582,3583],{},".gitignore",". Elsewhere, or for folders that the repository keeps, pass ",[211,3586,3587],{},"--ignore",", as in ",[211,3590,3591],{},"--ignore \"**\u002Fvendor\u002F**,**\u002Ftarget\u002F**\"",". A walk into ",[211,3594,3595],{},"node_modules"," or ",[211,3598,3599],{},"target\u002F"," also slows the run down, since jscpd embeds the functions it finds there.",[208,3602,3603,3604,3607,3608,3610,3611,3613,3614,3616],{},"Then read a sample of the pairs with ",[211,3605,3606],{},"-r console-full",". Two or three ",[211,3609,674],{}," pairs show whether the pairing works on this code. Read every ",[211,3612,682],{}," pair too, and every pair marked ",[211,3615,996],{},", since a function with the same name can do something else.",[208,3618,3619],{},"Before you call a function in an \"Only in\" list missing, search the other side for it: in its counterpart file, under another name, as part of a larger function, or replaced by a library or platform call. jscpd misses some pairs:",[224,3621,3622,3636,3646],{},[227,3623,3624,3625,3628,3629,3632,3633,3635],{},"constructors across languages, such as a Java constructor and Rust's ",[211,3626,3627],{},"new",", Kotlin's ",[211,3630,3631],{},"constructor"," or Swift's ",[211,3634,986],{},", pair only when their code is similar enough;",[227,3637,3638,3639,3642,3643,3444],{},"a short function renamed on the other side, such as ",[211,3640,3641],{},"add_history"," for ",[211,3644,3645],{},"_finder_penalty_add_history",[227,3647,3648],{},"when one function was split into several, or several merged into one, only the closest part may pair.",[208,3650,3651],{},"Some functions exist on one side by design: platform glue, such as an iOS delegate callback or an Android notification channel, helpers that one language needs and the other does not, and features that one side dropped.",[208,3653,3654],{},"An empty side is fine. At the start of a port the target has nothing yet, and jscpd prints the source's totals with a note:",[276,3656,3659],{"className":3657,"code":3658,"language":666,"meta":282},[664],"Code\n  0% 0 of 7 functions in python have a counterpart in typescript\ntypescript has no functions yet\n\nTests\n  0% 0 of 4 tests in python have a counterpart in typescript\ntypescript has no tests yet\n",[211,3660,3658],{"__ignoreMap":282},[208,3662,3663],{},"The JSON and Markdown reports still list every function of the source as unmatched, so they track a port from its first day.",[208,3665,3666,3668,3669,3671],{},[211,3667,238],{}," compares functions only, so types, constants and UI markup take no part. Similarity does not see small differences in behavior, so two versions that drifted apart still pair. The more the target is restructured, the fewer of its functions pair by code. Related code pairs too, such as a function that counts UTF-8 bytes and one that converts a string to them, which is what the ",[211,3670,682],{}," level warns about.",[271,3673,3675],{"id":3674},"more-information","More information",[224,3677,3678,3696,3714,3722],{},[227,3679,3680,3682,3683,3685,3686,3689,3690,3692,3693,721],{},[241,3681,83],{"href":84},": the model behind ",[211,3684,238],{},", the other models and their thresholds. Every ",[211,3687,3688],{},"--semantic-*"," option applies to ",[211,3691,238],{}," except ",[211,3694,3695],{},"--semantic-scope",[227,3697,3698,3702,3703,3706,3707,3710,3711,3713],{},[241,3699,3701],{"href":3700},"\u002Fgetting-started\u002Fagent-skill#compare-codebases","Agent skills",": ",[211,3704,3705],{},"compare-codebases"," runs and explains a comparison, and ",[211,3708,3709],{},"code-migration"," ports a codebase tests first with ",[211,3712,238],{}," as the progress measure.",[227,3715,3716,3702,3719,3721],{},[241,3717,21],{"href":3718},"\u002Fgetting-started\u002Fconfiguration#comparing-two-codebases",[211,3720,238],{}," in the table of options.",[227,3723,3724,3728],{},[241,3725,3727],{"href":854,"rel":3726},[467],"The reference in docs\u002Frust.md",": how the pairing works in detail, and how jscpd tells a test from code in each language.",[3730,3731,3732],"style",{},"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}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 .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 .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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":282,"searchDepth":304,"depth":304,"links":3734},[3735,3736,3737,3745,3748,3752,3753,3758,3759,3760],{"id":273,"depth":304,"text":274},{"id":459,"depth":304,"text":460},{"id":659,"depth":304,"text":660,"children":3738},[3739,3740,3741,3742,3743,3744],{"id":695,"depth":321,"text":696},{"id":705,"depth":321,"text":706},{"id":753,"depth":321,"text":754},{"id":785,"depth":321,"text":786},{"id":805,"depth":321,"text":806},{"id":875,"depth":321,"text":876},{"id":915,"depth":304,"text":916,"children":3746},[3747],{"id":1000,"depth":321,"text":1001},{"id":1093,"depth":304,"text":1094,"children":3749},[3750,3751],{"id":2822,"depth":321,"text":2823},{"id":2842,"depth":321,"text":2843},{"id":2937,"depth":304,"text":2938},{"id":3220,"depth":304,"text":3221,"children":3754},[3755,3756,3757],{"id":3268,"depth":321,"text":3269},{"id":3308,"depth":321,"text":3309},{"id":3332,"depth":321,"text":3333},{"id":3339,"depth":304,"text":3340},{"id":3573,"depth":304,"text":3574},{"id":3674,"depth":304,"text":3675},"Measure a port to another language, or check two implementations of one app for parity, with jscpd --compare: example reports in the console, JSON, Markdown and HTML, and how to read each one.",null,{},{"icon":91},{"title":3766,"description":3767},"Compare Two Codebases Function by Function with jscpd --compare","jscpd --compare pairs the functions of two folders, in one language or across two, and lists what each side has that the other lacks. Example console, JSON, Markdown and HTML reports, with a live migration map.","r7LTCHSjBnikfmwF8GrP8LlYxUX3S6EJlR88Dzkx1-s",[3770,3772],{"title":83,"path":84,"stem":85,"description":3771,"icon":86,"children":-1},"Find functions that do the same job with different code, in one language or across languages, with jscpd --semantic and a code embedding model.",{"title":93,"path":94,"stem":95,"description":3773,"icon":98,"children":-1},"Integrate jscpd into your CI pipeline and git hooks.",1791007955268]