Skip to content

Instantly share code, notes, and snippets.

@nyteshade
Created December 10, 2023 07:58
Show Gist options
  • Save nyteshade/be373c9a2c2b7edee4c69ff776a36507 to your computer and use it in GitHub Desktop.
Save nyteshade/be373c9a2c2b7edee4c69ff776a36507 to your computer and use it in GitHub Desktop.
Relies on Tickers
/* eslint-disable eqeqeq */
/* eslint-disable no-new-func */
import { Count, Strings, Ticker } from './ticker';
/**
* Finds the closing token for a given opening token in a string, starting from a
* specified index.
*
* @param {string} str - The string in which to find the closing token.
* @param {number} startIndex - The index in the string from which to start the search.
* @param {string} openToken - The opening token for which to find the corresponding
* closing token.
* @param {string} closeToken - The closing token corresponding to the openToken.
* @returns {string|null} The substring between the opening and closing tokens, or
* `null` if no closing token is found.
*/
function findClosingToken(str, startIndex, openToken, closeToken) {
const depth = new Ticker(0);
const collectedString = new Strings('');
for (let i = startIndex; i < str.length; i += 1) {
collectedString.push(str[i]);
if (str[i] === openToken) {
depth.tick();
} else if (str[i] === closeToken) {
depth.decrement();
if (depth == 0) {
return collectedString.value.join('');
}
}
}
return null;
}
/**
* Extracts the constructor function from a class or function input.
*
* @param {function} input - The input function or class from which to extract the
* constructor.
* @returns {Object|null} An object containing the extracted constructor function, or
* `null` if it cannot be extracted.
*/
function extractConstructor(input) {
const classString = (typeof input === 'function' && input.toString().includes('class'))
? input.prototype.constructor.toString()
: null;
if (!classString) {
return input;
}
// Regex to match the constructor including multiline parameters
const constructorRegex = /constructor\s*\(([\s\S]*?)\)\s*{/;
const match = constructorRegex.exec(classString);
if (!match) return input;
const constructorContent = new Strings()
const position = new Count(match.index)
constructorContent.tick(findClosingToken(classString, +position, '(', ')'))
position.add(constructorContent.last.length)
constructorContent.tick(findClosingToken(classString, +position, '{', '}'))
// Encapsulate the constructor in an object
const constructorFunction = new Function(`return function ${constructorContent}`)();
return { constructor: constructorFunction };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment