74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
|
/*---------------------------------------------------------------------------------------------
|
||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||
|
*--------------------------------------------------------------------------------------------*/
|
||
|
|
||
|
import { JSONVisitor, visit } from 'jsonc-parser';
|
||
|
import { Location, Position, Range, TextDocument } from 'vscode';
|
||
|
|
||
|
export interface INpmScriptReference {
|
||
|
name: string;
|
||
|
value: string;
|
||
|
nameRange: Range;
|
||
|
valueRange: Range;
|
||
|
}
|
||
|
|
||
|
export interface INpmScriptInfo {
|
||
|
location: Location;
|
||
|
scripts: INpmScriptReference[];
|
||
|
}
|
||
|
|
||
|
export const readScripts = (document: TextDocument, buffer = document.getText()): INpmScriptInfo | undefined => {
|
||
|
let start: Position | undefined;
|
||
|
let end: Position | undefined;
|
||
|
let inScripts = false;
|
||
|
let buildingScript: { name: string; nameRange: Range } | void;
|
||
|
let level = 0;
|
||
|
|
||
|
const scripts: INpmScriptReference[] = [];
|
||
|
const visitor: JSONVisitor = {
|
||
|
onError() {
|
||
|
// no-op
|
||
|
},
|
||
|
onObjectBegin() {
|
||
|
level++;
|
||
|
},
|
||
|
onObjectEnd(offset) {
|
||
|
if (inScripts) {
|
||
|
end = document.positionAt(offset);
|
||
|
inScripts = false;
|
||
|
}
|
||
|
level--;
|
||
|
},
|
||
|
onLiteralValue(value: unknown, offset: number, length: number) {
|
||
|
if (buildingScript && typeof value === 'string') {
|
||
|
scripts.push({
|
||
|
...buildingScript,
|
||
|
value,
|
||
|
valueRange: new Range(document.positionAt(offset), document.positionAt(offset + length)),
|
||
|
});
|
||
|
buildingScript = undefined;
|
||
|
}
|
||
|
},
|
||
|
onObjectProperty(property: string, offset: number, length: number) {
|
||
|
if (level === 1 && property === 'scripts') {
|
||
|
inScripts = true;
|
||
|
start = document.positionAt(offset);
|
||
|
} else if (inScripts) {
|
||
|
buildingScript = {
|
||
|
name: property,
|
||
|
nameRange: new Range(document.positionAt(offset), document.positionAt(offset + length))
|
||
|
};
|
||
|
}
|
||
|
},
|
||
|
};
|
||
|
|
||
|
visit(buffer, visitor);
|
||
|
|
||
|
if (start === undefined) {
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
return { location: new Location(document.uri, new Range(start, end ?? start)), scripts };
|
||
|
};
|