Created
December 10, 2023 07:58
-
-
Save nyteshade/be373c9a2c2b7edee4c69ff776a36507 to your computer and use it in GitHub Desktop.
Relies on Tickers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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