or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

commonjs-context.mdimport-export-analysis.mdindex.mdmodule-evaluation.mdmodule-resolution.mdsyntax-detection.mdutility-functions.md

syntax-detection.mddocs/

0

# Syntax Detection

1

2

Utilities for detecting ECMAScript module syntax, CommonJS syntax, and validating whether imports are safe for dynamic import() calls in Node.js. Uses heuristic-based pattern matching for fast analysis.

3

4

## Capabilities

5

6

### Has ESM Syntax

7

8

Determines if a given code string contains ECMAScript module syntax.

9

10

```typescript { .api }

11

/**

12

* Determines if a given code string contains ECMAScript module syntax

13

* @param code - The source code to analyse

14

* @param opts - Options for syntax detection

15

* @returns `true` if the code contains ESM syntax, otherwise `false`

16

*/

17

function hasESMSyntax(code: string, opts?: DetectSyntaxOptions): boolean;

18

```

19

20

**Usage Examples:**

21

22

```typescript

23

import { hasESMSyntax } from "mlly";

24

25

console.log(hasESMSyntax("export default foo = 123")); // true

26

console.log(hasESMSyntax("import { bar } from 'baz'")); // true

27

console.log(hasESMSyntax("const x = require('y')")); // false

28

```

29

30

### Has CJS Syntax

31

32

Determines if a given string of code contains CommonJS syntax.

33

34

```typescript { .api }

35

/**

36

* Determines if a given string of code contains CommonJS syntax

37

* @param code - The source code to analyse

38

* @param opts - Options for syntax detection

39

* @returns `true` if the code contains CommonJS syntax, `false` otherwise

40

*/

41

function hasCJSSyntax(code: string, opts?: DetectSyntaxOptions): boolean;

42

```

43

44

**Usage Examples:**

45

46

```typescript

47

import { hasCJSSyntax } from "mlly";

48

49

console.log(hasCJSSyntax("module.exports = {}")); // true

50

console.log(hasCJSSyntax("exports.foo = 'bar'")); // true

51

console.log(hasCJSSyntax("const x = require('y')")); // true

52

console.log(hasCJSSyntax("export default foo")); // false

53

```

54

55

### Detect Syntax

56

57

Analyses the supplied code to determine if it contains ECMAScript module syntax, CommonJS syntax, or both.

58

59

```typescript { .api }

60

/**

61

* Analyses the supplied code to determine if it contains ECMAScript module syntax, CommonJS syntax, or both

62

* @param code - The source code to analyse

63

* @param opts - Options for syntax detection

64

* @returns An object indicating the presence of ESM syntax (`hasESM`), CJS syntax (`hasCJS`) and whether both syntaxes are present (`isMixed`)

65

*/

66

function detectSyntax(code: string, opts?: DetectSyntaxOptions): {

67

hasESM: boolean;

68

hasCJS: boolean;

69

isMixed: boolean;

70

};

71

```

72

73

**Usage Example:**

74

75

```typescript

76

import { detectSyntax } from "mlly";

77

78

// Mixed syntax (common in legacy packages)

79

const result = detectSyntax('export default require("lodash")');

80

console.log(result); // { hasESM: true, hasCJS: true, isMixed: true }

81

82

// Pure ESM

83

const esmResult = detectSyntax('export const foo = "bar"');

84

console.log(esmResult); // { hasESM: true, hasCJS: false, isMixed: false }

85

```

86

87

### Is Valid Node Import

88

89

Validates whether a given identifier represents a valid node import, based on its protocol, file extension, and optionally its contents.

90

91

```typescript { .api }

92

/**

93

* Validates whether a given identifier represents a valid node import, based on its protocol, file extension, and optionally its contents

94

* @param id - The identifier or URL of the import to validate

95

* @param options - Options for resolving and validating the import

96

* @returns A promise that resolves to `true` if the import is valid, otherwise `false`

97

*/

98

function isValidNodeImport(id: string, options?: ValidNodeImportOptions): Promise<boolean>;

99

```

100

101

**Usage Examples:**

102

103

```typescript

104

import { isValidNodeImport } from "mlly";

105

106

// Check if safe to use dynamic import()

107

const isValid = await isValidNodeImport("some-package");

108

if (isValid) {

109

const module = await import("some-package");

110

} else {

111

// Need to use CommonJS require or bundler transform

112

console.log("This import requires special handling");

113

}

114

115

// Built-in modules are always valid

116

console.log(await isValidNodeImport("fs")); // true

117

console.log(await isValidNodeImport("node:path")); // true

118

119

// Data URLs are valid

120

console.log(await isValidNodeImport("data:text/javascript,export default 42")); // true

121

```

122

123

**Algorithm:**

124

125

The `isValidNodeImport` function uses the following validation steps:

126

127

1. **Protocol Check** - If is `data:` return `true` (✅ valid) - If is not `node:`, `file:` or `data:`, return `false` (❌ invalid)

128

2. **Resolve Path** - Use Node.js Resolution algorithm to resolve full path

129

3. **Extension Check** - If is `.mjs`, `.cjs`, `.node` or `.wasm`, return `true` (✅ valid) - If is not `.js`, return `false` (❌ invalid) - If matches known mixed syntax patterns (`.esm.js`, `.es.js`, etc) return `false` (❌ invalid)

130

4. **Package.json Check** - Read closest `package.json` file - If `type: 'module'` field is set, return `true` (✅ valid)

131

5. **Source Analysis** - Read source code of resolved path - Try to detect CommonJS syntax usage - If yes, return `true` (✅ valid) - Try to detect ESM syntax usage - If yes, return `false` (❌ invalid)

132

133

## Types

134

135

```typescript { .api }

136

interface DetectSyntaxOptions {

137

/** Indicates whether comments should be stripped from the code before syntax checking */

138

stripComments?: boolean;

139

}

140

141

interface ValidNodeImportOptions extends ResolveOptions {

142

/** The contents of the import, which may be analyzed to see if it contains CJS or ESM syntax as a last step in checking whether it is a valid import */

143

code?: string;

144

/** Protocols that are allowed as valid node imports */

145

allowedProtocols?: Array<string>;

146

/** Whether to strip comments from the code before checking for ESM syntax */

147

stripComments?: boolean;

148

}

149

```