{"version":3,"sources":["../src/in-files-detector.ts","../src/validators/skip-local.validator.ts","../src/files.ts","../src/hooks/blamer.ts","../src/hooks/fragment.ts","../src/utils/clone-found.ts","../src/utils/reports.ts","../src/subscribers/progress.ts","../src/subscribers/verbose.ts","../src/reporters/console.ts","../src/reporters/console-full.ts","../src/reporters/json.ts","../src/reporters/csv.ts","../src/reporters/markdown.ts","../src/reporters/xml.ts","../src/reporters/silent.ts","../src/reporters/threshold.ts","../src/reporters/xcode.ts","../src/reporters/ai.ts","../src/utils/options.ts"],"sourcesContent":["import {\n  Detector,\n  DetectorEvents,\n  IClone,\n  ICloneValidator,\n  IHandler,\n  IMapFrame,\n  IOptions,\n  IStore,\n  ISubscriber,\n  ITokenizer,\n  Statistic,\n} from '@jscpd/core';\nimport {getFormatByFile} from '@jscpd/tokenizer';\nimport {EntryWithContent, IHook, IReporter} from './interfaces';\nimport {SkipLocalValidator} from './validators';\n\nexport class InFilesDetector {\n\n  private readonly reporters: IReporter[] = [];\n  private readonly subscribes: ISubscriber[] = [];\n  private readonly postHooks: IHook[] = [];\n\n  constructor(\n    private readonly tokenizer: ITokenizer,\n    private readonly store: IStore<IMapFrame>,\n    private readonly statistic: Statistic,\n    public readonly options: IOptions) {\n    this.registerSubscriber(this.statistic);\n  }\n\n  registerReporter(reporter: IReporter): void {\n    this.reporters.push(reporter);\n  }\n\n  registerSubscriber(subscriber: ISubscriber): void {\n    this.subscribes.push(subscriber);\n  }\n\n  registerHook(hook: IHook): void {\n    this.postHooks.push(hook);\n  }\n\n  detect(fls: EntryWithContent[]): Promise<IClone[]> {\n    const files = fls.filter((f) => !!f);\n    if (files.length === 0) {\n      return Promise.resolve([]);\n    }\n    const options = this.options;\n    const hooks = [...this.postHooks];\n    const store = this.store;\n    const validators: ICloneValidator[] = [];\n\n    if (options.skipLocal) {\n      validators.push(new SkipLocalValidator());\n    }\n\n    const detector = new Detector(this.tokenizer, store, validators, options);\n\n    this.subscribes.forEach((listener: ISubscriber) => {\n      Object\n        .entries(listener.subscribe())\n        // @ts-ignore\n        .map(([event, handler]: [DetectorEvents, IHandler]) => detector.on(event, handler));\n    });\n\n    const detect = (entry: EntryWithContent, clones: IClone[] = []): Promise<IClone[]> => {\n      const {path, content} = entry;\n      const format: string|undefined = getFormatByFile(path, options.formatsExts);\n      return format !== undefined ? detector\n        .detect(path, content, format)\n        .then((clns: IClone[]) => {\n          if (clns) {\n            clones.push(...clns);\n          }\n          const file = files.pop();\n          if (file) {\n            return detect(file, clones);\n          }\n          return clones;\n        }): Promise.resolve([]);\n    };\n\n    const processHooks = (hook: IHook, detectedClones: IClone[]): Promise<IClone[]> => {\n      return hook\n        .process(detectedClones)\n        .then((clones: IClone[]) => {\n          const nextHook: IHook | undefined = hooks.pop();\n          if (nextHook) {\n            return processHooks(nextHook, clones);\n          }\n          return clones;\n        });\n    }\n\n    // @ts-ignore\n    return detect(files.pop())\n      .then((clones: IClone[]) => {\n        const hook = hooks.pop();\n        if (hook) {\n          return processHooks(hook, clones)\n        }\n        return clones;\n      })\n      .then((clones: IClone[]) => {\n        const statistic = this.statistic.getStatistic();\n        this.reporters.forEach((reporter: IReporter) => {\n          reporter.report(clones, statistic);\n        });\n        return clones;\n      });\n  }\n}\n","import {getOption, IClone, ICloneValidator, IOptions, IValidationResult} from '@jscpd/core';\nimport {isAbsolute, relative} from \"path\";\n\nexport class SkipLocalValidator implements ICloneValidator {\n\n\tvalidate(clone: IClone, options: IOptions): IValidationResult {\n\t\tconst status = !this.shouldSkipClone(clone, options);\n\t\treturn {\n\t\t\tstatus,\n\t\t\tclone,\n\t\t\tmessage: [\n\t\t\t\t`Sources of duplication located in same local folder (${clone.duplicationA.sourceId}, ${clone.duplicationB.sourceId})`\n\t\t\t]\n\t\t};\n\t}\n\n\tpublic shouldSkipClone(clone: IClone, options: IOptions): boolean {\n\t\tconst path: string[] = getOption('path', options);\n\t\treturn path.some(\n\t\t\t(dir) => SkipLocalValidator.isRelative(clone.duplicationA.sourceId, dir) && SkipLocalValidator.isRelative(clone.duplicationB.sourceId, dir)\n\t\t);\n\t}\n\n\tprivate static isRelative(file: string, path: string): boolean {\n\t\tconst rel = relative(path, file);\n\t\treturn rel !== '' && !rel.startsWith('..') && !isAbsolute(rel);\n\t}\n\n}\n","import {getOption, IOptions} from '@jscpd/core';\nimport {Entry, sync} from 'fast-glob';\nimport {getFormatByFile} from '@jscpd/tokenizer';\nimport { readFileSync, realpathSync } from 'fs-extra';\nimport {grey} from 'colors/safe';\nimport {EntryWithContent} from './interfaces';\nimport {lstatSync, Stats} from \"fs\";\nimport bytes from \"bytes\";\n\n\nfunction isFile(path: string): boolean {\n  try {\n    const stat: Stats = lstatSync(path);\n    return stat.isFile();\n  } catch (e) {\n    // lstatSync throws an error if path doesn't exist\n    return false;\n  }\n}\n\nfunction isSymlink(path: string): boolean {\n  try {\n    const stat: Stats = lstatSync(path);\n    return stat.isSymbolicLink();\n  } catch (e) {\n    // lstatSync throws an error if path doesn't exist\n    return false;\n  }\n}\n\nfunction skipNotSupportedFormats(options: IOptions): (entry: Entry) => boolean {\n  return (entry: Entry): boolean => {\n    const {path} = entry;\n    const format: string | undefined = getFormatByFile(path, options.formatsExts);\n    const shouldNotSkip = !!(format && options.format && options.format.includes(format));\n    if ((options.debug || options.verbose) && !shouldNotSkip) {\n      console.log(`File ${path} skipped! Format \"${format}\" does not included to supported formats.`);\n    }\n    return shouldNotSkip;\n  }\n}\n\nfunction skipBigFiles(options: IOptions): (entry: Entry) => boolean {\n  return (entry: Entry): boolean => {\n    const {stats, path} = entry;\n    if (!stats) {\n      return true;\n    }\n    // @ts-expect-error - stats is checked above, but DTS build doesn't recognize control flow\n    const shouldSkip = bytes.parse(stats.size) > bytes.parse(getOption('maxSize', options) || '0');\n    if (options.debug && shouldSkip) {\n      console.log(`File ${path} skipped! Size more then limit (${bytes(stats.size)} > ${getOption('maxSize', options)})`);\n    }\n    return !shouldSkip;\n  };\n}\n\nfunction skipFilesIfLinesOfContentNotInLimits(options: IOptions): (entry: EntryWithContent) => boolean {\n  return (entry: EntryWithContent): boolean => {\n    const {path, content} = entry;\n    const lines = content.split('\\n').length;\n    const minLines = getOption('minLines', options);\n    const maxLines = getOption('maxLines', options);\n    if (lines < minLines || lines > maxLines) {\n      if ((options.debug || options.verbose)) {\n        console.log(grey(`File ${path} skipped! Code lines=${lines} not in limits (${minLines}:${maxLines})`));\n      }\n      return false;\n    }\n    return true;\n  }\n}\n\nfunction addContentToEntry(entry: Entry): EntryWithContent {\n  const {path} = entry;\n  const content = readFileSync(path).toString();\n  return {...entry, content}\n}\n\nexport function getFilesToDetect(options: IOptions): EntryWithContent[] {\n  const pattern = options.pattern || '**/*';\n  let patterns = options.path;\n\n  if (options.noSymlinks) {\n    patterns = patterns!==undefined ? patterns.filter((path: string) => !isSymlink(path)) : [];\n  }\n\n  patterns = patterns!==undefined ? patterns.map((path: string) => {\n    const currentPath = realpathSync(path);\n\n    if (isFile(currentPath)) {\n      return path;\n    }\n\n    return path.endsWith('/') ? `${path}${pattern}` : `${path}/${pattern}`;\n  }): [];\n\n  return sync(\n    patterns,\n    {\n      ignore: options.ignore,\n      onlyFiles: true,\n      dot: true,\n      stats: true,\n      absolute: options.absolute || false,\n      followSymbolicLinks: !options.noSymlinks,\n      cwd: process.cwd(),\n    },\n  )\n    .filter(skipNotSupportedFormats(options))\n    .filter(skipBigFiles(options))\n    .map(addContentToEntry)\n    .filter(skipFilesIfLinesOfContentNotInLimits(options));\n}\n\n","import Blamer from 'blamer';\nimport {IBlamedLines, IClone} from '@jscpd/core';\nimport {IHook} from '..';\n\n\nexport class BlamerHook implements IHook {\n\n\tprocess(clones: IClone[]): Promise<IClone[]> {\n\t\treturn Promise.all(clones.map((clone: IClone) => BlamerHook.blameLines(clone)));\n\t}\n\n\tstatic async blameLines(clone: IClone): Promise<IClone> {\n\t\tconst blamer = new Blamer();\n\t\tconst blamedFileA: Record<string, IBlamedLines> = await blamer.blameByFile(clone.duplicationA.sourceId);\n\t\tconst blamedFileB: Record<string, IBlamedLines> = await blamer.blameByFile(clone.duplicationB.sourceId);\n\t\tclone.duplicationA.blame = BlamerHook.getBlamedLines(blamedFileA, clone.duplicationA.start.line, clone.duplicationA.end.line);\n\t\tclone.duplicationB.blame = BlamerHook.getBlamedLines(blamedFileB, clone.duplicationB.start.line, clone.duplicationB.end.line);\n\t\treturn clone;\n\t}\n\n\tstatic getBlamedLines(blamedFiles: Record<string, IBlamedLines>, start: number, end: number): IBlamedLines {\n\t\t// TODO rewrite the method\n\t\tconst [file] = Object.keys(blamedFiles);\n\t\tconst result: IBlamedLines = {};\n\t\t// @ts-ignore\n    Object.keys(blamedFiles[file])\n\t\t\t.filter((lineNumber) => {\n\t\t\t\treturn Number(lineNumber) >= start && Number(lineNumber) <= end;\n\t\t\t})\n      // @ts-ignore\n      .map((lineNumber) => blamedFiles[file][lineNumber])\n\t\t\t.forEach((info) => {\n\t\t\t\tresult[info.line] = info;\n\t\t\t});\n\t\treturn result;\n\t}\n}\n\n","import {IClone} from '@jscpd/core';\nimport {readFileSync} from \"fs\";\nimport {IHook} from '..';\n\nexport class FragmentsHook implements IHook {\n\n\tprocess(clones: IClone[]): Promise<IClone[]> {\n\t\treturn Promise.all(\n\t\t\tclones.map((clone: IClone) => FragmentsHook.addFragments(clone)),\n\t\t);\n\t}\n\n\tstatic addFragments(clone: IClone): IClone {\n\t\tconst codeA = readFileSync(clone.duplicationA.sourceId).toString();\n\t\tconst codeB = readFileSync(clone.duplicationB.sourceId).toString();\n\t\tclone.duplicationA.fragment = codeA.substring(clone.duplicationA.range[0], clone.duplicationA.range[1]);\n\t\tclone.duplicationB.fragment = codeB.substring(clone.duplicationB.range[0], clone.duplicationB.range[1]);\n\t\treturn clone;\n\t}\n\n}\n\n","import {IClone, IOptions} from '@jscpd/core';\nimport {red} from 'colors/safe';\nimport {getPathConsoleString, getSourceLocation} from './reports';\n\nexport function cloneFound(clone: IClone, options: IOptions): void {\n\tconst {duplicationA, duplicationB, format, isNew} = clone;\n\tconsole.log('Clone found (' + format + '):' + (isNew ? red('*') : ''));\n\tconsole.log(\n\t\t` - ${getPathConsoleString(duplicationA.sourceId, options)} [${getSourceLocation(\n\t\t\tduplicationA.start,\n\t\t\tduplicationA.end,\n\t\t)}] (${duplicationA.end.line - duplicationA.start.line} lines${duplicationA.end.position ? ', ' + (duplicationA.end.position - (duplicationA.start.position as number)) + ' tokens' : ''})`,\n\t);\n\tconsole.log(\n\t\t`   ${getPathConsoleString(duplicationB.sourceId, options)} [${getSourceLocation(\n\t\t\tduplicationB.start,\n\t\t\tduplicationB.end,\n\t\t)}]`,\n\t);\n\tconsole.log('');\n}\n","import {IClone, IOptions, IStatisticRow, ITokenLocation} from '@jscpd/core';\nimport {relative} from \"path\";\nimport {cwd} from \"process\";\nimport {bold, green, grey} from 'colors/safe';\n\nexport const compareDates = (firstDate: string, secondDate: string): string => {\n  const first = new Date(firstDate);\n  const second = new Date(secondDate);\n  switch (true) {\n    case first < second:\n      return '=>';\n    case first > second:\n      return '<=';\n    default:\n      return '==';\n  }\n}\n\nexport function escapeXml(unsafe: string): string {\n  return unsafe.replace(/[<>&'\"]/g, (c) => {\n    switch (c) {\n      case '<': return '&lt;';\n      case '>': return '&gt;';\n      case '&': return '&amp;';\n      case '\\'': return '&apos;';\n      case '\"': return '&quot;';\n      default: return  ''\n    }\n  });\n}\n\nexport function getPath(path: string, options: IOptions): string {\n  return options.absolute ? path : relative(cwd(), path);\n}\n\nexport function getPathConsoleString(path: string, options: IOptions): string {\n  return bold(green(getPath(path, options)));\n}\n\nexport function getSourceLocation(start: ITokenLocation, end: ITokenLocation): string {\n\treturn `${start.line}:${start.column} - ${end.line}:${end.column}`;\n}\n\nexport function generateLine(clone: IClone, position: number, line: string): string[] {\n\tconst lineNumberA: string = (clone.duplicationA.start.line + position).toString();\n\tconst lineNumberB: string = (clone.duplicationB.start.line + position).toString();\n\tif (clone.duplicationA.blame && clone.duplicationB.blame) {\n\n    return [\n\t\t\tlineNumberA,\n      // @ts-ignore\n      clone.duplicationA.blame[lineNumberA] ? clone.duplicationA.blame[lineNumberA].author : '',\n\t\t\tclone.duplicationA.blame[lineNumberA] && clone.duplicationB.blame[lineNumberB]\n        // @ts-ignore\n        ? compareDates(clone.duplicationA.blame[lineNumberA].date, clone.duplicationB.blame[lineNumberB].date)\n\t\t\t\t: '',\n\t\t\tlineNumberB,\n      // @ts-ignore\n\t\t\tclone.duplicationB.blame[lineNumberB] ? clone.duplicationB.blame[lineNumberB].author : '',\n\t\t\tgrey(line),\n\t\t];\n\t} else {\n\t\treturn [lineNumberA, lineNumberB, grey(line)];\n\t}\n}\n\nexport function convertStatisticToArray(format: string, statistic: IStatisticRow): string[] {\n  return [\n    format,\n    `${statistic.sources}`,\n    `${statistic.lines}`,\n    `${statistic.tokens}`,\n    `${statistic.clones}`,\n    `${statistic.duplicatedLines} (${statistic.percentage}%)`,\n    `${statistic.duplicatedTokens} (${statistic.percentageTokens}%)`,\n  ]\n}\n\n","import {DetectorEvents, IClone, IEventPayload, IHandler, IOptions, ISubscriber} from '@jscpd/core';\nimport {cloneFound} from '../utils/clone-found';\n\nexport class ProgressSubscriber implements ISubscriber {\n\n\tconstructor(private readonly options: IOptions) {\n\t}\n\n\tsubscribe(): Partial<Record<DetectorEvents, IHandler>> {\n\t\treturn {\n      CLONE_FOUND: (payload: IEventPayload): void => cloneFound(payload.clone as IClone, this.options),\n    };\n\t}\n}\n","import {grey, yellow} from 'colors/safe';\nimport {DetectorEvents, IEventPayload, IHandler, IOptions, ISubscriber} from '@jscpd/core';\n\nexport class VerboseSubscriber implements ISubscriber {\n\n\tconstructor(protected options: IOptions) {\n\t}\n\n\tsubscribe(): Partial<Record<DetectorEvents, IHandler>> {\n\t\treturn {\n      'CLONE_FOUND': (payload: IEventPayload): void => {\n        const {clone} = payload;\n        console.log(yellow('CLONE_FOUND'));\n        console.log(grey(JSON.stringify(clone, null, '\\t')));\n      },\n      'CLONE_SKIPPED': (payload: IEventPayload): void => {\n        const {validation} = payload;\n        console.log(yellow('CLONE_SKIPPED'));\n        console.log(\n          grey('Clone skipped: ' + validation?.message?.join(' ')),\n        );\n      },\n      'START_DETECTION': (payload: IEventPayload): void => {\n        const {source} = payload;\n        console.log(yellow('START_DETECTION'));\n        console.log(\n          grey('Start detection for source id=' + source?.getId() + ' format=' + source?.getFormat()),\n        )\n      },\n    };\n\t}\n}\n","import {IClone, IOptions, IStatistic} from '@jscpd/core';\nimport {bold, grey} from 'colors/safe';\nimport {IReporter} from '..';\nimport {convertStatisticToArray} from \"../utils/reports\";\n\nconst Table = require('cli-table3');\n\nexport class ConsoleReporter implements IReporter {\n\tprivate readonly options;\n\n\tconstructor(options: IOptions) {\n\t\tthis.options = options;\n\t}\n\n\treport(clones: IClone[], statistic: IStatistic | undefined = undefined): void {\n\t\tif (statistic && !this.options.silent) {\n\t\t\tconst table = new Table({\n        head: ['Format', 'Files analyzed', 'Total lines', 'Total tokens', 'Clones found', 'Duplicated lines', 'Duplicated tokens'],\n      });\n\n      Object.keys(statistic.formats)\n        // @ts-ignore\n        .filter((format) => statistic.formats[format].sources)\n\t\t\t\t.forEach((format: string) => {\n          // @ts-ignore\n          table.push(convertStatisticToArray(format, statistic.formats[format].total));\n\t\t\t\t});\n\t\t\ttable.push(convertStatisticToArray(bold('Total:'), statistic.total));\n\t\t\tconsole.log(table.toString());\n      console.log(grey(`Found ${clones.length} clones.`));\n\t\t}\n\t}\n}\n","import {IClone, IOptions} from '@jscpd/core';\nimport {IReporter} from '..';\nimport {generateLine} from '../utils/reports';\nimport {cloneFound} from '../utils/clone-found';\nimport {grey} from 'colors/safe';\n\nconst Table = require('cli-table3');\n\nconst TABLE_OPTIONS = {\n\tchars: {\n\t\ttop: '',\n\t\t'top-mid': '',\n\t\t'top-left': '',\n\t\t'top-right': '',\n\t\tbottom: '',\n\t\t'bottom-mid': '',\n\t\t'bottom-left': '',\n\t\t'bottom-right': '',\n\t\tleft: '',\n\t\t'left-mid': '',\n\t\tmid: '',\n\t\t'mid-mid': '',\n\t\tright: '',\n\t\t'right-mid': '',\n\t\tmiddle: '│',\n\t},\n};\n\nexport class ConsoleFullReporter implements IReporter {\n\n\tconstructor(private readonly options: IOptions) {\n\t}\n\n\tpublic report(clones: IClone[]): void {\n\t\tclones.forEach((clone: IClone) => {\n\t\t\tthis.cloneFullFound(clone);\n\t\t});\n\t\tconsole.log(grey(`Found ${clones.length} clones.`));\n\t}\n\n\tprivate cloneFullFound(clone: IClone): void {\n\t\tconst table = new Table(TABLE_OPTIONS);\n\n\t\tcloneFound(clone, this.options);\n\n    // @ts-ignore\n\t\tclone.duplicationA.fragment.split('\\n').forEach((line: string, position: number) => {\n\t\t\t(table).push(generateLine(clone, position, line));\n\t\t});\n\n\t\tconsole.log(table.toString());\n\t\tconsole.log('');\n\t}\n}\n","import {ensureDirSync, writeFileSync} from 'fs-extra';\nimport {getOption, IBlamedLines, IClone, IOptions, IStatistic, ITokenLocation} from '@jscpd/core';\nimport {getPath} from '../utils/reports';\nimport {green} from 'colors/safe';\nimport {join} from \"path\";\nimport {IReporter} from '..';\n\ninterface IDuplication {\n\tformat: string;\n\tlines: number;\n\ttokens: number;\n\tfirstFile: {\n\t\tname: string;\n\t\tstart: number;\n\t\tend: number;\n\t\tstartLoc: ITokenLocation;\n\t\tendLoc: ITokenLocation;\n\t\tblame?: IBlamedLines;\n\t};\n\tsecondFile: {\n\t\tname: string;\n\t\tstart: number;\n\t\tend: number;\n\t\tstartLoc: ITokenLocation;\n\t\tendLoc: ITokenLocation;\n\t\tblame?: IBlamedLines;\n\t};\n\tfragment: string;\n}\n\ninterface IJsonReport {\n\tduplicates: IDuplication[];\n\tstatistics: IStatistic;\n}\n\nexport class JsonReporter implements IReporter {\n\n  constructor(private options: IOptions) {\n  }\n\n  public generateJson(clones: IClone[], statistics: IStatistic): IJsonReport {\n    return {\n      statistics,\n      duplicates: clones.map(clone => this.cloneFound(clone))\n    };\n  }\n\n  public report(clones: IClone[], statistic: IStatistic): void {\n    const json = this.generateJson(clones, statistic);\n    ensureDirSync(getOption('output', this.options));\n    writeFileSync(getOption('output', this.options) + '/jscpd-report.json', JSON.stringify(json, null, '  '));\n    console.log(green(`JSON report saved to ${join(this.options.output as string, 'jscpd-report.json')}`));\n  }\n\n  private cloneFound(clone: IClone): IDuplication {\n    const startLineA = clone.duplicationA.start.line;\n    const endLineA = clone.duplicationA.end.line;\n    const startLineB = clone.duplicationB.start.line;\n    const endLineB = clone.duplicationB.end.line;\n\n    return {\n      format: clone.format,\n      lines: endLineA - startLineA + 1,\n      fragment: clone.duplicationA.fragment as string,\n      tokens: 0,\n      firstFile: {\n        name: getPath(clone.duplicationA.sourceId, this.options),\n        start: startLineA,\n        end: endLineA,\n        startLoc: clone.duplicationA.start,\n        endLoc: clone.duplicationA.end,\n        blame: clone.duplicationA.blame,\n      },\n      secondFile: {\n        name: getPath(clone.duplicationB.sourceId, this.options),\n        start: startLineB,\n        end: endLineB,\n        startLoc: clone.duplicationB.start,\n        endLoc: clone.duplicationB.end,\n        blame: clone.duplicationB.blame,\n      },\n    };\n  }\n}\n","import {IReporter} from '..';\nimport {getOption, IClone, IOptions, IStatistic} from \"@jscpd/core\";\nimport {ensureDirSync, writeFileSync} from \"fs-extra\";\nimport {green} from \"colors/safe\";\nimport {join} from \"path\";\nimport {convertStatisticToArray} from \"../utils/reports\";\n\nexport class CSVReporter implements IReporter {\n\n  constructor(private options: IOptions) {\n  }\n\n  // @ts-ignore\n  report(clones: IClone[], statistic: IStatistic | undefined): void {\n    const report = [\n      ['Format', 'Files analyzed', 'Total lines', 'Total tokens', 'Clones found', 'Duplicated lines', 'Duplicated tokens'],\n      ...Object.keys((statistic as any).formats).map((format: string) => convertStatisticToArray(format, (statistic as any).formats[format].total)),\n      convertStatisticToArray('Total:', (statistic as any).total)\n    ].map((arr) => arr.join(',')).join('\\n');\n\n    ensureDirSync(getOption('output', this.options));\n    writeFileSync(getOption('output', this.options) + '/jscpd-report.csv', report);\n    console.log(green(`CSV report saved to ${join(this.options?.output as string, 'jscpd-report.csv')}`));\n  }\n\n\n}\n","import {getOption, IClone, IOptions, IStatistic} from \"@jscpd/core\";\nimport {ensureDirSync, writeFileSync} from \"fs-extra\";\nimport {green} from \"colors/safe\";\nimport {join} from \"path\";\nimport {convertStatisticToArray} from \"../utils/reports\";\nimport {IReporter} from '..';\nimport markdownTable from \"markdown-table\";\n\nexport class MarkdownReporter implements IReporter {\n\n  constructor(private options: IOptions) {\n  }\n\n  report(clones: IClone[], statistic: IStatistic | undefined): void {\n    const report = `\n# Copy/paste detection report\n\n> Duplications detection: Found ${clones.length} exact clones with ${(statistic as any).total.duplicatedLines}(${(statistic as any).total.percentage}%) duplicated lines in ${(statistic as any).total.sources} (${Object.keys((statistic as any).formats).length} formats) files.\n\n${markdownTable([\n      ['Format', 'Files analyzed', 'Total lines', 'Total tokens', 'Clones found', 'Duplicated lines', 'Duplicated tokens'],\n      ...Object.keys((statistic as any).formats).map((format: string) => convertStatisticToArray(format, (statistic as any).formats[format].total)),\n      convertStatisticToArray('Total:', (statistic as any).total).map(item => `**${item}**`)\n    ])}\n`;\n    ensureDirSync(getOption('output', this.options));\n    writeFileSync(getOption('output', this.options) + '/jscpd-report.md', report);\n    console.log(green(`Markdown report saved to ${join(this.options.output as string, 'jscpd-report.md')}`));\n  }\n}\n","import {writeFileSync} from 'fs';\nimport {ensureDirSync} from 'fs-extra';\nimport {IReporter} from '..';\nimport {getOption, IClone, IOptions} from '@jscpd/core';\nimport {escapeXml, getPath} from '../utils/reports';\nimport {green} from 'colors/safe';\nimport {join} from \"path\";\n\nexport class XmlReporter implements IReporter {\n  constructor(private options: IOptions) {\n  }\n\n\n  public report(clones: IClone[]): void {\n    let xmlDoc = '<?xml version=\"1.0\" encoding=\"UTF-8\" ?>';\n\n    xmlDoc += '<pmd-cpd>';\n\n    clones.forEach((clone: IClone) => {\n      xmlDoc = `${xmlDoc}\n      <duplication lines=\"${clone.duplicationA.end.line - clone.duplicationA.start.line}\">\n            <file path=\"${escapeXml(getPath(clone.duplicationA.sourceId, this.options))}\" line=\"${clone.duplicationA.start.line}\">\n              <codefragment><![CDATA[${clone.duplicationA.fragment?.replace(/]]>/i, 'CDATA_END')}]]></codefragment>\n            </file>\n            <file path=\"${escapeXml(getPath(clone.duplicationB.sourceId, this.options))}\" line=\"${clone.duplicationB.start.line}\">\n              <codefragment><![CDATA[${clone.duplicationB.fragment?.replace(/]]>/i, 'CDATA_END')}]]></codefragment>\n            </file>\n            <codefragment><![CDATA[${clone.duplicationA.fragment?.replace(/]]>/i, 'CDATA_END')}]]></codefragment>\n        </duplication>\n      `;\n\t\t});\n\t\txmlDoc += '</pmd-cpd>';\n\n\t\tensureDirSync(getOption('output', this.options));\n\t\twriteFileSync(getOption('output', this.options) + '/jscpd-report.xml', xmlDoc);\n\t\tconsole.log(green(`XML report saved to ${join(this.options.output as string, 'jscpd-report.xml')}`));\n\t}\n}\n","import {bold} from 'colors/safe';\nimport {IClone, IStatistic} from '@jscpd/core';\nimport {IReporter} from '..';\n\nexport class SilentReporter implements IReporter {\n\n\tpublic report(clones: IClone[], statistic: IStatistic): void {\n\t\tif (statistic) {\n\t\t\tconsole.log(\n\t\t\t\t`Duplications detection: Found ${bold(clones.length.toString())} ` +\n\t\t\t\t`exact clones with ${bold(statistic.total.duplicatedLines.toString())}(${statistic.total.percentage}%) ` +\n\t\t\t\t`duplicated lines in ${bold(statistic.total.sources.toString())} ` +\n\t\t\t\t`(${Object.keys(statistic.formats).length} formats) files.`,\n\t\t\t);\n\t\t}\n\t}\n}\n","import {red} from 'colors/safe';\nimport {IClone, IOptions, IStatistic} from '@jscpd/core';\nimport {IReporter} from '..';\n\nexport class ThresholdReporter implements IReporter {\n\tconstructor(private options: IOptions) {\n\t}\n\n\t// @ts-ignore\n  public report(clones: IClone[], statistic: IStatistic | undefined): void {\n    if (statistic && this.options.threshold !== undefined && this.options.threshold < statistic.total.percentage) {\n      const message = `ERROR: jscpd found too many duplicates (${statistic.total.percentage}%) over threshold (${this.options.threshold}%)`;\n      console.error(red(message));\n      throw new Error(message);\n    }\n\t}\n}\n","import {IClone, IOptions} from '@jscpd/core';\nimport {IReporter} from '..';\nimport {getPath} from '../utils/reports';\n\nexport class XcodeReporter implements IReporter {\n\tconstructor(private readonly options: IOptions) {\n\t}\n\n\tpublic report(clones: IClone[]): void {\n\t\tclones.forEach((clone: IClone) => {\n\t\t\tthis.cloneFound(clone);\n\t\t});\n\t\tconsole.log(`Found ${clones.length} clones.`);\n\t}\n\n\tprivate cloneFound(clone: IClone): void {\n\t\tconst pathA = getPath(clone.duplicationA.sourceId, {...this.options, absolute: true});\n\t\tconst pathB = getPath(clone.duplicationB.sourceId, this.options);\n\t\tconst startLineA = clone.duplicationA.start.line;\n\t\tconst characterA = clone.duplicationA.start.column;\n\t\tconst endLineA = clone.duplicationA.end.line;\n\t\tconst startLineB = clone.duplicationB.start.line;\n\t\tconst endLineB = clone.duplicationB.end.line;\n\t\tconsole.log(`${pathA}:${startLineA}:${characterA}: warning: Found ${endLineA - startLineA} lines (${startLineA}-${endLineA}) duplicated on file ${pathB} (${startLineB}-${endLineB})`);\n\t}\n}\n","import { IClone, IOptions, IStatistic } from \"@jscpd/core\";\nimport { IReporter } from \"..\";\nimport { getPath } from \"../utils/reports\";\n\nfunction normalizePath(p: string): string {\n  return p.replace(/\\\\/g, \"/\");\n}\n\nfunction formatRange(start: number, end: number): string {\n  return `${start}-${end}`;\n}\n\nexport function compressCloneLine(\n  pathA: string,\n  pathB: string,\n  rangeA: string,\n  rangeB: string,\n): string {\n  const normA = normalizePath(pathA);\n  const normB = normalizePath(pathB);\n\n  if (normA === normB) {\n    return `${normA} ${rangeA} ~ ${rangeB}`;\n  }\n\n  const partsA = normA.split(\"/\");\n  const partsB = normB.split(\"/\");\n\n  let commonLen = 0;\n  const minLen = Math.min(partsA.length, partsB.length);\n  // Stop before the filename segment (minLen - 1)\n  while (commonLen < minLen - 1 && partsA[commonLen] === partsB[commonLen]) {\n    commonLen++;\n  }\n\n  if (commonLen === 0) {\n    return `${normA}:${rangeA} ~ ${normB}:${rangeB}`;\n  }\n\n  const prefix = partsA.slice(0, commonLen).join(\"/\");\n  const remA = partsA.slice(commonLen).join(\"/\");\n  const remB = partsB.slice(commonLen).join(\"/\");\n  return `${prefix}/ ${remA}:${rangeA} ~ ${remB}:${rangeB}`;\n}\n\nexport class AiReporter implements IReporter {\n  constructor(private readonly options: IOptions) {}\n\n  report(clones: IClone[], statistic: IStatistic | undefined): void {\n    if (this.options.silent) return;\n\n    console.log(\"Clones:\");\n\n    for (const clone of clones) {\n      const pathA = getPath(clone.duplicationA.sourceId, this.options);\n      const pathB = getPath(clone.duplicationB.sourceId, this.options);\n      const rangeA = formatRange(\n        clone.duplicationA.start.line,\n        clone.duplicationA.end.line,\n      );\n      const rangeB = formatRange(\n        clone.duplicationB.start.line,\n        clone.duplicationB.end.line,\n      );\n      console.log(compressCloneLine(pathA, pathB, rangeA, rangeB));\n    }\n\n    if (statistic) {\n      console.log(\"---\");\n      console.log(\n        `${clones.length} clones · ${statistic.total.percentage.toFixed(1)}% duplication`,\n      );\n    }\n  }\n}\n","export function parseFormatsExtensions(extensions = ''): { [key: string]: string[] } | undefined {\n\tconst result: { [key: string]: string[] } = {};\n\n\tif (!extensions) {\n\t\treturn undefined;\n\t}\n\n\textensions.split(';').forEach((format: string) => {\n\t\tconst pair = format.split(':');\n\t\t// @ts-ignore\n    result[pair[0]] = pair[1].split(',');\n\t});\n\n\treturn result;\n}\n"],"mappings":"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","names":["getOption","getFormatByFile","readFileSync","relative","grey","grey","bold","grey","bold","grey","grey","Table","getOption","green","getOption","getOption","ensureDirSync","writeFileSync","green","join","ensureDirSync","getOption","writeFileSync","green","join","getOption","ensureDirSync","writeFileSync","green","join","ensureDirSync","getOption","writeFileSync","green","join","writeFileSync","ensureDirSync","getOption","green","join","ensureDirSync","getOption","writeFileSync","bold","red"]}