@exercode/problem-utils 4.3.1 → 4.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/checkAllProblems.cjs.map +1 -1
- package/dist/cli/checkAllProblems.js.map +1 -1
- package/dist/cli/exercodeProblem.cjs.map +1 -1
- package/dist/cli/exercodeProblem.js.map +1 -1
- package/dist/cli/runSingleHarness.cjs.map +1 -1
- package/dist/cli/runSingleHarness.js.map +1 -1
- package/dist/cli/validateLearningMaterial.cjs.map +1 -1
- package/dist/cli/validateLearningMaterial.js.map +1 -1
- package/dist/helpers/checkProblemDirIsolation.cjs.map +1 -1
- package/dist/helpers/checkProblemDirIsolation.js.map +1 -1
- package/dist/helpers/cleanWorkingDirectory.cjs.map +1 -1
- package/dist/helpers/cleanWorkingDirectory.js.map +1 -1
- package/dist/helpers/compareExpectedOutputFiles.cjs.map +1 -1
- package/dist/helpers/compareExpectedOutputFiles.js.map +1 -1
- package/dist/helpers/compareStdoutAsSpaceSeparatedTokens.cjs.map +1 -1
- package/dist/helpers/compareStdoutAsSpaceSeparatedTokens.js.map +1 -1
- package/dist/helpers/copyTestCaseFileInput.cjs.map +1 -1
- package/dist/helpers/copyTestCaseFileInput.js.map +1 -1
- package/dist/helpers/defaultStdioHarness.cjs.map +1 -1
- package/dist/helpers/defaultStdioHarness.js.map +1 -1
- package/dist/helpers/findEntryPointFile.cjs.map +1 -1
- package/dist/helpers/findEntryPointFile.js.map +1 -1
- package/dist/helpers/findLanguageDefinitionByPath.cjs.map +1 -1
- package/dist/helpers/findLanguageDefinitionByPath.js.map +1 -1
- package/dist/helpers/findModelAnswerDirs.cjs.map +1 -1
- package/dist/helpers/findModelAnswerDirs.js.map +1 -1
- package/dist/helpers/guiRecording.cjs.map +1 -1
- package/dist/helpers/guiRecording.js.map +1 -1
- package/dist/helpers/javaJudge.cjs.map +1 -1
- package/dist/helpers/javaJudge.js.map +1 -1
- package/dist/helpers/judgeByStaticAnalysis.cjs.map +1 -1
- package/dist/helpers/judgeByStaticAnalysis.js.map +1 -1
- package/dist/helpers/parseArgs.cjs.map +1 -1
- package/dist/helpers/parseArgs.js.map +1 -1
- package/dist/helpers/parseCsv.cjs.map +1 -1
- package/dist/helpers/parseCsv.js.map +1 -1
- package/dist/helpers/printDebugBanner.cjs.map +1 -1
- package/dist/helpers/printDebugBanner.js.map +1 -1
- package/dist/helpers/printTestCaseResult.cjs.map +1 -1
- package/dist/helpers/printTestCaseResult.js.map +1 -1
- package/dist/helpers/readOutputFiles.cjs.map +1 -1
- package/dist/helpers/readOutputFiles.js.map +1 -1
- package/dist/helpers/readProblemMarkdownFrontMatter.cjs.map +1 -1
- package/dist/helpers/readProblemMarkdownFrontMatter.js.map +1 -1
- package/dist/helpers/readTestCases.cjs.map +1 -1
- package/dist/helpers/readTestCases.js.map +1 -1
- package/dist/helpers/removeCommentsInSourceCode.cjs.map +1 -1
- package/dist/helpers/removeCommentsInSourceCode.js.map +1 -1
- package/dist/helpers/resolveCwds.cjs.map +1 -1
- package/dist/helpers/resolveCwds.js.map +1 -1
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.cjs.map +1 -1
- package/dist/helpers/runCommandInTemporaryPackageManagerProject.js.map +1 -1
- package/dist/helpers/runHarnessProcess.cjs.map +1 -1
- package/dist/helpers/runHarnessProcess.js.map +1 -1
- package/dist/helpers/runIsolationCheckInDebugMode.cjs.map +1 -1
- package/dist/helpers/runIsolationCheckInDebugMode.js.map +1 -1
- package/dist/helpers/runPythonInTemporaryUvProject.cjs.map +1 -1
- package/dist/helpers/runPythonInTemporaryUvProject.js.map +1 -1
- package/dist/helpers/sourceCodeGrammars.cjs.map +1 -1
- package/dist/helpers/sourceCodeGrammars.js.map +1 -1
- package/dist/helpers/spawnWithLimits.cjs.map +1 -1
- package/dist/helpers/spawnWithLimits.js.map +1 -1
- package/dist/helpers/spawnWithTimeout.cjs.map +1 -1
- package/dist/helpers/spawnWithTimeout.js.map +1 -1
- package/dist/helpers/startHttpServer.cjs.map +1 -1
- package/dist/helpers/startHttpServer.js.map +1 -1
- package/dist/helpers/stdioJudgeRules.cjs.map +1 -1
- package/dist/helpers/stdioJudgeRules.js.map +1 -1
- package/dist/helpers/temporaryProblemDirCopy.cjs.map +1 -1
- package/dist/helpers/temporaryProblemDirCopy.js.map +1 -1
- package/dist/learningMaterial/frontmatter.cjs.map +1 -1
- package/dist/learningMaterial/frontmatter.js.map +1 -1
- package/dist/learningMaterial/fsHelpers.cjs.map +1 -1
- package/dist/learningMaterial/fsHelpers.js.map +1 -1
- package/dist/learningMaterial/schemas.cjs.map +1 -1
- package/dist/learningMaterial/schemas.js.map +1 -1
- package/dist/learningMaterial/validateContest.cjs.map +1 -1
- package/dist/learningMaterial/validateContest.js.map +1 -1
- package/dist/learningMaterial/validateCourse.cjs.map +1 -1
- package/dist/learningMaterial/validateCourse.js.map +1 -1
- package/dist/learningMaterial/validateMaterial.cjs.map +1 -1
- package/dist/learningMaterial/validateMaterial.js.map +1 -1
- package/dist/learningMaterial/validateProblem.cjs.map +1 -1
- package/dist/learningMaterial/validateProblem.js.map +1 -1
- package/dist/learningMaterial/validationResult.cjs.map +1 -1
- package/dist/learningMaterial/validationResult.js.map +1 -1
- package/dist/presets/command.cjs.map +1 -1
- package/dist/presets/command.js.map +1 -1
- package/dist/presets/evaluation.cjs.map +1 -1
- package/dist/presets/evaluation.js.map +1 -1
- package/dist/presets/guiCommand.cjs.map +1 -1
- package/dist/presets/guiCommand.js.map +1 -1
- package/dist/presets/springBoot.cjs.map +1 -1
- package/dist/presets/springBoot.js.map +1 -1
- package/dist/presets/stdio.cjs.map +1 -1
- package/dist/presets/stdio.js.map +1 -1
- package/dist/presets/tomcat.cjs.map +1 -1
- package/dist/presets/tomcat.js.map +1 -1
- package/dist/types/decisionCode.cjs.map +1 -1
- package/dist/types/decisionCode.js.map +1 -1
- package/dist/types/language.cjs.map +1 -1
- package/dist/types/language.js.map +1 -1
- package/dist/types/problem.cjs.map +1 -1
- package/dist/types/problem.js.map +1 -1
- package/dist/types/testCaseResult.cjs.map +1 -1
- package/dist/types/testCaseResult.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseCsv.cjs","names":[],"sources":["../../src/helpers/parseCsv.ts"],"sourcesContent":["export type CsvParseErrorReason = 'unterminated_quote' | 'unexpected_quote' | 'text_after_quoted_field';\n\nexport class CsvParseError extends Error {\n readonly reason: CsvParseErrorReason;\n /** 1-based physical line where the error was detected (the record's start line for an unterminated quote). */\n readonly lineNumber: number;\n\n constructor(reason: CsvParseErrorReason, lineNumber: number) {\n super(`${reason.replaceAll('_', ' ')} on line ${lineNumber}`);\n this.name = 'CsvParseError';\n this.reason = reason;\n this.lineNumber = lineNumber;\n }\n}\n\nexport interface CsvRecord {\n cells: string[];\n /** 1-based physical line on which the record starts (quoted fields may span several lines). */\n lineNumber: number;\n}\n\n/**\n * Parse RFC 4180 style CSV text (double-quoted fields, `\"\"` escapes, LF, CRLF, or CR line ends) into rows.\n * A trailing line end does not produce an extra row.\n *\n * @throws {CsvParseError} when a quoted field is not closed, or a quote appears anywhere but around a whole field.\n */\nexport function parseCsv(text: string): string[][] {\n return parseCsvRecords(text).map((record) => record.cells);\n}\n\n/** Like {@link parseCsv}, but also reports the physical line each record starts on. */\nexport function parseCsvRecords(text: string): CsvRecord[] {\n const records: CsvRecord[] = [];\n let cells: string[] = [];\n let field = '';\n let fieldState: 'start' | 'unquoted' | 'quoted' | 'closed' = 'start';\n let hasField = false;\n let lineNumber = 1;\n let recordLineNumber = 1;\n let index = 0;\n const content = text.startsWith('\\uFEFF') ? text.slice(1) : text;\n\n const endField = (): void => {\n cells.push(field);\n field = '';\n fieldState = 'start';\n };\n\n while (index < content.length) {\n const char = content[index] as string;\n if (fieldState === 'quoted') {\n if (char === '\"') {\n if (content[index + 1] === '\"') {\n field += '\"';\n index += 2;\n continue;\n }\n fieldState = 'closed';\n } else {\n if (char === '\\n' || (char === '\\r' && content[index + 1] !== '\\n')) lineNumber++;\n field += char;\n }\n index++;\n continue;\n }\n\n hasField = true;\n if (char === ',' || char === '\\n' || char === '\\r') {\n endField();\n if (char !== ',') {\n records.push({ cells, lineNumber: recordLineNumber });\n cells = [];\n hasField = false;\n if (char === '\\r' && content[index + 1] === '\\n') index++;\n lineNumber++;\n recordLineNumber = lineNumber;\n }\n } else if (char === '\"') {\n if (fieldState !== 'start') throw new CsvParseError('unexpected_quote', lineNumber);\n fieldState = 'quoted';\n } else if (fieldState === 'closed') {\n throw new CsvParseError('text_after_quoted_field', lineNumber);\n } else {\n fieldState = 'unquoted';\n field += char;\n }\n index++;\n }\n\n if (fieldState === 'quoted') throw new CsvParseError('unterminated_quote', recordLineNumber);\n if (hasField) {\n endField();\n records.push({ cells, lineNumber: recordLineNumber });\n }\n return records;\n}\n"],"mappings":"aAEA,
|
|
1
|
+
{"version":3,"file":"parseCsv.cjs","names":["CsvParseError","reason","lineNumber","parseCsv","parseCsvRecords","text","record","records","cells","field","fieldState","hasField","recordLineNumber","index","content","endField","char"],"sources":["../../src/helpers/parseCsv.ts"],"sourcesContent":["export type CsvParseErrorReason = 'unterminated_quote' | 'unexpected_quote' | 'text_after_quoted_field';\n\nexport class CsvParseError extends Error {\n readonly reason: CsvParseErrorReason;\n /** 1-based physical line where the error was detected (the record's start line for an unterminated quote). */\n readonly lineNumber: number;\n\n constructor(reason: CsvParseErrorReason, lineNumber: number) {\n super(`${reason.replaceAll('_', ' ')} on line ${lineNumber}`);\n this.name = 'CsvParseError';\n this.reason = reason;\n this.lineNumber = lineNumber;\n }\n}\n\nexport interface CsvRecord {\n cells: string[];\n /** 1-based physical line on which the record starts (quoted fields may span several lines). */\n lineNumber: number;\n}\n\n/**\n * Parse RFC 4180 style CSV text (double-quoted fields, `\"\"` escapes, LF, CRLF, or CR line ends) into rows.\n * A trailing line end does not produce an extra row.\n *\n * @throws {CsvParseError} when a quoted field is not closed, or a quote appears anywhere but around a whole field.\n */\nexport function parseCsv(text: string): string[][] {\n return parseCsvRecords(text).map((record) => record.cells);\n}\n\n/** Like {@link parseCsv}, but also reports the physical line each record starts on. */\nexport function parseCsvRecords(text: string): CsvRecord[] {\n const records: CsvRecord[] = [];\n let cells: string[] = [];\n let field = '';\n let fieldState: 'start' | 'unquoted' | 'quoted' | 'closed' = 'start';\n let hasField = false;\n let lineNumber = 1;\n let recordLineNumber = 1;\n let index = 0;\n const content = text.startsWith('\\uFEFF') ? text.slice(1) : text;\n\n const endField = (): void => {\n cells.push(field);\n field = '';\n fieldState = 'start';\n };\n\n while (index < content.length) {\n const char = content[index] as string;\n if (fieldState === 'quoted') {\n if (char === '\"') {\n if (content[index + 1] === '\"') {\n field += '\"';\n index += 2;\n continue;\n }\n fieldState = 'closed';\n } else {\n if (char === '\\n' || (char === '\\r' && content[index + 1] !== '\\n')) lineNumber++;\n field += char;\n }\n index++;\n continue;\n }\n\n hasField = true;\n if (char === ',' || char === '\\n' || char === '\\r') {\n endField();\n if (char !== ',') {\n records.push({ cells, lineNumber: recordLineNumber });\n cells = [];\n hasField = false;\n if (char === '\\r' && content[index + 1] === '\\n') index++;\n lineNumber++;\n recordLineNumber = lineNumber;\n }\n } else if (char === '\"') {\n if (fieldState !== 'start') throw new CsvParseError('unexpected_quote', lineNumber);\n fieldState = 'quoted';\n } else if (fieldState === 'closed') {\n throw new CsvParseError('text_after_quoted_field', lineNumber);\n } else {\n fieldState = 'unquoted';\n field += char;\n }\n index++;\n }\n\n if (fieldState === 'quoted') throw new CsvParseError('unterminated_quote', recordLineNumber);\n if (hasField) {\n endField();\n records.push({ cells, lineNumber: recordLineNumber });\n }\n return records;\n}\n"],"mappings":"aAEA,IAAaA,EAAb,cAAmC,KAAM,CACvC,OAEA,WAEA,YAAY,EAA6B,EAAoB,CAC3D,MAAM,GAAGC,EAAO,WAAW,IAAK,GAAG,EAAE,WAAWC,GAAY,EAC5D,KAAK,KAAO,gBACZ,KAAK,OAASD,EACd,KAAK,WAAaC,CACpB,CACF,EAcA,SAAgBC,EAAS,EAA0B,CACjD,OAAOC,EAAgBC,CAAI,CAAC,CAAC,IAAK,GAAWC,EAAO,KAAK,CAC3D,CAGA,SAAgBF,EAAgB,EAA2B,CACzD,IAAMG,EAAuB,CAAC,EAC1BC,EAAkB,CAAC,EACnBC,EAAQ,GACRC,EAAyD,QACzDC,EAAW,GACXT,EAAa,EACbU,EAAmB,EACnBC,EAAQ,EACNC,EAAUT,EAAK,WAAW,GAAQ,EAAIA,EAAK,MAAM,CAAC,EAAIA,EAEtDU,MAAuB,CAC3BP,EAAM,KAAKC,CAAK,EAChB,EAAQ,GACR,EAAa,OACf,EAEA,KAAOI,EAAQC,EAAQ,QAAQ,CAC7B,IAAME,EAAOF,EAAQD,GACrB,GAAIH,IAAe,SAAU,CAC3B,GAAIM,IAAS,IAAK,CAChB,GAAIF,EAAQD,EAAQ,KAAO,IAAK,CAC9B,GAAS,IACT,GAAS,EACT,QACF,CACA,EAAa,QACf,MACMG,IAAS;GAASA,IAAS,MAAQF,EAAQD,EAAQ,KAAO;IAAO,IACrE,GAASG,EAEX,IACA,QACF,CAGA,GADA,EAAW,GACPA,IAAS,KAAOA,IAAS;GAAQA,IAAS,KAC5CD,EAAS,EACLC,IAAS,MACXT,EAAQ,KAAK,CAAE,QAAO,WAAYK,CAAiB,CAAC,EACpD,EAAQ,CAAC,EACT,EAAW,GACPI,IAAS,MAAQF,EAAQD,EAAQ,KAAO;GAAM,IAClD,IACA,EAAmBX,QAEhB,GAAIc,IAAS,IAAK,CACvB,GAAIN,IAAe,QAAS,MAAM,IAAIV,EAAc,mBAAoBE,CAAU,EAClF,EAAa,QACf,MAAO,GAAIQ,IAAe,SACxB,MAAM,IAAIV,EAAc,0BAA2BE,CAAU,MAE7D,GAAa,WACb,GAASc,EAEX,GACF,CAEA,GAAIN,IAAe,SAAU,MAAM,IAAIV,EAAc,qBAAsBY,CAAgB,EAK3F,OAJID,IACFI,EAAS,EACTR,EAAQ,KAAK,CAAE,QAAO,WAAYK,CAAiB,CAAC,GAE/CL,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseCsv.js","names":[],"sources":["../../src/helpers/parseCsv.ts"],"sourcesContent":["export type CsvParseErrorReason = 'unterminated_quote' | 'unexpected_quote' | 'text_after_quoted_field';\n\nexport class CsvParseError extends Error {\n readonly reason: CsvParseErrorReason;\n /** 1-based physical line where the error was detected (the record's start line for an unterminated quote). */\n readonly lineNumber: number;\n\n constructor(reason: CsvParseErrorReason, lineNumber: number) {\n super(`${reason.replaceAll('_', ' ')} on line ${lineNumber}`);\n this.name = 'CsvParseError';\n this.reason = reason;\n this.lineNumber = lineNumber;\n }\n}\n\nexport interface CsvRecord {\n cells: string[];\n /** 1-based physical line on which the record starts (quoted fields may span several lines). */\n lineNumber: number;\n}\n\n/**\n * Parse RFC 4180 style CSV text (double-quoted fields, `\"\"` escapes, LF, CRLF, or CR line ends) into rows.\n * A trailing line end does not produce an extra row.\n *\n * @throws {CsvParseError} when a quoted field is not closed, or a quote appears anywhere but around a whole field.\n */\nexport function parseCsv(text: string): string[][] {\n return parseCsvRecords(text).map((record) => record.cells);\n}\n\n/** Like {@link parseCsv}, but also reports the physical line each record starts on. */\nexport function parseCsvRecords(text: string): CsvRecord[] {\n const records: CsvRecord[] = [];\n let cells: string[] = [];\n let field = '';\n let fieldState: 'start' | 'unquoted' | 'quoted' | 'closed' = 'start';\n let hasField = false;\n let lineNumber = 1;\n let recordLineNumber = 1;\n let index = 0;\n const content = text.startsWith('\\uFEFF') ? text.slice(1) : text;\n\n const endField = (): void => {\n cells.push(field);\n field = '';\n fieldState = 'start';\n };\n\n while (index < content.length) {\n const char = content[index] as string;\n if (fieldState === 'quoted') {\n if (char === '\"') {\n if (content[index + 1] === '\"') {\n field += '\"';\n index += 2;\n continue;\n }\n fieldState = 'closed';\n } else {\n if (char === '\\n' || (char === '\\r' && content[index + 1] !== '\\n')) lineNumber++;\n field += char;\n }\n index++;\n continue;\n }\n\n hasField = true;\n if (char === ',' || char === '\\n' || char === '\\r') {\n endField();\n if (char !== ',') {\n records.push({ cells, lineNumber: recordLineNumber });\n cells = [];\n hasField = false;\n if (char === '\\r' && content[index + 1] === '\\n') index++;\n lineNumber++;\n recordLineNumber = lineNumber;\n }\n } else if (char === '\"') {\n if (fieldState !== 'start') throw new CsvParseError('unexpected_quote', lineNumber);\n fieldState = 'quoted';\n } else if (fieldState === 'closed') {\n throw new CsvParseError('text_after_quoted_field', lineNumber);\n } else {\n fieldState = 'unquoted';\n field += char;\n }\n index++;\n }\n\n if (fieldState === 'quoted') throw new CsvParseError('unterminated_quote', recordLineNumber);\n if (hasField) {\n endField();\n records.push({ cells, lineNumber: recordLineNumber });\n }\n return records;\n}\n"],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"parseCsv.js","names":["CsvParseError","reason","lineNumber","parseCsv","parseCsvRecords","text","record","records","cells","field","fieldState","hasField","recordLineNumber","index","content","endField","char"],"sources":["../../src/helpers/parseCsv.ts"],"sourcesContent":["export type CsvParseErrorReason = 'unterminated_quote' | 'unexpected_quote' | 'text_after_quoted_field';\n\nexport class CsvParseError extends Error {\n readonly reason: CsvParseErrorReason;\n /** 1-based physical line where the error was detected (the record's start line for an unterminated quote). */\n readonly lineNumber: number;\n\n constructor(reason: CsvParseErrorReason, lineNumber: number) {\n super(`${reason.replaceAll('_', ' ')} on line ${lineNumber}`);\n this.name = 'CsvParseError';\n this.reason = reason;\n this.lineNumber = lineNumber;\n }\n}\n\nexport interface CsvRecord {\n cells: string[];\n /** 1-based physical line on which the record starts (quoted fields may span several lines). */\n lineNumber: number;\n}\n\n/**\n * Parse RFC 4180 style CSV text (double-quoted fields, `\"\"` escapes, LF, CRLF, or CR line ends) into rows.\n * A trailing line end does not produce an extra row.\n *\n * @throws {CsvParseError} when a quoted field is not closed, or a quote appears anywhere but around a whole field.\n */\nexport function parseCsv(text: string): string[][] {\n return parseCsvRecords(text).map((record) => record.cells);\n}\n\n/** Like {@link parseCsv}, but also reports the physical line each record starts on. */\nexport function parseCsvRecords(text: string): CsvRecord[] {\n const records: CsvRecord[] = [];\n let cells: string[] = [];\n let field = '';\n let fieldState: 'start' | 'unquoted' | 'quoted' | 'closed' = 'start';\n let hasField = false;\n let lineNumber = 1;\n let recordLineNumber = 1;\n let index = 0;\n const content = text.startsWith('\\uFEFF') ? text.slice(1) : text;\n\n const endField = (): void => {\n cells.push(field);\n field = '';\n fieldState = 'start';\n };\n\n while (index < content.length) {\n const char = content[index] as string;\n if (fieldState === 'quoted') {\n if (char === '\"') {\n if (content[index + 1] === '\"') {\n field += '\"';\n index += 2;\n continue;\n }\n fieldState = 'closed';\n } else {\n if (char === '\\n' || (char === '\\r' && content[index + 1] !== '\\n')) lineNumber++;\n field += char;\n }\n index++;\n continue;\n }\n\n hasField = true;\n if (char === ',' || char === '\\n' || char === '\\r') {\n endField();\n if (char !== ',') {\n records.push({ cells, lineNumber: recordLineNumber });\n cells = [];\n hasField = false;\n if (char === '\\r' && content[index + 1] === '\\n') index++;\n lineNumber++;\n recordLineNumber = lineNumber;\n }\n } else if (char === '\"') {\n if (fieldState !== 'start') throw new CsvParseError('unexpected_quote', lineNumber);\n fieldState = 'quoted';\n } else if (fieldState === 'closed') {\n throw new CsvParseError('text_after_quoted_field', lineNumber);\n } else {\n fieldState = 'unquoted';\n field += char;\n }\n index++;\n }\n\n if (fieldState === 'quoted') throw new CsvParseError('unterminated_quote', recordLineNumber);\n if (hasField) {\n endField();\n records.push({ cells, lineNumber: recordLineNumber });\n }\n return records;\n}\n"],"mappings":"AAEA,IAAaA,EAAb,cAAmC,KAAM,CACvC,OAEA,WAEA,YAAY,EAA6B,EAAoB,CAC3D,MAAM,GAAGC,EAAO,WAAW,IAAK,GAAG,EAAE,WAAWC,GAAY,EAC5D,KAAK,KAAO,gBACZ,KAAK,OAASD,EACd,KAAK,WAAaC,CACpB,CACF,EAcA,SAAgBC,EAAS,EAA0B,CACjD,OAAOC,EAAgBC,CAAI,CAAC,CAAC,IAAK,GAAWC,EAAO,KAAK,CAC3D,CAGA,SAAgBF,EAAgB,EAA2B,CACzD,IAAMG,EAAuB,CAAC,EAC1BC,EAAkB,CAAC,EACnBC,EAAQ,GACRC,EAAyD,QACzDC,EAAW,GACXT,EAAa,EACbU,EAAmB,EACnBC,EAAQ,EACNC,EAAUT,EAAK,WAAW,GAAQ,EAAIA,EAAK,MAAM,CAAC,EAAIA,EAEtDU,MAAuB,CAC3BP,EAAM,KAAKC,CAAK,EAChB,EAAQ,GACR,EAAa,OACf,EAEA,KAAOI,EAAQC,EAAQ,QAAQ,CAC7B,IAAME,EAAOF,EAAQD,GACrB,GAAIH,IAAe,SAAU,CAC3B,GAAIM,IAAS,IAAK,CAChB,GAAIF,EAAQD,EAAQ,KAAO,IAAK,CAC9B,GAAS,IACT,GAAS,EACT,QACF,CACA,EAAa,QACf,MACMG,IAAS;GAASA,IAAS,MAAQF,EAAQD,EAAQ,KAAO;IAAO,IACrE,GAASG,EAEX,IACA,QACF,CAGA,GADA,EAAW,GACPA,IAAS,KAAOA,IAAS;GAAQA,IAAS,KAC5CD,EAAS,EACLC,IAAS,MACXT,EAAQ,KAAK,CAAE,QAAO,WAAYK,CAAiB,CAAC,EACpD,EAAQ,CAAC,EACT,EAAW,GACPI,IAAS,MAAQF,EAAQD,EAAQ,KAAO;GAAM,IAClD,IACA,EAAmBX,QAEhB,GAAIc,IAAS,IAAK,CACvB,GAAIN,IAAe,QAAS,MAAM,IAAIV,EAAc,mBAAoBE,CAAU,EAClF,EAAa,QACf,MAAO,GAAIQ,IAAe,SACxB,MAAM,IAAIV,EAAc,0BAA2BE,CAAU,MAE7D,GAAa,WACb,GAASc,EAEX,GACF,CAEA,GAAIN,IAAe,SAAU,MAAM,IAAIV,EAAc,qBAAsBY,CAAgB,EAK3F,OAJID,IACFI,EAAS,EACTR,EAAQ,KAAK,CAAE,QAAO,WAAYK,CAAiB,CAAC,GAE/CL,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printDebugBanner.cjs","names":[],"sources":["../../src/helpers/printDebugBanner.ts"],"sourcesContent":["const BANNER_LINE = '='.repeat(72);\n\n/**\n * Print a prominent, multi-line banner to stderr so that debug-mode runs\n * (e.g., judging against model answers without an explicit cwd) are obvious.\n *\n * Written to stderr to avoid interfering with `printTestCaseResult` output on stdout.\n */\nexport function printDebugBanner(lines: readonly string[]): void {\n const body = lines.map((line) => ` ${line}`).join('\\n');\n console.warn(`\\n${BANNER_LINE}\\n${body}\\n${BANNER_LINE}`);\n}\n"],"mappings":"aAAA,
|
|
1
|
+
{"version":3,"file":"printDebugBanner.cjs","names":["BANNER_LINE","printDebugBanner","body","lines","line"],"sources":["../../src/helpers/printDebugBanner.ts"],"sourcesContent":["const BANNER_LINE = '='.repeat(72);\n\n/**\n * Print a prominent, multi-line banner to stderr so that debug-mode runs\n * (e.g., judging against model answers without an explicit cwd) are obvious.\n *\n * Written to stderr to avoid interfering with `printTestCaseResult` output on stdout.\n */\nexport function printDebugBanner(lines: readonly string[]): void {\n const body = lines.map((line) => ` ${line}`).join('\\n');\n console.warn(`\\n${BANNER_LINE}\\n${body}\\n${BANNER_LINE}`);\n}\n"],"mappings":"aAAA,MAAMA,EAAc,IAAI,OAAO,EAAE,EAQjC,SAAgBC,EAAiB,EAAgC,CAC/D,IAAMC,EAAOC,EAAM,IAAK,GAAS,KAAKC,GAAM,CAAC,CAAC,KAAK;CAAI,EACvD,QAAQ,KAAK,KAAKJ,EAAY,IAAIE,EAAK,IAAIF,GAAa,CAC1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printDebugBanner.js","names":[],"sources":["../../src/helpers/printDebugBanner.ts"],"sourcesContent":["const BANNER_LINE = '='.repeat(72);\n\n/**\n * Print a prominent, multi-line banner to stderr so that debug-mode runs\n * (e.g., judging against model answers without an explicit cwd) are obvious.\n *\n * Written to stderr to avoid interfering with `printTestCaseResult` output on stdout.\n */\nexport function printDebugBanner(lines: readonly string[]): void {\n const body = lines.map((line) => ` ${line}`).join('\\n');\n console.warn(`\\n${BANNER_LINE}\\n${body}\\n${BANNER_LINE}`);\n}\n"],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"printDebugBanner.js","names":["BANNER_LINE","printDebugBanner","body","lines","line"],"sources":["../../src/helpers/printDebugBanner.ts"],"sourcesContent":["const BANNER_LINE = '='.repeat(72);\n\n/**\n * Print a prominent, multi-line banner to stderr so that debug-mode runs\n * (e.g., judging against model answers without an explicit cwd) are obvious.\n *\n * Written to stderr to avoid interfering with `printTestCaseResult` output on stdout.\n */\nexport function printDebugBanner(lines: readonly string[]): void {\n const body = lines.map((line) => ` ${line}`).join('\\n');\n console.warn(`\\n${BANNER_LINE}\\n${body}\\n${BANNER_LINE}`);\n}\n"],"mappings":"AAAA,MAAMA,EAAc,IAAI,OAAO,EAAE,EAQjC,SAAgBC,EAAiB,EAAgC,CAC/D,IAAMC,EAAOC,EAAM,IAAK,GAAS,KAAKC,GAAM,CAAC,CAAC,KAAK;CAAI,EACvD,QAAQ,KAAK,KAAKJ,EAAY,IAAIE,EAAK,IAAIF,GAAa,CAC1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printTestCaseResult.cjs","names":["TEST_CASE_RESULT_PREFIX"],"sources":["../../src/helpers/printTestCaseResult.ts"],"sourcesContent":["import type { TestCaseResult } from '../types/testCaseResult.js';\nimport { TEST_CASE_RESULT_PREFIX } from '../types/testCaseResult.js';\n\n/**\n * Print a test case result in a format that can be read by the judge server.\n */\nexport function printTestCaseResult(result: TestCaseResult): void {\n console.info(`${TEST_CASE_RESULT_PREFIX}${JSON.stringify(result)}`);\n}\n\nexport function encodeFileForTestCaseResult(\n path: string,\n data: Buffer\n): NonNullable<TestCaseResult['outputFiles']>[number] {\n const utf8Text = data.toString('utf8');\n const isBinary = utf8Text.includes('\\uFFFD');\n return isBinary ? { path, encoding: 'base64', data: data.toString('base64') } : { path, data: utf8Text };\n}\n"],"mappings":"4DAMA,
|
|
1
|
+
{"version":3,"file":"printTestCaseResult.cjs","names":["TEST_CASE_RESULT_PREFIX","require_testCaseResult","printTestCaseResult","result","encodeFileForTestCaseResult","utf8Text","data"],"sources":["../../src/helpers/printTestCaseResult.ts"],"sourcesContent":["import type { TestCaseResult } from '../types/testCaseResult.js';\nimport { TEST_CASE_RESULT_PREFIX } from '../types/testCaseResult.js';\n\n/**\n * Print a test case result in a format that can be read by the judge server.\n */\nexport function printTestCaseResult(result: TestCaseResult): void {\n console.info(`${TEST_CASE_RESULT_PREFIX}${JSON.stringify(result)}`);\n}\n\nexport function encodeFileForTestCaseResult(\n path: string,\n data: Buffer\n): NonNullable<TestCaseResult['outputFiles']>[number] {\n const utf8Text = data.toString('utf8');\n const isBinary = utf8Text.includes('\\uFFFD');\n return isBinary ? { path, encoding: 'base64', data: data.toString('base64') } : { path, data: utf8Text };\n}\n"],"mappings":"4DAMA,SAAgBE,EAAoB,EAA8B,CAChE,QAAQ,KAAK,GAAGF,EAAAA,0BAA0B,KAAK,UAAUG,CAAM,GAAG,CACpE,CAEA,SAAgBC,EACd,EACA,EACoD,CACpD,IAAMC,EAAWC,EAAK,SAAS,MAAM,EAErC,OADiBD,EAAS,SAAS,GACrB,EAAI,CAAE,OAAM,SAAU,SAAU,KAAMC,EAAK,SAAS,QAAQ,CAAE,EAAI,CAAE,OAAM,KAAMD,CAAS,CACzG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printTestCaseResult.js","names":[],"sources":["../../src/helpers/printTestCaseResult.ts"],"sourcesContent":["import type { TestCaseResult } from '../types/testCaseResult.js';\nimport { TEST_CASE_RESULT_PREFIX } from '../types/testCaseResult.js';\n\n/**\n * Print a test case result in a format that can be read by the judge server.\n */\nexport function printTestCaseResult(result: TestCaseResult): void {\n console.info(`${TEST_CASE_RESULT_PREFIX}${JSON.stringify(result)}`);\n}\n\nexport function encodeFileForTestCaseResult(\n path: string,\n data: Buffer\n): NonNullable<TestCaseResult['outputFiles']>[number] {\n const utf8Text = data.toString('utf8');\n const isBinary = utf8Text.includes('\\uFFFD');\n return isBinary ? { path, encoding: 'base64', data: data.toString('base64') } : { path, data: utf8Text };\n}\n"],"mappings":"qEAMA,
|
|
1
|
+
{"version":3,"file":"printTestCaseResult.js","names":["printTestCaseResult","TEST_CASE_RESULT_PREFIX","result","encodeFileForTestCaseResult","utf8Text","data"],"sources":["../../src/helpers/printTestCaseResult.ts"],"sourcesContent":["import type { TestCaseResult } from '../types/testCaseResult.js';\nimport { TEST_CASE_RESULT_PREFIX } from '../types/testCaseResult.js';\n\n/**\n * Print a test case result in a format that can be read by the judge server.\n */\nexport function printTestCaseResult(result: TestCaseResult): void {\n console.info(`${TEST_CASE_RESULT_PREFIX}${JSON.stringify(result)}`);\n}\n\nexport function encodeFileForTestCaseResult(\n path: string,\n data: Buffer\n): NonNullable<TestCaseResult['outputFiles']>[number] {\n const utf8Text = data.toString('utf8');\n const isBinary = utf8Text.includes('\\uFFFD');\n return isBinary ? { path, encoding: 'base64', data: data.toString('base64') } : { path, data: utf8Text };\n}\n"],"mappings":"qEAMA,SAAgBA,EAAoB,EAA8B,CAChE,QAAQ,KAAK,GAAGC,IAA0B,KAAK,UAAUC,CAAM,GAAG,CACpE,CAEA,SAAgBC,EACd,EACA,EACoD,CACpD,IAAMC,EAAWC,EAAK,SAAS,MAAM,EAErC,OADiBD,EAAS,SAAS,GACrB,EAAI,CAAE,OAAM,SAAU,SAAU,KAAMC,EAAK,SAAS,QAAQ,CAAE,EAAI,CAAE,OAAM,KAAMD,CAAS,CACzG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readOutputFiles.cjs","names":["fs","path","encodeFileForTestCaseResult"],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n // Read as-is on purpose: the submission runs as the same OS user as this harness, so a symlink\n // only reaches what it can already read, and a planted FIFO only stalls its own run, which the\n // judge server's request timeout ends.\n const buffer = await fs.promises.readFile(path.join(cwd, filePath));\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n"],"mappings":"+LAOA,
|
|
1
|
+
{"version":3,"file":"readOutputFiles.cjs","names":["fs","path","encodeFileForTestCaseResult","require_runtime","require_printTestCaseResult","node_fs","node_path","readOutputFiles","outputFiles","filePath","outputFilePaths","buffer","cwd"],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n // Read as-is on purpose: the submission runs as the same OS user as this harness, so a symlink\n // only reaches what it can already read, and a planted FIFO only stalls its own run, which the\n // judge server's request timeout ends.\n const buffer = await fs.promises.readFile(path.join(cwd, filePath));\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n"],"mappings":"+LAOA,eAAsBO,EACpB,EACA,EACqD,CACrD,IAAMC,EAA0D,CAAC,EACjE,IAAK,IAAMC,KAAYC,EACrB,GAAI,CAIF,IAAMC,EAAS,MAAMX,EAAAA,QAAG,SAAS,SAASC,EAAAA,QAAK,KAAKW,EAAKH,CAAQ,CAAC,EAClED,EAAY,KAAKN,EAAAA,4BAA4BO,EAAUE,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAOH,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readOutputFiles.js","names":[],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n // Read as-is on purpose: the submission runs as the same OS user as this harness, so a symlink\n // only reaches what it can already read, and a planted FIFO only stalls its own run, which the\n // judge server's request timeout ends.\n const buffer = await fs.promises.readFile(path.join(cwd, filePath));\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n"],"mappings":"uHAOA,
|
|
1
|
+
{"version":3,"file":"readOutputFiles.js","names":["fs","path","readOutputFiles","outputFiles","filePath","outputFilePaths","buffer","cwd","encodeFileForTestCaseResult"],"sources":["../../src/helpers/readOutputFiles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { TestCaseResult } from '../types/testCaseResult.js';\n\nimport { encodeFileForTestCaseResult } from './printTestCaseResult.js';\n\nexport async function readOutputFiles(\n cwd: string,\n outputFilePaths: readonly string[]\n): Promise<NonNullable<TestCaseResult['outputFiles']>> {\n const outputFiles: NonNullable<TestCaseResult['outputFiles']> = [];\n for (const filePath of outputFilePaths) {\n try {\n // Read as-is on purpose: the submission runs as the same OS user as this harness, so a symlink\n // only reaches what it can already read, and a planted FIFO only stalls its own run, which the\n // judge server's request timeout ends.\n const buffer = await fs.promises.readFile(path.join(cwd, filePath));\n outputFiles.push(encodeFileForTestCaseResult(filePath, buffer));\n } catch {\n // file not found\n }\n }\n return outputFiles;\n}\n"],"mappings":"uHAOA,eAAsBE,EACpB,EACA,EACqD,CACrD,IAAMC,EAA0D,CAAC,EACjE,IAAK,IAAMC,KAAYC,EACrB,GAAI,CAIF,IAAMC,EAAS,MAAMN,EAAG,SAAS,SAASC,EAAK,KAAKM,EAAKH,CAAQ,CAAC,EAClED,EAAY,KAAKK,EAA4BJ,EAAUE,CAAM,CAAC,CAChE,MAAQ,CAER,CAEF,OAAOH,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readProblemMarkdownFrontMatter.cjs","names":["fs","path","parseFrontMatter","problemMarkdownFrontMatterSchema"],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\n/**\n * Whether a standard stdio problem is judgeable without test cases: static-analysis rules still\n * judge the submitted code, and manual scoring intentionally accepts every submission.\n */\nexport function judgesWithoutTestCases(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return (\n frontMatter.isManualScoringRequired === true ||\n (frontMatter.requiredRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenTextsInCode?.length ?? 0) > 0 ||\n (frontMatter.requiredSubmissionFilePaths?.length ?? 0) > 0\n );\n}\n\n/**\n * Whether the front matter judges every test case without an expected output: manual scoring\n * accepts every run, and required output files are checked by their presence after each run.\n * Code rules and required submission files do not count because they check the submission once,\n * in addition to the output comparison.\n */\nexport function judgesTestCasesWithoutExpectations(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return frontMatter.isManualScoringRequired === true || (frontMatter.requiredOutputFilePaths?.length ?? 0) > 0;\n}\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"yOAYA,
|
|
1
|
+
{"version":3,"file":"readProblemMarkdownFrontMatter.cjs","names":["fs","path","parseFrontMatter","problemMarkdownFrontMatterSchema","require_runtime","require_problem","node_fs","node_path","front_matter","judgesWithoutTestCases","frontMatter","judgesTestCasesWithoutExpectations","readProblemMarkdownFrontMatter","dirent","problemDir","markdown","attributes"],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\n/**\n * Whether a standard stdio problem is judgeable without test cases: static-analysis rules still\n * judge the submitted code, and manual scoring intentionally accepts every submission.\n */\nexport function judgesWithoutTestCases(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return (\n frontMatter.isManualScoringRequired === true ||\n (frontMatter.requiredRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenTextsInCode?.length ?? 0) > 0 ||\n (frontMatter.requiredSubmissionFilePaths?.length ?? 0) > 0\n );\n}\n\n/**\n * Whether the front matter judges every test case without an expected output: manual scoring\n * accepts every run, and required output files are checked by their presence after each run.\n * Code rules and required submission files do not count because they check the submission once,\n * in addition to the output comparison.\n */\nexport function judgesTestCasesWithoutExpectations(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return frontMatter.isManualScoringRequired === true || (frontMatter.requiredOutputFilePaths?.length ?? 0) > 0;\n}\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"yOAYA,SAAgBS,EAAuB,EAAkD,CACvF,OACEC,EAAY,0BAA4B,KACvCA,EAAY,uBAAuB,QAAU,GAAK,IAClDA,EAAY,wBAAwB,QAAU,GAAK,IACnDA,EAAY,sBAAsB,QAAU,GAAK,IACjDA,EAAY,6BAA6B,QAAU,GAAK,CAE7D,CAQA,SAAgBC,EAAmC,EAAkD,CACnG,OAAOD,EAAY,0BAA4B,KAASA,EAAY,yBAAyB,QAAU,GAAK,CAC9G,CAEA,eAAsBE,EAA+B,EAAyD,CAC5G,IAAK,IAAMC,KAAU,MAAMb,EAAAA,QAAG,SAAS,QAAQc,EAAY,CAAE,cAAe,EAAK,CAAC,EAAG,CAEnF,GADI,CAACD,EAAO,OAAO,GACf,EAAEA,EAAO,OAAS,cAAgBA,EAAO,KAAK,SAAS,aAAa,GAAI,SAE5E,IAAME,EAAW,MAAMf,EAAAA,QAAG,SAAS,SAASC,EAAAA,QAAK,KAAKY,EAAO,WAAYA,EAAO,IAAI,EAAG,MAAM,EAEvF,CAAE,eAAA,EAAgBX,EAAAA,QAAAA,CAA8Ea,CAAQ,EAE9G,OAAOZ,EAAAA,iCAAiC,MAAMa,CAAU,CAC1D,CAEA,MAAU,MAAM,+BAA+BF,GAAY,CAC7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readProblemMarkdownFrontMatter.js","names":[],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\n/**\n * Whether a standard stdio problem is judgeable without test cases: static-analysis rules still\n * judge the submitted code, and manual scoring intentionally accepts every submission.\n */\nexport function judgesWithoutTestCases(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return (\n frontMatter.isManualScoringRequired === true ||\n (frontMatter.requiredRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenTextsInCode?.length ?? 0) > 0 ||\n (frontMatter.requiredSubmissionFilePaths?.length ?? 0) > 0\n );\n}\n\n/**\n * Whether the front matter judges every test case without an expected output: manual scoring\n * accepts every run, and required output files are checked by their presence after each run.\n * Code rules and required submission files do not count because they check the submission once,\n * in addition to the output comparison.\n */\nexport function judgesTestCasesWithoutExpectations(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return frontMatter.isManualScoringRequired === true || (frontMatter.requiredOutputFilePaths?.length ?? 0) > 0;\n}\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"mJAYA,
|
|
1
|
+
{"version":3,"file":"readProblemMarkdownFrontMatter.js","names":["fs","path","parseFrontMatter","judgesWithoutTestCases","frontMatter","judgesTestCasesWithoutExpectations","readProblemMarkdownFrontMatter","dirent","problemDir","markdown","problemMarkdownFrontMatterSchema","attributes"],"sources":["../../src/helpers/readProblemMarkdownFrontMatter.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport parseFrontMatter from 'front-matter';\n\nimport type { ProblemMarkdownFrontMatter } from '../types/problem.js';\nimport { problemMarkdownFrontMatterSchema } from '../types/problem.js';\n\n/**\n * Whether a standard stdio problem is judgeable without test cases: static-analysis rules still\n * judge the submitted code, and manual scoring intentionally accepts every submission.\n */\nexport function judgesWithoutTestCases(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return (\n frontMatter.isManualScoringRequired === true ||\n (frontMatter.requiredRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenRegExpsInCode?.length ?? 0) > 0 ||\n (frontMatter.forbiddenTextsInCode?.length ?? 0) > 0 ||\n (frontMatter.requiredSubmissionFilePaths?.length ?? 0) > 0\n );\n}\n\n/**\n * Whether the front matter judges every test case without an expected output: manual scoring\n * accepts every run, and required output files are checked by their presence after each run.\n * Code rules and required submission files do not count because they check the submission once,\n * in addition to the output comparison.\n */\nexport function judgesTestCasesWithoutExpectations(frontMatter: ProblemMarkdownFrontMatter): boolean {\n return frontMatter.isManualScoringRequired === true || (frontMatter.requiredOutputFilePaths?.length ?? 0) > 0;\n}\n\nexport async function readProblemMarkdownFrontMatter(problemDir: string): Promise<ProblemMarkdownFrontMatter> {\n for (const dirent of await fs.promises.readdir(problemDir, { withFileTypes: true })) {\n if (!dirent.isFile()) continue;\n if (!(dirent.name === 'problem.md' || dirent.name.endsWith('.problem.md'))) continue;\n\n const markdown = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n const { attributes } = (parseFrontMatter as unknown as (markdown: string) => { attributes: unknown })(markdown);\n\n return problemMarkdownFrontMatterSchema.parse(attributes);\n }\n\n throw new Error(`problem markdown not found: ${problemDir}`);\n}\n"],"mappings":"mJAYA,SAAgBG,EAAuB,EAAkD,CACvF,OACEC,EAAY,0BAA4B,KACvCA,EAAY,uBAAuB,QAAU,GAAK,IAClDA,EAAY,wBAAwB,QAAU,GAAK,IACnDA,EAAY,sBAAsB,QAAU,GAAK,IACjDA,EAAY,6BAA6B,QAAU,GAAK,CAE7D,CAQA,SAAgBC,EAAmC,EAAkD,CACnG,OAAOD,EAAY,0BAA4B,KAASA,EAAY,yBAAyB,QAAU,GAAK,CAC9G,CAEA,eAAsBE,EAA+B,EAAyD,CAC5G,IAAK,IAAMC,KAAU,MAAMP,EAAG,SAAS,QAAQQ,EAAY,CAAE,cAAe,EAAK,CAAC,EAAG,CAEnF,GADI,CAACD,EAAO,OAAO,GACf,EAAEA,EAAO,OAAS,cAAgBA,EAAO,KAAK,SAAS,aAAa,GAAI,SAE5E,IAAME,EAAW,MAAMT,EAAG,SAAS,SAASC,EAAK,KAAKM,EAAO,WAAYA,EAAO,IAAI,EAAG,MAAM,EAEvF,CAAE,cAAgBL,EAA8EO,CAAQ,EAE9G,OAAOC,EAAiC,MAAMC,CAAU,CAC1D,CAEA,MAAU,MAAM,+BAA+BH,GAAY,CAC7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readTestCases.cjs","names":["fs","path"],"sources":["../../src/helpers/readTestCases.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst SHARED_TEST_CASE_NAME = '_shared';\n\n/**\n * Read the test cases of a `test_cases/` directory. A test case id is the name of every\n * `<id>.in` / `<id>.out` file and `<id>.fin/` / `<id>.fout/` directory; any of them may be absent,\n * and what an absent part means is up to the harness (the presets document their rules).\n * Other entries (e.g. `.json` configuration read by a custom `judge.ts`) are ignored.\n */\nexport async function readTestCases(directory: string): Promise<\n { id: string; input?: string; output?: string; fileInputPath?: string; fileOutputPath?: string }[] & {\n shared?: { fileInputPath?: string };\n }\n> {\n if (!fs.existsSync(directory)) return [];\n\n const idSet = new Set<string>();\n const idToInput = new Map<string, string>();\n const idToOutput = new Map<string, string>();\n const idToFileInputPath = new Map<string, string>();\n const idToFileOutputPath = new Map<string, string>();\n\n for (const dirent of await fs.promises.readdir(directory, { withFileTypes: true })) {\n if (dirent.isFile()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.in' && ext !== '.out') continue;\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n idSet.add(name);\n if (ext === '.in') idToInput.set(name, text);\n if (ext === '.out') idToOutput.set(name, text);\n } else if (dirent.isDirectory()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.fin' && ext !== '.fout') continue;\n\n idSet.add(name);\n if (ext === '.fin') idToFileInputPath.set(name, path.join(dirent.parentPath, dirent.name));\n if (ext === '.fout') idToFileOutputPath.set(name, path.join(dirent.parentPath, dirent.name));\n }\n }\n\n const testCases: Awaited<ReturnType<typeof readTestCases>> = [...idSet]\n .filter((id) => id !== SHARED_TEST_CASE_NAME)\n .toSorted()\n .map((id) => ({\n id,\n input: idToInput.get(id),\n output: idToOutput.get(id),\n fileInputPath: idToFileInputPath.get(id),\n fileOutputPath: idToFileOutputPath.get(id),\n }));\n\n if (idSet.has(SHARED_TEST_CASE_NAME)) {\n testCases.shared = { fileInputPath: idToFileInputPath.get(SHARED_TEST_CASE_NAME) };\n }\n\n return testCases;\n}\n"],"mappings":"wJAGA,
|
|
1
|
+
{"version":3,"file":"readTestCases.cjs","names":["fs","path","require_runtime","node_fs","node_path","SHARED_TEST_CASE_NAME","readTestCases","directory","idSet","idToInput","idToOutput","idToFileInputPath","idToFileOutputPath","dirent","ext","text","name","testCases","id"],"sources":["../../src/helpers/readTestCases.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst SHARED_TEST_CASE_NAME = '_shared';\n\n/**\n * Read the test cases of a `test_cases/` directory. A test case id is the name of every\n * `<id>.in` / `<id>.out` file and `<id>.fin/` / `<id>.fout/` directory; any of them may be absent,\n * and what an absent part means is up to the harness (the presets document their rules).\n * Other entries (e.g. `.json` configuration read by a custom `judge.ts`) are ignored.\n */\nexport async function readTestCases(directory: string): Promise<\n { id: string; input?: string; output?: string; fileInputPath?: string; fileOutputPath?: string }[] & {\n shared?: { fileInputPath?: string };\n }\n> {\n if (!fs.existsSync(directory)) return [];\n\n const idSet = new Set<string>();\n const idToInput = new Map<string, string>();\n const idToOutput = new Map<string, string>();\n const idToFileInputPath = new Map<string, string>();\n const idToFileOutputPath = new Map<string, string>();\n\n for (const dirent of await fs.promises.readdir(directory, { withFileTypes: true })) {\n if (dirent.isFile()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.in' && ext !== '.out') continue;\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n idSet.add(name);\n if (ext === '.in') idToInput.set(name, text);\n if (ext === '.out') idToOutput.set(name, text);\n } else if (dirent.isDirectory()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.fin' && ext !== '.fout') continue;\n\n idSet.add(name);\n if (ext === '.fin') idToFileInputPath.set(name, path.join(dirent.parentPath, dirent.name));\n if (ext === '.fout') idToFileOutputPath.set(name, path.join(dirent.parentPath, dirent.name));\n }\n }\n\n const testCases: Awaited<ReturnType<typeof readTestCases>> = [...idSet]\n .filter((id) => id !== SHARED_TEST_CASE_NAME)\n .toSorted()\n .map((id) => ({\n id,\n input: idToInput.get(id),\n output: idToOutput.get(id),\n fileInputPath: idToFileInputPath.get(id),\n fileOutputPath: idToFileOutputPath.get(id),\n }));\n\n if (idSet.has(SHARED_TEST_CASE_NAME)) {\n testCases.shared = { fileInputPath: idToFileInputPath.get(SHARED_TEST_CASE_NAME) };\n }\n\n return testCases;\n}\n"],"mappings":"wJAGA,MAAMK,EAAwB,UAQ9B,eAAsBC,EAAc,EAIlC,CACA,GAAI,CAACN,EAAAA,QAAG,WAAWO,CAAS,EAAG,MAAO,CAAC,EAEvC,IAAMC,kBAAQ,IAAI,IACZC,kBAAY,IAAI,IAChBC,kBAAa,IAAI,IACjBC,kBAAoB,IAAI,IACxBC,kBAAqB,IAAI,IAE/B,IAAK,IAAMC,KAAU,MAAMb,EAAAA,QAAG,SAAS,QAAQO,EAAW,CAAE,cAAe,EAAK,CAAC,EAC/E,GAAIM,EAAO,OAAO,EAAG,CACnB,GAAM,CAAE,MAAK,QAASZ,EAAAA,QAAK,MAAMY,EAAO,IAAI,EAC5C,GAAIC,IAAQ,OAASA,IAAQ,OAAQ,SAErC,IAAMC,EAAO,MAAMf,EAAAA,QAAG,SAAS,SAASC,EAAAA,QAAK,KAAKY,EAAO,WAAYA,EAAO,IAAI,EAAG,MAAM,EAEzFL,EAAM,IAAIQ,CAAI,EACVF,IAAQ,OAAOL,EAAU,IAAIO,EAAMD,CAAI,EACvCD,IAAQ,QAAQJ,EAAW,IAAIM,EAAMD,CAAI,CAC/C,MAAO,GAAIF,EAAO,YAAY,EAAG,CAC/B,GAAM,CAAE,MAAK,QAASZ,EAAAA,QAAK,MAAMY,EAAO,IAAI,EAC5C,GAAIC,IAAQ,QAAUA,IAAQ,QAAS,SAEvCN,EAAM,IAAIQ,CAAI,EACVF,IAAQ,QAAQH,EAAkB,IAAIK,EAAMf,EAAAA,QAAK,KAAKY,EAAO,WAAYA,EAAO,IAAI,CAAC,EACrFC,IAAQ,SAASF,EAAmB,IAAII,EAAMf,EAAAA,QAAK,KAAKY,EAAO,WAAYA,EAAO,IAAI,CAAC,CAC7F,CAGF,IAAMI,EAAuD,CAAC,GAAGT,CAAK,CAAC,CACpE,OAAQ,GAAOU,IAAOb,CAAqB,CAAC,CAC5C,SAAS,CAAC,CACV,IAAK,IAAQ,CACZ,KACA,MAAOI,EAAU,IAAIS,CAAE,EACvB,OAAQR,EAAW,IAAIQ,CAAE,EACzB,cAAeP,EAAkB,IAAIO,CAAE,EACvC,eAAgBN,EAAmB,IAAIM,CAAE,CAC3C,EAAE,EAMJ,OAJIV,EAAM,IAAIH,CAAqB,IACjC,EAAU,OAAS,CAAE,cAAeM,EAAkB,IAAIN,CAAqB,CAAE,GAG5EY,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readTestCases.js","names":[],"sources":["../../src/helpers/readTestCases.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst SHARED_TEST_CASE_NAME = '_shared';\n\n/**\n * Read the test cases of a `test_cases/` directory. A test case id is the name of every\n * `<id>.in` / `<id>.out` file and `<id>.fin/` / `<id>.fout/` directory; any of them may be absent,\n * and what an absent part means is up to the harness (the presets document their rules).\n * Other entries (e.g. `.json` configuration read by a custom `judge.ts`) are ignored.\n */\nexport async function readTestCases(directory: string): Promise<\n { id: string; input?: string; output?: string; fileInputPath?: string; fileOutputPath?: string }[] & {\n shared?: { fileInputPath?: string };\n }\n> {\n if (!fs.existsSync(directory)) return [];\n\n const idSet = new Set<string>();\n const idToInput = new Map<string, string>();\n const idToOutput = new Map<string, string>();\n const idToFileInputPath = new Map<string, string>();\n const idToFileOutputPath = new Map<string, string>();\n\n for (const dirent of await fs.promises.readdir(directory, { withFileTypes: true })) {\n if (dirent.isFile()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.in' && ext !== '.out') continue;\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n idSet.add(name);\n if (ext === '.in') idToInput.set(name, text);\n if (ext === '.out') idToOutput.set(name, text);\n } else if (dirent.isDirectory()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.fin' && ext !== '.fout') continue;\n\n idSet.add(name);\n if (ext === '.fin') idToFileInputPath.set(name, path.join(dirent.parentPath, dirent.name));\n if (ext === '.fout') idToFileOutputPath.set(name, path.join(dirent.parentPath, dirent.name));\n }\n }\n\n const testCases: Awaited<ReturnType<typeof readTestCases>> = [...idSet]\n .filter((id) => id !== SHARED_TEST_CASE_NAME)\n .toSorted()\n .map((id) => ({\n id,\n input: idToInput.get(id),\n output: idToOutput.get(id),\n fileInputPath: idToFileInputPath.get(id),\n fileOutputPath: idToFileOutputPath.get(id),\n }));\n\n if (idSet.has(SHARED_TEST_CASE_NAME)) {\n testCases.shared = { fileInputPath: idToFileInputPath.get(SHARED_TEST_CASE_NAME) };\n }\n\n return testCases;\n}\n"],"mappings":"gDAGA,
|
|
1
|
+
{"version":3,"file":"readTestCases.js","names":["fs","path","SHARED_TEST_CASE_NAME","readTestCases","directory","idSet","idToInput","idToOutput","idToFileInputPath","idToFileOutputPath","dirent","ext","text","name","testCases","id"],"sources":["../../src/helpers/readTestCases.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst SHARED_TEST_CASE_NAME = '_shared';\n\n/**\n * Read the test cases of a `test_cases/` directory. A test case id is the name of every\n * `<id>.in` / `<id>.out` file and `<id>.fin/` / `<id>.fout/` directory; any of them may be absent,\n * and what an absent part means is up to the harness (the presets document their rules).\n * Other entries (e.g. `.json` configuration read by a custom `judge.ts`) are ignored.\n */\nexport async function readTestCases(directory: string): Promise<\n { id: string; input?: string; output?: string; fileInputPath?: string; fileOutputPath?: string }[] & {\n shared?: { fileInputPath?: string };\n }\n> {\n if (!fs.existsSync(directory)) return [];\n\n const idSet = new Set<string>();\n const idToInput = new Map<string, string>();\n const idToOutput = new Map<string, string>();\n const idToFileInputPath = new Map<string, string>();\n const idToFileOutputPath = new Map<string, string>();\n\n for (const dirent of await fs.promises.readdir(directory, { withFileTypes: true })) {\n if (dirent.isFile()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.in' && ext !== '.out') continue;\n\n const text = await fs.promises.readFile(path.join(dirent.parentPath, dirent.name), 'utf8');\n\n idSet.add(name);\n if (ext === '.in') idToInput.set(name, text);\n if (ext === '.out') idToOutput.set(name, text);\n } else if (dirent.isDirectory()) {\n const { ext, name } = path.parse(dirent.name);\n if (ext !== '.fin' && ext !== '.fout') continue;\n\n idSet.add(name);\n if (ext === '.fin') idToFileInputPath.set(name, path.join(dirent.parentPath, dirent.name));\n if (ext === '.fout') idToFileOutputPath.set(name, path.join(dirent.parentPath, dirent.name));\n }\n }\n\n const testCases: Awaited<ReturnType<typeof readTestCases>> = [...idSet]\n .filter((id) => id !== SHARED_TEST_CASE_NAME)\n .toSorted()\n .map((id) => ({\n id,\n input: idToInput.get(id),\n output: idToOutput.get(id),\n fileInputPath: idToFileInputPath.get(id),\n fileOutputPath: idToFileOutputPath.get(id),\n }));\n\n if (idSet.has(SHARED_TEST_CASE_NAME)) {\n testCases.shared = { fileInputPath: idToFileInputPath.get(SHARED_TEST_CASE_NAME) };\n }\n\n return testCases;\n}\n"],"mappings":"gDAGA,MAAME,EAAwB,UAQ9B,eAAsBC,EAAc,EAIlC,CACA,GAAI,CAACH,EAAG,WAAWI,CAAS,EAAG,MAAO,CAAC,EAEvC,IAAMC,kBAAQ,IAAI,IACZC,kBAAY,IAAI,IAChBC,kBAAa,IAAI,IACjBC,kBAAoB,IAAI,IACxBC,kBAAqB,IAAI,IAE/B,IAAK,IAAMC,KAAU,MAAMV,EAAG,SAAS,QAAQI,EAAW,CAAE,cAAe,EAAK,CAAC,EAC/E,GAAIM,EAAO,OAAO,EAAG,CACnB,GAAM,CAAE,MAAK,QAAST,EAAK,MAAMS,EAAO,IAAI,EAC5C,GAAIC,IAAQ,OAASA,IAAQ,OAAQ,SAErC,IAAMC,EAAO,MAAMZ,EAAG,SAAS,SAASC,EAAK,KAAKS,EAAO,WAAYA,EAAO,IAAI,EAAG,MAAM,EAEzFL,EAAM,IAAIQ,CAAI,EACVF,IAAQ,OAAOL,EAAU,IAAIO,EAAMD,CAAI,EACvCD,IAAQ,QAAQJ,EAAW,IAAIM,EAAMD,CAAI,CAC/C,MAAO,GAAIF,EAAO,YAAY,EAAG,CAC/B,GAAM,CAAE,MAAK,QAAST,EAAK,MAAMS,EAAO,IAAI,EAC5C,GAAIC,IAAQ,QAAUA,IAAQ,QAAS,SAEvCN,EAAM,IAAIQ,CAAI,EACVF,IAAQ,QAAQH,EAAkB,IAAIK,EAAMZ,EAAK,KAAKS,EAAO,WAAYA,EAAO,IAAI,CAAC,EACrFC,IAAQ,SAASF,EAAmB,IAAII,EAAMZ,EAAK,KAAKS,EAAO,WAAYA,EAAO,IAAI,CAAC,CAC7F,CAGF,IAAMI,EAAuD,CAAC,GAAGT,CAAK,CAAC,CACpE,OAAQ,GAAOU,IAAOb,CAAqB,CAAC,CAC5C,SAAS,CAAC,CACV,IAAK,IAAQ,CACZ,KACA,MAAOI,EAAU,IAAIS,CAAE,EACvB,OAAQR,EAAW,IAAIQ,CAAE,EACzB,cAAeP,EAAkB,IAAIO,CAAE,EACvC,eAAgBN,EAAmB,IAAIM,CAAE,CAC3C,EAAE,EAMJ,OAJIV,EAAM,IAAIH,CAAqB,IACjC,EAAU,OAAS,CAAE,cAAeM,EAAkB,IAAIN,CAAqB,CAAE,GAG5EY,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"removeCommentsInSourceCode.cjs","names":[],"sources":["../../src/helpers/removeCommentsInSourceCode.ts"],"sourcesContent":["import type { LanguageDefinition } from '../types/language.js';\n\nexport type SourceCodeGrammar = NonNullable<LanguageDefinition['grammer']>;\n\n/** Removes comments from source code according to the provided language grammar. */\nexport function removeCommentsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: false });\n}\n\n/** Removes comments and string literal contents while preserving executable interpolation expressions. */\nexport function removeCommentsAndStringsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: true });\n}\n\ninterface CommentOrStringGrammar {\n closeRegExp: RegExp;\n isComment: boolean;\n openRegExp: RegExp;\n templateSyntax?: 'kotlin';\n}\n\ninterface BalancedExpressionOptions {\n slashStartsComments?: boolean;\n slashStartsRegExp: boolean;\n supportsKotlinStrings?: boolean;\n}\n\nfunction removeCommentsAndMaybeStringsInSourceCode(\n grammar: SourceCodeGrammar,\n sourceCode: string,\n options: { removeStrings: boolean },\n commentOrStringGrammars = compileCommentOrStringGrammars(grammar)\n): string {\n if (!grammar.comments?.length && (!options.removeStrings || !grammar.strings?.length)) return sourceCode;\n\n const newSourceCodeSlices: string[] = [];\n\n let lastIndex = 0;\n\n while (lastIndex < sourceCode.length) {\n let first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined;\n\n for (const commentOrStringGrammer of commentOrStringGrammars) {\n const startRegExp = commentOrStringGrammer.openRegExp;\n startRegExp.lastIndex = lastIndex;\n\n const match = startRegExp.exec(sourceCode);\n\n if (match && shouldPreferMatch(match, commentOrStringGrammer, first, options)) {\n first = { grammar: commentOrStringGrammer, match };\n }\n }\n\n if (first) {\n let stringPrefixStartIndex = first.match.index;\n if (!first.grammar.isComment && options.removeStrings) {\n stringPrefixStartIndex = getPythonStringPrefixStartIndex(sourceCode, first.match.index);\n }\n newSourceCodeSlices.push(sourceCode.slice(lastIndex, stringPrefixStartIndex));\n\n if (!first.grammar.isComment) {\n lastIndex = findStringEndIndex(sourceCode, first.match.index, first.grammar);\n const stringLiteral = sourceCode.slice(first.match.index, lastIndex);\n if (options.removeStrings) {\n newSourceCodeSlices.push(\n preserveStringInterpolationExpressions(\n grammar,\n commentOrStringGrammars,\n first.grammar,\n sourceCode,\n first.match.index,\n stringLiteral\n )\n );\n } else {\n newSourceCodeSlices.push(stringLiteral);\n }\n } else {\n const closeRegExp = first.grammar.closeRegExp;\n closeRegExp.lastIndex = first.match.index + first.match[0].length;\n\n const match = closeRegExp.exec(sourceCode);\n\n lastIndex = match ? match.index + match[0].length : sourceCode.length;\n }\n } else {\n newSourceCodeSlices.push(sourceCode.slice(lastIndex));\n lastIndex = sourceCode.length;\n }\n }\n\n return newSourceCodeSlices.join('');\n}\n\nfunction compileCommentOrStringGrammars(grammar: SourceCodeGrammar): readonly CommentOrStringGrammar[] {\n return [\n ...(grammar.comments?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close ?? /(?=\\n)/g),\n isComment: true,\n openRegExp: makeGlobalRegExp(v.open),\n })) ?? []),\n ...(grammar.strings?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close),\n isComment: false,\n openRegExp: makeGlobalRegExp(v.open),\n templateSyntax: v.templateSyntax,\n })) ?? []),\n ] satisfies CommentOrStringGrammar[];\n}\n\nfunction shouldPreferMatch(\n match: RegExpExecArray,\n grammar: CommentOrStringGrammar,\n first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined,\n options: { removeStrings: boolean }\n): boolean {\n if (!first) return true;\n if (match.index < first.match.index) return true;\n if (match.index > first.match.index) return false;\n return options.removeStrings && first.grammar.isComment && !grammar.isComment;\n}\n\nfunction makeGlobalRegExp(regExp: RegExp): RegExp {\n return new RegExp(regExp, regExp.flags.includes('g') ? regExp.flags : `${regExp.flags}g`);\n}\n\nfunction findStringEndIndex(sourceCode: string, stringStartIndex: number, grammar: CommentOrStringGrammar): number {\n if (grammar.templateSyntax === 'kotlin') return findKotlinStringEndIndex(sourceCode, stringStartIndex);\n if (sourceCode[stringStartIndex] === '`') return findJavaScriptTemplateEndIndex(sourceCode, stringStartIndex);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return findPythonFStringEndIndex(sourceCode, stringStartIndex);\n\n const closeRegExp = grammar.closeRegExp;\n closeRegExp.lastIndex = stringStartIndex + 1;\n const match = closeRegExp.exec(sourceCode);\n return match ? match.index + match[0].length : sourceCode.length;\n}\n\nfunction findKotlinStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n const isRawString = quote.length === 3;\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (!isRawString && sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index =\n readBalancedExpression(sourceCode, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findJavaScriptTemplateEndIndex(sourceCode: string, stringStartIndex: number): number {\n let index = stringStartIndex + 1;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '`') return index + 1;\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index = readBalancedExpression(sourceCode, index + 2, '}', { slashStartsRegExp: true }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findPythonFStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (sourceCode[index] === '{' && sourceCode[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '{') {\n index = readBalancedExpression(sourceCode, index + 1, '}', { slashStartsRegExp: false }).endIndex + 1;\n continue;\n }\n index += sourceCode[index] === '\\\\' ? 2 : 1;\n }\n\n return sourceCode.length;\n}\n\nfunction getStringQuote(sourceCode: string, stringStartIndex: number): string {\n const threeCharacterQuote = sourceCode.slice(stringStartIndex, stringStartIndex + 3);\n if (threeCharacterQuote === \"'''\" || threeCharacterQuote === '\"\"\"') return threeCharacterQuote;\n return sourceCode[stringStartIndex] ?? '';\n}\n\nfunction getPythonStringPrefixStartIndex(sourceCode: string, stringStartIndex: number): number {\n const prefix = getPythonStringPrefix(sourceCode, stringStartIndex);\n return prefix ? stringStartIndex - prefix.length : stringStartIndex;\n}\n\nfunction getPythonStringPrefix(sourceCode: string, stringStartIndex: number): string | undefined {\n if (sourceCode[stringStartIndex] !== '\"' && sourceCode[stringStartIndex] !== \"'\") return undefined;\n let index = stringStartIndex - 1;\n while (index >= 0 && /[A-Za-z]/.test(sourceCode[index] ?? '')) index -= 1;\n\n const prefix = sourceCode.slice(index + 1, stringStartIndex);\n if (!prefix || !/^[bfru]+$/i.test(prefix)) return undefined;\n if (index >= 0 && /[\\dA-Za-z_]/.test(sourceCode[index] ?? '')) return undefined;\n\n return prefix;\n}\n\nfunction preserveStringInterpolationExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringGrammar: CommentOrStringGrammar,\n sourceCode: string,\n stringStartIndex: number,\n stringLiteral: string\n): string {\n if (stringGrammar.templateSyntax === 'kotlin')\n return preserveKotlinStringTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (stringLiteral.startsWith('`'))\n return preserveJavaScriptTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return preservePythonFStringExpressions(grammar, commentOrStringGrammars, stringLiteral);\n return '';\n}\n\nfunction preserveKotlinStringTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const isRawString = quoteLength === 3;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (!isRawString && stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] !== '$') {\n index += 1;\n continue;\n }\n if (stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n if (isKotlinIdentifierStart(stringLiteral[index + 1])) {\n let endIndex = index + 2;\n while (isKotlinIdentifierPart(stringLiteral[endIndex])) endIndex += 1;\n expressions.push(stringLiteral.slice(index + 1, endIndex));\n index = endIndex;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction isKotlinIdentifierStart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}_]/u.test(character);\n}\n\nfunction isKotlinIdentifierPart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}\\p{N}_]/u.test(character);\n}\n\nfunction hasPythonFStringPrefix(sourceCode: string, stringStartIndex: number): boolean {\n return getPythonStringPrefix(sourceCode, stringStartIndex)?.toLowerCase().includes('f') ?? false;\n}\n\nfunction preserveJavaScriptTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const expressions: string[] = [];\n let index = 1;\n\n while (index < stringLiteral.length - 1) {\n if (stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '$' && stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', { slashStartsRegExp: true });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction preservePythonFStringExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (stringLiteral[index] === '{' && stringLiteral[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 1, '}', { slashStartsRegExp: false });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += stringLiteral[index] === '\\\\' ? 2 : 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction readBalancedExpression(\n sourceCode: string,\n startIndex: number,\n closeChar: string,\n options: BalancedExpressionOptions\n): { content: string; endIndex: number } {\n let depth = 1;\n let index = startIndex;\n\n while (index < sourceCode.length) {\n const char = sourceCode[index];\n if (char === '\"' && options.supportsKotlinStrings) {\n index = findKotlinStringEndIndex(sourceCode, index);\n continue;\n }\n if (char === '\"' || char === \"'\" || char === '`') {\n index = skipQuotedSpan(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '/'\n ) {\n index = skipJavaScriptSingleLineComment(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '*'\n ) {\n index = skipJavaScriptBlockComment(sourceCode, index);\n continue;\n }\n if (options.slashStartsRegExp && char === '/') {\n index = skipJavaScriptRegExpLiteral(sourceCode, index);\n continue;\n }\n if (char === '{') depth += 1;\n if (char === closeChar) {\n depth -= 1;\n if (depth === 0) return { content: sourceCode.slice(startIndex, index), endIndex: index };\n }\n index += 1;\n }\n\n return { content: sourceCode.slice(startIndex), endIndex: sourceCode.length };\n}\n\nfunction skipQuotedSpan(sourceCode: string, startIndex: number): number {\n const quote = getStringQuote(sourceCode, startIndex);\n let index = startIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n index += 1;\n }\n\n return index;\n}\n\nfunction skipJavaScriptRegExpLiteral(sourceCode: string, startIndex: number): number {\n let index = startIndex + 1;\n let inCharacterClass = false;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '[') inCharacterClass = true;\n if (sourceCode[index] === ']') inCharacterClass = false;\n if (sourceCode[index] === '/' && !inCharacterClass) {\n index += 1;\n while (/[A-Za-z]/.test(sourceCode[index] ?? '')) index += 1;\n return index;\n }\n if (sourceCode[index] === '\\n') return startIndex + 1;\n index += 1;\n }\n\n return startIndex + 1;\n}\n\nfunction skipJavaScriptSingleLineComment(sourceCode: string, startIndex: number): number {\n const newLineIndex = sourceCode.indexOf('\\n', startIndex + 2);\n return newLineIndex === -1 ? sourceCode.length : newLineIndex;\n}\n\nfunction skipJavaScriptBlockComment(sourceCode: string, startIndex: number): number {\n const endIndex = sourceCode.indexOf('*/', startIndex + 2);\n return endIndex === -1 ? sourceCode.length : endIndex + 2;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"removeCommentsInSourceCode.cjs","names":["removeCommentsInSourceCode","removeCommentsAndMaybeStringsInSourceCode","grammar","sourceCode","removeCommentsAndStringsInSourceCode","compileCommentOrStringGrammars","options","newSourceCodeSlices","lastIndex","first","commentOrStringGrammer","commentOrStringGrammars","startRegExp","match","shouldPreferMatch","stringPrefixStartIndex","getPythonStringPrefixStartIndex","closeRegExp","findStringEndIndex","stringLiteral","preserveStringInterpolationExpressions","makeGlobalRegExp","v","regExp","findKotlinStringEndIndex","stringStartIndex","findJavaScriptTemplateEndIndex","hasPythonFStringPrefix","findPythonFStringEndIndex","quote","getStringQuote","isRawString","index","readBalancedExpression","threeCharacterQuote","prefix","getPythonStringPrefix","stringGrammar","preserveKotlinStringTemplateExpressions","preserveJavaScriptTemplateExpressions","preservePythonFStringExpressions","quoteLength","expressions","expression","isKotlinIdentifierStart","endIndex","isKotlinIdentifierPart","character","depth","startIndex","char","skipQuotedSpan","skipJavaScriptSingleLineComment","skipJavaScriptBlockComment","skipJavaScriptRegExpLiteral","closeChar","inCharacterClass","newLineIndex"],"sources":["../../src/helpers/removeCommentsInSourceCode.ts"],"sourcesContent":["import type { LanguageDefinition } from '../types/language.js';\n\nexport type SourceCodeGrammar = NonNullable<LanguageDefinition['grammer']>;\n\n/** Removes comments from source code according to the provided language grammar. */\nexport function removeCommentsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: false });\n}\n\n/** Removes comments and string literal contents while preserving executable interpolation expressions. */\nexport function removeCommentsAndStringsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: true });\n}\n\ninterface CommentOrStringGrammar {\n closeRegExp: RegExp;\n isComment: boolean;\n openRegExp: RegExp;\n templateSyntax?: 'kotlin';\n}\n\ninterface BalancedExpressionOptions {\n slashStartsComments?: boolean;\n slashStartsRegExp: boolean;\n supportsKotlinStrings?: boolean;\n}\n\nfunction removeCommentsAndMaybeStringsInSourceCode(\n grammar: SourceCodeGrammar,\n sourceCode: string,\n options: { removeStrings: boolean },\n commentOrStringGrammars = compileCommentOrStringGrammars(grammar)\n): string {\n if (!grammar.comments?.length && (!options.removeStrings || !grammar.strings?.length)) return sourceCode;\n\n const newSourceCodeSlices: string[] = [];\n\n let lastIndex = 0;\n\n while (lastIndex < sourceCode.length) {\n let first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined;\n\n for (const commentOrStringGrammer of commentOrStringGrammars) {\n const startRegExp = commentOrStringGrammer.openRegExp;\n startRegExp.lastIndex = lastIndex;\n\n const match = startRegExp.exec(sourceCode);\n\n if (match && shouldPreferMatch(match, commentOrStringGrammer, first, options)) {\n first = { grammar: commentOrStringGrammer, match };\n }\n }\n\n if (first) {\n let stringPrefixStartIndex = first.match.index;\n if (!first.grammar.isComment && options.removeStrings) {\n stringPrefixStartIndex = getPythonStringPrefixStartIndex(sourceCode, first.match.index);\n }\n newSourceCodeSlices.push(sourceCode.slice(lastIndex, stringPrefixStartIndex));\n\n if (!first.grammar.isComment) {\n lastIndex = findStringEndIndex(sourceCode, first.match.index, first.grammar);\n const stringLiteral = sourceCode.slice(first.match.index, lastIndex);\n if (options.removeStrings) {\n newSourceCodeSlices.push(\n preserveStringInterpolationExpressions(\n grammar,\n commentOrStringGrammars,\n first.grammar,\n sourceCode,\n first.match.index,\n stringLiteral\n )\n );\n } else {\n newSourceCodeSlices.push(stringLiteral);\n }\n } else {\n const closeRegExp = first.grammar.closeRegExp;\n closeRegExp.lastIndex = first.match.index + first.match[0].length;\n\n const match = closeRegExp.exec(sourceCode);\n\n lastIndex = match ? match.index + match[0].length : sourceCode.length;\n }\n } else {\n newSourceCodeSlices.push(sourceCode.slice(lastIndex));\n lastIndex = sourceCode.length;\n }\n }\n\n return newSourceCodeSlices.join('');\n}\n\nfunction compileCommentOrStringGrammars(grammar: SourceCodeGrammar): readonly CommentOrStringGrammar[] {\n return [\n ...(grammar.comments?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close ?? /(?=\\n)/g),\n isComment: true,\n openRegExp: makeGlobalRegExp(v.open),\n })) ?? []),\n ...(grammar.strings?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close),\n isComment: false,\n openRegExp: makeGlobalRegExp(v.open),\n templateSyntax: v.templateSyntax,\n })) ?? []),\n ] satisfies CommentOrStringGrammar[];\n}\n\nfunction shouldPreferMatch(\n match: RegExpExecArray,\n grammar: CommentOrStringGrammar,\n first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined,\n options: { removeStrings: boolean }\n): boolean {\n if (!first) return true;\n if (match.index < first.match.index) return true;\n if (match.index > first.match.index) return false;\n return options.removeStrings && first.grammar.isComment && !grammar.isComment;\n}\n\nfunction makeGlobalRegExp(regExp: RegExp): RegExp {\n return new RegExp(regExp, regExp.flags.includes('g') ? regExp.flags : `${regExp.flags}g`);\n}\n\nfunction findStringEndIndex(sourceCode: string, stringStartIndex: number, grammar: CommentOrStringGrammar): number {\n if (grammar.templateSyntax === 'kotlin') return findKotlinStringEndIndex(sourceCode, stringStartIndex);\n if (sourceCode[stringStartIndex] === '`') return findJavaScriptTemplateEndIndex(sourceCode, stringStartIndex);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return findPythonFStringEndIndex(sourceCode, stringStartIndex);\n\n const closeRegExp = grammar.closeRegExp;\n closeRegExp.lastIndex = stringStartIndex + 1;\n const match = closeRegExp.exec(sourceCode);\n return match ? match.index + match[0].length : sourceCode.length;\n}\n\nfunction findKotlinStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n const isRawString = quote.length === 3;\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (!isRawString && sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index =\n readBalancedExpression(sourceCode, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findJavaScriptTemplateEndIndex(sourceCode: string, stringStartIndex: number): number {\n let index = stringStartIndex + 1;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '`') return index + 1;\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index = readBalancedExpression(sourceCode, index + 2, '}', { slashStartsRegExp: true }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findPythonFStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (sourceCode[index] === '{' && sourceCode[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '{') {\n index = readBalancedExpression(sourceCode, index + 1, '}', { slashStartsRegExp: false }).endIndex + 1;\n continue;\n }\n index += sourceCode[index] === '\\\\' ? 2 : 1;\n }\n\n return sourceCode.length;\n}\n\nfunction getStringQuote(sourceCode: string, stringStartIndex: number): string {\n const threeCharacterQuote = sourceCode.slice(stringStartIndex, stringStartIndex + 3);\n if (threeCharacterQuote === \"'''\" || threeCharacterQuote === '\"\"\"') return threeCharacterQuote;\n return sourceCode[stringStartIndex] ?? '';\n}\n\nfunction getPythonStringPrefixStartIndex(sourceCode: string, stringStartIndex: number): number {\n const prefix = getPythonStringPrefix(sourceCode, stringStartIndex);\n return prefix ? stringStartIndex - prefix.length : stringStartIndex;\n}\n\nfunction getPythonStringPrefix(sourceCode: string, stringStartIndex: number): string | undefined {\n if (sourceCode[stringStartIndex] !== '\"' && sourceCode[stringStartIndex] !== \"'\") return undefined;\n let index = stringStartIndex - 1;\n while (index >= 0 && /[A-Za-z]/.test(sourceCode[index] ?? '')) index -= 1;\n\n const prefix = sourceCode.slice(index + 1, stringStartIndex);\n if (!prefix || !/^[bfru]+$/i.test(prefix)) return undefined;\n if (index >= 0 && /[\\dA-Za-z_]/.test(sourceCode[index] ?? '')) return undefined;\n\n return prefix;\n}\n\nfunction preserveStringInterpolationExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringGrammar: CommentOrStringGrammar,\n sourceCode: string,\n stringStartIndex: number,\n stringLiteral: string\n): string {\n if (stringGrammar.templateSyntax === 'kotlin')\n return preserveKotlinStringTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (stringLiteral.startsWith('`'))\n return preserveJavaScriptTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return preservePythonFStringExpressions(grammar, commentOrStringGrammars, stringLiteral);\n return '';\n}\n\nfunction preserveKotlinStringTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const isRawString = quoteLength === 3;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (!isRawString && stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] !== '$') {\n index += 1;\n continue;\n }\n if (stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n if (isKotlinIdentifierStart(stringLiteral[index + 1])) {\n let endIndex = index + 2;\n while (isKotlinIdentifierPart(stringLiteral[endIndex])) endIndex += 1;\n expressions.push(stringLiteral.slice(index + 1, endIndex));\n index = endIndex;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction isKotlinIdentifierStart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}_]/u.test(character);\n}\n\nfunction isKotlinIdentifierPart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}\\p{N}_]/u.test(character);\n}\n\nfunction hasPythonFStringPrefix(sourceCode: string, stringStartIndex: number): boolean {\n return getPythonStringPrefix(sourceCode, stringStartIndex)?.toLowerCase().includes('f') ?? false;\n}\n\nfunction preserveJavaScriptTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const expressions: string[] = [];\n let index = 1;\n\n while (index < stringLiteral.length - 1) {\n if (stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '$' && stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', { slashStartsRegExp: true });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction preservePythonFStringExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (stringLiteral[index] === '{' && stringLiteral[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 1, '}', { slashStartsRegExp: false });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += stringLiteral[index] === '\\\\' ? 2 : 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction readBalancedExpression(\n sourceCode: string,\n startIndex: number,\n closeChar: string,\n options: BalancedExpressionOptions\n): { content: string; endIndex: number } {\n let depth = 1;\n let index = startIndex;\n\n while (index < sourceCode.length) {\n const char = sourceCode[index];\n if (char === '\"' && options.supportsKotlinStrings) {\n index = findKotlinStringEndIndex(sourceCode, index);\n continue;\n }\n if (char === '\"' || char === \"'\" || char === '`') {\n index = skipQuotedSpan(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '/'\n ) {\n index = skipJavaScriptSingleLineComment(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '*'\n ) {\n index = skipJavaScriptBlockComment(sourceCode, index);\n continue;\n }\n if (options.slashStartsRegExp && char === '/') {\n index = skipJavaScriptRegExpLiteral(sourceCode, index);\n continue;\n }\n if (char === '{') depth += 1;\n if (char === closeChar) {\n depth -= 1;\n if (depth === 0) return { content: sourceCode.slice(startIndex, index), endIndex: index };\n }\n index += 1;\n }\n\n return { content: sourceCode.slice(startIndex), endIndex: sourceCode.length };\n}\n\nfunction skipQuotedSpan(sourceCode: string, startIndex: number): number {\n const quote = getStringQuote(sourceCode, startIndex);\n let index = startIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n index += 1;\n }\n\n return index;\n}\n\nfunction skipJavaScriptRegExpLiteral(sourceCode: string, startIndex: number): number {\n let index = startIndex + 1;\n let inCharacterClass = false;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '[') inCharacterClass = true;\n if (sourceCode[index] === ']') inCharacterClass = false;\n if (sourceCode[index] === '/' && !inCharacterClass) {\n index += 1;\n while (/[A-Za-z]/.test(sourceCode[index] ?? '')) index += 1;\n return index;\n }\n if (sourceCode[index] === '\\n') return startIndex + 1;\n index += 1;\n }\n\n return startIndex + 1;\n}\n\nfunction skipJavaScriptSingleLineComment(sourceCode: string, startIndex: number): number {\n const newLineIndex = sourceCode.indexOf('\\n', startIndex + 2);\n return newLineIndex === -1 ? sourceCode.length : newLineIndex;\n}\n\nfunction skipJavaScriptBlockComment(sourceCode: string, startIndex: number): number {\n const endIndex = sourceCode.indexOf('*/', startIndex + 2);\n return endIndex === -1 ? sourceCode.length : endIndex + 2;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"removeCommentsInSourceCode.js","names":[],"sources":["../../src/helpers/removeCommentsInSourceCode.ts"],"sourcesContent":["import type { LanguageDefinition } from '../types/language.js';\n\nexport type SourceCodeGrammar = NonNullable<LanguageDefinition['grammer']>;\n\n/** Removes comments from source code according to the provided language grammar. */\nexport function removeCommentsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: false });\n}\n\n/** Removes comments and string literal contents while preserving executable interpolation expressions. */\nexport function removeCommentsAndStringsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: true });\n}\n\ninterface CommentOrStringGrammar {\n closeRegExp: RegExp;\n isComment: boolean;\n openRegExp: RegExp;\n templateSyntax?: 'kotlin';\n}\n\ninterface BalancedExpressionOptions {\n slashStartsComments?: boolean;\n slashStartsRegExp: boolean;\n supportsKotlinStrings?: boolean;\n}\n\nfunction removeCommentsAndMaybeStringsInSourceCode(\n grammar: SourceCodeGrammar,\n sourceCode: string,\n options: { removeStrings: boolean },\n commentOrStringGrammars = compileCommentOrStringGrammars(grammar)\n): string {\n if (!grammar.comments?.length && (!options.removeStrings || !grammar.strings?.length)) return sourceCode;\n\n const newSourceCodeSlices: string[] = [];\n\n let lastIndex = 0;\n\n while (lastIndex < sourceCode.length) {\n let first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined;\n\n for (const commentOrStringGrammer of commentOrStringGrammars) {\n const startRegExp = commentOrStringGrammer.openRegExp;\n startRegExp.lastIndex = lastIndex;\n\n const match = startRegExp.exec(sourceCode);\n\n if (match && shouldPreferMatch(match, commentOrStringGrammer, first, options)) {\n first = { grammar: commentOrStringGrammer, match };\n }\n }\n\n if (first) {\n let stringPrefixStartIndex = first.match.index;\n if (!first.grammar.isComment && options.removeStrings) {\n stringPrefixStartIndex = getPythonStringPrefixStartIndex(sourceCode, first.match.index);\n }\n newSourceCodeSlices.push(sourceCode.slice(lastIndex, stringPrefixStartIndex));\n\n if (!first.grammar.isComment) {\n lastIndex = findStringEndIndex(sourceCode, first.match.index, first.grammar);\n const stringLiteral = sourceCode.slice(first.match.index, lastIndex);\n if (options.removeStrings) {\n newSourceCodeSlices.push(\n preserveStringInterpolationExpressions(\n grammar,\n commentOrStringGrammars,\n first.grammar,\n sourceCode,\n first.match.index,\n stringLiteral\n )\n );\n } else {\n newSourceCodeSlices.push(stringLiteral);\n }\n } else {\n const closeRegExp = first.grammar.closeRegExp;\n closeRegExp.lastIndex = first.match.index + first.match[0].length;\n\n const match = closeRegExp.exec(sourceCode);\n\n lastIndex = match ? match.index + match[0].length : sourceCode.length;\n }\n } else {\n newSourceCodeSlices.push(sourceCode.slice(lastIndex));\n lastIndex = sourceCode.length;\n }\n }\n\n return newSourceCodeSlices.join('');\n}\n\nfunction compileCommentOrStringGrammars(grammar: SourceCodeGrammar): readonly CommentOrStringGrammar[] {\n return [\n ...(grammar.comments?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close ?? /(?=\\n)/g),\n isComment: true,\n openRegExp: makeGlobalRegExp(v.open),\n })) ?? []),\n ...(grammar.strings?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close),\n isComment: false,\n openRegExp: makeGlobalRegExp(v.open),\n templateSyntax: v.templateSyntax,\n })) ?? []),\n ] satisfies CommentOrStringGrammar[];\n}\n\nfunction shouldPreferMatch(\n match: RegExpExecArray,\n grammar: CommentOrStringGrammar,\n first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined,\n options: { removeStrings: boolean }\n): boolean {\n if (!first) return true;\n if (match.index < first.match.index) return true;\n if (match.index > first.match.index) return false;\n return options.removeStrings && first.grammar.isComment && !grammar.isComment;\n}\n\nfunction makeGlobalRegExp(regExp: RegExp): RegExp {\n return new RegExp(regExp, regExp.flags.includes('g') ? regExp.flags : `${regExp.flags}g`);\n}\n\nfunction findStringEndIndex(sourceCode: string, stringStartIndex: number, grammar: CommentOrStringGrammar): number {\n if (grammar.templateSyntax === 'kotlin') return findKotlinStringEndIndex(sourceCode, stringStartIndex);\n if (sourceCode[stringStartIndex] === '`') return findJavaScriptTemplateEndIndex(sourceCode, stringStartIndex);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return findPythonFStringEndIndex(sourceCode, stringStartIndex);\n\n const closeRegExp = grammar.closeRegExp;\n closeRegExp.lastIndex = stringStartIndex + 1;\n const match = closeRegExp.exec(sourceCode);\n return match ? match.index + match[0].length : sourceCode.length;\n}\n\nfunction findKotlinStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n const isRawString = quote.length === 3;\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (!isRawString && sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index =\n readBalancedExpression(sourceCode, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findJavaScriptTemplateEndIndex(sourceCode: string, stringStartIndex: number): number {\n let index = stringStartIndex + 1;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '`') return index + 1;\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index = readBalancedExpression(sourceCode, index + 2, '}', { slashStartsRegExp: true }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findPythonFStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (sourceCode[index] === '{' && sourceCode[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '{') {\n index = readBalancedExpression(sourceCode, index + 1, '}', { slashStartsRegExp: false }).endIndex + 1;\n continue;\n }\n index += sourceCode[index] === '\\\\' ? 2 : 1;\n }\n\n return sourceCode.length;\n}\n\nfunction getStringQuote(sourceCode: string, stringStartIndex: number): string {\n const threeCharacterQuote = sourceCode.slice(stringStartIndex, stringStartIndex + 3);\n if (threeCharacterQuote === \"'''\" || threeCharacterQuote === '\"\"\"') return threeCharacterQuote;\n return sourceCode[stringStartIndex] ?? '';\n}\n\nfunction getPythonStringPrefixStartIndex(sourceCode: string, stringStartIndex: number): number {\n const prefix = getPythonStringPrefix(sourceCode, stringStartIndex);\n return prefix ? stringStartIndex - prefix.length : stringStartIndex;\n}\n\nfunction getPythonStringPrefix(sourceCode: string, stringStartIndex: number): string | undefined {\n if (sourceCode[stringStartIndex] !== '\"' && sourceCode[stringStartIndex] !== \"'\") return undefined;\n let index = stringStartIndex - 1;\n while (index >= 0 && /[A-Za-z]/.test(sourceCode[index] ?? '')) index -= 1;\n\n const prefix = sourceCode.slice(index + 1, stringStartIndex);\n if (!prefix || !/^[bfru]+$/i.test(prefix)) return undefined;\n if (index >= 0 && /[\\dA-Za-z_]/.test(sourceCode[index] ?? '')) return undefined;\n\n return prefix;\n}\n\nfunction preserveStringInterpolationExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringGrammar: CommentOrStringGrammar,\n sourceCode: string,\n stringStartIndex: number,\n stringLiteral: string\n): string {\n if (stringGrammar.templateSyntax === 'kotlin')\n return preserveKotlinStringTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (stringLiteral.startsWith('`'))\n return preserveJavaScriptTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return preservePythonFStringExpressions(grammar, commentOrStringGrammars, stringLiteral);\n return '';\n}\n\nfunction preserveKotlinStringTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const isRawString = quoteLength === 3;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (!isRawString && stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] !== '$') {\n index += 1;\n continue;\n }\n if (stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n if (isKotlinIdentifierStart(stringLiteral[index + 1])) {\n let endIndex = index + 2;\n while (isKotlinIdentifierPart(stringLiteral[endIndex])) endIndex += 1;\n expressions.push(stringLiteral.slice(index + 1, endIndex));\n index = endIndex;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction isKotlinIdentifierStart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}_]/u.test(character);\n}\n\nfunction isKotlinIdentifierPart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}\\p{N}_]/u.test(character);\n}\n\nfunction hasPythonFStringPrefix(sourceCode: string, stringStartIndex: number): boolean {\n return getPythonStringPrefix(sourceCode, stringStartIndex)?.toLowerCase().includes('f') ?? false;\n}\n\nfunction preserveJavaScriptTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const expressions: string[] = [];\n let index = 1;\n\n while (index < stringLiteral.length - 1) {\n if (stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '$' && stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', { slashStartsRegExp: true });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction preservePythonFStringExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (stringLiteral[index] === '{' && stringLiteral[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 1, '}', { slashStartsRegExp: false });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += stringLiteral[index] === '\\\\' ? 2 : 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction readBalancedExpression(\n sourceCode: string,\n startIndex: number,\n closeChar: string,\n options: BalancedExpressionOptions\n): { content: string; endIndex: number } {\n let depth = 1;\n let index = startIndex;\n\n while (index < sourceCode.length) {\n const char = sourceCode[index];\n if (char === '\"' && options.supportsKotlinStrings) {\n index = findKotlinStringEndIndex(sourceCode, index);\n continue;\n }\n if (char === '\"' || char === \"'\" || char === '`') {\n index = skipQuotedSpan(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '/'\n ) {\n index = skipJavaScriptSingleLineComment(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '*'\n ) {\n index = skipJavaScriptBlockComment(sourceCode, index);\n continue;\n }\n if (options.slashStartsRegExp && char === '/') {\n index = skipJavaScriptRegExpLiteral(sourceCode, index);\n continue;\n }\n if (char === '{') depth += 1;\n if (char === closeChar) {\n depth -= 1;\n if (depth === 0) return { content: sourceCode.slice(startIndex, index), endIndex: index };\n }\n index += 1;\n }\n\n return { content: sourceCode.slice(startIndex), endIndex: sourceCode.length };\n}\n\nfunction skipQuotedSpan(sourceCode: string, startIndex: number): number {\n const quote = getStringQuote(sourceCode, startIndex);\n let index = startIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n index += 1;\n }\n\n return index;\n}\n\nfunction skipJavaScriptRegExpLiteral(sourceCode: string, startIndex: number): number {\n let index = startIndex + 1;\n let inCharacterClass = false;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '[') inCharacterClass = true;\n if (sourceCode[index] === ']') inCharacterClass = false;\n if (sourceCode[index] === '/' && !inCharacterClass) {\n index += 1;\n while (/[A-Za-z]/.test(sourceCode[index] ?? '')) index += 1;\n return index;\n }\n if (sourceCode[index] === '\\n') return startIndex + 1;\n index += 1;\n }\n\n return startIndex + 1;\n}\n\nfunction skipJavaScriptSingleLineComment(sourceCode: string, startIndex: number): number {\n const newLineIndex = sourceCode.indexOf('\\n', startIndex + 2);\n return newLineIndex === -1 ? sourceCode.length : newLineIndex;\n}\n\nfunction skipJavaScriptBlockComment(sourceCode: string, startIndex: number): number {\n const endIndex = sourceCode.indexOf('*/', startIndex + 2);\n return endIndex === -1 ? sourceCode.length : endIndex + 2;\n}\n"],"mappings":"AAKA,SAAgB,EAA2B,EAA4B,EAA4B,CACjG,OAAO,EAA0C,EAAS,EAAY,CAAE,cAAe,EAAM,CAAC,CAChG,CAGA,SAAgB,EAAqC,EAA4B,EAA4B,CAC3G,OAAO,EAA0C,EAAS,EAAY,CAAE,cAAe,EAAK,CAAC,CAC/F,CAeA,SAAS,EACP,EACA,EACA,EACA,EAA0B,EAA+B,CAAO,EACxD,CACR,GAAI,CAAC,EAAQ,UAAU,SAAW,CAAC,EAAQ,eAAiB,CAAC,EAAQ,SAAS,QAAS,OAAO,EAE9F,IAAM,EAAgC,CAAC,EAEnC,EAAY,EAEhB,KAAO,EAAY,EAAW,QAAQ,CACpC,IAAI,EAEJ,IAAK,IAAM,KAA0B,EAAyB,CAC5D,IAAM,EAAc,EAAuB,WAC3C,EAAY,UAAY,EAExB,IAAM,EAAQ,EAAY,KAAK,CAAU,EAErC,GAAS,EAAkB,EAAO,EAAwB,EAAO,CAAO,IAC1E,EAAQ,CAAE,QAAS,EAAwB,OAAM,EAErD,CAEA,GAAI,EAAO,CACT,IAAI,EAAyB,EAAM,MAAM,MAMzC,GALI,CAAC,EAAM,QAAQ,WAAa,EAAQ,gBACtC,EAAyB,EAAgC,EAAY,EAAM,MAAM,KAAK,GAExF,EAAoB,KAAK,EAAW,MAAM,EAAW,CAAsB,CAAC,EAEvE,EAAM,QAAQ,UAiBZ,CACL,IAAM,EAAc,EAAM,QAAQ,YAClC,EAAY,UAAY,EAAM,MAAM,MAAQ,EAAM,MAAM,EAAE,CAAC,OAE3D,IAAM,EAAQ,EAAY,KAAK,CAAU,EAEzC,EAAY,EAAQ,EAAM,MAAQ,EAAM,EAAE,CAAC,OAAS,EAAW,MACjE,KAxB8B,CAC5B,EAAY,EAAmB,EAAY,EAAM,MAAM,MAAO,EAAM,OAAO,EAC3E,IAAM,EAAgB,EAAW,MAAM,EAAM,MAAM,MAAO,CAAS,EAC/D,EAAQ,cACV,EAAoB,KAClB,EACE,EACA,EACA,EAAM,QACN,EACA,EAAM,MAAM,MACZ,CACF,CACF,EAEA,EAAoB,KAAK,CAAa,CAE1C,CAQF,MACE,EAAoB,KAAK,EAAW,MAAM,CAAS,CAAC,EACpD,EAAY,EAAW,MAE3B,CAEA,OAAO,EAAoB,KAAK,EAAE,CACpC,CAEA,SAAS,EAA+B,EAA+D,CACrG,MAAO,CACL,GAAI,EAAQ,UAAU,IAAK,IAAO,CAChC,YAAa,EAAiB,EAAE,OAAS,SAAS,EAClD,UAAW,GACX,WAAY,EAAiB,EAAE,IAAI,CACrC,EAAE,GAAK,CAAC,EACR,GAAI,EAAQ,SAAS,IAAK,IAAO,CAC/B,YAAa,EAAiB,EAAE,KAAK,EACrC,UAAW,GACX,WAAY,EAAiB,EAAE,IAAI,EACnC,eAAgB,EAAE,cACpB,EAAE,GAAK,CAAC,CACV,CACF,CAEA,SAAS,EACP,EACA,EACA,EACA,EACS,CAIT,MAHI,CAAC,GACD,EAAM,MAAQ,EAAM,MAAM,MAAc,GACxC,EAAM,MAAQ,EAAM,MAAM,MAAc,GACrC,EAAQ,eAAiB,EAAM,QAAQ,WAAa,CAAC,EAAQ,SACtE,CAEA,SAAS,EAAiB,EAAwB,CAChD,OAAO,IAAI,OAAO,EAAQ,EAAO,MAAM,SAAS,GAAG,EAAI,EAAO,MAAQ,GAAG,EAAO,MAAM,EAAE,CAC1F,CAEA,SAAS,EAAmB,EAAoB,EAA0B,EAAyC,CACjH,GAAI,EAAQ,iBAAmB,SAAU,OAAO,EAAyB,EAAY,CAAgB,EACrG,GAAI,EAAW,KAAsB,IAAK,OAAO,EAA+B,EAAY,CAAgB,EAC5G,GAAI,EAAuB,EAAY,CAAgB,EACrD,OAAO,EAA0B,EAAY,CAAgB,EAE/D,IAAM,EAAc,EAAQ,YAC5B,EAAY,UAAY,EAAmB,EAC3C,IAAM,EAAQ,EAAY,KAAK,CAAU,EACzC,OAAO,EAAQ,EAAM,MAAQ,EAAM,EAAE,CAAC,OAAS,EAAW,MAC5D,CAEA,SAAS,EAAyB,EAAoB,EAAkC,CACtF,IAAM,EAAQ,EAAe,EAAY,CAAgB,EACnD,EAAc,EAAM,SAAW,EACjC,EAAQ,EAAmB,EAAM,OAErC,KAAO,EAAQ,EAAW,QAAQ,CAChC,GAAI,EAAW,WAAW,EAAO,CAAK,EAAG,OAAO,EAAQ,EAAM,OAC9D,GAAI,CAAC,GAAe,EAAW,KAAW,KAAM,CAC9C,GAAS,EACT,QACF,CACA,GAAI,EAAW,KAAW,KAAO,EAAW,EAAQ,KAAO,IAAK,CAC9D,EACE,EAAuB,EAAY,EAAQ,EAAG,IAAK,CACjD,oBAAqB,GACrB,kBAAmB,GACnB,sBAAuB,EACzB,CAAC,CAAC,CAAC,SAAW,EAChB,QACF,CACA,GAAS,CACX,CAEA,OAAO,EAAW,MACpB,CAEA,SAAS,EAA+B,EAAoB,EAAkC,CAC5F,IAAI,EAAQ,EAAmB,EAE/B,KAAO,EAAQ,EAAW,QAAQ,CAChC,GAAI,EAAW,KAAW,KAAM,CAC9B,GAAS,EACT,QACF,CACA,GAAI,EAAW,KAAW,IAAK,OAAO,EAAQ,EAC9C,GAAI,EAAW,KAAW,KAAO,EAAW,EAAQ,KAAO,IAAK,CAC9D,EAAQ,EAAuB,EAAY,EAAQ,EAAG,IAAK,CAAE,kBAAmB,EAAK,CAAC,CAAC,CAAC,SAAW,EACnG,QACF,CACA,GAAS,CACX,CAEA,OAAO,EAAW,MACpB,CAEA,SAAS,EAA0B,EAAoB,EAAkC,CACvF,IAAM,EAAQ,EAAe,EAAY,CAAgB,EACrD,EAAQ,EAAmB,EAAM,OAErC,KAAO,EAAQ,EAAW,QAAQ,CAChC,GAAI,EAAW,WAAW,EAAO,CAAK,EAAG,OAAO,EAAQ,EAAM,OAC9D,GAAI,EAAW,KAAW,KAAO,EAAW,EAAQ,KAAO,IAAK,CAC9D,GAAS,EACT,QACF,CACA,GAAI,EAAW,KAAW,IAAK,CAC7B,EAAQ,EAAuB,EAAY,EAAQ,EAAG,IAAK,CAAE,kBAAmB,EAAM,CAAC,CAAC,CAAC,SAAW,EACpG,QACF,CACA,GAAS,EAAW,KAAW,KAAO,EAAI,CAC5C,CAEA,OAAO,EAAW,MACpB,CAEA,SAAS,EAAe,EAAoB,EAAkC,CAC5E,IAAM,EAAsB,EAAW,MAAM,EAAkB,EAAmB,CAAC,EAEnF,OADI,IAAwB,OAAS,IAAwB,MAAc,EACpE,EAAW,IAAqB,EACzC,CAEA,SAAS,EAAgC,EAAoB,EAAkC,CAC7F,IAAM,EAAS,EAAsB,EAAY,CAAgB,EACjE,OAAO,EAAS,EAAmB,EAAO,OAAS,CACrD,CAEA,SAAS,EAAsB,EAAoB,EAA8C,CAC/F,GAAI,EAAW,KAAsB,KAAO,EAAW,KAAsB,IAAK,OAClF,IAAI,EAAQ,EAAmB,EAC/B,KAAO,GAAS,GAAK,WAAW,KAAK,EAAW,IAAU,EAAE,GAAG,IAE/D,IAAM,EAAS,EAAW,MAAM,EAAQ,EAAG,CAAgB,EACvD,GAAC,GAAW,aAAa,KAAK,CAAM,GACpC,KAAS,GAAK,cAAc,KAAK,EAAW,IAAU,EAAE,GAE5D,OAAO,CACT,CAEA,SAAS,EACP,EACA,EACA,EACA,EACA,EACA,EACQ,CAOR,OANI,EAAc,iBAAmB,SAC5B,EAAwC,EAAS,EAAyB,CAAa,EAC5F,EAAc,WAAW,GAAG,EACvB,EAAsC,EAAS,EAAyB,CAAa,EAC1F,EAAuB,EAAY,CAAgB,EAC9C,EAAiC,EAAS,EAAyB,CAAa,EAClF,EACT,CAEA,SAAS,EACP,EACA,EACA,EACQ,CACR,IAAM,EAAc,EAAe,EAAe,CAAC,CAAC,CAAC,OAC/C,EAAc,IAAgB,EAC9B,EAAwB,CAAC,EAC3B,EAAQ,EAEZ,KAAO,EAAQ,EAAc,OAAS,GAAa,CACjD,GAAI,CAAC,GAAe,EAAc,KAAW,KAAM,CACjD,GAAS,EACT,QACF,CACA,GAAI,EAAc,KAAW,IAAK,CAChC,GAAS,EACT,QACF,CACA,GAAI,EAAc,EAAQ,KAAO,IAAK,CACpC,IAAM,EAAa,EAAuB,EAAe,EAAQ,EAAG,IAAK,CACvE,oBAAqB,GACrB,kBAAmB,GACnB,sBAAuB,EACzB,CAAC,EACD,EAAY,KACV,EACE,EACA,EAAW,QACX,CAAE,cAAe,EAAK,EACtB,CACF,CACF,EACA,EAAQ,EAAW,SAAW,EAC9B,QACF,CACA,GAAI,EAAwB,EAAc,EAAQ,EAAE,EAAG,CACrD,IAAI,EAAW,EAAQ,EACvB,KAAO,EAAuB,EAAc,EAAS,GAAG,GAAY,EACpE,EAAY,KAAK,EAAc,MAAM,EAAQ,EAAG,CAAQ,CAAC,EACzD,EAAQ,EACR,QACF,CACA,GAAS,CACX,CAEA,OAAO,EAAY,KAAK;CAAI,CAC9B,CAEA,SAAS,EAAwB,EAAwC,CACvE,OAAO,IAAc,IAAA,IAAa,YAAY,KAAK,CAAS,CAC9D,CAEA,SAAS,EAAuB,EAAwC,CACtE,OAAO,IAAc,IAAA,IAAa,iBAAiB,KAAK,CAAS,CACnE,CAEA,SAAS,EAAuB,EAAoB,EAAmC,CACrF,OAAO,EAAsB,EAAY,CAAgB,CAAC,EAAE,YAAY,CAAC,CAAC,SAAS,GAAG,GAAK,EAC7F,CAEA,SAAS,EACP,EACA,EACA,EACQ,CACR,IAAM,EAAwB,CAAC,EAC3B,EAAQ,EAEZ,KAAO,EAAQ,EAAc,OAAS,GAAG,CACvC,GAAI,EAAc,KAAW,KAAM,CACjC,GAAS,EACT,QACF,CACA,GAAI,EAAc,KAAW,KAAO,EAAc,EAAQ,KAAO,IAAK,CACpE,IAAM,EAAa,EAAuB,EAAe,EAAQ,EAAG,IAAK,CAAE,kBAAmB,EAAK,CAAC,EACpG,EAAY,KACV,EACE,EACA,EAAW,QACX,CAAE,cAAe,EAAK,EACtB,CACF,CACF,EACA,EAAQ,EAAW,SAAW,EAC9B,QACF,CACA,GAAS,CACX,CAEA,OAAO,EAAY,KAAK;CAAI,CAC9B,CAEA,SAAS,EACP,EACA,EACA,EACQ,CACR,IAAM,EAAc,EAAe,EAAe,CAAC,CAAC,CAAC,OAC/C,EAAwB,CAAC,EAC3B,EAAQ,EAEZ,KAAO,EAAQ,EAAc,OAAS,GAAa,CACjD,GAAI,EAAc,KAAW,KAAO,EAAc,EAAQ,KAAO,IAAK,CACpE,GAAS,EACT,QACF,CACA,GAAI,EAAc,KAAW,IAAK,CAChC,IAAM,EAAa,EAAuB,EAAe,EAAQ,EAAG,IAAK,CAAE,kBAAmB,EAAM,CAAC,EACrG,EAAY,KACV,EACE,EACA,EAAW,QACX,CAAE,cAAe,EAAK,EACtB,CACF,CACF,EACA,EAAQ,EAAW,SAAW,EAC9B,QACF,CACA,GAAS,EAAc,KAAW,KAAO,EAAI,CAC/C,CAEA,OAAO,EAAY,KAAK;CAAI,CAC9B,CAEA,SAAS,EACP,EACA,EACA,EACA,EACuC,CACvC,IAAI,EAAQ,EACR,EAAQ,EAEZ,KAAO,EAAQ,EAAW,QAAQ,CAChC,IAAM,EAAO,EAAW,GACxB,GAAI,IAAS,KAAO,EAAQ,sBAAuB,CACjD,EAAQ,EAAyB,EAAY,CAAK,EAClD,QACF,CACA,GAAI,IAAS,KAAO,IAAS,KAAO,IAAS,IAAK,CAChD,EAAQ,EAAe,EAAY,CAAK,EACxC,QACF,CACA,IACG,EAAQ,qBAAuB,EAAQ,oBACxC,EAAW,KAAW,KACtB,EAAW,EAAQ,KAAO,IAC1B,CACA,EAAQ,EAAgC,EAAY,CAAK,EACzD,QACF,CACA,IACG,EAAQ,qBAAuB,EAAQ,oBACxC,EAAW,KAAW,KACtB,EAAW,EAAQ,KAAO,IAC1B,CACA,EAAQ,EAA2B,EAAY,CAAK,EACpD,QACF,CACA,GAAI,EAAQ,mBAAqB,IAAS,IAAK,CAC7C,EAAQ,EAA4B,EAAY,CAAK,EACrD,QACF,CAEA,GADI,IAAS,MAAK,GAAS,GACvB,IAAS,IACX,IACI,IAAU,GAAG,MAAO,CAAE,QAAS,EAAW,MAAM,EAAY,CAAK,EAAG,SAAU,CAAM,EAE1F,GAAS,CACX,CAEA,MAAO,CAAE,QAAS,EAAW,MAAM,CAAU,EAAG,SAAU,EAAW,MAAO,CAC9E,CAEA,SAAS,EAAe,EAAoB,EAA4B,CACtE,IAAM,EAAQ,EAAe,EAAY,CAAU,EAC/C,EAAQ,EAAa,EAAM,OAE/B,KAAO,EAAQ,EAAW,QAAQ,CAChC,GAAI,EAAW,KAAW,KAAM,CAC9B,GAAS,EACT,QACF,CACA,GAAI,EAAW,WAAW,EAAO,CAAK,EAAG,OAAO,EAAQ,EAAM,OAC9D,GAAS,CACX,CAEA,OAAO,CACT,CAEA,SAAS,EAA4B,EAAoB,EAA4B,CACnF,IAAI,EAAQ,EAAa,EACrB,EAAmB,GAEvB,KAAO,EAAQ,EAAW,QAAQ,CAChC,GAAI,EAAW,KAAW,KAAM,CAC9B,GAAS,EACT,QACF,CAGA,GAFI,EAAW,KAAW,MAAK,EAAmB,IAC9C,EAAW,KAAW,MAAK,EAAmB,IAC9C,EAAW,KAAW,KAAO,CAAC,EAAkB,CAElD,IADA,GAAS,EACF,WAAW,KAAK,EAAW,IAAU,EAAE,GAAG,GAAS,EAC1D,OAAO,CACT,CACA,GAAI,EAAW,KAAW;EAAM,OAAO,EAAa,EACpD,GAAS,CACX,CAEA,OAAO,EAAa,CACtB,CAEA,SAAS,EAAgC,EAAoB,EAA4B,CACvF,IAAM,EAAe,EAAW,QAAQ;EAAM,EAAa,CAAC,EAC5D,OAAO,IAAiB,GAAK,EAAW,OAAS,CACnD,CAEA,SAAS,EAA2B,EAAoB,EAA4B,CAClF,IAAM,EAAW,EAAW,QAAQ,KAAM,EAAa,CAAC,EACxD,OAAO,IAAa,GAAK,EAAW,OAAS,EAAW,CAC1D"}
|
|
1
|
+
{"version":3,"file":"removeCommentsInSourceCode.js","names":["removeCommentsInSourceCode","removeCommentsAndMaybeStringsInSourceCode","grammar","sourceCode","removeCommentsAndStringsInSourceCode","compileCommentOrStringGrammars","options","newSourceCodeSlices","lastIndex","first","commentOrStringGrammer","commentOrStringGrammars","startRegExp","match","shouldPreferMatch","stringPrefixStartIndex","getPythonStringPrefixStartIndex","closeRegExp","findStringEndIndex","stringLiteral","preserveStringInterpolationExpressions","makeGlobalRegExp","v","regExp","findKotlinStringEndIndex","stringStartIndex","findJavaScriptTemplateEndIndex","hasPythonFStringPrefix","findPythonFStringEndIndex","quote","getStringQuote","isRawString","index","readBalancedExpression","threeCharacterQuote","prefix","getPythonStringPrefix","stringGrammar","preserveKotlinStringTemplateExpressions","preserveJavaScriptTemplateExpressions","preservePythonFStringExpressions","quoteLength","expressions","expression","isKotlinIdentifierStart","endIndex","isKotlinIdentifierPart","character","depth","startIndex","char","skipQuotedSpan","skipJavaScriptSingleLineComment","skipJavaScriptBlockComment","skipJavaScriptRegExpLiteral","closeChar","inCharacterClass","newLineIndex"],"sources":["../../src/helpers/removeCommentsInSourceCode.ts"],"sourcesContent":["import type { LanguageDefinition } from '../types/language.js';\n\nexport type SourceCodeGrammar = NonNullable<LanguageDefinition['grammer']>;\n\n/** Removes comments from source code according to the provided language grammar. */\nexport function removeCommentsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: false });\n}\n\n/** Removes comments and string literal contents while preserving executable interpolation expressions. */\nexport function removeCommentsAndStringsInSourceCode(grammar: SourceCodeGrammar, sourceCode: string): string {\n return removeCommentsAndMaybeStringsInSourceCode(grammar, sourceCode, { removeStrings: true });\n}\n\ninterface CommentOrStringGrammar {\n closeRegExp: RegExp;\n isComment: boolean;\n openRegExp: RegExp;\n templateSyntax?: 'kotlin';\n}\n\ninterface BalancedExpressionOptions {\n slashStartsComments?: boolean;\n slashStartsRegExp: boolean;\n supportsKotlinStrings?: boolean;\n}\n\nfunction removeCommentsAndMaybeStringsInSourceCode(\n grammar: SourceCodeGrammar,\n sourceCode: string,\n options: { removeStrings: boolean },\n commentOrStringGrammars = compileCommentOrStringGrammars(grammar)\n): string {\n if (!grammar.comments?.length && (!options.removeStrings || !grammar.strings?.length)) return sourceCode;\n\n const newSourceCodeSlices: string[] = [];\n\n let lastIndex = 0;\n\n while (lastIndex < sourceCode.length) {\n let first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined;\n\n for (const commentOrStringGrammer of commentOrStringGrammars) {\n const startRegExp = commentOrStringGrammer.openRegExp;\n startRegExp.lastIndex = lastIndex;\n\n const match = startRegExp.exec(sourceCode);\n\n if (match && shouldPreferMatch(match, commentOrStringGrammer, first, options)) {\n first = { grammar: commentOrStringGrammer, match };\n }\n }\n\n if (first) {\n let stringPrefixStartIndex = first.match.index;\n if (!first.grammar.isComment && options.removeStrings) {\n stringPrefixStartIndex = getPythonStringPrefixStartIndex(sourceCode, first.match.index);\n }\n newSourceCodeSlices.push(sourceCode.slice(lastIndex, stringPrefixStartIndex));\n\n if (!first.grammar.isComment) {\n lastIndex = findStringEndIndex(sourceCode, first.match.index, first.grammar);\n const stringLiteral = sourceCode.slice(first.match.index, lastIndex);\n if (options.removeStrings) {\n newSourceCodeSlices.push(\n preserveStringInterpolationExpressions(\n grammar,\n commentOrStringGrammars,\n first.grammar,\n sourceCode,\n first.match.index,\n stringLiteral\n )\n );\n } else {\n newSourceCodeSlices.push(stringLiteral);\n }\n } else {\n const closeRegExp = first.grammar.closeRegExp;\n closeRegExp.lastIndex = first.match.index + first.match[0].length;\n\n const match = closeRegExp.exec(sourceCode);\n\n lastIndex = match ? match.index + match[0].length : sourceCode.length;\n }\n } else {\n newSourceCodeSlices.push(sourceCode.slice(lastIndex));\n lastIndex = sourceCode.length;\n }\n }\n\n return newSourceCodeSlices.join('');\n}\n\nfunction compileCommentOrStringGrammars(grammar: SourceCodeGrammar): readonly CommentOrStringGrammar[] {\n return [\n ...(grammar.comments?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close ?? /(?=\\n)/g),\n isComment: true,\n openRegExp: makeGlobalRegExp(v.open),\n })) ?? []),\n ...(grammar.strings?.map((v) => ({\n closeRegExp: makeGlobalRegExp(v.close),\n isComment: false,\n openRegExp: makeGlobalRegExp(v.open),\n templateSyntax: v.templateSyntax,\n })) ?? []),\n ] satisfies CommentOrStringGrammar[];\n}\n\nfunction shouldPreferMatch(\n match: RegExpExecArray,\n grammar: CommentOrStringGrammar,\n first: { grammar: CommentOrStringGrammar; match: RegExpExecArray } | undefined,\n options: { removeStrings: boolean }\n): boolean {\n if (!first) return true;\n if (match.index < first.match.index) return true;\n if (match.index > first.match.index) return false;\n return options.removeStrings && first.grammar.isComment && !grammar.isComment;\n}\n\nfunction makeGlobalRegExp(regExp: RegExp): RegExp {\n return new RegExp(regExp, regExp.flags.includes('g') ? regExp.flags : `${regExp.flags}g`);\n}\n\nfunction findStringEndIndex(sourceCode: string, stringStartIndex: number, grammar: CommentOrStringGrammar): number {\n if (grammar.templateSyntax === 'kotlin') return findKotlinStringEndIndex(sourceCode, stringStartIndex);\n if (sourceCode[stringStartIndex] === '`') return findJavaScriptTemplateEndIndex(sourceCode, stringStartIndex);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return findPythonFStringEndIndex(sourceCode, stringStartIndex);\n\n const closeRegExp = grammar.closeRegExp;\n closeRegExp.lastIndex = stringStartIndex + 1;\n const match = closeRegExp.exec(sourceCode);\n return match ? match.index + match[0].length : sourceCode.length;\n}\n\nfunction findKotlinStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n const isRawString = quote.length === 3;\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (!isRawString && sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index =\n readBalancedExpression(sourceCode, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findJavaScriptTemplateEndIndex(sourceCode: string, stringStartIndex: number): number {\n let index = stringStartIndex + 1;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '`') return index + 1;\n if (sourceCode[index] === '$' && sourceCode[index + 1] === '{') {\n index = readBalancedExpression(sourceCode, index + 2, '}', { slashStartsRegExp: true }).endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return sourceCode.length;\n}\n\nfunction findPythonFStringEndIndex(sourceCode: string, stringStartIndex: number): number {\n const quote = getStringQuote(sourceCode, stringStartIndex);\n let index = stringStartIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n if (sourceCode[index] === '{' && sourceCode[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '{') {\n index = readBalancedExpression(sourceCode, index + 1, '}', { slashStartsRegExp: false }).endIndex + 1;\n continue;\n }\n index += sourceCode[index] === '\\\\' ? 2 : 1;\n }\n\n return sourceCode.length;\n}\n\nfunction getStringQuote(sourceCode: string, stringStartIndex: number): string {\n const threeCharacterQuote = sourceCode.slice(stringStartIndex, stringStartIndex + 3);\n if (threeCharacterQuote === \"'''\" || threeCharacterQuote === '\"\"\"') return threeCharacterQuote;\n return sourceCode[stringStartIndex] ?? '';\n}\n\nfunction getPythonStringPrefixStartIndex(sourceCode: string, stringStartIndex: number): number {\n const prefix = getPythonStringPrefix(sourceCode, stringStartIndex);\n return prefix ? stringStartIndex - prefix.length : stringStartIndex;\n}\n\nfunction getPythonStringPrefix(sourceCode: string, stringStartIndex: number): string | undefined {\n if (sourceCode[stringStartIndex] !== '\"' && sourceCode[stringStartIndex] !== \"'\") return undefined;\n let index = stringStartIndex - 1;\n while (index >= 0 && /[A-Za-z]/.test(sourceCode[index] ?? '')) index -= 1;\n\n const prefix = sourceCode.slice(index + 1, stringStartIndex);\n if (!prefix || !/^[bfru]+$/i.test(prefix)) return undefined;\n if (index >= 0 && /[\\dA-Za-z_]/.test(sourceCode[index] ?? '')) return undefined;\n\n return prefix;\n}\n\nfunction preserveStringInterpolationExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringGrammar: CommentOrStringGrammar,\n sourceCode: string,\n stringStartIndex: number,\n stringLiteral: string\n): string {\n if (stringGrammar.templateSyntax === 'kotlin')\n return preserveKotlinStringTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (stringLiteral.startsWith('`'))\n return preserveJavaScriptTemplateExpressions(grammar, commentOrStringGrammars, stringLiteral);\n if (hasPythonFStringPrefix(sourceCode, stringStartIndex))\n return preservePythonFStringExpressions(grammar, commentOrStringGrammars, stringLiteral);\n return '';\n}\n\nfunction preserveKotlinStringTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const isRawString = quoteLength === 3;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (!isRawString && stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] !== '$') {\n index += 1;\n continue;\n }\n if (stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', {\n slashStartsComments: true,\n slashStartsRegExp: false,\n supportsKotlinStrings: true,\n });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n if (isKotlinIdentifierStart(stringLiteral[index + 1])) {\n let endIndex = index + 2;\n while (isKotlinIdentifierPart(stringLiteral[endIndex])) endIndex += 1;\n expressions.push(stringLiteral.slice(index + 1, endIndex));\n index = endIndex;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction isKotlinIdentifierStart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}_]/u.test(character);\n}\n\nfunction isKotlinIdentifierPart(character: string | undefined): boolean {\n return character !== undefined && /[\\p{L}\\p{N}_]/u.test(character);\n}\n\nfunction hasPythonFStringPrefix(sourceCode: string, stringStartIndex: number): boolean {\n return getPythonStringPrefix(sourceCode, stringStartIndex)?.toLowerCase().includes('f') ?? false;\n}\n\nfunction preserveJavaScriptTemplateExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const expressions: string[] = [];\n let index = 1;\n\n while (index < stringLiteral.length - 1) {\n if (stringLiteral[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '$' && stringLiteral[index + 1] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 2, '}', { slashStartsRegExp: true });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction preservePythonFStringExpressions(\n grammar: SourceCodeGrammar,\n commentOrStringGrammars: readonly CommentOrStringGrammar[],\n stringLiteral: string\n): string {\n const quoteLength = getStringQuote(stringLiteral, 0).length;\n const expressions: string[] = [];\n let index = quoteLength;\n\n while (index < stringLiteral.length - quoteLength) {\n if (stringLiteral[index] === '{' && stringLiteral[index + 1] === '{') {\n index += 2;\n continue;\n }\n if (stringLiteral[index] === '{') {\n const expression = readBalancedExpression(stringLiteral, index + 1, '}', { slashStartsRegExp: false });\n expressions.push(\n removeCommentsAndMaybeStringsInSourceCode(\n grammar,\n expression.content,\n { removeStrings: true },\n commentOrStringGrammars\n )\n );\n index = expression.endIndex + 1;\n continue;\n }\n index += stringLiteral[index] === '\\\\' ? 2 : 1;\n }\n\n return expressions.join('\\n');\n}\n\nfunction readBalancedExpression(\n sourceCode: string,\n startIndex: number,\n closeChar: string,\n options: BalancedExpressionOptions\n): { content: string; endIndex: number } {\n let depth = 1;\n let index = startIndex;\n\n while (index < sourceCode.length) {\n const char = sourceCode[index];\n if (char === '\"' && options.supportsKotlinStrings) {\n index = findKotlinStringEndIndex(sourceCode, index);\n continue;\n }\n if (char === '\"' || char === \"'\" || char === '`') {\n index = skipQuotedSpan(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '/'\n ) {\n index = skipJavaScriptSingleLineComment(sourceCode, index);\n continue;\n }\n if (\n (options.slashStartsComments || options.slashStartsRegExp) &&\n sourceCode[index] === '/' &&\n sourceCode[index + 1] === '*'\n ) {\n index = skipJavaScriptBlockComment(sourceCode, index);\n continue;\n }\n if (options.slashStartsRegExp && char === '/') {\n index = skipJavaScriptRegExpLiteral(sourceCode, index);\n continue;\n }\n if (char === '{') depth += 1;\n if (char === closeChar) {\n depth -= 1;\n if (depth === 0) return { content: sourceCode.slice(startIndex, index), endIndex: index };\n }\n index += 1;\n }\n\n return { content: sourceCode.slice(startIndex), endIndex: sourceCode.length };\n}\n\nfunction skipQuotedSpan(sourceCode: string, startIndex: number): number {\n const quote = getStringQuote(sourceCode, startIndex);\n let index = startIndex + quote.length;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode.startsWith(quote, index)) return index + quote.length;\n index += 1;\n }\n\n return index;\n}\n\nfunction skipJavaScriptRegExpLiteral(sourceCode: string, startIndex: number): number {\n let index = startIndex + 1;\n let inCharacterClass = false;\n\n while (index < sourceCode.length) {\n if (sourceCode[index] === '\\\\') {\n index += 2;\n continue;\n }\n if (sourceCode[index] === '[') inCharacterClass = true;\n if (sourceCode[index] === ']') inCharacterClass = false;\n if (sourceCode[index] === '/' && !inCharacterClass) {\n index += 1;\n while (/[A-Za-z]/.test(sourceCode[index] ?? '')) index += 1;\n return index;\n }\n if (sourceCode[index] === '\\n') return startIndex + 1;\n index += 1;\n }\n\n return startIndex + 1;\n}\n\nfunction skipJavaScriptSingleLineComment(sourceCode: string, startIndex: number): number {\n const newLineIndex = sourceCode.indexOf('\\n', startIndex + 2);\n return newLineIndex === -1 ? sourceCode.length : newLineIndex;\n}\n\nfunction skipJavaScriptBlockComment(sourceCode: string, startIndex: number): number {\n const endIndex = sourceCode.indexOf('*/', startIndex + 2);\n return endIndex === -1 ? sourceCode.length : endIndex + 2;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveCwds.cjs","names":["findModelAnswerDirs","findFailingModelAnswerDirs","path","MODEL_ANSWERS_DIRNAME","FAILING_MODEL_ANSWERS_DIRNAME"],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"yLAgCA,
|
|
1
|
+
{"version":3,"file":"resolveCwds.cjs","names":["findModelAnswerDirs","findFailingModelAnswerDirs","path","MODEL_ANSWERS_DIRNAME","FAILING_MODEL_ANSWERS_DIRNAME","require_runtime","require_printDebugBanner","require_findModelAnswerDirs","node_path","resolveCwds","cwdArg","modelAnswerDirs","failingModelAnswerDirs","problemDir","scriptName","getInvokedScriptName","exampleAnswer","dir","printDebugCwdBanner","relativeCwd","resolvedCwd","printDebugExpectationFailureBanner","scriptPath"],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"yLAgCA,eAAsBS,EAAY,EAAoB,EAAmD,CACvG,GAAIC,EAAQ,MAAO,CAAE,KAAM,CAAC,CAAE,IAAKA,EAAQ,eAAgB,UAAW,CAAC,EAAG,YAAa,EAAM,EAE7F,GAAM,CAACC,EAAiBC,GAA0B,MAAM,QAAQ,IAAI,CAClEZ,EAAAA,oBAAoBa,CAAU,EAC9BZ,EAAAA,2BAA2BY,CAAU,CACvC,CAAC,EACD,GAAIF,EAAgB,SAAW,GAAKC,EAAuB,SAAW,EACpE,MAAU,MACR,+DAA+DV,EAAAA,QAAK,KAAKW,EAAYV,EAAAA,qBAAqB,EAAE,MAAMD,EAAAA,QAAK,KAAKW,EAAYT,EAAAA,6BAA6B,EAAE,EACzK,EAGF,IAAMU,EAAaC,EAAqB,EAClCC,EACJd,EAAAA,QAAK,SAASW,EAAYF,EAAgB,IAAMC,EAAuB,IAAM,EAAE,GAAK,iBAiBtF,OAhBAN,EAAA,iBAAiB,CACf,qEACA,GACA,iBAAiBO,IACjB,kBAAkBF,EAAgB,OAAO,IACzC,GAAGA,EAAgB,IAAK,GAAQ,OAAOT,EAAAA,QAAK,SAASW,EAAYI,CAAG,GAAG,EACvE,0BAA0BL,EAAuB,OAAO,IACxD,GAAGA,EAAuB,IAAK,GAAQ,OAAOV,EAAAA,QAAK,SAASW,EAAYI,CAAG,GAAG,EAC9E,GACA,kFACA,SAASH,EAAW,sBACpB,eACA,SAASA,EAAW,GAAGE,IACvB,SAASF,EAAW,GAAGE,EAAc,yBACvC,CAAC,EAEM,CACL,KAAM,CACJ,GAAGL,EAAgB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,EAC9E,GAAGC,EAAuB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,CACvF,EACA,YAAa,EACf,CACF,CAMA,SAAgBM,EAAoB,EAAoB,EAAgC,CACtF,IAAMC,EAAcjB,EAAAA,QAAK,SAASW,EAAYO,EAAY,GAAG,GAAKA,EAAY,IACxEN,EAAaC,EAAqB,EACxCT,EAAA,iBAAiB,CACf,yBAAyBa,IACzB,oBAAoBC,EAAY,iBAChC,GACA,iDACA,SAASN,EAAW,GAAGK,IACvB,qDACF,CAAC,CACH,CAEA,SAAgBE,EAAmC,EAAoB,EAAgC,CACrG,IAAMF,EAAcjB,EAAAA,QAAK,SAASW,EAAYO,EAAY,GAAG,GAAKA,EAAY,IAC9Ed,EAAA,iBAAiB,CACf,oCAAoCa,IACpC,oBAAoBC,EAAY,iBAChCA,EAAY,iBAAmB,WAC3B,8CACA,qDACN,CAAC,CACH,CAEA,SAASL,GAA+B,CACtC,IAAMO,EAAa,QAAQ,KAAK,GAChC,OAAOA,EAAapB,EAAAA,QAAK,SAASoB,CAAU,EAAI,UAClD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveCwds.js","names":[],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"+OAgCA,
|
|
1
|
+
{"version":3,"file":"resolveCwds.js","names":["path","resolveCwds","cwdArg","modelAnswerDirs","failingModelAnswerDirs","findModelAnswerDirs","problemDir","findFailingModelAnswerDirs","MODEL_ANSWERS_DIRNAME","FAILING_MODEL_ANSWERS_DIRNAME","scriptName","getInvokedScriptName","exampleAnswer","printDebugBanner","dir","printDebugCwdBanner","relativeCwd","resolvedCwd","printDebugExpectationFailureBanner","scriptPath"],"sources":["../../src/helpers/resolveCwds.ts"],"sourcesContent":["import path from 'node:path';\n\nimport {\n FAILING_MODEL_ANSWERS_DIRNAME,\n MODEL_ANSWERS_DIRNAME,\n findFailingModelAnswerDirs,\n findModelAnswerDirs,\n} from './findModelAnswerDirs.js';\nimport { printDebugBanner } from './printDebugBanner.js';\n\nexport type ExpectedJudgeResult = 'accepted' | 'rejected';\n\nexport interface ResolvedCwd {\n cwd: string;\n expectedResult: ExpectedJudgeResult;\n}\n\nexport interface ResolvedCwds {\n cwds: readonly ResolvedCwd[];\n isDebugMode: boolean;\n}\n\n/**\n * Resolve which working directories to judge.\n *\n * - If `cwdArg` is provided, use it as the single cwd.\n * - Otherwise (debug mode), enumerate `<problemDir>/model_answers/*` and\n * `<problemDir>/model_answers.fails/*` and judge each.\n * A prominent banner is printed so users can tell at a glance that this is a debug run.\n *\n * @throws if `cwdArg` is missing and no model answer directories are found.\n */\nexport async function resolveCwds(problemDir: string, cwdArg: string | undefined): Promise<ResolvedCwds> {\n if (cwdArg) return { cwds: [{ cwd: cwdArg, expectedResult: 'accepted' }], isDebugMode: false };\n\n const [modelAnswerDirs, failingModelAnswerDirs] = await Promise.all([\n findModelAnswerDirs(problemDir),\n findFailingModelAnswerDirs(problemDir),\n ]);\n if (modelAnswerDirs.length === 0 && failingModelAnswerDirs.length === 0) {\n throw new Error(\n `cwd argument required (no model answer directories found in ${path.join(problemDir, MODEL_ANSWERS_DIRNAME)} or ${path.join(problemDir, FAILING_MODEL_ANSWERS_DIRNAME)})`\n );\n }\n\n const scriptName = getInvokedScriptName();\n const exampleAnswer =\n path.relative(problemDir, modelAnswerDirs[0] ?? failingModelAnswerDirs[0] ?? '') || '<model_answer>';\n printDebugBanner([\n '[DEBUG MODE] cwd not provided -- judging against all model answers',\n '',\n `Problem dir : ${problemDir}`,\n `Model answers (${modelAnswerDirs.length}):`,\n ...modelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n `Failing model answers (${failingModelAnswerDirs.length}):`,\n ...failingModelAnswerDirs.map((dir) => ` - ${path.relative(problemDir, dir)}`),\n '',\n 'To judge a single cwd (e.g., a user submission), pass it as the first argument:',\n ` bun ${scriptName} <cwd> [params-json]`,\n 'For example:',\n ` bun ${scriptName} ${exampleAnswer}`,\n ` bun ${scriptName} ${exampleAnswer} '{\"language\":\"python\"}'`,\n ]);\n\n return {\n cwds: [\n ...modelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'accepted' as const })),\n ...failingModelAnswerDirs.map((cwd) => ({ cwd, expectedResult: 'rejected' as const })),\n ],\n isDebugMode: true,\n };\n}\n\n/**\n * Print a per-cwd banner shown before judging each model answer in debug mode.\n * Includes the command for re-running this single cwd.\n */\nexport function printDebugCwdBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n const scriptName = getInvokedScriptName();\n printDebugBanner([\n `[DEBUG MODE] judging: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n '',\n 'To judge only this cwd as a normal submission:',\n ` bun ${scriptName} ${relativeCwd}`,\n 'Run without a cwd to check debug-mode expectations.',\n ]);\n}\n\nexport function printDebugExpectationFailureBanner(problemDir: string, resolvedCwd: ResolvedCwd): void {\n const relativeCwd = path.relative(problemDir, resolvedCwd.cwd) || resolvedCwd.cwd;\n printDebugBanner([\n `[DEBUG MODE] expectation failed: ${relativeCwd}`,\n `Expected result: ${resolvedCwd.expectedResult}`,\n resolvedCwd.expectedResult === 'accepted'\n ? 'The model answer was rejected by the judge.'\n : 'The failing model answer was accepted by the judge.',\n ]);\n}\n\nfunction getInvokedScriptName(): string {\n const scriptPath = process.argv[1];\n return scriptPath ? path.basename(scriptPath) : 'judge.ts';\n}\n"],"mappings":"+OAgCA,eAAsBC,EAAY,EAAoB,EAAmD,CACvG,GAAIC,EAAQ,MAAO,CAAE,KAAM,CAAC,CAAE,IAAKA,EAAQ,eAAgB,UAAW,CAAC,EAAG,YAAa,EAAM,EAE7F,GAAM,CAACC,EAAiBC,GAA0B,MAAM,QAAQ,IAAI,CAClEC,EAAoBC,CAAU,EAC9BC,EAA2BD,CAAU,CACvC,CAAC,EACD,GAAIH,EAAgB,SAAW,GAAKC,EAAuB,SAAW,EACpE,MAAU,MACR,+DAA+DJ,EAAK,KAAKM,EAAYE,CAAqB,EAAE,MAAMR,EAAK,KAAKM,EAAYG,CAA6B,EAAE,EACzK,EAGF,IAAMC,EAAaC,EAAqB,EAClCC,EACJZ,EAAK,SAASM,EAAYH,EAAgB,IAAMC,EAAuB,IAAM,EAAE,GAAK,iBAiBtF,OAhBAS,EAAiB,CACf,qEACA,GACA,iBAAiBP,IACjB,kBAAkBH,EAAgB,OAAO,IACzC,GAAGA,EAAgB,IAAK,GAAQ,OAAOH,EAAK,SAASM,EAAYQ,CAAG,GAAG,EACvE,0BAA0BV,EAAuB,OAAO,IACxD,GAAGA,EAAuB,IAAK,GAAQ,OAAOJ,EAAK,SAASM,EAAYQ,CAAG,GAAG,EAC9E,GACA,kFACA,SAASJ,EAAW,sBACpB,eACA,SAASA,EAAW,GAAGE,IACvB,SAASF,EAAW,GAAGE,EAAc,yBACvC,CAAC,EAEM,CACL,KAAM,CACJ,GAAGT,EAAgB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,EAC9E,GAAGC,EAAuB,IAAK,IAAS,CAAE,MAAK,eAAgB,UAAoB,EAAE,CACvF,EACA,YAAa,EACf,CACF,CAMA,SAAgBW,EAAoB,EAAoB,EAAgC,CACtF,IAAMC,EAAchB,EAAK,SAASM,EAAYW,EAAY,GAAG,GAAKA,EAAY,IACxEP,EAAaC,EAAqB,EACxCE,EAAiB,CACf,yBAAyBG,IACzB,oBAAoBC,EAAY,iBAChC,GACA,iDACA,SAASP,EAAW,GAAGM,IACvB,qDACF,CAAC,CACH,CAEA,SAAgBE,EAAmC,EAAoB,EAAgC,CACrG,IAAMF,EAAchB,EAAK,SAASM,EAAYW,EAAY,GAAG,GAAKA,EAAY,IAC9EJ,EAAiB,CACf,oCAAoCG,IACpC,oBAAoBC,EAAY,iBAChCA,EAAY,iBAAmB,WAC3B,8CACA,qDACN,CAAC,CACH,CAEA,SAASN,GAA+B,CACtC,IAAMQ,EAAa,QAAQ,KAAK,GAChC,OAAOA,EAAanB,EAAK,SAASmB,CAAU,EAAI,UAClD"}
|