Skip to content

Commit

Permalink
Fix code frame for Node.js v21 (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed Oct 27, 2023
1 parent be6fbf9 commit 789771a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 19 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ jobs:
fail-fast: false
matrix:
node-version:
- 21
- 20
- 18
- 16
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
Expand Down
40 changes: 26 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ export const JSONError = errorEx('JSONError', {
codeFrame: errorEx.append('\n\n%s\n'),
});

const generateCodeFrame = (string, location, highlightCode = true) =>
codeFrameColumns(string, {start: location}, {highlightCode});

const getErrorLocation = (string, error) => {
const match = error.message.match(/in JSON at position (?<index>\d+)(?: \(line (?<line>\d+) column (?<column>\d+)\))? while parsing/);

if (!match) {
return;
}

let {index, line, column} = match.groups;

if (line && column) {
return {line: Number(line), column: Number(column)};
}

({line, column} = new LinesAndColumns(string).locationForIndex(Number(index)));

return {line: line + 1, column: column + 1};
};

export default function parseJson(string, reviver, filename) {
if (typeof reviver === 'string') {
filename = reviver;
Expand All @@ -23,26 +44,17 @@ export default function parseJson(string, reviver, filename) {
}
} catch (error) {
error.message = error.message.replace(/\n/g, '');
const indexMatch = error.message.match(/in JSON at position (\d+) while parsing/);

const jsonError = new JSONError(error);

if (filename) {
jsonError.fileName = filename;
}

if (indexMatch && indexMatch.length > 0) {
const lines = new LinesAndColumns(string);
const index = Number(indexMatch[1]);
const location = lines.locationForIndex(index);

const generateCodeFrame = ({highlightCode}) => codeFrameColumns(
string,
{start: {line: location.line + 1, column: location.column + 1}},
{highlightCode},
);

jsonError.codeFrame = generateCodeFrame({highlightCode: true});
jsonError.rawCodeFrame = generateCodeFrame({highlightCode: false});
const location = getErrorLocation(string, error);
if (location) {
jsonError.codeFrame = generateCodeFrame(string, location);
jsonError.rawCodeFrame = generateCodeFrame(string, location, /* highlightCode */ false);
}

throw jsonError;
Expand Down
16 changes: 13 additions & 3 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@ import process from 'node:process';
import test from 'ava';
import parseJson, {JSONError} from './index.js';

const errorMessageRegex = /^v(?:16|18)\./.test(process.version)
? /Unexpected token "}"/
: /Expected double-quoted property name in JSON at position 16 while parsing/;
const errorMessageRegex = (() => {
const version = Number(process.versions.node.split('.')[0]);

if (version < 20) {
return /Unexpected token "}"/;
}

if (version < 21) {
return /Expected double-quoted property name in JSON at position 16 while parsing/;
}

return /Expected double-quoted property name in JSON at position 16 \(line 3 column 1\) while parsing/;
})();
const errorMessageRegexWithFileName = new RegExp(errorMessageRegex.source + '.*in foo\\.json');

test('main', t => {
Expand Down

0 comments on commit 789771a

Please sign in to comment.