[{"data":1,"prerenderedAt":1812},["ShallowReactive",2],{"navigation_docs":3,"blog-post-jscpd-5-4-3":249,"blog-views-jscpd-5-4-3":1809},[4,29,104,124,194],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"Start",false,"\u002Fstart","1.start",[10,14,19,24],{"title":11,"path":7,"stem":12,"icon":13},"What jscpd finds","1.start\u002Findex","i-lucide-house",{"title":15,"path":16,"stem":17,"icon":18},"Installation","\u002Fstart\u002Finstallation","1.start\u002F2.installation","i-lucide-download",{"title":20,"path":21,"stem":22,"icon":23},"Quickstart","\u002Fstart\u002Fquickstart","1.start\u002F3.quickstart","i-lucide-rocket",{"title":25,"path":26,"stem":27,"icon":28},"Configuration basics","\u002Fstart\u002Fconfiguration","1.start\u002F4.configuration","i-lucide-settings-2",{"title":30,"icon":6,"path":31,"stem":32,"children":33,"page":6},"Guides","\u002Fguides","2.guides",[34,39,44,49,54,59,64,69,74,79,84,89,94,99],{"title":35,"path":36,"stem":37,"icon":38},"Use jscpd in CI","\u002Fguides\u002Fci","2.guides\u002F01.ci","i-lucide-github",{"title":40,"path":41,"stem":42,"icon":43},"Pre-commit hooks","\u002Fguides\u002Fpre-commit","2.guides\u002F02.pre-commit","i-lucide-git-commit",{"title":45,"path":46,"stem":47,"icon":48},"Fail only on new duplication","\u002Fguides\u002Fbaseline","2.guides\u002F03.baseline","i-lucide-git-compare",{"title":50,"path":51,"stem":52,"icon":53},"Monorepos","\u002Fguides\u002Fmonorepos","2.guides\u002F04.monorepos","i-lucide-folder-tree",{"title":55,"path":56,"stem":57,"icon":58},"Cross-format detection","\u002Fguides\u002Fcross-format","2.guides\u002F05.cross-format","i-lucide-layers",{"title":60,"path":61,"stem":62,"icon":63},"Agents","\u002Fguides\u002Fagents","2.guides\u002F06.agents","i-lucide-cpu",{"title":65,"path":66,"stem":67,"icon":68},"Editors","\u002Fguides\u002Feditors","2.guides\u002F07.editors","i-lucide-code",{"title":70,"path":71,"stem":72,"icon":73},"Duplication over git history","\u002Fguides\u002Fhistory","2.guides\u002F08.history","i-lucide-chart-no-axes-combined",{"title":75,"path":76,"stem":77,"icon":78},"Dashboard and health score","\u002Fguides\u002Fdashboard","2.guides\u002F09.dashboard","i-lucide-layout-dashboard",{"title":80,"path":81,"stem":82,"icon":83},"Dead code","\u002Fguides\u002Fdead-code","2.guides\u002F10.dead-code","i-lucide-ghost",{"title":85,"path":86,"stem":87,"icon":88},"Comparing two codebases","\u002Fguides\u002Fcompare","2.guides\u002F11.compare","i-lucide-git-compare-arrows",{"title":90,"path":91,"stem":92,"icon":93},"Semantic clones","\u002Fguides\u002Fsemantic-clones","2.guides\u002F12.semantic-clones","i-lucide-brain-circuit",{"title":95,"path":96,"stem":97,"icon":98},"Similar functions","\u002Fguides\u002Fsimilarity","2.guides\u002F13.similarity","i-lucide-list-tree",{"title":100,"path":101,"stem":102,"icon":103},"Boundaries","\u002Fguides\u002Fboundaries","2.guides\u002F14.boundaries","i-lucide-fence",{"title":105,"icon":6,"path":106,"stem":107,"children":108,"page":6},"Concepts","\u002Fconcepts","3.concepts",[109,114,119],{"title":110,"path":111,"stem":112,"icon":113},"Types of code clones","\u002Fconcepts\u002Fclone-types","3.concepts\u002F1.clone-types","i-lucide-copy",{"title":115,"path":116,"stem":117,"icon":118},"How detection works","\u002Fconcepts\u002Fhow-detection-works","3.concepts\u002F2.how-detection-works","i-lucide-scan-search",{"title":120,"path":121,"stem":122,"icon":123},"The health score","\u002Fconcepts\u002Fhealth-score","3.concepts\u002F3.health-score","i-lucide-heart-pulse",{"title":125,"icon":6,"path":126,"stem":127,"children":128,"page":6},"Reference","\u002Freference","4.reference",[129,134,139,144,181,186,190],{"title":130,"path":131,"stem":132,"icon":133},"CLI options","\u002Freference\u002Fcli","4.reference\u002F1.cli","i-lucide-terminal",{"title":135,"path":136,"stem":137,"icon":138},"The config file","\u002Freference\u002Fconfig-file","4.reference\u002F2.config-file","i-lucide-settings",{"title":140,"path":141,"stem":142,"icon":143},"Exit codes","\u002Freference\u002Fexit-codes","4.reference\u002F3.exit-codes","i-lucide-log-out",{"title":145,"icon":6,"path":146,"stem":147,"children":148},"Reporters","\u002Freference\u002Freporters","4.reference\u002F4.reporters\u002Findex",[149,151,156,161,166,171,176],{"title":145,"path":146,"stem":147,"icon":150},"i-lucide-file-chart-column",{"title":152,"path":153,"stem":154,"icon":155},"HTML reporter","\u002Freference\u002Freporters\u002Fhtml","4.reference\u002F4.reporters\u002F2.html","i-lucide-file-code",{"title":157,"path":158,"stem":159,"icon":160},"JSON reporter","\u002Freference\u002Freporters\u002Fjson","4.reference\u002F4.reporters\u002F3.json","i-lucide-braces",{"title":162,"path":163,"stem":164,"icon":165},"Badge reporter","\u002Freference\u002Freporters\u002Fbadge","4.reference\u002F4.reporters\u002F4.badge","i-lucide-award",{"title":167,"path":168,"stem":169,"icon":170},"SARIF reporter","\u002Freference\u002Freporters\u002Fsarif","4.reference\u002F4.reporters\u002F5.sarif","i-lucide-shield-check",{"title":172,"path":173,"stem":174,"icon":175},"CodeClimate reporter","\u002Freference\u002Freporters\u002Fcodeclimate","4.reference\u002F4.reporters\u002F6.codeclimate","i-lucide-flag-triangle-right",{"title":177,"path":178,"stem":179,"icon":180},"OpenMetrics reporter","\u002Freference\u002Freporters\u002Fopenmetrics","4.reference\u002F4.reporters\u002F7.openmetrics","i-lucide-activity",{"title":182,"path":183,"stem":184,"icon":185},"Supported formats","\u002Freference\u002Fsupported-formats","4.reference\u002F5.supported-formats","i-lucide-languages",{"title":187,"path":188,"stem":189,"icon":38},"GitHub Action","\u002Freference\u002Fgithub-action","4.reference\u002F6.github-action",{"title":191,"path":192,"stem":193,"icon":68},"Rust crates","\u002Freference\u002Frust-crates","4.reference\u002F7.rust-crates",{"title":195,"icon":6,"path":196,"stem":197,"children":198,"page":6},"Project","\u002Fproject","5.project",[199,204,209,214,239,244],{"title":200,"path":201,"stem":202,"icon":203},"Changelog","\u002Fproject\u002Fchangelog","5.project\u002F1.changelog","i-lucide-scroll-text",{"title":205,"path":206,"stem":207,"icon":208},"Migrating from v4 to v5","\u002Fproject\u002Fmigration","5.project\u002F2.migration","i-lucide-arrow-right-left",{"title":210,"path":211,"stem":212,"icon":213},"jscpd v4 (TypeScript)","\u002Fproject\u002Fv4","5.project\u002F3.v4","i-simple-icons-typescript",{"title":215,"icon":6,"path":216,"stem":217,"children":218},"Benchmarks","\u002Fproject\u002Fbenchmarks","5.project\u002F4.benchmarks\u002Findex",[219,221,226,230,235],{"title":215,"path":216,"stem":217,"icon":220},"i-lucide-gauge",{"title":222,"path":223,"stem":224,"icon":225},"Detection Speed","\u002Fproject\u002Fbenchmarks\u002Fdetection-speed","5.project\u002F4.benchmarks\u002F2.detection-speed","i-lucide-zap",{"title":227,"path":228,"stem":229,"icon":58},"Multi-Format Detection","\u002Fproject\u002Fbenchmarks\u002Fcross-format","5.project\u002F4.benchmarks\u002F3.cross-format",{"title":231,"path":232,"stem":233,"icon":234},"AI Token Efficiency","\u002Fproject\u002Fbenchmarks\u002Fai-token-efficiency","5.project\u002F4.benchmarks\u002F4.ai-token-efficiency","i-lucide-sparkles",{"title":236,"path":237,"stem":238,"icon":93},"Embedding Models","\u002Fproject\u002Fbenchmarks\u002Fembedding-models","5.project\u002F4.benchmarks\u002F5.embedding-models",{"title":240,"path":241,"stem":242,"icon":243},"Research","\u002Fproject\u002Fresearch","5.project\u002F5.research","i-lucide-graduation-cap",{"title":245,"path":246,"stem":247,"icon":248},"Articles","\u002Fproject\u002Farticles","5.project\u002F6.articles","i-lucide-newspaper",{"id":250,"title":251,"authors":252,"body":254,"date":1797,"description":1798,"extension":1799,"meta":1800,"navigation":6,"path":1801,"publishedAt":1802,"seo":1803,"stem":1805,"tags":1806,"__hash__":1808},"blog\u002Fblog\u002Fjscpd-5-4-3.md","What's new in jscpd 5.4.3",[253],"kucherenko",{"type":255,"value":256,"toc":1786},"minimark",[257,261,266,294,573,598,635,639,642,665,684,688,699,736,782,790,793,1040,1043,1087,1129,1133,1140,1177,1198,1202,1209,1400,1514,1517,1562,1569,1655,1661,1665,1705,1709,1750,1782],[258,259,260],"p",{},"5.4.3 is a smaller release than 5.4.2. It adds a function for Node.js scripts, shows both sides of a clone in the HTML report, and fixes things people ran into in real projects: an Action that ignored the pinned version, ignore regions that leaked, and dead-code findings that weren't dead. Most of the fixes came from issues with a reproduction and the cause, and several came with the fix too.",[262,263,265],"h2",{"id":264},"run-jscpd-from-a-nodejs-script","Run jscpd from a Node.js script",[258,267,268,269,273,274,277,278,281,282,285,286,289,290,293],{},"The npm package used to give you only the ",[270,271,272],"code",{},"jscpd"," command. A script that wanted to run it started a second Node.js process with ",[270,275,276],{},"npx jscpd",", and tools such as knip didn't see that the project uses jscpd. Now ",[270,279,280],{},"require(\"jscpd\")"," and ",[270,283,284],{},"import { runJscpd } from \"jscpd\""," give you ",[270,287,288],{},"runJscpd(args, options)",". It finds the binary for the platform the same way the command does and returns what ",[270,291,292],{},"spawnSync"," returns:",[295,296,301],"pre",{"className":297,"code":298,"language":299,"meta":300,"style":300},"language-js shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { runJscpd } from \"jscpd\";\n\nconst { status, stderr } = runJscpd(\n  [process.argv[2], \"--min-tokens\", \"25\", \"--threshold\", \"10\", \"--silent\"],\n  { encoding: \"utf8\" }\n);\nif (status !== 0) {\n  console.error(stderr.trim());\n  process.exit(status);\n}\nconsole.log(\"duplication is under 10%\");\n","js","",[270,302,303,338,345,375,444,467,475,496,523,543,549],{"__ignoreMap":300},[304,305,308,312,316,320,323,326,329,332,335],"span",{"class":306,"line":307},"line",1,[304,309,311],{"class":310},"s7zQu","import",[304,313,315],{"class":314},"sMK4o"," {",[304,317,319],{"class":318},"sTEyZ"," runJscpd",[304,321,322],{"class":314}," }",[304,324,325],{"class":310}," from",[304,327,328],{"class":314}," \"",[304,330,272],{"class":331},"sfazB",[304,333,334],{"class":314},"\"",[304,336,337],{"class":314},";\n",[304,339,341],{"class":306,"line":340},2,[304,342,344],{"emptyLinePlaceholder":343},true,"\n",[304,346,348,352,354,357,360,363,366,369,372],{"class":306,"line":347},3,[304,349,351],{"class":350},"spNyl","const",[304,353,315],{"class":314},[304,355,356],{"class":318}," status",[304,358,359],{"class":314},",",[304,361,362],{"class":318}," stderr ",[304,364,365],{"class":314},"}",[304,367,368],{"class":314}," =",[304,370,319],{"class":371},"s2Zo4",[304,373,374],{"class":318},"(\n",[304,376,378,381,384,387,391,394,396,398,401,403,405,407,410,412,414,416,419,421,423,425,428,430,432,434,437,439,441],{"class":306,"line":377},4,[304,379,380],{"class":318},"  [process",[304,382,383],{"class":314},".",[304,385,386],{"class":318},"argv[",[304,388,390],{"class":389},"sbssI","2",[304,392,393],{"class":318},"]",[304,395,359],{"class":314},[304,397,328],{"class":314},[304,399,400],{"class":331},"--min-tokens",[304,402,334],{"class":314},[304,404,359],{"class":314},[304,406,328],{"class":314},[304,408,409],{"class":331},"25",[304,411,334],{"class":314},[304,413,359],{"class":314},[304,415,328],{"class":314},[304,417,418],{"class":331},"--threshold",[304,420,334],{"class":314},[304,422,359],{"class":314},[304,424,328],{"class":314},[304,426,427],{"class":331},"10",[304,429,334],{"class":314},[304,431,359],{"class":314},[304,433,328],{"class":314},[304,435,436],{"class":331},"--silent",[304,438,334],{"class":314},[304,440,393],{"class":318},[304,442,443],{"class":314},",\n",[304,445,447,450,454,457,459,462,464],{"class":306,"line":446},5,[304,448,449],{"class":314},"  {",[304,451,453],{"class":452},"swJcz"," encoding",[304,455,456],{"class":314},":",[304,458,328],{"class":314},[304,460,461],{"class":331},"utf8",[304,463,334],{"class":314},[304,465,466],{"class":314}," }\n",[304,468,470,473],{"class":306,"line":469},6,[304,471,472],{"class":318},")",[304,474,337],{"class":314},[304,476,478,481,484,487,490,493],{"class":306,"line":477},7,[304,479,480],{"class":310},"if",[304,482,483],{"class":318}," (status ",[304,485,486],{"class":314},"!==",[304,488,489],{"class":389}," 0",[304,491,492],{"class":318},") ",[304,494,495],{"class":314},"{\n",[304,497,499,502,504,507,510,513,515,518,521],{"class":306,"line":498},8,[304,500,501],{"class":318},"  console",[304,503,383],{"class":314},[304,505,506],{"class":371},"error",[304,508,509],{"class":452},"(",[304,511,512],{"class":318},"stderr",[304,514,383],{"class":314},[304,516,517],{"class":371},"trim",[304,519,520],{"class":452},"())",[304,522,337],{"class":314},[304,524,526,529,531,534,536,539,541],{"class":306,"line":525},9,[304,527,528],{"class":318},"  process",[304,530,383],{"class":314},[304,532,533],{"class":371},"exit",[304,535,509],{"class":452},[304,537,538],{"class":318},"status",[304,540,472],{"class":452},[304,542,337],{"class":314},[304,544,546],{"class":306,"line":545},10,[304,547,548],{"class":314},"}\n",[304,550,552,555,557,560,562,564,567,569,571],{"class":306,"line":551},11,[304,553,554],{"class":318},"console",[304,556,383],{"class":314},[304,558,559],{"class":371},"log",[304,561,509],{"class":318},[304,563,334],{"class":314},[304,565,566],{"class":331},"duplication is under 10%",[304,568,334],{"class":314},[304,570,472],{"class":318},[304,572,337],{"class":314},[295,574,578],{"className":575,"code":576,"language":577,"meta":300,"style":300},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","node check.mjs src\n# ERROR: jscpd found too many duplicates (50.0%) over threshold (10.0%)\n","bash",[270,579,580,592],{"__ignoreMap":300},[304,581,582,586,589],{"class":306,"line":307},[304,583,585],{"class":584},"sBMFI","node",[304,587,588],{"class":331}," check.mjs",[304,590,591],{"class":331}," src\n",[304,593,594],{"class":306,"line":340},[304,595,597],{"class":596},"sHwdD","# ERROR: jscpd found too many duplicates (50.0%) over threshold (10.0%)\n",[258,599,600,601,604,605,608,609,612,613,616,617,624,625,630,631,634],{},"Where the command prints an error and exits, for example on a platform without a prebuilt binary, the function throws an ",[270,602,603],{},"Error"," with the same message and ",[270,606,607],{},"code === \"JSCPD_NO_BINARY\"",". The types are in ",[270,610,611],{},"index.d.ts",". Detection still runs in the Rust binary only, so this is a way to start it, not the v4 ",[270,614,615],{},"jscpd()"," API. ",[618,619,623],"a",{"href":620,"rel":621},"https:\u002F\u002Fgithub.com\u002Fabrahamguo",[622],"nofollow","@abrahamguo"," wrote it (",[618,626,629],{"href":627,"rel":628},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1238",[622],"#1238","), and the next release adds ",[270,632,633],{},"getJscpdReport()"," from the same author, which returns the parsed JSON report.",[262,636,638],{"id":637},"both-sides-of-a-clone-in-the-html-report","Both sides of a clone in the HTML report",[258,640,641],{},"\"Show code\" in the HTML report opened only the first fragment, so to see what it was a copy of you went to the other file yourself. Now it opens both fragments side by side, or one above the other on a narrow screen. Each fragment sits under its file name with line numbers, and a long line scrolls inside its own pane. The report highlights the code with Prism again, as the v4 report did, and inlines only the languages it shows, so the file stays small: the report below is 27 KB.",[295,643,645],{"className":575,"code":644,"language":577,"meta":300,"style":300},"jscpd --reporters html fixtures\u002Ffile-names-demo\n# HTML report saved to report\u002Fjscpd-report.html\n",[270,646,647,660],{"__ignoreMap":300},[304,648,649,651,654,657],{"class":306,"line":307},[304,650,272],{"class":584},[304,652,653],{"class":331}," --reporters",[304,655,656],{"class":331}," html",[304,658,659],{"class":331}," fixtures\u002Ffile-names-demo\n",[304,661,662],{"class":306,"line":340},[304,663,664],{"class":596},"# HTML report saved to report\u002Fjscpd-report.html\n",[258,666,667,672,673,678,679,383],{},[618,668,671],{"href":669,"target":670},"\u002Fexamples\u002Fhtml-report-demo.html","_blank","Open the report"," of the file names demo: three clones, in Elixir, in a Dockerfile and in a Makefile. Thanks to ",[618,674,677],{"href":675,"rel":676},"https:\u002F\u002Fgithub.com\u002Fcrystalfp",[622],"@crystalfp"," for ",[618,680,683],{"href":681,"rel":682},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1263",[622],"the issue",[262,685,687],{"id":686},"pinning-the-action-pins-jscpd","Pinning the Action pins jscpd",[258,689,690,691,694,695,698],{},"The ",[270,692,693],{},"version"," input of the GitHub Action defaulted to ",[270,696,697],{},"latest",". So this workflow installed jscpd 5.4.2 the day 5.4.2 came out, even though it pins the Action to 5.4.1:",[295,700,704],{"className":701,"code":702,"language":703,"meta":300,"style":300},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","- uses: kucherenko\u002Fjscpd@v5.4.1\n  with:\n    path: src\n","yaml",[270,705,706,719,727],{"__ignoreMap":300},[304,707,708,711,714,716],{"class":306,"line":307},[304,709,710],{"class":314},"-",[304,712,713],{"class":452}," uses",[304,715,456],{"class":314},[304,717,718],{"class":331}," kucherenko\u002Fjscpd@v5.4.1\n",[304,720,721,724],{"class":306,"line":340},[304,722,723],{"class":452},"  with",[304,725,726],{"class":314},":\n",[304,728,729,732,734],{"class":306,"line":347},[304,730,731],{"class":452},"    path",[304,733,456],{"class":314},[304,735,591],{"class":331},[258,737,738,739,741,742,745,746,749,750,753,754,757,758,763,764,769,770,775,776,781],{},"From v5.4.3 on, an empty ",[270,740,693],{}," installs the release that the Action's own ref belongs to. Pin ",[270,743,744],{},"kucherenko\u002Fjscpd@v5.4.3"," or its commit SHA, and you get jscpd 5.4.3 until you move the pin, and a Dependabot bump of the Action updates both. ",[270,747,748],{},"version: latest"," still installs the newest release, and ",[270,751,752],{},"@v5"," keeps following the latest 5.x as before. Older tags can't learn this, so ",[270,755,756],{},"@v5.4.1"," still installs the newest jscpd. Reported by ",[618,759,762],{"href":760,"rel":761},"https:\u002F\u002Fgithub.com\u002Fdannystaple",[622],"@dannystaple",", fixed by ",[618,765,768],{"href":766,"rel":767},"https:\u002F\u002Fgithub.com\u002Fsarankumar1325",[622],"@sarankumar1325"," (",[618,771,774],{"href":772,"rel":773},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1240",[622],"#1240",", ",[618,777,780],{"href":778,"rel":779},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1249",[622],"#1249",").",[262,783,785,786,789],{"id":784},"jscpdignore-regions-with-in-a-string","jscpd:ignore regions with ",[270,787,788],{},"\u002F*"," in a string",[258,791,792],{},"Here is a list of routes between ignore markers, and a test fixture with the same list:",[295,794,798],{"className":795,"code":796,"language":797,"meta":300,"style":300},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F* jscpd:ignore-start *\u002F\nexport const PROTECTED_ROUTES = [\n  { path: \"\u002Fapi\u002Fauth\u002Forganization\u002F*\", roles: [\"owner\", \"admin\"], audit: true },\n  { path: \"\u002Fapi\u002Fauth\u002Fmembers\u002F*\", roles: [\"owner\", \"admin\"], audit: true },\n  { path: \"\u002Fapi\u002Fbilling\u002Finvoices\u002F*\", roles: [\"owner\", \"billing\"], audit: true },\n  { path: \"\u002Fapi\u002Fbilling\u002Fcards\u002F*\", roles: [\"owner\", \"billing\"], audit: false },\n];\n\u002F* jscpd:ignore-end *\u002F\n","ts",[270,799,800,805,822,880,929,979,1029,1035],{"__ignoreMap":300},[304,801,802],{"class":306,"line":307},[304,803,804],{"class":596},"\u002F* jscpd:ignore-start *\u002F\n",[304,806,807,810,813,816,819],{"class":306,"line":340},[304,808,809],{"class":310},"export",[304,811,812],{"class":350}," const",[304,814,815],{"class":318}," PROTECTED_ROUTES ",[304,817,818],{"class":314},"=",[304,820,821],{"class":318}," [\n",[304,823,824,826,829,831,833,836,838,840,843,845,848,850,853,855,857,859,862,864,866,868,871,873,877],{"class":306,"line":347},[304,825,449],{"class":314},[304,827,828],{"class":452}," path",[304,830,456],{"class":314},[304,832,328],{"class":314},[304,834,835],{"class":331},"\u002Fapi\u002Fauth\u002Forganization\u002F*",[304,837,334],{"class":314},[304,839,359],{"class":314},[304,841,842],{"class":452}," roles",[304,844,456],{"class":314},[304,846,847],{"class":318}," [",[304,849,334],{"class":314},[304,851,852],{"class":331},"owner",[304,854,334],{"class":314},[304,856,359],{"class":314},[304,858,328],{"class":314},[304,860,861],{"class":331},"admin",[304,863,334],{"class":314},[304,865,393],{"class":318},[304,867,359],{"class":314},[304,869,870],{"class":452}," audit",[304,872,456],{"class":314},[304,874,876],{"class":875},"sfNiH"," true",[304,878,879],{"class":314}," },\n",[304,881,882,884,886,888,890,893,895,897,899,901,903,905,907,909,911,913,915,917,919,921,923,925,927],{"class":306,"line":377},[304,883,449],{"class":314},[304,885,828],{"class":452},[304,887,456],{"class":314},[304,889,328],{"class":314},[304,891,892],{"class":331},"\u002Fapi\u002Fauth\u002Fmembers\u002F*",[304,894,334],{"class":314},[304,896,359],{"class":314},[304,898,842],{"class":452},[304,900,456],{"class":314},[304,902,847],{"class":318},[304,904,334],{"class":314},[304,906,852],{"class":331},[304,908,334],{"class":314},[304,910,359],{"class":314},[304,912,328],{"class":314},[304,914,861],{"class":331},[304,916,334],{"class":314},[304,918,393],{"class":318},[304,920,359],{"class":314},[304,922,870],{"class":452},[304,924,456],{"class":314},[304,926,876],{"class":875},[304,928,879],{"class":314},[304,930,931,933,935,937,939,942,944,946,948,950,952,954,956,958,960,962,965,967,969,971,973,975,977],{"class":306,"line":446},[304,932,449],{"class":314},[304,934,828],{"class":452},[304,936,456],{"class":314},[304,938,328],{"class":314},[304,940,941],{"class":331},"\u002Fapi\u002Fbilling\u002Finvoices\u002F*",[304,943,334],{"class":314},[304,945,359],{"class":314},[304,947,842],{"class":452},[304,949,456],{"class":314},[304,951,847],{"class":318},[304,953,334],{"class":314},[304,955,852],{"class":331},[304,957,334],{"class":314},[304,959,359],{"class":314},[304,961,328],{"class":314},[304,963,964],{"class":331},"billing",[304,966,334],{"class":314},[304,968,393],{"class":318},[304,970,359],{"class":314},[304,972,870],{"class":452},[304,974,456],{"class":314},[304,976,876],{"class":875},[304,978,879],{"class":314},[304,980,981,983,985,987,989,992,994,996,998,1000,1002,1004,1006,1008,1010,1012,1014,1016,1018,1020,1022,1024,1027],{"class":306,"line":469},[304,982,449],{"class":314},[304,984,828],{"class":452},[304,986,456],{"class":314},[304,988,328],{"class":314},[304,990,991],{"class":331},"\u002Fapi\u002Fbilling\u002Fcards\u002F*",[304,993,334],{"class":314},[304,995,359],{"class":314},[304,997,842],{"class":452},[304,999,456],{"class":314},[304,1001,847],{"class":318},[304,1003,334],{"class":314},[304,1005,852],{"class":331},[304,1007,334],{"class":314},[304,1009,359],{"class":314},[304,1011,328],{"class":314},[304,1013,964],{"class":331},[304,1015,334],{"class":314},[304,1017,393],{"class":318},[304,1019,359],{"class":314},[304,1021,870],{"class":452},[304,1023,456],{"class":314},[304,1025,1026],{"class":875}," false",[304,1028,879],{"class":314},[304,1030,1031,1033],{"class":306,"line":477},[304,1032,393],{"class":318},[304,1034,337],{"class":314},[304,1036,1037],{"class":306,"line":498},[304,1038,1039],{"class":596},"\u002F* jscpd:ignore-end *\u002F\n",[258,1041,1042],{},"jscpd 5.4.2 reported the region anyway:",[295,1044,1046],{"className":575,"code":1045,"language":577,"meta":300,"style":300},"jscpd --min-tokens 25 --min-lines 3 .\n# Clone found (typescript)\n#  - src\u002Fauth\u002Froutes.ts [3:37 - 7:3] (5 lines, 70 tokens)\n#    test\u002Froutes.fixture.ts [2:37 - 6:3]\n# Found 1 clones.\n",[270,1047,1048,1067,1072,1077,1082],{"__ignoreMap":300},[304,1049,1050,1052,1055,1058,1061,1064],{"class":306,"line":307},[304,1051,272],{"class":584},[304,1053,1054],{"class":331}," --min-tokens",[304,1056,1057],{"class":389}," 25",[304,1059,1060],{"class":331}," --min-lines",[304,1062,1063],{"class":389}," 3",[304,1065,1066],{"class":331}," .\n",[304,1068,1069],{"class":306,"line":340},[304,1070,1071],{"class":596},"# Clone found (typescript)\n",[304,1073,1074],{"class":306,"line":347},[304,1075,1076],{"class":596},"#  - src\u002Fauth\u002Froutes.ts [3:37 - 7:3] (5 lines, 70 tokens)\n",[304,1078,1079],{"class":306,"line":377},[304,1080,1081],{"class":596},"#    test\u002Froutes.fixture.ts [2:37 - 6:3]\n",[304,1083,1084],{"class":306,"line":446},[304,1085,1086],{"class":596},"# Found 1 clones.\n",[258,1088,1089,1090,1092,1093,1096,1097,1100,1101,1104,1105,1108,1109,1114,1115,1118,1119,775,1124,781],{},"The JavaScript and TypeScript tokenizer looked for the markers with a byte scan that took every ",[270,1091,788],{}," for the start of a comment, the one in ",[270,1094,1095],{},"\"\u002Fapi\u002Fauth\u002Forganization\u002F*\""," too. That fake comment ran to the next ",[270,1098,1099],{},"*\u002F",", the one that closes ",[270,1102,1103],{},"jscpd:ignore-end",", so the region ended at the first route. 5.4.3 finds the markers by their text, as the other languages do, and prints ",[270,1106,1107],{},"Found 0 clones."," Markers inside template literals, such as the CSS of a styled component, work as before. ",[618,1110,1113],{"href":1111,"rel":1112},"https:\u002F\u002Fgithub.com\u002Fbauchdj",[622],"@bauchdj"," found it in a data file of URL globs that gave 126 clones, and sent the cause; ",[618,1116,768],{"href":766,"rel":1117},[622]," fixed it (",[618,1120,1123],{"href":1121,"rel":1122},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1257",[622],"#1257",[618,1125,1128],{"href":1126,"rel":1127},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1258",[622],"#1258",[262,1130,1132],{"id":1131},"ignore-this-clone-in-jsx","\"Ignore this clone\" in JSX",[258,1134,1135,1136,1139],{},"The language server's \"Ignore this clone\" action wrote ",[270,1137,1138],{},"\u002F\u002F jscpd:ignore-start"," among JSX children, where the page renders it as text, and it could put a marker inside a tag, which TypeScript can't parse. Now it writes markers that JSX accepts and keeps them outside of tags:",[295,1141,1145],{"className":1142,"code":1143,"language":1144,"meta":300,"style":300},"language-tsx shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cul>\n  {\u002F* jscpd:ignore-start *\u002F}\n  \u003Cli>{order.id}\u003C\u002Fli>\n  \u003Cli>{order.total}\u003C\u002Fli>\n  {\u002F* jscpd:ignore-end *\u002F}\n\u003C\u002Ful>\n","tsx",[270,1146,1147,1152,1157,1162,1167,1172],{"__ignoreMap":300},[304,1148,1149],{"class":306,"line":307},[304,1150,1151],{},"\u003Cul>\n",[304,1153,1154],{"class":306,"line":340},[304,1155,1156],{},"  {\u002F* jscpd:ignore-start *\u002F}\n",[304,1158,1159],{"class":306,"line":347},[304,1160,1161],{},"  \u003Cli>{order.id}\u003C\u002Fli>\n",[304,1163,1164],{"class":306,"line":377},[304,1165,1166],{},"  \u003Cli>{order.total}\u003C\u002Fli>\n",[304,1168,1169],{"class":306,"line":446},[304,1170,1171],{},"  {\u002F* jscpd:ignore-end *\u002F}\n",[304,1173,1174],{"class":306,"line":469},[304,1175,1176],{},"\u003C\u002Ful>\n",[258,1178,1179,1180,1183,1184,1187,1188,775,1193,781],{},"When the clone starts or ends inside a tag, the start marker goes before the tag and the end marker after it. Each copy of a ",[270,1181,1182],{},"--cross-formats"," clone gets the comment syntax of its own file, and the ",[270,1185,1186],{},"\u003Cscript lang=\"tsx\">"," of a Vue, Svelte or Astro component gets the JSX markers (",[618,1189,1192],{"href":1190,"rel":1191},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1260",[622],"#1260",[618,1194,1197],{"href":1195,"rel":1196},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1264",[622],"#1264",[262,1199,1201],{"id":1200},"dead-code-that-wasnt-dead","Dead code that wasn't dead",[258,1203,1204,1205,1208],{},"Three reports from ",[618,1206,623],{"href":620,"rel":1207},[622]," came with the cause, and in this small project two of them show up at once:",[295,1210,1212],{"className":297,"code":1211,"language":299,"meta":300,"style":300},"\u002F\u002F src\u002Fmain.js\nimport { Cart } from \".\u002Fcart.js\";\n\nconst cart = new Cart(\"EUR\");\ncart.add({ sku: \"tea\", price: 450 });\n\nexport async function openAdmin() {\n  const { renderAdmin } = await import(`.\u002Fadmin\u002Fpanel.js`);\n  renderAdmin(document.body, cart);\n}\n",[270,1213,1214,1219,1241,1245,1272,1315,1319,1338,1372,1396],{"__ignoreMap":300},[304,1215,1216],{"class":306,"line":307},[304,1217,1218],{"class":596},"\u002F\u002F src\u002Fmain.js\n",[304,1220,1221,1223,1225,1228,1230,1232,1234,1237,1239],{"class":306,"line":340},[304,1222,311],{"class":310},[304,1224,315],{"class":314},[304,1226,1227],{"class":318}," Cart",[304,1229,322],{"class":314},[304,1231,325],{"class":310},[304,1233,328],{"class":314},[304,1235,1236],{"class":331},".\u002Fcart.js",[304,1238,334],{"class":314},[304,1240,337],{"class":314},[304,1242,1243],{"class":306,"line":347},[304,1244,344],{"emptyLinePlaceholder":343},[304,1246,1247,1249,1252,1254,1257,1259,1261,1263,1266,1268,1270],{"class":306,"line":377},[304,1248,351],{"class":350},[304,1250,1251],{"class":318}," cart ",[304,1253,818],{"class":314},[304,1255,1256],{"class":314}," new",[304,1258,1227],{"class":371},[304,1260,509],{"class":318},[304,1262,334],{"class":314},[304,1264,1265],{"class":331},"EUR",[304,1267,334],{"class":314},[304,1269,472],{"class":318},[304,1271,337],{"class":314},[304,1273,1274,1277,1279,1282,1284,1287,1290,1292,1294,1297,1299,1301,1304,1306,1309,1311,1313],{"class":306,"line":446},[304,1275,1276],{"class":318},"cart",[304,1278,383],{"class":314},[304,1280,1281],{"class":371},"add",[304,1283,509],{"class":318},[304,1285,1286],{"class":314},"{",[304,1288,1289],{"class":452}," sku",[304,1291,456],{"class":314},[304,1293,328],{"class":314},[304,1295,1296],{"class":331},"tea",[304,1298,334],{"class":314},[304,1300,359],{"class":314},[304,1302,1303],{"class":452}," price",[304,1305,456],{"class":314},[304,1307,1308],{"class":389}," 450",[304,1310,322],{"class":314},[304,1312,472],{"class":318},[304,1314,337],{"class":314},[304,1316,1317],{"class":306,"line":469},[304,1318,344],{"emptyLinePlaceholder":343},[304,1320,1321,1323,1326,1329,1332,1335],{"class":306,"line":477},[304,1322,809],{"class":310},[304,1324,1325],{"class":350}," async",[304,1327,1328],{"class":350}," function",[304,1330,1331],{"class":371}," openAdmin",[304,1333,1334],{"class":314},"()",[304,1336,1337],{"class":314}," {\n",[304,1339,1340,1343,1345,1348,1350,1352,1355,1358,1360,1363,1366,1368,1370],{"class":306,"line":498},[304,1341,1342],{"class":350},"  const",[304,1344,315],{"class":314},[304,1346,1347],{"class":318}," renderAdmin",[304,1349,322],{"class":314},[304,1351,368],{"class":314},[304,1353,1354],{"class":310}," await",[304,1356,1357],{"class":314}," import",[304,1359,509],{"class":452},[304,1361,1362],{"class":314},"`",[304,1364,1365],{"class":331},".\u002Fadmin\u002Fpanel.js",[304,1367,1362],{"class":314},[304,1369,472],{"class":452},[304,1371,337],{"class":314},[304,1373,1374,1377,1379,1382,1384,1387,1389,1392,1394],{"class":306,"line":525},[304,1375,1376],{"class":371},"  renderAdmin",[304,1378,509],{"class":452},[304,1380,1381],{"class":318},"document",[304,1383,383],{"class":314},[304,1385,1386],{"class":318},"body",[304,1388,359],{"class":314},[304,1390,1391],{"class":318}," cart",[304,1393,472],{"class":452},[304,1395,337],{"class":314},[304,1397,1398],{"class":306,"line":545},[304,1399,548],{"class":314},[295,1401,1403],{"className":297,"code":1402,"language":299,"meta":300,"style":300},"\u002F\u002F src\u002Fcart.js\nexport class Cart {\n  constructor(currency) {\n    this.currency = currency;\n    this.items = [];\n  }\n\n  add(item) {\n    this.items.push(item);\n  }\n}\n",[270,1404,1405,1410,1421,1436,1450,1464,1469,1473,1487,1506,1510],{"__ignoreMap":300},[304,1406,1407],{"class":306,"line":307},[304,1408,1409],{"class":596},"\u002F\u002F src\u002Fcart.js\n",[304,1411,1412,1414,1417,1419],{"class":306,"line":340},[304,1413,809],{"class":310},[304,1415,1416],{"class":350}," class",[304,1418,1227],{"class":584},[304,1420,1337],{"class":314},[304,1422,1423,1426,1428,1432,1434],{"class":306,"line":347},[304,1424,1425],{"class":350},"  constructor",[304,1427,509],{"class":314},[304,1429,1431],{"class":1430},"sHdIc","currency",[304,1433,472],{"class":314},[304,1435,1337],{"class":314},[304,1437,1438,1441,1443,1445,1448],{"class":306,"line":377},[304,1439,1440],{"class":314},"    this.",[304,1442,1431],{"class":318},[304,1444,368],{"class":314},[304,1446,1447],{"class":318}," currency",[304,1449,337],{"class":314},[304,1451,1452,1454,1457,1459,1462],{"class":306,"line":446},[304,1453,1440],{"class":314},[304,1455,1456],{"class":318},"items",[304,1458,368],{"class":314},[304,1460,1461],{"class":452}," []",[304,1463,337],{"class":314},[304,1465,1466],{"class":306,"line":469},[304,1467,1468],{"class":314},"  }\n",[304,1470,1471],{"class":306,"line":477},[304,1472,344],{"emptyLinePlaceholder":343},[304,1474,1475,1478,1480,1483,1485],{"class":306,"line":498},[304,1476,1477],{"class":452},"  add",[304,1479,509],{"class":314},[304,1481,1482],{"class":1430},"item",[304,1484,472],{"class":314},[304,1486,1337],{"class":314},[304,1488,1489,1491,1493,1495,1498,1500,1502,1504],{"class":306,"line":525},[304,1490,1440],{"class":314},[304,1492,1456],{"class":318},[304,1494,383],{"class":314},[304,1496,1497],{"class":371},"push",[304,1499,509],{"class":452},[304,1501,1482],{"class":318},[304,1503,472],{"class":452},[304,1505,337],{"class":314},[304,1507,1508],{"class":306,"line":545},[304,1509,1468],{"class":314},[304,1511,1512],{"class":306,"line":551},[304,1513,548],{"class":314},[258,1515,1516],{},"jscpd 5.4.2:",[295,1518,1520],{"className":575,"code":1519,"language":577,"meta":300,"style":300},"jscpd --dead-code --dead-code-categories all .\n# Unused files (1)\n#  - src\u002Fadmin\u002Fpanel.js  certain 95%  3 lines\n# Unused members (1)\n#  - method src\u002Fcart.js:2:3 Cart.constructor  medium 70%  4 lines\n# Found 2 dead code findings in 3 files (31.8% of 22 lines).\n",[270,1521,1522,1537,1542,1547,1552,1557],{"__ignoreMap":300},[304,1523,1524,1526,1529,1532,1535],{"class":306,"line":307},[304,1525,272],{"class":584},[304,1527,1528],{"class":331}," --dead-code",[304,1530,1531],{"class":331}," --dead-code-categories",[304,1533,1534],{"class":331}," all",[304,1536,1066],{"class":331},[304,1538,1539],{"class":306,"line":340},[304,1540,1541],{"class":596},"# Unused files (1)\n",[304,1543,1544],{"class":306,"line":347},[304,1545,1546],{"class":596},"#  - src\u002Fadmin\u002Fpanel.js  certain 95%  3 lines\n",[304,1548,1549],{"class":306,"line":377},[304,1550,1551],{"class":596},"# Unused members (1)\n",[304,1553,1554],{"class":306,"line":446},[304,1555,1556],{"class":596},"#  - method src\u002Fcart.js:2:3 Cart.constructor  medium 70%  4 lines\n",[304,1558,1559],{"class":306,"line":469},[304,1560,1561],{"class":596},"# Found 2 dead code findings in 3 files (31.8% of 22 lines).\n",[258,1563,1564,1565,1568],{},"jscpd 5.4.3 prints ",[270,1566,1567],{},"No dead code found."," for the same project:",[1570,1571,1572,1609,1636],"ul",{},[1573,1574,1575,1578,1579,1582,1583,1586,1587,1590,1591,1594,1595,1598,1599,775,1604,781],"li",{},[270,1576,1577],{},"import()"," with backticks and nothing interpolated, such as ",[270,1580,1581],{},"import(`.\u002Fadmin\u002Fpanel.js`)",", is followed now, and so is ",[270,1584,1585],{},"import.meta.glob(`.\u002Fpages\u002F*.ts`)",". A quoted specifier with a ",[270,1588,1589],{},"$"," in it, such as SvelteKit's ",[270,1592,1593],{},"import('$lib\u002Fx')",", is followed too: only ",[270,1596,1597],{},"${"," inside backticks counts as interpolation. Before, the importing file also lost 30 points of confidence on all its findings (",[618,1600,1603],{"href":1601,"rel":1602},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1239",[622],"#1239",[618,1605,1608],{"href":1606,"rel":1607},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1251",[622],"#1251",[1573,1610,1611,1614,1615,1618,1619,1622,1623,769,1626,775,1631,781],{},[270,1612,1613],{},"constructor"," in JavaScript and dunder methods such as ",[270,1616,1617],{},"__init__"," or ",[270,1620,1621],{},"__repr__"," in Python are called by the runtime, not by name, so the unused-member check skips them. Fixed by ",[618,1624,768],{"href":766,"rel":1625},[622],[618,1627,1630],{"href":1628,"rel":1629},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1253",[622],"#1253",[618,1632,1635],{"href":1633,"rel":1634},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1254",[622],"#1254",[1573,1637,1638,281,1641,1644,1645,775,1650,781],{},[270,1639,1640],{},"knip.ts",[270,1642,1643],{},"knip.js"," are knip's config, and a new framework entry keeps them as entry points instead of unused files (",[618,1646,1649],{"href":1647,"rel":1648},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1255",[622],"#1255",[618,1651,1654],{"href":1652,"rel":1653},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1256",[622],"#1256",[258,1656,1657,1658,1660],{},"On six repositories that we checked with the ",[270,1659,1577],{}," fix, nothing new was reported.",[262,1662,1664],{"id":1663},"security-and-packaging","Security and packaging",[1570,1666,1667,1674,1677,1688],{},[1573,1668,1669,1670,1673],{},"The Linux binaries accepted certificates from the leaked emSign intermediate CAs. rustls-webpki 0.103.16 and webpki-roots 1.0.10 reject them. This matters only for ",[270,1671,1672],{},"--semantic-url"," with a remote API on Linux: model downloads are pinned by SHA-256, and macOS and Windows use the system TLS stack (RUSTSEC-2026-0381, 0382, 0383).",[1573,1675,1676],{},"candle 0.11.1 brings zip 9.3.0, which fixes RUSTSEC-2026-0429 and three zip advisories, and askama no longer pulls in the unmaintained basic-toml.",[1573,1678,1679,1682,1683,781],{},[270,1680,1681],{},"nix run github:kucherenko\u002Fjscpd"," builds again, and a Nix workflow builds and runs the package on Linux and macOS (",[618,1684,1687],{"href":1685,"rel":1686},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fpull\u002F1272",[622],"#1272",[1573,1689,1690,1691,1694,1695,769,1700,781],{},"The npmmirror registry never copied ",[270,1692,1693],{},"jscpd-linux-x64-gnu@5.4.2",", so pnpm installs through the mirror lost the Linux binary without a warning. The release pipeline asks the mirror to sync every package now. Reported by ",[618,1696,1699],{"href":1697,"rel":1698},"https:\u002F\u002Fgithub.com\u002Ficret",[622],"@icret",[618,1701,1704],{"href":1702,"rel":1703},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Fissues\u002F1261",[622],"#1261",[262,1706,1708],{"id":1707},"update","Update",[295,1710,1712],{"className":575,"code":1711,"language":577,"meta":300,"style":300},"curl -fsSL https:\u002F\u002Fjscpd.dev\u002Finstall.sh | bash\n# or\nnpm i -g jscpd@5\n",[270,1713,1714,1731,1736],{"__ignoreMap":300},[304,1715,1716,1719,1722,1725,1728],{"class":306,"line":307},[304,1717,1718],{"class":584},"curl",[304,1720,1721],{"class":331}," -fsSL",[304,1723,1724],{"class":331}," https:\u002F\u002Fjscpd.dev\u002Finstall.sh",[304,1726,1727],{"class":314}," |",[304,1729,1730],{"class":584}," bash\n",[304,1732,1733],{"class":306,"line":340},[304,1734,1735],{"class":596},"# or\n",[304,1737,1738,1741,1744,1747],{"class":306,"line":347},[304,1739,1740],{"class":584},"npm",[304,1742,1743],{"class":331}," i",[304,1745,1746],{"class":331}," -g",[304,1748,1749],{"class":331}," jscpd@5\n",[258,1751,1752,1753,1756,1757,1762,1763,775,1766,775,1769,775,1772,775,1775,281,1778,1781],{},"The full list is in the ",[618,1754,1755],{"href":201},"changelog"," and in the ",[618,1758,1761],{"href":1759,"rel":1760},"https:\u002F\u002Fgithub.com\u002Fkucherenko\u002Fjscpd\u002Freleases\u002Ftag\u002Fv5.4.3",[622],"release notes",". Thanks to ",[618,1764,623],{"href":620,"rel":1765},[622],[618,1767,768],{"href":766,"rel":1768},[622],[618,1770,762],{"href":760,"rel":1771},[622],[618,1773,1113],{"href":1111,"rel":1774},[622],[618,1776,677],{"href":675,"rel":1777},[622],[618,1779,1699],{"href":1697,"rel":1780},[622]," for the issues, the causes and the fixes in this release!",[1783,1784,1785],"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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}",{"title":300,"searchDepth":340,"depth":340,"links":1787},[1788,1789,1790,1791,1793,1794,1795,1796],{"id":264,"depth":340,"text":265},{"id":637,"depth":340,"text":638},{"id":686,"depth":340,"text":687},{"id":784,"depth":340,"text":1792},"jscpd:ignore regions with \u002F* in a string",{"id":1131,"depth":340,"text":1132},{"id":1200,"depth":340,"text":1201},{"id":1663,"depth":340,"text":1664},{"id":1707,"depth":340,"text":1708},"2026-11-12","runJscpd() for Node.js scripts, both fragments of a clone in the HTML report, an Action that installs the jscpd of its own tag, and fixes for jscpd:ignore regions and dead-code findings. With commands and real output.","md",{},"\u002Fblog\u002Fjscpd-5-4-3","2026-11-12T10:00:00Z",{"title":251,"description":1804},"jscpd 5.4.3 explained with examples: runJscpd() from the npm package, a side-by-side HTML report with highlighting, Action version pinning, jscpd:ignore regions with \u002F* in strings, and dead-code fixes for import() and constructors.","blog\u002Fjscpd-5-4-3",[1807],"release","uqNUcN2RE0dNFoajeR066zng3f4MMN-1uVbxe8ylnOA",{"\u002Fblog\u002Fjscpd-5-4-3":1810},{"views":347,"visits":1811},0,1794624623286]