Pick a mode. Don't worry, both are equally unforgiving.
+
Wow, still here? Are you waiting for the other player?
+
Take your time. Maybe indecision is your strategy.
+
Still deciding? It's just Hang(le)man, not life or death.
+
Is this a game or a dramatic pause competition. . .
+
Fun fact: waiting won't make you any better at this.
+
Alright, stay here forever if that's your winning move.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/2_multiplayer.js b/EC327_Hangle_COMPLETED/2_multiplayer.js
new file mode 100644
index 0000000000000000000000000000000000000000..2d82bd6f016fcab7ddbaeeb05e5c1a8ceb0af4b6
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/2_multiplayer.js
@@ -0,0 +1,29 @@
+/**
+ * Adds click event listeners to buttons to handle page redirection.
+ *
+ * This code assigns event listeners to two different buttons with IDs button1 and button2.
+ * When clicked, these buttons redirect the user to specific pages:
+ *
+ *
+ *
button 1: Redirects the user to 3_multihangman.html.
+ *
button 2: Redirects the user to 3_multihangle.html.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/2_soloplayer.js b/EC327_Hangle_COMPLETED/2_soloplayer.js
new file mode 100644
index 0000000000000000000000000000000000000000..d6a8b7d7a7476e039f4b3cb77e56a899a4a13bc8
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/2_soloplayer.js
@@ -0,0 +1,36 @@
+/**
+ * Adds click event listeners to buttons to handle page redirection.
+ *
+ * This code assigns event listeners to 3 different buttons with IDs button1, button2 and button3.
+ * When clicked, these buttons redirect the user to specific pages:
+ *
+ *
+ *
button 1: Redirects the user to 3_easymode.html.
+ *
button 2: Redirects the user to 3_medmode.html.
+ *
button 3: Redirects the user to 3_hardmode.html.
+ *
+ *
+ * @example:
+ *
+ *
+ *
+ *
+ *
+ *
+ * @event click - Triggered when either button is clicked.
+ * @return void - The assigned function does not return any value.
+ * @see window.location
+ * @see document.getElementById
+ */
+
+document.getElementById('button1').addEventListener('click', () => {
+ window.location.href = '3_easymode.html';
+});
+
+document.getElementById('button2').addEventListener('click', () => {
+ window.location.href = '3_medmode.html';
+});
+
+document.getElementById('button3').addEventListener('click', () => {
+ window.location.href = '3_hardmode.html';
+});
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/3_darkmode.js b/EC327_Hangle_COMPLETED/3_darkmode.js
new file mode 100644
index 0000000000000000000000000000000000000000..5531479d466e4bdc98afd8559f2dc2b2e1906b81
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_darkmode.js
@@ -0,0 +1,79 @@
+let darkmode = localStorage.getItem('darkmode')// initializes localStorage object and stores the object in web storage API
+const darkmode_slider = document.getElementById("darkmode-slider");
+
+/**
+ *
Enables dark mode by applying the 'darkmode' class to the document body
+ * and storing the user's preference in local storage.
+ *
+ *
This function performs the following actions:
+ *
+ *
Adds the 'darkmode' class to the `document.body`, changing the appearance of the page.
+ *
Saves the user's preference for dark mode in the browser's `localStorage`
+ * with the key 'darkmode' and value 'active'.
+ *
+ *
+ * @example:
+ * enableDarkmode(); // Activates dark mode for the page
+ *
+ * @return void - The assigned function does not return any value.
+ * @see https://www.w3schools.com/jsref/met_storage_getitem.asp
+ * @seehttps://www.youtube.com/watch?v=_gKEUYarehE
+ */
+const enableDarkmode = () =>{
+ document.body.classList.add('darkmode')
+ localStorage.setItem('darkmode', 'active')
+}
+
+
+/**
+ *
disables dark mode by applying the 'darkmode' class to the document body
+ * and storing the user's preference in local storage.
+ *
+ *
This function performs the following actions:
+ *
+ *
Adds the 'darkmode' class to the `document.body`, changing the appearance of the page.
+ *
Saves the user's preference for dark mode in the browser's `localStorage`
+ * with the key 'darkmode' and value null.
+ *
+ *
+ * @example:
+ * disableDarkmode(); // disables dark mode for the page
+ *
+ * @return void - The assigned function does not return any value.
+ * @see https://www.w3schools.com/jsref/met_storage_getitem.asp
+ * @seehttps://www.youtube.com/watch?v=_gKEUYarehE
+ */
+const disableDarkmode = () =>{
+ document.body.classList.remove('darkmode')
+ localStorage.setItem('darkmode', null)
+}
+
+
+if(darkmode ==="active") enableDarkmode();//enables darkmode
+
+/**
+ *
adds an event listener to darkmode slider to toggle the darkmode.
+ * It checks th current state of darkmode. if darkmode is not enabled it enables the darkmode
+ * and vicevesa. This all occurs when the slider changes.
+ *
+ *
This function performs the following actions:
+ *
+ *
Enables dark mode: Calls enableDarkmode if the current mode is not active.
+ *
Disables dark mode: Calls disableDarkmode if the current mode is active.
Here's everything you need to know to get started.
+
+
The goal is to guess the hidden word by selecting letters.
+
Each time you guess a letter, the game will provide feedback on your guess
+
+
+
+ Green: The letter is correct and in the correct position.
+
+
Yellow: The letter is in the word but in the wrong position.
+
Gray: The letter is not in the word.
+
+
+ Each wrong guess adds a piece to the hangman.
+
+
+
+ If you guess all the letters correctly, you win!
+
+
+
+
Challenge Mode
+
+
In Challenge Mode, letters you've guessed incorrectly won't turn gray, so you'll need to remember your guesses as you play.
+
+
+
+
+
+
+
+
+
+ ×
+
Settings
+
Make this game your own
+
+
Sound
+
+
+
+
+
Prefer a quieter experience? Toggle sound settings.
+
+
Dark Mode
+
+
+
+
+
Dark mode for a relaxed gaming experience.
+
+
+
Challenge Mode
+
+
+
+
+
Remember the letters you've already guessed wrong.
+
+
+
+
+
+
+
+
+
+
+ ×
+
Hint
+
Follow these tips to make the most of your hints
+
+
You can reveal a letter by clicking "Reveal a Letter".
+
Use "Additional Life" to reduce your penalty chances.
+
Plan your guesses strategically before using hints.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EC327_Hangle_COMPLETED/3_easymode.js b/EC327_Hangle_COMPLETED/3_easymode.js
new file mode 100644
index 0000000000000000000000000000000000000000..2e63bb224932ae1638cf26ad97f9186f881d1230
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_easymode.js
@@ -0,0 +1,948 @@
+const keyboard_container = document.querySelector("#keyboard_container");
+let currentword;
+let max_attempts = 6;
+var gameover = false;
+let wrong_attempts = 0;
+let word_length = 4;
+var spot = 0;
+let currentIndex = 1;
+let correct_word = 0;
+
+/**
+ * Initializes the Hangle game by setting up the word to guess, creating the game UI,
+ * and enabling user interaction through an on-screen keyboard and physical keyboard inputs.
+ *
+ * [Long Description]
+ * This function sets up the initial game state. It selects a random word and prepares
+ * a visual representation of the word as tiles in the game UI. It also dynamically
+ * generates an on-screen keyboard, allowing users to input guesses by clicking buttons
+ * or pressing keys on a physical keyboard. The function includes event listeners to
+ * handle typing interactions and maintains synchronization between on-screen and physical
+ * keyboard inputs.
+ *
+ * Key Steps:
+ * 1. Selects a random word and hint from a predefined list (`easy_word`).
+ * 2. Creates blank tiles corresponding to the letters of the selected word.
+ * 3. Dynamically generates an on-screen keyboard for user interaction.
+ * 4. Binds physical keyboard events to match the on-screen keyboard functionality.
+ *
+ * @global {Array} easy_word - An array of objects containing words and hints for the game.
+ * Each object has the structure: `{ word: string, hint: string }`.
+ * @global {HTMLElement} keyboard_container - The DOM element where the keyboard is rendered.
+ * @global {number} word_length - The length of the word to guess.
+ * @global {function} input - A callback function that processes user input for letter guesses.
+ * @global {function} updateRemoveBodyPartButton - Updates the initial state of controls (e.g., remove body part button).
+ *
+ * @throws {Error} Throws an error if any of the global dependencies (`easy_word`, `keyboard_container`, `input`) are undefined.
+ *
+ * @example
+ * // Basic usage of the initialize function to start the game:
+ * initialize();
+ *
+ * @see input - The function handling user guesses and game logic.
+ * @see updateRemoveBodyPartButton - The function managing the state of hangle-related controls.
+ *
+ * @see Game Development Tutorial - Great Day Designs
+ * @see Hangman Game Tutorial - Kenny Yip Coding
+ */
+
+function initialize() {
+ const getRandomWord = () => {
+ const { word, hint } = easy_word[Math.floor(Math.random() * easy_word.length)];
+ const new_hint = hint.replace(/\.$/, "");
+ currentword = word.toUpperCase();
+ // Remove automatic hint display
+ };
+
+ getRandomWord();
+ updateRemoveBodyPartButton(); // Initial button state
+
+ const tile_category = document.querySelector(".display");
+ tile_category.innerHTML = "";
+
+ // Create HangMan Space
+ for (let i = 0; i < word_length; i++) {
+ const tile = document.createElement("li");
+ tile.id = i.toString();
+ tile.classList.add("letter");
+ tile.innerText = "";
+ tile_category.appendChild(tile);
+ }
+
+
+ /// This is for typing the words in the boxes
+ const rows = [
+ "qwertyuiop".split(""),
+ "asdfghjkl".split(""),
+ [{ char: "↵", key: "enter" }, ..."zxcvbnm".split(""), { char: "⌫", key: "backspace" }],
+ ];
+
+
+
+ /// This is for typing the words in the boxes
+
+ rows.forEach((row) => {
+ const keyboard_row = document.createElement("div"); // Create a row container
+ keyboard_row.classList.add("keyboard_row");
+
+ row.forEach((item) => {
+ const button = document.createElement("button");
+
+ if (typeof item === "string") {
+ button.innerText = item.toUpperCase();
+ button.dataset.key = item;
+ } else {
+ button.innerText = item.char;
+ button.dataset.key = item.key;
+ }
+
+ button.addEventListener("click", () => {
+ input(button.dataset.key);
+ });
+
+ keyboard_row.appendChild(button);
+ });
+
+ keyboard_container.appendChild(keyboard_row);
+ });
+
+ // Typing with keys
+ document.addEventListener("keyup", (e) => {
+
+ const keyPressed = e.key.toLowerCase();
+ console.log("Key pressed:", keyPressed);
+
+ let button = document.querySelector(`button[data-key="${keyPressed}"]`);
+
+ if (!button) {
+ if (e.key === "Enter") {
+ button = document.querySelector(`button[data-key="enter"]`);
+ } else if (e.key === "Backspace") {
+ button = document.querySelector(`button[data-key="backspace"]`);
+ }
+ }
+
+ if (button) {
+ button.click();
+ } else {
+ console.log("No matching button found for:", keyPressed);
+ }
+ });
+}
+
+/**
+*
Toggles the sound setting based on the state of the sound slider (checkbox).
+* This function reads the state of the sound slider, stores it in `localStorage`,
+* and allows persistence of the user's sound preference across sessions.
+*
Key functionality:
+*
+*
If the slider is checked, sound is enabled
+*
If the slider is unchecked, sound is disabled.
+*
+*
+*
The state of the sound preference is saved in `localStorage` with the key `soundEnabled`.
+*
+* Example usage:
+* toggleSound(); // Saves the sound setting (enabled or disabled)
+* @return void - The assigned function does not return any value.
+* @since 2024-12-09
+*/
+function toggleSound() {
+ const soundEnabled = document.getElementById('sound-slider').checked;
+ localStorage.setItem('soundEnabled', soundEnabled); // Save the state
+}
+
+/**
+ * Loads the user's sound preference from `localStorage` and applies it to the sound slider.
+ *
+ * This function checks the `localStorage` for the user's saved sound preference under the key
+ * soundEnabled. If no preference is found (value is null), it defaults
+ * to enabling sound and saves this default state back to `localStorage`. The function then updates
+ * the state of the sound slider on the webpage based on the retrieved or default preference.
+ *
+ *
+ *
Retrieves Preference: Reads the soundEnabled key from `localStorage`.
+ *
Defaults to Sound ON: If no preference exists, sets soundEnabled to true.
+ *
Updates UI: Reflects the preference in the sound slider's checked state.
+ *
+ *
+ * @example:
+ * loadSoundPreference(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function loadSoundPreference() {
+ let soundEnabled = JSON.parse(localStorage.getItem('soundEnabled'));
+
+ if (soundEnabled === null) {
+ // Default to sound ON if no preference is saved
+ soundEnabled = true;
+ localStorage.setItem('soundEnabled', true);
+ }
+
+ // Set the slider and the sound state based on localStorage
+ document.getElementById('sound-slider').checked = soundEnabled;
+}
+
+// Attach the event listener for the sound slider toggle
+document.getElementById('sound-slider').addEventListener('change', toggleSound);
+
+// Load the sound preference on page load
+document.addEventListener('DOMContentLoaded', loadSoundPreference);
+
+/**
+ * Allows sound to play, grabbing the specific sound file from its path, when soundEnabled is true.
+ *
+ * This function checks the when sound is enabled. If sound is enabled the function plays the audio.
+ * If sound is not enabled it logs it to the console saying "Sound is disabled".
+ *
+ *
+ *
sound is enabled sound plays
+ *
sound is disabled sound does not play
+ *
+ *
+ * @example:
+ * playSound(audioPath); // Loads and applies the user's sound preference on page load.
+ * @param audioPath - write audio path in string
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function playSound(audioPath) {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled')); // Check the current sound state
+ if (soundEnabled) {
+ const audio = new Audio(audioPath);
+ audio.play();
+ } else {
+ console.log("Sound is disabled.");
+ }
+}
+
+/**
+ * Processes user input and updates the game state based on the key pressed.
+ *
+ * [Long Description]
+ * This function handles user input during gameplay. Depending on the key pressed,
+ * it performs one of the following actions:
+ * 1. **Backspace**: Clears the most recent unlocked tile and updates the current spot.
+ * 2. **Enter**: Initiates the process to check the current word or letter against the answer.
+ * 3. **Letter Key**: Fills the first available unlocked tile with the pressed letter.
+ *
+ * The function also ensures that no actions are performed if the game is over.
+ * It plays a click sound for every input using the `playSound` function.
+ *
+ * @param {string} keyPressed - The key that was pressed by the user. Can be one of the following:
+ * - `"backspace"`: Deletes the most recent input in an unlocked tile.
+ * - `"enter"`: Triggers the letter/word check process.
+ * - Any other string representing a letter: Fills an available tile with the letter.
+ *
+ * @global {boolean} gameover - A flag indicating whether the game has ended. Prevents further input if `true`.
+ * @global {function} playSound - A function that plays a specified sound file.
+ * @global {number} spot - Tracks the current position for the next input in the tiles.
+ * @global {number} word_length - The length of the word to guess, used to iterate over tiles.
+ *
+ * @throws {Error} Throws an error if the global variables (`gameover`, `spot`, or `word_length`) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * input("a"); // Fills the next available tile with "A".
+ * input("backspace"); // Clears the last input from an unlocked tile.
+ * input("enter"); // Initiates letter/word check logic.
+ *
+ * @see checkletter - The function called when "enter" is pressed to validate the current word/letter.
+ * @see playSound - The function used to play sound effects.
+ * @since 2024-12-09
+ *
+ * */
+const input = (keyPressed) => {
+ if (gameover) return;
+ playSound('sounds/click.wav');
+ if (keyPressed == "backspace") {
+
+ for (let i=spot-1; i>=0; i--) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock) {
+ currtile.innerText = "";
+ spot = i;
+ break;
+ }
+
+ }
+ }
+
+ else if (keyPressed == "enter") {
+ checkletter();
+
+
+ }
+
+ else {
+ for (let i = 0; i < word_length; i++) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock && currtile.innerText === "") {
+ currtile.innerText = keyPressed.toUpperCase();
+ spot = i + 1;
+ break;
+ }
+ }
+ }
+
+}
+
+/**
+ * Validates the user's guess by comparing it with the correct word and updates the game state accordingly.
+ *
+ * [Long Description]
+ * This function checks whether all the tiles have been filled with letters before validating the guess.
+ * If any tile is empty, it prompts the user to fill all spots. If the tiles are filled, it evaluates each
+ * letter against the target word (`currentword`) and updates the game state:
+ *
+ * 1. Correct guesses (letters in the correct position) are marked with the "right" class.
+ * 2. Incorrectly positioned but valid letters are marked with the "there" class.
+ * 3. Invalid letters (not in the word) are marked with the "wrong" class.
+ *
+ * Additionally, it tracks the number of incorrect guesses, updates the hangman display, and manages
+ * the game's end state by calling `checkgameover`. The keyboard buttons are dynamically updated to
+ * reflect the accuracy of the user's guesses.
+ *
+ * @global {string} currentword - The word the player is trying to guess.
+ * @global {number} correct_word - The count of correctly guessed letters in the correct positions.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of allowed wrong guesses before game over.
+ * @global {function} updatehangman - Updates the hangman figure based on incorrect attempts.
+ * @global {function} updateRemoveBodyPartButton - Manages the state of the "remove body part" button.
+ * @global {function} resetboard - Resets the tile board for the next round.
+ * @global {function} checkgameover - Checks if the game is over due to winning or exceeding maximum attempts.
+ *
+ * @throws {Error} Throws an error if any required global variables (`currentword`, `word_length`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * checkletter();
+ * // Output:
+ * // - Updates the tile and keyboard button states based on the user's guess.
+ * // - Logs incorrect attempts or success status to the console.
+ *
+ * @note This logic was developed with assistance from ChatGPT to ensure accuracy and clarity.
+ *
+ * @see updatehangman - Handles the visual display of the hangman figure.
+ * @see checkgameover - Manages the game's end state based on current progress.
+ *
+ *
+ */
+function checkletter() {
+
+ let spotsfilled = true;
+
+ for (let i =0; i {
+ currtile.classList.add("bounce");
+
+ // Remove the animation class after it ends
+ currtile.addEventListener("animationend", () => {
+ currtile.classList.remove("bounce");
+ });
+ }, i * 150); // Stagger delay by 150ms per tile
+ }
+}
+
+/**
+ * Checks if the game is over and handles end-of-game actions accordingly.
+ *
+ * [Long Description]
+ * This function determines whether the game has ended based on the player's most recent guess.
+ * If the guess was correct and the game is won, it sets the game state to "over," displays a
+ * winning message, animates the tiles, plays a victory sound, and launches confetti. If the
+ * number of incorrect attempts reaches or exceeds the maximum allowed, it ends the game,
+ * displays a losing message, and plays a failure sound.
+ *
+ * @param {boolean} incorrectGuess - Indicates whether the last guess was incorrect.
+ * If `true`, the game checks if the maximum attempts have been exceeded.
+ *
+ * @global {boolean} gameover - A flag that indicates if the game has ended. This is set to `true` when the game is over.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of incorrect guesses allowed before the game ends.
+ * @global {string} currentword - The word the player was trying to guess, used in the losing message.
+ * @global {function} animateTiles - Animates the tiles when the game is won.
+ * @global {function} displayMessage - Displays a message to the player indicating the game's outcome.
+ * @global {function} playSound - Plays a sound file corresponding to the game's outcome (win or lose).
+ *
+ * @throws {Error} Throws an error if any required global variables (`gameover`, `wrong_attempts`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * checkgameover(false); // Handles the "win" scenario if no incorrect guess.
+ * checkgameover(true); // Checks if the player has exceeded the maximum allowed incorrect attempts.
+ *
+ * @see animateTiles - For handling tile animations upon winning.
+ * @see displayMessage - For managing game status messages.
+ * @see confetti - Used to trigger confetti effects for celebrations.
+ * @since 2024-12-09
+ */
+function checkgameover(incorrectGuess) {
+
+ if (!incorrectGuess) {
+ gameover = true;
+ console.log("good!")
+ displayMessage("You Win!", true, true)
+ animateTiles();
+ confetti({
+ particleCount: 150, // Number of confetti pieces
+ spread: 70, // Spread angle of confetti
+ origin: { y: 0.6 }, // Confetti drop point
+ colors: ['#bb0000', '#ffffff', '#00bb00'] // Custom colors
+ });
+ playSound('sounds/win.wav');
+ return;
+ }
+
+ if (wrong_attempts >= max_attempts) {
+ gameover = true;
+ console.log("bad");
+ displayMessage(`Game Over! The word was: ${currentword}`);
+ playSound('sounds/lose.wav');
+ return;
+ }
+ }
+
+
+
+/**
+ * Displays a message overlay on the screen with optional reset and home buttons.
+ *
+ * [Long Description]
+ * This function creates and displays an overlay message on the screen. It includes a customizable
+ * message and optional buttons for resetting the game and navigating to the home page. The overlay
+ * is styled dynamically based on whether the game was won or lost. The "Play Again" button reloads
+ * the page to restart the game, while the "Go Home" button redirects to the main page.
+ *
+ * A fade-in animation is triggered after the overlay is appended to the DOM for a smooth visual effect.
+ *
+ * @param {string} message - The message to display on the overlay.
+ * @param {boolean} [showResetButton=true] - Determines whether the "Play Again" button is displayed.
+ * @param {boolean} [isWin=false] - Specifies whether the game was won, which affects the overlay's style.
+ *
+ * @example
+ * // Display a winning message with reset and home buttons:
+ * displayMessage("You Win!", true, true);
+ *
+ * // Display a losing message without a reset button:
+ * displayMessage("Game Over! The word was: CAT", false);
+ *
+ * @see location.reload - Used to reload the page for restarting the game.
+ * @see window.location.href - Redirects to the specified home page URL.
+ * @since 2024-12-09
+ */
+ function displayMessage(message, showResetButton = true, isWin = false) {
+ // Create the black overlay
+ const overlay = document.createElement("div");
+ overlay.classList.add(isWin ? "overlay-win" : "overlay");
+
+ // Create the message container
+ const messageContainer = document.createElement("div");
+ messageContainer.classList.add("message-container");
+
+ // Add the message text
+ const messageText = document.createElement("p");
+ messageText.classList.add("message-text");
+ messageText.innerText = message;
+ messageContainer.appendChild(messageText);
+
+ // Add the reset button
+ if (showResetButton) {
+ const resetButton = document.createElement("button");
+ resetButton.classList.add("reset-button");
+ resetButton.innerText = "Play Again";
+ resetButton.addEventListener("click", () => {
+ location.reload(); // Reload the page to restart the game
+ });
+ messageContainer.appendChild(resetButton);
+ }
+
+ // Add the home button
+ const homeButton = document.createElement("button");
+ homeButton.classList.add("home-button");
+ homeButton.innerText = "Go Home";
+ homeButton.addEventListener("click", () => {
+ window.location.href = "1_mainpage.html"; // Redirect to home page
+ });
+ messageContainer.appendChild(homeButton);
+
+ // Append the container to the overlay
+ overlay.appendChild(messageContainer);
+
+ document.body.appendChild(overlay);
+
+ // Trigger fade-in animation
+ setTimeout(() => {
+ overlay.classList.add("fade-in");
+ }, 10);
+}
+
+
+
+/**
+ * Resets the letter tiles on the board for the next round of the game.
+ *
+ * [Long Description]
+ * This function clears the text and resets the styles for all letter tiles that
+ * are not marked as "right" (correctly guessed letters). It ensures that only
+ * unlocked tiles (tiles without the "right" class) are cleared, while maintaining
+ * the state of correctly guessed tiles. Additionally, it removes the "there"
+ * class from all tiles, resetting their visual state.
+ *
+ * Key Features:
+ * - Clears the `innerText` of tiles that are not locked as correct.
+ * - Removes the "there" class from all tiles.
+ * - Resets the `spot` tracker to 0, indicating the starting position for input in the next round.
+ *
+ * @global {number} word_length - The length of the word being guessed, used to determine the number of tiles.
+ * @global {number} spot - Tracks the current position for the next input. This is reset to 0 by this function.
+ *
+ * @example
+ * // Reset the board for a new round:
+ * resetboard();
+ *
+ * @see spot - Resets the spot tracker for the next round of inputs.
+ * @since 2024-12-09
+ */
+function resetboard() {
+ for (let i = 0; i < word_length; i++) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.classList.contains("right")) {
+ currtile.innerText = ""; // Clear the tile's text
+ currtile.classList.remove("there"); // Remove the "there" class
+ }
+ }
+
+ spot = 0; // Reset the spot tracker to the starting position
+}
+
+/**
+ * Updates the hangman figure by revealing the next body part image.
+ *
+ *
This function manages the visual representation of incorrect guesses by progressively
+ * revealing parts of the hangman figure. Each time an incorrect guess is made, the opacity
+ * of the next body part image in the sequence is set to 1, making it visible. The function
+ * keeps track of the current index of the body parts and ensures that it does not exceed the
+ * total number of body parts available.
+ *
+ *
+ *
Increment Index: The function increments the `currentIndex` to keep track
+ * of which body part should be revealed next.
+ *
Reveal Body Part: The next body part image in the sequence is revealed
+ * by changing its opacity.
+ *
Boundary Check: Ensures that no more body parts are revealed after the
+ * last image in the sequence.
+ *
+ *
+ * @global {NodeList} images - A collection of elements representing the hangman body parts.
+ * These elements are queried from the DOM using the `.body-part` class.
+ * @global {number} currentIndex - Tracks the current body part being revealed. Incremented with
+ * each incorrect guess.
+ *
+ * @throws {Error} Throws an error if the `images` NodeList is undefined or `currentIndex` exceeds its length.
+ *
+ * @example
+ * // Example usage:
+ * updatehangman();
+ * // Output:
+ * // - Reveals the next body part in the sequence by making it visible.
+ *
+ * @since 2024-12-09
+ */
+function updatehangman() {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex < images.length) {
+ images[currentIndex].style.opacity = 1; // Show the next image
+ currentIndex++;
+ }
+}
+/**
+ * Redirects the user to the main page when the "Home" link is clicked.
+ *
+ *
This function listens for a click event on the element with the ID `Home-link`. Upon clicking,
+ * the user is redirected to the "1_mainpage.html" page. It is primarily used for navigation purposes
+ * within the application.
+* Assigns the initialize and loadDarkModePreference function to the window.onload event.
+* This ensures the initialize and loadDarkModePreference function executes automatically when the webpage finishes loading.
+*
+* The window.onload event is triggered after all assets
+* (e.g., HTML, CSS, JavaScript, images) are fully loaded.
+* By using this assignment, the initialize and loadDarkModePreference function initializes
+* or performs actions required after the page loads.
+* @return void - The assigned function does not return any value.
+* @see {@link window.onload}
+* @since 2024-12-09
+*/
+window.onload = function() {
+ initialize();
+ loadDarkModePreference(); // Load dark mode state when the page loads
+};
+
+/**
+ *
+ * toggles darkmode on and off and saves the data into {@code localStorage} object, which is
+ * then stored in the web storage API
+ *
+ *
+ * This function toggles the darkmode class on the {@code document.body} element,
+ * which typically applies or removes dark mode styling. It also updates the {@code localStorage}
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ * @example:
+ * toggleDarkMode(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see document.body
+ * @since 2024-12-09
+ */
+function toggleDarkMode() {
+ const darkModeEnabled = document.body.classList.toggle('darkmode');
+ localStorage.setItem('darkModeEnabled', darkModeEnabled); // Save the state
+}
+
+/**
+ * Toggles the dark mode on or off and saves the current state in localStorage.
+ *
+ * This function toggles the darkmode class on the document.body element,
+ * which typically applies or removes dark mode styling. It also updates the localStorage
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ *
+ * @example usage:
+ * toggleDarkMode(); // Toggles dark mode and saves the state
+ *
+ * @return void - This function does not return any value.
+ * @see localStorage
+ * @see document.body
+ */
+function loadDarkModePreference() {
+ const darkModeEnabled = JSON.parse(localStorage.getItem('darkModeEnabled'));
+
+ if (darkModeEnabled) {
+ // Apply dark mode if it was enabled
+ document.body.classList.add('darkmode');
+ document.getElementById('darkmode-slider').checked = true; // Set the slider to ON
+ } else {
+ // Ensure light mode if dark mode was not enabled
+ document.body.classList.remove('darkmode');
+ document.getElementById('darkmode-slider').checked = false; // Set the slider to OFF
+ }
+}
+
+// Attach the event listener for the dark mode slider toggle
+document.getElementById('darkmode-slider').addEventListener('change', toggleDarkMode);
+
+// Load the dark mode preference on page load
+document.addEventListener('DOMContentLoaded', loadDarkModePreference);
+
+
+const challengeSlider = document.getElementById("challenge-slider");
+const keyboardContainer = document.getElementById("keyboard_container");
+/**
+ *
+ * Toggles the "grey-mode" class on the keyboard container based on the challenge slider's state.
+ *
+ *
+ *
+ *
Checked: Enables "grey-mode" on the keyboard container.
+ *
Unchecked: Disables "grey-mode" and restores default styling.
+ *
+ *
+ * @event change - Triggered when the state of the challenge slider changes (checked/unchecked).
+ *
+ * @param {Event} event - The event triggered when the slider's state changes.
+ *
+ * @global {HTMLElement} challengeSlider - The DOM element representing the challenge slider.
+ * @global {HTMLElement} keyboardContainer - The DOM element containing the keyboard.
+ *
+ * @example
+ * // Example usage:
+ * challengeSlider.addEventListener("change", () => {
+ * if (challengeSlider.checked) {
+ * keyboardContainer.classList.add("grey-mode");
+ * } else {
+ * keyboardContainer.classList.remove("grey-mode");
+ * }
+ * });
+ *
+ * @return {void} - This function does not return a value.
+ * @see keyboardContainer - The target element for the "grey-mode" class.
+ * @see challengeSlider - The slider controlling the challenge mode.
+ * @since 2024-12-09
+ */
+challengeSlider.addEventListener("change", (event) => {
+ if (challengeSlider.checked) {
+ keyboardContainer.classList.add("grey-mode"); // Enable challenge mode
+ } else {
+ keyboardContainer.classList.remove("grey-mode"); // Disable challenge mode
+ }
+});
+
+
+/**
+ * Handles the click event of the "remove-body-part" button to remove a body part image.
+ *
+ *
This function is triggered when the user clicks the "remove-body-part" button. It reduces the visibility
+ * of the most recent body part image (by setting its opacity to 0) and decreases the `wrong_attempts` count.
+ * The button is then disabled and visually updated to indicate it's no longer clickable. If no wrong attempts
+ * are left, the button is hidden.
+ *
+ * @function
+ * @param none
+ * @return void
+ * @see wrong_attempts,currentIndex
+ * @since 2024-12-09
+ */
+document.getElementById('remove-body-part').addEventListener('click', function () {
+ if (wrong_attempts > 0) {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex > 1) {
+ currentIndex--;
+ images[currentIndex].style.opacity = 0;
+ wrong_attempts = Math.max(0, wrong_attempts - 1);
+ console.log(`Body part removed. Remaining wrong attempts: ${max_attempts - wrong_attempts}`);
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+ } else {
+ this.style.display = 'none';
+ }
+});
+
+/**
+ * Adds an event listener to the "reveal-letter" button to reveal a random unrevealed letter from the current word.
+ *
This functionality helps the user by revealing a letter from the target word when the button is clicked.
+ * The revealed letter is displayed in its corresponding tile on the interface and marked as "right."
+ * Additionally, the associated keyboard key is highlighted. Once all letters are revealed,
+ * the game checks for completion, and the "reveal-letter" button is disabled to prevent further use.
+ *
+ *
Revealing a Letter: A random unrevealed letter is selected, displayed on the game tile, and marked as correct.
+ *
Keyboard Highlight: The corresponding keyboard key is updated to indicate it has been used correctly.
+ *
Button State: The "reveal-letter" button is disabled after a letter is revealed to prevent additional usage.
+ *
Game Completion: If all letters are revealed, the game checks for completion.
+ *
Error Handling: If all letters have already been revealed, a message is logged to the console.
+ *
+ *
+ * @function
+ * @since 2024-12-09
+ */
+document.getElementById('reveal-letter').addEventListener('click', function () {
+ const randomIndex = getRandomUnrevealedLetter();
+
+ if (randomIndex !== null) {
+ const currTile = document.getElementById(randomIndex.toString());
+ currTile.innerText = currentword[randomIndex];
+ currTile.classList.add("right");
+ currTile.dataset.lock = "true";
+ const keyButton = document.querySelector(`button[data-key="${currentword[randomIndex].toLowerCase()}"]`);
+ if (keyButton) {
+ keyButton.classList.add("right");
+ }
+ correct_word++;
+ if (correct_word === word_length) {
+ checkgameover(false);
+ }
+ } else {
+ console.log("All letters have already been revealed.");
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Retrieves the index of a random unrevealed letter from the current word.
+ *
+ *
This function identifies all the tiles representing unrevealed letters and randomly selects
+ * one of them. If all letters have been revealed, it returns `null`. The unrevealed letters are
+ * determined by checking the absence of a `lock` attribute in the dataset of each tile element.
+ *
+ * @function
+ * @param none
+ * @return {number|null} - The index of a random unrevealed letter, or `null` if no letters are left to reveal.
+ * @see word_length
+ * @since 2024-12-09
+ *
+ */
+function getRandomUnrevealedLetter() {
+ const unrevealedIndices = [];
+ for (let i = 0; i < word_length; i++) {
+ const currTile = document.getElementById(i.toString());
+ if (!currTile.dataset.lock) {
+ unrevealedIndices.push(i);
+ }
+ }
+ if (unrevealedIndices.length > 0) {
+ const randomIndex = Math.floor(Math.random() * unrevealedIndices.length);
+ return unrevealedIndices[randomIndex];
+ }
+ return null;
+}
+
+/**
+ * Displays a hint for the current word when the "show-clue" button is clicked.
+ *
+ *
This method retrieves a hint corresponding to the current word from the `easy_word` array
+ * and displays it in the designated clue area. After displaying the hint, the "show-clue" button
+ * is disabled to prevent multiple uses.
+ *
+ * @function
+ * @return void
+ * @throws Error if the current word is not found in the `easy_word` array.
+ * @see easy_word
+ * @since 2024-12-09
+ */
+document.getElementById('show-clue').addEventListener('click', function() {
+ const clueContent = document.getElementById('clue-content');
+ const hint = easy_word.find(item => item.word.toUpperCase() === currentword).hint;
+ clueContent.textContent = hint.replace(/\.$/, "");
+ clueContent.style.display = 'block';
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Updates the visibility of the "Remove Body Part" button based on the number of wrong attempts.
+ *
+ *
This function checks the value of `wrong_attempts` and adjusts the display style of the
+ * "remove-body-part" button accordingly. The button becomes visible when there is at least one wrong
+ * attempt and is hidden otherwise. This functionality ensures that the button is only accessible
+ * when it is relevant to the game state.
+ *
+ * @function
+ * @return void
+ * @since 2024-12-09
+ */
+function updateRemoveBodyPartButton() {
+ const removeBodyPartButton = document.getElementById('remove-body-part');
+ if (wrong_attempts > 0) {
+ removeBodyPartButton.style.display = 'inline-block';
+ } else {
+ removeBodyPartButton.style.display = 'none';
+ }
+}
+
+module.exports = {
+ initialize,
+ input,
+ checkletter,
+ resetboard,
+ checkgameover,
+ updatehangman,
+};
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/3_easywordbank.js b/EC327_Hangle_COMPLETED/3_easywordbank.js
new file mode 100644
index 0000000000000000000000000000000000000000..bc8436974a966ba03b715d70c52924426a078c9e
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_easywordbank.js
@@ -0,0 +1,94 @@
+const easy_word = [
+ { word: "book", hint: "Often found on a shelf, it's full of knowledge or stories." },
+ { word: "coin", hint: "It's small, round, and jingles in your pocket." },
+ { word: "moon", hint: "It has phases and lights up the night." },
+ { word: "love", hint: "Something you feel but cannot hold." },
+ { word: "rain", hint: "It makes the ground wet and feeds the plants." },
+ { word: "lamp", hint: "A companion to darkness, it glows softly." },
+ { word: "fish", hint: "It swims but has no feet or hands." },
+ { word: "tree", hint: "It grows tall, stands still, and has rings inside." },
+ { word: "star", hint: "A tiny speck in the sky that shines." },
+ { word: "time", hint: "You can't see it, but it keeps everything moving." },
+ { word: "game", hint: "Played for fun, but sometimes for competition too." },
+ { word: "wind", hint: "It moves but cannot be seen." },
+ { word: "fire", hint: "It's warm, bright, and devours what it touches." },
+ { word: "milk", hint: "A white drink that comes from an animal." },
+ { word: "gold", hint: "A shiny metal that's always in demand." },
+ { word: "rock", hint: "Solid, silent, and has been around forever." },
+ { word: "lake", hint: "A resting place for water, surrounded by land." },
+ { word: "desk", hint: "Where work gets done, or at least tried." },
+ { word: "door", hint: "It swings or slides to let you in or out." },
+ { word: "snow", hint: "It's cold, white, and falls quietly." },
+ { word: "bird", hint: "It sings but does not speak." },
+ { word: "frog", hint: "It hops and often hides near water." },
+ { word: "wave", hint: "It's both in the ocean and in a friendly greeting." },
+ { word: "home", hint: "A place where your heart feels safe." },
+ { word: "cake", hint: "It's sweet, layered, and often has candles." },
+ { word: "boat", hint: "It floats but cannot swim." },
+ { word: "song", hint: "A story told in notes and rhythm." },
+ { word: "nest", hint: "Built high or low, it's a safe place for new life." },
+ { word: "belt", hint: "Keeps things together but goes unnoticed." },
+ { word: "ring", hint: "A circle that holds great significance." },
+ { word: "dust", hint: "It's tiny and always finds its way back." },
+ { word: "veil", hint: "It hides but doesn't fully conceal." },
+ { word: "bark", hint: "It's tough on the outside but protects what's inside." },
+ { word: "gift", hint: "It's given, not taken, and brings a smile." },
+ { word: "king", hint: "Rules without a weapon, leads without a map." },
+ { word: "pond", hint: "A mirror for the sky, still and shallow." },
+ { word: "salt", hint: "It enhances but doesn't overpower." },
+ { word: "path", hint: "It guides, but you must choose to follow." },
+ { word: "rope", hint: "Twisted strands that hold things together." },
+ { word: "film", hint: "It tells stories without turning a page." },
+ { word: "echo", hint: "It's your voice, but from somewhere else." },
+ { word: "leaf", hint: "It's green in life but brown in death." },
+ { word: "dusk", hint: "It signals the end of a bright day." },
+ { word: "seed", hint: "It holds potential for something great." },
+ { word: "jade", hint: "A green gem that's smooth and cool." },
+ { word: "pear", hint: "A fruit with curves and a sweet heart." },
+ { word: "arch", hint: "A curve that holds weight or marks a path." },
+ { word: "grid", hint: "A pattern of lines crossing each other." },
+ { word: "band", hint: "It holds together or plays together." },
+ { word: "vest", hint: "A garment that keeps your core warm." },
+ { word: "toad", hint: "A warty friend of ponds and marshes." },
+ { word: "clay", hint: "Soft and moldable, it hardens with fire." },
+ { word: "rice", hint: "A staple food that's small but filling." },
+ { word: "pear", hint: "A fruit that's neither apple nor orange." },
+ { word: "drum", hint: "It makes music with just a beat." },
+ { word: "wing", hint: "It helps some to fly and others to dream." },
+ { word: "nest", hint: "Where feathers and eggs come together." },
+ { word: "silk", hint: "Soft as a whisper, spun by a tiny creature." },
+ { word: "lion", hint: "It roars but doesn't purr." },
+ { word: "coal", hint: "It fuels fire but turns to ash." },
+ { word: "barn", hint: "A shelter for the quiet workers of the farm." },
+ { word: "rope", hint: "It's long, strong, and helps you climb." },
+ { word: "bead", hint: "Small and colorful, strung together with care." },
+ { word: "mist", hint: "A soft, wet veil for the morning." },
+ { word: "iron", hint: "Hard, strong, and a tool of the past." },
+ { word: "reef", hint: "A home under the sea, teeming with life." },
+ { word: "veil", hint: "A cover that's both seen and unseen." },
+ { word: "lime", hint: "A citrus fruit that adds zest to life." },
+ { word: "yarn", hint: "It tells a tale or weaves a fabric." },
+ { word: "glow", hint: "A soft light that warms the dark." },
+ { word: "beam", hint: "A ray of light or a sturdy support." },
+ { word: "snow", hint: "White and silent, it blankets the world." },
+ { word: "kite", hint: "It dances with the wind but needs a string." },
+ { word: "mint", hint: "Fresh, cool, and often green." },
+ { word: "wave", hint: "It rolls in endlessly, greeting the shore." },
+ { word: "rose", hint: "Beautiful and fragrant, but watch for thorns." },
+ { word: "grid", hint: "A network of lines that organizes." },
+ { word: "bell", hint: "It rings to mark time or call attention." },
+ { word: "dove", hint: "A bird of peace, white and serene." },
+ { word: "soap", hint: "It cleans but doesn't stay clean itself." },
+ { word: "jade", hint: "Precious and green, a stone of the east." },
+ { word: "rust", hint: "The color of decay on metal." },
+ { word: "wave", hint: "It crashes but never breaks completely." },
+ { word: "lamp", hint: "It brightens the corner where it stands." },
+ { word: "vine", hint: "It climbs but stays rooted." },
+ { word: "maze", hint: "A path that's not always straightforward." },
+ { word: "plum", hint: "Sweet, round, and often purple." },
+ { word: "twig", hint: "A small branch, light but strong." },
+ { word: "flax", hint: "A plant that gives both fiber and oil." },
+ { word: "fern", hint: "A green plant with feathery fronds." },
+ { word: "knit", hint: "To loop yarn into fabric." },
+ { word: "bark", hint: "It's rough and protects the tree." }
+];
diff --git a/EC327_Hangle_COMPLETED/3_hardmode.css b/EC327_Hangle_COMPLETED/3_hardmode.css
new file mode 100644
index 0000000000000000000000000000000000000000..5e9d09e5ca07cfdbd8527437e323c68c820b6567
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_hardmode.css
@@ -0,0 +1,798 @@
+:root{
+ --backgroundbody-color: #f0f0f0;
+ --body-color: #333;
+ --backgroundnavbar-color: #ffffff;
+ --border-bottom: #ddd;
+ --navitem-color: black;
+ --backgroundmodal-color:black;
+ --backgroundmodalcontent-color: white;
+ --closebutton-color: black;
+ --backgroundbox-color: white;
+ --borderboxdisplayeletter-color: #d3d3d3;
+ --backgroundboxdisplayeletter-color: white;
+ --borderboxdisplayright-color:#7AA96B;
+ --backgroundboxdisplayright-color: #7AA96B;
+ --boxdisplayright-color: white;
+ --borderboxdisplaythere-color: #C3B671;
+ --backgroundboxdisplaythere-color: #C3B671;
+ --backgroundkeyboardrow-color:rgb(215, 215, 215);
+ --keyboardrow-color:rgb(33, 33, 33);
+ --modalcontentletter-color: black;
+
+
+}
+.darkmode{
+
+ --backgroundbody-color: #202020;
+ --body-color: #333;
+ --backgroundnavbar-color: #656565;
+ --border-bottom: #434343;
+ --navitem-color: rgb(255, 255, 255);
+ --backgroundmodal-color:black;
+ --backgroundmodalcontent-color: rgb(64, 64, 64);
+ --closebutton-color: black;
+ --backgroundbox-color: rgb(98, 98, 98);
+ --borderboxdisplayeletter-color: #202020;
+ --backgroundboxdisplayeletter-color: rgb(98, 98, 98);
+ --borderboxdisplayright-color:#7AA96B;
+ --backgroundboxdisplayright-color: #7AA96B;
+ --boxdisplayright-color: white;
+ --borderboxdisplaythere-color: #C3B671;
+ --backgroundboxdisplaythere-color: #C3B671;
+ --backgroundkeyboardrow-color:rgb(62, 62, 62);
+ --keyboardrow-color:rgb(198, 198, 198);
+ --letter-color: rgb(255, 255, 255);
+ --modalcontentletter-color: white;
+}
+
+body {
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ background-color: var(--backgroundbody-color);
+ color: var(--body-color);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-around;
+ height: 100vh;
+}
+
+.navbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10px 20px;
+ background-color: var(--backgroundnavbar-color);
+ border-bottom: 1px solid var(--border-bottom);
+ box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-right {
+ display: flex;
+ align-items: center;
+ gap: 30px;
+}
+
+.nav-item {
+ text-decoration: none;
+ color: var(--navitem-color);
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: color 0.3s ease;
+}
+
+
+/* Modal Styling */
+.modal {
+ display: none; /* Hidden by default */
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: var(--backgroundmodal-color); /* Semi-transparent black background */
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+}
+
+.modal.active {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.modal-content {
+ background-color: var(--backgroundmodalcontent-color);
+ padding: 20px 60px;
+ border-radius: 10px;
+ width: 50%;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
+ animation: fadeIn 0.3s ease;
+ color: var(--modalcontentletter-color);
+ text-align: center;
+ position: relative;
+ width: 35%;
+ max-width: 500px;
+ height: auto;
+ padding: 5px 30px;
+ border-radius: 12px;
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
+ background-color: var( --backgroundnavbar-color);
+}
+
+.modal #status {
+ color: var(--modalcontentletter-color);
+}
+
+
+h2 {
+ font-family: 'Georgia', serif; /* Georgia font with serif fallback */
+ font-weight: 1000; /* Bold weight */
+ font-size: 30px; /* Adjust size as needed */
+ color: var( --letter-color); /* Text color */
+ line-height: 1; /* Adjust spacing between lines if multiline */
+ text-align: left; /* Optional: Center the text */
+ margin-bottom: 5px;
+}
+
+p {
+ margin-top: 8px;
+ font-weight: 500;
+ font-family: 'Georgia', serif; /* Georgia font with serif fallback */
+ font-size: 20px; /* Adjust size as needed */
+ color: var( --letter-color); /* Text color */
+ text-align: left; /* Optional: Center the text */
+}
+
+ul {
+ text-align: left; /* Align text to the left */
+ list-style: disc; /* Use standard bullet points */
+ padding-left: 20px; /* Add space for proper bullet alignment */
+ margin: 10px 0; /* Add spacing around the list */
+ font-family: 'Georgia', serif; /* Match font style */
+ font-size: 18px; /* Match font size to the paragraph */
+ line-height: 1.5; /* Add spacing between list items */
+ margin-bottom: 20px;
+}
+
+ul li {
+ margin-bottom: 8px; /* Add spacing between bullet points */
+}
+
+.close-button {
+ position: absolute;
+ top: 10px;
+ right: 15px; /* Adjust as needed to position horizontally */
+ font-size: 24px;
+ font-weight: bold;
+ color: var(--closebutton-color);
+ cursor: pointer;
+}
+.close-button:hover {
+ color: red;
+}
+
+/* Modal Fade-In Animation */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: scale(0.9);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+/* hints */
+#hint-content {
+ margin: 10px 0;
+ font-weight: bold;
+ color: var(--modalcontentletter-color);
+ text-align: center;
+}
+
+#clue-content {
+ margin: 15px 0;
+ font-weight: bold;
+ color: var(--modalcontentletter-color);
+ text-align: center;
+ padding: 10px;
+ background-color: rgba(0, 0, 0, 0.05);
+ border-radius: 5px;
+}
+
+.hint-buttons-container {
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ margin-bottom: 20px;
+}
+
+.hint-button {
+ font-family: 'Georgia', serif;
+ font-weight: 500;
+ padding: 10px 20px;
+ background-color: white;
+ border: 2px solid black;
+ border-radius: 5px;
+ cursor: pointer;
+ font-size: 16px;
+ width: 180px;
+ box-sizing: border-box;
+}
+
+.hint-button:hover {
+ background-color: black;
+ color: white;
+}
+
+.hint-button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ background-color: #f0f0f0;
+ color: #666;
+ border-color: #666;
+}
+
+#remove-body-part {
+ display: block;
+ margin: 3px auto 0;
+}
+
+/*settings */
+
+#settings-modal ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+
+#settings-modal ul li {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 15px;
+ line-height: 1.5;
+}
+
+#settings-modal .sound-slider-container,
+#settings-modal .darkmode-slider-container,
+#settings-modal .challenge-slider-container {
+ margin: 0; /* Remove margin to prevent misalignment */
+ padding: 0; /* Remove padding to prevent misalignment */
+}
+
+.sound-slider,
+.darkmode-slider,
+.challenge-slider {
+ width: 60px; /* Adjust width for consistent sizing */
+ height: 34px; /* Adjust height for consistent sizing */
+ transform: translateY(-1px);
+}
+
+#subtitle {
+ font-size: 14px;
+ margin-top: -15px;
+ margin-bottom: 15px;
+}
+
+/* guide */
+/* Align the color-rules with the guide title */
+#color-rules {
+ font-size: 16px;
+ list-style: none; /* Remove bullet points */
+ padding: 0; /* Remove padding */
+ margin-left: -20px; /* Align with parent content */
+ margin-top: 10px; /* Add some space between the parent list and color rules */
+}
+
+
+.guide-image {
+ display: block;
+ width: 300px;
+ height: auto;
+ margin: 15px auto; /* Center the image horizontally */
+
+}
+
+#text-rules {
+ list-style: none;
+ margin-left: -20px;
+}
+
+.box {
+ background-color: var(--backgroundbox-color);
+ width: auto;
+ height: 350px;
+ padding: 60px 40px;
+ box-sizing: border-box;
+ text-align: center;
+ border-radius: 10px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ font-size: 18px;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 60px;
+}
+
+
+#hangman-container {
+ position: relative; /* Position relative for child positioning */
+ width: 300px; /* Set a fixed width */
+ height: 450px; /* Set a fixed height */
+ display: flex; /* Allow for centering the child parts */
+ align-items: center; /* Vertically center */
+ justify-content: center; /* Horizontally center */
+ align-items: center;
+
+}
+
+/* Style for hangman body parts */
+.body-part {
+ position: absolute; /* Absolute positioning inside relative parent */
+ opacity: 0; /* Hidden by default */
+ transition: opacity 0.15s ease-in; /* Fade in effect */
+}
+
+/* Specific styles for each body part */
+#head {
+ width: 17%; /* Proportional to container */
+ height: auto;
+ top: 38%; /* Adjust to fit inside the container */
+ left: 55%; /* Center horizontally */
+}
+
+#body {
+ width: 40%; /* Smaller portion of the container */
+ height: auto;
+ top: 45%;
+ left: 43%;
+}
+
+#rarm {
+ width: 12%;
+ height: auto;
+ top: 50%;
+ left: 62%;
+}
+
+#larm {
+ width: 12%;
+ height: auto;
+ top: 50%;
+ left: 52%;
+}
+
+#rleg {
+ width: 12%;
+ height: auto;
+ top: 67.5%;
+ left: 52%;
+}
+
+#lleg {
+ width: 12%;
+ height: auto;
+ top: 67.5%;
+ left: 62%;
+}
+
+/* Ensure the initial empty part of the hangman is visible */
+#empty {
+ display: block;
+ width: 100%;
+ height: auto;
+}
+
+.box .display {
+ display: flex;
+ gap: 10px;
+ list-style: none;
+ align-items: center;
+ justify-content: center;
+}
+
+.box .display .letter {
+ border: 2px solid var(--borderboxdisplayeletter-color);
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--backgroundboxdisplayeletter-color);
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ font-size: 24px;
+ color: var(--letter-color);
+ text-transform: uppercase;
+ font-weight: 900;
+}
+
+.box .display .right {
+ border: 2px solid var(--borderboxdisplayright-color);
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--backgroundboxdisplayright-color);
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ color: var(--boxdisplayright-color);
+ font-size: 24px;
+ text-transform: uppercase;
+ font-weight: 900;
+}
+
+.box .display .there {
+ border: 2px solid var(--borderboxdisplaythere-color);
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color:var(--backgroundboxdisplaythere-color);
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ color:var(--boxdisplayright-color);
+ font-size: 24px;
+ text-transform: uppercase;
+ font-weight: 900;
+}
+
+#keyboard_container {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ transform: translateY(-60px);
+
+}
+
+.keyboard_row {
+ display: flex;
+ justify-content: center;
+ gap: 6px;
+}
+
+.keyboard_row button {
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ font-weight: bold;
+ height: 58px;
+ width: 48px;
+ cursor: pointer;
+ background-color: var(--backgroundkeyboardrow-color);
+ color: var(--keyboardrow-color);
+ border: none;
+ border-radius: 4px;
+ text-transform: uppercase;
+ transition: background-color 0.2s ease, transform 0.2s ease;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.keyboard_row button:hover {
+ background-color: #e0e0e0;
+ transform: scale(1.1);
+}
+
+.keyboard_row button:active {
+ background-color: black;
+ color: white;
+ transform: scale(0.95);
+}
+
+.keyboard_row button[data-key="enter"],
+.keyboard_row button[data-key="backspace"] {
+ flex-grow: 1.5;
+ width: auto;
+ text-transform: none;
+ font-size:
+ 20px;
+}
+
+.keyboard_row button.right {
+ background-color: #7AA96B;
+ color: white;
+}
+
+.keyboard_row button.there {
+ background-color: #C3B671;
+ color: white;
+}
+
+.keyboard_row button.wrong {
+ background-color: #282828;
+ color: white;
+}
+
+
+/* Black overlay with a darker background */
+.overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.95); /* Darker black background */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0; /* Hidden by default */
+ z-index: 1000; /* Ensure it's above other content */
+ transition: opacity 0.5s ease; /* Smooth fade-in transition */
+}
+
+.overlay-win {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0; /* Hidden by default */
+ z-index: 1000; /* Ensure it's above other content */
+ transition: opacity 0.5s ease; /* Smooth fade-in transition */
+}
+
+/* Fade-in effect */
+.overlay.fade-in {
+ opacity: 1; /* Fully visible */
+}
+
+.overlay-win.fade-in {
+ opacity: 1; /* Fully visible */
+}
+
+/* Message container */
+.message-container {
+ background-color: white;
+ padding: 30px 40px; /* Increase padding for better spacing */
+ border-radius: 10px;
+ text-align: center;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
+ animation: slide-in 0.5s ease; /* Slide-in effect */
+ max-width: 500px; /* Set a maximum width for the popup */
+ width: 90%; /* Responsive for smaller screens */
+ box-sizing: border-box; /* Include padding in the width */
+}
+
+/* Slide-in animation */
+@keyframes slide-in {
+ from {
+ transform: translateY(-50px); /* Slightly above the center */
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0); /* At the center */
+ opacity: 1;
+ }
+}
+
+/* Message text */
+.message-text {
+ font-family: 'Georgia', serif;
+ font-size: 24px;
+ color: black;
+ margin-bottom: 20px;
+ text-align: center; /* Ensure horizontal centering */
+ line-height: 1.5; /* Improve readability */
+}
+.reset-button,
+.home-button {
+ font-family: 'Georgia', serif;
+ font-weight: 500;
+ padding: 10px 20px;
+ background-color: white;
+ border: 2px solid black;
+ border-radius: 5px;
+ cursor: pointer;
+ font-size: 16px;
+ display: inline-block; /* Prevent button from stretching */
+ transition: background-color 0.3s ease;
+ margin-left: 10px; /* Added margin for spacing between buttons */
+}
+
+.reset-button:hover,
+.home-button:hover {
+ background-color: black;
+ color: white;
+}
+
+
+.darkmode-slider-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.darkmode-slider-toggle {
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 34px;
+}
+
+.darkmode-slider-toggle input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.darkmode-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.darkmode-slider:before {
+ position: absolute;
+ content: "";
+ height: 26px;
+ width: 26px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.darkmode-slider-toggle input:checked + .darkmode-slider {
+ background-color: black;
+}
+
+.darkmode-slider-toggle input:checked + .darkmode-slider:before {
+ transform: translateX(26px);
+}
+
+.challenge-slider-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.challenge-slider-toggle {
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 34px;
+}
+
+.challenge-slider-toggle input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.challenge-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.challenge-slider:before {
+ position: absolute;
+ content: "";
+ height: 26px;
+ width: 26px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.challenge-slider-toggle input:checked + .challenge-slider {
+ background-color: black;
+}
+
+.challenge-slider-toggle input:checked + .challenge-slider:before {
+ transform: translateX(26px);
+}
+
+#status {
+ font-size: 16px;
+ color: #333;
+}
+
+#keyboard_container.grey-mode button {
+ background-color: grey !important;
+ color: white !important;
+}
+
+#keyboard_container.grey-mode button.right{
+ background-color: #7AA96B !important;
+ color: white !important;
+}
+
+#keyboard_container.grey-mode button.there{
+ background-color: #C3B671 !important;
+ color: white !important;
+}
+
+@keyframes bounce {
+ 0%, 20%, 50%, 80%, 100% {
+ transform: translateY(0);
+ }
+ 40% {
+ transform: translateY(-10px);
+ }
+ 60% {
+ transform: translateY(-5px);
+ }
+}
+
+.bounce {
+ animation: bounce 0.5s ease-in-out;
+}
+
+.sound-slider-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.sound-slider-toggle {
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 34px;
+}
+
+.sound-slider-toggle input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.sound-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.sound-slider:before {
+ position: absolute;
+ content: "";
+ height: 26px;
+ width: 26px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.sound-slider-toggle input:checked + .sound-slider {
+ background-color: black;
+}
+
+.sound-slider-toggle input:checked + .sound-slider:before {
+ transform: translateX(26px);
+}
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/3_hardmode.html b/EC327_Hangle_COMPLETED/3_hardmode.html
new file mode 100644
index 0000000000000000000000000000000000000000..c91c03af71c37d119222df274077035fc94cb40a
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_hardmode.html
@@ -0,0 +1,170 @@
+
+
+
+
+
+ Basic Web Project
+
+
+
+
+
+
+
+
+
+
+
+
+ ×
+
Guide
+
Here's everything you need to know to get started.
+
+
The goal is to guess the hidden word by selecting letters.
+
Each time you guess a letter, the game will provide feedback on your guess
+
+
+
+ Green: The letter is correct and in the correct position.
+
+
Yellow: The letter is in the word but in the wrong position.
+
Gray: The letter is not in the word.
+
+
+ Each wrong guess adds a piece to the hangman.
+
+
+
+ If you guess all the letters correctly, you win!
+
+
+
+
Challenge Mode
+
+
In Challenge Mode, letters you've guessed incorrectly won't turn gray, so you'll need to remember your guesses as you play.
+
+
+
+
+
+
+
+
+
+ ×
+
Settings
+
Make this game your own
+
+
Sound
+
+
+
+
+
Prefer a quieter experience? Toggle sound settings.
+
+
Dark Mode
+
+
+
+
+
Dark mode for a relaxed gaming experience.
+
+
+
Challenge Mode
+
+
+
+
+
Remember the letters you've already guessed wrong.
+
+
+
+
+
+
+
+
+
+
+ ×
+
Hint
+
Follow these tips to make the most of your hints
+
+
You can reveal a letter by clicking "Reveal a Letter".
+
Use "Additional Life" to reduce your penalty chances.
+
Plan your guesses strategically before using hints.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EC327_Hangle_COMPLETED/3_hardmode.js b/EC327_Hangle_COMPLETED/3_hardmode.js
new file mode 100644
index 0000000000000000000000000000000000000000..30c9243d50db6c5672a1c180534a4fabb944cfb8
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_hardmode.js
@@ -0,0 +1,947 @@
+const keyboard_container = document.querySelector("#keyboard_container");
+let currentword;
+let max_attempts = 6;
+var gameover = false;
+let wrong_attempts = 0;
+let word_length = 6;
+var spot = 0;
+let currentIndex = 1;
+let correct_word = 0;
+
+
+/**
+ * Initializes the Hangle game by setting up the word to guess, creating the game UI,
+ * and enabling user interaction through an on-screen keyboard and physical keyboard inputs.
+ *
+ * [Long Description]
+ * This function sets up the initial game state. It selects a random word and prepares
+ * a visual representation of the word as tiles in the game UI. It also dynamically
+ * generates an on-screen keyboard, allowing users to input guesses by clicking buttons
+ * or pressing keys on a physical keyboard. The function includes event listeners to
+ * handle typing interactions and maintains synchronization between on-screen and physical
+ * keyboard inputs.
+ *
+ * Key Steps:
+ * 1. Selects a random word and hint from a predefined list (`easy_word`).
+ * 2. Creates blank tiles corresponding to the letters of the selected word.
+ * 3. Dynamically generates an on-screen keyboard for user interaction.
+ * 4. Binds physical keyboard events to match the on-screen keyboard functionality.
+ *
+ * @global {Array} easy_word - An array of objects containing words and hints for the game.
+ * Each object has the structure: `{ word: string, hint: string }`.
+ * @global {HTMLElement} keyboard_container - The DOM element where the keyboard is rendered.
+ * @global {number} word_length - The length of the word to guess.
+ * @global {function} input - A callback function that processes user input for letter guesses.
+ * @global {function} updateRemoveBodyPartButton - Updates the initial state of controls (e.g., remove body part button).
+ *
+ * @throws {Error} Throws an error if any of the global dependencies (`easy_word`, `keyboard_container`, `input`) are undefined.
+ *
+ * @example
+ * // Basic usage of the initialize function to start the game:
+ * initialize();
+ *
+ * @see input - The function handling user guesses and game logic.
+ * @see updateRemoveBodyPartButton - The function managing the state of hangman-related controls.
+ *
+ * @see Game Development Tutorial - Great Day Designs
+ * @see Hangman Game Tutorial - Kenny Yip Coding
+ *
+ */
+function initialize() {
+ const getRandomWord = () => {
+ const { word, hint } = hard_word[Math.floor(Math.random() * hard_word.length)];
+ const new_hint = hint.replace(/\.$/, "");
+ currentword = word.toUpperCase();
+ // Remove automatic hint display
+ };
+
+ getRandomWord();
+ updateRemoveBodyPartButton(); // Initial button state
+
+ const tile_category = document.querySelector(".display");
+ tile_category.innerHTML = "";
+
+ // Create HangMan Space
+ for (let i = 0; i < word_length; i++) {
+ const tile = document.createElement("li");
+ tile.id = i.toString();
+ tile.classList.add("letter");
+ tile.innerText = "";
+ tile_category.appendChild(tile);
+ }
+
+
+ /// This is for typing the words in the boxes
+ const rows = [
+ "qwertyuiop".split(""),
+ "asdfghjkl".split(""),
+ [{ char: "↵", key: "enter" }, ..."zxcvbnm".split(""), { char: "⌫", key: "backspace" }],
+ ];
+
+
+
+ /// This is for typing the words in the boxes
+
+ rows.forEach((row) => {
+ const keyboard_row = document.createElement("div"); // Create a row container
+ keyboard_row.classList.add("keyboard_row");
+
+ row.forEach((item) => {
+ const button = document.createElement("button");
+
+ if (typeof item === "string") {
+ button.innerText = item.toUpperCase();
+ button.dataset.key = item;
+ } else {
+ button.innerText = item.char;
+ button.dataset.key = item.key;
+ }
+
+ button.addEventListener("click", () => {
+ input(button.dataset.key);
+ });
+
+ keyboard_row.appendChild(button);
+ });
+
+ keyboard_container.appendChild(keyboard_row);
+ });
+
+ // Typing with keys
+ document.addEventListener("keyup", (e) => {
+
+ const keyPressed = e.key.toLowerCase();
+ console.log("Key pressed:", keyPressed);
+
+ let button = document.querySelector(`button[data-key="${keyPressed}"]`);
+
+ if (!button) {
+ if (e.key === "Enter") {
+ button = document.querySelector(`button[data-key="enter"]`);
+ } else if (e.key === "Backspace") {
+ button = document.querySelector(`button[data-key="backspace"]`);
+ }
+ }
+
+ if (button) {
+ button.click();
+ } else {
+ console.log("No matching button found for:", keyPressed);
+ }
+ });
+}
+
+/**
+*
+* Assigns the initialize function to the window.onload event.
+* This ensures the initialize function executes automatically when the webpage finishes loading.
+*
+* The window.onload event is triggered after all assets
+* (e.g., HTML, CSS, JavaScript, images) are fully loaded.
+* By using this assignment, the initialize function initializes
+* or performs actions required after the page loads.
+* @return void - The assigned function does not return any value.
+* @see {@link window.onload}
+* @since 2024-12-09
+*/
+window.onload = function() {
+ initialize();
+}
+/**
+*
Toggles the sound setting based on the state of the sound slider (checkbox).
+* This function reads the state of the sound slider, stores it in `localStorage`,
+* and allows persistence of the user's sound preference across sessions.
+*
Key functionality:
+*
+*
If the slider is checked, sound is enabled
+*
If the slider is unchecked, sound is disabled.
+*
+*
+*
The state of the sound preference is saved in `localStorage` with the key `soundEnabled`.
+*
+* Example usage:
+* toggleSound(); // Saves the sound setting (enabled or disabled)
+* @return void - The assigned function does not return any value.
+* @since 2024-12-09
+*/
+function toggleSound() {
+ const soundEnabled = document.getElementById('sound-slider').checked;
+ localStorage.setItem('soundEnabled', soundEnabled); // Save the state
+}
+
+/**
+ * Loads the user's sound preference from `localStorage` and applies it to the sound slider.
+ *
+ * This function checks the `localStorage` for the user's saved sound preference under the key
+ * soundEnabled. If no preference is found (value is null), it defaults
+ * to enabling sound and saves this default state back to `localStorage`. The function then updates
+ * the state of the sound slider on the webpage based on the retrieved or default preference.
+ *
+ *
+ *
Retrieves Preference: Reads the soundEnabled key from `localStorage`.
+ *
Defaults to Sound ON: If no preference exists, sets soundEnabled to true.
+ *
Updates UI: Reflects the preference in the sound slider's checked state.
+ *
+ *
+ * @example:
+ * loadSoundPreference(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function loadSoundPreference() {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled'));
+
+ if (soundEnabled !== null) {
+ // Set the slider and the sound state based on localStorage
+ document.getElementById('sound-slider').checked = soundEnabled;
+ } else {
+ // Default to sound ON if no preference is saved
+ localStorage.setItem('soundEnabled', true);
+ document.getElementById('sound-slider').checked = true;
+ }
+}
+
+// Attach the event listener for the sound slider toggle
+document.getElementById('sound-slider').addEventListener('change', toggleSound);
+
+// Load the sound preference on page load
+document.addEventListener('DOMContentLoaded', loadSoundPreference);
+
+/**
+ * Allows sound to play, grabbing the specific sound file from its path, when soundEnabled is true.
+ *
+ * This function checks the when sound is enabled. If sound is enabled the function plays the audio.
+ * If sound is not enabled it logs it to the console saying "Sound is disabled".
+ *
+ *
+ *
sound is enabled sound plays
+ *
sound is disabled sound does not play
+ *
+ *
+ * @example:
+ * playSound(audioPath); // Loads and applies the user's sound preference on page load.
+ * @param audioPath - write audio path in string
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function playSound(audioPath) {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled')); // Check the current sound state
+ if (soundEnabled) {
+ const audio = new Audio(audioPath);
+ audio.play();
+ } else {
+ console.log("Sound is disabled.");
+ }
+}
+
+/**
+ * Processes user input and updates the game state based on the key pressed.
+ *
+ * [Long Description]
+ * This function handles user input during gameplay. Depending on the key pressed,
+ * it performs one of the following actions:
+ * 1. **Backspace**: Clears the most recent unlocked tile and updates the current spot.
+ * 2. **Enter**: Initiates the process to check the current word or letter against the answer.
+ * 3. **Letter Key**: Fills the first available unlocked tile with the pressed letter.
+ *
+ * The function also ensures that no actions are performed if the game is over.
+ * It plays a click sound for every input using the `playSound` function.
+ *
+ * @param {string} keyPressed - The key that was pressed by the user. Can be one of the following:
+ * - `"backspace"`: Deletes the most recent input in an unlocked tile.
+ * - `"enter"`: Triggers the letter/word check process.
+ * - Any other string representing a letter: Fills an available tile with the letter.
+ *
+ * @global {boolean} gameover - A flag indicating whether the game has ended. Prevents further input if `true`.
+ * @global {function} playSound - A function that plays a specified sound file.
+ * @global {number} spot - Tracks the current position for the next input in the tiles.
+ * @global {number} word_length - The length of the word to guess, used to iterate over tiles.
+ *
+ * @throws {Error} Throws an error if the global variables (`gameover`, `spot`, or `word_length`) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * input("a"); // Fills the next available tile with "A".
+ * input("backspace"); // Clears the last input from an unlocked tile.
+ * input("enter"); // Initiates letter/word check logic.
+ *
+ * @see checkletter - The function called when "enter" is pressed to validate the current word/letter.
+ * @see playSound - The function used to play sound effects.
+ *
+ *
+ * */
+const input = (keyPressed) => {
+ if (gameover) return;
+ playSound('sounds/click.wav');
+ if (keyPressed == "backspace") {
+
+ for (let i=spot-1; i>=0; i--) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock) {
+ currtile.innerText = "";
+ spot = i;
+ break;
+ }
+
+ }
+ }
+
+ else if (keyPressed == "enter") {
+ checkletter();
+
+
+ }
+
+ else {
+ for (let i = 0; i < word_length; i++) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock && currtile.innerText === "") {
+ currtile.innerText = keyPressed.toUpperCase();
+ spot = i + 1;
+ break;
+ }
+ }
+ }
+
+}
+
+/**
+ * Validates the user's guess by comparing it with the correct word and updates the game state accordingly.
+ *
+ * [Long Description]
+ * This function checks whether all the tiles have been filled with letters before validating the guess.
+ * If any tile is empty, it prompts the user to fill all spots. If the tiles are filled, it evaluates each
+ * letter against the target word (`currentword`) and updates the game state:
+ *
+ * 1. Correct guesses (letters in the correct position) are marked with the "right" class.
+ * 2. Incorrectly positioned but valid letters are marked with the "there" class.
+ * 3. Invalid letters (not in the word) are marked with the "wrong" class.
+ *
+ * Additionally, it tracks the number of incorrect guesses, updates the hangman display, and manages
+ * the game's end state by calling `checkgameover`. The keyboard buttons are dynamically updated to
+ * reflect the accuracy of the user's guesses.
+ *
+ * @global {string} currentword - The word the player is trying to guess.
+ * @global {number} correct_word - The count of correctly guessed letters in the correct positions.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of allowed wrong guesses before game over.
+ * @global {function} updatehangman - Updates the hangman figure based on incorrect attempts.
+ * @global {function} updateRemoveBodyPartButton - Manages the state of the "remove body part" button.
+ * @global {function} resetboard - Resets the tile board for the next round.
+ * @global {function} checkgameover - Checks if the game is over due to winning or exceeding maximum attempts.
+ *
+ * @throws {Error} Throws an error if any required global variables (`currentword`, `word_length`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * checkletter();
+ * // Output:
+ * // - Updates the tile and keyboard button states based on the user's guess.
+ * // - Logs incorrect attempts or success status to the console.
+ *
+ * @see updatehangman - Handles the visual display of the hangman figure.
+ * @see checkgameover - Manages the game's end state based on current progress.
+ *
+ * @note This logic was developed with assistance from ChatGPT to ensure accuracy and clarity.
+ */
+function checkletter() {
+
+ let spotsfilled = true;
+
+ for (let i =0; i {
+ currtile.classList.add("bounce");
+
+ // Remove the animation class after it ends
+ currtile.addEventListener("animationend", () => {
+ currtile.classList.remove("bounce");
+ });
+ }, i * 150); // Stagger delay by 150ms per tile
+ }
+}
+
+/**
+ * Checks if the game is over and handles end-of-game actions accordingly.
+ *
+ * [Long Description]
+ * This function determines whether the game has ended based on the player's most recent guess.
+ * If the guess was correct and the game is won, it sets the game state to "over," displays a
+ * winning message, animates the tiles, plays a victory sound, and launches confetti. If the
+ * number of incorrect attempts reaches or exceeds the maximum allowed, it ends the game,
+ * displays a losing message, and plays a failure sound.
+ *
+ * @param {boolean} incorrectGuess - Indicates whether the last guess was incorrect.
+ * If `true`, the game checks if the maximum attempts have been exceeded.
+ *
+ * @global {boolean} gameover - A flag that indicates if the game has ended. This is set to `true` when the game is over.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of incorrect guesses allowed before the game ends.
+ * @global {string} currentword - The word the player was trying to guess, used in the losing message.
+ * @global {function} animateTiles - Animates the tiles when the game is won.
+ * @global {function} displayMessage - Displays a message to the player indicating the game's outcome.
+ * @global {function} playSound - Plays a sound file corresponding to the game's outcome (win or lose).
+ *
+ *
+ * @example
+ * // Example usage:
+ * checkgameover(false); // Handles the "win" scenario if no incorrect guess.
+ * checkgameover(true); // Checks if the player has exceeded the maximum allowed incorrect attempts.
+ *
+ * @see animateTiles - For handling tile animations upon winning.
+ * @see displayMessage - For managing game status messages.
+ * @see confetti - Used to trigger confetti effects for celebrations.
+ *
+ */
+function checkgameover(incorrectGuess) {
+
+ if (!incorrectGuess) {
+ gameover = true;
+ console.log("good!")
+ displaymessage("You Win!", true, true)
+ animateTiles();
+ playSound('sounds/win.wav');
+ confetti({
+ particleCount: 150, // Number of confetti pieces
+ spread: 70, // Spread angle of confetti
+ origin: { y: 0.6 }, // Confetti drop point
+ colors: ['#bb0000', '#ffffff', '#00bb00'] // Custom colors
+ });
+ return;
+ }
+
+ if (wrong_attempts >= max_attempts) {
+ gameover = true;
+ console.log("bad");
+ displaymessage(`Game Over! The word was: ${currentword}`);
+ playSound('sounds/lose.wav');
+ return;
+ }
+ }
+
+
+ /**
+ * Displays a message overlay on the screen with optional reset and home buttons.
+ *
+ * [Long Description]
+ * This function creates and displays an overlay message on the screen. It includes a customizable
+ * message and optional buttons for resetting the game and navigating to the home page. The overlay
+ * is styled dynamically based on whether the game was won or lost. The "Play Again" button reloads
+ * the page to restart the game, while the "Go Home" button redirects to the main page.
+ *
+ * A fade-in animation is triggered after the overlay is appended to the DOM for a smooth visual effect.
+ *
+ * @param {string} message - The message to display on the overlay.
+ * @param {boolean} [showResetButton=true] - Determines whether the "Play Again" button is displayed.
+ * @param {boolean} [isWin=false] - Specifies whether the game was won, which affects the overlay's style.
+ *
+ * @example
+ * // Display a winning message with reset and home buttons:
+ * displayMessage("You Win!", true, true);
+ *
+ * // Display a losing message without a reset button:
+ * displayMessage("Game Over! The word was: CAT", false);
+ *
+ * @see location.reload - Used to reload the page for restarting the game.
+ * @see window.location.href - Redirects to the specified home page URL.
+ *
+ */
+ function displaymessage(message, showResetButton = true, isWin = false) {
+ // Create the black overlay
+ const overlay = document.createElement("div");
+ overlay.classList.add(isWin ? "overlay-win" : "overlay");
+
+ // Create the message container
+ const messageContainer = document.createElement("div");
+ messageContainer.classList.add("message-container");
+
+ // Add the message text
+ const messageText = document.createElement("p");
+ messageText.classList.add("message-text");
+ messageText.innerText = message;
+ messageContainer.appendChild(messageText);
+
+ // Add the reset button (Play Again)
+ if (showResetButton) {
+ const resetButton = document.createElement("button");
+ resetButton.classList.add("reset-button");
+ resetButton.innerText = "Play Again";
+ resetButton.addEventListener("click", () => {
+ location.reload(); // Reload the page to restart the game
+ });
+ messageContainer.appendChild(resetButton);
+ }
+
+ // Add the Home button (go to home page)
+ const homeButton = document.createElement("button");
+ homeButton.classList.add("home-button");
+ homeButton.innerText = "Go Home";
+ homeButton.addEventListener("click", () => {
+ window.location.href = '1_mainpage.html'; // Redirect to home page
+ });
+ messageContainer.appendChild(homeButton);
+
+ // Append the container to the overlay
+ overlay.appendChild(messageContainer);
+
+ // Append the overlay to the body
+ document.body.appendChild(overlay);
+
+ // Trigger fade-in animation
+ setTimeout(() => {
+ overlay.classList.add("fade-in");
+ }, 10);
+}
+
+/**
+ * Resets the letter tiles on the board for the next round of the game.
+ *
+ * [Long Description]
+ * This function clears the text and resets the styles for all letter tiles that
+ * are not marked as "right" (correctly guessed letters). It ensures that only
+ * unlocked tiles (tiles without the "right" class) are cleared, while maintaining
+ * the state of correctly guessed tiles. Additionally, it removes the "there"
+ * class from all tiles, resetting their visual state.
+ *
+ * Key Features:
+ * - Clears the `innerText` of tiles that are not locked as correct.
+ * - Removes the "there" class from all tiles.
+ * - Resets the `spot` tracker to 0, indicating the starting position for input in the next round.
+ *
+ * @global {number} word_length - The length of the word being guessed, used to determine the number of tiles.
+ * @global {number} spot - Tracks the current position for the next input. This is reset to 0 by this function.
+ *
+ * @example
+ * // Reset the board for a new round:
+ * resetboard();
+ *
+ * @see spot - Resets the spot tracker for the next round of inputs.
+ * @since 2024-12-09
+ */
+function resetboard() {
+ for (let i = 0; iThis function manages the visual representation of incorrect guesses by progressively
+ * revealing parts of the hangman figure. Each time an incorrect guess is made, the opacity
+ * of the next body part image in the sequence is set to 1, making it visible. The function
+ * keeps track of the current index of the body parts and ensures that it does not exceed the
+ * total number of body parts available.
+ *
+ *
+ *
Increment Index: The function increments the `currentIndex` to keep track
+ * of which body part should be revealed next.
+ *
Reveal Body Part: The next body part image in the sequence is revealed
+ * by changing its opacity.
+ *
Boundary Check: Ensures that no more body parts are revealed after the
+ * last image in the sequence.
+ *
+ *
+ * @global {NodeList} images - A collection of elements representing the hangman body parts.
+ * These elements are queried from the DOM using the `.body-part` class.
+ * @global {number} currentIndex - Tracks the current body part being revealed. Incremented with
+ * each incorrect guess.
+ *
+ * @throws {Error} Throws an error if the `images` NodeList is undefined or `currentIndex` exceeds its length.
+ *
+ * @example
+ * // Example usage:
+ * updatehangman();
+ * // Output:
+ * // - Reveals the next body part in the sequence by making it visible.
+ *
+ * @since 2024-12-09
+ */
+function updatehangman() {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex < images.length) {
+ images[currentIndex].style.opacity = 1; // Show the next image
+ currentIndex++;
+ }
+}
+
+/**
+ * Redirects the user to the main page when the "Home" link is clicked.
+ *
+ *
This function listens for a click event on the element with the ID `Home-link`. Upon clicking,
+ * the user is redirected to the "1_mainpage.html" page. It is primarily used for navigation purposes
+ * within the application.
+ * toggles darkmode on and off and saves the data into {@code localStorage} object, which is
+ * then stored in the web storage API
+ *
+ *
+ * This function toggles the darkmode class on the {@code document.body} element,
+ * which typically applies or removes dark mode styling. It also updates the {@code localStorage}
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ * @example:
+ * toggleDarkMode(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see document.body
+ * @since 2024-12-09
+ */
+function toggleDarkMode() {
+ const darkModeEnabled = document.body.classList.toggle('darkmode');
+ localStorage.setItem('darkModeEnabled', darkModeEnabled); // Save the state
+}
+
+/**
+ * Toggles the dark mode on or off and saves the current state in localStorage.
+ *
+ * This function toggles the darkmode class on the document.body element,
+ * which typically applies or removes dark mode styling. It also updates the localStorage
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ *
+ * @example usage:
+ * toggleDarkMode(); // Toggles dark mode and saves the state
+ *
+ * @return void - This function does not return any value.
+ * @see localStorage
+ * @see document.body
+ */
+function loadDarkModePreference() {
+ const darkModeEnabled = JSON.parse(localStorage.getItem('darkModeEnabled'));
+
+ if (darkModeEnabled) {
+ // Apply dark mode if it was enabled
+ document.body.classList.add('darkmode');
+ document.getElementById('darkmode-slider').checked = true; // Set the slider to ON
+ } else {
+ // Ensure light mode if dark mode was not enabled
+ document.body.classList.remove('darkmode');
+ document.getElementById('darkmode-slider').checked = false; // Set the slider to OFF
+ }
+}
+
+// Attach the event listener for the dark mode slider toggle
+document.getElementById('darkmode-slider').addEventListener('change', toggleDarkMode);
+
+// Load the dark mode preference on page load
+document.addEventListener('DOMContentLoaded', loadDarkModePreference);
+
+
+const challengeSlider = document.getElementById("challenge-slider");
+const keyboardContainer = document.getElementById("keyboard_container");
+/**
+ *
+ * Toggles the "grey-mode" class on the keyboard container based on the challenge slider's state.
+ *
+ *
+ *
+ *
Checked: Enables "grey-mode" on the keyboard container.
+ *
Unchecked: Disables "grey-mode" and restores default styling.
+ *
+ *
+ * @event change - Triggered when the state of the challenge slider changes (checked/unchecked).
+ *
+ * @param {Event} event - The event triggered when the slider's state changes.
+ *
+ * @global {HTMLElement} challengeSlider - The DOM element representing the challenge slider.
+ * @global {HTMLElement} keyboardContainer - The DOM element containing the keyboard.
+ *
+ * @example
+ * // Example usage:
+ * challengeSlider.addEventListener("change", () => {
+ * if (challengeSlider.checked) {
+ * keyboardContainer.classList.add("grey-mode");
+ * } else {
+ * keyboardContainer.classList.remove("grey-mode");
+ * }
+ * });
+ *
+ * @return {void} - This function does not return a value.
+ * @see keyboardContainer - The target element for the "grey-mode" class.
+ * @see challengeSlider - The slider controlling the challenge mode.
+ * @since 2024-12-09
+ */
+challengeSlider.addEventListener("change", () => {
+ if (challengeSlider.checked) {
+ keyboardContainer.classList.add("grey-mode");
+ } else {
+ keyboardContainer.classList.remove("grey-mode");
+ }
+});
+
+/**
+ * Handles the click event of the "remove-body-part" button to remove a body part image.
+ *
+ *
This function is triggered when the user clicks the "remove-body-part" button. It reduces the visibility
+ * of the most recent body part image (by setting its opacity to 0) and decreases the `wrong_attempts` count.
+ * The button is then disabled and visually updated to indicate it's no longer clickable. If no wrong attempts
+ * are left, the button is hidden.
+ *
+ * @function
+ * @param none
+ * @return void
+ * @see wrong_attempts,currentIndex
+ * @since 2024-12-09
+ */
+document.getElementById('remove-body-part').addEventListener('click', function () {
+ if (wrong_attempts > 0) {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex > 1) {
+ currentIndex--;
+ images[currentIndex].style.opacity = 0;
+ wrong_attempts = Math.max(0, wrong_attempts - 1);
+ console.log(`Body part removed. Remaining wrong attempts: ${max_attempts - wrong_attempts}`);
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+ } else {
+ this.style.display = 'none';
+ }
+});
+
+/**
+ * Adds an event listener to the "reveal-letter" button to reveal a random unrevealed letter from the current word.
+ *
This functionality helps the user by revealing a letter from the target word when the button is clicked.
+ * The revealed letter is displayed in its corresponding tile on the interface and marked as "right."
+ * Additionally, the associated keyboard key is highlighted. Once all letters are revealed,
+ * the game checks for completion, and the "reveal-letter" button is disabled to prevent further use.
+ *
+ *
Revealing a Letter: A random unrevealed letter is selected, displayed on the game tile, and marked as correct.
+ *
Keyboard Highlight: The corresponding keyboard key is updated to indicate it has been used correctly.
+ *
Button State: The "reveal-letter" button is disabled after a letter is revealed to prevent additional usage.
+ *
Game Completion: If all letters are revealed, the game checks for completion.
+ *
Error Handling: If all letters have already been revealed, a message is logged to the console.
+ *
+ *
+ * @function
+ * @since 2024-12-09
+ */
+document.getElementById('reveal-letter').addEventListener('click', function () {
+ const randomIndex = getRandomUnrevealedLetter();
+
+ if (randomIndex !== null) {
+ const currTile = document.getElementById(randomIndex.toString());
+ currTile.innerText = currentword[randomIndex];
+ currTile.classList.add("right");
+ currTile.dataset.lock = "true";
+
+ // Update the keyboard button color
+ const keyButton = document.querySelector(`button[data-key="${currentword[randomIndex].toLowerCase()}"]`);
+ if (keyButton) {
+ keyButton.classList.add("right");
+ }
+
+ correct_word++;
+
+ if (correct_word === word_length) {
+ checkgameover(false);
+ }
+ } else {
+ console.log("All letters have already been revealed.");
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+/**
+ * Retrieves the index of a random unrevealed letter from the current word.
+ *
+ *
This function identifies all the tiles representing unrevealed letters and randomly selects
+ * one of them. If all letters have been revealed, it returns `null`. The unrevealed letters are
+ * determined by checking the absence of a `lock` attribute in the dataset of each tile element.
+ *
+ * @function
+ * @param none
+ * @return {number|null} - The index of a random unrevealed letter, or `null` if no letters are left to reveal.
+ * @see word_length
+ * @since 2024-12-09
+ *
+ */
+function getRandomUnrevealedLetter() {
+ const unrevealedIndices = [];
+ // Collect indices of unrevealed letters
+ for (let i = 0; i < word_length; i++) {
+ const currTile = document.getElementById(i.toString());
+ if (!currTile.dataset.lock) {
+ unrevealedIndices.push(i);
+ }
+ }
+ // Shuffle the unrevealed indices
+ if (unrevealedIndices.length > 0) {
+ const randomIndex = Math.floor(Math.random() * unrevealedIndices.length);
+ return unrevealedIndices[randomIndex];
+ }
+ return null; // No letters left to reveal
+}
+/**
+ * Displays a hint for the current word when the "show-clue" button is clicked.
+ *
+ *
This method retrieves a hint corresponding to the current word from the `easy_word` array
+ * and displays it in the designated clue area. After displaying the hint, the "show-clue" button
+ * is disabled to prevent multiple uses.
+ *
+ * @function
+ * @return void
+ * @throws Error if the current word is not found in the `easy_word` array.
+ * @see easy_word
+ * @since 2024-12-09
+ */
+document.getElementById('show-clue').addEventListener('click', function() {
+ const clueContent = document.getElementById('clue-content');
+ const hint = hard_word.find(item => item.word.toUpperCase() === currentword).hint;
+ clueContent.textContent = hint.replace(/\.$/, "");
+ clueContent.style.display = 'block';
+
+ // Disable the button after use
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Updates the visibility of the "Remove Body Part" button based on the number of wrong attempts.
+ *
+ *
This function checks the value of `wrong_attempts` and adjusts the display style of the
+ * "remove-body-part" button accordingly. The button becomes visible when there is at least one wrong
+ * attempt and is hidden otherwise. This functionality ensures that the button is only accessible
+ * when it is relevant to the game state.
+ *
+ * @function
+ * @return void
+ * @since 2024-12-09
+ */
+function updateRemoveBodyPartButton() {
+ const removeBodyPartButton = document.getElementById('remove-body-part');
+ if (wrong_attempts > 0) {
+ removeBodyPartButton.style.display = 'inline-block';
+ } else {
+ removeBodyPartButton.style.display = 'none';
+ }
+}
+
+module.exports = {
+ initialize,
+ input,
+ checkletter,
+ resetboard,
+ checkgameover,
+ updatehangman,
+};
diff --git a/EC327_Hangle_COMPLETED/3_hardwordbank.js b/EC327_Hangle_COMPLETED/3_hardwordbank.js
new file mode 100644
index 0000000000000000000000000000000000000000..87c8da75bdcf0ff180ed14e2992e7b99d240ca6c
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_hardwordbank.js
@@ -0,0 +1,103 @@
+const hard_word = [
+ { word: "butter", hint: "Spread on bread, often yellow." },
+ { word: "orange", hint: "A citrus fruit that's both a color and a taste." },
+ { word: "planet", hint: "Orbits a star in space." },
+ { word: "soccer", hint: "A sport played with a round ball and two goals." },
+ { word: "guitar", hint: "A stringed musical instrument." },
+ { word: "bridge", hint: "Connects two places over water." },
+ { word: "school", hint: "Where you go to learn." },
+ { word: "tomato", hint: "A red fruit often used in salads and sauces." },
+ { word: "wallet", hint: "Holds your money and cards." },
+ { word: "forest", hint: "A large area covered with trees." },
+ { word: "ladder", hint: "Used to climb to higher places." },
+ { word: "cotton", hint: "A soft material often used for clothes." },
+ { word: "flower", hint: "Blooms with petals and bright colors." },
+ { word: "pencil", hint: "Used for writing or drawing." },
+ { word: "potato", hint: "A root vegetable used in fries." },
+ { word: "gloves", hint: "Worn on hands for warmth or protection." },
+ { word: "animal", hint: "A living creature, not a plant." },
+ { word: "rocket", hint: "Flies into space with astronauts or satellites." },
+ { word: "market", hint: "A place to buy and sell goods." },
+ { word: "summer", hint: "The warmest season of the year." },
+ { word: "rabbit", hint: "A small animal with long ears." },
+ { word: "island", hint: "Land surrounded by water." },
+ { word: "cherry", hint: "A small red fruit often on top of desserts." },
+ { word: "camera", hint: "Used to take photos or videos." },
+ { word: "beacon", hint: "A light used to guide or warn." },
+ { word: "silver", hint: "A shiny, precious metal." },
+ { word: "jungle", hint: "A dense tropical forest." },
+ { word: "cookie", hint: "A sweet baked snack." },
+ { word: "castle", hint: "A fortress for royalty or defense." },
+ { word: "saddle", hint: "Placed on a horse for riding." },
+ { word: "pirate", hint: "Sails the seas looking for treasure." },
+ { word: "dragon", hint: "A mythical creature that breathes fire." },
+ { word: "desert", hint: "A dry, sandy area with little rain." },
+ { word: "pepper", hint: "A spicy vegetable or seasoning." },
+ { word: "rocket", hint: "A spacecraft or fireworks device." },
+ { word: "cotton", hint: "A fabric made from a soft plant." },
+ { word: "subway", hint: "An underground train system." },
+ { word: "butter", hint: "Used in cooking or on toast." },
+ { word: "winter", hint: "The coldest season of the year." },
+ { word: "throne", hint: "A royal seat for kings or queens." },
+ { word: "planet", hint: "A celestial body orbiting a star." },
+ { word: "goblin", hint: "A mischievous mythical creature." },
+ { word: "friend", hint: "Someone you trust and enjoy being with." },
+ { word: "beacon", hint: "A guiding or warning light." },
+ { word: "wallet", hint: "Keeps your money and cards secure." },
+ { word: "beetle", hint: "An insect with a hard shell." },
+ { word: "stream", hint: "A small flowing body of water." },
+ { word: "garden", hint: "A place to grow flowers or vegetables." },
+ { word: "bucket", hint: "Used to carry water or other items." },
+ { word: "anchor", hint: "Keeps a ship in place." },
+ { word: "glider", hint: "A lightweight plane without an engine." },
+ { word: "banjos", hint: "Stringed instruments with a circular body." },
+ { word: "parrot", hint: "A colorful bird that can mimic sounds." },
+ { word: "helmet", hint: "Protects your head during activities." },
+ { word: "stripe", hint: "A long, narrow band of color." },
+ { word: "shadow", hint: "A dark area where light is blocked." },
+ { word: "orange", hint: "Both a fruit and a color." },
+ { word: "tunnel", hint: "A passageway through or under something." },
+ { word: "locker", hint: "A secure place to store items." },
+ { word: "picnic", hint: "An outdoor meal on a blanket." },
+ { word: "coffin", hint: "A box for burial." },
+ { word: "voyage", hint: "A long journey, often by sea." },
+ { word: "packet", hint: "A small container or bundle." },
+ { word: "poster", hint: "A large printed display for walls." },
+ { word: "lantern", hint: "A portable light source." },
+ { word: "stitch", hint: "A single loop in sewing or knitting." },
+ { word: "zipper", hint: "A fastener for clothes or bags." },
+ { word: "hunger", hint: "The need or desire for food." },
+ { word: "hammer", hint: "A tool used for driving nails." },
+ { word: "stride", hint: "A confident and purposeful walk." },
+ { word: "ladder", hint: "Used to climb to higher places." },
+ { word: "pillow", hint: "Rest your head on it while sleeping." },
+ { word: "market", hint: "A place where goods are bought or sold." },
+ { word: "puddle", hint: "A small pool of liquid on the ground." },
+ { word: "breeze", hint: "A gentle and light wind." },
+ { word: "planet", hint: "Orbits a star in a solar system." },
+ { word: "cheese", hint: "Made from milk, often yellow or white." },
+ { word: "cactus", hint: "A spiky plant found in deserts." },
+ { word: "muffin", hint: "A small, sweet baked treat." },
+ { word: "beacon", hint: "A light used to warn or guide." },
+ { word: "quartz", hint: "A common mineral, often clear or white." },
+ { word: "jigsaw", hint: "A type of puzzle with many pieces." },
+ { word: "planet", hint: "A large celestial body orbiting a star." },
+ { word: "pickle", hint: "A cucumber preserved in vinegar." },
+ { word: "velvet", hint: "A soft and smooth fabric." },
+ { word: "hazard", hint: "Something that can cause harm." },
+ { word: "stream", hint: "A small, flowing body of water." },
+ { word: "pepper", hint: "A spicy seasoning or vegetable." },
+ { word: "beacon", hint: "A signal light or guiding tower." },
+ { word: "banana", hint: "A yellow fruit that's often curved." },
+ { word: "sleigh", hint: "Pulled by reindeer in snowy areas." },
+ { word: "button", hint: "Fastens clothes or activates devices." },
+ { word: "tunnel", hint: "An underground passage or road." },
+ { word: "window", hint: "Allows light and air into a room." },
+ { word: "throne", hint: "A royal chair for kings or queens." },
+ { word: "bridge", hint: "Spans a gap, often over water." },
+ { word: "ticket", hint: "Allows entry to events or travel." },
+ { word: "parrot", hint: "A bird known for mimicking sounds." },
+ { word: "hammer", hint: "Used to hit nails into wood." },
+ { word: "socket", hint: "Provides power for electronic devices." },
+ { word: "planet", hint: "A celestial body orbiting a star." },
+];
diff --git a/EC327_Hangle_COMPLETED/3_medmode.css b/EC327_Hangle_COMPLETED/3_medmode.css
new file mode 100644
index 0000000000000000000000000000000000000000..7464918cf03d04c5fdf7145c0a6857b9c040bc7e
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_medmode.css
@@ -0,0 +1,802 @@
+:root{
+ --backgroundbody-color: #f0f0f0;
+ --body-color: #333;
+ --backgroundnavbar-color: #ffffff;
+ --border-bottom: #ddd;
+ --navitem-color: black;
+ --backgroundmodal-color:black;
+ --backgroundmodalcontent-color: white;
+ --closebutton-color: black;
+ --backgroundbox-color: white;
+ --borderboxdisplayeletter-color: #d3d3d3;
+ --backgroundboxdisplayeletter-color: white;
+ --borderboxdisplayright-color:#7AA96B;
+ --backgroundboxdisplayright-color: #7AA96B;
+ --boxdisplayright-color: white;
+ --borderboxdisplaythere-color: #C3B671;
+ --backgroundboxdisplaythere-color: #C3B671;
+ --backgroundkeyboardrow-color:rgb(215, 215, 215);
+ --keyboardrow-color:rgb(33, 33, 33);
+ --modalcontentletter-color: black;
+
+
+}
+.darkmode{
+
+ --backgroundbody-color: #202020;
+ --body-color: #333;
+ --backgroundnavbar-color: #434343;
+ --border-bottom: #434343;
+ --navitem-color: rgb(255, 255, 255);
+ --backgroundmodal-color:black;
+ --backgroundmodalcontent-color: rgb(64, 64, 64);
+ --closebutton-color: black;
+ --backgroundbox-color: rgb(98, 98, 98);
+ --borderboxdisplayeletter-color: #202020;
+ --backgroundboxdisplayeletter-color: rgb(98, 98, 98);
+ --borderboxdisplayright-color:#7AA96B;
+ --backgroundboxdisplayright-color: #7AA96B;
+ --boxdisplayright-color: white;
+ --borderboxdisplaythere-color: #C3B671;
+ --backgroundboxdisplaythere-color: #C3B671;
+ --backgroundkeyboardrow-color:rgb(62, 62, 62);
+ --keyboardrow-color:rgb(198, 198, 198);
+ --letter-color: rgb(255, 255, 255);
+ --modalcontentletter-color: white;
+}
+
+body {
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ background-color: var(--backgroundbody-color);
+ color: var(--body-color);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: space-around;
+ height: 100vh;
+}
+
+.navbar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10px 20px;
+ background-color: var(--backgroundnavbar-color);
+ border-bottom: 1px solid var(--border-bottom);
+ box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-right {
+ display: flex;
+ align-items: center;
+ gap: 30px;
+}
+
+.nav-item {
+ text-decoration: none;
+ color: var(--navitem-color);
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: color 0.3s ease;
+}
+
+
+/* Modal Styling */
+.modal {
+ display: none; /* Hidden by default */
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: var(--backgroundmodal-color); /* Semi-transparent black background */
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+}
+
+.modal.active {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.modal-content {
+ background-color: var(--backgroundmodalcontent-color);
+ padding: 20px 60px;
+ border-radius: 10px;
+ width: 50%;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
+ animation: fadeIn 0.3s ease;
+ color: var(--modalcontentletter-color);
+ text-align: center;
+ position: relative;
+ width: 35%;
+ max-width: 500px;
+ height: auto;
+ padding: 5px 30px;
+ border-radius: 12px;
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
+ background-color: var( --backgroundnavbar-color);
+}
+
+.modal #status {
+ color: var(--modalcontentletter-color);
+}
+
+
+h2 {
+ font-family: 'Georgia', serif; /* Georgia font with serif fallback */
+ font-weight: 1000; /* Bold weight */
+ font-size: 30px; /* Adjust size as needed */
+ color: var( --letter-color); /* Text color */
+ line-height: 1; /* Adjust spacing between lines if multiline */
+ text-align: left; /* Optional: Center the text */
+ margin-bottom: 5px;
+}
+
+p {
+ margin-top: 8px;
+ font-weight: 500;
+ font-family: 'Georgia', serif; /* Georgia font with serif fallback */
+ font-size: 20px; /* Adjust size as needed */
+ color: var( --letter-color); /* Text color */
+ text-align: left; /* Optional: Center the text */
+}
+
+ul {
+ text-align: left; /* Align text to the left */
+ list-style: disc; /* Use standard bullet points */
+ padding-left: 20px; /* Add space for proper bullet alignment */
+ margin: 10px 0; /* Add spacing around the list */
+ font-family: 'Georgia', serif; /* Match font style */
+ font-size: 18px; /* Match font size to the paragraph */
+ line-height: 1.5; /* Add spacing between list items */
+ margin-bottom: 20px;
+}
+
+ul li {
+ margin-bottom: 8px; /* Add spacing between bullet points */
+}
+
+.close-button {
+ position: absolute;
+ top: 10px;
+ right: 15px; /* Adjust as needed to position horizontally */
+ font-size: 24px;
+ font-weight: bold;
+ color: var(--closebutton-color);
+ cursor: pointer;
+}
+.close-button:hover {
+ color: red;
+}
+
+/* Modal Fade-In Animation */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: scale(0.9);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+/* hints */
+#hint-content {
+ margin: 10px 0;
+ font-weight: bold;
+ color: var(--modalcontentletter-color);
+ text-align: center;
+}
+
+#clue-content {
+ margin: 15px 0;
+ font-weight: bold;
+ color: var(--modalcontentletter-color);
+ text-align: center;
+ padding: 10px;
+ background-color: rgba(0, 0, 0, 0.05);
+ border-radius: 5px;
+}
+
+.hint-buttons-container {
+ display: flex;
+ justify-content: center;
+ gap: 10px;
+ margin-bottom: 20px;
+}
+
+.hint-button {
+ font-family: 'Georgia', serif;
+ font-weight: 500;
+ padding: 10px 20px;
+ background-color: white;
+ border: 2px solid black;
+ border-radius: 5px;
+ cursor: pointer;
+ font-size: 16px;
+ width: 180px;
+ box-sizing: border-box;
+}
+
+.hint-button:hover {
+ background-color: black;
+ color: white;
+}
+
+.hint-button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ background-color: #f0f0f0;
+ color: #666;
+ border-color: #666;
+}
+
+#remove-body-part {
+ display: block;
+ margin: 3px auto 0;
+}
+/*settings */
+
+#settings-modal ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+}
+
+#settings-modal ul li {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 15px;
+ line-height: 1.5;
+}
+
+#settings-modal .sound-slider-container,
+#settings-modal .darkmode-slider-container,
+#settings-modal .challenge-slider-container {
+ margin: 0; /* Remove margin to prevent misalignment */
+ padding: 0; /* Remove padding to prevent misalignment */
+}
+
+.sound-slider,
+.darkmode-slider,
+.challenge-slider {
+ width: 60px; /* Adjust width for consistent sizing */
+ height: 34px; /* Adjust height for consistent sizing */
+ transform: translateY(-1px);
+}
+
+#subtitle {
+ font-size: 14px;
+ margin-top: -15px;
+ margin-bottom: 15px;
+}
+
+/* guide */
+/* Align the color-rules with the guide title */
+#color-rules {
+ font-size: 16px;
+ list-style: none; /* Remove bullet points */
+ padding: 0; /* Remove padding */
+ margin-left: -20px; /* Align with parent content */
+ margin-top: 10px; /* Add some space between the parent list and color rules */
+}
+
+
+.guide-image {
+ display: block;
+ width: 300px;
+ height: auto;
+ margin: 15px auto; /* Center the image horizontally */
+
+}
+
+#text-rules {
+ list-style: none;
+ margin-left: -20px;
+}
+
+.box {
+ background-color: var(--backgroundbox-color);
+ width: 800px;
+ height: 350px;
+ padding: 60px 40px;
+ box-sizing: border-box;
+ text-align: center;
+ border-radius: 10px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ font-size: 18px;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 60px;
+}
+
+
+#hangman-container {
+ position: relative; /* Position relative for child positioning */
+ width: 300px; /* Set a fixed width */
+ height: 450px; /* Set a fixed height */
+ display: flex; /* Allow for centering the child parts */
+ align-items: center; /* Vertically center */
+ justify-content: center; /* Horizontally center */
+ align-items: center;
+
+}
+
+/* Style for hangman body parts */
+.body-part {
+ position: absolute; /* Absolute positioning inside relative parent */
+ opacity: 0; /* Hidden by default */
+ transition: opacity 0.15s ease-in; /* Fade in effect */
+}
+
+/* Specific styles for each body part */
+#head {
+ width: 17%; /* Proportional to container */
+ height: auto;
+ top: 38%; /* Adjust to fit inside the container */
+ left: 55%; /* Center horizontally */
+}
+
+#body {
+ width: 40%; /* Smaller portion of the container */
+ height: auto;
+ top: 45%;
+ left: 43%;
+}
+
+#rarm {
+ width: 12%;
+ height: auto;
+ top: 50%;
+ left: 62%;
+}
+
+#larm {
+ width: 12%;
+ height: auto;
+ top: 50%;
+ left: 52%;
+}
+
+#rleg {
+ width: 12%;
+ height: auto;
+ top: 67.5%;
+ left: 52%;
+}
+
+#lleg {
+ width: 12%;
+ height: auto;
+ top: 67.5%;
+ left: 62%;
+}
+
+/* Ensure the initial empty part of the hangman is visible */
+#empty {
+ display: block;
+ width: 100%;
+ height: auto;
+}
+
+.box .display {
+ display: flex;
+ gap: 10px;
+ list-style: none;
+ align-items: center;
+ justify-content: center;
+}
+
+.box .display .letter {
+ border: 2px solid var(--borderboxdisplayeletter-color);
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--backgroundboxdisplayeletter-color);
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ font-size: 24px;
+ color: var(--letter-color);
+ text-transform: uppercase;
+ font-weight: 900;
+}
+
+.box .display .right {
+ border: 2px solid var(--borderboxdisplayright-color);
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--backgroundboxdisplayright-color);
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ color: var(--boxdisplayright-color);
+ font-size: 24px;
+ text-transform: uppercase;
+ font-weight: 900;
+}
+
+.box .display .there {
+ border: 2px solid var(--borderboxdisplaythere-color);
+ width: 60px;
+ height: 60px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color:var(--backgroundboxdisplaythere-color);
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ color:var(--boxdisplayright-color);
+ font-size: 24px;
+ text-transform: uppercase;
+ font-weight: 900;
+}
+
+#keyboard_container {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ transform: translateY(-60px);
+
+}
+
+.keyboard_row {
+ display: flex;
+ justify-content: center;
+ gap: 6px;
+}
+
+.keyboard_row button {
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
+ font-weight: bold;
+ height: 58px;
+ width: 48px;
+ cursor: pointer;
+ background-color: var(--backgroundkeyboardrow-color);
+ color: var(--keyboardrow-color);
+ border: none;
+ border-radius: 4px;
+ text-transform: uppercase;
+ transition: background-color 0.2s ease, transform 0.2s ease;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.keyboard_row button:hover {
+ background-color: #e0e0e0;
+ transform: scale(1.1);
+}
+
+.keyboard_row button:active {
+ background-color: black;
+ color: white;
+ transform: scale(0.95);
+}
+
+.keyboard_row button[data-key="enter"],
+.keyboard_row button[data-key="backspace"] {
+ flex-grow: 1.5;
+ width: auto;
+ text-transform: none;
+ font-size:
+ 20px;
+}
+
+.keyboard_row button.right {
+ background-color: #7AA96B;
+ color: white;
+}
+
+.keyboard_row button.there {
+ background-color: #C3B671;
+ color: white;
+}
+
+.keyboard_row button.wrong {
+ background-color: #282828;
+ color: white;
+}
+
+
+/* Black overlay with a darker background */
+.overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.95); /* Darker black background */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0; /* Hidden by default */
+ z-index: 1000; /* Ensure it's above other content */
+ transition: opacity 0.5s ease; /* Smooth fade-in transition */
+}
+
+.overlay-win {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0; /* Hidden by default */
+ z-index: 1000; /* Ensure it's above other content */
+ transition: opacity 0.5s ease; /* Smooth fade-in transition */
+}
+
+
+/* Fade-in effect */
+.overlay.fade-in {
+ opacity: 1; /* Fully visible */
+}
+
+.overlay-win.fade-in {
+ opacity: 1; /* Fully visible */
+}
+
+
+/* Message container */
+.message-container {
+ background-color: white;
+ padding: 30px 40px; /* Increase padding for better spacing */
+ border-radius: 10px;
+ text-align: center;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
+ animation: slide-in 0.5s ease; /* Slide-in effect */
+ max-width: 500px; /* Set a maximum width for the popup */
+ width: 90%; /* Responsive for smaller screens */
+ box-sizing: border-box; /* Include padding in the width */
+}
+
+/* Slide-in animation */
+@keyframes slide-in {
+ from {
+ transform: translateY(-50px); /* Slightly above the center */
+ opacity: 0;
+ }
+ to {
+ transform: translateY(0); /* At the center */
+ opacity: 1;
+ }
+}
+
+/* Message text */
+.message-text {
+ font-family: 'Georgia', serif;
+ font-size: 24px;
+ color: black;
+ margin-bottom: 20px;
+ text-align: center; /* Ensure horizontal centering */
+ line-height: 1.5; /* Improve readability */
+}
+
+/* Reset button */
+/* General button styling (Reset and Home buttons) */
+.reset-button,
+.home-button {
+ font-family: 'Georgia', serif;
+ font-weight: 500;
+ padding: 10px 20px;
+ background-color: white;
+ border: 2px solid black;
+ border-radius: 5px;
+ cursor: pointer;
+ font-size: 16px;
+ display: inline-block; /* Prevent button from stretching */
+ transition: background-color 0.3s ease;
+ margin: 10px 5px; /* Space between buttons */
+}
+
+/* Hover effect for both buttons */
+.reset-button:hover,
+.home-button:hover {
+ background-color: black;
+ color: white;
+}
+
+.darkmode-slider-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.darkmode-slider-toggle {
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 34px;
+}
+
+.darkmode-slider-toggle input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.darkmode-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.darkmode-slider:before {
+ position: absolute;
+ content: "";
+ height: 26px;
+ width: 26px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.darkmode-slider-toggle input:checked + .darkmode-slider {
+ background-color: black;
+}
+
+.darkmode-slider-toggle input:checked + .darkmode-slider:before {
+ transform: translateX(26px);
+}
+
+.challenge-slider-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+
+
+.challenge-slider-toggle {
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 34px;
+}
+
+.challenge-slider-toggle input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.challenge-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.challenge-slider:before {
+ position: absolute;
+ content: "";
+ height: 26px;
+ width: 26px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.challenge-slider-toggle input:checked + .challenge-slider {
+ background-color: black;
+}
+
+.challenge-slider-toggle input:checked + .challenge-slider:before {
+ transform: translateX(26px);
+}
+
+
+
+#keyboard_container.grey-mode button {
+ background-color: grey !important;
+ color: white !important;
+}
+
+#keyboard_container.grey-mode button.right{
+ background-color: #7AA96B !important;
+ color: white !important;
+}
+
+#keyboard_container.grey-mode button.there{
+ background-color: #C3B671 !important;
+ color: white !important;
+}
+
+@keyframes bounce {
+ 0%, 20%, 50%, 80%, 100% {
+ transform: translateY(0);
+ }
+ 40% {
+ transform: translateY(-10px);
+ }
+ 60% {
+ transform: translateY(-5px);
+ }
+}
+
+.bounce {
+ animation: bounce 0.5s ease-in-out;
+}
+
+
+.sound-slider-container {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.sound-slider-toggle {
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 34px;
+}
+
+.sound-slider-toggle input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.sound-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ transition: 0.4s;
+ border-radius: 34px;
+}
+
+.sound-slider:before {
+ position: absolute;
+ content: "";
+ height: 26px;
+ width: 26px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+.sound-slider-toggle input:checked + .sound-slider {
+ background-color: black;
+}
+
+.sound-slider-toggle input:checked + .sound-slider:before {
+ transform: translateX(26px);
+}
diff --git a/EC327_Hangle_COMPLETED/3_medmode.html b/EC327_Hangle_COMPLETED/3_medmode.html
new file mode 100644
index 0000000000000000000000000000000000000000..32e50b34ca451811422ef2115226d11bcc45d257
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_medmode.html
@@ -0,0 +1,170 @@
+
+
+
+
+
+ Basic Web Project
+
+
+
+
+
+
+
+
+
+
+
+
+ ×
+
Guide
+
Here's everything you need to know to get started.
+
+
The goal is to guess the hidden word by selecting letters.
+
Each time you guess a letter, the game will provide feedback on your guess
+
+
+
+ Green: The letter is correct and in the correct position.
+
+
Yellow: The letter is in the word but in the wrong position.
+
Gray: The letter is not in the word.
+
+
+ Each wrong guess adds a piece to the hangman.
+
+
+
+ If you guess all the letters correctly, you win!
+
+
+
+
Challenge Mode
+
+
In Challenge Mode, letters you've guessed incorrectly won't turn gray, so you'll need to remember your guesses as you play.
+
+
+
+
+
+
+
+
+
+ ×
+
Settings
+
Make this game your own
+
+
Sound
+
+
+
+
+
Prefer a quieter experience? Toggle sound settings.
+
+
Dark Mode
+
+
+
+
+
Dark mode for a relaxed gaming experience.
+
+
+
Challenge Mode
+
+
+
+
+
Remember the letters you've already guessed wrong.
+
+
+
+
+
+
+
+
+
+
+ ×
+
Hint
+
Follow these tips to make the most of your hints
+
+
You can reveal a letter by clicking "Reveal a Letter".
+
Use "Additional Life" to reduce your penalty chances.
+
Plan your guesses strategically before using hints.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EC327_Hangle_COMPLETED/3_medmode.js b/EC327_Hangle_COMPLETED/3_medmode.js
new file mode 100644
index 0000000000000000000000000000000000000000..e9c4511681e40ee7af52fafa1b139a78469c4734
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_medmode.js
@@ -0,0 +1,941 @@
+const keyboard_container = document.querySelector("#keyboard_container");
+let currentword;
+let max_attempts = 6;
+var gameover = false;
+let wrong_attempts = 0;
+let word_length = 5;
+var spot = 0;
+let currentIndex = 1;
+let correct_word = 0;
+
+window.onload = function() {
+ initialize();
+}
+
+/**
+ * Initializes the Hangle game by setting up the word to guess, creating the game UI,
+ * and enabling user interaction through an on-screen keyboard and physical keyboard inputs.
+ *
+ * [Long Description]
+ * This function sets up the initial game state. It selects a random word and prepares
+ * a visual representation of the word as tiles in the game UI. It also dynamically
+ * generates an on-screen keyboard, allowing users to input guesses by clicking buttons
+ * or pressing keys on a physical keyboard. The function includes event listeners to
+ * handle typing interactions and maintains synchronization between on-screen and physical
+ * keyboard inputs.
+ *
+ * Key Steps:
+ * 1. Selects a random word and hint from a predefined list (`easy_word`).
+ * 2. Creates blank tiles corresponding to the letters of the selected word.
+ * 3. Dynamically generates an on-screen keyboard for user interaction.
+ * 4. Binds physical keyboard events to match the on-screen keyboard functionality.
+ *
+ * @global {Array} easy_word - An array of objects containing words and hints for the game.
+ * Each object has the structure: `{ word: string, hint: string }`.
+ * @global {HTMLElement} keyboard_container - The DOM element where the keyboard is rendered.
+ * @global {number} word_length - The length of the word to guess.
+ * @global {function} input - A callback function that processes user input for letter guesses.
+ * @global {function} updateRemoveBodyPartButton - Updates the initial state of controls (e.g., remove body part button).
+ *
+ * @throws {Error} Throws an error if any of the global dependencies (`easy_word`, `keyboard_container`, `input`) are undefined.
+ *
+ * @example
+ * // Basic usage of the initialize function to start the game:
+ * initialize();
+ *
+ * @see input - The function handling user guesses and game logic.
+ * @see updateRemoveBodyPartButton - The function managing the state of hangman-related controls.
+ *
+ *
+ * @see Game Development Tutorial - Great Day Designs
+ * @see Hangman Game Tutorial - Kenny Yip Coding
+ *
+ */
+
+function initialize() {
+ const getRandomWord = () => {
+ const { word, hint } = med_word[Math.floor(Math.random() * med_word.length)];
+ const new_hint = hint.replace(/\.$/, "");
+ currentword = word.toUpperCase();
+ // Remove automatic hint display
+ };
+
+ getRandomWord();
+ updateRemoveBodyPartButton(); // Initial button state
+
+ const tile_category = document.querySelector(".display");
+ tile_category.innerHTML = "";
+
+ // Create HangMan Space
+ for (let i = 0; i < word_length; i++) {
+ const tile = document.createElement("li");
+ tile.id = i.toString();
+ tile.classList.add("letter");
+ tile.innerText = "";
+ tile_category.appendChild(tile);
+ }
+
+
+ /// This is for typing the words in the boxes
+ const rows = [
+ "qwertyuiop".split(""),
+ "asdfghjkl".split(""),
+ [{ char: "↵", key: "enter" }, ..."zxcvbnm".split(""), { char: "⌫", key: "backspace" }],
+ ];
+
+
+
+ /// This is for typing the words in the boxes
+
+ rows.forEach((row) => {
+ const keyboard_row = document.createElement("div"); // Create a row container
+ keyboard_row.classList.add("keyboard_row");
+
+ row.forEach((item) => {
+ const button = document.createElement("button");
+
+ if (typeof item === "string") {
+ button.innerText = item.toUpperCase();
+ button.dataset.key = item;
+ } else {
+ button.innerText = item.char;
+ button.dataset.key = item.key;
+ }
+
+ button.addEventListener("click", () => {
+ input(button.dataset.key);
+ });
+
+ keyboard_row.appendChild(button);
+ });
+
+ keyboard_container.appendChild(keyboard_row);
+ });
+
+ // Typing with keys
+ document.addEventListener("keyup", (e) => {
+
+ const keyPressed = e.key.toLowerCase();
+ console.log("Key pressed:", keyPressed);
+
+ let button = document.querySelector(`button[data-key="${keyPressed}"]`);
+
+ if (!button) {
+ if (e.key === "Enter") {
+ button = document.querySelector(`button[data-key="enter"]`);
+ } else if (e.key === "Backspace") {
+ button = document.querySelector(`button[data-key="backspace"]`);
+ }
+ }
+
+ if (button) {
+ button.click();
+ } else {
+ console.log("No matching button found for:", keyPressed);
+ }
+ });
+}
+
+/**
+*
Toggles the sound setting based on the state of the sound slider (checkbox).
+* This function reads the state of the sound slider, stores it in `localStorage`,
+* and allows persistence of the user's sound preference across sessions.
+*
Key functionality:
+*
+*
If the slider is checked, sound is enabled
+*
If the slider is unchecked, sound is disabled.
+*
+*
+*
The state of the sound preference is saved in `localStorage` with the key `soundEnabled`.
+*
+* Example usage:
+* toggleSound(); // Saves the sound setting (enabled or disabled)
+* @return void - The assigned function does not return any value.
+* @since 2024-12-09
+*/
+function toggleSound() {
+ const soundEnabled = document.getElementById('sound-slider').checked;
+ localStorage.setItem('soundEnabled', soundEnabled); // Save the state
+}
+
+/**
+ * Loads the user's sound preference from `localStorage` and applies it to the sound slider.
+ *
+ * This function checks the `localStorage` for the user's saved sound preference under the key
+ * soundEnabled. If no preference is found (value is null), it defaults
+ * to enabling sound and saves this default state back to `localStorage`. The function then updates
+ * the state of the sound slider on the webpage based on the retrieved or default preference.
+ *
+ *
+ *
Retrieves Preference: Reads the soundEnabled key from `localStorage`.
+ *
Defaults to Sound ON: If no preference exists, sets soundEnabled to true.
+ *
Updates UI: Reflects the preference in the sound slider's checked state.
+ *
+ *
+ * @example:
+ * loadSoundPreference(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function loadSoundPreference() {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled'));
+
+ if (soundEnabled !== null) {
+ // Set the slider and the sound state based on localStorage
+ document.getElementById('sound-slider').checked = soundEnabled;
+ } else {
+ // Default to sound ON if no preference is saved
+ localStorage.setItem('soundEnabled', true);
+ document.getElementById('sound-slider').checked = true;
+ }
+}
+
+// Attach the event listener for the sound slider toggle
+document.getElementById('sound-slider').addEventListener('change', toggleSound);
+
+// Load the sound preference on page load
+document.addEventListener('DOMContentLoaded', loadSoundPreference);
+
+/**
+ * Allows sound to play, grabbing the specific sound file from its path, when soundEnabled is true.
+ *
+ * This function checks the when sound is enabled. If sound is enabled the function plays the audio.
+ * If sound is not enabled it logs it to the console saying "Sound is disabled".
+ *
+ *
+ *
sound is enabled sound plays
+ *
sound is disabled sound does not play
+ *
+ *
+ * @example:
+ * playSound(audioPath); // Loads and applies the user's sound preference on page load.
+ * @param audioPath - write audio path in string
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function playSound(audioPath) {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled')); // Check the current sound state
+ if (soundEnabled) {
+ const audio = new Audio(audioPath);
+ audio.play();
+ } else {
+ console.log("Sound is disabled.");
+ }
+}
+
+/**
+ * Processes user input and updates the game state based on the key pressed.
+ *
+ * [Long Description]
+ * This function handles user input during gameplay. Depending on the key pressed,
+ * it performs one of the following actions:
+ * 1. **Backspace**: Clears the most recent unlocked tile and updates the current spot.
+ * 2. **Enter**: Initiates the process to check the current word or letter against the answer.
+ * 3. **Letter Key**: Fills the first available unlocked tile with the pressed letter.
+ *
+ * The function also ensures that no actions are performed if the game is over.
+ * It plays a click sound for every input using the `playSound` function.
+ *
+ * @param {string} keyPressed - The key that was pressed by the user. Can be one of the following:
+ * - `"backspace"`: Deletes the most recent input in an unlocked tile.
+ * - `"enter"`: Triggers the letter/word check process.
+ * - Any other string representing a letter: Fills an available tile with the letter.
+ *
+ * @global {boolean} gameover - A flag indicating whether the game has ended. Prevents further input if `true`.
+ * @global {function} playSound - A function that plays a specified sound file.
+ * @global {number} spot - Tracks the current position for the next input in the tiles.
+ * @global {number} word_length - The length of the word to guess, used to iterate over tiles.
+ *
+ * @throws {Error} Throws an error if the global variables (`gameover`, `spot`, or `word_length`) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * input("a"); // Fills the next available tile with "A".
+ * input("backspace"); // Clears the last input from an unlocked tile.
+ * input("enter"); // Initiates letter/word check logic.
+ *
+ * @see checkletter - The function called when "enter" is pressed to validate the current word/letter.
+ * @see playSound - The function used to play sound effects.
+ *
+ * */
+const input = (keyPressed) => {
+ if (gameover) return;
+ playSound('sounds/click.wav');
+ if (keyPressed == "backspace") {
+
+ for (let i=spot-1; i>=0; i--) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock) {
+ currtile.innerText = "";
+ spot = i;
+ break;
+ }
+
+ }
+ }
+
+ else if (keyPressed == "enter") {
+ checkletter();
+
+
+ }
+
+ else {
+ for (let i = 0; i < word_length; i++) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock && currtile.innerText === "") {
+ currtile.innerText = keyPressed.toUpperCase();
+ spot = i + 1;
+ break;
+ }
+ }
+ }
+
+}
+
+/**
+ * Validates the user's guess by comparing it with the correct word and updates the game state accordingly.
+ *
+ * [Long Description]
+ * This function checks whether all the tiles have been filled with letters before validating the guess.
+ * If any tile is empty, it prompts the user to fill all spots. If the tiles are filled, it evaluates each
+ * letter against the target word (`currentword`) and updates the game state:
+ *
+ * 1. Correct guesses (letters in the correct position) are marked with the "right" class.
+ * 2. Incorrectly positioned but valid letters are marked with the "there" class.
+ * 3. Invalid letters (not in the word) are marked with the "wrong" class.
+ *
+ * Additionally, it tracks the number of incorrect guesses, updates the hangman display, and manages
+ * the game's end state by calling `checkgameover`. The keyboard buttons are dynamically updated to
+ * reflect the accuracy of the user's guesses.
+ *
+ * @global {string} currentword - The word the player is trying to guess.
+ * @global {number} correct_word - The count of correctly guessed letters in the correct positions.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of allowed wrong guesses before game over.
+ * @global {function} updatehangman - Updates the hangman figure based on incorrect attempts.
+ * @global {function} updateRemoveBodyPartButton - Manages the state of the "remove body part" button.
+ * @global {function} resetboard - Resets the tile board for the next round.
+ * @global {function} checkgameover - Checks if the game is over due to winning or exceeding maximum attempts.
+ *
+ *
+ * @example
+ * // Example usage:
+ * checkletter();
+ * // Output:
+ * // - Updates the tile and keyboard button states based on the user's guess.
+ * // - Logs incorrect attempts or success status to the console.
+ *
+ * @see updatehangman - Handles the visual display of the hangman figure.
+ * @see checkgameover - Manages the game's end state based on current progress.
+ *
+ * @note This logic was developed with assistance from ChatGPT to ensure accuracy and clarity.
+ *
+ */
+function checkletter() {
+
+ let spotsfilled = true;
+
+ for (let i =0; i {
+ currtile.classList.add("bounce");
+
+ // Remove the animation class after it ends
+ currtile.addEventListener("animationend", () => {
+ currtile.classList.remove("bounce");
+ });
+ }, i * 150); // Stagger delay by 150ms per tile
+ }
+}
+
+/**
+ * Checks if the game is over and handles end-of-game actions accordingly.
+ *
+ * [Long Description]
+ * This function determines whether the game has ended based on the player's most recent guess.
+ * If the guess was correct and the game is won, it sets the game state to "over," displays a
+ * winning message, animates the tiles, plays a victory sound, and launches confetti. If the
+ * number of incorrect attempts reaches or exceeds the maximum allowed, it ends the game,
+ * displays a losing message, and plays a failure sound.
+ *
+ * @param {boolean} incorrectGuess - Indicates whether the last guess was incorrect.
+ * If `true`, the game checks if the maximum attempts have been exceeded.
+ *
+ * @global {boolean} gameover - A flag that indicates if the game has ended. This is set to `true` when the game is over.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of incorrect guesses allowed before the game ends.
+ * @global {string} currentword - The word the player was trying to guess, used in the losing message.
+ * @global {function} animateTiles - Animates the tiles when the game is won.
+ * @global {function} displayMessage - Displays a message to the player indicating the game's outcome.
+ * @global {function} playSound - Plays a sound file corresponding to the game's outcome (win or lose).
+ *
+ * @throws {Error} Throws an error if any required global variables (`gameover`, `wrong_attempts`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * checkgameover(false); // Handles the "win" scenario if no incorrect guess.
+ * checkgameover(true); // Checks if the player has exceeded the maximum allowed incorrect attempts.
+ *
+ * @see animateTiles - For handling tile animations upon winning.
+ * @see displayMessage - For managing game status messages.
+ * @see confetti - Used to trigger confetti effects for celebrations.
+ *
+ */
+function checkgameover(incorrectGuess) {
+
+ if (!incorrectGuess) {
+ gameover = true;
+ console.log("good!")
+ displaymessage("You Win!", true, true)
+ animateTiles();
+ playSound('sounds/win.wav');
+ confetti({
+ particleCount: 150, // Number of confetti pieces
+ spread: 70, // Spread angle of confetti
+ origin: { y: 0.6 }, // Confetti drop point
+ colors: ['#bb0000', '#ffffff', '#00bb00'] // Custom colors
+ });
+ return;
+ }
+
+ if (wrong_attempts >= max_attempts) {
+ gameover = true;
+ console.log("bad");
+ displaymessage(`Game Over! The word was: ${currentword}`);
+ playSound('sounds/lose.wav');
+ return;
+ }
+ }
+
+
+
+/**
+ * Displays a message overlay on the screen with optional reset and home buttons.
+ *
+ * [Long Description]
+ * This function creates and displays an overlay message on the screen. It includes a customizable
+ * message and optional buttons for resetting the game and navigating to the home page. The overlay
+ * is styled dynamically based on whether the game was won or lost. The "Play Again" button reloads
+ * the page to restart the game, while the "Go Home" button redirects to the main page.
+ *
+ * A fade-in animation is triggered after the overlay is appended to the DOM for a smooth visual effect.
+ *
+ * @param {string} message - The message to display on the overlay.
+ * @param {boolean} [showResetButton=true] - Determines whether the "Play Again" button is displayed.
+ * @param {boolean} [isWin=false] - Specifies whether the game was won, which affects the overlay's style.
+ *
+ * @example
+ * // Display a winning message with reset and home buttons:
+ * displayMessage("You Win!", true, true);
+ *
+ * // Display a losing message without a reset button:
+ * displayMessage("Game Over! The word was: CAT", false);
+ *
+ * @see location.reload - Used to reload the page for restarting the game.
+ * @see window.location.href - Redirects to the specified home page URL.
+ *
+ */
+
+ function displaymessage(message, showResetButton = true, isWin = false) {
+ // Create the black overlay
+ const overlay = document.createElement("div");
+ overlay.classList.add(isWin ? "overlay-win" : "overlay");
+
+ // Create the message container
+ const messageContainer = document.createElement("div");
+ messageContainer.classList.add("message-container");
+
+ // Add the message text
+ const messageText = document.createElement("p");
+ messageText.classList.add("message-text");
+ messageText.innerText = message;
+ messageContainer.appendChild(messageText);
+
+ // Add the reset button
+ if (showResetButton) {
+ const resetButton = document.createElement("button");
+ resetButton.classList.add("reset-button");
+ resetButton.innerText = "Play Again";
+ resetButton.addEventListener("click", () => {
+ location.reload(); // Reload the page to restart the game
+ });
+ messageContainer.appendChild(resetButton);
+ }
+
+ // Add the Home button
+ const homeButton = document.createElement("button");
+ homeButton.classList.add("home-button");
+ homeButton.innerText = "Go Home";
+ homeButton.addEventListener("click", () => {
+ window.location.href = "1_mainpage.html"; // Redirect to the home page
+ });
+ messageContainer.appendChild(homeButton);
+
+ // Append the container to the overlay
+ overlay.appendChild(messageContainer);
+
+ // Append the overlay to the body
+ document.body.appendChild(overlay);
+
+ setTimeout(() => {
+ overlay.classList.add("fade-in");
+ }, 10);
+}
+
+/**
+ * Resets the letter tiles on the board for the next round of the game.
+ *
+ * [Long Description]
+ * This function clears the text and resets the styles for all letter tiles that
+ * are not marked as "right" (correctly guessed letters). It ensures that only
+ * unlocked tiles (tiles without the "right" class) are cleared, while maintaining
+ * the state of correctly guessed tiles. Additionally, it removes the "there"
+ * class from all tiles, resetting their visual state.
+ *
+ * Key Features:
+ * - Clears the `innerText` of tiles that are not locked as correct.
+ * - Removes the "there" class from all tiles.
+ * - Resets the `spot` tracker to 0, indicating the starting position for input in the next round.
+ *
+ * @global {number} word_length - The length of the word being guessed, used to determine the number of tiles.
+ * @global {number} spot - Tracks the current position for the next input. This is reset to 0 by this function.
+ *
+ * @example
+ * // Reset the board for a new round:
+ * resetboard();
+ *
+ * @see spot - Resets the spot tracker for the next round of inputs.
+ * @since 2024-12-09
+ */
+function resetboard() {
+ for (let i = 0; iThis function manages the visual representation of incorrect guesses by progressively
+ * revealing parts of the hangman figure. Each time an incorrect guess is made, the opacity
+ * of the next body part image in the sequence is set to 1, making it visible. The function
+ * keeps track of the current index of the body parts and ensures that it does not exceed the
+ * total number of body parts available.
+ *
+ *
+ *
Increment Index: The function increments the `currentIndex` to keep track
+ * of which body part should be revealed next.
+ *
Reveal Body Part: The next body part image in the sequence is revealed
+ * by changing its opacity.
+ *
Boundary Check: Ensures that no more body parts are revealed after the
+ * last image in the sequence.
+ *
+ *
+ * @global {NodeList} images - A collection of elements representing the hangman body parts.
+ * These elements are queried from the DOM using the `.body-part` class.
+ * @global {number} currentIndex - Tracks the current body part being revealed. Incremented with
+ * each incorrect guess.
+ *
+ * @throws {Error} Throws an error if the `images` NodeList is undefined or `currentIndex` exceeds its length.
+ *
+ * @example
+ * // Example usage:
+ * updatehangman();
+ * // Output:
+ * // - Reveals the next body part in the sequence by making it visible.
+ *
+ * @since 2024-12-09
+ */
+function updatehangman() {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex < images.length) {
+ images[currentIndex].style.opacity = 1; // Show the next image
+ currentIndex++;
+ }
+}
+
+/**
+ * Redirects the user to the main page when the "Home" link is clicked.
+ *
+ *
This function listens for a click event on the element with the ID `Home-link`. Upon clicking,
+ * the user is redirected to the "1_mainpage.html" page. It is primarily used for navigation purposes
+ * within the application.
+ * toggles darkmode on and off and saves the data into {@code localStorage} object, which is
+ * then stored in the web storage API
+ *
+ *
+ * This function toggles the darkmode class on the {@code document.body} element,
+ * which typically applies or removes dark mode styling. It also updates the {@code localStorage}
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ * @example:
+ * toggleDarkMode(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see document.body
+ * @since 2024-12-09
+ */
+function toggleDarkMode() {
+ const darkModeEnabled = document.body.classList.toggle('darkmode');
+ localStorage.setItem('darkModeEnabled', darkModeEnabled); // Save the state
+}
+
+/**
+ * Toggles the dark mode on or off and saves the current state in localStorage.
+ *
+ * This function toggles the darkmode class on the document.body element,
+ * which typically applies or removes dark mode styling. It also updates the localStorage
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ *
+ * @example usage:
+ * toggleDarkMode(); // Toggles dark mode and saves the state
+ *
+ * @return void - This function does not return any value.
+ * @see localStorage
+ * @see document.body
+ */
+function loadDarkModePreference() {
+ const darkModeEnabled = JSON.parse(localStorage.getItem('darkModeEnabled'));
+
+ if (darkModeEnabled) {
+ // Apply dark mode if it was enabled
+ document.body.classList.add('darkmode');
+ document.getElementById('darkmode-slider').checked = true; // Set the slider to ON
+ } else {
+ // Ensure light mode if dark mode was not enabled
+ document.body.classList.remove('darkmode');
+ document.getElementById('darkmode-slider').checked = false; // Set the slider to OFF
+ }
+}
+
+// Attach the event listener for the dark mode slider toggle
+document.getElementById('darkmode-slider').addEventListener('change', toggleDarkMode);
+
+// Load the dark mode preference on page load
+document.addEventListener('DOMContentLoaded', loadDarkModePreference);
+
+
+const challengeSlider = document.getElementById("challenge-slider");
+const keyboardContainer = document.getElementById("keyboard_container");
+/**
+ *
+ * Toggles the "grey-mode" class on the keyboard container based on the challenge slider's state.
+ *
+ *
+ *
+ *
Checked: Enables "grey-mode" on the keyboard container.
+ *
Unchecked: Disables "grey-mode" and restores default styling.
+ *
+ *
+ * @event change - Triggered when the state of the challenge slider changes (checked/unchecked).
+ *
+ * @param {Event} event - The event triggered when the slider's state changes.
+ *
+ * @global {HTMLElement} challengeSlider - The DOM element representing the challenge slider.
+ * @global {HTMLElement} keyboardContainer - The DOM element containing the keyboard.
+ *
+ * @example
+ * // Example usage:
+ * challengeSlider.addEventListener("change", () => {
+ * if (challengeSlider.checked) {
+ * keyboardContainer.classList.add("grey-mode");
+ * } else {
+ * keyboardContainer.classList.remove("grey-mode");
+ * }
+ * });
+ *
+ * @return {void} - This function does not return a value.
+ * @see keyboardContainer - The target element for the "grey-mode" class.
+ * @see challengeSlider - The slider controlling the challenge mode.
+ * @since 2024-12-09
+ */
+challengeSlider.addEventListener("change", () => {
+ if (challengeSlider.checked) {
+ keyboardContainer.classList.add("grey-mode");
+ } else {
+ keyboardContainer.classList.remove("grey-mode");
+ }
+});
+
+/**
+ * Handles the click event of the "remove-body-part" button to remove a body part image.
+ *
+ *
This function is triggered when the user clicks the "remove-body-part" button. It reduces the visibility
+ * of the most recent body part image (by setting its opacity to 0) and decreases the `wrong_attempts` count.
+ * The button is then disabled and visually updated to indicate it's no longer clickable. If no wrong attempts
+ * are left, the button is hidden.
+ *
+ * @function
+ * @param none
+ * @return void
+ * @see wrong_attempts,currentIndex
+ * @since 2024-12-09
+ */
+document.getElementById('remove-body-part').addEventListener('click', function () {
+ if (wrong_attempts > 0) {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex > 1) {
+ currentIndex--;
+ images[currentIndex].style.opacity = 0;
+ wrong_attempts = Math.max(0, wrong_attempts - 1);
+ console.log(`Body part removed. Remaining wrong attempts: ${max_attempts - wrong_attempts}`);
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+ } else {
+ this.style.display = 'none';
+ }
+});
+
+/**
+ * Adds an event listener to the "reveal-letter" button to reveal a random unrevealed letter from the current word.
+ *
This functionality helps the user by revealing a letter from the target word when the button is clicked.
+ * The revealed letter is displayed in its corresponding tile on the interface and marked as "right."
+ * Additionally, the associated keyboard key is highlighted. Once all letters are revealed,
+ * the game checks for completion, and the "reveal-letter" button is disabled to prevent further use.
+ *
+ *
Revealing a Letter: A random unrevealed letter is selected, displayed on the game tile, and marked as correct.
+ *
Keyboard Highlight: The corresponding keyboard key is updated to indicate it has been used correctly.
+ *
Button State: The "reveal-letter" button is disabled after a letter is revealed to prevent additional usage.
+ *
Game Completion: If all letters are revealed, the game checks for completion.
+ *
Error Handling: If all letters have already been revealed, a message is logged to the console.
+ *
+ *
+ * @function
+ * @since 2024-12-09
+ */
+document.getElementById('reveal-letter').addEventListener('click', function () {
+ const randomIndex = getRandomUnrevealedLetter();
+
+ if (randomIndex !== null) {
+ const currTile = document.getElementById(randomIndex.toString());
+ currTile.innerText = currentword[randomIndex];
+ currTile.classList.add("right");
+ currTile.dataset.lock = "true";
+
+ // Update the keyboard button color
+ const keyButton = document.querySelector(`button[data-key="${currentword[randomIndex].toLowerCase()}"]`);
+ if (keyButton) {
+ keyButton.classList.add("right");
+ }
+
+ correct_word++;
+
+ if (correct_word === word_length) {
+ checkgameover(false);
+ }
+ } else {
+ console.log("All letters have already been revealed.");
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Retrieves the index of a random unrevealed letter from the current word.
+ *
+ *
This function identifies all the tiles representing unrevealed letters and randomly selects
+ * one of them. If all letters have been revealed, it returns `null`. The unrevealed letters are
+ * determined by checking the absence of a `lock` attribute in the dataset of each tile element.
+ *
+ * @function
+ * @param none
+ * @return {number|null} - The index of a random unrevealed letter, or `null` if no letters are left to reveal.
+ * @see word_length
+ * @since 2024-12-09
+ *
+ */
+function getRandomUnrevealedLetter() {
+ const unrevealedIndices = [];
+ // Collect indices of unrevealed letters
+ for (let i = 0; i < word_length; i++) {
+ const currTile = document.getElementById(i.toString());
+ if (!currTile.dataset.lock) {
+ unrevealedIndices.push(i);
+ }
+ }
+ // Shuffle the unrevealed indices
+ if (unrevealedIndices.length > 0) {
+ const randomIndex = Math.floor(Math.random() * unrevealedIndices.length);
+ return unrevealedIndices[randomIndex];
+ }
+ return null; // No letters left to reveal
+}
+
+/**
+ * Displays a hint for the current word when the "show-clue" button is clicked.
+ *
+ *
This method retrieves a hint corresponding to the current word from the `easy_word` array
+ * and displays it in the designated clue area. After displaying the hint, the "show-clue" button
+ * is disabled to prevent multiple uses.
+ *
+ * @function
+ * @return void
+ * @throws Error if the current word is not found in the `easy_word` array.
+ * @see easy_word
+ * @since 2024-12-09
+ */
+document.getElementById('show-clue').addEventListener('click', function() {
+ const clueContent = document.getElementById('clue-content');
+ const hint = med_word.find(item => item.word.toUpperCase() === currentword).hint;
+ clueContent.textContent = hint.replace(/\.$/, "");
+ clueContent.style.display = 'block';
+
+ // Disable the button after use
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Updates the visibility of the "Remove Body Part" button based on the number of wrong attempts.
+ *
+ *
This function checks the value of `wrong_attempts` and adjusts the display style of the
+ * "remove-body-part" button accordingly. The button becomes visible when there is at least one wrong
+ * attempt and is hidden otherwise. This functionality ensures that the button is only accessible
+ * when it is relevant to the game state.
+ *
+ * @function
+ * @return void
+ * @since 2024-12-09
+ */
+function updateRemoveBodyPartButton() {
+ const removeBodyPartButton = document.getElementById('remove-body-part');
+ if (wrong_attempts > 0) {
+ removeBodyPartButton.style.display = 'inline-block';
+ } else {
+ removeBodyPartButton.style.display = 'none';
+ }
+}
+
+module.exports = {
+ initialize,
+ input,
+ checkletter,
+ resetboard,
+ checkgameover,
+ updatehangman,
+};
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/3_medwordbank.js b/EC327_Hangle_COMPLETED/3_medwordbank.js
new file mode 100644
index 0000000000000000000000000000000000000000..1173a196858975b09ed75824a85cfff9fe5c1a0e
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_medwordbank.js
@@ -0,0 +1,120 @@
+const med_word = [
+ { word: "apple", hint: "A sweet fruit that keeps the doctor away." },
+ { word: "bread", hint: "A staple food made from flour and water." },
+ { word: "grape", hint: "A small fruit that comes in bunches." },
+ { word: "clock", hint: "It tells you the time throughout the day." },
+ { word: "piano", hint: "A musical instrument with keys." },
+ { word: "chair", hint: "You sit on it for comfort." },
+ { word: "flame", hint: "A visible part of a fire." },
+ { word: "table", hint: "Furniture with a flat top surface." },
+ { word: "cloud", hint: "White and fluffy, floating in the sky." },
+ { word: "light", hint: "It brightens up the dark." },
+ { word: "stone", hint: "Hard and found on the ground." },
+ { word: "water", hint: "Essential for life and found in rivers." },
+ { word: "truck", hint: "A vehicle used to transport goods." },
+ { word: "dance", hint: "A movement to music." },
+ { word: "flute", hint: "A wind instrument that makes music." },
+ { word: "lemon", hint: "A yellow citrus fruit." },
+ { word: "smile", hint: "A facial expression of happiness." },
+ { word: "bread", hint: "A baked food often used for sandwiches." },
+ { word: "plant", hint: "Green and grows in soil." },
+ { word: "candy", hint: "A sweet treat enjoyed by many." },
+ { word: "house", hint: "A place where people live." },
+ { word: "grass", hint: "It covers the ground and is green." },
+ { word: "field", hint: "An open area of land." },
+ { word: "river", hint: "Flows into lakes or oceans." },
+ { word: "night", hint: "The time when it is dark." },
+ { word: "arrow", hint: "A pointed weapon or direction sign." },
+ { word: "cycle", hint: "A repeated sequence of events." },
+ { word: "beach", hint: "Where sand meets the sea." },
+ { word: "toast", hint: "Bread that has been browned by heat." },
+ { word: "space", hint: "Where the stars and planets exist." },
+ { word: "flour", hint: "Used for baking bread and cakes." },
+ { word: "chain", hint: "A series of linked metal rings." },
+ { word: "sheep", hint: "An animal with wool." },
+ { word: "grill", hint: "Used to cook food outdoors." },
+ { word: "glove", hint: "Worn to protect or warm hands." },
+ { word: "steam", hint: "Hot vapor rising from boiling water." },
+ { word: "fruit", hint: "Sweet and grows on trees or plants." },
+ { word: "smoke", hint: "Rises from fire or a chimney." },
+ { word: "leash", hint: "Used to control a dog during a walk." },
+ { word: "zebra", hint: "A black-and-white striped animal." },
+ { word: "stone", hint: "A small piece of rock." },
+ { word: "frost", hint: "Forms on cold surfaces in winter." },
+ { word: "purse", hint: "Used to carry money and small items." },
+ { word: "plane", hint: "Flies high and carries passengers." },
+ { word: "field", hint: "An open space of grass or crops." },
+ { word: "flask", hint: "Used to carry liquids on the go." },
+ { word: "spear", hint: "A long weapon with a sharp tip." },
+ { word: "shade", hint: "Blocks sunlight to keep things cool." },
+ { word: "latch", hint: "Keeps a door closed securely." },
+ { word: "plant", hint: "Grows and thrives in sunlight." },
+ { word: "berry", hint: "Small, juicy fruit often red or blue." },
+ { word: "daisy", hint: "A flower with white petals and a yellow center." },
+ { word: "flint", hint: "A hard stone used to start fires." },
+ { word: "cream", hint: "Thick and rich, often on desserts." },
+ { word: "spice", hint: "Adds flavor and aroma to food." },
+ { word: "crown", hint: "Worn by kings and queens." },
+ { word: "eagle", hint: "A bird with sharp eyes and strong wings." },
+ { word: "grape", hint: "A small fruit that grows in clusters." },
+ { word: "torch", hint: "Used to light the way in darkness." },
+ { word: "flame", hint: "The glowing part of a fire." },
+ { word: "pouch", hint: "A small bag for carrying items." },
+ { word: "paint", hint: "Used to add color to surfaces." },
+ { word: "frost", hint: "White ice crystals on cold mornings." },
+ { word: "drift", hint: "To move slowly with the wind or water." },
+ { word: "cliff", hint: "A steep rock face near water." },
+ { word: "shell", hint: "Protective cover for some animals." },
+ { word: "honey", hint: "Sweet and made by bees." },
+ { word: "brick", hint: "A block used for building walls." },
+ { word: "storm", hint: "Rain, wind, and thunder combined." },
+ { word: "teeth", hint: "Used for chewing food." },
+ { word: "arrow", hint: "A symbol or weapon with a pointed tip." },
+ { word: "shark", hint: "A predator in the ocean." },
+ { word: "vivid", hint: "Bright and full of color." },
+ { word: "spoon", hint: "Used to eat soup or cereal." },
+ { word: "orbit", hint: "The path of a planet or moon." },
+ { word: "giant", hint: "Very large and powerful." },
+ { word: "piano", hint: "An instrument with black and white keys." },
+ { word: "raven", hint: "A large black bird with a cawing sound." },
+ { word: "bread", hint: "A staple food made from dough." },
+ { word: "charm", hint: "A small object thought to bring luck." },
+ { word: "cable", hint: "Used to transmit electricity or data." },
+ { word: "apple", hint: "A fruit often red or green." },
+ { word: "fence", hint: "A barrier around a yard or field." },
+ { word: "glass", hint: "Transparent and used in windows." },
+ { word: "loyal", hint: "Faithful and trustworthy." },
+ { word: "grape", hint: "A fruit used to make wine." },
+ { word: "pride", hint: "A feeling of deep satisfaction." },
+ { word: "shiny", hint: "Reflects light brightly." },
+ { word: "beast", hint: "A wild and dangerous animal." },
+ { word: "scent", hint: "A smell, often pleasant." },
+ { word: "brick", hint: "A building block made of clay." },
+ { word: "plant", hint: "Grows from soil and needs water." },
+ { word: "smoke", hint: "Rises from fire or chimneys." },
+ { word: "weave", hint: "To make fabric by crossing threads." },
+ { word: "stone", hint: "A hard mineral from the earth." },
+ { word: "flame", hint: "Part of a fire that glows and burns." },
+ { word: "crown", hint: "Worn by royalty as a symbol of power." },
+ { word: "shrub", hint: "A small bushy plant." },
+ { word: "harsh", hint: "Rough or unpleasant to experience." },
+ { word: "bench", hint: "A long seat often found in parks." },
+ { word: "clash", hint: "A conflict or disagreement." },
+ { word: "flask", hint: "A container for holding liquids." },
+ { word: "steam", hint: "Hot vapor rising from boiling water." },
+ { word: "spark", hint: "A small burst of fire or light." },
+ { word: "grill", hint: "Used for cooking food over a flame." },
+ { word: "ridge", hint: "A long, narrow hilltop." },
+ { word: "dream", hint: "Thoughts and visions while asleep." },
+ { word: "plank", hint: "A flat piece of wood or material." },
+ { word: "chill", hint: "A feeling of coldness." },
+ { word: "vowel", hint: "A letter like A, E, I, O, or U." },
+ { word: "cliff", hint: "A steep rock face, often near the sea." },
+ { word: "brick", hint: "Used for construction and building walls." },
+ { word: "ocean", hint: "A vast body of saltwater." },
+ { word: "flute", hint: "A wind instrument with holes to play." },
+ { word: "giant", hint: "Something very large or huge." },
+ { word: "flour", hint: "A powder used in baking." },
+ { word: "sheep", hint: "An animal raised for its wool." },
+ { word: "smile", hint: "A happy expression on the face." },
+];
diff --git a/EC327_Hangle_COMPLETED/3_menubar.js b/EC327_Hangle_COMPLETED/3_menubar.js
new file mode 100644
index 0000000000000000000000000000000000000000..1eb104b4a34e792eed381bafff1ff22a78e32c09
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_menubar.js
@@ -0,0 +1,156 @@
+/**
+ * This script handles the opening and closing of the "Guide," "Settings," and "Hints” buttons.
+ *
+ * - Each link (`guideLink`, `settingsLink`, `hintsLink`) opens its corresponding modal when clicked.
+ * - Each modal can be closed via a close button or by clicking outside the modal.
+ */
+
+
+//creates the modals and buttons
+const guideLink = document.getElementById("guide-link");
+const settingsLink = document.getElementById("settings-link");
+const hintsLink = document.getElementById("hints-link")
+
+const guideModal = document.getElementById("guide-modal");
+const settingsModal = document.getElementById("settings-modal");
+const hintsModal = document.getElementById("hints-modal");
+
+
+const closeGuideButton = document.getElementById("close-guide");
+const closeSettingsButton = document.getElementById("close-settings");
+const closeHintsButton = document.getElementById("close-hints");
+
+/**
+ * Adds an event listener to the `guideLink` element to handle click events.
+ *
+ *
When the `guide` element is clicked:
+ *
+ *
Prevents the default behavior of navigating to a new page.
+ *
Displays the guide modal by changing its `display` style to `flex`.
+ *
+ * @return void - The assigned function does not return any value.
+ * @see guideModal
+ */
+
+guideLink.addEventListener("click", (event) => {
+ event.preventDefault(); // Prevent default link behavior
+ guideModal.style.display = "flex"; // Show modal
+});
+
+/**
+ *
Adds an event listener to close the `guideLink` element.
+ *
+ *
When the close guide button is clicked, it closes the modal window
+ * @return void - The assigned function does not return any value.
+ * @see guideModal
+ */
+
+closeGuideButton.addEventListener("click", () => {
+ guideModal.style.display = "none"; // Hide modal
+});
+
+/**
+ *
Adds an event listener to the window to handle click events for closing the Settings modal.
+ *
+ *
When a click event occurs outside the modal window:
+ *
+ *
Checks if the click target is the `settingsModal` element.
+ *
If the target is outside the window, hides the modal by setting its display style to `none`.
+ *
+ * @return void - The assigned function does not return any value.
+ * @see guideModal
+ */
+
+window.addEventListener("click", (event) => {
+ if (event.target === guideModal) {
+ guideModal.style.display = "none"; // Hide modal
+ }
+});
+
+/**
+ *
Adds an event listener to the `settingLink` element to handle click events.
+ *
+ *
When the `settings` element is clicked:
+ *
+ *
Prevents the default behavior of navigating to a new page.
+ *
Displays the guide modal by changing its `display` style to `flex`.
+ *
+ * @return void - The assigned function does not return any value.
+ * @see settingsModal
+ */
+settingsLink.addEventListener("click", (event) => {
+ event.preventDefault(); // Prevent default link behavior
+ settingsModal.style.display = "flex"; // Show modal
+});
+
+/**
+ *
Adds an event listener to close the `settingsLink` element.
+ *
+ *
When the close settings button is clicked, it closes the modal window
+ * @return void - The assigned function does not return any value.
+ * @see settingsModal
+ */
+closeSettingsButton.addEventListener("click", () => {
+ settingsModal.style.display = "none"; // Hide modal
+});
+
+/**
+ *
Adds an event listener to the window to handle click events for closing the Settings modal.
+ *
+ *
When a click event occurs outside the modal window:
+ *
+ *
Checks if the click target is the `settingsModal` element.
+ *
If the target is outside the window, hides the modal by setting its display style to `none`.
+ *
+ * @return void - The assigned function does not return any value.
+ * @see settingsModal
+ */
+window.addEventListener("click", (event) => {
+ if (event.target === settingsModal) {
+ settingsModal.style.display = "none"; // Hide modal
+ }
+});
+
+/**
+ *
Adds an event listener to the `hintsLink` element to handle click events.
+ *
+ *
When the `hints` element is clicked:
+ *
+ *
Prevents the default behavior of navigating to a new page.
+ *
Displays the guide modal by changing its `display` style to `flex`.
+ *
+ * @return void - The assigned function does not return any value.
+ * @see hintsModal
+ */
+hintsLink.addEventListener("click", (event) => {
+ event.preventDefault(); // Prevent default link behavior
+ hintsModal.style.display = "flex"; // Show modal
+});
+
+/**
+ *
Adds an event listener to close the `hintsLink` element.
+ *
+ *
When the close hints button is clicked, it closes the modal window
+ * @return void - The assigned function does not return any value.
+ * @see hintsModal
+ */
+closeHintsButton.addEventListener("click", () => {
+ hintsModal.style.display = "none"; // Hide modal
+});
+
+/**
+ *
Adds an event listener to the window to handle click events for closing the Hints modal.
+ *
+ *
When a click event occurs outside the modal window:
+ *
+ *
Checks if the click target is the `hintsModal` element.
+ *
If the target is outside the window, hides the modal by setting its display style to `none`.
Here's everything you need to know to get started.
+
+
The goal is to guess the hidden word by selecting letters.
+
Each time you guess a letter, the game will provide feedback on your guess
+
+
+
+ Green: The letter is correct and in the correct position.
+
+
Yellow: The letter is in the word but in the wrong position.
+
Gray: The letter is not in the word.
+
+
+ Each wrong guess adds a piece to the hangman.
+
+
+
+ If you guess all the letters correctly, you win!
+
+
+
+
Challenge Mode
+
+
In Challenge Mode, letters you've guessed incorrectly won't turn gray, so you'll need to remember your guesses as you play.
+
+
+
+
+
+
+
+
+
+ ×
+
Settings
+
Make this game your own
+
+
Sound
+
+
+
+
+
Prefer a quieter experience? Toggle sound settings.
+
+
Dark Mode
+
+
+
+
+
Dark mode for a relaxed gaming experience.
+
+
+
Challenge Mode
+
+
+
+
+
Remember the letters you've already guessed wrong.
+
+
+
+
+
+
+
+
+
+
+ ×
+
Hint
+
Follow these tips to make the most of your hints
+
+
You can reveal a letter by clicking "Reveal a Letter".
+
Use "Additional Life" to reduce your penalty chances.
+
Plan your guesses strategically before using hints.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EC327_Hangle_COMPLETED/3_multihangle.js b/EC327_Hangle_COMPLETED/3_multihangle.js
new file mode 100644
index 0000000000000000000000000000000000000000..abc96887bc8c516453d8e9d2991c0ea129bec6ce
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_multihangle.js
@@ -0,0 +1,987 @@
+/**
+ * Processes the user input for the game, validating the word entered by the user.
+ *
+ * This function retrieves the value entered by the user in the input field with ID
+ * userInput and performs several checks:
+ *
+ *
+ *
Empty Input: If no input is provided, it shows a message prompting the user to enter a valid word.
+ *
Invalid Characters: If the input contains numbers or special characters, it prompts the user to enter a word consisting only of letters.
+ *
Word Length: If the input length exceeds 8 characters, it shows a message restricting the word length to 8 letters.
+ *
+ *
+ * If the input passes all checks, the function:
+ *
+ *
+ *
Sets the currentword to the uppercased version of the input.
+ *
Sets the word_length dynamically based on the length of the input.
+ *
Hides the popup element by setting its display style to "none".
+ *
Initializes the game by calling the initialize() function.
+ *
+ *
+ * @example:
+ * returnText(); // Processes the user input and updates the game state.
+ *
+ * @return void - This function does not return any value.
+ * @see initialize
+ * @see currentword
+ * @see word_length
+ * @since 2024-12-09
+ */
+function returnText() {
+ const input = document.getElementById("userInput").value.trim();
+ const message_category = document.querySelector("p");
+ const letters = /^[A-Za-z]+$/;
+
+ if (input === "" || input == null) {
+ const message_category = document.querySelector("p");
+ message_category.innerHTML = "Make it hard to the other person can't guess it (max 8 letters)";
+ return;
+ }
+
+ else if (!letters.test(input)) {
+ const message_category = document.querySelector("p");
+ message_category.innerHTML = "Really, numbers? Put in a word.";
+ return;
+ }
+
+ else if (input.length > 8) {
+ const message_category = document.querySelector("p");
+ message_category.innerHTML = "Can't be more than 8 letters.";
+ return;
+ }
+
+ currentword = input.toUpperCase();
+ word_length = currentword.length; // Set word length dynamically
+ //console.log("Word Set:", currentword);
+
+ // Hide the popup
+ const popup = document.querySelector(".popup");
+ popup.style.display = "none";
+
+ // Initialize the game
+ initialize();
+}
+
+const keyboard_container = document.querySelector("#keyboard_container");
+let currentword;
+let max_attempts = 6;
+var gameover = false;
+let wrong_attempts = 0;
+let word_length;
+var spot = 0;
+let currentIndex = 1;
+let correct_word = 0;
+
+/**
+*
+* Assigns the returnText function to the window.onload event.
+* This ensures the returnText function executes automatically when the webpage finishes loading.
+*
+* The window.onload event is triggered after all assets
+* (e.g., HTML, CSS, JavaScript, images) are fully loaded.
+* By using this assignment, the returnText function initializes
+* or performs actions required after the page loads.
+* @return void - The assigned function does not return any value.
+* @see {@link window.onload}
+*
+*/
+window.onload = function() {
+ returnText();
+}
+
+/**
+ * Redirects the user to the main page when the "Home" link is clicked.
+ *
+ *
This function listens for a click event on the element with the ID `Home-link`. Upon clicking,
+ * the user is redirected to the "1_mainpage.html" page. It is primarily used for navigation purposes
+ * within the application.
+ *
+ * @function
+ * @param none
+ * @return void
+ * @since 2024-12-09
+ */
+
+document.getElementById('Home-link').addEventListener('click', () => {
+ window.location.href = '1_mainpage.html';
+});
+
+/**
+ * Initializes the Hangle game by setting up the word tiles and the keyboard interface.
+ *
+ * [Long Description]
+ * This function prepares the game UI and functionality, including the following:
+ * - Resets the display for the word tiles and keyboard.
+ * - Dynamically creates tiles for the word to guess and sets them up as interactive elements.
+ * - Generates a virtual keyboard for user input, including special keys ("Enter" and "Backspace").
+ * - Binds event listeners for both virtual and physical keyboards to ensure seamless user interaction.
+ *
+ * Steps:
+ * 1. Clears the existing word display area (`.display`).
+ * 2. Creates blank tiles representing the word, appending them to the display container.
+ * 3. Generates a virtual keyboard with rows of buttons for letters and special keys.
+ * 4. Attaches click listeners to virtual keyboard buttons and binds physical keyboard inputs.
+ *
+ * @global {HTMLElement} tile_category - The DOM container for displaying the word tiles.
+ * @global {HTMLElement} keyboard_container - The DOM container for rendering the virtual keyboard.
+ * @global {function} input - Handles user input for letter guesses.
+ * @global {function} updateRemoveBodyPartButton - Updates the initial state of game controls (e.g., remove body part button).
+ * @global {number} word_length - The length of the word to guess, used to create tiles.
+ *
+ * @throws {Error} Throws an error if required global variables (`tile_category`, `keyboard_container`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * initialize();
+ * // - Resets the game UI and sets up the tiles and keyboard for a new game.
+ *
+ * @see input - Handles user interaction with the keyboard for letter input.
+ * @see updateRemoveBodyPartButton - Manages the state of specific game controls.
+ *
+ * @see Game Development Tutorial - Great Day Designs
+ * @see Hangman Game Tutorial - Kenny Yip Coding
+ *
+ */
+
+function initialize() {
+ const tile_category = document.querySelector(".display");
+ tile_category.innerHTML = "";
+ updateRemoveBodyPartButton()
+
+ // Create HangMan Space
+ for (let i=0; i {
+ const keyboard_row = document.createElement("div"); // Create a row container
+ keyboard_row.classList.add("keyboard_row");
+
+ row.forEach((item) => {
+ const button = document.createElement("button");
+
+ if (typeof item === "string") {
+ button.innerText = item.toUpperCase();
+ button.dataset.key = item;
+ } else {
+ button.innerText = item.char;
+ button.dataset.key = item.key;
+ }
+
+ button.addEventListener("click", () => {
+ input(button.dataset.key);
+ });
+
+ keyboard_row.appendChild(button);
+ });
+
+ keyboard_container.appendChild(keyboard_row);
+ });
+
+ // Typing with keys
+ document.addEventListener("keyup", (e) => {
+
+ const keyPressed = e.key.toLowerCase();
+ console.log("Key pressed:", keyPressed);
+
+ let button = document.querySelector(`button[data-key="${keyPressed}"]`);
+
+ if (!button) {
+ if (e.key === "Enter") {
+ button = document.querySelector(`button[data-key="enter"]`);
+ } else if (e.key === "Backspace") {
+ button = document.querySelector(`button[data-key="backspace"]`);
+ }
+ }
+
+ if (button) {
+ button.click();
+ } else {
+ console.log("No matching button found for:", keyPressed);
+ }
+ });
+}
+
+/**
+*
Toggles the sound setting based on the state of the sound slider (checkbox).
+* This function reads the state of the sound slider, stores it in `localStorage`,
+* and allows persistence of the user's sound preference across sessions.
+*
Key functionality:
+*
+*
If the slider is checked, sound is enabled
+*
If the slider is unchecked, sound is disabled.
+*
+*
+*
The state of the sound preference is saved in `localStorage` with the key `soundEnabled`.
+*
+* Example usage:
+* toggleSound(); // Saves the sound setting (enabled or disabled)
+* @return void - The assigned function does not return any value.
+* @since 2024-12-09
+*/
+function toggleSound() {
+ const soundEnabled = document.getElementById('sound-slider').checked;
+ localStorage.setItem('soundEnabled', soundEnabled); // Save the state
+}
+
+/**
+ * Loads the user's sound preference from `localStorage` and applies it to the sound slider.
+ *
+ * This function checks the `localStorage` for the user's saved sound preference under the key
+ * soundEnabled. If no preference is found (value is null), it defaults
+ * to enabling sound and saves this default state back to `localStorage`. The function then updates
+ * the state of the sound slider on the webpage based on the retrieved or default preference.
+ *
+ *
+ *
Retrieves Preference: Reads the soundEnabled key from `localStorage`.
+ *
Defaults to Sound ON: If no preference exists, sets soundEnabled to true.
+ *
Updates UI: Reflects the preference in the sound slider's checked state.
+ *
+ *
+ * @example:
+ * loadSoundPreference(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function loadSoundPreference() {
+ let soundEnabled = JSON.parse(localStorage.getItem('soundEnabled'));
+
+ if (soundEnabled === null) {
+ // Default to sound ON if no preference is saved
+ soundEnabled = true;
+ localStorage.setItem('soundEnabled', true);
+ }
+
+ // Set the slider and the sound state based on localStorage
+ document.getElementById('sound-slider').checked = soundEnabled;
+}
+
+// Attach the event listener for the sound slider toggle
+document.getElementById('sound-slider').addEventListener('change', toggleSound);
+
+// Load the sound preference on page load
+document.addEventListener('DOMContentLoaded', loadSoundPreference);
+
+/**
+ * Allows sound to play, grabbing the specific sound file from its path, when soundEnabled is true.
+ *
+ * This function checks the when sound is enabled. If sound is enabled the function plays the audio.
+ * If sound is not enabled it logs it to the console saying "Sound is disabled".
+ *
+ *
+ *
sound is enabled sound plays
+ *
sound is disabled sound does not play
+ *
+ *
+ * @example:
+ * playSound(audioPath); // Loads and applies the user's sound preference on page load.
+ * @param audioPath - write audio path in string
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function playSound(audioPath) {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled')); // Check the current sound state
+ if (soundEnabled) {
+ const audio = new Audio(audioPath);
+ audio.play();
+ } else {
+ console.log("Sound is disabled.");
+ }
+}
+
+/**
+ * Processes user input and updates the game state based on the key pressed.
+ *
+ * [Long Description]
+ * This function manages user input during gameplay. Depending on the key pressed, it performs one of the following actions:
+ * 1. **Backspace**: Clears the most recent unlocked tile, updates the `spot` tracker, and exits the loop.
+ * 2. **Enter**: Invokes `checkletter` to validate the current word or letter against the answer.
+ * 3. **Letter Key**: Finds the first available unlocked tile and populates it with the letter, updating `spot` accordingly.
+ *
+ * The function ensures that no actions are taken if the game is over (`gameover` is `true`). It provides auditory feedback for
+ * all key presses using the `playSound` function. Additionally, it handles edge cases such as locked tiles and
+ * ensures no actions occur when all tiles are filled.
+ *
+ * @param {string} keyPressed - The key pressed by the user. Can be one of the following:
+ * - `"backspace"`: Clears the most recent input in an unlocked tile.
+ * - `"enter"`: Triggers the letter/word validation process.
+ * - Any other string representing a letter: Fills the next available tile.
+ *
+ * @global {boolean} gameover - Prevents further input if the game has ended.
+ * @global {function} playSound - Plays a sound to provide auditory feedback for key presses.
+ * @global {number} spot - Tracks the position of the next tile to populate.
+ * @global {number} word_length - Determines the number of tiles in the current word.
+ *
+ *
+ * @example
+ * // Example usage:
+ * input("a"); // Fills the next available tile with "A".
+ * input("backspace"); // Clears the last input in an unlocked tile.
+ * input("enter"); // Validates the user's word or letter.
+ *
+ * @see checkletter - Validates the current word/letter when "enter" is pressed.
+ * @see playSound - Provides auditory feedback for key presses.
+ *
+ */
+const input = (keyPressed) => {
+ if (gameover) return;
+
+ playSound('sounds/click.wav');
+
+ if (keyPressed == "backspace") {
+
+ for (let i=spot-1; i>=0; i--) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock) {
+ currtile.innerText = "";
+ spot = i;
+ break;
+ }
+
+ }
+ }
+
+ else if (keyPressed == "enter") {
+ checkletter();
+
+
+ }
+
+ else {
+ for (let i = 0; i < word_length; i++) {
+ const currtile = document.getElementById(i.toString());
+ if (!currtile.dataset.lock && currtile.innerText === "") {
+ currtile.innerText = keyPressed.toUpperCase();
+ spot = i + 1;
+ break;
+ }
+ }
+ }
+
+}
+
+/**
+ * Validates the user's guess by comparing it with the correct word and updates the game state accordingly.
+ *
+ * [Long Description]
+ * This function checks whether all the tiles have been filled with letters before validating the guess.
+ * If any tile is empty, it prompts the user to fill all spots. If the tiles are filled, it evaluates each
+ * letter against the target word (`currentword`) and updates the game state:
+ *
+ * 1. Correct guesses (letters in the correct position) are marked with the "right" class.
+ * 2. Incorrectly positioned but valid letters are marked with the "there" class.
+ * 3. Invalid letters (not in the word) are marked with the "wrong" class.
+ *
+ * Additionally, it tracks the number of incorrect guesses, updates the hangman display, and manages
+ * the game's end state by calling `checkgameover`. The keyboard buttons are dynamically updated to
+ * reflect the accuracy of the user's guesses.
+ *
+ * @global {string} currentword - The word the player is trying to guess.
+ * @global {number} correct_word - The count of correctly guessed letters in the correct positions.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of allowed wrong guesses before game over.
+ * @global {function} updatehangman - Updates the hangman figure based on incorrect attempts.
+ * @global {function} updateRemoveBodyPartButton - Manages the state of the "remove body part" button.
+ * @global {function} resetboard - Resets the tile board for the next round.
+ * @global {function} checkgameover - Checks if the game is over due to winning or exceeding maximum attempts.
+ *
+ * @throws {Error} Throws an error if any required global variables (`currentword`, `word_length`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * checkletter();
+ * // Output:
+ * // - Updates the tile and keyboard button states based on the user's guess.
+ * // - Logs incorrect attempts or success status to the console.
+ *
+ * @see updatehangman - Handles the visual display of the hangman figure.
+ * @see checkgameover - Manages the game's end state based on current progress.
+ *
+ * @note This logic was developed with assistance from ChatGPT to ensure accuracy and clarity.
+ */
+
+function checkletter() {
+
+ let spotsfilled = true;
+
+ for (let i =0; i {
+ currtile.classList.add("bounce");
+
+ // Remove the animation class after it ends
+ currtile.addEventListener("animationend", () => {
+ currtile.classList.remove("bounce");
+ });
+ }, i * 150); // Stagger delay by 150ms per tile
+ }
+}
+
+
+/**
+ * Checks if the game is over and handles end-of-game actions accordingly.
+ *
+ * [Long Description]
+ * This function determines whether the game has ended based on the player's most recent guess.
+ * If the guess was correct and the game is won, it sets the game state to "over," displays a
+ * winning message, animates the tiles, plays a victory sound, and launches confetti. If the
+ * number of incorrect attempts reaches or exceeds the maximum allowed, it ends the game,
+ * displays a losing message, and plays a failure sound.
+ *
+ * @param {boolean} incorrectGuess - Indicates whether the last guess was incorrect.
+ * If `true`, the game checks if the maximum attempts have been exceeded.
+ *
+ * @global {boolean} gameover - A flag that indicates if the game has ended. This is set to `true` when the game is over.
+ * @global {number} wrong_attempts - The current number of incorrect guesses.
+ * @global {number} max_attempts - The maximum number of incorrect guesses allowed before the game ends.
+ * @global {string} currentword - The word the player was trying to guess, used in the losing message.
+ * @global {function} animateTiles - Animates the tiles when the game is won.
+ * @global {function} displayMessage - Displays a message to the player indicating the game's outcome.
+ * @global {function} playSound - Plays a sound file corresponding to the game's outcome (win or lose).
+ *
+ *
+ * @example
+ * // Example usage:
+ * checkgameover(false); // Handles the "win" scenario if no incorrect guess.
+ * checkgameover(true); // Checks if the player has exceeded the maximum allowed incorrect attempts.
+ *
+ * @see animateTiles - For handling tile animations upon winning.
+ * @see displayMessage - For managing game status messages.
+ * @see confetti - Used to trigger confetti effects for celebrations.
+ *
+ */
+function checkgameover(incorrectGuess) {
+
+ if (!incorrectGuess) {
+ gameover = true;
+ console.log("good!");
+ displaymessage("You Win!", true, true);
+ animateTiles();
+ playSound('sounds/win.wav');
+ confetti({
+ particleCount: 150,
+ spread: 70,
+ origin: { y: 0.6 },
+ colors: ['#bb0000','#ffffff','#00bb00']
+ });
+ return;
+ }
+
+ if (wrong_attempts >= max_attempts) {
+ gameover = true;
+ console.log("bad");
+ displaymessage(`Game Over! The word was: ${currentword}`);
+ playSound('sounds/lose.wav');
+ return;
+ }
+ }
+
+ /**
+ * Displays a message overlay on the screen with optional reset and home buttons.
+ *
+ * [Long Description]
+ * This function creates and displays an overlay message on the screen. It includes a customizable
+ * message and optional buttons for resetting the game and navigating to the home page. The overlay
+ * is styled dynamically based on whether the game was won or lost. The "Play Again" button reloads
+ * the page to restart the game, while the "Go Home" button redirects to the main page.
+ *
+ * A fade-in animation is triggered after the overlay is appended to the DOM for a smooth visual effect.
+ *
+ * @param {string} message - The message to display on the overlay.
+ * @param {boolean} [showResetButton=true] - Determines whether the "Play Again" button is displayed.
+ * @param {boolean} [isWin=false] - Specifies whether the game was won, which affects the overlay's style.
+ *
+ * @example
+ * // Display a winning message with reset and home buttons:
+ * displayMessage("You Win!", true, true);
+ *
+ * // Display a losing message without a reset button:
+ * displayMessage("Game Over! The word was: CAT", false);
+ *
+ * @see location.reload - Used to reload the page for restarting the game.
+ * @see window.location.href - Redirects to the specified home page URL.
+ */
+ function displaymessage(message, showResetButton = true, isWin = false) {
+ // Create the black overlay
+ const overlay = document.createElement("div");
+ overlay.classList.add(isWin ? "overlay-win" : "overlay");
+
+ // Create the message container
+ const messageContainer = document.createElement("div");
+ messageContainer.classList.add("message-container");
+
+ // Add the message text
+ const messageText = document.createElement("p");
+ messageText.classList.add("message-text");
+ messageText.innerText = message;
+ messageContainer.appendChild(messageText);
+
+ // Add the reset button (Play Again)
+ if (showResetButton) {
+ const resetButton = document.createElement("button");
+ resetButton.classList.add("reset-button");
+ resetButton.innerText = "Play Again";
+ resetButton.addEventListener("click", () => {
+ location.reload(); // Reload the page to restart the game
+ });
+ messageContainer.appendChild(resetButton);
+ }
+
+ // Add the Home button (go to home page)
+ const homeButton = document.createElement("button");
+ homeButton.classList.add("home-button");
+ homeButton.innerText = "Go Home";
+ homeButton.addEventListener("click", () => {
+ window.location.href = '1_mainpage.html'; // Redirect to home page
+ });
+ messageContainer.appendChild(homeButton);
+
+ // Append the container to the overlay
+ overlay.appendChild(messageContainer);
+
+ // Append the overlay to the body
+ document.body.appendChild(overlay);
+
+ // Trigger fade-in animation
+ setTimeout(() => {
+ overlay.classList.add("fade-in");
+ }, 10);
+}
+
+
+/**
+ * Resets the letter tiles on the board for the next round of the game.
+ *
+ * [Long Description]
+ * This function clears the text and resets the styles for all letter tiles that
+ * are not marked as "right" (correctly guessed letters). It ensures that only
+ * unlocked tiles (tiles without the "right" class) are cleared, while maintaining
+ * the state of correctly guessed tiles. Additionally, it removes the "there"
+ * class from all tiles, resetting their visual state.
+ *
+ * Key Features:
+ * - Clears the `innerText` of tiles that are not locked as correct.
+ * - Removes the "there" class from all tiles.
+ * - Resets the `spot` tracker to 0, indicating the starting position for input in the next round.
+ *
+ * @global {number} word_length - The length of the word being guessed, used to determine the number of tiles.
+ * @global {number} spot - Tracks the current position for the next input. This is reset to 0 by this function.
+ *
+ * @example
+ * // Reset the board for a new round:
+ * resetboard();
+ *
+ * @see spot - Resets the spot tracker for the next round of inputs.
+ * @since 2024-12-09
+ */
+function resetboard() {
+ for (let i = 0; iThis function manages the visual representation of incorrect guesses by progressively
+ * revealing parts of the hangman figure. Each time an incorrect guess is made, the opacity
+ * of the next body part image in the sequence is set to 1, making it visible. The function
+ * keeps track of the current index of the body parts and ensures that it does not exceed the
+ * total number of body parts available.
+ *
+ *
+ *
Increment Index: The function increments the `currentIndex` to keep track
+ * of which body part should be revealed next.
+ *
Reveal Body Part: The next body part image in the sequence is revealed
+ * by changing its opacity.
+ *
Boundary Check: Ensures that no more body parts are revealed after the
+ * last image in the sequence.
+ *
+ *
+ * @global {NodeList} images - A collection of elements representing the hangman body parts.
+ * These elements are queried from the DOM using the `.body-part` class.
+ * @global {number} currentIndex - Tracks the current body part being revealed. Incremented with
+ * each incorrect guess.
+ *
+ * @throws {Error} Throws an error if the `images` NodeList is undefined or `currentIndex` exceeds its length.
+ *
+ * @example
+ * // Example usage:
+ * updatehangman();
+ * // Output:
+ * // - Reveals the next body part in the sequence by making it visible.
+ *
+ * @since 2024-12-09
+ */
+function updatehangman() {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex < images.length) {
+ images[currentIndex].style.opacity = 1; // Show the next image
+ currentIndex++;
+ }
+}
+
+document.getElementById('Home-link').addEventListener('click', () => {
+ window.location.href = 'index.html';
+});
+
+/**
+ *
+ * toggles darkmode on and off and saves the data into {@code localStorage} object, which is
+ * then stored in the web storage API
+ *
+ *
+ * This function toggles the darkmode class on the {@code document.body} element,
+ * which typically applies or removes dark mode styling. It also updates the {@code localStorage}
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ * @example:
+ * toggleDarkMode(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see document.body
+ * @since 2024-12-09
+ */
+function toggleDarkMode() {
+ const darkModeEnabled = document.body.classList.toggle('darkmode');
+ localStorage.setItem('darkModeEnabled', darkModeEnabled); // Save the state
+}
+
+/**
+ * Toggles the dark mode on or off and saves the current state in localStorage.
+ *
+ * This function toggles the darkmode class on the document.body element,
+ * which typically applies or removes dark mode styling. It also updates the localStorage
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ *
+ * @example usage:
+ * toggleDarkMode(); // Toggles dark mode and saves the state
+ *
+ * @return void - This function does not return any value.
+ * @see localStorage
+ * @see document.body
+ */
+function loadDarkModePreference() {
+ const darkModeEnabled = JSON.parse(localStorage.getItem('darkModeEnabled'));
+
+ if (darkModeEnabled) {
+ // Apply dark mode if it was enabled
+ document.body.classList.add('darkmode');
+ document.getElementById('darkmode-slider').checked = true; // Set the slider to ON
+ } else {
+ // Ensure light mode if dark mode was not enabled
+ document.body.classList.remove('darkmode');
+ document.getElementById('darkmode-slider').checked = false; // Set the slider to OFF
+ }
+}
+
+// Attach the event listener for the dark mode slider toggle
+document.getElementById('darkmode-slider').addEventListener('change', toggleDarkMode);
+
+// Load the dark mode preference on page load
+document.addEventListener('DOMContentLoaded', loadDarkModePreference);
+
+
+const challengeSlider = document.getElementById("challenge-slider");
+const keyboardContainer = document.getElementById("keyboard_container");
+/**
+ *
+ * Toggles the "grey-mode" class on the keyboard container based on the challenge slider's state.
+ *
+ *
+ *
+ *
Checked: Enables "grey-mode" on the keyboard container.
+ *
Unchecked: Disables "grey-mode" and restores default styling.
+ *
+ *
+ * @event change - Triggered when the state of the challenge slider changes (checked/unchecked).
+ *
+ * @param {Event} event - The event triggered when the slider's state changes.
+ *
+ * @global {HTMLElement} challengeSlider - The DOM element representing the challenge slider.
+ * @global {HTMLElement} keyboardContainer - The DOM element containing the keyboard.
+ *
+ * @example
+ * // Example usage:
+ * challengeSlider.addEventListener("change", () => {
+ * if (challengeSlider.checked) {
+ * keyboardContainer.classList.add("grey-mode");
+ * } else {
+ * keyboardContainer.classList.remove("grey-mode");
+ * }
+ * });
+ *
+ * @return {void} - This function does not return a value.
+ * @see keyboardContainer - The target element for the "grey-mode" class.
+ * @see challengeSlider - The slider controlling the challenge mode.
+ * @since 2024-12-09
+ */
+challengeSlider.addEventListener("change", () => {
+ if (challengeSlider.checked) {
+ keyboardContainer.classList.add("grey-mode");
+ } else {
+ keyboardContainer.classList.remove("grey-mode");
+ }
+});
+
+/**
+ * Handles the click event of the "remove-body-part" button to remove a body part image.
+ *
+ *
This function is triggered when the user clicks the "remove-body-part" button. It reduces the visibility
+ * of the most recent body part image (by setting its opacity to 0) and decreases the `wrong_attempts` count.
+ * The button is then disabled and visually updated to indicate it's no longer clickable. If no wrong attempts
+ * are left, the button is hidden.
+ *
+ * @function
+ * @param none
+ * @return void
+ * @see wrong_attempts,currentIndex
+ * @since 2024-12-09
+ */
+document.getElementById('remove-body-part').addEventListener('click', function () {
+ if (wrong_attempts > 0) {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex > 1) {
+ currentIndex--;
+ images[currentIndex].style.opacity = 0;
+ wrong_attempts = Math.max(0, wrong_attempts - 1);
+ console.log(`Body part removed. Remaining wrong attempts: ${max_attempts - wrong_attempts}`);
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+ } else {
+ this.style.display = 'none';
+ }
+});
+
+/**
+ * Adds an event listener to the "reveal-letter" button to reveal a random unrevealed letter from the current word.
+ *
This functionality helps the user by revealing a letter from the target word when the button is clicked.
+ * The revealed letter is displayed in its corresponding tile on the interface and marked as "right."
+ * Additionally, the associated keyboard key is highlighted. Once all letters are revealed,
+ * the game checks for completion, and the "reveal-letter" button is disabled to prevent further use.
+ *
+ *
Revealing a Letter: A random unrevealed letter is selected, displayed on the game tile, and marked as correct.
+ *
Keyboard Highlight: The corresponding keyboard key is updated to indicate it has been used correctly.
+ *
Button State: The "reveal-letter" button is disabled after a letter is revealed to prevent additional usage.
+ *
Game Completion: If all letters are revealed, the game checks for completion.
+ *
Error Handling: If all letters have already been revealed, a message is logged to the console.
+ *
+ *
+ * @function
+ * @since 2024-12-09
+ */
+document.getElementById('reveal-letter').addEventListener('click', function () {
+ const randomIndex = getRandomUnrevealedLetter();
+
+ if (randomIndex !== null) {
+ const currTile = document.getElementById(randomIndex.toString());
+ currTile.innerText = currentword[randomIndex];
+ currTile.classList.add("right");
+ currTile.dataset.lock = "true";
+
+ // Update the keyboard button color
+ const keyButton = document.querySelector(`button[data-key="${currentword[randomIndex].toLowerCase()}"]`);
+ if (keyButton) {
+ keyButton.classList.add("right");
+ }
+
+ correct_word++;
+
+ if (correct_word === word_length) {
+ checkgameover(false);
+ }
+ } else {
+ console.log("All letters have already been revealed.");
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Retrieves the index of a random unrevealed letter from the current word.
+ *
+ *
This function identifies all the tiles representing unrevealed letters and randomly selects
+ * one of them. If all letters have been revealed, it returns `null`. The unrevealed letters are
+ * determined by checking the absence of a `lock` attribute in the dataset of each tile element.
+ *
+ * @function
+ * @param none
+ * @return {number|null} - The index of a random unrevealed letter, or `null` if no letters are left to reveal.
+ * @see word_length
+ * @since 2024-12-09
+ *
+ */
+function getRandomUnrevealedLetter() {
+ const unrevealedIndices = [];
+ // Collect indices of unrevealed letters
+ for (let i = 0; i < word_length; i++) {
+ const currTile = document.getElementById(i.toString());
+ if (!currTile.dataset.lock) {
+ unrevealedIndices.push(i);
+ }
+ }
+ // Shuffle the unrevealed indices
+ if (unrevealedIndices.length > 0) {
+ const randomIndex = Math.floor(Math.random() * unrevealedIndices.length);
+ return unrevealedIndices[randomIndex];
+ }
+ return null; // No letters left to reveal
+}
+
+/**
+ * Updates the visibility of the "Remove Body Part" button based on the number of wrong attempts.
+ *
+ *
This function checks the value of `wrong_attempts` and adjusts the display style of the
+ * "remove-body-part" button accordingly. The button becomes visible when there is at least one wrong
+ * attempt and is hidden otherwise. This functionality ensures that the button is only accessible
+ * when it is relevant to the game state.
Here's everything you need to know to get started:
+
+
The goal is to guess the hidden word by selecting letters.
+
Each time you guess a letter, the game will provide feedback on your guess.
+
+
+
+
Green: The letter is correct and in the correct position.
+
Gray: The letter is not in the word.
+
+
+
Each wrong guess adds a piece to the hangman figure.
+
If you guess all the letters correctly before completing the hangman, you win!
+
+
Challenge Mode:
+
+
In Challenge Mode, letters you've guessed incorrectly won't turn gray, so you'll need to remember your guesses as you play.
+
+
+
+
+
+
+
+
+ ×
+
Settings
+
Make this game your own
+
+
Sound
+
+
+
+
+
Prefer a quieter experience? Toggle sound settings.
+
+
Dark Mode
+
+
+
+
+
Dark mode for a relaxed gaming experience.
+
+
+
Challenge Mode
+
+
+
+
+
Remember the letters you've already guessed wrong.
+
+
+
+
+
+
+
+
+
+
+ ×
+
Hint
+
Follow these tips to make the most of your hints
+
+
You can reveal a letter by clicking "Reveal a Letter".
+
Use "Remove Body Part" to reduce your penalty chances.
+
Plan your guesses strategically before using hints.
+
+
Here is a hint for the word
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/EC327_Hangle_COMPLETED/3_multihangman.js b/EC327_Hangle_COMPLETED/3_multihangman.js
new file mode 100644
index 0000000000000000000000000000000000000000..12e5b59c82930f34207352edec813fe9ba8cfb2e
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/3_multihangman.js
@@ -0,0 +1,852 @@
+/**
+ * Processes the user input for the game, validating the word entered by the user.
+ *
+ * This function retrieves the value entered by the user in the input field with ID
+ * userInput and performs several checks:
+ *
+ *
+ *
Empty Input: If no input is provided, it shows a message prompting the user to enter a valid word.
+ *
Invalid Characters: If the input contains numbers or special characters, it prompts the user to enter a word consisting only of letters.
+ *
Word Length: If the input length exceeds 8 characters, it shows a message restricting the word length to 8 letters.
+ *
+ *
+ * If the input passes all checks, the function:
+ *
+ *
+ *
Sets the currentword to the uppercased version of the input.
+ *
Sets the word_length dynamically based on the length of the input.
+ *
Hides the popup element by setting its display style to "none".
+ *
Initializes the game by calling the initialize() function.
+ *
+ *
+ * Example usage:
+ *
+ * returnText(); // Processes the user input and updates the game state.
+ *
+ *
+ * @return void - This function does not return any value.
+ * @see initialize
+ * @see currentword
+ * @see word_length
+ * @since 2024-12-09
+ */
+function returnText() {
+ const input = document.getElementById("userInput").value.trim();
+ const message_category = document.querySelector("p");
+ const letters = /^[A-Za-z]+$/;
+
+
+ if (input === "" || input == null) {
+ const message_category = document.querySelector("p");
+ message_category.innerHTML = "Make it hard to the other person can't guess it (max 8 letters)";
+ return;
+ }
+
+ else if (!letters.test(input)) {
+ const message_category = document.querySelector("p");
+ message_category.innerHTML = "Really, numbers? Put in a word.";
+ return;
+ }
+
+ else if (input.length > 8) {
+ const message_category = document.querySelector("p");
+ message_category.innerHTML = "Can't be more than 8 letters.";
+ return;
+ }
+
+ currentword = input.toUpperCase();
+ word_length = currentword.length; // Set word length dynamically
+ console.log("Word Set:", currentword);
+
+ // Hide the popup
+ const popup = document.querySelector(".popup");
+ popup.style.display = "none";
+
+ // Initialize the game
+ initialize();
+}
+
+const keyboard_container = document.querySelector("#keyboard_container");
+let currentword;
+let max_attempts = 6;
+var gameover = false;
+let wrong_attempts = 0;
+let right_attempts = 0;
+let word_length;
+var spot = 0;
+let currentIndex = 1;
+let correct_word = 0;
+
+/**
+*
+* Assigns the returnText function to the window.onload event.
+* This ensures the returnText function executes automatically when the webpage finishes loading.
+*
+* The window.onload event is triggered after all assets
+* (e.g., HTML, CSS, JavaScript, images) are fully loaded.
+* By using this assignment, the returnText function initializes
+* or performs actions required after the page loads.
+* @return void - The assigned function does not return any value.
+* @see {@link window.onload}
+*
+*/
+window.onload = function() {
+ returnText();
+}
+
+
+document.getElementById('Home-link').addEventListener('click', () => {
+ window.location.href = '1_mainpage.html';
+});
+
+/**
+ * Initializes the Hangman game by setting up the word display and virtual keyboard.
+ *
+ * [Long Description]
+ * This function prepares the Hangman game interface by:
+ * 1. Verifying that the target word (`currentword`) and its length (`word_length`) are set.
+ * 2. Creating and displaying blank tiles for each letter of the target word.
+ * 3. Generating a virtual keyboard with buttons for each letter, allowing user interaction.
+ * 4. Binding a keyup event listener to handle physical keyboard inputs.
+ *
+ * If the target word is not set correctly, the function logs an error and exits early.
+ *
+ * @global {string} currentword - The target word for the game. Must be defined before calling this function.
+ * @global {number} word_length - The length of the target word, used to create the corresponding number of tiles.
+ * @global {HTMLElement} tile_category - The DOM element where the letter tiles are displayed.
+ * @global {HTMLElement} keyboard_container - The DOM element where the virtual keyboard is rendered.
+ * @global {function} input - A function that processes user input from the virtual or physical keyboard.
+ * @global {function} handleKeyup - A function that processes physical keyboard inputs.
+ *
+ * @throws {Error} Logs an error if `currentword` or `word_length` is not properly set.
+ *
+ * @example
+ * // Example usage:
+ * initialize();
+ * // Output:
+ * // - Sets up the game UI with blank tiles and a functional keyboard.
+ *
+ * @see input - Handles user input for typing letters.
+ * @see handleKeyup - Handles physical keyboard inputs and triggers the appropriate logic.
+ *
+ * @see Game Development Tutorial - Great Day Designs
+ * @see Hangman Game Tutorial - Kenny Yip Coding
+ *
+ */
+function initialize() {
+ // Check if the word is set
+ if (!currentword || word_length === 0) {
+ console.error("Game initialization failed. Ensure the word is set properly.");
+ return;
+ }
+
+ const tile_category = document.querySelector(".display");
+ tile_category.innerHTML = "";
+
+ // Create Hangman Space
+ for (let i = 0; i < word_length; i++) {
+ const tile = document.createElement("li");
+ tile.id = i.toString();
+ tile.classList.add("letter");
+ tile.innerText = "";
+ tile_category.appendChild(tile);
+ }
+
+ // Keyboard setup
+ keyboard_container.innerHTML = ""; // Clear the keyboard container
+
+ const rows = [
+ "qwertyuiop".split(""),
+ "asdfghjkl".split(""),
+ "zxcvbnm".split(""),
+ ];
+
+ rows.forEach((row) => {
+ const keyboard_row = document.createElement("div");
+ keyboard_row.classList.add("keyboard_row");
+
+ row.forEach((item) => {
+ const button = document.createElement("button");
+
+ if (typeof item === "string") {
+ button.innerText = item.toUpperCase();
+ button.dataset.key = item;
+ }
+
+ button.addEventListener("click", () => {
+ input(button.dataset.key);
+ });
+
+ keyboard_row.appendChild(button);
+ });
+
+ keyboard_container.appendChild(keyboard_row);
+ });
+
+ // Add typing functionality
+ document.addEventListener("keyup", handleKeyup);
+
+ //console.log("Game initialized with word:", currentword);
+}
+
+/**
+ * Handles keyup events and simulates a button click based on the key pressed.
+ *
+ *
This function processes the `keyup` event to identify the key pressed and triggers the corresponding
+ * button's `click` event if a matching button exists. It ensures that keypresses are ignored if a popup
+ * is active or if the game is not properly initialized. This function is essential for keyboard-based
+ * interaction within the game.
+ *
+ * @function
+ * @param {KeyboardEvent} e - The `keyup` event object containing information about the key pressed.
+ * @return void
+ * @throws Error if `currentword` is not defined, indicating that the game has not been initialized.
+ * @see currentword
+ * @since 2024-12-09
+ */
+function handleKeyup(e) {
+ const popup = document.querySelector(".popup");
+
+ // Ignore keypress if popup is visible
+ if (popup.style.display === "flex" || popup.style.display === "block") {
+ console.log("Popup is active. Ignoring keypress.");
+ return;
+ }
+
+ // Ensure the game is initialized
+ if (!currentword) {
+ console.error("Cannot process keypress: currentword is undefined.");
+ return;
+ }
+
+ const keyPressed = e.key.toLowerCase();
+ console.log("Key pressed:", keyPressed);
+
+ const button = document.querySelector(`button[data-key="${keyPressed}"]`);
+ if (button) {
+ button.click(); // Simulate a button click
+ } else {
+ console.log(`No matching button found for: ${keyPressed}`);
+ }
+}
+
+/**
+*
Toggles the sound setting based on the state of the sound slider (checkbox).
+* This function reads the state of the sound slider, stores it in `localStorage`,
+* and allows persistence of the user's sound preference across sessions.
+*
Key functionality:
+*
+*
If the slider is checked, sound is enabled
+*
If the slider is unchecked, sound is disabled.
+*
+*
+*
The state of the sound preference is saved in `localStorage` with the key `soundEnabled`.
+*
+* Example usage:
+* toggleSound(); // Saves the sound setting (enabled or disabled)
+* @return void - The assigned function does not return any value.
+* @since 2024-12-09
+*/
+function toggleSound() {
+ const soundEnabled = document.getElementById('sound-slider').checked;
+ localStorage.setItem('soundEnabled', soundEnabled); // Save the state
+}
+
+/**
+ * Loads the user's sound preference from `localStorage` and applies it to the sound slider.
+ *
+ * This function checks the `localStorage` for the user's saved sound preference under the key
+ * soundEnabled. If no preference is found (value is null), it defaults
+ * to enabling sound and saves this default state back to `localStorage`. The function then updates
+ * the state of the sound slider on the webpage based on the retrieved or default preference.
+ *
+ *
+ *
Retrieves Preference: Reads the soundEnabled key from `localStorage`.
+ *
Defaults to Sound ON: If no preference exists, sets soundEnabled to true.
+ *
Updates UI: Reflects the preference in the sound slider's checked state.
+ *
+ *
+ * @example:
+ * loadSoundPreference(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function loadSoundPreference() {
+ let soundEnabled = JSON.parse(localStorage.getItem('soundEnabled'));
+
+ if (soundEnabled === null) {
+ // Default to sound ON if no preference is saved
+ soundEnabled = true;
+ localStorage.setItem('soundEnabled', true);
+ }
+
+ // Set the slider and the sound state based on localStorage
+ document.getElementById('sound-slider').checked = soundEnabled;
+}
+
+// Attach the event listener for the sound slider toggle
+document.getElementById('sound-slider').addEventListener('change', toggleSound);
+
+// Load the sound preference on page load
+document.addEventListener('DOMContentLoaded', loadSoundPreference);
+
+/**
+ * Allows sound to play, grabbing the specific sound file from its path, when soundEnabled is true.
+ *
+ * This function checks the when sound is enabled. If sound is enabled the function plays the audio.
+ * If sound is not enabled it logs it to the console saying "Sound is disabled".
+ *
+ *
+ *
sound is enabled sound plays
+ *
sound is disabled sound does not play
+ *
+ *
+ * @example:
+ * playSound(audioPath); // Loads and applies the user's sound preference on page load.
+ * @param audioPath - write audio path in string
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see JSON.parse
+ * @since 2024-12-09
+ */
+function playSound(audioPath) {
+ const soundEnabled = JSON.parse(localStorage.getItem('soundEnabled')); // Check the current sound state
+ if (soundEnabled) {
+ const audio = new Audio(audioPath);
+ audio.play();
+ } else {
+ console.log("Sound is disabled.");
+ }
+}
+
+/**
+ * Handles user input for guessing letters and updates the game state accordingly.
+ *
+ * [Long Description]
+ * This function processes user guesses based on the key pressed, whether through a virtual or physical keyboard.
+ * It performs the following actions:
+ * 1. Prevents further action if the corresponding button for the pressed key is already disabled.
+ * 2. Checks if the guessed letter exists in the target word (`currentword`):
+ * - For correct guesses:
+ * - Updates the matching tiles with the guessed letter.
+ * - Adds a "right" class to the tile and button for visual feedback.
+ * - Increments the `right_attempts` counter.
+ * - For incorrect guesses:
+ * - Marks the button with a "wrong" class.
+ * - Increments the `wrong_attempts` counter.
+ * - Updates the hangman display by calling `updatehangman`.
+ * 3. Disables the key button to prevent duplicate inputs.
+ * 4. Checks if the game is over by invoking `checkgameover`.
+ *
+ * @param {string} keyPressed - The letter key pressed by the user (case-insensitive).
+ *
+ * @global {string} currentword - The target word to guess.
+ * @global {number} word_length - The length of the target word.
+ * @global {number} right_attempts - Tracks the number of correctly guessed letters.
+ * @global {number} wrong_attempts - Tracks the number of incorrect guesses.
+ * @global {function} updatehangman - Updates the visual representation of the hangman based on incorrect guesses.
+ * @global {function} checkgameover - Checks if the game has ended (win or lose) based on the game state.
+ * @global {function} playSound - Plays sound effects for user interactions.
+ *
+ * @throws {Error} Throws an error if required global variables (`currentword`, `word_length`, etc.) are undefined.
+ *
+ * @example
+ * // Example usage:
+ * input("a"); // Handles the user's guess of the letter "A".
+ * // If correct:
+ * // - Updates tiles with "A".
+ * // - Marks the button as "right".
+ * // - Increments `right_attempts`.
+ * // If incorrect:
+ * // - Marks the button as "wrong".
+ * // - Increments `wrong_attempts`.
+ * // - Updates the hangman display.
+ *
+ * @see updatehangman - Updates the visual state of the hangman figure.
+ * @see checkgameover - Evaluates whether the game has ended.
+ *
+ */
+const input = (keyPressed) => {
+ const keyButton = document.querySelector(`button[data-key="${keyPressed.toLowerCase()}"]`);
+
+ if (keyButton.disabled) return;
+
+
+ if (currentword.includes(keyPressed.toUpperCase())) {
+
+ for (let i = 0; i < word_length; i++) {
+ if (currentword[i] === keyPressed.toUpperCase()) {
+ const currTile = document.getElementById(i.toString());
+
+ if (currTile) {
+ currTile.innerText = keyPressed.toUpperCase();
+ currTile.classList.add("right");
+ right_attempts++;
+
+ }
+ keyButton.classList.add("right");
+ }
+ }
+ keyButton.classList.add("correct");
+ playSound('sounds/click.wav');
+ } else {
+ keyButton.classList.add("wrong");
+ wrong_attempts++;
+ updatehangman();
+ playSound('sounds/click.wav');
+ }
+
+ keyButton.disabled = true;
+ checkgameover(wrong_attempts);
+};
+
+/**
+ * Animates the tiles with a "bounce" effect sequentially.
+ *
+ * [Long Description]
+ * This function applies a "bounce" animation to each tile representing the guessed word.
+ * The animation is applied sequentially with a staggered delay, ensuring a smooth visual effect.
+ * After the animation ends, the "bounce" class is removed from each tile to reset its state.
+ *
+ * The delay for each tile is based on its index, creating a cascading animation effect.
+ * This function is primarily used to enhance user experience by providing visual feedback.
+ *
+ * @global {number} word_length - The total number of tiles to animate, corresponding to the length of the word.
+ *
+ * @throws {Error} Throws an error if the global variable `word_length` is undefined or if a tile element cannot be found.
+ *
+ * @example
+ * // Example usage:
+ * animateTiles();
+ * // Output:
+ * // - Applies a "bounce" animation to each tile with a staggered delay.
+ *
+ */
+function animateTiles() {
+ for (let i = 0; i < word_length; i++) {
+ const currtile = document.getElementById(i.toString());
+
+ // Add a delay for each tile based on its index
+ setTimeout(() => {
+ currtile.classList.add("bounce");
+
+ // Remove the animation class after it ends
+ currtile.addEventListener("animationend", () => {
+ currtile.classList.remove("bounce");
+ });
+ }, i * 150); // Stagger delay by 150ms per tile
+ }
+}
+
+/**
+ * Checks the game state to determine if the player has won or lost and handles end-of-game actions.
+ *
+ * [Long Description]
+ * This function evaluates whether the game is over based on the number of incorrect attempts or
+ * the number of correctly guessed letters. Depending on the result:
+ * 1. **Game Lost**:
+ * - If the number of incorrect attempts (`wrong_attempts`) reaches 6:
+ * - Sets the `gameover` flag to `true`.
+ * - Displays a "Game Over" message with the correct word.
+ * - Plays a "lose" sound effect.
+ * - Triggers tile animations for visual feedback.
+ * 2. **Game Won**:
+ * - If the number of correctly guessed letters (`right_attempts`) equals the word length (`word_length`):
+ * - Sets the `gameover` flag to `true`.
+ * - Displays a "You Win!" message.
+ * - Plays a "win" sound effect.
+ * - Launches a confetti animation for celebration.
+ * - Triggers tile animations for visual feedback.
+ *
+ * This function ensures proper handling of both win and lose states and enhances the user experience
+ * through sound effects, animations, and visual cues.
+ *
+ * @param {number} wrong_attempts - The current count of incorrect guesses by the player.
+ *
+ * @global {boolean} gameover - A flag indicating whether the game has ended.
+ * @global {string} currentword - The word the player is trying to guess.
+ * @global {number} right_attempts - The count of correctly guessed letters.
+ * @global {number} word_length - The total number of letters in the target word.
+ * @global {function} displaymessage - Displays a message to the player (win or lose).
+ * @global {function} playSound - Plays sound effects for the game's win or lose scenarios.
+ * @global {function} animateTiles - Animates the letter tiles for visual feedback.
+ *
+ * @example
+ * // Example usage:
+ * checkgameover(6); // Handles the "Game Over" scenario if the player has reached the max wrong attempts.
+ * checkgameover(3); // Handles the "You Win" scenario if the player guesses all letters correctly.
+ *
+ * @see displaymessage - Used to show end-of-game messages.
+ * @see playSound - Handles sound effects for win and lose events.
+ * @see animateTiles - Animates the tiles for added feedback at the end of the game.
+ * @see confetti - Creates a celebratory effect for winning the game.
+ *
+ */
+function checkgameover(wrong_attempts) {
+
+ if (wrong_attempts == 6) {
+ gameover = true;
+ console.log("bad");
+ displaymessage(`Game Over! The word was: ${currentword}`);
+ playSound('sounds/lose.wav');
+ animateTiles();
+ return;
+ }
+
+ if (right_attempts==word_length) {
+ gameover = true;
+ console.log("good!")
+ displaymessage("You Win!", true, true)
+ animateTiles();
+ confetti({
+ particleCount: 150, // Number of confetti pieces
+ spread: 70, // Spread angle of confetti
+ origin: { y: 0.6 }, // Confetti drop point
+ colors: ['#bb0000', '#ffffff', '#00bb00'] // Custom colors
+ });
+ playSound('sounds/win.wav');
+ return;
+ }
+ }
+
+/**
+ * Displays a message overlay on the screen with optional reset and home buttons.
+ *
+ * [Long Description]
+ * This function creates and displays an overlay message on the screen. It includes a customizable
+ * message and optional buttons for resetting the game and navigating to the home page. The overlay
+ * is styled dynamically based on whether the game was won or lost. The "Play Again" button reloads
+ * the page to restart the game, while the "Go Home" button redirects to the main page.
+ *
+ * A fade-in animation is triggered after the overlay is appended to the DOM for a smooth visual effect.
+ *
+ * @param {string} message - The message to display on the overlay.
+ * @param {boolean} [showResetButton=true] - Determines whether the "Play Again" button is displayed.
+ * @param {boolean} [isWin=false] - Specifies whether the game was won, which affects the overlay's style.
+ *
+ * @example
+ * // Display a winning message with reset and home buttons:
+ * displayMessage("You Win!", true, true);
+ *
+ * // Display a losing message without a reset button:
+ * displayMessage("Game Over! The word was: CAT", false);
+ *
+ * @see location.reload - Used to reload the page for restarting the game.
+ * @see window.location.href - Redirects to the specified home page URL.
+ *
+ */
+
+ function displaymessage(message, showResetButton = true, isWin = false) {
+ // Create the black overlay
+ const overlay = document.createElement("div");
+ overlay.classList.add(isWin ? "overlay-win" : "overlay");
+
+ // Create the message container
+ const messageContainer = document.createElement("div");
+ messageContainer.classList.add("message-container");
+
+ // Add the message text
+ const messageText = document.createElement("p");
+ messageText.classList.add("message-text");
+ messageText.innerText = message;
+ messageContainer.appendChild(messageText);
+
+ // Add the reset button (Play Again)
+ if (showResetButton) {
+ const resetButton = document.createElement("button");
+ resetButton.classList.add("reset-button");
+ resetButton.innerText = "Play Again";
+ resetButton.addEventListener("click", () => {
+ location.reload(); // Reload the page to restart the game
+ });
+ messageContainer.appendChild(resetButton);
+ }
+
+ // Add the Home button (go to home page)
+ const homeButton = document.createElement("button");
+ homeButton.classList.add("home-button");
+ homeButton.innerText = "Go Home";
+ homeButton.addEventListener("click", () => {
+ window.location.href = '1_mainpage.html'; // Redirect to home page
+ });
+ messageContainer.appendChild(homeButton);
+
+ // Append the container to the overlay
+ overlay.appendChild(messageContainer);
+
+ // Append the overlay to the body
+ document.body.appendChild(overlay);
+
+ // Trigger fade-in animation
+ setTimeout(() => {
+ overlay.classList.add("fade-in");
+ }, 10);
+}
+
+/**
+ * Updates the hangman figure by revealing the next body part image.
+ *
+ *
This function manages the visual representation of incorrect guesses by progressively
+ * revealing parts of the hangman figure. Each time an incorrect guess is made, the opacity
+ * of the next body part image in the sequence is set to 1, making it visible. The function
+ * keeps track of the current index of the body parts and ensures that it does not exceed the
+ * total number of body parts available.
+ *
+ *
+ *
Increment Index: The function increments the `currentIndex` to keep track
+ * of which body part should be revealed next.
+ *
Reveal Body Part: The next body part image in the sequence is revealed
+ * by changing its opacity.
+ *
Boundary Check: Ensures that no more body parts are revealed after the
+ * last image in the sequence.
+ *
+ *
+ * @global {NodeList} images - A collection of elements representing the hangman body parts.
+ * These elements are queried from the DOM using the `.body-part` class.
+ * @global {number} currentIndex - Tracks the current body part being revealed. Incremented with
+ * each incorrect guess.
+ *
+ * @throws {Error} Throws an error if the `images` NodeList is undefined or `currentIndex` exceeds its length.
+ *
+ * @example
+ * // Example usage:
+ * updatehangman();
+ * // Output:
+ * // - Reveals the next body part in the sequence by making it visible.
+ *
+ * @since 2024-12-09
+ */
+function updatehangman() {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex < images.length) {
+ images[currentIndex].style.opacity = 1; // Show the next image
+ currentIndex++;
+ }
+}
+
+/**
+ * Redirects the user to the main page when the "Home" link is clicked.
+ *
+ *
This function listens for a click event on the element with the ID `Home-link`. Upon clicking,
+ * the user is redirected to the "1_mainpage.html" page. It is primarily used for navigation purposes
+ * within the application.
+ * toggles darkmode on and off and saves the data into {@code localStorage} object, which is
+ * then stored in the web storage API
+ *
+ *
+ * This function toggles the darkmode class on the {@code document.body} element,
+ * which typically applies or removes dark mode styling. It also updates the {@code localStorage}
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ * @example:
+ * toggleDarkMode(); // Loads and applies the user's sound preference on page load.
+ * @return void - This function does not return a value.
+ * @see localStorage
+ * @see document.body
+ * @since 2024-12-09
+ */
+function toggleDarkMode() {
+ const darkModeEnabled = document.body.classList.toggle('darkmode');
+ localStorage.setItem('darkModeEnabled', darkModeEnabled); // Save the state
+}
+
+/**
+ * Toggles the dark mode on or off and saves the current state in localStorage.
+ *
+ * This function toggles the darkmode class on the document.body element,
+ * which typically applies or removes dark mode styling. It also updates the localStorage
+ * with the current dark mode state. The state is saved as a boolean, where true
+ * indicates that dark mode is enabled and false indicates that dark mode is disabled.
+ *
+ *
+ * @example usage:
+ * toggleDarkMode(); // Toggles dark mode and saves the state
+ *
+ * @return void - This function does not return any value.
+ * @see localStorage
+ * @see document.body
+ */
+function loadDarkModePreference() {
+ const darkModeEnabled = JSON.parse(localStorage.getItem('darkModeEnabled'));
+
+ if (darkModeEnabled) {
+ // Apply dark mode if it was enabled
+ document.body.classList.add('darkmode');
+ document.getElementById('darkmode-slider').checked = true; // Set the slider to ON
+ } else {
+ // Ensure light mode if dark mode was not enabled
+ document.body.classList.remove('darkmode');
+ document.getElementById('darkmode-slider').checked = false; // Set the slider to OFF
+ }
+}
+document.getElementById('darkmode-slider').addEventListener('change', toggleDarkMode);
+document.addEventListener('DOMContentLoaded', loadDarkModePreference);
+
+
+const challengeSlider = document.getElementById("challenge-slider");
+const keyboardContainer = document.getElementById("keyboard_container");
+/**
+ *
+ * Toggles the "grey-mode" class on the keyboard container based on the challenge slider's state.
+ *
+ *
+ *
+ *
Checked: Enables "grey-mode" on the keyboard container.
+ *
Unchecked: Disables "grey-mode" and restores default styling.
+ *
+ *
+ * @event change - Triggered when the state of the challenge slider changes (checked/unchecked).
+ *
+ * @param {Event} event - The event triggered when the slider's state changes.
+ *
+ * @global {HTMLElement} challengeSlider - The DOM element representing the challenge slider.
+ * @global {HTMLElement} keyboardContainer - The DOM element containing the keyboard.
+ *
+ * @example
+ * // Example usage:
+ * challengeSlider.addEventListener("change", () => {
+ * if (challengeSlider.checked) {
+ * keyboardContainer.classList.add("grey-mode");
+ * } else {
+ * keyboardContainer.classList.remove("grey-mode");
+ * }
+ * });
+ *
+ * @return {void} - This function does not return a value.
+ * @see keyboardContainer - The target element for the "grey-mode" class.
+ * @see challengeSlider - The slider controlling the challenge mode.
+ * @since 2024-12-09
+ */
+challengeSlider.addEventListener("change", () => {
+ if (challengeSlider.checked) {
+ keyboardContainer.classList.add("grey-mode");
+ } else {
+ keyboardContainer.classList.remove("grey-mode");
+ }
+});
+
+/**
+ * Handles the click event of the "remove-body-part" button to remove a body part image.
+ *
+ *
This function is triggered when the user clicks the "remove-body-part" button. It reduces the visibility
+ * of the most recent body part image (by setting its opacity to 0) and decreases the `wrong_attempts` count.
+ * The button is then disabled and visually updated to indicate it's no longer clickable. If no wrong attempts
+ * are left, the button is hidden.
+ *
+ * @function
+ * @param none
+ * @return void
+ * @see wrong_attempts,currentIndex
+ * @since 2024-12-09
+ */
+document.getElementById('remove-body-part').addEventListener('click', function () {
+ const images = document.querySelectorAll('.body-part');
+ if (currentIndex > 1) {
+ currentIndex--;
+ images[currentIndex].style.opacity = 0;
+ wrong_attempts = Math.max(0, wrong_attempts - 1);
+ console.log(`Body part removed. Remaining wrong attempts: ${max_attempts - wrong_attempts}`);
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Adds an event listener to the "reveal-letter" button to reveal a random unrevealed letter from the current word.
+ *
This functionality helps the user by revealing a letter from the target word when the button is clicked.
+ * The revealed letter is displayed in its corresponding tile on the interface and marked as "right."
+ * Additionally, the associated keyboard key is highlighted. Once all letters are revealed,
+ * the game checks for completion, and the "reveal-letter" button is disabled to prevent further use.
+ *
+ *
Revealing a Letter: A random unrevealed letter is selected, displayed on the game tile, and marked as correct.
+ *
Keyboard Highlight: The corresponding keyboard key is updated to indicate it has been used correctly.
+ *
Button State: The "reveal-letter" button is disabled after a letter is revealed to prevent additional usage.
+ *
Game Completion: If all letters are revealed, the game checks for completion.
+ *
Error Handling: If all letters have already been revealed, a message is logged to the console.
+ *
+ *
+ * @function
+ * @since 2024-12-09
+ */
+document.getElementById('reveal-letter').addEventListener('click', function () {
+ const randomIndex = getRandomUnrevealedLetter();
+
+ if (randomIndex !== null) {
+ const currTile = document.getElementById(randomIndex.toString());
+ currTile.innerText = currentword[randomIndex];
+ currTile.classList.add("right");
+ currTile.dataset.lock = "true";
+ const keyButton = document.querySelector(`button[data-key="${currentword[randomIndex].toLowerCase()}"]`);
+ if (keyButton) {
+ keyButton.classList.add("right");
+ }
+ correct_word++;
+ if (correct_word === word_length) {
+ checkgameover(false);
+ }
+ } else {
+ console.log("All letters have already been revealed.");
+ }
+ this.disabled = true;
+ this.style.opacity = 0.5;
+ this.style.cursor = 'not-allowed';
+});
+
+/**
+ * Retrieves the index of a random unrevealed letter from the current word.
+ *
+ *
This function identifies all the tiles representing unrevealed letters and randomly selects
+ * one of them. If all letters have been revealed, it returns `null`. The unrevealed letters are
+ * determined by checking the absence of a `lock` attribute in the dataset of each tile element.
+ *
+ * @function
+ * @param none
+ * @return {number|null} - The index of a random unrevealed letter, or `null` if no letters are left to reveal.
+ * @see word_length
+ * @since 2024-12-09
+ *
+ */
+function getRandomUnrevealedLetter() {
+ const unrevealedIndices = [];
+ for (let i = 0; i < word_length; i++) {
+ const currTile = document.getElementById(i.toString());
+ if (!currTile.dataset.lock) {
+ unrevealedIndices.push(i);
+ }
+ }
+ if (unrevealedIndices.length > 0) {
+ const randomIndex = Math.floor(Math.random() * unrevealedIndices.length);
+ return unrevealedIndices[randomIndex];
+ }
+ return null;
+}
+
+module.exports = {
+ initialize,
+ input,
+ checkletater,
+ checkgameover,
+ updatehangman,
+};
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/images/body.png b/EC327_Hangle_COMPLETED/images/body.png
new file mode 100755
index 0000000000000000000000000000000000000000..544f021855173c8686f2da2a53ef17fa16707ad1
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/body.png differ
diff --git a/EC327_Hangle_COMPLETED/images/empty.png b/EC327_Hangle_COMPLETED/images/empty.png
new file mode 100755
index 0000000000000000000000000000000000000000..9cf55b290751173a968099d0adcb2daf1303fa2f
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/empty.png differ
diff --git a/EC327_Hangle_COMPLETED/images/ex1.png b/EC327_Hangle_COMPLETED/images/ex1.png
new file mode 100644
index 0000000000000000000000000000000000000000..aab69832ca721009c8804bc8fb3c1e1ed992ac7c
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/ex1.png differ
diff --git a/EC327_Hangle_COMPLETED/images/guide.png b/EC327_Hangle_COMPLETED/images/guide.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e7f7638c6ed0c8de83567566b46cd83b2df304b
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/guide.png differ
diff --git a/EC327_Hangle_COMPLETED/images/hangman.jpg b/EC327_Hangle_COMPLETED/images/hangman.jpg
new file mode 100755
index 0000000000000000000000000000000000000000..7400c644d0508fe86fd798ffe1b5e044c57f3be1
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/hangman.jpg differ
diff --git a/EC327_Hangle_COMPLETED/images/head.png b/EC327_Hangle_COMPLETED/images/head.png
new file mode 100755
index 0000000000000000000000000000000000000000..64bfa14352866e04764f7b2dfa8832c353f06913
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/head.png differ
diff --git a/EC327_Hangle_COMPLETED/images/headx.png b/EC327_Hangle_COMPLETED/images/headx.png
new file mode 100755
index 0000000000000000000000000000000000000000..6b43436c98e1c5fbfde453b96860deefd1526194
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/headx.png differ
diff --git a/EC327_Hangle_COMPLETED/images/hint.png b/EC327_Hangle_COMPLETED/images/hint.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ca0b2fa70bb7a750e9b7ddb5e58baeaca1b5c24
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/hint.png differ
diff --git a/EC327_Hangle_COMPLETED/images/home.png b/EC327_Hangle_COMPLETED/images/home.png
new file mode 100644
index 0000000000000000000000000000000000000000..5f2344ecfec81adf1f0e6838acd17470a3995309
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/home.png differ
diff --git a/EC327_Hangle_COMPLETED/images/left_arm.png b/EC327_Hangle_COMPLETED/images/left_arm.png
new file mode 100755
index 0000000000000000000000000000000000000000..1a405661f2098a99727c03b34fdb11d52ed9e7da
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/left_arm.png differ
diff --git a/EC327_Hangle_COMPLETED/images/left_leg.png b/EC327_Hangle_COMPLETED/images/left_leg.png
new file mode 100755
index 0000000000000000000000000000000000000000..1a405661f2098a99727c03b34fdb11d52ed9e7da
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/left_leg.png differ
diff --git a/EC327_Hangle_COMPLETED/images/right_arm.png b/EC327_Hangle_COMPLETED/images/right_arm.png
new file mode 100755
index 0000000000000000000000000000000000000000..75165eed081e78231228c9f2cba259a8eecfcd83
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/right_arm.png differ
diff --git a/EC327_Hangle_COMPLETED/images/right_leg.png b/EC327_Hangle_COMPLETED/images/right_leg.png
new file mode 100755
index 0000000000000000000000000000000000000000..c4e75162ca842699f10dc0407ca36224d171b6a5
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/right_leg.png differ
diff --git a/EC327_Hangle_COMPLETED/images/settings.png b/EC327_Hangle_COMPLETED/images/settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..0dde2f381838e8d7feb5bb15227e3fe7a333cf94
Binary files /dev/null and b/EC327_Hangle_COMPLETED/images/settings.png differ
diff --git a/EC327_Hangle_COMPLETED/makefile b/EC327_Hangle_COMPLETED/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1de8d7f43e4d98454091b8fed087efa109f70379
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/makefile
@@ -0,0 +1,63 @@
+# Variables
+MAIN_PAGE = 1_mainpage.html
+EASY_MODE = 3_easymode.html
+MED_MODE = 3_medmode.html
+HARD_MODE = 3_hardmode.html
+MULTIPLAYER = 3_multihangle.html
+HANGMAN = 3_multihangman.html
+BROWSER = open
+NODE = node
+CHECK_LETTER = tests/checkletter.js
+GET_RANDOM_WORD = tests/getRandomWord.js
+GET_RANDOM_UNREVEALED_LETTER = tests/getRandomUnrevealedLetter.js
+CHECK_GAME_OVER = tests/checkgameover.js
+
+#Requires Node.js to run unit tests.
+#Please download Node https://nodejs.org/en/download/package-manager
+test_mainpage:
+ $(BROWSER) $(MAIN_PAGE)
+
+test_easymode:
+ $(BROWSER) $(EASY_MODE)
+
+test_medmode:
+ $(BROWSER) $(MED_MODE)
+
+test_hardmode:
+ $(BROWSER) $(HARD_MODE)
+
+test_multiplayer:
+ $(BROWSER) $(MULTIPLAYER)
+
+test_hangman:
+ $(BROWSER) $(HANGMAN)
+
+test_checkletter:
+ @echo "Running checkletter.js"
+ $(NODE) $(CHECK_LETTER)
+
+test_getrandomword:
+ @echo "Running getRandomWord.js"
+ $(NODE) $(GET_RANDOM_WORD)
+
+test_get_random_unrevealed_letter:
+ @echo "Running getRandomUnrevealedLetter.js"
+ $(NODE) $(GET_RANDOM_UNREVEALED_LETTER)
+
+test_check_game_over:
+ @echo "Running checkgameover.js"
+ $(NODE) $(CHECK_GAME_OVER)
+
+help:
+ @echo "Available targets:"
+ @echo "make test_mainpage - Tests mainpage functionality"
+ @echo "make test_easymode - Tests easy mode functionality"
+ @echo "make test_medmode - Tests medium mode functionality"
+ @echo "make test_hardmode - Tests hard mode functionality"
+ @echo "make test_multiplayer - Tests multiplayer functionality"
+ @echo "make test_hangman - Tests hangman functionality"
+ @echo "make test_checkletter - Tests checkletter function"
+ @echo "make test_getrandomword - Tests getRandomWord function"
+ @echo "make test_get_random_unrevealed_letter - Tests getRandomUnrevealedLetter function"
+ @echo "make test_check_game_over - Tests checkgameover function"
+
diff --git a/EC327_Hangle_COMPLETED/sounds/click.wav b/EC327_Hangle_COMPLETED/sounds/click.wav
new file mode 100755
index 0000000000000000000000000000000000000000..0a8da1c8408388bc25e603dde8e9cccc268e97b6
Binary files /dev/null and b/EC327_Hangle_COMPLETED/sounds/click.wav differ
diff --git a/EC327_Hangle_COMPLETED/sounds/lose.wav b/EC327_Hangle_COMPLETED/sounds/lose.wav
new file mode 100755
index 0000000000000000000000000000000000000000..dbf2f4ce75b11b7acd974543de11dd6e9ad2ae87
Binary files /dev/null and b/EC327_Hangle_COMPLETED/sounds/lose.wav differ
diff --git a/EC327_Hangle_COMPLETED/sounds/win.wav b/EC327_Hangle_COMPLETED/sounds/win.wav
new file mode 100755
index 0000000000000000000000000000000000000000..d2d34f19cc3cb0f3fa05d1ba6d1f4654f72e285f
Binary files /dev/null and b/EC327_Hangle_COMPLETED/sounds/win.wav differ
diff --git a/EC327_Hangle_COMPLETED/tests/checkgameover.js b/EC327_Hangle_COMPLETED/tests/checkgameover.js
new file mode 100644
index 0000000000000000000000000000000000000000..40d1bea06c98dc8a866ef6a84ce6d87dd546aa83
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/tests/checkgameover.js
@@ -0,0 +1,58 @@
+let gameover = false;
+//Changed the return statements to reflect what the client side game would actually do (allow or prevent user from continuing)
+function checkgameover(incorrectGuess) {
+
+ if (!incorrectGuess) {
+ gameover = true;
+ //console.log("good!")
+ //CLIENT SIDE DISPLAY BELOW
+ /*
+ displayMessage("You Win!", true, true)
+ animateTiles();
+ confetti({
+ particleCount: 150, // Number of confetti pieces
+ spread: 70, // Spread angle of confetti
+ origin: { y: 0.6 }, // Confetti drop point
+ colors: ['#bb0000', '#ffffff', '#00bb00'] // Custom colors
+ });
+ playSound('sounds/win.wav');
+ */
+ return true;
+ }
+
+ if (wrong_attempts >= max_attempts) {
+ gameover = true;
+ //console.log("bad");
+ //CLIENT SIDE DISPLAY BELOW
+ /*
+ displayMessage(`Game Over! The word was: ${currentword}`);
+ playSound('sounds/lose.wav');
+ */
+ return false;
+ }
+ return null;
+}
+let max_attempts = 5;
+let wrong_attempts = 4;
+
+let GoodGame = checkgameover(false);
+if (GoodGame === true) {
+ console.log("Test Passed: Player wins!");
+} else {
+ console.log("Test Failed: Winning condition not met.");
+}
+wrong_attempts = 5;
+GoodGame = checkgameover(true);
+if (GoodGame === false) {
+ console.log("Test Passed: Player loses!");
+} else {
+ console.log("Test Failed: Losing condition not met.");
+}
+
+wrong_attempts = 3;
+GoodGame = checkgameover(true);
+if (GoodGame === null) {
+ console.log("Test Passed: Game continues.");
+} else {
+ console.log("Test Failed: Premature gameover");
+}
diff --git a/EC327_Hangle_COMPLETED/tests/checkletter.js b/EC327_Hangle_COMPLETED/tests/checkletter.js
new file mode 100644
index 0000000000000000000000000000000000000000..ab890271ea073714e20298493da04e8b43b9c01e
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/tests/checkletter.js
@@ -0,0 +1,142 @@
+
+/*
+commented out dependencies
+Checking if it is the correct guess should work, Keyboard turning colors is not included in this test
+*/
+function checkletter() {
+
+ let spotsfilled = true;
+
+ for (let i =0; i 0) {
+ const randomIndex = Math.floor(Math.random() * unrevealedIndices.length);
+ const indexToReveal = unrevealedIndices[randomIndex];
+ return finishedWord[indexToReveal];
+ }
+ return null;
+}
+
+const revealedLetter = getRandomUnrevealedLetter();
+if (revealedLetter == 'T'){
+ console.log("Test Passed: Function works as intended. Letter T");
+}
+else if (revealedLetter == 'O'){
+ console.log("Test Passed: Function works as intended. Letter: O");
+}
+else{
+ console.log("Test Failed: Function does not work as intended");
+}
\ No newline at end of file
diff --git a/EC327_Hangle_COMPLETED/tests/getRandomWord.js b/EC327_Hangle_COMPLETED/tests/getRandomWord.js
new file mode 100644
index 0000000000000000000000000000000000000000..554d7b706da78452fe8cbb2cbe4d1ae72a3a099a
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/tests/getRandomWord.js
@@ -0,0 +1,32 @@
+import { sample_word } from "./sampleWordBank.js";
+let currentword;
+let new_hint;
+
+const getRandomWord = () => {
+ const { word, hint } = sample_word[Math.floor(Math.random() * sample_word.length)];
+ new_hint = hint.replace(/\.$/, ""); // Process hint if necessary
+ currentword = word.toUpperCase();
+};
+
+// Test to ensure getRandomWord sets correct word and hint
+getRandomWord();
+
+if (
+ sample_word.some(entry => entry.word.toUpperCase() === currentword) &&
+ sample_word.some(entry => entry.hint.replace(/\.$/, "") === new_hint)
+) {
+ console.log("Test Passed: getRandomWord function works!");
+}
+else if (sample_word.some(entry => entry.word.toUpperCase() === currentword) &&
+ sample_word.some(entry => entry.hint.replace(/\.$/, "") !== new_hint))
+ {
+ console.log("Test Failed: Word matches however hint doesn't match");
+}
+else if (sample_word.some(entry => entry.word.toUpperCase() !== currentword) &&
+ sample_word.some(entry => entry.hint.replace(/\.$/, "") === new_hint))
+ {
+ console.log("Test Failed: Word doesn't match however hint matches");
+}
+else {
+ console.log("Test Failed: Word doesn't match and hint doesn't match");
+}
diff --git a/EC327_Hangle_COMPLETED/tests/sampleWordBank.js b/EC327_Hangle_COMPLETED/tests/sampleWordBank.js
new file mode 100644
index 0000000000000000000000000000000000000000..7cd732a34146fdfc027b7e1ce13d6c82c5bc72ba
--- /dev/null
+++ b/EC327_Hangle_COMPLETED/tests/sampleWordBank.js
@@ -0,0 +1,94 @@
+export const sample_word = [
+ { word: "book", hint: "Often found on a shelf, it's full of knowledge or stories." },
+ { word: "coin", hint: "It's small, round, and jingles in your pocket." },
+ { word: "moon", hint: "It has phases and lights up the night." },
+ { word: "love", hint: "Something you feel but cannot hold." },
+ { word: "rain", hint: "It makes the ground wet and feeds the plants." },
+ { word: "lamp", hint: "A companion to darkness, it glows softly." },
+ { word: "fish", hint: "It swims but has no feet or hands." },
+ { word: "tree", hint: "It grows tall, stands still, and has rings inside." },
+ { word: "star", hint: "A tiny speck in the sky that shines." },
+ { word: "time", hint: "You can't see it, but it keeps everything moving." },
+ { word: "game", hint: "Played for fun, but sometimes for competition too." },
+ { word: "wind", hint: "It moves but cannot be seen." },
+ { word: "fire", hint: "It's warm, bright, and devours what it touches." },
+ { word: "milk", hint: "A white drink that comes from an animal." },
+ { word: "gold", hint: "A shiny metal that's always in demand." },
+ { word: "rock", hint: "Solid, silent, and has been around forever." },
+ { word: "lake", hint: "A resting place for water, surrounded by land." },
+ { word: "desk", hint: "Where work gets done, or at least tried." },
+ { word: "door", hint: "It swings or slides to let you in or out." },
+ { word: "snow", hint: "It's cold, white, and falls quietly." },
+ { word: "bird", hint: "It sings but does not speak." },
+ { word: "frog", hint: "It hops and often hides near water." },
+ { word: "wave", hint: "It's both in the ocean and in a friendly greeting." },
+ { word: "home", hint: "A place where your heart feels safe." },
+ { word: "cake", hint: "It's sweet, layered, and often has candles." },
+ { word: "boat", hint: "It floats but cannot swim." },
+ { word: "song", hint: "A story told in notes and rhythm." },
+ { word: "nest", hint: "Built high or low, it's a safe place for new life." },
+ { word: "belt", hint: "Keeps things together but goes unnoticed." },
+ { word: "ring", hint: "A circle that holds great significance." },
+ { word: "dust", hint: "It's tiny and always finds its way back." },
+ { word: "veil", hint: "It hides but doesn't fully conceal." },
+ { word: "bark", hint: "It's tough on the outside but protects what's inside." },
+ { word: "gift", hint: "It's given, not taken, and brings a smile." },
+ { word: "king", hint: "Rules without a weapon, leads without a map." },
+ { word: "pond", hint: "A mirror for the sky, still and shallow." },
+ { word: "salt", hint: "It enhances but doesn't overpower." },
+ { word: "path", hint: "It guides, but you must choose to follow." },
+ { word: "rope", hint: "Twisted strands that hold things together." },
+ { word: "film", hint: "It tells stories without turning a page." },
+ { word: "echo", hint: "It's your voice, but from somewhere else." },
+ { word: "leaf", hint: "It's green in life but brown in death." },
+ { word: "dusk", hint: "It signals the end of a bright day." },
+ { word: "seed", hint: "It holds potential for something great." },
+ { word: "jade", hint: "A green gem that's smooth and cool." },
+ { word: "pear", hint: "A fruit with curves and a sweet heart." },
+ { word: "arch", hint: "A curve that holds weight or marks a path." },
+ { word: "grid", hint: "A pattern of lines crossing each other." },
+ { word: "band", hint: "It holds together or plays together." },
+ { word: "vest", hint: "A garment that keeps your core warm." },
+ { word: "toad", hint: "A warty friend of ponds and marshes." },
+ { word: "clay", hint: "Soft and moldable, it hardens with fire." },
+ { word: "rice", hint: "A staple food that's small but filling." },
+ { word: "pear", hint: "A fruit that's neither apple nor orange." },
+ { word: "drum", hint: "It makes music with just a beat." },
+ { word: "wing", hint: "It helps some to fly and others to dream." },
+ { word: "nest", hint: "Where feathers and eggs come together." },
+ { word: "silk", hint: "Soft as a whisper, spun by a tiny creature." },
+ { word: "lion", hint: "It roars but doesn't purr." },
+ { word: "coal", hint: "It fuels fire but turns to ash." },
+ { word: "barn", hint: "A shelter for the quiet workers of the farm." },
+ { word: "rope", hint: "It's long, strong, and helps you climb." },
+ { word: "bead", hint: "Small and colorful, strung together with care." },
+ { word: "mist", hint: "A soft, wet veil for the morning." },
+ { word: "iron", hint: "Hard, strong, and a tool of the past." },
+ { word: "reef", hint: "A home under the sea, teeming with life." },
+ { word: "veil", hint: "A cover that's both seen and unseen." },
+ { word: "lime", hint: "A citrus fruit that adds zest to life." },
+ { word: "yarn", hint: "It tells a tale or weaves a fabric." },
+ { word: "glow", hint: "A soft light that warms the dark." },
+ { word: "beam", hint: "A ray of light or a sturdy support." },
+ { word: "snow", hint: "White and silent, it blankets the world." },
+ { word: "kite", hint: "It dances with the wind but needs a string." },
+ { word: "mint", hint: "Fresh, cool, and often green." },
+ { word: "wave", hint: "It rolls in endlessly, greeting the shore." },
+ { word: "rose", hint: "Beautiful and fragrant, but watch for thorns." },
+ { word: "grid", hint: "A network of lines that organizes." },
+ { word: "bell", hint: "It rings to mark time or call attention." },
+ { word: "dove", hint: "A bird of peace, white and serene." },
+ { word: "soap", hint: "It cleans but doesn't stay clean itself." },
+ { word: "jade", hint: "Precious and green, a stone of the east." },
+ { word: "rust", hint: "The color of decay on metal." },
+ { word: "wave", hint: "It crashes but never breaks completely." },
+ { word: "lamp", hint: "It brightens the corner where it stands." },
+ { word: "vine", hint: "It climbs but stays rooted." },
+ { word: "maze", hint: "A path that's not always straightforward." },
+ { word: "plum", hint: "Sweet, round, and often purple." },
+ { word: "twig", hint: "A small branch, light but strong." },
+ { word: "flax", hint: "A plant that gives both fiber and oil." },
+ { word: "fern", hint: "A green plant with feathery fronds." },
+ { word: "knit", hint: "To loop yarn into fabric." },
+ { word: "bark", hint: "It's rough and protects the tree." }
+];
\ No newline at end of file
diff --git a/Hangle_Presentation.md b/Hangle_Presentation.md
new file mode 100644
index 0000000000000000000000000000000000000000..ee082c1c24b37b28a53dc7c865515b11b0fcfa52
--- /dev/null
+++ b/Hangle_Presentation.md
@@ -0,0 +1 @@
+https://docs.google.com/presentation/d/1O8fvFTt4cYT5GHmz04i2oXHca7CEzyxnkVngmjDQq_4/edit?usp=sharing
\ No newline at end of file
diff --git a/Issue2/.gitkeep b/Issue2/.gitkeep
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Issue2/README.txt b/Issue2/README.txt
new file mode 100755
index 0000000000000000000000000000000000000000..0a1839b1f602b260741b5386a2f80379d296e143
--- /dev/null
+++ b/Issue2/README.txt
@@ -0,0 +1,22 @@
+Basic Web Project
+=================
+
+This project demonstrates a simple setup with HTML, CSS, and JavaScript. It includes a single webpage (index.html),
+a stylesheet (styles.css), and a script (script.js).
+
+How to Run
+----------
+1. Open the `index.html` file in a web browser to view the project.
+
+Project Files
+-------------
+- `index.html`: The main HTML file for the webpage.
+- `styles.css`: The external stylesheet for styling the webpage.
+- `script.js`: The external JavaScript file for interactive behavior.
+
+Intended IDE
+------------
+This project was created using Visual Studio Code (VSCode). You can use other IDEs like WebStorm, NetBeans, or IntelliJ
+if preferred.
+
+To edit or extend this project, open the folder in your IDE and modify the files as needed.
diff --git a/Issue2/images/.gitkeep b/Issue2/images/.gitkeep
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Issue2/images/hangman.jpg b/Issue2/images/hangman.jpg
new file mode 100755
index 0000000000000000000000000000000000000000..b68200efbc7ab3c42599fe3a94cc28da5e0c0d66
Binary files /dev/null and b/Issue2/images/hangman.jpg differ
diff --git a/Issue2/index.html b/Issue2/index.html
new file mode 100755
index 0000000000000000000000000000000000000000..07e16745097e15ea2f8e3c59b73684db013f35d1
--- /dev/null
+++ b/Issue2/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+ Basic Web Project
+
+
+
+
+
Welcome to Hangle
+
+
+
+
Better than hang-man and wordle
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Issue2/script.js b/Issue2/script.js
new file mode 100755
index 0000000000000000000000000000000000000000..0459232ea1aa95c616e795c045c65b5f4b199a48
--- /dev/null
+++ b/Issue2/script.js
@@ -0,0 +1,3 @@
+document.getElementById('alertButton').addEventListener('click', () => {
+ alert('Hello! This button is working!');
+});
\ No newline at end of file
diff --git a/Issue2/styles.css b/Issue2/styles.css
new file mode 100755
index 0000000000000000000000000000000000000000..04a632c0fdd5fc991952421b4e8434ec82e6ad6a
--- /dev/null
+++ b/Issue2/styles.css
@@ -0,0 +1,39 @@
+body {
+ font-family: Arial, sans-serif;
+ margin: 0;
+ padding: 0;
+ background-color: #f0f0f0;
+ color: #333;
+}
+
+header {
+ background-color: #4CAF50;
+ color: white;
+ text-align: center;
+ padding: 1em 0;
+}
+
+main {
+ padding: 2em;
+ text-align: center;
+}
+
+button {
+ padding: 0.5em 1em;
+ background-color: #4CAF50;
+ color: white;
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+}
+
+button:hover {
+ background-color: #45a049;
+}
+img {
+ border: 2px solid #ccc;
+ border-radius: 10px;
+ box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5);
+ display: block;
+ margin: 20px auto;
+}
\ No newline at end of file
diff --git a/Issue4/.gitkeep b/Issue4/.gitkeep
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Issue4/amIPositive.js b/Issue4/amIPositive.js
new file mode 100755
index 0000000000000000000000000000000000000000..f3879fb3286e7611b27adcf2dd1e40333c552ce8
--- /dev/null
+++ b/Issue4/amIPositive.js
@@ -0,0 +1,8 @@
+/**
+ * @param num A number
+ * @return true iff num is greater than 0
+ */
+function amIPositive(num){
+ return num > 0;
+}
+module.exports = amIPositive;
\ No newline at end of file
diff --git a/Issue4/amIPositive.test.js b/Issue4/amIPositive.test.js
new file mode 100755
index 0000000000000000000000000000000000000000..8cbee31633e80670cad17149bf9307beff29ebbe
--- /dev/null
+++ b/Issue4/amIPositive.test.js
@@ -0,0 +1,9 @@
+
+const amIPositive = require('./amIPositive');
+
+test('testAmIPositive', () => {
+
+ expect(amIPositive(5)).toBe(true);
+ expect(amIPositive(-1)).toBe(false);
+ expect(amIPositive(0)).toBe(false);
+});
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/browserslist b/Issue4/node_modules/.bin/browserslist
new file mode 120000
index 0000000000000000000000000000000000000000..3cd991b25889f57066bd84dac91a170faacf2ce0
--- /dev/null
+++ b/Issue4/node_modules/.bin/browserslist
@@ -0,0 +1 @@
+../browserslist/cli.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/create-jest b/Issue4/node_modules/.bin/create-jest
new file mode 120000
index 0000000000000000000000000000000000000000..8d6301e0fe27451f08128afb69bd353ad8454e12
--- /dev/null
+++ b/Issue4/node_modules/.bin/create-jest
@@ -0,0 +1 @@
+../create-jest/bin/create-jest.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/esparse b/Issue4/node_modules/.bin/esparse
new file mode 120000
index 0000000000000000000000000000000000000000..7423b18b24efb09ee2916ad6db079b83ef0eb132
--- /dev/null
+++ b/Issue4/node_modules/.bin/esparse
@@ -0,0 +1 @@
+../esprima/bin/esparse.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/esvalidate b/Issue4/node_modules/.bin/esvalidate
new file mode 120000
index 0000000000000000000000000000000000000000..16069effbc99a3dfc83b6a7b8f04a2c18fb9861f
--- /dev/null
+++ b/Issue4/node_modules/.bin/esvalidate
@@ -0,0 +1 @@
+../esprima/bin/esvalidate.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/import-local-fixture b/Issue4/node_modules/.bin/import-local-fixture
new file mode 120000
index 0000000000000000000000000000000000000000..ff4b104829f24894b0218a17d811684df96431fe
--- /dev/null
+++ b/Issue4/node_modules/.bin/import-local-fixture
@@ -0,0 +1 @@
+../import-local/fixtures/cli.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/jest b/Issue4/node_modules/.bin/jest
new file mode 120000
index 0000000000000000000000000000000000000000..61c186154294ce526897d071f42ac6e2c09b0762
--- /dev/null
+++ b/Issue4/node_modules/.bin/jest
@@ -0,0 +1 @@
+../jest/bin/jest.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/js-yaml b/Issue4/node_modules/.bin/js-yaml
new file mode 120000
index 0000000000000000000000000000000000000000..9dbd010d470368b942148cb9ec3acf02d7aac993
--- /dev/null
+++ b/Issue4/node_modules/.bin/js-yaml
@@ -0,0 +1 @@
+../js-yaml/bin/js-yaml.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/jsesc b/Issue4/node_modules/.bin/jsesc
new file mode 120000
index 0000000000000000000000000000000000000000..7237604c357fcd14956d824342803e6a19542461
--- /dev/null
+++ b/Issue4/node_modules/.bin/jsesc
@@ -0,0 +1 @@
+../jsesc/bin/jsesc
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/json5 b/Issue4/node_modules/.bin/json5
new file mode 120000
index 0000000000000000000000000000000000000000..217f37981d7a988fe3ef9b1179774023a96a224c
--- /dev/null
+++ b/Issue4/node_modules/.bin/json5
@@ -0,0 +1 @@
+../json5/lib/cli.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/node-which b/Issue4/node_modules/.bin/node-which
new file mode 120000
index 0000000000000000000000000000000000000000..6f8415ec58dffcb931a5808d19e3c39a0430f581
--- /dev/null
+++ b/Issue4/node_modules/.bin/node-which
@@ -0,0 +1 @@
+../which/bin/node-which
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/parser b/Issue4/node_modules/.bin/parser
new file mode 120000
index 0000000000000000000000000000000000000000..ce7bf97efb312b0e7d04416403294f8134c9e551
--- /dev/null
+++ b/Issue4/node_modules/.bin/parser
@@ -0,0 +1 @@
+../@babel/parser/bin/babel-parser.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/resolve b/Issue4/node_modules/.bin/resolve
new file mode 120000
index 0000000000000000000000000000000000000000..b6afda6c753f1fb771d1ae4bb413ee11c4cd0037
--- /dev/null
+++ b/Issue4/node_modules/.bin/resolve
@@ -0,0 +1 @@
+../resolve/bin/resolve
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/semver b/Issue4/node_modules/.bin/semver
new file mode 120000
index 0000000000000000000000000000000000000000..5aaadf42c4a8b282cbf6cc5c73e6ea0beedd2d46
--- /dev/null
+++ b/Issue4/node_modules/.bin/semver
@@ -0,0 +1 @@
+../semver/bin/semver.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.bin/update-browserslist-db b/Issue4/node_modules/.bin/update-browserslist-db
new file mode 120000
index 0000000000000000000000000000000000000000..b11e16f3d5c54b6365c37fa71087e2454e750393
--- /dev/null
+++ b/Issue4/node_modules/.bin/update-browserslist-db
@@ -0,0 +1 @@
+../update-browserslist-db/cli.js
\ No newline at end of file
diff --git a/Issue4/node_modules/.package-lock.json b/Issue4/node_modules/.package-lock.json
new file mode 100755
index 0000000000000000000000000000000000000000..5c59990d3d38cf87715d2e184c5886aaca1b36f4
--- /dev/null
+++ b/Issue4/node_modules/.package-lock.json
@@ -0,0 +1,3629 @@
+{
+ "name": "unittest",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz",
+ "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
+ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.0",
+ "@babel/generator": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.0",
+ "@babel/parser": "^7.26.0",
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.26.0",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz",
+ "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.26.2",
+ "@babel/types": "^7.26.0",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
+ "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
+ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
+ "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.26.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
+ "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.26.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz",
+ "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
+ "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "22.9.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.3.tgz",
+ "integrity": "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.8"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
+ "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
+ "node-releases": "^2.0.18",
+ "update-browserslist-db": "^1.1.1"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001683",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001683.tgz",
+ "integrity": "sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz",
+ "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.64",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.64.tgz",
+ "integrity": "sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
+ "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
+ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/Issue4/node_modules/@ampproject/remapping/LICENSE b/Issue4/node_modules/@ampproject/remapping/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Issue4/node_modules/@ampproject/remapping/README.md b/Issue4/node_modules/@ampproject/remapping/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..1463c9f6289d6aec71987d5299b8806af4821fb4
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/README.md
@@ -0,0 +1,218 @@
+# @ampproject/remapping
+
+> Remap sequential sourcemaps through transformations to point at the original source code
+
+Remapping allows you to take the sourcemaps generated through transforming your code and "remap"
+them to the original source locations. Think "my minified code, transformed with babel and bundled
+with webpack", all pointing to the correct location in your original source code.
+
+With remapping, none of your source code transformations need to be aware of the input's sourcemap,
+they only need to generate an output sourcemap. This greatly simplifies building custom
+transformations (think a find-and-replace).
+
+## Installation
+
+```sh
+npm install @ampproject/remapping
+```
+
+## Usage
+
+```typescript
+function remapping(
+ map: SourceMap | SourceMap[],
+ loader: (file: string, ctx: LoaderContext) => (SourceMap | null | undefined),
+ options?: { excludeContent: boolean, decodedMappings: boolean }
+): SourceMap;
+
+// LoaderContext gives the loader the importing sourcemap, tree depth, the ability to override the
+// "source" location (where child sources are resolved relative to, or the location of original
+// source), and the ability to override the "content" of an original source for inclusion in the
+// output sourcemap.
+type LoaderContext = {
+ readonly importer: string;
+ readonly depth: number;
+ source: string;
+ content: string | null | undefined;
+}
+```
+
+`remapping` takes the final output sourcemap, and a `loader` function. For every source file pointer
+in the sourcemap, the `loader` will be called with the resolved path. If the path itself represents
+a transformed file (it has a sourcmap associated with it), then the `loader` should return that
+sourcemap. If not, the path will be treated as an original, untransformed source code.
+
+```js
+// Babel transformed "helloworld.js" into "transformed.js"
+const transformedMap = JSON.stringify({
+ file: 'transformed.js',
+ // 1st column of 2nd line of output file translates into the 1st source
+ // file, line 3, column 2
+ mappings: ';CAEE',
+ sources: ['helloworld.js'],
+ version: 3,
+});
+
+// Uglify minified "transformed.js" into "transformed.min.js"
+const minifiedTransformedMap = JSON.stringify({
+ file: 'transformed.min.js',
+ // 0th column of 1st line of output file translates into the 1st source
+ // file, line 2, column 1.
+ mappings: 'AACC',
+ names: [],
+ sources: ['transformed.js'],
+ version: 3,
+});
+
+const remapped = remapping(
+ minifiedTransformedMap,
+ (file, ctx) => {
+
+ // The "transformed.js" file is an transformed file.
+ if (file === 'transformed.js') {
+ // The root importer is empty.
+ console.assert(ctx.importer === '');
+ // The depth in the sourcemap tree we're currently loading.
+ // The root `minifiedTransformedMap` is depth 0, and its source children are depth 1, etc.
+ console.assert(ctx.depth === 1);
+
+ return transformedMap;
+ }
+
+ // Loader will be called to load transformedMap's source file pointers as well.
+ console.assert(file === 'helloworld.js');
+ // `transformed.js`'s sourcemap points into `helloworld.js`.
+ console.assert(ctx.importer === 'transformed.js');
+ // This is a source child of `transformed`, which is a source child of `minifiedTransformedMap`.
+ console.assert(ctx.depth === 2);
+ return null;
+ }
+);
+
+console.log(remapped);
+// {
+// file: 'transpiled.min.js',
+// mappings: 'AAEE',
+// sources: ['helloworld.js'],
+// version: 3,
+// };
+```
+
+In this example, `loader` will be called twice:
+
+1. `"transformed.js"`, the first source file pointer in the `minifiedTransformedMap`. We return the
+ associated sourcemap for it (its a transformed file, after all) so that sourcemap locations can
+ be traced through it into the source files it represents.
+2. `"helloworld.js"`, our original, unmodified source code. This file does not have a sourcemap, so
+ we return `null`.
+
+The `remapped` sourcemap now points from `transformed.min.js` into locations in `helloworld.js`. If
+you were to read the `mappings`, it says "0th column of the first line output line points to the 1st
+column of the 2nd line of the file `helloworld.js`".
+
+### Multiple transformations of a file
+
+As a convenience, if you have multiple single-source transformations of a file, you may pass an
+array of sourcemap files in the order of most-recent transformation sourcemap first. Note that this
+changes the `importer` and `depth` of each call to our loader. So our above example could have been
+written as:
+
+```js
+const remapped = remapping(
+ [minifiedTransformedMap, transformedMap],
+ () => null
+);
+
+console.log(remapped);
+// {
+// file: 'transpiled.min.js',
+// mappings: 'AAEE',
+// sources: ['helloworld.js'],
+// version: 3,
+// };
+```
+
+### Advanced control of the loading graph
+
+#### `source`
+
+The `source` property can overridden to any value to change the location of the current load. Eg,
+for an original source file, it allows us to change the location to the original source regardless
+of what the sourcemap source entry says. And for transformed files, it allows us to change the
+relative resolving location for child sources of the loaded sourcemap.
+
+```js
+const remapped = remapping(
+ minifiedTransformedMap,
+ (file, ctx) => {
+
+ if (file === 'transformed.js') {
+ // We pretend the transformed.js file actually exists in the 'src/' directory. When the nested
+ // source files are loaded, they will now be relative to `src/`.
+ ctx.source = 'src/transformed.js';
+ return transformedMap;
+ }
+
+ console.assert(file === 'src/helloworld.js');
+ // We could futher change the source of this original file, eg, to be inside a nested directory
+ // itself. This will be reflected in the remapped sourcemap.
+ ctx.source = 'src/nested/transformed.js';
+ return null;
+ }
+);
+
+console.log(remapped);
+// {
+// …,
+// sources: ['src/nested/helloworld.js'],
+// };
+```
+
+
+#### `content`
+
+The `content` property can be overridden when we encounter an original source file. Eg, this allows
+you to manually provide the source content of the original file regardless of whether the
+`sourcesContent` field is present in the parent sourcemap. It can also be set to `null` to remove
+the source content.
+
+```js
+const remapped = remapping(
+ minifiedTransformedMap,
+ (file, ctx) => {
+
+ if (file === 'transformed.js') {
+ // transformedMap does not include a `sourcesContent` field, so usually the remapped sourcemap
+ // would not include any `sourcesContent` values.
+ return transformedMap;
+ }
+
+ console.assert(file === 'helloworld.js');
+ // We can read the file to provide the source content.
+ ctx.content = fs.readFileSync(file, 'utf8');
+ return null;
+ }
+);
+
+console.log(remapped);
+// {
+// …,
+// sourcesContent: [
+// 'console.log("Hello world!")',
+// ],
+// };
+```
+
+### Options
+
+#### excludeContent
+
+By default, `excludeContent` is `false`. Passing `{ excludeContent: true }` will exclude the
+`sourcesContent` field from the returned sourcemap. This is mainly useful when you want to reduce
+the size out the sourcemap.
+
+#### decodedMappings
+
+By default, `decodedMappings` is `false`. Passing `{ decodedMappings: true }` will leave the
+`mappings` field in a [decoded state](https://github.com/rich-harris/sourcemap-codec) instead of
+encoding into a VLQ string.
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/remapping.mjs b/Issue4/node_modules/@ampproject/remapping/dist/remapping.mjs
new file mode 100755
index 0000000000000000000000000000000000000000..f3875999c027f75f69e1b22f7d8fedb1eceef63e
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/remapping.mjs
@@ -0,0 +1,197 @@
+import { decodedMappings, traceSegment, TraceMap } from '@jridgewell/trace-mapping';
+import { GenMapping, maybeAddSegment, setSourceContent, setIgnore, toDecodedMap, toEncodedMap } from '@jridgewell/gen-mapping';
+
+const SOURCELESS_MAPPING = /* #__PURE__ */ SegmentObject('', -1, -1, '', null, false);
+const EMPTY_SOURCES = [];
+function SegmentObject(source, line, column, name, content, ignore) {
+ return { source, line, column, name, content, ignore };
+}
+function Source(map, sources, source, content, ignore) {
+ return {
+ map,
+ sources,
+ source,
+ content,
+ ignore,
+ };
+}
+/**
+ * MapSource represents a single sourcemap, with the ability to trace mappings into its child nodes
+ * (which may themselves be SourceMapTrees).
+ */
+function MapSource(map, sources) {
+ return Source(map, sources, '', null, false);
+}
+/**
+ * A "leaf" node in the sourcemap tree, representing an original, unmodified source file. Recursive
+ * segment tracing ends at the `OriginalSource`.
+ */
+function OriginalSource(source, content, ignore) {
+ return Source(null, EMPTY_SOURCES, source, content, ignore);
+}
+/**
+ * traceMappings is only called on the root level SourceMapTree, and begins the process of
+ * resolving each mapping in terms of the original source files.
+ */
+function traceMappings(tree) {
+ // TODO: Eventually support sourceRoot, which has to be removed because the sources are already
+ // fully resolved. We'll need to make sources relative to the sourceRoot before adding them.
+ const gen = new GenMapping({ file: tree.map.file });
+ const { sources: rootSources, map } = tree;
+ const rootNames = map.names;
+ const rootMappings = decodedMappings(map);
+ for (let i = 0; i < rootMappings.length; i++) {
+ const segments = rootMappings[i];
+ for (let j = 0; j < segments.length; j++) {
+ const segment = segments[j];
+ const genCol = segment[0];
+ let traced = SOURCELESS_MAPPING;
+ // 1-length segments only move the current generated column, there's no source information
+ // to gather from it.
+ if (segment.length !== 1) {
+ const source = rootSources[segment[1]];
+ traced = originalPositionFor(source, segment[2], segment[3], segment.length === 5 ? rootNames[segment[4]] : '');
+ // If the trace is invalid, then the trace ran into a sourcemap that doesn't contain a
+ // respective segment into an original source.
+ if (traced == null)
+ continue;
+ }
+ const { column, line, name, content, source, ignore } = traced;
+ maybeAddSegment(gen, i, genCol, source, line, column, name);
+ if (source && content != null)
+ setSourceContent(gen, source, content);
+ if (ignore)
+ setIgnore(gen, source, true);
+ }
+ }
+ return gen;
+}
+/**
+ * originalPositionFor is only called on children SourceMapTrees. It recurses down into its own
+ * child SourceMapTrees, until we find the original source map.
+ */
+function originalPositionFor(source, line, column, name) {
+ if (!source.map) {
+ return SegmentObject(source.source, line, column, name, source.content, source.ignore);
+ }
+ const segment = traceSegment(source.map, line, column);
+ // If we couldn't find a segment, then this doesn't exist in the sourcemap.
+ if (segment == null)
+ return null;
+ // 1-length segments only move the current generated column, there's no source information
+ // to gather from it.
+ if (segment.length === 1)
+ return SOURCELESS_MAPPING;
+ return originalPositionFor(source.sources[segment[1]], segment[2], segment[3], segment.length === 5 ? source.map.names[segment[4]] : name);
+}
+
+function asArray(value) {
+ if (Array.isArray(value))
+ return value;
+ return [value];
+}
+/**
+ * Recursively builds a tree structure out of sourcemap files, with each node
+ * being either an `OriginalSource` "leaf" or a `SourceMapTree` composed of
+ * `OriginalSource`s and `SourceMapTree`s.
+ *
+ * Every sourcemap is composed of a collection of source files and mappings
+ * into locations of those source files. When we generate a `SourceMapTree` for
+ * the sourcemap, we attempt to load each source file's own sourcemap. If it
+ * does not have an associated sourcemap, it is considered an original,
+ * unmodified source file.
+ */
+function buildSourceMapTree(input, loader) {
+ const maps = asArray(input).map((m) => new TraceMap(m, ''));
+ const map = maps.pop();
+ for (let i = 0; i < maps.length; i++) {
+ if (maps[i].sources.length > 1) {
+ throw new Error(`Transformation map ${i} must have exactly one source file.\n` +
+ 'Did you specify these with the most recent transformation maps first?');
+ }
+ }
+ let tree = build(map, loader, '', 0);
+ for (let i = maps.length - 1; i >= 0; i--) {
+ tree = MapSource(maps[i], [tree]);
+ }
+ return tree;
+}
+function build(map, loader, importer, importerDepth) {
+ const { resolvedSources, sourcesContent, ignoreList } = map;
+ const depth = importerDepth + 1;
+ const children = resolvedSources.map((sourceFile, i) => {
+ // The loading context gives the loader more information about why this file is being loaded
+ // (eg, from which importer). It also allows the loader to override the location of the loaded
+ // sourcemap/original source, or to override the content in the sourcesContent field if it's
+ // an unmodified source file.
+ const ctx = {
+ importer,
+ depth,
+ source: sourceFile || '',
+ content: undefined,
+ ignore: undefined,
+ };
+ // Use the provided loader callback to retrieve the file's sourcemap.
+ // TODO: We should eventually support async loading of sourcemap files.
+ const sourceMap = loader(ctx.source, ctx);
+ const { source, content, ignore } = ctx;
+ // If there is a sourcemap, then we need to recurse into it to load its source files.
+ if (sourceMap)
+ return build(new TraceMap(sourceMap, source), loader, source, depth);
+ // Else, it's an unmodified source file.
+ // The contents of this unmodified source file can be overridden via the loader context,
+ // allowing it to be explicitly null or a string. If it remains undefined, we fall back to
+ // the importing sourcemap's `sourcesContent` field.
+ const sourceContent = content !== undefined ? content : sourcesContent ? sourcesContent[i] : null;
+ const ignored = ignore !== undefined ? ignore : ignoreList ? ignoreList.includes(i) : false;
+ return OriginalSource(source, sourceContent, ignored);
+ });
+ return MapSource(map, children);
+}
+
+/**
+ * A SourceMap v3 compatible sourcemap, which only includes fields that were
+ * provided to it.
+ */
+class SourceMap {
+ constructor(map, options) {
+ const out = options.decodedMappings ? toDecodedMap(map) : toEncodedMap(map);
+ this.version = out.version; // SourceMap spec says this should be first.
+ this.file = out.file;
+ this.mappings = out.mappings;
+ this.names = out.names;
+ this.ignoreList = out.ignoreList;
+ this.sourceRoot = out.sourceRoot;
+ this.sources = out.sources;
+ if (!options.excludeContent) {
+ this.sourcesContent = out.sourcesContent;
+ }
+ }
+ toString() {
+ return JSON.stringify(this);
+ }
+}
+
+/**
+ * Traces through all the mappings in the root sourcemap, through the sources
+ * (and their sourcemaps), all the way back to the original source location.
+ *
+ * `loader` will be called every time we encounter a source file. If it returns
+ * a sourcemap, we will recurse into that sourcemap to continue the trace. If
+ * it returns a falsey value, that source file is treated as an original,
+ * unmodified source file.
+ *
+ * Pass `excludeContent` to exclude any self-containing source file content
+ * from the output sourcemap.
+ *
+ * Pass `decodedMappings` to receive a SourceMap with decoded (instead of
+ * VLQ encoded) mappings.
+ */
+function remapping(input, loader, options) {
+ const opts = typeof options === 'object' ? options : { excludeContent: !!options, decodedMappings: false };
+ const tree = buildSourceMapTree(input, loader);
+ return new SourceMap(traceMappings(tree), opts);
+}
+
+export { remapping as default };
+//# sourceMappingURL=remapping.mjs.map
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/remapping.mjs.map b/Issue4/node_modules/@ampproject/remapping/dist/remapping.mjs.map
new file mode 100755
index 0000000000000000000000000000000000000000..0eb007bfdf5fd31d2d2292e7e24fbd7e859a06d8
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/remapping.mjs.map
@@ -0,0 +1 @@
+{"version":3,"file":"remapping.mjs","sources":["../src/source-map-tree.ts","../src/build-source-map-tree.ts","../src/source-map.ts","../src/remapping.ts"],"sourcesContent":["import { GenMapping, maybeAddSegment, setIgnore, setSourceContent } from '@jridgewell/gen-mapping';\nimport { traceSegment, decodedMappings } from '@jridgewell/trace-mapping';\n\nimport type { TraceMap } from '@jridgewell/trace-mapping';\n\nexport type SourceMapSegmentObject = {\n column: number;\n line: number;\n name: string;\n source: string;\n content: string | null;\n ignore: boolean;\n};\n\nexport type OriginalSource = {\n map: null;\n sources: Sources[];\n source: string;\n content: string | null;\n ignore: boolean;\n};\n\nexport type MapSource = {\n map: TraceMap;\n sources: Sources[];\n source: string;\n content: null;\n ignore: false;\n};\n\nexport type Sources = OriginalSource | MapSource;\n\nconst SOURCELESS_MAPPING = /* #__PURE__ */ SegmentObject('', -1, -1, '', null, false);\nconst EMPTY_SOURCES: Sources[] = [];\n\nfunction SegmentObject(\n source: string,\n line: number,\n column: number,\n name: string,\n content: string | null,\n ignore: boolean\n): SourceMapSegmentObject {\n return { source, line, column, name, content, ignore };\n}\n\nfunction Source(\n map: TraceMap,\n sources: Sources[],\n source: '',\n content: null,\n ignore: false\n): MapSource;\nfunction Source(\n map: null,\n sources: Sources[],\n source: string,\n content: string | null,\n ignore: boolean\n): OriginalSource;\nfunction Source(\n map: TraceMap | null,\n sources: Sources[],\n source: string | '',\n content: string | null,\n ignore: boolean\n): Sources {\n return {\n map,\n sources,\n source,\n content,\n ignore,\n } as any;\n}\n\n/**\n * MapSource represents a single sourcemap, with the ability to trace mappings into its child nodes\n * (which may themselves be SourceMapTrees).\n */\nexport function MapSource(map: TraceMap, sources: Sources[]): MapSource {\n return Source(map, sources, '', null, false);\n}\n\n/**\n * A \"leaf\" node in the sourcemap tree, representing an original, unmodified source file. Recursive\n * segment tracing ends at the `OriginalSource`.\n */\nexport function OriginalSource(\n source: string,\n content: string | null,\n ignore: boolean\n): OriginalSource {\n return Source(null, EMPTY_SOURCES, source, content, ignore);\n}\n\n/**\n * traceMappings is only called on the root level SourceMapTree, and begins the process of\n * resolving each mapping in terms of the original source files.\n */\nexport function traceMappings(tree: MapSource): GenMapping {\n // TODO: Eventually support sourceRoot, which has to be removed because the sources are already\n // fully resolved. We'll need to make sources relative to the sourceRoot before adding them.\n const gen = new GenMapping({ file: tree.map.file });\n const { sources: rootSources, map } = tree;\n const rootNames = map.names;\n const rootMappings = decodedMappings(map);\n\n for (let i = 0; i < rootMappings.length; i++) {\n const segments = rootMappings[i];\n\n for (let j = 0; j < segments.length; j++) {\n const segment = segments[j];\n const genCol = segment[0];\n let traced: SourceMapSegmentObject | null = SOURCELESS_MAPPING;\n\n // 1-length segments only move the current generated column, there's no source information\n // to gather from it.\n if (segment.length !== 1) {\n const source = rootSources[segment[1]];\n traced = originalPositionFor(\n source,\n segment[2],\n segment[3],\n segment.length === 5 ? rootNames[segment[4]] : ''\n );\n\n // If the trace is invalid, then the trace ran into a sourcemap that doesn't contain a\n // respective segment into an original source.\n if (traced == null) continue;\n }\n\n const { column, line, name, content, source, ignore } = traced;\n\n maybeAddSegment(gen, i, genCol, source, line, column, name);\n if (source && content != null) setSourceContent(gen, source, content);\n if (ignore) setIgnore(gen, source, true);\n }\n }\n\n return gen;\n}\n\n/**\n * originalPositionFor is only called on children SourceMapTrees. It recurses down into its own\n * child SourceMapTrees, until we find the original source map.\n */\nexport function originalPositionFor(\n source: Sources,\n line: number,\n column: number,\n name: string\n): SourceMapSegmentObject | null {\n if (!source.map) {\n return SegmentObject(source.source, line, column, name, source.content, source.ignore);\n }\n\n const segment = traceSegment(source.map, line, column);\n\n // If we couldn't find a segment, then this doesn't exist in the sourcemap.\n if (segment == null) return null;\n // 1-length segments only move the current generated column, there's no source information\n // to gather from it.\n if (segment.length === 1) return SOURCELESS_MAPPING;\n\n return originalPositionFor(\n source.sources[segment[1]],\n segment[2],\n segment[3],\n segment.length === 5 ? source.map.names[segment[4]] : name\n );\n}\n","import { TraceMap } from '@jridgewell/trace-mapping';\n\nimport { OriginalSource, MapSource } from './source-map-tree';\n\nimport type { Sources, MapSource as MapSourceType } from './source-map-tree';\nimport type { SourceMapInput, SourceMapLoader, LoaderContext } from './types';\n\nfunction asArray(value: T | T[]): T[] {\n if (Array.isArray(value)) return value;\n return [value];\n}\n\n/**\n * Recursively builds a tree structure out of sourcemap files, with each node\n * being either an `OriginalSource` \"leaf\" or a `SourceMapTree` composed of\n * `OriginalSource`s and `SourceMapTree`s.\n *\n * Every sourcemap is composed of a collection of source files and mappings\n * into locations of those source files. When we generate a `SourceMapTree` for\n * the sourcemap, we attempt to load each source file's own sourcemap. If it\n * does not have an associated sourcemap, it is considered an original,\n * unmodified source file.\n */\nexport default function buildSourceMapTree(\n input: SourceMapInput | SourceMapInput[],\n loader: SourceMapLoader\n): MapSourceType {\n const maps = asArray(input).map((m) => new TraceMap(m, ''));\n const map = maps.pop()!;\n\n for (let i = 0; i < maps.length; i++) {\n if (maps[i].sources.length > 1) {\n throw new Error(\n `Transformation map ${i} must have exactly one source file.\\n` +\n 'Did you specify these with the most recent transformation maps first?'\n );\n }\n }\n\n let tree = build(map, loader, '', 0);\n for (let i = maps.length - 1; i >= 0; i--) {\n tree = MapSource(maps[i], [tree]);\n }\n return tree;\n}\n\nfunction build(\n map: TraceMap,\n loader: SourceMapLoader,\n importer: string,\n importerDepth: number\n): MapSourceType {\n const { resolvedSources, sourcesContent, ignoreList } = map;\n\n const depth = importerDepth + 1;\n const children = resolvedSources.map((sourceFile: string | null, i: number): Sources => {\n // The loading context gives the loader more information about why this file is being loaded\n // (eg, from which importer). It also allows the loader to override the location of the loaded\n // sourcemap/original source, or to override the content in the sourcesContent field if it's\n // an unmodified source file.\n const ctx: LoaderContext = {\n importer,\n depth,\n source: sourceFile || '',\n content: undefined,\n ignore: undefined,\n };\n\n // Use the provided loader callback to retrieve the file's sourcemap.\n // TODO: We should eventually support async loading of sourcemap files.\n const sourceMap = loader(ctx.source, ctx);\n\n const { source, content, ignore } = ctx;\n\n // If there is a sourcemap, then we need to recurse into it to load its source files.\n if (sourceMap) return build(new TraceMap(sourceMap, source), loader, source, depth);\n\n // Else, it's an unmodified source file.\n // The contents of this unmodified source file can be overridden via the loader context,\n // allowing it to be explicitly null or a string. If it remains undefined, we fall back to\n // the importing sourcemap's `sourcesContent` field.\n const sourceContent =\n content !== undefined ? content : sourcesContent ? sourcesContent[i] : null;\n const ignored = ignore !== undefined ? ignore : ignoreList ? ignoreList.includes(i) : false;\n return OriginalSource(source, sourceContent, ignored);\n });\n\n return MapSource(map, children);\n}\n","import { toDecodedMap, toEncodedMap } from '@jridgewell/gen-mapping';\n\nimport type { GenMapping } from '@jridgewell/gen-mapping';\nimport type { DecodedSourceMap, EncodedSourceMap, Options } from './types';\n\n/**\n * A SourceMap v3 compatible sourcemap, which only includes fields that were\n * provided to it.\n */\nexport default class SourceMap {\n declare file?: string | null;\n declare mappings: EncodedSourceMap['mappings'] | DecodedSourceMap['mappings'];\n declare sourceRoot?: string;\n declare names: string[];\n declare sources: (string | null)[];\n declare sourcesContent?: (string | null)[];\n declare version: 3;\n declare ignoreList: number[] | undefined;\n\n constructor(map: GenMapping, options: Options) {\n const out = options.decodedMappings ? toDecodedMap(map) : toEncodedMap(map);\n this.version = out.version; // SourceMap spec says this should be first.\n this.file = out.file;\n this.mappings = out.mappings as SourceMap['mappings'];\n this.names = out.names as SourceMap['names'];\n this.ignoreList = out.ignoreList as SourceMap['ignoreList'];\n this.sourceRoot = out.sourceRoot;\n\n this.sources = out.sources as SourceMap['sources'];\n if (!options.excludeContent) {\n this.sourcesContent = out.sourcesContent as SourceMap['sourcesContent'];\n }\n }\n\n toString(): string {\n return JSON.stringify(this);\n }\n}\n","import buildSourceMapTree from './build-source-map-tree';\nimport { traceMappings } from './source-map-tree';\nimport SourceMap from './source-map';\n\nimport type { SourceMapInput, SourceMapLoader, Options } from './types';\nexport type {\n SourceMapSegment,\n EncodedSourceMap,\n EncodedSourceMap as RawSourceMap,\n DecodedSourceMap,\n SourceMapInput,\n SourceMapLoader,\n LoaderContext,\n Options,\n} from './types';\nexport type { SourceMap };\n\n/**\n * Traces through all the mappings in the root sourcemap, through the sources\n * (and their sourcemaps), all the way back to the original source location.\n *\n * `loader` will be called every time we encounter a source file. If it returns\n * a sourcemap, we will recurse into that sourcemap to continue the trace. If\n * it returns a falsey value, that source file is treated as an original,\n * unmodified source file.\n *\n * Pass `excludeContent` to exclude any self-containing source file content\n * from the output sourcemap.\n *\n * Pass `decodedMappings` to receive a SourceMap with decoded (instead of\n * VLQ encoded) mappings.\n */\nexport default function remapping(\n input: SourceMapInput | SourceMapInput[],\n loader: SourceMapLoader,\n options?: boolean | Options\n): SourceMap {\n const opts =\n typeof options === 'object' ? options : { excludeContent: !!options, decodedMappings: false };\n const tree = buildSourceMapTree(input, loader);\n return new SourceMap(traceMappings(tree), opts);\n}\n"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/remapping.umd.js b/Issue4/node_modules/@ampproject/remapping/dist/remapping.umd.js
new file mode 100755
index 0000000000000000000000000000000000000000..6b7b3bb520a45dc796f569274695bc9690a31cd5
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/remapping.umd.js
@@ -0,0 +1,202 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@jridgewell/trace-mapping'), require('@jridgewell/gen-mapping')) :
+ typeof define === 'function' && define.amd ? define(['@jridgewell/trace-mapping', '@jridgewell/gen-mapping'], factory) :
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.remapping = factory(global.traceMapping, global.genMapping));
+})(this, (function (traceMapping, genMapping) { 'use strict';
+
+ const SOURCELESS_MAPPING = /* #__PURE__ */ SegmentObject('', -1, -1, '', null, false);
+ const EMPTY_SOURCES = [];
+ function SegmentObject(source, line, column, name, content, ignore) {
+ return { source, line, column, name, content, ignore };
+ }
+ function Source(map, sources, source, content, ignore) {
+ return {
+ map,
+ sources,
+ source,
+ content,
+ ignore,
+ };
+ }
+ /**
+ * MapSource represents a single sourcemap, with the ability to trace mappings into its child nodes
+ * (which may themselves be SourceMapTrees).
+ */
+ function MapSource(map, sources) {
+ return Source(map, sources, '', null, false);
+ }
+ /**
+ * A "leaf" node in the sourcemap tree, representing an original, unmodified source file. Recursive
+ * segment tracing ends at the `OriginalSource`.
+ */
+ function OriginalSource(source, content, ignore) {
+ return Source(null, EMPTY_SOURCES, source, content, ignore);
+ }
+ /**
+ * traceMappings is only called on the root level SourceMapTree, and begins the process of
+ * resolving each mapping in terms of the original source files.
+ */
+ function traceMappings(tree) {
+ // TODO: Eventually support sourceRoot, which has to be removed because the sources are already
+ // fully resolved. We'll need to make sources relative to the sourceRoot before adding them.
+ const gen = new genMapping.GenMapping({ file: tree.map.file });
+ const { sources: rootSources, map } = tree;
+ const rootNames = map.names;
+ const rootMappings = traceMapping.decodedMappings(map);
+ for (let i = 0; i < rootMappings.length; i++) {
+ const segments = rootMappings[i];
+ for (let j = 0; j < segments.length; j++) {
+ const segment = segments[j];
+ const genCol = segment[0];
+ let traced = SOURCELESS_MAPPING;
+ // 1-length segments only move the current generated column, there's no source information
+ // to gather from it.
+ if (segment.length !== 1) {
+ const source = rootSources[segment[1]];
+ traced = originalPositionFor(source, segment[2], segment[3], segment.length === 5 ? rootNames[segment[4]] : '');
+ // If the trace is invalid, then the trace ran into a sourcemap that doesn't contain a
+ // respective segment into an original source.
+ if (traced == null)
+ continue;
+ }
+ const { column, line, name, content, source, ignore } = traced;
+ genMapping.maybeAddSegment(gen, i, genCol, source, line, column, name);
+ if (source && content != null)
+ genMapping.setSourceContent(gen, source, content);
+ if (ignore)
+ genMapping.setIgnore(gen, source, true);
+ }
+ }
+ return gen;
+ }
+ /**
+ * originalPositionFor is only called on children SourceMapTrees. It recurses down into its own
+ * child SourceMapTrees, until we find the original source map.
+ */
+ function originalPositionFor(source, line, column, name) {
+ if (!source.map) {
+ return SegmentObject(source.source, line, column, name, source.content, source.ignore);
+ }
+ const segment = traceMapping.traceSegment(source.map, line, column);
+ // If we couldn't find a segment, then this doesn't exist in the sourcemap.
+ if (segment == null)
+ return null;
+ // 1-length segments only move the current generated column, there's no source information
+ // to gather from it.
+ if (segment.length === 1)
+ return SOURCELESS_MAPPING;
+ return originalPositionFor(source.sources[segment[1]], segment[2], segment[3], segment.length === 5 ? source.map.names[segment[4]] : name);
+ }
+
+ function asArray(value) {
+ if (Array.isArray(value))
+ return value;
+ return [value];
+ }
+ /**
+ * Recursively builds a tree structure out of sourcemap files, with each node
+ * being either an `OriginalSource` "leaf" or a `SourceMapTree` composed of
+ * `OriginalSource`s and `SourceMapTree`s.
+ *
+ * Every sourcemap is composed of a collection of source files and mappings
+ * into locations of those source files. When we generate a `SourceMapTree` for
+ * the sourcemap, we attempt to load each source file's own sourcemap. If it
+ * does not have an associated sourcemap, it is considered an original,
+ * unmodified source file.
+ */
+ function buildSourceMapTree(input, loader) {
+ const maps = asArray(input).map((m) => new traceMapping.TraceMap(m, ''));
+ const map = maps.pop();
+ for (let i = 0; i < maps.length; i++) {
+ if (maps[i].sources.length > 1) {
+ throw new Error(`Transformation map ${i} must have exactly one source file.\n` +
+ 'Did you specify these with the most recent transformation maps first?');
+ }
+ }
+ let tree = build(map, loader, '', 0);
+ for (let i = maps.length - 1; i >= 0; i--) {
+ tree = MapSource(maps[i], [tree]);
+ }
+ return tree;
+ }
+ function build(map, loader, importer, importerDepth) {
+ const { resolvedSources, sourcesContent, ignoreList } = map;
+ const depth = importerDepth + 1;
+ const children = resolvedSources.map((sourceFile, i) => {
+ // The loading context gives the loader more information about why this file is being loaded
+ // (eg, from which importer). It also allows the loader to override the location of the loaded
+ // sourcemap/original source, or to override the content in the sourcesContent field if it's
+ // an unmodified source file.
+ const ctx = {
+ importer,
+ depth,
+ source: sourceFile || '',
+ content: undefined,
+ ignore: undefined,
+ };
+ // Use the provided loader callback to retrieve the file's sourcemap.
+ // TODO: We should eventually support async loading of sourcemap files.
+ const sourceMap = loader(ctx.source, ctx);
+ const { source, content, ignore } = ctx;
+ // If there is a sourcemap, then we need to recurse into it to load its source files.
+ if (sourceMap)
+ return build(new traceMapping.TraceMap(sourceMap, source), loader, source, depth);
+ // Else, it's an unmodified source file.
+ // The contents of this unmodified source file can be overridden via the loader context,
+ // allowing it to be explicitly null or a string. If it remains undefined, we fall back to
+ // the importing sourcemap's `sourcesContent` field.
+ const sourceContent = content !== undefined ? content : sourcesContent ? sourcesContent[i] : null;
+ const ignored = ignore !== undefined ? ignore : ignoreList ? ignoreList.includes(i) : false;
+ return OriginalSource(source, sourceContent, ignored);
+ });
+ return MapSource(map, children);
+ }
+
+ /**
+ * A SourceMap v3 compatible sourcemap, which only includes fields that were
+ * provided to it.
+ */
+ class SourceMap {
+ constructor(map, options) {
+ const out = options.decodedMappings ? genMapping.toDecodedMap(map) : genMapping.toEncodedMap(map);
+ this.version = out.version; // SourceMap spec says this should be first.
+ this.file = out.file;
+ this.mappings = out.mappings;
+ this.names = out.names;
+ this.ignoreList = out.ignoreList;
+ this.sourceRoot = out.sourceRoot;
+ this.sources = out.sources;
+ if (!options.excludeContent) {
+ this.sourcesContent = out.sourcesContent;
+ }
+ }
+ toString() {
+ return JSON.stringify(this);
+ }
+ }
+
+ /**
+ * Traces through all the mappings in the root sourcemap, through the sources
+ * (and their sourcemaps), all the way back to the original source location.
+ *
+ * `loader` will be called every time we encounter a source file. If it returns
+ * a sourcemap, we will recurse into that sourcemap to continue the trace. If
+ * it returns a falsey value, that source file is treated as an original,
+ * unmodified source file.
+ *
+ * Pass `excludeContent` to exclude any self-containing source file content
+ * from the output sourcemap.
+ *
+ * Pass `decodedMappings` to receive a SourceMap with decoded (instead of
+ * VLQ encoded) mappings.
+ */
+ function remapping(input, loader, options) {
+ const opts = typeof options === 'object' ? options : { excludeContent: !!options, decodedMappings: false };
+ const tree = buildSourceMapTree(input, loader);
+ return new SourceMap(traceMappings(tree), opts);
+ }
+
+ return remapping;
+
+}));
+//# sourceMappingURL=remapping.umd.js.map
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/remapping.umd.js.map b/Issue4/node_modules/@ampproject/remapping/dist/remapping.umd.js.map
new file mode 100755
index 0000000000000000000000000000000000000000..d3f0f87d00345dd1e6494cbcb0179afec02f1900
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/remapping.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"remapping.umd.js","sources":["../src/source-map-tree.ts","../src/build-source-map-tree.ts","../src/source-map.ts","../src/remapping.ts"],"sourcesContent":["import { GenMapping, maybeAddSegment, setIgnore, setSourceContent } from '@jridgewell/gen-mapping';\nimport { traceSegment, decodedMappings } from '@jridgewell/trace-mapping';\n\nimport type { TraceMap } from '@jridgewell/trace-mapping';\n\nexport type SourceMapSegmentObject = {\n column: number;\n line: number;\n name: string;\n source: string;\n content: string | null;\n ignore: boolean;\n};\n\nexport type OriginalSource = {\n map: null;\n sources: Sources[];\n source: string;\n content: string | null;\n ignore: boolean;\n};\n\nexport type MapSource = {\n map: TraceMap;\n sources: Sources[];\n source: string;\n content: null;\n ignore: false;\n};\n\nexport type Sources = OriginalSource | MapSource;\n\nconst SOURCELESS_MAPPING = /* #__PURE__ */ SegmentObject('', -1, -1, '', null, false);\nconst EMPTY_SOURCES: Sources[] = [];\n\nfunction SegmentObject(\n source: string,\n line: number,\n column: number,\n name: string,\n content: string | null,\n ignore: boolean\n): SourceMapSegmentObject {\n return { source, line, column, name, content, ignore };\n}\n\nfunction Source(\n map: TraceMap,\n sources: Sources[],\n source: '',\n content: null,\n ignore: false\n): MapSource;\nfunction Source(\n map: null,\n sources: Sources[],\n source: string,\n content: string | null,\n ignore: boolean\n): OriginalSource;\nfunction Source(\n map: TraceMap | null,\n sources: Sources[],\n source: string | '',\n content: string | null,\n ignore: boolean\n): Sources {\n return {\n map,\n sources,\n source,\n content,\n ignore,\n } as any;\n}\n\n/**\n * MapSource represents a single sourcemap, with the ability to trace mappings into its child nodes\n * (which may themselves be SourceMapTrees).\n */\nexport function MapSource(map: TraceMap, sources: Sources[]): MapSource {\n return Source(map, sources, '', null, false);\n}\n\n/**\n * A \"leaf\" node in the sourcemap tree, representing an original, unmodified source file. Recursive\n * segment tracing ends at the `OriginalSource`.\n */\nexport function OriginalSource(\n source: string,\n content: string | null,\n ignore: boolean\n): OriginalSource {\n return Source(null, EMPTY_SOURCES, source, content, ignore);\n}\n\n/**\n * traceMappings is only called on the root level SourceMapTree, and begins the process of\n * resolving each mapping in terms of the original source files.\n */\nexport function traceMappings(tree: MapSource): GenMapping {\n // TODO: Eventually support sourceRoot, which has to be removed because the sources are already\n // fully resolved. We'll need to make sources relative to the sourceRoot before adding them.\n const gen = new GenMapping({ file: tree.map.file });\n const { sources: rootSources, map } = tree;\n const rootNames = map.names;\n const rootMappings = decodedMappings(map);\n\n for (let i = 0; i < rootMappings.length; i++) {\n const segments = rootMappings[i];\n\n for (let j = 0; j < segments.length; j++) {\n const segment = segments[j];\n const genCol = segment[0];\n let traced: SourceMapSegmentObject | null = SOURCELESS_MAPPING;\n\n // 1-length segments only move the current generated column, there's no source information\n // to gather from it.\n if (segment.length !== 1) {\n const source = rootSources[segment[1]];\n traced = originalPositionFor(\n source,\n segment[2],\n segment[3],\n segment.length === 5 ? rootNames[segment[4]] : ''\n );\n\n // If the trace is invalid, then the trace ran into a sourcemap that doesn't contain a\n // respective segment into an original source.\n if (traced == null) continue;\n }\n\n const { column, line, name, content, source, ignore } = traced;\n\n maybeAddSegment(gen, i, genCol, source, line, column, name);\n if (source && content != null) setSourceContent(gen, source, content);\n if (ignore) setIgnore(gen, source, true);\n }\n }\n\n return gen;\n}\n\n/**\n * originalPositionFor is only called on children SourceMapTrees. It recurses down into its own\n * child SourceMapTrees, until we find the original source map.\n */\nexport function originalPositionFor(\n source: Sources,\n line: number,\n column: number,\n name: string\n): SourceMapSegmentObject | null {\n if (!source.map) {\n return SegmentObject(source.source, line, column, name, source.content, source.ignore);\n }\n\n const segment = traceSegment(source.map, line, column);\n\n // If we couldn't find a segment, then this doesn't exist in the sourcemap.\n if (segment == null) return null;\n // 1-length segments only move the current generated column, there's no source information\n // to gather from it.\n if (segment.length === 1) return SOURCELESS_MAPPING;\n\n return originalPositionFor(\n source.sources[segment[1]],\n segment[2],\n segment[3],\n segment.length === 5 ? source.map.names[segment[4]] : name\n );\n}\n","import { TraceMap } from '@jridgewell/trace-mapping';\n\nimport { OriginalSource, MapSource } from './source-map-tree';\n\nimport type { Sources, MapSource as MapSourceType } from './source-map-tree';\nimport type { SourceMapInput, SourceMapLoader, LoaderContext } from './types';\n\nfunction asArray(value: T | T[]): T[] {\n if (Array.isArray(value)) return value;\n return [value];\n}\n\n/**\n * Recursively builds a tree structure out of sourcemap files, with each node\n * being either an `OriginalSource` \"leaf\" or a `SourceMapTree` composed of\n * `OriginalSource`s and `SourceMapTree`s.\n *\n * Every sourcemap is composed of a collection of source files and mappings\n * into locations of those source files. When we generate a `SourceMapTree` for\n * the sourcemap, we attempt to load each source file's own sourcemap. If it\n * does not have an associated sourcemap, it is considered an original,\n * unmodified source file.\n */\nexport default function buildSourceMapTree(\n input: SourceMapInput | SourceMapInput[],\n loader: SourceMapLoader\n): MapSourceType {\n const maps = asArray(input).map((m) => new TraceMap(m, ''));\n const map = maps.pop()!;\n\n for (let i = 0; i < maps.length; i++) {\n if (maps[i].sources.length > 1) {\n throw new Error(\n `Transformation map ${i} must have exactly one source file.\\n` +\n 'Did you specify these with the most recent transformation maps first?'\n );\n }\n }\n\n let tree = build(map, loader, '', 0);\n for (let i = maps.length - 1; i >= 0; i--) {\n tree = MapSource(maps[i], [tree]);\n }\n return tree;\n}\n\nfunction build(\n map: TraceMap,\n loader: SourceMapLoader,\n importer: string,\n importerDepth: number\n): MapSourceType {\n const { resolvedSources, sourcesContent, ignoreList } = map;\n\n const depth = importerDepth + 1;\n const children = resolvedSources.map((sourceFile: string | null, i: number): Sources => {\n // The loading context gives the loader more information about why this file is being loaded\n // (eg, from which importer). It also allows the loader to override the location of the loaded\n // sourcemap/original source, or to override the content in the sourcesContent field if it's\n // an unmodified source file.\n const ctx: LoaderContext = {\n importer,\n depth,\n source: sourceFile || '',\n content: undefined,\n ignore: undefined,\n };\n\n // Use the provided loader callback to retrieve the file's sourcemap.\n // TODO: We should eventually support async loading of sourcemap files.\n const sourceMap = loader(ctx.source, ctx);\n\n const { source, content, ignore } = ctx;\n\n // If there is a sourcemap, then we need to recurse into it to load its source files.\n if (sourceMap) return build(new TraceMap(sourceMap, source), loader, source, depth);\n\n // Else, it's an unmodified source file.\n // The contents of this unmodified source file can be overridden via the loader context,\n // allowing it to be explicitly null or a string. If it remains undefined, we fall back to\n // the importing sourcemap's `sourcesContent` field.\n const sourceContent =\n content !== undefined ? content : sourcesContent ? sourcesContent[i] : null;\n const ignored = ignore !== undefined ? ignore : ignoreList ? ignoreList.includes(i) : false;\n return OriginalSource(source, sourceContent, ignored);\n });\n\n return MapSource(map, children);\n}\n","import { toDecodedMap, toEncodedMap } from '@jridgewell/gen-mapping';\n\nimport type { GenMapping } from '@jridgewell/gen-mapping';\nimport type { DecodedSourceMap, EncodedSourceMap, Options } from './types';\n\n/**\n * A SourceMap v3 compatible sourcemap, which only includes fields that were\n * provided to it.\n */\nexport default class SourceMap {\n declare file?: string | null;\n declare mappings: EncodedSourceMap['mappings'] | DecodedSourceMap['mappings'];\n declare sourceRoot?: string;\n declare names: string[];\n declare sources: (string | null)[];\n declare sourcesContent?: (string | null)[];\n declare version: 3;\n declare ignoreList: number[] | undefined;\n\n constructor(map: GenMapping, options: Options) {\n const out = options.decodedMappings ? toDecodedMap(map) : toEncodedMap(map);\n this.version = out.version; // SourceMap spec says this should be first.\n this.file = out.file;\n this.mappings = out.mappings as SourceMap['mappings'];\n this.names = out.names as SourceMap['names'];\n this.ignoreList = out.ignoreList as SourceMap['ignoreList'];\n this.sourceRoot = out.sourceRoot;\n\n this.sources = out.sources as SourceMap['sources'];\n if (!options.excludeContent) {\n this.sourcesContent = out.sourcesContent as SourceMap['sourcesContent'];\n }\n }\n\n toString(): string {\n return JSON.stringify(this);\n }\n}\n","import buildSourceMapTree from './build-source-map-tree';\nimport { traceMappings } from './source-map-tree';\nimport SourceMap from './source-map';\n\nimport type { SourceMapInput, SourceMapLoader, Options } from './types';\nexport type {\n SourceMapSegment,\n EncodedSourceMap,\n EncodedSourceMap as RawSourceMap,\n DecodedSourceMap,\n SourceMapInput,\n SourceMapLoader,\n LoaderContext,\n Options,\n} from './types';\nexport type { SourceMap };\n\n/**\n * Traces through all the mappings in the root sourcemap, through the sources\n * (and their sourcemaps), all the way back to the original source location.\n *\n * `loader` will be called every time we encounter a source file. If it returns\n * a sourcemap, we will recurse into that sourcemap to continue the trace. If\n * it returns a falsey value, that source file is treated as an original,\n * unmodified source file.\n *\n * Pass `excludeContent` to exclude any self-containing source file content\n * from the output sourcemap.\n *\n * Pass `decodedMappings` to receive a SourceMap with decoded (instead of\n * VLQ encoded) mappings.\n */\nexport default function remapping(\n input: SourceMapInput | SourceMapInput[],\n loader: SourceMapLoader,\n options?: boolean | Options\n): SourceMap {\n const opts =\n typeof options === 'object' ? options : { excludeContent: !!options, decodedMappings: false };\n const tree = buildSourceMapTree(input, loader);\n return new SourceMap(traceMappings(tree), opts);\n}\n"],"names":["GenMapping","decodedMappings","maybeAddSegment","setSourceContent","setIgnore","traceSegment","TraceMap","toDecodedMap","toEncodedMap"],"mappings":"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"}
\ No newline at end of file
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/types/build-source-map-tree.d.ts b/Issue4/node_modules/@ampproject/remapping/dist/types/build-source-map-tree.d.ts
new file mode 100755
index 0000000000000000000000000000000000000000..f87fceab779ab635c51c3c74248e3bdfedf22e4e
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/types/build-source-map-tree.d.ts
@@ -0,0 +1,14 @@
+import type { MapSource as MapSourceType } from './source-map-tree';
+import type { SourceMapInput, SourceMapLoader } from './types';
+/**
+ * Recursively builds a tree structure out of sourcemap files, with each node
+ * being either an `OriginalSource` "leaf" or a `SourceMapTree` composed of
+ * `OriginalSource`s and `SourceMapTree`s.
+ *
+ * Every sourcemap is composed of a collection of source files and mappings
+ * into locations of those source files. When we generate a `SourceMapTree` for
+ * the sourcemap, we attempt to load each source file's own sourcemap. If it
+ * does not have an associated sourcemap, it is considered an original,
+ * unmodified source file.
+ */
+export default function buildSourceMapTree(input: SourceMapInput | SourceMapInput[], loader: SourceMapLoader): MapSourceType;
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/types/remapping.d.ts b/Issue4/node_modules/@ampproject/remapping/dist/types/remapping.d.ts
new file mode 100755
index 0000000000000000000000000000000000000000..771fe30711abc13773e931edf8339d89ad0b5c4d
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/types/remapping.d.ts
@@ -0,0 +1,20 @@
+import SourceMap from './source-map';
+import type { SourceMapInput, SourceMapLoader, Options } from './types';
+export type { SourceMapSegment, EncodedSourceMap, EncodedSourceMap as RawSourceMap, DecodedSourceMap, SourceMapInput, SourceMapLoader, LoaderContext, Options, } from './types';
+export type { SourceMap };
+/**
+ * Traces through all the mappings in the root sourcemap, through the sources
+ * (and their sourcemaps), all the way back to the original source location.
+ *
+ * `loader` will be called every time we encounter a source file. If it returns
+ * a sourcemap, we will recurse into that sourcemap to continue the trace. If
+ * it returns a falsey value, that source file is treated as an original,
+ * unmodified source file.
+ *
+ * Pass `excludeContent` to exclude any self-containing source file content
+ * from the output sourcemap.
+ *
+ * Pass `decodedMappings` to receive a SourceMap with decoded (instead of
+ * VLQ encoded) mappings.
+ */
+export default function remapping(input: SourceMapInput | SourceMapInput[], loader: SourceMapLoader, options?: boolean | Options): SourceMap;
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/types/source-map-tree.d.ts b/Issue4/node_modules/@ampproject/remapping/dist/types/source-map-tree.d.ts
new file mode 100755
index 0000000000000000000000000000000000000000..935bc698fd386327dea9e47ee862aade7e4224ca
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/types/source-map-tree.d.ts
@@ -0,0 +1,45 @@
+import { GenMapping } from '@jridgewell/gen-mapping';
+import type { TraceMap } from '@jridgewell/trace-mapping';
+export declare type SourceMapSegmentObject = {
+ column: number;
+ line: number;
+ name: string;
+ source: string;
+ content: string | null;
+ ignore: boolean;
+};
+export declare type OriginalSource = {
+ map: null;
+ sources: Sources[];
+ source: string;
+ content: string | null;
+ ignore: boolean;
+};
+export declare type MapSource = {
+ map: TraceMap;
+ sources: Sources[];
+ source: string;
+ content: null;
+ ignore: false;
+};
+export declare type Sources = OriginalSource | MapSource;
+/**
+ * MapSource represents a single sourcemap, with the ability to trace mappings into its child nodes
+ * (which may themselves be SourceMapTrees).
+ */
+export declare function MapSource(map: TraceMap, sources: Sources[]): MapSource;
+/**
+ * A "leaf" node in the sourcemap tree, representing an original, unmodified source file. Recursive
+ * segment tracing ends at the `OriginalSource`.
+ */
+export declare function OriginalSource(source: string, content: string | null, ignore: boolean): OriginalSource;
+/**
+ * traceMappings is only called on the root level SourceMapTree, and begins the process of
+ * resolving each mapping in terms of the original source files.
+ */
+export declare function traceMappings(tree: MapSource): GenMapping;
+/**
+ * originalPositionFor is only called on children SourceMapTrees. It recurses down into its own
+ * child SourceMapTrees, until we find the original source map.
+ */
+export declare function originalPositionFor(source: Sources, line: number, column: number, name: string): SourceMapSegmentObject | null;
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/types/source-map.d.ts b/Issue4/node_modules/@ampproject/remapping/dist/types/source-map.d.ts
new file mode 100755
index 0000000000000000000000000000000000000000..cbd7f0afd08703134d12ed1238f374cc4f04cfd9
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/types/source-map.d.ts
@@ -0,0 +1,18 @@
+import type { GenMapping } from '@jridgewell/gen-mapping';
+import type { DecodedSourceMap, EncodedSourceMap, Options } from './types';
+/**
+ * A SourceMap v3 compatible sourcemap, which only includes fields that were
+ * provided to it.
+ */
+export default class SourceMap {
+ file?: string | null;
+ mappings: EncodedSourceMap['mappings'] | DecodedSourceMap['mappings'];
+ sourceRoot?: string;
+ names: string[];
+ sources: (string | null)[];
+ sourcesContent?: (string | null)[];
+ version: 3;
+ ignoreList: number[] | undefined;
+ constructor(map: GenMapping, options: Options);
+ toString(): string;
+}
diff --git a/Issue4/node_modules/@ampproject/remapping/dist/types/types.d.ts b/Issue4/node_modules/@ampproject/remapping/dist/types/types.d.ts
new file mode 100755
index 0000000000000000000000000000000000000000..4d78c4bc763e33881f8f070362b0c70a9a3876be
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/dist/types/types.d.ts
@@ -0,0 +1,15 @@
+import type { SourceMapInput } from '@jridgewell/trace-mapping';
+export type { SourceMapSegment, DecodedSourceMap, EncodedSourceMap, } from '@jridgewell/trace-mapping';
+export type { SourceMapInput };
+export declare type LoaderContext = {
+ readonly importer: string;
+ readonly depth: number;
+ source: string;
+ content: string | null | undefined;
+ ignore: boolean | undefined;
+};
+export declare type SourceMapLoader = (file: string, ctx: LoaderContext) => SourceMapInput | null | undefined | void;
+export declare type Options = {
+ excludeContent?: boolean;
+ decodedMappings?: boolean;
+};
diff --git a/Issue4/node_modules/@ampproject/remapping/package.json b/Issue4/node_modules/@ampproject/remapping/package.json
new file mode 100755
index 0000000000000000000000000000000000000000..091224c6730b07ca7ed7a42d2804edb0e73a9219
--- /dev/null
+++ b/Issue4/node_modules/@ampproject/remapping/package.json
@@ -0,0 +1,75 @@
+{
+ "name": "@ampproject/remapping",
+ "version": "2.3.0",
+ "description": "Remap sequential sourcemaps through transformations to point at the original source code",
+ "keywords": [
+ "source",
+ "map",
+ "remap"
+ ],
+ "main": "dist/remapping.umd.js",
+ "module": "dist/remapping.mjs",
+ "types": "dist/types/remapping.d.ts",
+ "exports": {
+ ".": [
+ {
+ "types": "./dist/types/remapping.d.ts",
+ "browser": "./dist/remapping.umd.js",
+ "require": "./dist/remapping.umd.js",
+ "import": "./dist/remapping.mjs"
+ },
+ "./dist/remapping.umd.js"
+ ],
+ "./package.json": "./package.json"
+ },
+ "files": [
+ "dist"
+ ],
+ "author": "Justin Ridgewell ",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/ampproject/remapping.git"
+ },
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "scripts": {
+ "build": "run-s -n build:*",
+ "build:rollup": "rollup -c rollup.config.js",
+ "build:ts": "tsc --project tsconfig.build.json",
+ "lint": "run-s -n lint:*",
+ "lint:prettier": "npm run test:lint:prettier -- --write",
+ "lint:ts": "npm run test:lint:ts -- --fix",
+ "prebuild": "rm -rf dist",
+ "prepublishOnly": "npm run preversion",
+ "preversion": "run-s test build",
+ "test": "run-s -n test:lint test:only",
+ "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
+ "test:lint": "run-s -n test:lint:*",
+ "test:lint:prettier": "prettier --check '{src,test}/**/*.ts'",
+ "test:lint:ts": "eslint '{src,test}/**/*.ts'",
+ "test:only": "jest --coverage",
+ "test:watch": "jest --coverage --watch"
+ },
+ "devDependencies": {
+ "@rollup/plugin-typescript": "8.3.2",
+ "@types/jest": "27.4.1",
+ "@typescript-eslint/eslint-plugin": "5.20.0",
+ "@typescript-eslint/parser": "5.20.0",
+ "eslint": "8.14.0",
+ "eslint-config-prettier": "8.5.0",
+ "jest": "27.5.1",
+ "jest-config": "27.5.1",
+ "npm-run-all": "4.1.5",
+ "prettier": "2.6.2",
+ "rollup": "2.70.2",
+ "ts-jest": "27.1.4",
+ "tslib": "2.4.0",
+ "typescript": "4.6.3"
+ },
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+}
diff --git a/Issue4/node_modules/@babel/code-frame/LICENSE b/Issue4/node_modules/@babel/code-frame/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..f31575ec773bb199aeb7c0d0f1612cfe1c7038f1
--- /dev/null
+++ b/Issue4/node_modules/@babel/code-frame/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2014-present Sebastian McKenzie and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Issue4/node_modules/@babel/code-frame/README.md b/Issue4/node_modules/@babel/code-frame/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..7160755113aaa771161a0626a7a9c7b6a99ac8d8
--- /dev/null
+++ b/Issue4/node_modules/@babel/code-frame/README.md
@@ -0,0 +1,19 @@
+# @babel/code-frame
+
+> Generate errors that contain a code frame that point to source locations.
+
+See our website [@babel/code-frame](https://babeljs.io/docs/babel-code-frame) for more information.
+
+## Install
+
+Using npm:
+
+```sh
+npm install --save-dev @babel/code-frame
+```
+
+or using yarn:
+
+```sh
+yarn add @babel/code-frame --dev
+```
diff --git a/Issue4/node_modules/@babel/code-frame/lib/index.js b/Issue4/node_modules/@babel/code-frame/lib/index.js
new file mode 100755
index 0000000000000000000000000000000000000000..b409f30138d539c6c32b8b4996323769dfdaa770
--- /dev/null
+++ b/Issue4/node_modules/@babel/code-frame/lib/index.js
@@ -0,0 +1,216 @@
+'use strict';
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+var picocolors = require('picocolors');
+var jsTokens = require('js-tokens');
+var helperValidatorIdentifier = require('@babel/helper-validator-identifier');
+
+function isColorSupported() {
+ return (typeof process === "object" && (process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false") ? false : picocolors.isColorSupported
+ );
+}
+const compose = (f, g) => v => f(g(v));
+function buildDefs(colors) {
+ return {
+ keyword: colors.cyan,
+ capitalized: colors.yellow,
+ jsxIdentifier: colors.yellow,
+ punctuator: colors.yellow,
+ number: colors.magenta,
+ string: colors.green,
+ regex: colors.magenta,
+ comment: colors.gray,
+ invalid: compose(compose(colors.white, colors.bgRed), colors.bold),
+ gutter: colors.gray,
+ marker: compose(colors.red, colors.bold),
+ message: compose(colors.red, colors.bold),
+ reset: colors.reset
+ };
+}
+const defsOn = buildDefs(picocolors.createColors(true));
+const defsOff = buildDefs(picocolors.createColors(false));
+function getDefs(enabled) {
+ return enabled ? defsOn : defsOff;
+}
+
+const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]);
+const NEWLINE$1 = /\r\n|[\n\r\u2028\u2029]/;
+const BRACKET = /^[()[\]{}]$/;
+let tokenize;
+{
+ const JSX_TAG = /^[a-z][\w-]*$/i;
+ const getTokenType = function (token, offset, text) {
+ if (token.type === "name") {
+ if (helperValidatorIdentifier.isKeyword(token.value) || helperValidatorIdentifier.isStrictReservedWord(token.value, true) || sometimesKeywords.has(token.value)) {
+ return "keyword";
+ }
+ if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.slice(offset - 2, offset) === "")) {
+ return "jsxIdentifier";
+ }
+ if (token.value[0] !== token.value[0].toLowerCase()) {
+ return "capitalized";
+ }
+ }
+ if (token.type === "punctuator" && BRACKET.test(token.value)) {
+ return "bracket";
+ }
+ if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
+ return "punctuator";
+ }
+ return token.type;
+ };
+ tokenize = function* (text) {
+ let match;
+ while (match = jsTokens.default.exec(text)) {
+ const token = jsTokens.matchToToken(match);
+ yield {
+ type: getTokenType(token, match.index, text),
+ value: token.value
+ };
+ }
+ };
+}
+function highlight(text) {
+ if (text === "") return "";
+ const defs = getDefs(true);
+ let highlighted = "";
+ for (const {
+ type,
+ value
+ } of tokenize(text)) {
+ if (type in defs) {
+ highlighted += value.split(NEWLINE$1).map(str => defs[type](str)).join("\n");
+ } else {
+ highlighted += value;
+ }
+ }
+ return highlighted;
+}
+
+let deprecationWarningShown = false;
+const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
+function getMarkerLines(loc, source, opts) {
+ const startLoc = Object.assign({
+ column: 0,
+ line: -1
+ }, loc.start);
+ const endLoc = Object.assign({}, startLoc, loc.end);
+ const {
+ linesAbove = 2,
+ linesBelow = 3
+ } = opts || {};
+ const startLine = startLoc.line;
+ const startColumn = startLoc.column;
+ const endLine = endLoc.line;
+ const endColumn = endLoc.column;
+ let start = Math.max(startLine - (linesAbove + 1), 0);
+ let end = Math.min(source.length, endLine + linesBelow);
+ if (startLine === -1) {
+ start = 0;
+ }
+ if (endLine === -1) {
+ end = source.length;
+ }
+ const lineDiff = endLine - startLine;
+ const markerLines = {};
+ if (lineDiff) {
+ for (let i = 0; i <= lineDiff; i++) {
+ const lineNumber = i + startLine;
+ if (!startColumn) {
+ markerLines[lineNumber] = true;
+ } else if (i === 0) {
+ const sourceLength = source[lineNumber - 1].length;
+ markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
+ } else if (i === lineDiff) {
+ markerLines[lineNumber] = [0, endColumn];
+ } else {
+ const sourceLength = source[lineNumber - i].length;
+ markerLines[lineNumber] = [0, sourceLength];
+ }
+ }
+ } else {
+ if (startColumn === endColumn) {
+ if (startColumn) {
+ markerLines[startLine] = [startColumn, 0];
+ } else {
+ markerLines[startLine] = true;
+ }
+ } else {
+ markerLines[startLine] = [startColumn, endColumn - startColumn];
+ }
+ }
+ return {
+ start,
+ end,
+ markerLines
+ };
+}
+function codeFrameColumns(rawLines, loc, opts = {}) {
+ const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;
+ const defs = getDefs(shouldHighlight);
+ const lines = rawLines.split(NEWLINE);
+ const {
+ start,
+ end,
+ markerLines
+ } = getMarkerLines(loc, lines, opts);
+ const hasColumns = loc.start && typeof loc.start.column === "number";
+ const numberMaxWidth = String(end).length;
+ const highlightedLines = shouldHighlight ? highlight(rawLines) : rawLines;
+ let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index) => {
+ const number = start + 1 + index;
+ const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
+ const gutter = ` ${paddedNumber} |`;
+ const hasMarker = markerLines[number];
+ const lastMarkerLine = !markerLines[number + 1];
+ if (hasMarker) {
+ let markerLine = "";
+ if (Array.isArray(hasMarker)) {
+ const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
+ const numberOfMarkers = hasMarker[1] || 1;
+ markerLine = ["\n ", defs.gutter(gutter.replace(/\d/g, " ")), " ", markerSpacing, defs.marker("^").repeat(numberOfMarkers)].join("");
+ if (lastMarkerLine && opts.message) {
+ markerLine += " " + defs.message(opts.message);
+ }
+ }
+ return [defs.marker(">"), defs.gutter(gutter), line.length > 0 ? ` ${line}` : "", markerLine].join("");
+ } else {
+ return ` ${defs.gutter(gutter)}${line.length > 0 ? ` ${line}` : ""}`;
+ }
+ }).join("\n");
+ if (opts.message && !hasColumns) {
+ frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
+ }
+ if (shouldHighlight) {
+ return defs.reset(frame);
+ } else {
+ return frame;
+ }
+}
+function index (rawLines, lineNumber, colNumber, opts = {}) {
+ if (!deprecationWarningShown) {
+ deprecationWarningShown = true;
+ const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
+ if (process.emitWarning) {
+ process.emitWarning(message, "DeprecationWarning");
+ } else {
+ const deprecationError = new Error(message);
+ deprecationError.name = "DeprecationWarning";
+ console.warn(new Error(message));
+ }
+ }
+ colNumber = Math.max(colNumber, 0);
+ const location = {
+ start: {
+ column: colNumber,
+ line: lineNumber
+ }
+ };
+ return codeFrameColumns(rawLines, location, opts);
+}
+
+exports.codeFrameColumns = codeFrameColumns;
+exports.default = index;
+exports.highlight = highlight;
+//# sourceMappingURL=index.js.map
diff --git a/Issue4/node_modules/@babel/code-frame/lib/index.js.map b/Issue4/node_modules/@babel/code-frame/lib/index.js.map
new file mode 100755
index 0000000000000000000000000000000000000000..46a181dcd56d72518304708b57c0831cd4e7aaa7
--- /dev/null
+++ b/Issue4/node_modules/@babel/code-frame/lib/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sources":["../src/defs.ts","../src/highlight.ts","../src/index.ts"],"sourcesContent":["import picocolors, { createColors } from \"picocolors\";\nimport type { Colors, Formatter } from \"picocolors/types\";\n\nexport function isColorSupported() {\n return (\n // See https://github.com/alexeyraspopov/picocolors/issues/62\n typeof process === \"object\" &&\n (process.env.FORCE_COLOR === \"0\" || process.env.FORCE_COLOR === \"false\")\n ? false\n : picocolors.isColorSupported\n );\n}\n\nexport type InternalTokenType =\n | \"keyword\"\n | \"capitalized\"\n | \"jsxIdentifier\"\n | \"punctuator\"\n | \"number\"\n | \"string\"\n | \"regex\"\n | \"comment\"\n | \"invalid\";\n\ntype UITokens = \"gutter\" | \"marker\" | \"message\";\n\nexport type Defs = {\n [_ in InternalTokenType | UITokens | \"reset\"]: Formatter;\n};\n\nconst compose: (f: (gv: U) => V, g: (v: T) => U) => (v: T) => V =\n (f, g) => v =>\n f(g(v));\n\n/**\n * Styles for token types.\n */\nfunction buildDefs(colors: Colors): Defs {\n return {\n keyword: colors.cyan,\n capitalized: colors.yellow,\n jsxIdentifier: colors.yellow,\n punctuator: colors.yellow,\n number: colors.magenta,\n string: colors.green,\n regex: colors.magenta,\n comment: colors.gray,\n invalid: compose(compose(colors.white, colors.bgRed), colors.bold),\n\n gutter: colors.gray,\n marker: compose(colors.red, colors.bold),\n message: compose(colors.red, colors.bold),\n\n reset: colors.reset,\n };\n}\n\nconst defsOn = buildDefs(createColors(true));\nconst defsOff = buildDefs(createColors(false));\n\nexport function getDefs(enabled: boolean): Defs {\n return enabled ? defsOn : defsOff;\n}\n","import type { Token as JSToken, JSXToken } from \"js-tokens\";\nimport jsTokens from \"js-tokens\";\n\nimport {\n isStrictReservedWord,\n isKeyword,\n} from \"@babel/helper-validator-identifier\";\n\nimport { getDefs, type InternalTokenType } from \"./defs.ts\";\n\n/**\n * Names that are always allowed as identifiers, but also appear as keywords\n * within certain syntactic productions.\n *\n * https://tc39.es/ecma262/#sec-keywords-and-reserved-words\n *\n * `target` has been omitted since it is very likely going to be a false\n * positive.\n */\nconst sometimesKeywords = new Set([\"as\", \"async\", \"from\", \"get\", \"of\", \"set\"]);\n\ntype Token = {\n type: InternalTokenType | \"uncolored\";\n value: string;\n};\n\n/**\n * RegExp to test for newlines in terminal.\n */\nconst NEWLINE = /\\r\\n|[\\n\\r\\u2028\\u2029]/;\n\n/**\n * RegExp to test for the three types of brackets.\n */\nconst BRACKET = /^[()[\\]{}]$/;\n\nlet tokenize: (\n text: string,\n) => Generator<{ type: InternalTokenType | \"uncolored\"; value: string }>;\n\nif (process.env.BABEL_8_BREAKING) {\n /**\n * Get the type of token, specifying punctuator type.\n */\n const getTokenType = function (\n token: JSToken | JSXToken,\n ): InternalTokenType | \"uncolored\" {\n if (token.type === \"IdentifierName\") {\n if (\n isKeyword(token.value) ||\n isStrictReservedWord(token.value, true) ||\n sometimesKeywords.has(token.value)\n ) {\n return \"keyword\";\n }\n\n if (token.value[0] !== token.value[0].toLowerCase()) {\n return \"capitalized\";\n }\n }\n\n if (token.type === \"Punctuator\" && BRACKET.test(token.value)) {\n return \"uncolored\";\n }\n\n if (token.type === \"Invalid\" && token.value === \"@\") {\n return \"punctuator\";\n }\n\n switch (token.type) {\n case \"NumericLiteral\":\n return \"number\";\n\n case \"StringLiteral\":\n case \"JSXString\":\n case \"NoSubstitutionTemplate\":\n return \"string\";\n\n case \"RegularExpressionLiteral\":\n return \"regex\";\n\n case \"Punctuator\":\n case \"JSXPunctuator\":\n return \"punctuator\";\n\n case \"MultiLineComment\":\n case \"SingleLineComment\":\n return \"comment\";\n\n case \"Invalid\":\n case \"JSXInvalid\":\n return \"invalid\";\n\n case \"JSXIdentifier\":\n return \"jsxIdentifier\";\n\n default:\n return \"uncolored\";\n }\n };\n\n /**\n * Turn a string of JS into an array of objects.\n */\n tokenize = function* (text: string): Generator {\n for (const token of jsTokens(text, { jsx: true })) {\n switch (token.type) {\n case \"TemplateHead\":\n yield { type: \"string\", value: token.value.slice(0, -2) };\n yield { type: \"punctuator\", value: \"${\" };\n break;\n\n case \"TemplateMiddle\":\n yield { type: \"punctuator\", value: \"}\" };\n yield { type: \"string\", value: token.value.slice(1, -2) };\n yield { type: \"punctuator\", value: \"${\" };\n break;\n\n case \"TemplateTail\":\n yield { type: \"punctuator\", value: \"}\" };\n yield { type: \"string\", value: token.value.slice(1) };\n break;\n\n default:\n yield {\n type: getTokenType(token),\n value: token.value,\n };\n }\n }\n };\n} else {\n /**\n * RegExp to test for what seems to be a JSX tag name.\n */\n const JSX_TAG = /^[a-z][\\w-]*$/i;\n\n // The token here is defined in js-tokens@4. However we don't bother\n // typing it since the whole block will be removed in Babel 8\n const getTokenType = function (token: any, offset: number, text: string) {\n if (token.type === \"name\") {\n if (\n isKeyword(token.value) ||\n isStrictReservedWord(token.value, true) ||\n sometimesKeywords.has(token.value)\n ) {\n return \"keyword\";\n }\n\n if (\n JSX_TAG.test(token.value) &&\n (text[offset - 1] === \"<\" || text.slice(offset - 2, offset) === \"\")\n ) {\n return \"jsxIdentifier\";\n }\n\n if (token.value[0] !== token.value[0].toLowerCase()) {\n return \"capitalized\";\n }\n }\n\n if (token.type === \"punctuator\" && BRACKET.test(token.value)) {\n return \"bracket\";\n }\n\n if (\n token.type === \"invalid\" &&\n (token.value === \"@\" || token.value === \"#\")\n ) {\n return \"punctuator\";\n }\n\n return token.type;\n };\n\n tokenize = function* (text: string) {\n let match;\n while ((match = (jsTokens as any).default.exec(text))) {\n const token = (jsTokens as any).matchToToken(match);\n\n yield {\n type: getTokenType(token, match.index, text),\n value: token.value,\n };\n }\n };\n}\n\nexport function highlight(text: string) {\n if (text === \"\") return \"\";\n\n const defs = getDefs(true);\n\n let highlighted = \"\";\n\n for (const { type, value } of tokenize(text)) {\n if (type in defs) {\n highlighted += value\n .split(NEWLINE)\n .map(str => defs[type as InternalTokenType](str))\n .join(\"\\n\");\n } else {\n highlighted += value;\n }\n }\n\n return highlighted;\n}\n","import { getDefs, isColorSupported } from \"./defs.ts\";\nimport { highlight } from \"./highlight.ts\";\n\nexport { highlight };\n\nlet deprecationWarningShown = false;\n\ntype Location = {\n column: number;\n line: number;\n};\n\ntype NodeLocation = {\n end?: Location;\n start: Location;\n};\n\nexport interface Options {\n /** Syntax highlight the code as JavaScript for terminals. default: false */\n highlightCode?: boolean;\n /** The number of lines to show above the error. default: 2 */\n linesAbove?: number;\n /** The number of lines to show below the error. default: 3 */\n linesBelow?: number;\n /**\n * Forcibly syntax highlight the code as JavaScript (for non-terminals);\n * overrides highlightCode.\n * default: false\n */\n forceColor?: boolean;\n /**\n * Pass in a string to be displayed inline (if possible) next to the\n * highlighted location in the code. If it can't be positioned inline,\n * it will be placed above the code frame.\n * default: nothing\n */\n message?: string;\n}\n\n/**\n * RegExp to test for newlines in terminal.\n */\n\nconst NEWLINE = /\\r\\n|[\\n\\r\\u2028\\u2029]/;\n\n/**\n * Extract what lines should be marked and highlighted.\n */\n\ntype MarkerLines = Record;\n\nfunction getMarkerLines(\n loc: NodeLocation,\n source: Array,\n opts: Options,\n): {\n start: number;\n end: number;\n markerLines: MarkerLines;\n} {\n const startLoc: Location = {\n column: 0,\n line: -1,\n ...loc.start,\n };\n const endLoc: Location = {\n ...startLoc,\n ...loc.end,\n };\n const { linesAbove = 2, linesBelow = 3 } = opts || {};\n const startLine = startLoc.line;\n const startColumn = startLoc.column;\n const endLine = endLoc.line;\n const endColumn = endLoc.column;\n\n let start = Math.max(startLine - (linesAbove + 1), 0);\n let end = Math.min(source.length, endLine + linesBelow);\n\n if (startLine === -1) {\n start = 0;\n }\n\n if (endLine === -1) {\n end = source.length;\n }\n\n const lineDiff = endLine - startLine;\n const markerLines: MarkerLines = {};\n\n if (lineDiff) {\n for (let i = 0; i <= lineDiff; i++) {\n const lineNumber = i + startLine;\n\n if (!startColumn) {\n markerLines[lineNumber] = true;\n } else if (i === 0) {\n const sourceLength = source[lineNumber - 1].length;\n\n markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];\n } else if (i === lineDiff) {\n markerLines[lineNumber] = [0, endColumn];\n } else {\n const sourceLength = source[lineNumber - i].length;\n\n markerLines[lineNumber] = [0, sourceLength];\n }\n }\n } else {\n if (startColumn === endColumn) {\n if (startColumn) {\n markerLines[startLine] = [startColumn, 0];\n } else {\n markerLines[startLine] = true;\n }\n } else {\n markerLines[startLine] = [startColumn, endColumn - startColumn];\n }\n }\n\n return { start, end, markerLines };\n}\n\nexport function codeFrameColumns(\n rawLines: string,\n loc: NodeLocation,\n opts: Options = {},\n): string {\n const shouldHighlight =\n opts.forceColor || (isColorSupported() && opts.highlightCode);\n const defs = getDefs(shouldHighlight);\n\n const lines = rawLines.split(NEWLINE);\n const { start, end, markerLines } = getMarkerLines(loc, lines, opts);\n const hasColumns = loc.start && typeof loc.start.column === \"number\";\n\n const numberMaxWidth = String(end).length;\n\n const highlightedLines = shouldHighlight ? highlight(rawLines) : rawLines;\n\n let frame = highlightedLines\n .split(NEWLINE, end)\n .slice(start, end)\n .map((line, index) => {\n const number = start + 1 + index;\n const paddedNumber = ` ${number}`.slice(-numberMaxWidth);\n const gutter = ` ${paddedNumber} |`;\n const hasMarker = markerLines[number];\n const lastMarkerLine = !markerLines[number + 1];\n if (hasMarker) {\n let markerLine = \"\";\n if (Array.isArray(hasMarker)) {\n const markerSpacing = line\n .slice(0, Math.max(hasMarker[0] - 1, 0))\n .replace(/[^\\t]/g, \" \");\n const numberOfMarkers = hasMarker[1] || 1;\n\n markerLine = [\n \"\\n \",\n defs.gutter(gutter.replace(/\\d/g, \" \")),\n \" \",\n markerSpacing,\n defs.marker(\"^\").repeat(numberOfMarkers),\n ].join(\"\");\n\n if (lastMarkerLine && opts.message) {\n markerLine += \" \" + defs.message(opts.message);\n }\n }\n return [\n defs.marker(\">\"),\n defs.gutter(gutter),\n line.length > 0 ? ` ${line}` : \"\",\n markerLine,\n ].join(\"\");\n } else {\n return ` ${defs.gutter(gutter)}${line.length > 0 ? ` ${line}` : \"\"}`;\n }\n })\n .join(\"\\n\");\n\n if (opts.message && !hasColumns) {\n frame = `${\" \".repeat(numberMaxWidth + 1)}${opts.message}\\n${frame}`;\n }\n\n if (shouldHighlight) {\n return defs.reset(frame);\n } else {\n return frame;\n }\n}\n\n/**\n * Create a code frame, adding line numbers, code highlighting, and pointing to a given position.\n */\n\nexport default function (\n rawLines: string,\n lineNumber: number,\n colNumber?: number | null,\n opts: Options = {},\n): string {\n if (!deprecationWarningShown) {\n deprecationWarningShown = true;\n\n const message =\n \"Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.\";\n\n if (process.emitWarning) {\n // A string is directly supplied to emitWarning, because when supplying an\n // Error object node throws in the tests because of different contexts\n process.emitWarning(message, \"DeprecationWarning\");\n } else {\n const deprecationError = new Error(message);\n deprecationError.name = \"DeprecationWarning\";\n console.warn(new Error(message));\n }\n }\n\n colNumber = Math.max(colNumber, 0);\n\n const location: NodeLocation = {\n start: { column: colNumber, line: lineNumber },\n };\n\n return codeFrameColumns(rawLines, location, opts);\n}\n"],"names":["isColorSupported","process","env","FORCE_COLOR","picocolors","compose","f","g","v","buildDefs","colors","keyword","cyan","capitalized","yellow","jsxIdentifier","punctuator","number","magenta","string","green","regex","comment","gray","invalid","white","bgRed","bold","gutter","marker","red","message","reset","defsOn","createColors","defsOff","getDefs","enabled","sometimesKeywords","Set","NEWLINE","BRACKET","tokenize","JSX_TAG","getTokenType","token","offset","text","type","isKeyword","value","isStrictReservedWord","has","test","slice","toLowerCase","match","jsTokens","default","exec","matchToToken","index","highlight","defs","highlighted","split","map","str","join","deprecationWarningShown","getMarkerLines","loc","source","opts","startLoc","Object","assign","column","line","start","endLoc","end","linesAbove","linesBelow","startLine","startColumn","endLine","endColumn","Math","max","min","length","lineDiff","markerLines","i","lineNumber","sourceLength","codeFrameColumns","rawLines","shouldHighlight","forceColor","highlightCode","lines","hasColumns","numberMaxWidth","String","highlightedLines","frame","paddedNumber","hasMarker","lastMarkerLine","markerLine","Array","isArray","markerSpacing","replace","numberOfMarkers","repeat","colNumber","emitWarning","deprecationError","Error","name","console","warn","location"],"mappings":"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"}
\ No newline at end of file
diff --git a/Issue4/node_modules/@babel/code-frame/package.json b/Issue4/node_modules/@babel/code-frame/package.json
new file mode 100755
index 0000000000000000000000000000000000000000..076c31289a80c07dbf47226f90d40582a2e10655
--- /dev/null
+++ b/Issue4/node_modules/@babel/code-frame/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@babel/code-frame",
+ "version": "7.26.2",
+ "description": "Generate errors that contain a code frame that point to source locations.",
+ "author": "The Babel Team (https://babel.dev/team)",
+ "homepage": "https://babel.dev/docs/en/next/babel-code-frame",
+ "bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen",
+ "license": "MIT",
+ "publishConfig": {
+ "access": "public"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/babel/babel.git",
+ "directory": "packages/babel-code-frame"
+ },
+ "main": "./lib/index.js",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "devDependencies": {
+ "import-meta-resolve": "^4.1.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "type": "commonjs"
+}
\ No newline at end of file
diff --git a/Issue4/node_modules/@babel/compat-data/LICENSE b/Issue4/node_modules/@babel/compat-data/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..f31575ec773bb199aeb7c0d0f1612cfe1c7038f1
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2014-present Sebastian McKenzie and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Issue4/node_modules/@babel/compat-data/README.md b/Issue4/node_modules/@babel/compat-data/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..381f3deb4ee0fcbcf571b63e803e41759a2d635e
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/README.md
@@ -0,0 +1,19 @@
+# @babel/compat-data
+
+>
+
+See our website [@babel/compat-data](https://babeljs.io/docs/babel-compat-data) for more information.
+
+## Install
+
+Using npm:
+
+```sh
+npm install --save @babel/compat-data
+```
+
+or using yarn:
+
+```sh
+yarn add @babel/compat-data
+```
diff --git a/Issue4/node_modules/@babel/compat-data/corejs2-built-ins.js b/Issue4/node_modules/@babel/compat-data/corejs2-built-ins.js
new file mode 100755
index 0000000000000000000000000000000000000000..ed19e0b8a4ffd6bf191602c04d7c9308038f5562
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/corejs2-built-ins.js
@@ -0,0 +1,2 @@
+// Todo (Babel 8): remove this file as Babel 8 drop support of core-js 2
+module.exports = require("./data/corejs2-built-ins.json");
diff --git a/Issue4/node_modules/@babel/compat-data/corejs3-shipped-proposals.js b/Issue4/node_modules/@babel/compat-data/corejs3-shipped-proposals.js
new file mode 100755
index 0000000000000000000000000000000000000000..7909b8c46d3717def2168c9a1e8cc6a068b29541
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/corejs3-shipped-proposals.js
@@ -0,0 +1,2 @@
+// Todo (Babel 8): remove this file now that it is included in babel-plugin-polyfill-corejs3
+module.exports = require("./data/corejs3-shipped-proposals.json");
diff --git a/Issue4/node_modules/@babel/compat-data/data/corejs2-built-ins.json b/Issue4/node_modules/@babel/compat-data/data/corejs2-built-ins.json
new file mode 100755
index 0000000000000000000000000000000000000000..5fe8ca8dd141dfb6470d7b5391ffe6c54e7712b6
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/data/corejs2-built-ins.json
@@ -0,0 +1,2090 @@
+{
+ "es6.array.copy-within": {
+ "chrome": "45",
+ "opera": "32",
+ "edge": "12",
+ "firefox": "32",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.31"
+ },
+ "es6.array.every": {
+ "chrome": "5",
+ "opera": "10.10",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.fill": {
+ "chrome": "45",
+ "opera": "32",
+ "edge": "12",
+ "firefox": "31",
+ "safari": "7.1",
+ "node": "4",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.31"
+ },
+ "es6.array.filter": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.array.find": {
+ "chrome": "45",
+ "opera": "32",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "4",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.31"
+ },
+ "es6.array.find-index": {
+ "chrome": "45",
+ "opera": "32",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "4",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.31"
+ },
+ "es7.array.flat-map": {
+ "chrome": "69",
+ "opera": "56",
+ "edge": "79",
+ "firefox": "62",
+ "safari": "12",
+ "node": "11",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "10",
+ "rhino": "1.7.15",
+ "opera_mobile": "48",
+ "electron": "4.0"
+ },
+ "es6.array.for-each": {
+ "chrome": "5",
+ "opera": "10.10",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.from": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "36",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es7.array.includes": {
+ "chrome": "47",
+ "opera": "34",
+ "edge": "14",
+ "firefox": "102",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "34",
+ "electron": "0.36"
+ },
+ "es6.array.index-of": {
+ "chrome": "5",
+ "opera": "10.10",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.is-array": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.iterator": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "12",
+ "firefox": "60",
+ "safari": "9",
+ "node": "10",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "9",
+ "rhino": "1.7.13",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "es6.array.last-index-of": {
+ "chrome": "5",
+ "opera": "10.10",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.map": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.array.of": {
+ "chrome": "45",
+ "opera": "32",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.31"
+ },
+ "es6.array.reduce": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "3",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.reduce-right": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "3",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.slice": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.array.some": {
+ "chrome": "5",
+ "opera": "10.10",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.array.sort": {
+ "chrome": "63",
+ "opera": "50",
+ "edge": "12",
+ "firefox": "5",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ie": "9",
+ "ios": "12",
+ "samsung": "8",
+ "rhino": "1.7.13",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es6.array.species": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.date.now": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.date.to-iso-string": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "3.5",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.date.to-json": {
+ "chrome": "5",
+ "opera": "12.10",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "10",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "10",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12.1",
+ "electron": "0.20"
+ },
+ "es6.date.to-primitive": {
+ "chrome": "47",
+ "opera": "34",
+ "edge": "15",
+ "firefox": "44",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "34",
+ "electron": "0.36"
+ },
+ "es6.date.to-string": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "10",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.function.bind": {
+ "chrome": "7",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "5.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "es6.function.has-instance": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "50",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.function.name": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "14",
+ "firefox": "2",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es6.map": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.math.acosh": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.asinh": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.atanh": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.cbrt": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.clz32": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "31",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.cosh": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.expm1": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.fround": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "26",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.hypot": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "27",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.imul": {
+ "chrome": "30",
+ "opera": "17",
+ "edge": "12",
+ "firefox": "23",
+ "safari": "7",
+ "node": "0.12",
+ "deno": "1",
+ "android": "4.4",
+ "ios": "7",
+ "samsung": "2",
+ "rhino": "1.7.13",
+ "opera_mobile": "18",
+ "electron": "0.20"
+ },
+ "es6.math.log1p": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.log10": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.log2": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.sign": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.sinh": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.tanh": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.math.trunc": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "7.1",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.number.constructor": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "36",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.number.epsilon": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.14",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.number.is-finite": {
+ "chrome": "19",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "16",
+ "safari": "9",
+ "node": "0.8",
+ "deno": "1",
+ "android": "4.1",
+ "ios": "9",
+ "samsung": "1.5",
+ "rhino": "1.7.13",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.number.is-integer": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "16",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.13",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.number.is-nan": {
+ "chrome": "19",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "15",
+ "safari": "9",
+ "node": "0.8",
+ "deno": "1",
+ "android": "4.1",
+ "ios": "9",
+ "samsung": "1.5",
+ "rhino": "1.7.13",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.number.is-safe-integer": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "32",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.13",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.number.max-safe-integer": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "31",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.13",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.number.min-safe-integer": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "31",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.13",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.number.parse-float": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.14",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.number.parse-int": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "25",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.14",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es6.object.assign": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "13",
+ "firefox": "36",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.object.create": {
+ "chrome": "5",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "es7.object.define-getter": {
+ "chrome": "62",
+ "opera": "49",
+ "edge": "16",
+ "firefox": "48",
+ "safari": "9",
+ "node": "8.10",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es7.object.define-setter": {
+ "chrome": "62",
+ "opera": "49",
+ "edge": "16",
+ "firefox": "48",
+ "safari": "9",
+ "node": "8.10",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es6.object.define-property": {
+ "chrome": "5",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "5.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "es6.object.define-properties": {
+ "chrome": "5",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "es7.object.entries": {
+ "chrome": "54",
+ "opera": "41",
+ "edge": "14",
+ "firefox": "47",
+ "safari": "10.1",
+ "node": "7",
+ "deno": "1",
+ "ios": "10.3",
+ "samsung": "6",
+ "rhino": "1.7.14",
+ "opera_mobile": "41",
+ "electron": "1.4"
+ },
+ "es6.object.freeze": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es6.object.get-own-property-descriptor": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es7.object.get-own-property-descriptors": {
+ "chrome": "54",
+ "opera": "41",
+ "edge": "15",
+ "firefox": "50",
+ "safari": "10.1",
+ "node": "7",
+ "deno": "1",
+ "ios": "10.3",
+ "samsung": "6",
+ "opera_mobile": "41",
+ "electron": "1.4"
+ },
+ "es6.object.get-own-property-names": {
+ "chrome": "40",
+ "opera": "27",
+ "edge": "12",
+ "firefox": "33",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "27",
+ "electron": "0.21"
+ },
+ "es6.object.get-prototype-of": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es7.object.lookup-getter": {
+ "chrome": "62",
+ "opera": "49",
+ "edge": "79",
+ "firefox": "36",
+ "safari": "9",
+ "node": "8.10",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es7.object.lookup-setter": {
+ "chrome": "62",
+ "opera": "49",
+ "edge": "79",
+ "firefox": "36",
+ "safari": "9",
+ "node": "8.10",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es6.object.prevent-extensions": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es6.object.to-string": {
+ "chrome": "57",
+ "opera": "44",
+ "edge": "15",
+ "firefox": "51",
+ "safari": "10",
+ "node": "8",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "7",
+ "opera_mobile": "43",
+ "electron": "1.7"
+ },
+ "es6.object.is": {
+ "chrome": "19",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "22",
+ "safari": "9",
+ "node": "0.8",
+ "deno": "1",
+ "android": "4.1",
+ "ios": "9",
+ "samsung": "1.5",
+ "rhino": "1.7.13",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.object.is-frozen": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es6.object.is-sealed": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es6.object.is-extensible": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es6.object.keys": {
+ "chrome": "40",
+ "opera": "27",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "27",
+ "electron": "0.21"
+ },
+ "es6.object.seal": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "35",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.13",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "es6.object.set-prototype-of": {
+ "chrome": "34",
+ "opera": "21",
+ "edge": "12",
+ "firefox": "31",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ie": "11",
+ "ios": "9",
+ "samsung": "2",
+ "rhino": "1.7.13",
+ "opera_mobile": "21",
+ "electron": "0.20"
+ },
+ "es7.object.values": {
+ "chrome": "54",
+ "opera": "41",
+ "edge": "14",
+ "firefox": "47",
+ "safari": "10.1",
+ "node": "7",
+ "deno": "1",
+ "ios": "10.3",
+ "samsung": "6",
+ "rhino": "1.7.14",
+ "opera_mobile": "41",
+ "electron": "1.4"
+ },
+ "es6.promise": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "14",
+ "firefox": "45",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es7.promise.finally": {
+ "chrome": "63",
+ "opera": "50",
+ "edge": "18",
+ "firefox": "58",
+ "safari": "11.1",
+ "node": "10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "8",
+ "rhino": "1.7.15",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es6.reflect.apply": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.construct": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "13",
+ "firefox": "49",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.define-property": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "13",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.delete-property": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.get": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.get-own-property-descriptor": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.get-prototype-of": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.has": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.is-extensible": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.own-keys": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.prevent-extensions": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.set": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.reflect.set-prototype-of": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "42",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.regexp.constructor": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "79",
+ "firefox": "40",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "es6.regexp.flags": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "79",
+ "firefox": "37",
+ "safari": "9",
+ "node": "6",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "es6.regexp.match": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "79",
+ "firefox": "49",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "es6.regexp.replace": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "79",
+ "firefox": "49",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "es6.regexp.split": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "79",
+ "firefox": "49",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "es6.regexp.search": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "79",
+ "firefox": "49",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "es6.regexp.to-string": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "79",
+ "firefox": "39",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "es6.set": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.symbol": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "79",
+ "firefox": "51",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es7.symbol.async-iterator": {
+ "chrome": "63",
+ "opera": "50",
+ "edge": "79",
+ "firefox": "57",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "es6.string.anchor": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.big": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.blink": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.bold": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.code-point-at": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "29",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.ends-with": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "29",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.fixed": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.fontcolor": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.fontsize": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.from-code-point": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "29",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.includes": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "40",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.italics": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.iterator": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "36",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "es6.string.link": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es7.string.pad-start": {
+ "chrome": "57",
+ "opera": "44",
+ "edge": "15",
+ "firefox": "48",
+ "safari": "10",
+ "node": "8",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "7",
+ "rhino": "1.7.13",
+ "opera_mobile": "43",
+ "electron": "1.7"
+ },
+ "es7.string.pad-end": {
+ "chrome": "57",
+ "opera": "44",
+ "edge": "15",
+ "firefox": "48",
+ "safari": "10",
+ "node": "8",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "7",
+ "rhino": "1.7.13",
+ "opera_mobile": "43",
+ "electron": "1.7"
+ },
+ "es6.string.raw": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "34",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.14",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.repeat": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "24",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.small": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.starts-with": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "29",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "rhino": "1.7.13",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "es6.string.strike": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.sub": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.sup": {
+ "chrome": "5",
+ "opera": "15",
+ "edge": "12",
+ "firefox": "17",
+ "safari": "6",
+ "node": "0.4",
+ "deno": "1",
+ "android": "4",
+ "ios": "7",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.14",
+ "opera_mobile": "14",
+ "electron": "0.20"
+ },
+ "es6.string.trim": {
+ "chrome": "5",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "3.5",
+ "safari": "4",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "es7.string.trim-left": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "79",
+ "firefox": "61",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "9",
+ "rhino": "1.7.13",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "es7.string.trim-right": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "79",
+ "firefox": "61",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "9",
+ "rhino": "1.7.13",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "es6.typed.array-buffer": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.data-view": {
+ "chrome": "5",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "15",
+ "safari": "5.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "10",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "es6.typed.int8-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.uint8-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.uint8-clamped-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.int16-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.uint16-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.int32-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.uint32-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.float32-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.typed.float64-array": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "13",
+ "firefox": "48",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.weak-map": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "9",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "es6.weak-set": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "9",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ }
+}
diff --git a/Issue4/node_modules/@babel/compat-data/data/corejs3-shipped-proposals.json b/Issue4/node_modules/@babel/compat-data/data/corejs3-shipped-proposals.json
new file mode 100755
index 0000000000000000000000000000000000000000..d03b698ff0c18a2e55ff3df2414e4bc366962515
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/data/corejs3-shipped-proposals.json
@@ -0,0 +1,5 @@
+[
+ "esnext.promise.all-settled",
+ "esnext.string.match-all",
+ "esnext.global-this"
+]
diff --git a/Issue4/node_modules/@babel/compat-data/data/native-modules.json b/Issue4/node_modules/@babel/compat-data/data/native-modules.json
new file mode 100755
index 0000000000000000000000000000000000000000..2328d2138bd513cde3d1fe009ef41f969226f023
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/data/native-modules.json
@@ -0,0 +1,18 @@
+{
+ "es6.module": {
+ "chrome": "61",
+ "and_chr": "61",
+ "edge": "16",
+ "firefox": "60",
+ "and_ff": "60",
+ "node": "13.2.0",
+ "opera": "48",
+ "op_mob": "45",
+ "safari": "10.1",
+ "ios": "10.3",
+ "samsung": "8.2",
+ "android": "61",
+ "electron": "2.0",
+ "ios_saf": "10.3"
+ }
+}
diff --git a/Issue4/node_modules/@babel/compat-data/data/overlapping-plugins.json b/Issue4/node_modules/@babel/compat-data/data/overlapping-plugins.json
new file mode 100755
index 0000000000000000000000000000000000000000..9b884bd44b8372593a2f2371f9fe49745fd1550c
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/data/overlapping-plugins.json
@@ -0,0 +1,35 @@
+{
+ "transform-async-to-generator": [
+ "bugfix/transform-async-arrows-in-class"
+ ],
+ "transform-parameters": [
+ "bugfix/transform-edge-default-parameters",
+ "bugfix/transform-safari-id-destructuring-collision-in-function-expression"
+ ],
+ "transform-function-name": [
+ "bugfix/transform-edge-function-name"
+ ],
+ "transform-block-scoping": [
+ "bugfix/transform-safari-block-shadowing",
+ "bugfix/transform-safari-for-shadowing"
+ ],
+ "transform-template-literals": [
+ "bugfix/transform-tagged-template-caching"
+ ],
+ "transform-optional-chaining": [
+ "bugfix/transform-v8-spread-parameters-in-optional-chaining"
+ ],
+ "proposal-optional-chaining": [
+ "bugfix/transform-v8-spread-parameters-in-optional-chaining"
+ ],
+ "transform-class-properties": [
+ "bugfix/transform-v8-static-class-fields-redefine-readonly",
+ "bugfix/transform-firefox-class-in-computed-class-key",
+ "bugfix/transform-safari-class-field-initializer-scope"
+ ],
+ "proposal-class-properties": [
+ "bugfix/transform-v8-static-class-fields-redefine-readonly",
+ "bugfix/transform-firefox-class-in-computed-class-key",
+ "bugfix/transform-safari-class-field-initializer-scope"
+ ]
+}
diff --git a/Issue4/node_modules/@babel/compat-data/data/plugin-bugfixes.json b/Issue4/node_modules/@babel/compat-data/data/plugin-bugfixes.json
new file mode 100755
index 0000000000000000000000000000000000000000..82e4e2111f0db851be7b7de9b97e48370b552261
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/data/plugin-bugfixes.json
@@ -0,0 +1,213 @@
+{
+ "bugfix/transform-async-arrows-in-class": {
+ "chrome": "55",
+ "opera": "42",
+ "edge": "15",
+ "firefox": "52",
+ "safari": "11",
+ "node": "7.6",
+ "deno": "1",
+ "ios": "11",
+ "samsung": "6",
+ "opera_mobile": "42",
+ "electron": "1.6"
+ },
+ "bugfix/transform-edge-default-parameters": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "18",
+ "firefox": "52",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "bugfix/transform-edge-function-name": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "79",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "bugfix/transform-safari-block-shadowing": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "44",
+ "safari": "11",
+ "node": "6",
+ "deno": "1",
+ "ie": "11",
+ "ios": "11",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "bugfix/transform-safari-for-shadowing": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "12",
+ "firefox": "4",
+ "safari": "11",
+ "node": "6",
+ "deno": "1",
+ "ie": "11",
+ "ios": "11",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "bugfix/transform-safari-id-destructuring-collision-in-function-expression": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "14",
+ "firefox": "2",
+ "safari": "16.3",
+ "node": "6",
+ "deno": "1",
+ "ios": "16.3",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "bugfix/transform-tagged-template-caching": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "34",
+ "safari": "13",
+ "node": "4",
+ "deno": "1",
+ "ios": "13",
+ "samsung": "3.4",
+ "rhino": "1.7.14",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "bugfix/transform-v8-spread-parameters-in-optional-chaining": {
+ "chrome": "91",
+ "opera": "77",
+ "edge": "91",
+ "firefox": "74",
+ "safari": "13.1",
+ "node": "16.9",
+ "deno": "1.9",
+ "ios": "13.4",
+ "samsung": "16",
+ "opera_mobile": "64",
+ "electron": "13.0"
+ },
+ "bugfix/transform-firefox-class-in-computed-class-key": {
+ "chrome": "74",
+ "opera": "62",
+ "edge": "79",
+ "safari": "16",
+ "node": "12",
+ "deno": "1",
+ "ios": "16",
+ "samsung": "11",
+ "opera_mobile": "53",
+ "electron": "6.0"
+ },
+ "transform-optional-chaining": {
+ "chrome": "80",
+ "opera": "67",
+ "edge": "80",
+ "firefox": "74",
+ "safari": "13.1",
+ "node": "14",
+ "deno": "1",
+ "ios": "13.4",
+ "samsung": "13",
+ "opera_mobile": "57",
+ "electron": "8.0"
+ },
+ "proposal-optional-chaining": {
+ "chrome": "80",
+ "opera": "67",
+ "edge": "80",
+ "firefox": "74",
+ "safari": "13.1",
+ "node": "14",
+ "deno": "1",
+ "ios": "13.4",
+ "samsung": "13",
+ "opera_mobile": "57",
+ "electron": "8.0"
+ },
+ "transform-parameters": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "transform-async-to-generator": {
+ "chrome": "55",
+ "opera": "42",
+ "edge": "15",
+ "firefox": "52",
+ "safari": "10.1",
+ "node": "7.6",
+ "deno": "1",
+ "ios": "10.3",
+ "samsung": "6",
+ "opera_mobile": "42",
+ "electron": "1.6"
+ },
+ "transform-template-literals": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "13",
+ "firefox": "34",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "transform-function-name": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "14",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "transform-block-scoping": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "14",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ }
+}
diff --git a/Issue4/node_modules/@babel/compat-data/data/plugins.json b/Issue4/node_modules/@babel/compat-data/data/plugins.json
new file mode 100755
index 0000000000000000000000000000000000000000..65d76621f17beee2f9bec4869d04ab7187ef7c3e
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/data/plugins.json
@@ -0,0 +1,825 @@
+{
+ "transform-duplicate-named-capturing-groups-regex": {
+ "chrome": "126",
+ "opera": "112",
+ "edge": "126",
+ "firefox": "129",
+ "safari": "17.4",
+ "node": "23",
+ "ios": "17.4",
+ "electron": "31.0"
+ },
+ "transform-regexp-modifiers": {
+ "chrome": "125",
+ "opera": "111",
+ "edge": "125",
+ "firefox": "132",
+ "node": "23",
+ "electron": "31.0"
+ },
+ "transform-unicode-sets-regex": {
+ "chrome": "112",
+ "opera": "98",
+ "edge": "112",
+ "firefox": "116",
+ "safari": "17",
+ "node": "20",
+ "deno": "1.32",
+ "ios": "17",
+ "opera_mobile": "75",
+ "electron": "24.0"
+ },
+ "bugfix/transform-v8-static-class-fields-redefine-readonly": {
+ "chrome": "98",
+ "opera": "84",
+ "edge": "98",
+ "firefox": "75",
+ "safari": "15",
+ "node": "12",
+ "deno": "1.18",
+ "ios": "15",
+ "samsung": "11",
+ "opera_mobile": "52",
+ "electron": "17.0"
+ },
+ "bugfix/transform-firefox-class-in-computed-class-key": {
+ "chrome": "74",
+ "opera": "62",
+ "edge": "79",
+ "safari": "16",
+ "node": "12",
+ "deno": "1",
+ "ios": "16",
+ "samsung": "11",
+ "opera_mobile": "53",
+ "electron": "6.0"
+ },
+ "bugfix/transform-safari-class-field-initializer-scope": {
+ "chrome": "74",
+ "opera": "62",
+ "edge": "79",
+ "firefox": "69",
+ "safari": "16",
+ "node": "12",
+ "deno": "1",
+ "ios": "16",
+ "samsung": "11",
+ "opera_mobile": "53",
+ "electron": "6.0"
+ },
+ "transform-class-static-block": {
+ "chrome": "94",
+ "opera": "80",
+ "edge": "94",
+ "firefox": "93",
+ "safari": "16.4",
+ "node": "16.11",
+ "deno": "1.14",
+ "ios": "16.4",
+ "samsung": "17",
+ "opera_mobile": "66",
+ "electron": "15.0"
+ },
+ "proposal-class-static-block": {
+ "chrome": "94",
+ "opera": "80",
+ "edge": "94",
+ "firefox": "93",
+ "safari": "16.4",
+ "node": "16.11",
+ "deno": "1.14",
+ "ios": "16.4",
+ "samsung": "17",
+ "opera_mobile": "66",
+ "electron": "15.0"
+ },
+ "transform-private-property-in-object": {
+ "chrome": "91",
+ "opera": "77",
+ "edge": "91",
+ "firefox": "90",
+ "safari": "15",
+ "node": "16.9",
+ "deno": "1.9",
+ "ios": "15",
+ "samsung": "16",
+ "opera_mobile": "64",
+ "electron": "13.0"
+ },
+ "proposal-private-property-in-object": {
+ "chrome": "91",
+ "opera": "77",
+ "edge": "91",
+ "firefox": "90",
+ "safari": "15",
+ "node": "16.9",
+ "deno": "1.9",
+ "ios": "15",
+ "samsung": "16",
+ "opera_mobile": "64",
+ "electron": "13.0"
+ },
+ "transform-class-properties": {
+ "chrome": "74",
+ "opera": "62",
+ "edge": "79",
+ "firefox": "90",
+ "safari": "14.1",
+ "node": "12",
+ "deno": "1",
+ "ios": "14.5",
+ "samsung": "11",
+ "opera_mobile": "53",
+ "electron": "6.0"
+ },
+ "proposal-class-properties": {
+ "chrome": "74",
+ "opera": "62",
+ "edge": "79",
+ "firefox": "90",
+ "safari": "14.1",
+ "node": "12",
+ "deno": "1",
+ "ios": "14.5",
+ "samsung": "11",
+ "opera_mobile": "53",
+ "electron": "6.0"
+ },
+ "transform-private-methods": {
+ "chrome": "84",
+ "opera": "70",
+ "edge": "84",
+ "firefox": "90",
+ "safari": "15",
+ "node": "14.6",
+ "deno": "1",
+ "ios": "15",
+ "samsung": "14",
+ "opera_mobile": "60",
+ "electron": "10.0"
+ },
+ "proposal-private-methods": {
+ "chrome": "84",
+ "opera": "70",
+ "edge": "84",
+ "firefox": "90",
+ "safari": "15",
+ "node": "14.6",
+ "deno": "1",
+ "ios": "15",
+ "samsung": "14",
+ "opera_mobile": "60",
+ "electron": "10.0"
+ },
+ "transform-numeric-separator": {
+ "chrome": "75",
+ "opera": "62",
+ "edge": "79",
+ "firefox": "70",
+ "safari": "13",
+ "node": "12.5",
+ "deno": "1",
+ "ios": "13",
+ "samsung": "11",
+ "rhino": "1.7.14",
+ "opera_mobile": "54",
+ "electron": "6.0"
+ },
+ "proposal-numeric-separator": {
+ "chrome": "75",
+ "opera": "62",
+ "edge": "79",
+ "firefox": "70",
+ "safari": "13",
+ "node": "12.5",
+ "deno": "1",
+ "ios": "13",
+ "samsung": "11",
+ "rhino": "1.7.14",
+ "opera_mobile": "54",
+ "electron": "6.0"
+ },
+ "transform-logical-assignment-operators": {
+ "chrome": "85",
+ "opera": "71",
+ "edge": "85",
+ "firefox": "79",
+ "safari": "14",
+ "node": "15",
+ "deno": "1.2",
+ "ios": "14",
+ "samsung": "14",
+ "opera_mobile": "60",
+ "electron": "10.0"
+ },
+ "proposal-logical-assignment-operators": {
+ "chrome": "85",
+ "opera": "71",
+ "edge": "85",
+ "firefox": "79",
+ "safari": "14",
+ "node": "15",
+ "deno": "1.2",
+ "ios": "14",
+ "samsung": "14",
+ "opera_mobile": "60",
+ "electron": "10.0"
+ },
+ "transform-nullish-coalescing-operator": {
+ "chrome": "80",
+ "opera": "67",
+ "edge": "80",
+ "firefox": "72",
+ "safari": "13.1",
+ "node": "14",
+ "deno": "1",
+ "ios": "13.4",
+ "samsung": "13",
+ "opera_mobile": "57",
+ "electron": "8.0"
+ },
+ "proposal-nullish-coalescing-operator": {
+ "chrome": "80",
+ "opera": "67",
+ "edge": "80",
+ "firefox": "72",
+ "safari": "13.1",
+ "node": "14",
+ "deno": "1",
+ "ios": "13.4",
+ "samsung": "13",
+ "opera_mobile": "57",
+ "electron": "8.0"
+ },
+ "transform-optional-chaining": {
+ "chrome": "91",
+ "opera": "77",
+ "edge": "91",
+ "firefox": "74",
+ "safari": "13.1",
+ "node": "16.9",
+ "deno": "1.9",
+ "ios": "13.4",
+ "samsung": "16",
+ "opera_mobile": "64",
+ "electron": "13.0"
+ },
+ "proposal-optional-chaining": {
+ "chrome": "91",
+ "opera": "77",
+ "edge": "91",
+ "firefox": "74",
+ "safari": "13.1",
+ "node": "16.9",
+ "deno": "1.9",
+ "ios": "13.4",
+ "samsung": "16",
+ "opera_mobile": "64",
+ "electron": "13.0"
+ },
+ "transform-json-strings": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "79",
+ "firefox": "62",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "9",
+ "rhino": "1.7.14",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "proposal-json-strings": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "79",
+ "firefox": "62",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "9",
+ "rhino": "1.7.14",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "transform-optional-catch-binding": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "79",
+ "firefox": "58",
+ "safari": "11.1",
+ "node": "10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "9",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "proposal-optional-catch-binding": {
+ "chrome": "66",
+ "opera": "53",
+ "edge": "79",
+ "firefox": "58",
+ "safari": "11.1",
+ "node": "10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "9",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "transform-parameters": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "18",
+ "firefox": "53",
+ "safari": "16.3",
+ "node": "6",
+ "deno": "1",
+ "ios": "16.3",
+ "samsung": "5",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "transform-async-generator-functions": {
+ "chrome": "63",
+ "opera": "50",
+ "edge": "79",
+ "firefox": "57",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "proposal-async-generator-functions": {
+ "chrome": "63",
+ "opera": "50",
+ "edge": "79",
+ "firefox": "57",
+ "safari": "12",
+ "node": "10",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "8",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "transform-object-rest-spread": {
+ "chrome": "60",
+ "opera": "47",
+ "edge": "79",
+ "firefox": "55",
+ "safari": "11.1",
+ "node": "8.3",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "8",
+ "opera_mobile": "44",
+ "electron": "2.0"
+ },
+ "proposal-object-rest-spread": {
+ "chrome": "60",
+ "opera": "47",
+ "edge": "79",
+ "firefox": "55",
+ "safari": "11.1",
+ "node": "8.3",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "8",
+ "opera_mobile": "44",
+ "electron": "2.0"
+ },
+ "transform-dotall-regex": {
+ "chrome": "62",
+ "opera": "49",
+ "edge": "79",
+ "firefox": "78",
+ "safari": "11.1",
+ "node": "8.10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "8",
+ "rhino": "1.7.15",
+ "opera_mobile": "46",
+ "electron": "3.0"
+ },
+ "transform-unicode-property-regex": {
+ "chrome": "64",
+ "opera": "51",
+ "edge": "79",
+ "firefox": "78",
+ "safari": "11.1",
+ "node": "10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "9",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "proposal-unicode-property-regex": {
+ "chrome": "64",
+ "opera": "51",
+ "edge": "79",
+ "firefox": "78",
+ "safari": "11.1",
+ "node": "10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "9",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "transform-named-capturing-groups-regex": {
+ "chrome": "64",
+ "opera": "51",
+ "edge": "79",
+ "firefox": "78",
+ "safari": "11.1",
+ "node": "10",
+ "deno": "1",
+ "ios": "11.3",
+ "samsung": "9",
+ "opera_mobile": "47",
+ "electron": "3.0"
+ },
+ "transform-async-to-generator": {
+ "chrome": "55",
+ "opera": "42",
+ "edge": "15",
+ "firefox": "52",
+ "safari": "11",
+ "node": "7.6",
+ "deno": "1",
+ "ios": "11",
+ "samsung": "6",
+ "opera_mobile": "42",
+ "electron": "1.6"
+ },
+ "transform-exponentiation-operator": {
+ "chrome": "52",
+ "opera": "39",
+ "edge": "14",
+ "firefox": "52",
+ "safari": "10.1",
+ "node": "7",
+ "deno": "1",
+ "ios": "10.3",
+ "samsung": "6",
+ "rhino": "1.7.14",
+ "opera_mobile": "41",
+ "electron": "1.3"
+ },
+ "transform-template-literals": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "13",
+ "firefox": "34",
+ "safari": "13",
+ "node": "4",
+ "deno": "1",
+ "ios": "13",
+ "samsung": "3.4",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "transform-literals": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "53",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.15",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "transform-function-name": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "79",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "transform-arrow-functions": {
+ "chrome": "47",
+ "opera": "34",
+ "edge": "13",
+ "firefox": "43",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.13",
+ "opera_mobile": "34",
+ "electron": "0.36"
+ },
+ "transform-block-scoped-functions": {
+ "chrome": "41",
+ "opera": "28",
+ "edge": "12",
+ "firefox": "46",
+ "safari": "10",
+ "node": "4",
+ "deno": "1",
+ "ie": "11",
+ "ios": "10",
+ "samsung": "3.4",
+ "opera_mobile": "28",
+ "electron": "0.21"
+ },
+ "transform-classes": {
+ "chrome": "46",
+ "opera": "33",
+ "edge": "13",
+ "firefox": "45",
+ "safari": "10",
+ "node": "5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "33",
+ "electron": "0.36"
+ },
+ "transform-object-super": {
+ "chrome": "46",
+ "opera": "33",
+ "edge": "13",
+ "firefox": "45",
+ "safari": "10",
+ "node": "5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "33",
+ "electron": "0.36"
+ },
+ "transform-shorthand-properties": {
+ "chrome": "43",
+ "opera": "30",
+ "edge": "12",
+ "firefox": "33",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.14",
+ "opera_mobile": "30",
+ "electron": "0.27"
+ },
+ "transform-duplicate-keys": {
+ "chrome": "42",
+ "opera": "29",
+ "edge": "12",
+ "firefox": "34",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3.4",
+ "opera_mobile": "29",
+ "electron": "0.25"
+ },
+ "transform-computed-properties": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "34",
+ "safari": "7.1",
+ "node": "4",
+ "deno": "1",
+ "ios": "8",
+ "samsung": "4",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "transform-for-of": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "transform-sticky-regex": {
+ "chrome": "49",
+ "opera": "36",
+ "edge": "13",
+ "firefox": "3",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "rhino": "1.7.15",
+ "opera_mobile": "36",
+ "electron": "0.37"
+ },
+ "transform-unicode-escapes": {
+ "chrome": "44",
+ "opera": "31",
+ "edge": "12",
+ "firefox": "53",
+ "safari": "9",
+ "node": "4",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "4",
+ "rhino": "1.7.15",
+ "opera_mobile": "32",
+ "electron": "0.30"
+ },
+ "transform-unicode-regex": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "13",
+ "firefox": "46",
+ "safari": "12",
+ "node": "6",
+ "deno": "1",
+ "ios": "12",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "transform-spread": {
+ "chrome": "46",
+ "opera": "33",
+ "edge": "13",
+ "firefox": "45",
+ "safari": "10",
+ "node": "5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "33",
+ "electron": "0.36"
+ },
+ "transform-destructuring": {
+ "chrome": "51",
+ "opera": "38",
+ "edge": "15",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6.5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "41",
+ "electron": "1.2"
+ },
+ "transform-block-scoping": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "14",
+ "firefox": "53",
+ "safari": "11",
+ "node": "6",
+ "deno": "1",
+ "ios": "11",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "transform-typeof-symbol": {
+ "chrome": "38",
+ "opera": "25",
+ "edge": "12",
+ "firefox": "36",
+ "safari": "9",
+ "node": "0.12",
+ "deno": "1",
+ "ios": "9",
+ "samsung": "3",
+ "rhino": "1.7.13",
+ "opera_mobile": "25",
+ "electron": "0.20"
+ },
+ "transform-new-target": {
+ "chrome": "46",
+ "opera": "33",
+ "edge": "14",
+ "firefox": "41",
+ "safari": "10",
+ "node": "5",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "33",
+ "electron": "0.36"
+ },
+ "transform-regenerator": {
+ "chrome": "50",
+ "opera": "37",
+ "edge": "13",
+ "firefox": "53",
+ "safari": "10",
+ "node": "6",
+ "deno": "1",
+ "ios": "10",
+ "samsung": "5",
+ "opera_mobile": "37",
+ "electron": "1.1"
+ },
+ "transform-member-expression-literals": {
+ "chrome": "7",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "5.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "transform-property-literals": {
+ "chrome": "7",
+ "opera": "12",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "5.1",
+ "node": "0.4",
+ "deno": "1",
+ "ie": "9",
+ "android": "4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "12",
+ "electron": "0.20"
+ },
+ "transform-reserved-words": {
+ "chrome": "13",
+ "opera": "10.50",
+ "edge": "12",
+ "firefox": "2",
+ "safari": "3.1",
+ "node": "0.6",
+ "deno": "1",
+ "ie": "9",
+ "android": "4.4",
+ "ios": "6",
+ "phantom": "1.9",
+ "samsung": "1",
+ "rhino": "1.7.13",
+ "opera_mobile": "10.1",
+ "electron": "0.20"
+ },
+ "transform-export-namespace-from": {
+ "chrome": "72",
+ "deno": "1.0",
+ "edge": "79",
+ "firefox": "80",
+ "node": "13.2",
+ "opera": "60",
+ "opera_mobile": "51",
+ "safari": "14.1",
+ "ios": "14.5",
+ "samsung": "11.0",
+ "android": "72",
+ "electron": "5.0"
+ },
+ "proposal-export-namespace-from": {
+ "chrome": "72",
+ "deno": "1.0",
+ "edge": "79",
+ "firefox": "80",
+ "node": "13.2",
+ "opera": "60",
+ "opera_mobile": "51",
+ "safari": "14.1",
+ "ios": "14.5",
+ "samsung": "11.0",
+ "android": "72",
+ "electron": "5.0"
+ }
+}
diff --git a/Issue4/node_modules/@babel/compat-data/native-modules.js b/Issue4/node_modules/@babel/compat-data/native-modules.js
new file mode 100755
index 0000000000000000000000000000000000000000..8e97da4bcfde871962df602e6f10c230f54ddf10
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/native-modules.js
@@ -0,0 +1 @@
+module.exports = require("./data/native-modules.json");
diff --git a/Issue4/node_modules/@babel/compat-data/overlapping-plugins.js b/Issue4/node_modules/@babel/compat-data/overlapping-plugins.js
new file mode 100755
index 0000000000000000000000000000000000000000..88242e467810d45bf6e3f2d39cb4ab09161b6a8f
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/overlapping-plugins.js
@@ -0,0 +1 @@
+module.exports = require("./data/overlapping-plugins.json");
diff --git a/Issue4/node_modules/@babel/compat-data/package.json b/Issue4/node_modules/@babel/compat-data/package.json
new file mode 100755
index 0000000000000000000000000000000000000000..d3c1394006a49f32e563b59282c72a53b7a2fe07
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@babel/compat-data",
+ "version": "7.26.2",
+ "author": "The Babel Team (https://babel.dev/team)",
+ "license": "MIT",
+ "description": "",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/babel/babel.git",
+ "directory": "packages/babel-compat-data"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "exports": {
+ "./plugins": "./plugins.js",
+ "./native-modules": "./native-modules.js",
+ "./corejs2-built-ins": "./corejs2-built-ins.js",
+ "./corejs3-shipped-proposals": "./corejs3-shipped-proposals.js",
+ "./overlapping-plugins": "./overlapping-plugins.js",
+ "./plugin-bugfixes": "./plugin-bugfixes.js"
+ },
+ "scripts": {
+ "build-data": "./scripts/download-compat-table.sh && node ./scripts/build-data.js && node ./scripts/build-modules-support.js && node ./scripts/build-bugfixes-targets.js"
+ },
+ "keywords": [
+ "babel",
+ "compat-table",
+ "compat-data"
+ ],
+ "devDependencies": {
+ "@mdn/browser-compat-data": "^5.5.36",
+ "core-js-compat": "^3.37.1",
+ "electron-to-chromium": "^1.4.816"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "type": "commonjs"
+}
\ No newline at end of file
diff --git a/Issue4/node_modules/@babel/compat-data/plugin-bugfixes.js b/Issue4/node_modules/@babel/compat-data/plugin-bugfixes.js
new file mode 100755
index 0000000000000000000000000000000000000000..f390181a6302ef4f7a2a35aae5281f316924eab3
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/plugin-bugfixes.js
@@ -0,0 +1 @@
+module.exports = require("./data/plugin-bugfixes.json");
diff --git a/Issue4/node_modules/@babel/compat-data/plugins.js b/Issue4/node_modules/@babel/compat-data/plugins.js
new file mode 100755
index 0000000000000000000000000000000000000000..42646edce6dc93caf5e0707466b1b3a8bbd9124e
--- /dev/null
+++ b/Issue4/node_modules/@babel/compat-data/plugins.js
@@ -0,0 +1 @@
+module.exports = require("./data/plugins.json");
diff --git a/Issue4/node_modules/@babel/core/LICENSE b/Issue4/node_modules/@babel/core/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..f31575ec773bb199aeb7c0d0f1612cfe1c7038f1
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright (c) 2014-present Sebastian McKenzie and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Issue4/node_modules/@babel/core/README.md b/Issue4/node_modules/@babel/core/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..2903543469699795279ec0c977ee56114bd21e01
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/README.md
@@ -0,0 +1,19 @@
+# @babel/core
+
+> Babel compiler core.
+
+See our website [@babel/core](https://babeljs.io/docs/babel-core) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20core%22+is%3Aopen) associated with this package.
+
+## Install
+
+Using npm:
+
+```sh
+npm install --save-dev @babel/core
+```
+
+or using yarn:
+
+```sh
+yarn add @babel/core --dev
+```
diff --git a/Issue4/node_modules/@babel/core/cjs-proxy.cjs b/Issue4/node_modules/@babel/core/cjs-proxy.cjs
new file mode 100755
index 0000000000000000000000000000000000000000..accdb43d64b26d621268aab72379ce23a81996e1
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/cjs-proxy.cjs
@@ -0,0 +1,68 @@
+"use strict";
+
+const babelP = import("./lib/index.js");
+let babel = null;
+Object.defineProperty(exports, "__ initialize @babel/core cjs proxy __", {
+ set(val) {
+ babel = val;
+ },
+});
+
+exports.version = require("./package.json").version;
+
+const functionNames = [
+ "createConfigItem",
+ "loadPartialConfig",
+ "loadOptions",
+ "transform",
+ "transformFile",
+ "transformFromAst",
+ "parse",
+];
+const propertyNames = [
+ "buildExternalHelpers",
+ "types",
+ "tokTypes",
+ "traverse",
+ "template",
+];
+
+for (const name of functionNames) {
+ exports[name] = function (...args) {
+ if (
+ process.env.BABEL_8_BREAKING &&
+ typeof args[args.length - 1] !== "function"
+ ) {
+ throw new Error(
+ `Starting from Babel 8.0.0, the '${name}' function expects a callback. If you need to call it synchronously, please use '${name}Sync'.`
+ );
+ }
+
+ babelP.then(babel => {
+ babel[name](...args);
+ });
+ };
+ exports[`${name}Async`] = function (...args) {
+ return babelP.then(babel => babel[`${name}Async`](...args));
+ };
+ exports[`${name}Sync`] = function (...args) {
+ if (!babel) throw notLoadedError(`${name}Sync`, "callable");
+ return babel[`${name}Sync`](...args);
+ };
+}
+
+for (const name of propertyNames) {
+ Object.defineProperty(exports, name, {
+ get() {
+ if (!babel) throw notLoadedError(name, "accessible");
+ return babel[name];
+ },
+ });
+}
+
+function notLoadedError(name, keyword) {
+ return new Error(
+ `The \`${name}\` export of @babel/core is only ${keyword}` +
+ ` from the CommonJS version after that the ESM version is loaded.`
+ );
+}
diff --git a/Issue4/node_modules/@babel/core/lib/config/cache-contexts.js b/Issue4/node_modules/@babel/core/lib/config/cache-contexts.js
new file mode 100755
index 0000000000000000000000000000000000000000..d7c091273bd4e1fcf53e09cec65b03542cfad44b
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/cache-contexts.js
@@ -0,0 +1,3 @@
+0 && 0;
+
+//# sourceMappingURL=cache-contexts.js.map
diff --git a/Issue4/node_modules/@babel/core/lib/config/cache-contexts.js.map b/Issue4/node_modules/@babel/core/lib/config/cache-contexts.js.map
new file mode 100755
index 0000000000000000000000000000000000000000..9fa85d56b137b19c1e81e1b1ddb32c84cbff3b63
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/cache-contexts.js.map
@@ -0,0 +1 @@
+{"version":3,"names":[],"sources":["../../src/config/cache-contexts.ts"],"sourcesContent":["import type { Targets } from \"@babel/helper-compilation-targets\";\n\nimport type { ConfigContext } from \"./config-chain.ts\";\nimport type { CallerMetadata } from \"./validation/options.ts\";\n\nexport type { ConfigContext as FullConfig };\n\nexport type FullPreset = {\n targets: Targets;\n} & ConfigContext;\nexport type FullPlugin = {\n assumptions: { [name: string]: boolean };\n} & FullPreset;\n\n// Context not including filename since it is used in places that cannot\n// process 'ignore'/'only' and other filename-based logic.\nexport type SimpleConfig = {\n envName: string;\n caller: CallerMetadata | undefined;\n};\nexport type SimplePreset = {\n targets: Targets;\n} & SimpleConfig;\nexport type SimplePlugin = {\n assumptions: {\n [name: string]: boolean;\n };\n} & SimplePreset;\n"],"mappings":"","ignoreList":[]}
\ No newline at end of file
diff --git a/Issue4/node_modules/@babel/core/lib/config/caching.js b/Issue4/node_modules/@babel/core/lib/config/caching.js
new file mode 100755
index 0000000000000000000000000000000000000000..344c8390e3d054513e7c797fef4cfa98f0ba30f7
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/caching.js
@@ -0,0 +1,261 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.assertSimpleType = assertSimpleType;
+exports.makeStrongCache = makeStrongCache;
+exports.makeStrongCacheSync = makeStrongCacheSync;
+exports.makeWeakCache = makeWeakCache;
+exports.makeWeakCacheSync = makeWeakCacheSync;
+function _gensync() {
+ const data = require("gensync");
+ _gensync = function () {
+ return data;
+ };
+ return data;
+}
+var _async = require("../gensync-utils/async.js");
+var _util = require("./util.js");
+const synchronize = gen => {
+ return _gensync()(gen).sync;
+};
+function* genTrue() {
+ return true;
+}
+function makeWeakCache(handler) {
+ return makeCachedFunction(WeakMap, handler);
+}
+function makeWeakCacheSync(handler) {
+ return synchronize(makeWeakCache(handler));
+}
+function makeStrongCache(handler) {
+ return makeCachedFunction(Map, handler);
+}
+function makeStrongCacheSync(handler) {
+ return synchronize(makeStrongCache(handler));
+}
+function makeCachedFunction(CallCache, handler) {
+ const callCacheSync = new CallCache();
+ const callCacheAsync = new CallCache();
+ const futureCache = new CallCache();
+ return function* cachedFunction(arg, data) {
+ const asyncContext = yield* (0, _async.isAsync)();
+ const callCache = asyncContext ? callCacheAsync : callCacheSync;
+ const cached = yield* getCachedValueOrWait(asyncContext, callCache, futureCache, arg, data);
+ if (cached.valid) return cached.value;
+ const cache = new CacheConfigurator(data);
+ const handlerResult = handler(arg, cache);
+ let finishLock;
+ let value;
+ if ((0, _util.isIterableIterator)(handlerResult)) {
+ value = yield* (0, _async.onFirstPause)(handlerResult, () => {
+ finishLock = setupAsyncLocks(cache, futureCache, arg);
+ });
+ } else {
+ value = handlerResult;
+ }
+ updateFunctionCache(callCache, cache, arg, value);
+ if (finishLock) {
+ futureCache.delete(arg);
+ finishLock.release(value);
+ }
+ return value;
+ };
+}
+function* getCachedValue(cache, arg, data) {
+ const cachedValue = cache.get(arg);
+ if (cachedValue) {
+ for (const {
+ value,
+ valid
+ } of cachedValue) {
+ if (yield* valid(data)) return {
+ valid: true,
+ value
+ };
+ }
+ }
+ return {
+ valid: false,
+ value: null
+ };
+}
+function* getCachedValueOrWait(asyncContext, callCache, futureCache, arg, data) {
+ const cached = yield* getCachedValue(callCache, arg, data);
+ if (cached.valid) {
+ return cached;
+ }
+ if (asyncContext) {
+ const cached = yield* getCachedValue(futureCache, arg, data);
+ if (cached.valid) {
+ const value = yield* (0, _async.waitFor)(cached.value.promise);
+ return {
+ valid: true,
+ value
+ };
+ }
+ }
+ return {
+ valid: false,
+ value: null
+ };
+}
+function setupAsyncLocks(config, futureCache, arg) {
+ const finishLock = new Lock();
+ updateFunctionCache(futureCache, config, arg, finishLock);
+ return finishLock;
+}
+function updateFunctionCache(cache, config, arg, value) {
+ if (!config.configured()) config.forever();
+ let cachedValue = cache.get(arg);
+ config.deactivate();
+ switch (config.mode()) {
+ case "forever":
+ cachedValue = [{
+ value,
+ valid: genTrue
+ }];
+ cache.set(arg, cachedValue);
+ break;
+ case "invalidate":
+ cachedValue = [{
+ value,
+ valid: config.validator()
+ }];
+ cache.set(arg, cachedValue);
+ break;
+ case "valid":
+ if (cachedValue) {
+ cachedValue.push({
+ value,
+ valid: config.validator()
+ });
+ } else {
+ cachedValue = [{
+ value,
+ valid: config.validator()
+ }];
+ cache.set(arg, cachedValue);
+ }
+ }
+}
+class CacheConfigurator {
+ constructor(data) {
+ this._active = true;
+ this._never = false;
+ this._forever = false;
+ this._invalidate = false;
+ this._configured = false;
+ this._pairs = [];
+ this._data = void 0;
+ this._data = data;
+ }
+ simple() {
+ return makeSimpleConfigurator(this);
+ }
+ mode() {
+ if (this._never) return "never";
+ if (this._forever) return "forever";
+ if (this._invalidate) return "invalidate";
+ return "valid";
+ }
+ forever() {
+ if (!this._active) {
+ throw new Error("Cannot change caching after evaluation has completed.");
+ }
+ if (this._never) {
+ throw new Error("Caching has already been configured with .never()");
+ }
+ this._forever = true;
+ this._configured = true;
+ }
+ never() {
+ if (!this._active) {
+ throw new Error("Cannot change caching after evaluation has completed.");
+ }
+ if (this._forever) {
+ throw new Error("Caching has already been configured with .forever()");
+ }
+ this._never = true;
+ this._configured = true;
+ }
+ using(handler) {
+ if (!this._active) {
+ throw new Error("Cannot change caching after evaluation has completed.");
+ }
+ if (this._never || this._forever) {
+ throw new Error("Caching has already been configured with .never or .forever()");
+ }
+ this._configured = true;
+ const key = handler(this._data);
+ const fn = (0, _async.maybeAsync)(handler, `You appear to be using an async cache handler, but Babel has been called synchronously`);
+ if ((0, _async.isThenable)(key)) {
+ return key.then(key => {
+ this._pairs.push([key, fn]);
+ return key;
+ });
+ }
+ this._pairs.push([key, fn]);
+ return key;
+ }
+ invalidate(handler) {
+ this._invalidate = true;
+ return this.using(handler);
+ }
+ validator() {
+ const pairs = this._pairs;
+ return function* (data) {
+ for (const [key, fn] of pairs) {
+ if (key !== (yield* fn(data))) return false;
+ }
+ return true;
+ };
+ }
+ deactivate() {
+ this._active = false;
+ }
+ configured() {
+ return this._configured;
+ }
+}
+function makeSimpleConfigurator(cache) {
+ function cacheFn(val) {
+ if (typeof val === "boolean") {
+ if (val) cache.forever();else cache.never();
+ return;
+ }
+ return cache.using(() => assertSimpleType(val()));
+ }
+ cacheFn.forever = () => cache.forever();
+ cacheFn.never = () => cache.never();
+ cacheFn.using = cb => cache.using(() => assertSimpleType(cb()));
+ cacheFn.invalidate = cb => cache.invalidate(() => assertSimpleType(cb()));
+ return cacheFn;
+}
+function assertSimpleType(value) {
+ if ((0, _async.isThenable)(value)) {
+ throw new Error(`You appear to be using an async cache handler, ` + `which your current version of Babel does not support. ` + `We may add support for this in the future, ` + `but if you're on the most recent version of @babel/core and still ` + `seeing this error, then you'll need to synchronously handle your caching logic.`);
+ }
+ if (value != null && typeof value !== "string" && typeof value !== "boolean" && typeof value !== "number") {
+ throw new Error("Cache keys must be either string, boolean, number, null, or undefined.");
+ }
+ return value;
+}
+class Lock {
+ constructor() {
+ this.released = false;
+ this.promise = void 0;
+ this._resolve = void 0;
+ this.promise = new Promise(resolve => {
+ this._resolve = resolve;
+ });
+ }
+ release(value) {
+ this.released = true;
+ this._resolve(value);
+ }
+}
+0 && 0;
+
+//# sourceMappingURL=caching.js.map
diff --git a/Issue4/node_modules/@babel/core/lib/config/caching.js.map b/Issue4/node_modules/@babel/core/lib/config/caching.js.map
new file mode 100755
index 0000000000000000000000000000000000000000..174ac86111b6166bb40c859e85586f848cf262ba
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/caching.js.map
@@ -0,0 +1 @@
+{"version":3,"names":["_gensync","data","require","_async","_util","synchronize","gen","gensync","sync","genTrue","makeWeakCache","handler","makeCachedFunction","WeakMap","makeWeakCacheSync","makeStrongCache","Map","makeStrongCacheSync","CallCache","callCacheSync","callCacheAsync","futureCache","cachedFunction","arg","asyncContext","isAsync","callCache","cached","getCachedValueOrWait","valid","value","cache","CacheConfigurator","handlerResult","finishLock","isIterableIterator","onFirstPause","setupAsyncLocks","updateFunctionCache","delete","release","getCachedValue","cachedValue","get","waitFor","promise","config","Lock","configured","forever","deactivate","mode","set","validator","push","constructor","_active","_never","_forever","_invalidate","_configured","_pairs","_data","simple","makeSimpleConfigurator","Error","never","using","key","fn","maybeAsync","isThenable","then","invalidate","pairs","cacheFn","val","assertSimpleType","cb","released","_resolve","Promise","resolve"],"sources":["../../src/config/caching.ts"],"sourcesContent":["import gensync from \"gensync\";\nimport type { Handler } from \"gensync\";\nimport {\n maybeAsync,\n isAsync,\n onFirstPause,\n waitFor,\n isThenable,\n} from \"../gensync-utils/async.ts\";\nimport { isIterableIterator } from \"./util.ts\";\n\nexport type { CacheConfigurator };\n\nexport type SimpleCacheConfigurator = {\n (forever: boolean): void;\n (handler: () => T): T;\n\n forever: () => void;\n never: () => void;\n using: (handler: () => T) => T;\n invalidate: (handler: () => T) => T;\n};\n\nexport type CacheEntry = Array<{\n value: ResultT;\n valid: (channel: SideChannel) => Handler;\n}>;\n\nconst synchronize = (\n gen: (...args: ArgsT) => Handler,\n): ((...args: ArgsT) => ResultT) => {\n return gensync(gen).sync;\n};\n\n// eslint-disable-next-line require-yield\nfunction* genTrue() {\n return true;\n}\n\nexport function makeWeakCache(\n handler: (\n arg: ArgT,\n cache: CacheConfigurator,\n ) => Handler | ResultT,\n): (arg: ArgT, data: SideChannel) => Handler {\n return makeCachedFunction(WeakMap, handler);\n}\n\nexport function makeWeakCacheSync(\n handler: (arg: ArgT, cache?: CacheConfigurator) => ResultT,\n): (arg: ArgT, data?: SideChannel) => ResultT {\n return synchronize<[ArgT, SideChannel], ResultT>(\n makeWeakCache(handler),\n );\n}\n\nexport function makeStrongCache(\n handler: (\n arg: ArgT,\n cache: CacheConfigurator,\n ) => Handler | ResultT,\n): (arg: ArgT, data: SideChannel) => Handler {\n return makeCachedFunction(Map, handler);\n}\n\nexport function makeStrongCacheSync(\n handler: (arg: ArgT, cache?: CacheConfigurator) => ResultT,\n): (arg: ArgT, data?: SideChannel) => ResultT {\n return synchronize<[ArgT, SideChannel], ResultT>(\n makeStrongCache(handler),\n );\n}\n\n/* NOTE: Part of the logic explained in this comment is explained in the\n * getCachedValueOrWait and setupAsyncLocks functions.\n *\n * > There are only two hard things in Computer Science: cache invalidation and naming things.\n * > -- Phil Karlton\n *\n * I don't know if Phil was also thinking about handling a cache whose invalidation function is\n * defined asynchronously is considered, but it is REALLY hard to do correctly.\n *\n * The implemented logic (only when gensync is run asynchronously) is the following:\n * 1. If there is a valid cache associated to the current \"arg\" parameter,\n * a. RETURN the cached value\n * 3. If there is a FinishLock associated to the current \"arg\" parameter representing a valid cache,\n * a. Wait for that lock to be released\n * b. RETURN the value associated with that lock\n * 5. Start executing the function to be cached\n * a. If it pauses on a promise, then\n * i. Let FinishLock be a new lock\n * ii. Store FinishLock as associated to the current \"arg\" parameter\n * iii. Wait for the function to finish executing\n * iv. Release FinishLock\n * v. Send the function result to anyone waiting on FinishLock\n * 6. Store the result in the cache\n * 7. RETURN the result\n */\nfunction makeCachedFunction(\n CallCache: new () => CacheMap,\n handler: (\n arg: ArgT,\n cache: CacheConfigurator,\n ) => Handler | ResultT,\n): (arg: ArgT, data: SideChannel) => Handler {\n const callCacheSync = new CallCache();\n const callCacheAsync = new CallCache();\n const futureCache = new CallCache>();\n\n return function* cachedFunction(arg: ArgT, data: SideChannel) {\n const asyncContext = yield* isAsync();\n const callCache = asyncContext ? callCacheAsync : callCacheSync;\n\n const cached = yield* getCachedValueOrWait(\n asyncContext,\n callCache,\n futureCache,\n arg,\n data,\n );\n if (cached.valid) return cached.value;\n\n const cache = new CacheConfigurator(data);\n\n const handlerResult: Handler | ResultT = handler(arg, cache);\n\n let finishLock: Lock;\n let value: ResultT;\n\n if (isIterableIterator(handlerResult)) {\n value = yield* onFirstPause(handlerResult, () => {\n finishLock = setupAsyncLocks(cache, futureCache, arg);\n });\n } else {\n value = handlerResult;\n }\n\n updateFunctionCache(callCache, cache, arg, value);\n\n if (finishLock) {\n futureCache.delete(arg);\n finishLock.release(value);\n }\n\n return value;\n };\n}\n\ntype CacheMap =\n | Map>\n // @ts-expect-error todo(flow->ts): add `extends object` constraint to ArgT\n | WeakMap>;\n\nfunction* getCachedValue(\n cache: CacheMap,\n arg: ArgT,\n data: SideChannel,\n): Handler<{ valid: true; value: ResultT } | { valid: false; value: null }> {\n const cachedValue: CacheEntry | void = cache.get(arg);\n\n if (cachedValue) {\n for (const { value, valid } of cachedValue) {\n if (yield* valid(data)) return { valid: true, value };\n }\n }\n\n return { valid: false, value: null };\n}\n\nfunction* getCachedValueOrWait(\n asyncContext: boolean,\n callCache: CacheMap,\n futureCache: CacheMap, SideChannel>,\n arg: ArgT,\n data: SideChannel,\n): Handler<{ valid: true; value: ResultT } | { valid: false; value: null }> {\n const cached = yield* getCachedValue(callCache, arg, data);\n if (cached.valid) {\n return cached;\n }\n\n if (asyncContext) {\n const cached = yield* getCachedValue(futureCache, arg, data);\n if (cached.valid) {\n const value = yield* waitFor(cached.value.promise);\n return { valid: true, value };\n }\n }\n\n return { valid: false, value: null };\n}\n\nfunction setupAsyncLocks(\n config: CacheConfigurator,\n futureCache: CacheMap, SideChannel>,\n arg: ArgT,\n): Lock {\n const finishLock = new Lock();\n\n updateFunctionCache(futureCache, config, arg, finishLock);\n\n return finishLock;\n}\n\nfunction updateFunctionCache<\n ArgT,\n ResultT,\n SideChannel,\n Cache extends CacheMap,\n>(\n cache: Cache,\n config: CacheConfigurator,\n arg: ArgT,\n value: ResultT,\n) {\n if (!config.configured()) config.forever();\n\n let cachedValue: CacheEntry | void = cache.get(arg);\n\n config.deactivate();\n\n switch (config.mode()) {\n case \"forever\":\n cachedValue = [{ value, valid: genTrue }];\n cache.set(arg, cachedValue);\n break;\n case \"invalidate\":\n cachedValue = [{ value, valid: config.validator() }];\n cache.set(arg, cachedValue);\n break;\n case \"valid\":\n if (cachedValue) {\n cachedValue.push({ value, valid: config.validator() });\n } else {\n cachedValue = [{ value, valid: config.validator() }];\n cache.set(arg, cachedValue);\n }\n }\n}\n\nclass CacheConfigurator {\n _active: boolean = true;\n _never: boolean = false;\n _forever: boolean = false;\n _invalidate: boolean = false;\n\n _configured: boolean = false;\n\n _pairs: Array<\n [cachedValue: unknown, handler: (data: SideChannel) => Handler]\n > = [];\n\n _data: SideChannel;\n\n constructor(data: SideChannel) {\n this._data = data;\n }\n\n simple() {\n return makeSimpleConfigurator(this);\n }\n\n mode() {\n if (this._never) return \"never\";\n if (this._forever) return \"forever\";\n if (this._invalidate) return \"invalidate\";\n return \"valid\";\n }\n\n forever() {\n if (!this._active) {\n throw new Error(\"Cannot change caching after evaluation has completed.\");\n }\n if (this._never) {\n throw new Error(\"Caching has already been configured with .never()\");\n }\n this._forever = true;\n this._configured = true;\n }\n\n never() {\n if (!this._active) {\n throw new Error(\"Cannot change caching after evaluation has completed.\");\n }\n if (this._forever) {\n throw new Error(\"Caching has already been configured with .forever()\");\n }\n this._never = true;\n this._configured = true;\n }\n\n using(handler: (data: SideChannel) => T): T {\n if (!this._active) {\n throw new Error(\"Cannot change caching after evaluation has completed.\");\n }\n if (this._never || this._forever) {\n throw new Error(\n \"Caching has already been configured with .never or .forever()\",\n );\n }\n this._configured = true;\n\n const key = handler(this._data);\n\n const fn = maybeAsync(\n handler,\n `You appear to be using an async cache handler, but Babel has been called synchronously`,\n );\n\n if (isThenable(key)) {\n // @ts-expect-error todo(flow->ts): improve function return type annotation\n return key.then((key: unknown) => {\n this._pairs.push([key, fn]);\n return key;\n });\n }\n\n this._pairs.push([key, fn]);\n return key;\n }\n\n invalidate(handler: (data: SideChannel) => T): T {\n this._invalidate = true;\n return this.using(handler);\n }\n\n validator(): (data: SideChannel) => Handler {\n const pairs = this._pairs;\n return function* (data: SideChannel) {\n for (const [key, fn] of pairs) {\n if (key !== (yield* fn(data))) return false;\n }\n return true;\n };\n }\n\n deactivate() {\n this._active = false;\n }\n\n configured() {\n return this._configured;\n }\n}\n\nfunction makeSimpleConfigurator(\n cache: CacheConfigurator,\n): SimpleCacheConfigurator {\n function cacheFn(val: any) {\n if (typeof val === \"boolean\") {\n if (val) cache.forever();\n else cache.never();\n return;\n }\n\n return cache.using(() => assertSimpleType(val()));\n }\n cacheFn.forever = () => cache.forever();\n cacheFn.never = () => cache.never();\n cacheFn.using = (cb: () => SimpleType) =>\n cache.using(() => assertSimpleType(cb()));\n cacheFn.invalidate = (cb: () => SimpleType) =>\n cache.invalidate(() => assertSimpleType(cb()));\n\n return cacheFn as any;\n}\n\n// Types are limited here so that in the future these values can be used\n// as part of Babel's caching logic.\nexport type SimpleType =\n | string\n | boolean\n | number\n | null\n | void\n | Promise;\nexport function assertSimpleType(value: unknown): SimpleType {\n if (isThenable(value)) {\n throw new Error(\n `You appear to be using an async cache handler, ` +\n `which your current version of Babel does not support. ` +\n `We may add support for this in the future, ` +\n `but if you're on the most recent version of @babel/core and still ` +\n `seeing this error, then you'll need to synchronously handle your caching logic.`,\n );\n }\n\n if (\n value != null &&\n typeof value !== \"string\" &&\n typeof value !== \"boolean\" &&\n typeof value !== \"number\"\n ) {\n throw new Error(\n \"Cache keys must be either string, boolean, number, null, or undefined.\",\n );\n }\n // @ts-expect-error Type 'unknown' is not assignable to type 'SimpleType'. This can be removed\n // when strictNullCheck is enabled\n return value;\n}\n\nclass Lock {\n released: boolean = false;\n promise: Promise;\n _resolve: (value: T) => void;\n\n constructor() {\n this.promise = new Promise(resolve => {\n this._resolve = resolve;\n });\n }\n\n release(value: T) {\n this.released = true;\n this._resolve(value);\n }\n}\n"],"mappings":"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","ignoreList":[]}
\ No newline at end of file
diff --git a/Issue4/node_modules/@babel/core/lib/config/config-chain.js b/Issue4/node_modules/@babel/core/lib/config/config-chain.js
new file mode 100755
index 0000000000000000000000000000000000000000..591de0c9861373959eadcbcf1b7192d9592e969b
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/config-chain.js
@@ -0,0 +1,469 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.buildPresetChain = buildPresetChain;
+exports.buildPresetChainWalker = void 0;
+exports.buildRootChain = buildRootChain;
+function _path() {
+ const data = require("path");
+ _path = function () {
+ return data;
+ };
+ return data;
+}
+function _debug() {
+ const data = require("debug");
+ _debug = function () {
+ return data;
+ };
+ return data;
+}
+var _options = require("./validation/options.js");
+var _patternToRegex = require("./pattern-to-regex.js");
+var _printer = require("./printer.js");
+var _rewriteStackTrace = require("../errors/rewrite-stack-trace.js");
+var _configError = require("../errors/config-error.js");
+var _index = require("./files/index.js");
+var _caching = require("./caching.js");
+var _configDescriptors = require("./config-descriptors.js");
+const debug = _debug()("babel:config:config-chain");
+function* buildPresetChain(arg, context) {
+ const chain = yield* buildPresetChainWalker(arg, context);
+ if (!chain) return null;
+ return {
+ plugins: dedupDescriptors(chain.plugins),
+ presets: dedupDescriptors(chain.presets),
+ options: chain.options.map(o => normalizeOptions(o)),
+ files: new Set()
+ };
+}
+const buildPresetChainWalker = exports.buildPresetChainWalker = makeChainWalker({
+ root: preset => loadPresetDescriptors(preset),
+ env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),
+ overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),
+ overridesEnv: (preset, index, envName) => loadPresetOverridesEnvDescriptors(preset)(index)(envName),
+ createLogger: () => () => {}
+});
+const loadPresetDescriptors = (0, _caching.makeWeakCacheSync)(preset => buildRootDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors));
+const loadPresetEnvDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(envName => buildEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, envName)));
+const loadPresetOverridesDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(index => buildOverrideDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index)));
+const loadPresetOverridesEnvDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(index => (0, _caching.makeStrongCacheSync)(envName => buildOverrideEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index, envName))));
+function* buildRootChain(opts, context) {
+ let configReport, babelRcReport;
+ const programmaticLogger = new _printer.ConfigPrinter();
+ const programmaticChain = yield* loadProgrammaticChain({
+ options: opts,
+ dirname: context.cwd
+ }, context, undefined, programmaticLogger);
+ if (!programmaticChain) return null;
+ const programmaticReport = yield* programmaticLogger.output();
+ let configFile;
+ if (typeof opts.configFile === "string") {
+ configFile = yield* (0, _index.loadConfig)(opts.configFile, context.cwd, context.envName, context.caller);
+ } else if (opts.configFile !== false) {
+ configFile = yield* (0, _index.findRootConfig)(context.root, context.envName, context.caller);
+ }
+ let {
+ babelrc,
+ babelrcRoots
+ } = opts;
+ let babelrcRootsDirectory = context.cwd;
+ const configFileChain = emptyChain();
+ const configFileLogger = new _printer.ConfigPrinter();
+ if (configFile) {
+ const validatedFile = validateConfigFile(configFile);
+ const result = yield* loadFileChain(validatedFile, context, undefined, configFileLogger);
+ if (!result) return null;
+ configReport = yield* configFileLogger.output();
+ if (babelrc === undefined) {
+ babelrc = validatedFile.options.babelrc;
+ }
+ if (babelrcRoots === undefined) {
+ babelrcRootsDirectory = validatedFile.dirname;
+ babelrcRoots = validatedFile.options.babelrcRoots;
+ }
+ mergeChain(configFileChain, result);
+ }
+ let ignoreFile, babelrcFile;
+ let isIgnored = false;
+ const fileChain = emptyChain();
+ if ((babelrc === true || babelrc === undefined) && typeof context.filename === "string") {
+ const pkgData = yield* (0, _index.findPackageData)(context.filename);
+ if (pkgData && babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory)) {
+ ({
+ ignore: ignoreFile,
+ config: babelrcFile
+ } = yield* (0, _index.findRelativeConfig)(pkgData, context.envName, context.caller));
+ if (ignoreFile) {
+ fileChain.files.add(ignoreFile.filepath);
+ }
+ if (ignoreFile && shouldIgnore(context, ignoreFile.ignore, null, ignoreFile.dirname)) {
+ isIgnored = true;
+ }
+ if (babelrcFile && !isIgnored) {
+ const validatedFile = validateBabelrcFile(babelrcFile);
+ const babelrcLogger = new _printer.ConfigPrinter();
+ const result = yield* loadFileChain(validatedFile, context, undefined, babelrcLogger);
+ if (!result) {
+ isIgnored = true;
+ } else {
+ babelRcReport = yield* babelrcLogger.output();
+ mergeChain(fileChain, result);
+ }
+ }
+ if (babelrcFile && isIgnored) {
+ fileChain.files.add(babelrcFile.filepath);
+ }
+ }
+ }
+ if (context.showConfig) {
+ console.log(`Babel configs on "${context.filename}" (ascending priority):\n` + [configReport, babelRcReport, programmaticReport].filter(x => !!x).join("\n\n") + "\n-----End Babel configs-----");
+ }
+ const chain = mergeChain(mergeChain(mergeChain(emptyChain(), configFileChain), fileChain), programmaticChain);
+ return {
+ plugins: isIgnored ? [] : dedupDescriptors(chain.plugins),
+ presets: isIgnored ? [] : dedupDescriptors(chain.presets),
+ options: isIgnored ? [] : chain.options.map(o => normalizeOptions(o)),
+ fileHandling: isIgnored ? "ignored" : "transpile",
+ ignore: ignoreFile || undefined,
+ babelrc: babelrcFile || undefined,
+ config: configFile || undefined,
+ files: chain.files
+ };
+}
+function babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory) {
+ if (typeof babelrcRoots === "boolean") return babelrcRoots;
+ const absoluteRoot = context.root;
+ if (babelrcRoots === undefined) {
+ return pkgData.directories.includes(absoluteRoot);
+ }
+ let babelrcPatterns = babelrcRoots;
+ if (!Array.isArray(babelrcPatterns)) {
+ babelrcPatterns = [babelrcPatterns];
+ }
+ babelrcPatterns = babelrcPatterns.map(pat => {
+ return typeof pat === "string" ? _path().resolve(babelrcRootsDirectory, pat) : pat;
+ });
+ if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) {
+ return pkgData.directories.includes(absoluteRoot);
+ }
+ return babelrcPatterns.some(pat => {
+ if (typeof pat === "string") {
+ pat = (0, _patternToRegex.default)(pat, babelrcRootsDirectory);
+ }
+ return pkgData.directories.some(directory => {
+ return matchPattern(pat, babelrcRootsDirectory, directory, context);
+ });
+ });
+}
+const validateConfigFile = (0, _caching.makeWeakCacheSync)(file => ({
+ filepath: file.filepath,
+ dirname: file.dirname,
+ options: (0, _options.validate)("configfile", file.options, file.filepath)
+}));
+const validateBabelrcFile = (0, _caching.makeWeakCacheSync)(file => ({
+ filepath: file.filepath,
+ dirname: file.dirname,
+ options: (0, _options.validate)("babelrcfile", file.options, file.filepath)
+}));
+const validateExtendFile = (0, _caching.makeWeakCacheSync)(file => ({
+ filepath: file.filepath,
+ dirname: file.dirname,
+ options: (0, _options.validate)("extendsfile", file.options, file.filepath)
+}));
+const loadProgrammaticChain = makeChainWalker({
+ root: input => buildRootDescriptors(input, "base", _configDescriptors.createCachedDescriptors),
+ env: (input, envName) => buildEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, envName),
+ overrides: (input, index) => buildOverrideDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index),
+ overridesEnv: (input, index, envName) => buildOverrideEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index, envName),
+ createLogger: (input, context, baseLogger) => buildProgrammaticLogger(input, context, baseLogger)
+});
+const loadFileChainWalker = makeChainWalker({
+ root: file => loadFileDescriptors(file),
+ env: (file, envName) => loadFileEnvDescriptors(file)(envName),
+ overrides: (file, index) => loadFileOverridesDescriptors(file)(index),
+ overridesEnv: (file, index, envName) => loadFileOverridesEnvDescriptors(file)(index)(envName),
+ createLogger: (file, context, baseLogger) => buildFileLogger(file.filepath, context, baseLogger)
+});
+function* loadFileChain(input, context, files, baseLogger) {
+ const chain = yield* loadFileChainWalker(input, context, files, baseLogger);
+ chain == null || chain.files.add(input.filepath);
+ return chain;
+}
+const loadFileDescriptors = (0, _caching.makeWeakCacheSync)(file => buildRootDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors));
+const loadFileEnvDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(envName => buildEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, envName)));
+const loadFileOverridesDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(index => buildOverrideDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index)));
+const loadFileOverridesEnvDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(index => (0, _caching.makeStrongCacheSync)(envName => buildOverrideEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index, envName))));
+function buildFileLogger(filepath, context, baseLogger) {
+ if (!baseLogger) {
+ return () => {};
+ }
+ return baseLogger.configure(context.showConfig, _printer.ChainFormatter.Config, {
+ filepath
+ });
+}
+function buildRootDescriptors({
+ dirname,
+ options
+}, alias, descriptors) {
+ return descriptors(dirname, options, alias);
+}
+function buildProgrammaticLogger(_, context, baseLogger) {
+ var _context$caller;
+ if (!baseLogger) {
+ return () => {};
+ }
+ return baseLogger.configure(context.showConfig, _printer.ChainFormatter.Programmatic, {
+ callerName: (_context$caller = context.caller) == null ? void 0 : _context$caller.name
+ });
+}
+function buildEnvDescriptors({
+ dirname,
+ options
+}, alias, descriptors, envName) {
+ var _options$env;
+ const opts = (_options$env = options.env) == null ? void 0 : _options$env[envName];
+ return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null;
+}
+function buildOverrideDescriptors({
+ dirname,
+ options
+}, alias, descriptors, index) {
+ var _options$overrides;
+ const opts = (_options$overrides = options.overrides) == null ? void 0 : _options$overrides[index];
+ if (!opts) throw new Error("Assertion failure - missing override");
+ return descriptors(dirname, opts, `${alias}.overrides[${index}]`);
+}
+function buildOverrideEnvDescriptors({
+ dirname,
+ options
+}, alias, descriptors, index, envName) {
+ var _options$overrides2, _override$env;
+ const override = (_options$overrides2 = options.overrides) == null ? void 0 : _options$overrides2[index];
+ if (!override) throw new Error("Assertion failure - missing override");
+ const opts = (_override$env = override.env) == null ? void 0 : _override$env[envName];
+ return opts ? descriptors(dirname, opts, `${alias}.overrides[${index}].env["${envName}"]`) : null;
+}
+function makeChainWalker({
+ root,
+ env,
+ overrides,
+ overridesEnv,
+ createLogger
+}) {
+ return function* chainWalker(input, context, files = new Set(), baseLogger) {
+ const {
+ dirname
+ } = input;
+ const flattenedConfigs = [];
+ const rootOpts = root(input);
+ if (configIsApplicable(rootOpts, dirname, context, input.filepath)) {
+ flattenedConfigs.push({
+ config: rootOpts,
+ envName: undefined,
+ index: undefined
+ });
+ const envOpts = env(input, context.envName);
+ if (envOpts && configIsApplicable(envOpts, dirname, context, input.filepath)) {
+ flattenedConfigs.push({
+ config: envOpts,
+ envName: context.envName,
+ index: undefined
+ });
+ }
+ (rootOpts.options.overrides || []).forEach((_, index) => {
+ const overrideOps = overrides(input, index);
+ if (configIsApplicable(overrideOps, dirname, context, input.filepath)) {
+ flattenedConfigs.push({
+ config: overrideOps,
+ index,
+ envName: undefined
+ });
+ const overrideEnvOpts = overridesEnv(input, index, context.envName);
+ if (overrideEnvOpts && configIsApplicable(overrideEnvOpts, dirname, context, input.filepath)) {
+ flattenedConfigs.push({
+ config: overrideEnvOpts,
+ index,
+ envName: context.envName
+ });
+ }
+ }
+ });
+ }
+ if (flattenedConfigs.some(({
+ config: {
+ options: {
+ ignore,
+ only
+ }
+ }
+ }) => shouldIgnore(context, ignore, only, dirname))) {
+ return null;
+ }
+ const chain = emptyChain();
+ const logger = createLogger(input, context, baseLogger);
+ for (const {
+ config,
+ index,
+ envName
+ } of flattenedConfigs) {
+ if (!(yield* mergeExtendsChain(chain, config.options, dirname, context, files, baseLogger))) {
+ return null;
+ }
+ logger(config, index, envName);
+ yield* mergeChainOpts(chain, config);
+ }
+ return chain;
+ };
+}
+function* mergeExtendsChain(chain, opts, dirname, context, files, baseLogger) {
+ if (opts.extends === undefined) return true;
+ const file = yield* (0, _index.loadConfig)(opts.extends, dirname, context.envName, context.caller);
+ if (files.has(file)) {
+ throw new Error(`Configuration cycle detected loading ${file.filepath}.\n` + `File already loaded following the config chain:\n` + Array.from(files, file => ` - ${file.filepath}`).join("\n"));
+ }
+ files.add(file);
+ const fileChain = yield* loadFileChain(validateExtendFile(file), context, files, baseLogger);
+ files.delete(file);
+ if (!fileChain) return false;
+ mergeChain(chain, fileChain);
+ return true;
+}
+function mergeChain(target, source) {
+ target.options.push(...source.options);
+ target.plugins.push(...source.plugins);
+ target.presets.push(...source.presets);
+ for (const file of source.files) {
+ target.files.add(file);
+ }
+ return target;
+}
+function* mergeChainOpts(target, {
+ options,
+ plugins,
+ presets
+}) {
+ target.options.push(options);
+ target.plugins.push(...(yield* plugins()));
+ target.presets.push(...(yield* presets()));
+ return target;
+}
+function emptyChain() {
+ return {
+ options: [],
+ presets: [],
+ plugins: [],
+ files: new Set()
+ };
+}
+function normalizeOptions(opts) {
+ const options = Object.assign({}, opts);
+ delete options.extends;
+ delete options.env;
+ delete options.overrides;
+ delete options.plugins;
+ delete options.presets;
+ delete options.passPerPreset;
+ delete options.ignore;
+ delete options.only;
+ delete options.test;
+ delete options.include;
+ delete options.exclude;
+ if (hasOwnProperty.call(options, "sourceMap")) {
+ options.sourceMaps = options.sourceMap;
+ delete options.sourceMap;
+ }
+ return options;
+}
+function dedupDescriptors(items) {
+ const map = new Map();
+ const descriptors = [];
+ for (const item of items) {
+ if (typeof item.value === "function") {
+ const fnKey = item.value;
+ let nameMap = map.get(fnKey);
+ if (!nameMap) {
+ nameMap = new Map();
+ map.set(fnKey, nameMap);
+ }
+ let desc = nameMap.get(item.name);
+ if (!desc) {
+ desc = {
+ value: item
+ };
+ descriptors.push(desc);
+ if (!item.ownPass) nameMap.set(item.name, desc);
+ } else {
+ desc.value = item;
+ }
+ } else {
+ descriptors.push({
+ value: item
+ });
+ }
+ }
+ return descriptors.reduce((acc, desc) => {
+ acc.push(desc.value);
+ return acc;
+ }, []);
+}
+function configIsApplicable({
+ options
+}, dirname, context, configName) {
+ return (options.test === undefined || configFieldIsApplicable(context, options.test, dirname, configName)) && (options.include === undefined || configFieldIsApplicable(context, options.include, dirname, configName)) && (options.exclude === undefined || !configFieldIsApplicable(context, options.exclude, dirname, configName));
+}
+function configFieldIsApplicable(context, test, dirname, configName) {
+ const patterns = Array.isArray(test) ? test : [test];
+ return matchesPatterns(context, patterns, dirname, configName);
+}
+function ignoreListReplacer(_key, value) {
+ if (value instanceof RegExp) {
+ return String(value);
+ }
+ return value;
+}
+function shouldIgnore(context, ignore, only, dirname) {
+ if (ignore && matchesPatterns(context, ignore, dirname)) {
+ var _context$filename;
+ const message = `No config is applied to "${(_context$filename = context.filename) != null ? _context$filename : "(unknown)"}" because it matches one of \`ignore: ${JSON.stringify(ignore, ignoreListReplacer)}\` from "${dirname}"`;
+ debug(message);
+ if (context.showConfig) {
+ console.log(message);
+ }
+ return true;
+ }
+ if (only && !matchesPatterns(context, only, dirname)) {
+ var _context$filename2;
+ const message = `No config is applied to "${(_context$filename2 = context.filename) != null ? _context$filename2 : "(unknown)"}" because it fails to match one of \`only: ${JSON.stringify(only, ignoreListReplacer)}\` from "${dirname}"`;
+ debug(message);
+ if (context.showConfig) {
+ console.log(message);
+ }
+ return true;
+ }
+ return false;
+}
+function matchesPatterns(context, patterns, dirname, configName) {
+ return patterns.some(pattern => matchPattern(pattern, dirname, context.filename, context, configName));
+}
+function matchPattern(pattern, dirname, pathToTest, context, configName) {
+ if (typeof pattern === "function") {
+ return !!(0, _rewriteStackTrace.endHiddenCallStack)(pattern)(pathToTest, {
+ dirname,
+ envName: context.envName,
+ caller: context.caller
+ });
+ }
+ if (typeof pathToTest !== "string") {
+ throw new _configError.default(`Configuration contains string/RegExp pattern, but no filename was passed to Babel`, configName);
+ }
+ if (typeof pattern === "string") {
+ pattern = (0, _patternToRegex.default)(pattern, dirname);
+ }
+ return pattern.test(pathToTest);
+}
+0 && 0;
+
+//# sourceMappingURL=config-chain.js.map
diff --git a/Issue4/node_modules/@babel/core/lib/config/config-chain.js.map b/Issue4/node_modules/@babel/core/lib/config/config-chain.js.map
new file mode 100755
index 0000000000000000000000000000000000000000..8e58051db20b858d21b794dc8487322c0f613045
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/config-chain.js.map
@@ -0,0 +1 @@
+{"version":3,"names":["_path","data","require","_debug","_options","_patternToRegex","_printer","_rewriteStackTrace","_configError","_index","_caching","_configDescriptors","debug","buildDebug","buildPresetChain","arg","context","chain","buildPresetChainWalker","plugins","dedupDescriptors","presets","options","map","o","normalizeOptions","files","Set","exports","makeChainWalker","root","preset","loadPresetDescriptors","env","envName","loadPresetEnvDescriptors","overrides","index","loadPresetOverridesDescriptors","overridesEnv","loadPresetOverridesEnvDescriptors","createLogger","makeWeakCacheSync","buildRootDescriptors","alias","createUncachedDescriptors","makeStrongCacheSync","buildEnvDescriptors","buildOverrideDescriptors","buildOverrideEnvDescriptors","buildRootChain","opts","configReport","babelRcReport","programmaticLogger","ConfigPrinter","programmaticChain","loadProgrammaticChain","dirname","cwd","undefined","programmaticReport","output","configFile","loadConfig","caller","findRootConfig","babelrc","babelrcRoots","babelrcRootsDirectory","configFileChain","emptyChain","configFileLogger","validatedFile","validateConfigFile","result","loadFileChain","mergeChain","ignoreFile","babelrcFile","isIgnored","fileChain","filename","pkgData","findPackageData","babelrcLoadEnabled","ignore","config","findRelativeConfig","add","filepath","shouldIgnore","validateBabelrcFile","babelrcLogger","showConfig","console","log","filter","x","join","fileHandling","absoluteRoot","directories","includes","babelrcPatterns","Array","isArray","pat","path","resolve","length","some","pathPatternToRegex","directory","matchPattern","file","validate","validateExtendFile","input","createCachedDescriptors","baseLogger","buildProgrammaticLogger","loadFileChainWalker","loadFileDescriptors","loadFileEnvDescriptors","loadFileOverridesDescriptors","loadFileOverridesEnvDescriptors","buildFileLogger","configure","ChainFormatter","Config","descriptors","_","_context$caller","Programmatic","callerName","name","_options$env","_options$overrides","Error","_options$overrides2","_override$env","override","chainWalker","flattenedConfigs","rootOpts","configIsApplicable","push","envOpts","forEach","overrideOps","overrideEnvOpts","only","logger","mergeExtendsChain","mergeChainOpts","extends","has","from","delete","target","source","Object","assign","passPerPreset","test","include","exclude","hasOwnProperty","call","sourceMaps","sourceMap","items","Map","item","value","fnKey","nameMap","get","set","desc","ownPass","reduce","acc","configName","configFieldIsApplicable","patterns","matchesPatterns","ignoreListReplacer","_key","RegExp","String","_context$filename","message","JSON","stringify","_context$filename2","pattern","pathToTest","endHiddenCallStack","ConfigError"],"sources":["../../src/config/config-chain.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\n\nimport path from \"path\";\nimport buildDebug from \"debug\";\nimport type { Handler } from \"gensync\";\nimport { validate } from \"./validation/options.ts\";\nimport type {\n ValidatedOptions,\n IgnoreList,\n ConfigApplicableTest,\n BabelrcSearch,\n CallerMetadata,\n IgnoreItem,\n} from \"./validation/options.ts\";\nimport pathPatternToRegex from \"./pattern-to-regex.ts\";\nimport { ConfigPrinter, ChainFormatter } from \"./printer.ts\";\nimport type { ReadonlyDeepArray } from \"./helpers/deep-array.ts\";\n\nimport { endHiddenCallStack } from \"../errors/rewrite-stack-trace.ts\";\nimport ConfigError from \"../errors/config-error.ts\";\nimport type { PluginAPI, PresetAPI } from \"./helpers/config-api.ts\";\n\nconst debug = buildDebug(\"babel:config:config-chain\");\n\nimport {\n findPackageData,\n findRelativeConfig,\n findRootConfig,\n loadConfig,\n} from \"./files/index.ts\";\nimport type { ConfigFile, IgnoreFile, FilePackageData } from \"./files/index.ts\";\n\nimport { makeWeakCacheSync, makeStrongCacheSync } from \"./caching.ts\";\n\nimport {\n createCachedDescriptors,\n createUncachedDescriptors,\n} from \"./config-descriptors.ts\";\nimport type {\n UnloadedDescriptor,\n OptionsAndDescriptors,\n ValidatedFile,\n} from \"./config-descriptors.ts\";\n\nexport type ConfigChain = {\n plugins: Array>;\n presets: Array>;\n options: Array;\n files: Set;\n};\n\nexport type PresetInstance = {\n options: ValidatedOptions;\n alias: string;\n dirname: string;\n externalDependencies: ReadonlyDeepArray;\n};\n\nexport type ConfigContext = {\n filename: string | undefined;\n cwd: string;\n root: string;\n envName: string;\n caller: CallerMetadata | undefined;\n showConfig: boolean;\n};\n\n/**\n * Build a config chain for a given preset.\n */\nexport function* buildPresetChain(\n arg: PresetInstance,\n context: any,\n): Handler {\n const chain = yield* buildPresetChainWalker(arg, context);\n if (!chain) return null;\n\n return {\n plugins: dedupDescriptors(chain.plugins),\n presets: dedupDescriptors(chain.presets),\n options: chain.options.map(o => normalizeOptions(o)),\n files: new Set(),\n };\n}\n\nexport const buildPresetChainWalker = makeChainWalker({\n root: preset => loadPresetDescriptors(preset),\n env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),\n overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),\n overridesEnv: (preset, index, envName) =>\n loadPresetOverridesEnvDescriptors(preset)(index)(envName),\n createLogger: () => () => {}, // Currently we don't support logging how preset is expanded\n});\nconst loadPresetDescriptors = makeWeakCacheSync((preset: PresetInstance) =>\n buildRootDescriptors(preset, preset.alias, createUncachedDescriptors),\n);\nconst loadPresetEnvDescriptors = makeWeakCacheSync((preset: PresetInstance) =>\n makeStrongCacheSync((envName: string) =>\n buildEnvDescriptors(\n preset,\n preset.alias,\n createUncachedDescriptors,\n envName,\n ),\n ),\n);\nconst loadPresetOverridesDescriptors = makeWeakCacheSync(\n (preset: PresetInstance) =>\n makeStrongCacheSync((index: number) =>\n buildOverrideDescriptors(\n preset,\n preset.alias,\n createUncachedDescriptors,\n index,\n ),\n ),\n);\nconst loadPresetOverridesEnvDescriptors = makeWeakCacheSync(\n (preset: PresetInstance) =>\n makeStrongCacheSync((index: number) =>\n makeStrongCacheSync((envName: string) =>\n buildOverrideEnvDescriptors(\n preset,\n preset.alias,\n createUncachedDescriptors,\n index,\n envName,\n ),\n ),\n ),\n);\n\nexport type FileHandling = \"transpile\" | \"ignored\" | \"unsupported\";\nexport type RootConfigChain = ConfigChain & {\n babelrc: ConfigFile | void;\n config: ConfigFile | void;\n ignore: IgnoreFile | void;\n fileHandling: FileHandling;\n files: Set;\n};\n\n/**\n * Build a config chain for Babel's full root configuration.\n */\nexport function* buildRootChain(\n opts: ValidatedOptions,\n context: ConfigContext,\n): Handler {\n let configReport, babelRcReport;\n const programmaticLogger = new ConfigPrinter();\n const programmaticChain = yield* loadProgrammaticChain(\n {\n options: opts,\n dirname: context.cwd,\n },\n context,\n undefined,\n programmaticLogger,\n );\n if (!programmaticChain) return null;\n const programmaticReport = yield* programmaticLogger.output();\n\n let configFile;\n if (typeof opts.configFile === \"string\") {\n configFile = yield* loadConfig(\n opts.configFile,\n context.cwd,\n context.envName,\n context.caller,\n );\n } else if (opts.configFile !== false) {\n configFile = yield* findRootConfig(\n context.root,\n context.envName,\n context.caller,\n );\n }\n\n let { babelrc, babelrcRoots } = opts;\n let babelrcRootsDirectory = context.cwd;\n\n const configFileChain = emptyChain();\n const configFileLogger = new ConfigPrinter();\n if (configFile) {\n const validatedFile = validateConfigFile(configFile);\n const result = yield* loadFileChain(\n validatedFile,\n context,\n undefined,\n configFileLogger,\n );\n if (!result) return null;\n configReport = yield* configFileLogger.output();\n\n // Allow config files to toggle `.babelrc` resolution on and off and\n // specify where the roots are.\n if (babelrc === undefined) {\n babelrc = validatedFile.options.babelrc;\n }\n if (babelrcRoots === undefined) {\n babelrcRootsDirectory = validatedFile.dirname;\n babelrcRoots = validatedFile.options.babelrcRoots;\n }\n\n mergeChain(configFileChain, result);\n }\n\n let ignoreFile, babelrcFile;\n let isIgnored = false;\n const fileChain = emptyChain();\n // resolve all .babelrc files\n if (\n (babelrc === true || babelrc === undefined) &&\n typeof context.filename === \"string\"\n ) {\n const pkgData = yield* findPackageData(context.filename);\n\n if (\n pkgData &&\n babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory)\n ) {\n ({ ignore: ignoreFile, config: babelrcFile } = yield* findRelativeConfig(\n pkgData,\n context.envName,\n context.caller,\n ));\n\n if (ignoreFile) {\n fileChain.files.add(ignoreFile.filepath);\n }\n\n if (\n ignoreFile &&\n shouldIgnore(context, ignoreFile.ignore, null, ignoreFile.dirname)\n ) {\n isIgnored = true;\n }\n\n if (babelrcFile && !isIgnored) {\n const validatedFile = validateBabelrcFile(babelrcFile);\n const babelrcLogger = new ConfigPrinter();\n const result = yield* loadFileChain(\n validatedFile,\n context,\n undefined,\n babelrcLogger,\n );\n if (!result) {\n isIgnored = true;\n } else {\n babelRcReport = yield* babelrcLogger.output();\n mergeChain(fileChain, result);\n }\n }\n\n if (babelrcFile && isIgnored) {\n fileChain.files.add(babelrcFile.filepath);\n }\n }\n }\n\n if (context.showConfig) {\n console.log(\n `Babel configs on \"${context.filename}\" (ascending priority):\\n` +\n // print config by the order of ascending priority\n [configReport, babelRcReport, programmaticReport]\n .filter(x => !!x)\n .join(\"\\n\\n\") +\n \"\\n-----End Babel configs-----\",\n );\n }\n // Insert file chain in front so programmatic options have priority\n // over configuration file chain items.\n const chain = mergeChain(\n mergeChain(mergeChain(emptyChain(), configFileChain), fileChain),\n programmaticChain,\n );\n\n return {\n plugins: isIgnored ? [] : dedupDescriptors(chain.plugins),\n presets: isIgnored ? [] : dedupDescriptors(chain.presets),\n options: isIgnored ? [] : chain.options.map(o => normalizeOptions(o)),\n fileHandling: isIgnored ? \"ignored\" : \"transpile\",\n ignore: ignoreFile || undefined,\n babelrc: babelrcFile || undefined,\n config: configFile || undefined,\n files: chain.files,\n };\n}\n\nfunction babelrcLoadEnabled(\n context: ConfigContext,\n pkgData: FilePackageData,\n babelrcRoots: BabelrcSearch | undefined,\n babelrcRootsDirectory: string,\n): boolean {\n if (typeof babelrcRoots === \"boolean\") return babelrcRoots;\n\n const absoluteRoot = context.root;\n\n // Fast path to avoid having to match patterns if the babelrc is just\n // loading in the standard root directory.\n if (babelrcRoots === undefined) {\n return pkgData.directories.includes(absoluteRoot);\n }\n\n let babelrcPatterns = babelrcRoots;\n if (!Array.isArray(babelrcPatterns)) {\n babelrcPatterns = [babelrcPatterns as IgnoreItem];\n }\n babelrcPatterns = babelrcPatterns.map(pat => {\n return typeof pat === \"string\"\n ? path.resolve(babelrcRootsDirectory, pat)\n : pat;\n });\n\n // Fast path to avoid having to match patterns if the babelrc is just\n // loading in the standard root directory.\n if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) {\n return pkgData.directories.includes(absoluteRoot);\n }\n\n return babelrcPatterns.some(pat => {\n if (typeof pat === \"string\") {\n pat = pathPatternToRegex(pat, babelrcRootsDirectory);\n }\n\n return pkgData.directories.some(directory => {\n return matchPattern(pat, babelrcRootsDirectory, directory, context);\n });\n });\n}\n\nconst validateConfigFile = makeWeakCacheSync(\n (file: ConfigFile): ValidatedFile => ({\n filepath: file.filepath,\n dirname: file.dirname,\n options: validate(\"configfile\", file.options, file.filepath),\n }),\n);\n\nconst validateBabelrcFile = makeWeakCacheSync(\n (file: ConfigFile): ValidatedFile => ({\n filepath: file.filepath,\n dirname: file.dirname,\n options: validate(\"babelrcfile\", file.options, file.filepath),\n }),\n);\n\nconst validateExtendFile = makeWeakCacheSync(\n (file: ConfigFile): ValidatedFile => ({\n filepath: file.filepath,\n dirname: file.dirname,\n options: validate(\"extendsfile\", file.options, file.filepath),\n }),\n);\n\n/**\n * Build a config chain for just the programmatic options passed into Babel.\n */\nconst loadProgrammaticChain = makeChainWalker({\n root: input => buildRootDescriptors(input, \"base\", createCachedDescriptors),\n env: (input, envName) =>\n buildEnvDescriptors(input, \"base\", createCachedDescriptors, envName),\n overrides: (input, index) =>\n buildOverrideDescriptors(input, \"base\", createCachedDescriptors, index),\n overridesEnv: (input, index, envName) =>\n buildOverrideEnvDescriptors(\n input,\n \"base\",\n createCachedDescriptors,\n index,\n envName,\n ),\n createLogger: (input, context, baseLogger) =>\n buildProgrammaticLogger(input, context, baseLogger),\n});\n\n/**\n * Build a config chain for a given file.\n */\nconst loadFileChainWalker = makeChainWalker({\n root: file => loadFileDescriptors(file),\n env: (file, envName) => loadFileEnvDescriptors(file)(envName),\n overrides: (file, index) => loadFileOverridesDescriptors(file)(index),\n overridesEnv: (file, index, envName) =>\n loadFileOverridesEnvDescriptors(file)(index)(envName),\n createLogger: (file, context, baseLogger) =>\n buildFileLogger(file.filepath, context, baseLogger),\n});\n\nfunction* loadFileChain(\n input: ValidatedFile,\n context: ConfigContext,\n files: Set,\n baseLogger: ConfigPrinter,\n) {\n const chain = yield* loadFileChainWalker(input, context, files, baseLogger);\n chain?.files.add(input.filepath);\n\n return chain;\n}\n\nconst loadFileDescriptors = makeWeakCacheSync((file: ValidatedFile) =>\n buildRootDescriptors(file, file.filepath, createUncachedDescriptors),\n);\nconst loadFileEnvDescriptors = makeWeakCacheSync((file: ValidatedFile) =>\n makeStrongCacheSync((envName: string) =>\n buildEnvDescriptors(\n file,\n file.filepath,\n createUncachedDescriptors,\n envName,\n ),\n ),\n);\nconst loadFileOverridesDescriptors = makeWeakCacheSync((file: ValidatedFile) =>\n makeStrongCacheSync((index: number) =>\n buildOverrideDescriptors(\n file,\n file.filepath,\n createUncachedDescriptors,\n index,\n ),\n ),\n);\nconst loadFileOverridesEnvDescriptors = makeWeakCacheSync(\n (file: ValidatedFile) =>\n makeStrongCacheSync((index: number) =>\n makeStrongCacheSync((envName: string) =>\n buildOverrideEnvDescriptors(\n file,\n file.filepath,\n createUncachedDescriptors,\n index,\n envName,\n ),\n ),\n ),\n);\n\nfunction buildFileLogger(\n filepath: string,\n context: ConfigContext,\n baseLogger: ConfigPrinter | void,\n) {\n if (!baseLogger) {\n return () => {};\n }\n return baseLogger.configure(context.showConfig, ChainFormatter.Config, {\n filepath,\n });\n}\n\nfunction buildRootDescriptors(\n { dirname, options }: Partial,\n alias: string,\n descriptors: (\n dirname: string,\n options: ValidatedOptions,\n alias: string,\n ) => OptionsAndDescriptors,\n) {\n return descriptors(dirname, options, alias);\n}\n\nfunction buildProgrammaticLogger(\n _: unknown,\n context: ConfigContext,\n baseLogger: ConfigPrinter | void,\n) {\n if (!baseLogger) {\n return () => {};\n }\n return baseLogger.configure(context.showConfig, ChainFormatter.Programmatic, {\n callerName: context.caller?.name,\n });\n}\n\nfunction buildEnvDescriptors(\n { dirname, options }: Partial,\n alias: string,\n descriptors: (\n dirname: string,\n options: ValidatedOptions,\n alias: string,\n ) => OptionsAndDescriptors,\n envName: string,\n) {\n const opts = options.env?.[envName];\n return opts ? descriptors(dirname, opts, `${alias}.env[\"${envName}\"]`) : null;\n}\n\nfunction buildOverrideDescriptors(\n { dirname, options }: Partial,\n alias: string,\n descriptors: (\n dirname: string,\n options: ValidatedOptions,\n alias: string,\n ) => OptionsAndDescriptors,\n index: number,\n) {\n const opts = options.overrides?.[index];\n if (!opts) throw new Error(\"Assertion failure - missing override\");\n\n return descriptors(dirname, opts, `${alias}.overrides[${index}]`);\n}\n\nfunction buildOverrideEnvDescriptors(\n { dirname, options }: Partial,\n alias: string,\n descriptors: (\n dirname: string,\n options: ValidatedOptions,\n alias: string,\n ) => OptionsAndDescriptors,\n index: number,\n envName: string,\n) {\n const override = options.overrides?.[index];\n if (!override) throw new Error(\"Assertion failure - missing override\");\n\n const opts = override.env?.[envName];\n return opts\n ? descriptors(\n dirname,\n opts,\n `${alias}.overrides[${index}].env[\"${envName}\"]`,\n )\n : null;\n}\n\nfunction makeChainWalker<\n ArgT extends {\n options: ValidatedOptions;\n dirname: string;\n filepath?: string;\n },\n>({\n root,\n env,\n overrides,\n overridesEnv,\n createLogger,\n}: {\n root: (configEntry: ArgT) => OptionsAndDescriptors;\n env: (configEntry: ArgT, env: string) => OptionsAndDescriptors | null;\n overrides: (configEntry: ArgT, index: number) => OptionsAndDescriptors;\n overridesEnv: (\n configEntry: ArgT,\n index: number,\n env: string,\n ) => OptionsAndDescriptors | null;\n createLogger: (\n configEntry: ArgT,\n context: ConfigContext,\n printer: ConfigPrinter | void,\n ) => (\n opts: OptionsAndDescriptors,\n index?: number | null,\n env?: string | null,\n ) => void;\n}): (\n configEntry: ArgT,\n context: ConfigContext,\n files?: Set,\n baseLogger?: ConfigPrinter,\n) => Handler {\n return function* chainWalker(input, context, files = new Set(), baseLogger) {\n const { dirname } = input;\n\n const flattenedConfigs: Array<{\n config: OptionsAndDescriptors;\n index: number | undefined | null;\n envName: string | undefined | null;\n }> = [];\n\n const rootOpts = root(input);\n if (configIsApplicable(rootOpts, dirname, context, input.filepath)) {\n flattenedConfigs.push({\n config: rootOpts,\n envName: undefined,\n index: undefined,\n });\n\n const envOpts = env(input, context.envName);\n if (\n envOpts &&\n configIsApplicable(envOpts, dirname, context, input.filepath)\n ) {\n flattenedConfigs.push({\n config: envOpts,\n envName: context.envName,\n index: undefined,\n });\n }\n\n (rootOpts.options.overrides || []).forEach((_, index) => {\n const overrideOps = overrides(input, index);\n if (configIsApplicable(overrideOps, dirname, context, input.filepath)) {\n flattenedConfigs.push({\n config: overrideOps,\n index,\n envName: undefined,\n });\n\n const overrideEnvOpts = overridesEnv(input, index, context.envName);\n if (\n overrideEnvOpts &&\n configIsApplicable(\n overrideEnvOpts,\n dirname,\n context,\n input.filepath,\n )\n ) {\n flattenedConfigs.push({\n config: overrideEnvOpts,\n index,\n envName: context.envName,\n });\n }\n }\n });\n }\n\n // Process 'ignore' and 'only' before 'extends' items are processed so\n // that we don't do extra work loading extended configs if a file is\n // ignored.\n if (\n flattenedConfigs.some(\n ({\n config: {\n options: { ignore, only },\n },\n }) => shouldIgnore(context, ignore, only, dirname),\n )\n ) {\n return null;\n }\n\n const chain = emptyChain();\n const logger = createLogger(input, context, baseLogger);\n\n for (const { config, index, envName } of flattenedConfigs) {\n if (\n !(yield* mergeExtendsChain(\n chain,\n config.options,\n dirname,\n context,\n files,\n baseLogger,\n ))\n ) {\n return null;\n }\n\n logger(config, index, envName);\n yield* mergeChainOpts(chain, config);\n }\n return chain;\n };\n}\n\nfunction* mergeExtendsChain(\n chain: ConfigChain,\n opts: ValidatedOptions,\n dirname: string,\n context: ConfigContext,\n files: Set,\n baseLogger?: ConfigPrinter,\n): Handler {\n if (opts.extends === undefined) return true;\n\n const file = yield* loadConfig(\n opts.extends,\n dirname,\n context.envName,\n context.caller,\n );\n\n if (files.has(file)) {\n throw new Error(\n `Configuration cycle detected loading ${file.filepath}.\\n` +\n `File already loaded following the config chain:\\n` +\n Array.from(files, file => ` - ${file.filepath}`).join(\"\\n\"),\n );\n }\n\n files.add(file);\n const fileChain = yield* loadFileChain(\n validateExtendFile(file),\n context,\n files,\n baseLogger,\n );\n files.delete(file);\n\n if (!fileChain) return false;\n\n mergeChain(chain, fileChain);\n\n return true;\n}\n\nfunction mergeChain(target: ConfigChain, source: ConfigChain): ConfigChain {\n target.options.push(...source.options);\n target.plugins.push(...source.plugins);\n target.presets.push(...source.presets);\n for (const file of source.files) {\n target.files.add(file);\n }\n\n return target;\n}\n\nfunction* mergeChainOpts(\n target: ConfigChain,\n { options, plugins, presets }: OptionsAndDescriptors,\n): Handler {\n target.options.push(options);\n target.plugins.push(...(yield* plugins()));\n target.presets.push(...(yield* presets()));\n\n return target;\n}\n\nfunction emptyChain(): ConfigChain {\n return {\n options: [],\n presets: [],\n plugins: [],\n files: new Set(),\n };\n}\n\nfunction normalizeOptions(opts: ValidatedOptions): ValidatedOptions {\n const options = {\n ...opts,\n };\n delete options.extends;\n delete options.env;\n delete options.overrides;\n delete options.plugins;\n delete options.presets;\n delete options.passPerPreset;\n delete options.ignore;\n delete options.only;\n delete options.test;\n delete options.include;\n delete options.exclude;\n\n // \"sourceMap\" is just aliased to sourceMap, so copy it over as\n // we merge the options together.\n if (Object.hasOwn(options, \"sourceMap\")) {\n options.sourceMaps = options.sourceMap;\n delete options.sourceMap;\n }\n return options;\n}\n\nfunction dedupDescriptors(\n items: Array>,\n): Array> {\n const map: Map<\n Function,\n Map }>\n > = new Map();\n\n const descriptors = [];\n\n for (const item of items) {\n if (typeof item.value === \"function\") {\n const fnKey = item.value;\n let nameMap = map.get(fnKey);\n if (!nameMap) {\n nameMap = new Map();\n map.set(fnKey, nameMap);\n }\n let desc = nameMap.get(item.name);\n if (!desc) {\n desc = { value: item };\n descriptors.push(desc);\n\n // Treat passPerPreset presets as unique, skipping them\n // in the merge processing steps.\n if (!item.ownPass) nameMap.set(item.name, desc);\n } else {\n desc.value = item;\n }\n } else {\n descriptors.push({ value: item });\n }\n }\n\n return descriptors.reduce((acc, desc) => {\n acc.push(desc.value);\n return acc;\n }, []);\n}\n\nfunction configIsApplicable(\n { options }: OptionsAndDescriptors,\n dirname: string,\n context: ConfigContext,\n configName: string,\n): boolean {\n return (\n (options.test === undefined ||\n configFieldIsApplicable(context, options.test, dirname, configName)) &&\n (options.include === undefined ||\n configFieldIsApplicable(context, options.include, dirname, configName)) &&\n (options.exclude === undefined ||\n !configFieldIsApplicable(context, options.exclude, dirname, configName))\n );\n}\n\nfunction configFieldIsApplicable(\n context: ConfigContext,\n test: ConfigApplicableTest,\n dirname: string,\n configName: string,\n): boolean {\n const patterns = Array.isArray(test) ? test : [test];\n\n return matchesPatterns(context, patterns, dirname, configName);\n}\n\n/**\n * Print the ignoreList-values in a more helpful way than the default.\n */\nfunction ignoreListReplacer(\n _key: string,\n value: IgnoreList | IgnoreItem,\n): IgnoreList | IgnoreItem | string {\n if (value instanceof RegExp) {\n return String(value);\n }\n\n return value;\n}\n\n/**\n * Tests if a filename should be ignored based on \"ignore\" and \"only\" options.\n */\nfunction shouldIgnore(\n context: ConfigContext,\n ignore: IgnoreList | undefined | null,\n only: IgnoreList | undefined | null,\n dirname: string,\n): boolean {\n if (ignore && matchesPatterns(context, ignore, dirname)) {\n const message = `No config is applied to \"${\n context.filename ?? \"(unknown)\"\n }\" because it matches one of \\`ignore: ${JSON.stringify(\n ignore,\n ignoreListReplacer,\n )}\\` from \"${dirname}\"`;\n debug(message);\n if (context.showConfig) {\n console.log(message);\n }\n return true;\n }\n\n if (only && !matchesPatterns(context, only, dirname)) {\n const message = `No config is applied to \"${\n context.filename ?? \"(unknown)\"\n }\" because it fails to match one of \\`only: ${JSON.stringify(\n only,\n ignoreListReplacer,\n )}\\` from \"${dirname}\"`;\n debug(message);\n if (context.showConfig) {\n console.log(message);\n }\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns result of calling function with filename if pattern is a function.\n * Otherwise returns result of matching pattern Regex with filename.\n */\nfunction matchesPatterns(\n context: ConfigContext,\n patterns: IgnoreList,\n dirname: string,\n configName?: string,\n): boolean {\n return patterns.some(pattern =>\n matchPattern(pattern, dirname, context.filename, context, configName),\n );\n}\n\nfunction matchPattern(\n pattern: IgnoreItem,\n dirname: string,\n pathToTest: string | undefined,\n context: ConfigContext,\n configName?: string,\n): boolean {\n if (typeof pattern === \"function\") {\n return !!endHiddenCallStack(pattern)(pathToTest, {\n dirname,\n envName: context.envName,\n caller: context.caller,\n });\n }\n\n if (typeof pathToTest !== \"string\") {\n throw new ConfigError(\n `Configuration contains string/RegExp pattern, but no filename was passed to Babel`,\n configName,\n );\n }\n\n if (typeof pattern === \"string\") {\n pattern = pathPatternToRegex(pattern, dirname);\n }\n return pattern.test(pathToTest);\n}\n"],"mappings":"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","ignoreList":[]}
\ No newline at end of file
diff --git a/Issue4/node_modules/@babel/core/lib/config/config-descriptors.js b/Issue4/node_modules/@babel/core/lib/config/config-descriptors.js
new file mode 100755
index 0000000000000000000000000000000000000000..21fb4146b7f3dcb802756eaf3141d6e424e8a399
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/config-descriptors.js
@@ -0,0 +1,190 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.createCachedDescriptors = createCachedDescriptors;
+exports.createDescriptor = createDescriptor;
+exports.createUncachedDescriptors = createUncachedDescriptors;
+function _gensync() {
+ const data = require("gensync");
+ _gensync = function () {
+ return data;
+ };
+ return data;
+}
+var _functional = require("../gensync-utils/functional.js");
+var _index = require("./files/index.js");
+var _item = require("./item.js");
+var _caching = require("./caching.js");
+var _resolveTargets = require("./resolve-targets.js");
+function isEqualDescriptor(a, b) {
+ var _a$file, _b$file, _a$file2, _b$file2;
+ return a.name === b.name && a.value === b.value && a.options === b.options && a.dirname === b.dirname && a.alias === b.alias && a.ownPass === b.ownPass && ((_a$file = a.file) == null ? void 0 : _a$file.request) === ((_b$file = b.file) == null ? void 0 : _b$file.request) && ((_a$file2 = a.file) == null ? void 0 : _a$file2.resolved) === ((_b$file2 = b.file) == null ? void 0 : _b$file2.resolved);
+}
+function* handlerOf(value) {
+ return value;
+}
+function optionsWithResolvedBrowserslistConfigFile(options, dirname) {
+ if (typeof options.browserslistConfigFile === "string") {
+ options.browserslistConfigFile = (0, _resolveTargets.resolveBrowserslistConfigFile)(options.browserslistConfigFile, dirname);
+ }
+ return options;
+}
+function createCachedDescriptors(dirname, options, alias) {
+ const {
+ plugins,
+ presets,
+ passPerPreset
+ } = options;
+ return {
+ options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
+ plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => handlerOf([]),
+ presets: presets ? () => createCachedPresetDescriptors(presets, dirname)(alias)(!!passPerPreset) : () => handlerOf([])
+ };
+}
+function createUncachedDescriptors(dirname, options, alias) {
+ return {
+ options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
+ plugins: (0, _functional.once)(() => createPluginDescriptors(options.plugins || [], dirname, alias)),
+ presets: (0, _functional.once)(() => createPresetDescriptors(options.presets || [], dirname, alias, !!options.passPerPreset))
+ };
+}
+const PRESET_DESCRIPTOR_CACHE = new WeakMap();
+const createCachedPresetDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
+ const dirname = cache.using(dir => dir);
+ return (0, _caching.makeStrongCacheSync)(alias => (0, _caching.makeStrongCache)(function* (passPerPreset) {
+ const descriptors = yield* createPresetDescriptors(items, dirname, alias, passPerPreset);
+ return descriptors.map(desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc));
+ }));
+});
+const PLUGIN_DESCRIPTOR_CACHE = new WeakMap();
+const createCachedPluginDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
+ const dirname = cache.using(dir => dir);
+ return (0, _caching.makeStrongCache)(function* (alias) {
+ const descriptors = yield* createPluginDescriptors(items, dirname, alias);
+ return descriptors.map(desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc));
+ });
+});
+const DEFAULT_OPTIONS = {};
+function loadCachedDescriptor(cache, desc) {
+ const {
+ value,
+ options = DEFAULT_OPTIONS
+ } = desc;
+ if (options === false) return desc;
+ let cacheByOptions = cache.get(value);
+ if (!cacheByOptions) {
+ cacheByOptions = new WeakMap();
+ cache.set(value, cacheByOptions);
+ }
+ let possibilities = cacheByOptions.get(options);
+ if (!possibilities) {
+ possibilities = [];
+ cacheByOptions.set(options, possibilities);
+ }
+ if (!possibilities.includes(desc)) {
+ const matches = possibilities.filter(possibility => isEqualDescriptor(possibility, desc));
+ if (matches.length > 0) {
+ return matches[0];
+ }
+ possibilities.push(desc);
+ }
+ return desc;
+}
+function* createPresetDescriptors(items, dirname, alias, passPerPreset) {
+ return yield* createDescriptors("preset", items, dirname, alias, passPerPreset);
+}
+function* createPluginDescriptors(items, dirname, alias) {
+ return yield* createDescriptors("plugin", items, dirname, alias);
+}
+function* createDescriptors(type, items, dirname, alias, ownPass) {
+ const descriptors = yield* _gensync().all(items.map((item, index) => createDescriptor(item, dirname, {
+ type,
+ alias: `${alias}$${index}`,
+ ownPass: !!ownPass
+ })));
+ assertNoDuplicates(descriptors);
+ return descriptors;
+}
+function* createDescriptor(pair, dirname, {
+ type,
+ alias,
+ ownPass
+}) {
+ const desc = (0, _item.getItemDescriptor)(pair);
+ if (desc) {
+ return desc;
+ }
+ let name;
+ let options;
+ let value = pair;
+ if (Array.isArray(value)) {
+ if (value.length === 3) {
+ [value, options, name] = value;
+ } else {
+ [value, options] = value;
+ }
+ }
+ let file = undefined;
+ let filepath = null;
+ if (typeof value === "string") {
+ if (typeof type !== "string") {
+ throw new Error("To resolve a string-based item, the type of item must be given");
+ }
+ const resolver = type === "plugin" ? _index.loadPlugin : _index.loadPreset;
+ const request = value;
+ ({
+ filepath,
+ value
+ } = yield* resolver(value, dirname));
+ file = {
+ request,
+ resolved: filepath
+ };
+ }
+ if (!value) {
+ throw new Error(`Unexpected falsy value: ${String(value)}`);
+ }
+ if (typeof value === "object" && value.__esModule) {
+ if (value.default) {
+ value = value.default;
+ } else {
+ throw new Error("Must export a default export when using ES6 modules.");
+ }
+ }
+ if (typeof value !== "object" && typeof value !== "function") {
+ throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`);
+ }
+ if (filepath !== null && typeof value === "object" && value) {
+ throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`);
+ }
+ return {
+ name,
+ alias: filepath || alias,
+ value,
+ options,
+ dirname,
+ ownPass,
+ file
+ };
+}
+function assertNoDuplicates(items) {
+ const map = new Map();
+ for (const item of items) {
+ if (typeof item.value !== "function") continue;
+ let nameMap = map.get(item.value);
+ if (!nameMap) {
+ nameMap = new Set();
+ map.set(item.value, nameMap);
+ }
+ if (nameMap.has(item.name)) {
+ const conflicts = items.filter(i => i.value === item.value);
+ throw new Error([`Duplicate plugin/preset detected.`, `If you'd like to use two separate instances of a plugin,`, `they need separate names, e.g.`, ``, ` plugins: [`, ` ['some-plugin', {}],`, ` ['some-plugin', {}, 'some unique name'],`, ` ]`, ``, `Duplicates detected are:`, `${JSON.stringify(conflicts, null, 2)}`].join("\n"));
+ }
+ nameMap.add(item.name);
+ }
+}
+0 && 0;
+
+//# sourceMappingURL=config-descriptors.js.map
diff --git a/Issue4/node_modules/@babel/core/lib/config/config-descriptors.js.map b/Issue4/node_modules/@babel/core/lib/config/config-descriptors.js.map
new file mode 100755
index 0000000000000000000000000000000000000000..cddcbd8164962fe1f49541200861691dc9e00114
--- /dev/null
+++ b/Issue4/node_modules/@babel/core/lib/config/config-descriptors.js.map
@@ -0,0 +1 @@
+{"version":3,"names":["_gensync","data","require","_functional","_index","_item","_caching","_resolveTargets","isEqualDescriptor","a","b","_a$file","_b$file","_a$file2","_b$file2","name","value","options","dirname","alias","ownPass","file","request","resolved","handlerOf","optionsWithResolvedBrowserslistConfigFile","browserslistConfigFile","resolveBrowserslistConfigFile","createCachedDescriptors","plugins","presets","passPerPreset","createCachedPluginDescriptors","createCachedPresetDescriptors","createUncachedDescriptors","once","createPluginDescriptors","createPresetDescriptors","PRESET_DESCRIPTOR_CACHE","WeakMap","makeWeakCacheSync","items","cache","using","dir","makeStrongCacheSync","makeStrongCache","descriptors","map","desc","loadCachedDescriptor","PLUGIN_DESCRIPTOR_CACHE","DEFAULT_OPTIONS","cacheByOptions","get","set","possibilities","includes","matches","filter","possibility","length","push","createDescriptors","type","gensync","all","item","index","createDescriptor","assertNoDuplicates","pair","getItemDescriptor","Array","isArray","undefined","filepath","Error","resolver","loadPlugin","loadPreset","String","__esModule","default","Map","nameMap","Set","has","conflicts","i","JSON","stringify","join","add"],"sources":["../../src/config/config-descriptors.ts"],"sourcesContent":["import gensync, { type Handler } from \"gensync\";\nimport { once } from \"../gensync-utils/functional.ts\";\n\nimport { loadPlugin, loadPreset } from \"./files/index.ts\";\n\nimport { getItemDescriptor } from \"./item.ts\";\n\nimport {\n makeWeakCacheSync,\n makeStrongCacheSync,\n makeStrongCache,\n} from \"./caching.ts\";\nimport type { CacheConfigurator } from \"./caching.ts\";\n\nimport type {\n ValidatedOptions,\n PluginList,\n PluginItem,\n} from \"./validation/options.ts\";\n\nimport { resolveBrowserslistConfigFile } from \"./resolve-targets.ts\";\nimport type { PluginAPI, PresetAPI } from \"./helpers/config-api.ts\";\n\n// Represents a config object and functions to lazily load the descriptors\n// for the plugins and presets so we don't load the plugins/presets unless\n// the options object actually ends up being applicable.\nexport type OptionsAndDescriptors = {\n options: ValidatedOptions;\n plugins: () => Handler>>;\n presets: () => Handler>>;\n};\n\n// Represents a plugin or presets at a given location in a config object.\n// At this point these have been resolved to a specific object or function,\n// but have not yet been executed to call functions with options.\nexport interface UnloadedDescriptor {\n name: string | undefined;\n value: object | ((api: API, options: Options, dirname: string) => unknown);\n options: Options;\n dirname: string;\n alias: string;\n ownPass?: boolean;\n file?: {\n request: string;\n resolved: string;\n };\n}\n\nfunction isEqualDescriptor(\n a: UnloadedDescriptor,\n b: UnloadedDescriptor,\n): boolean {\n return (\n a.name === b.name &&\n a.value === b.value &&\n a.options === b.options &&\n a.dirname === b.dirname &&\n a.alias === b.alias &&\n a.ownPass === b.ownPass &&\n a.file?.request === b.file?.request &&\n a.file?.resolved === b.file?.resolved\n );\n}\n\nexport type ValidatedFile = {\n filepath: string;\n dirname: string;\n options: ValidatedOptions;\n};\n\n// eslint-disable-next-line require-yield\nfunction* handlerOf(value: T): Handler {\n return value;\n}\n\nfunction optionsWithResolvedBrowserslistConfigFile(\n options: ValidatedOptions,\n dirname: string,\n): ValidatedOptions {\n if (typeof options.browserslistConfigFile === \"string\") {\n options.browserslistConfigFile = resolveBrowserslistConfigFile(\n options.browserslistConfigFile,\n dirname,\n );\n }\n return options;\n}\n\n/**\n * Create a set of descriptors from a given options object, preserving\n * descriptor identity based on the identity of the plugin/preset arrays\n * themselves, and potentially on the identity of the plugins/presets + options.\n */\nexport function createCachedDescriptors(\n dirname: string,\n options: ValidatedOptions,\n alias: string,\n): OptionsAndDescriptors {\n const { plugins, presets, passPerPreset } = options;\n return {\n options: optionsWithResolvedBrowserslistConfigFile(options, dirname),\n plugins: plugins\n ? () =>\n // @ts-expect-error todo(flow->ts) ts complains about incorrect arguments\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n createCachedPluginDescriptors(plugins, dirname)(alias)\n : () => handlerOf([]),\n presets: presets\n ? () =>\n // @ts-expect-error todo(flow->ts) ts complains about incorrect arguments\n // eslint-disable-next-line @typescript-eslint/no-use-before-define\n createCachedPresetDescriptors(presets, dirname)(alias)(\n !!passPerPreset,\n )\n : () => handlerOf([]),\n };\n}\n\n/**\n * Create a set of descriptors from a given options object, with consistent\n * identity for the descriptors, but not caching based on any specific identity.\n */\nexport function createUncachedDescriptors(\n dirname: string,\n options: ValidatedOptions,\n alias: string,\n): OptionsAndDescriptors {\n return {\n options: optionsWithResolvedBrowserslistConfigFile(options, dirname),\n // The returned result here is cached to represent a config object in\n // memory, so we build and memoize the descriptors to ensure the same\n // values are returned consistently.\n plugins: once(() =>\n createPluginDescriptors(options.plugins || [], dirname, alias),\n ),\n presets: once(() =>\n createPresetDescriptors(\n options.presets || [],\n dirname,\n alias,\n !!options.passPerPreset,\n ),\n ),\n };\n}\n\nconst PRESET_DESCRIPTOR_CACHE = new WeakMap();\nconst createCachedPresetDescriptors = makeWeakCacheSync(\n (items: PluginList, cache: CacheConfigurator) => {\n const dirname = cache.using(dir => dir);\n return makeStrongCacheSync((alias: string) =>\n makeStrongCache(function* (\n passPerPreset: boolean,\n ): Handler>> {\n const descriptors = yield* createPresetDescriptors(\n items,\n dirname,\n alias,\n passPerPreset,\n );\n return descriptors.map(\n // Items are cached using the overall preset array identity when\n // possibly, but individual descriptors are also cached if a match\n // can be found in the previously-used descriptor lists.\n desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc),\n );\n }),\n );\n },\n);\n\nconst PLUGIN_DESCRIPTOR_CACHE = new WeakMap();\nconst createCachedPluginDescriptors = makeWeakCacheSync(\n (items: PluginList, cache: CacheConfigurator) => {\n const dirname = cache.using(dir => dir);\n return makeStrongCache(function* (\n alias: string,\n ): Handler>> {\n const descriptors = yield* createPluginDescriptors(items, dirname, alias);\n return descriptors.map(\n // Items are cached using the overall plugin array identity when\n // possibly, but individual descriptors are also cached if a match\n // can be found in the previously-used descriptor lists.\n desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc),\n );\n });\n },\n);\n\n/**\n * When no options object is given in a descriptor, this object is used\n * as a WeakMap key in order to have consistent identity.\n */\nconst DEFAULT_OPTIONS = {};\n\n/**\n * Given the cache and a descriptor, returns a matching descriptor from the\n * cache, or else returns the input descriptor and adds it to the cache for\n * next time.\n */\nfunction loadCachedDescriptor(\n cache: WeakMap<\n object | Function,\n WeakMap