diff --git a/src/syntax.ts b/src/syntax.ts index 7a5855e..2711495 100644 --- a/src/syntax.ts +++ b/src/syntax.ts @@ -14,17 +14,35 @@ const COMMENT_RE = /\/\*.+?\*\/|\/\/.*(?=[nr])/g; const BUILTIN_EXTENSIONS = new Set([".mjs", ".cjs", ".node", ".wasm"]); -export function hasESMSyntax(code: string): boolean { - return ESM_RE.test(code.replace(COMMENT_RE, "")); +export type DetectSyntaxOptions = { stripComments?: boolean }; + +export function hasESMSyntax( + code: string, + opts: DetectSyntaxOptions = {}, +): boolean { + if (opts.stripComments) { + code = code.replace(COMMENT_RE, ""); + } + return ESM_RE.test(code); } -export function hasCJSSyntax(code: string): boolean { - return CJS_RE.test(code.replace(COMMENT_RE, "")); +export function hasCJSSyntax( + code: string, + opts: DetectSyntaxOptions = {}, +): boolean { + if (opts.stripComments) { + code = code.replace(COMMENT_RE, ""); + } + return CJS_RE.test(code); } -export function detectSyntax(code: string) { - const hasESM = hasESMSyntax(code); - const hasCJS = hasCJSSyntax(code); +export function detectSyntax(code: string, opts: DetectSyntaxOptions = {}) { + if (opts.stripComments) { + code = code.replace(COMMENT_RE, ""); + } + // We strip comments once hence not passing opts down to hasESMSyntax and hasCJSSyntax + const hasESM = hasESMSyntax(code, {}); + const hasCJS = hasCJSSyntax(code, {}); return { hasESM, diff --git a/test/syntax.test.ts b/test/syntax.test.ts index 4e8c286..785cb07 100644 --- a/test/syntax.test.ts +++ b/test/syntax.test.ts @@ -61,6 +61,11 @@ const staticTests = { isMixed: false, }, "export class": { hasESM: true, hasCJS: false, isMixed: false }, + "const start = '/* ';import foo from 'bar';const end = ' */'": { + hasESM: true, + hasCJS: false, + isMixed: false, + }, // CJS "exports.c={}": { hasESM: false, hasCJS: true, isMixed: false }, "const b=true;module.exports={b};": { @@ -82,6 +87,9 @@ const staticTests = { isMixed: false, }, "const a={};": { hasESM: false, hasCJS: false, isMixed: false }, +}; + +const staticTestsWithComments = { '// They\'re exposed using "export import" so that types are passed along as expected\nmodule.exports={};': { hasESM: false, hasCJS: true, isMixed: false }, }; @@ -94,6 +102,16 @@ describe("detectSyntax", () => { } }); +describe("detectSyntax (with comment)", () => { + for (const [input, result] of Object.entries(staticTestsWithComments)) { + it(input, () => { + expect(detectSyntax(input, { stripComments: true })).to.deep.equal( + result, + ); + }); + } +}); + const nodeImportTests = { "node:fs": true, fs: true,