elearning/Frontend-Learner/node_modules/parse-imports-exports/partParsers.js
2026-01-13 10:48:02 +07:00

169 lines
5.2 KiB
JavaScript

/**
* Parses destructuring assignment.
*/
export const parseDestructuring = (sourceStartsWithDestructuring) => {
const openBracket = sourceStartsWithDestructuring[0];
const closeBracket = openBracket === '{' ? '}' : ']';
const names = [];
var bracketsDepth = 1;
var index = 1;
var isInsideSinglelineComment = false;
var isInsideMultilineComment = false;
for (; index < sourceStartsWithDestructuring.length; index += 1) {
const char = sourceStartsWithDestructuring[index];
if (isInsideSinglelineComment) {
if (char === '\n') {
isInsideSinglelineComment = false;
}
continue;
}
else if (isInsideMultilineComment) {
if (char === '*' && sourceStartsWithDestructuring[index + 1] === '/') {
isInsideMultilineComment = false;
index += 1;
}
continue;
}
if (char === openBracket) {
bracketsDepth += 1;
}
else if (char === closeBracket) {
bracketsDepth -= 1;
if (bracketsDepth === 0) {
return { endIndex: index, names };
}
}
else if (char === ':') {
names.pop();
}
else if (char === '/') {
const nextChar = sourceStartsWithDestructuring[index + 1];
if (nextChar === '/') {
isInsideSinglelineComment = true;
index += 1;
}
else if (nextChar === '*') {
isInsideMultilineComment = true;
index += 1;
}
}
else if (char in identifierStartCharacters) {
const nameIndex = parseIdentifier(sourceStartsWithDestructuring.slice(index));
if (nameIndex === 0) {
return;
}
names.push(sourceStartsWithDestructuring.slice(index, index + nameIndex));
index += nameIndex - 1;
}
}
return;
};
/**
* Parses string literal after `from` at the end of the source string.
*/
export const parseFrom = (quoteCharacter, sourceWithString) => {
var hasBackslash = false;
var index = sourceWithString.length - 1;
for (; index !== -1; index -= 1) {
const char = sourceWithString[index];
if (char === '\\') {
hasBackslash = true;
}
if (char === quoteCharacter && sourceWithString[index - 1] !== '\\') {
break;
}
}
var from = sourceWithString.slice(index + 1);
if (hasBackslash) {
from = from.replace(backslashesRegExp, stripFirstCharacter);
}
return { from, index };
};
/**
* Parses identifier from the start of the source string.
*/
export const parseIdentifier = (sourceStartsWithIdentifier) => {
if (!identifierStartCharacters[sourceStartsWithIdentifier[0]]) {
return 0;
}
for (let index = 1; index < sourceStartsWithIdentifier.length; index += 1) {
if (!identifierCharacters[sourceStartsWithIdentifier[index]]) {
return index;
}
}
return sourceStartsWithIdentifier.length;
};
/**
* Parses import/reexport attributes in `with`-part of import/reexport (like `with { type: "json" }`).
*/
export const parseWith = (startIndex, source) => {
const endIndex = source.indexOf('}', startIndex);
if (endIndex === -1) {
return;
}
const withAttributes = { __proto__: null };
const attributesSource = source.slice(startIndex, endIndex).trim();
if (attributesSource === '') {
return { endIndex, with: withAttributes };
}
const attributes = attributesSource.split(',');
for (const attribute of attributes) {
const parts = attribute.split(':');
if (parts.length !== 2) {
return { endIndex };
}
let key = parts[0].trim();
if (key[0] === "'" || key[0] === '"') {
key = trimQuotes(key);
}
if (!key) {
return { endIndex };
}
const value = trimQuotes(parts[1].trim());
if (!value || key in withAttributes) {
return { endIndex };
}
withAttributes[key] = value;
}
return { endIndex, with: withAttributes };
};
/**
* Regexp that find all backslashes.
*/
const backslashesRegExp = /\\+/g;
/**
* Hash with start characters of identifiers.
*/
const identifierStartCharacters = { __proto__: null };
for (const character of 'abcdefghijklmnopqrstuvwxyz_$') {
identifierStartCharacters[character] = true;
identifierStartCharacters[character.toUpperCase()] = true;
}
/**
* Hash with characters of identifiers.
*/
const identifierCharacters = { __proto__: null, ...identifierStartCharacters };
for (const character of '0123456789') {
identifierCharacters[character] = true;
}
/**
* Strips first character from string.
*/
const stripFirstCharacter = (someString) => someString.slice(1);
/**
* Trims single or double quotes around the string value.
* If string is not quoted, returns `undefined`.
*/
const trimQuotes = (value) => {
if (value.length < 2) {
return;
}
var firstChar = value[0];
if (firstChar !== "'" && firstChar !== '"') {
return;
}
if (firstChar !== value[value.length - 1]) {
return;
}
return value.slice(1, -1);
};