Can you help me add the element-in-element selection?

style.xcss:
@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;700&display=swap');

@function dark-mode($font) {
  background-color: #000;
  color: #fff;
  font-family: $font, sans-serif;
}

body {
  @include dark-mode('Ubuntu');
}

h1 {
  color: blue;

  span {
    color: #000;
  }

  &:hover {
    color: red;
  }
}

---

Output (style.css):
@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;700&display=swap');
body {
  background-color: #000;
  color: #fff;
  font-family: 'Ubuntu', sans-serif;
}
h1 {
  color: blue;
}
h1:hover {
  color: red;
}

How it should be (style.css):
@import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;700&display=swap');
body {
  background-color: #000;
  color: #fff;
  font-family: 'Ubuntu', sans-serif;
}
h1 {
  color: blue;
}
h1 span {
  color: #000;
}
h1:hover {
  color: red;
}

---

xcss.ts:
import fs from 'fs';

class XCSS {
    static compile(code: string): string {
        // Stores function definitions
        const functions: Record<string, { params: string[], body: string[] }> = {};

        // Split the code into lines for processing
        const lines = code.split(/\r?\n/);

        // Root block to hold all top-level CSS
        const rootBlock: { selector: string, declarations: string[], children: any[] } = { selector: '', declarations: [], children: [] };
        let currentBlock = rootBlock;

        // Stack to keep track of nested blocks
        const blockStack = [rootBlock];

        // Flags for parsing functions
        let inFunction = false;
        let currentFunctionName = '';
        let currentFunctionParams: string[] = [];
        let currentFunctionBody: string[] = [];

        function escapeRegExp(string: string): string {
            return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
        }

        for (let line of lines) {
            line = line.trim();

            if (line === '') {
                continue; // Skip empty lines
            }

            if (line.startsWith('@import')) {
                // Handle @import directives
                if (!line.endsWith(';')) {
                    currentBlock.declarations.push(line + ';');
                } else {
                    currentBlock.declarations.push(line);
                }
            } else if (line.startsWith('@function')) {
                // Start of a function definition
                const funcMatch = line.match(/@function\s+([^(]+)\(([^)]*)\)\s*{/);
                if (funcMatch) {
                    inFunction = true;
                    currentFunctionName = funcMatch[1].trim();
                    currentFunctionParams = funcMatch[2].split(',').map(p => p.trim());
                    currentFunctionBody = [];
                }
            } else if (inFunction) {
                if (line === '}') {
                    // End of function definition, store it
                    functions[currentFunctionName] = {
                        params: currentFunctionParams,
                        body: currentFunctionBody,
                    };
                    inFunction = false;
                    currentFunctionName = '';
                    currentFunctionParams = [];
                    currentFunctionBody = [];
                } else {
                    // Accumulate function body lines
                    currentFunctionBody.push(line);
                }
            } else if (line.startsWith('@include')) {
                // Handle @include directives
                const includeMatch = line.match(/@include\s+([^(]+)\(([^)]*)\);?/);
                if (includeMatch) {
                    const includeName = includeMatch[1].trim();
                    const includeArgs = includeMatch[2].split(',').map(a => a.trim());

                    const func = functions[includeName];
                    if (func) {
                        const paramValues: Record<string, string> = {};
                        func.params.forEach((param, index) => {
                            paramValues[param] = includeArgs[index] || '';
                        });

                        // Replace variables in the function body and add to current block
                        for (let funcLine of func.body) {
                            let processedLine = funcLine;
                            for (const [param, value] of Object.entries(paramValues)) {
                                const regex = new RegExp(escapeRegExp(param), 'g');
                                processedLine = processedLine.replace(regex, value);
                            }

                            currentBlock.declarations.push(processedLine);
                        }
                    } else {
                        console.error(`Function ${includeName} not defined.`);
                    }
                }
            } else if (line.endsWith('{')) {
                // Start of a new block
                const selector = line.slice(0, -1).trim();
                const newBlock: { selector: string, declarations: string[], children: any[] } = { selector, declarations: [], children: [] };
                currentBlock.children.push(newBlock);
                blockStack.push(newBlock);
                currentBlock = newBlock;
            } else if (line === '}') {
                // End of the current block
                blockStack.pop();
                currentBlock = blockStack[blockStack.length - 1];

            } else {
                // Add declarations to the current block
                currentBlock.declarations.push(line);
            }
        }

        // Generate the final CSS from the block tree
        const outputLines: string[] = [];

        function generateCSS(
            block: { selector: string; declarations: string[]; children: any[] },
            parentSelectors: string[] = []
        ): void {
            let currentSelectors: string[] = [];

            if (block.selector) {
                // Process selectors
                const selectorParts = block.selector.split(',').map((s) => s.trim());
                const parents = parentSelectors.length ? parentSelectors : [''];
                for (const parentSelector of parents) {
                    for (const part of selectorParts) {
                        if (part.includes('&')) {
                            currentSelectors.push(part.replace(/&/g, parentSelector).trim());
                        } else {
                            const combined = (parentSelector + ' ' + part).trim();
                            currentSelectors.push(combined);
                        }
                    }
                }
            } else if (parentSelectors.length > 0) {
                // No selector but have parent selectors
                currentSelectors = parentSelectors.slice();
            } else {
                // Top-level declarations without selectors
                currentSelectors = [];
            }

            if (block.declarations.length > 0) {
                if (currentSelectors.length > 0) {
                    // Output selectors with declarations
                    for (const selector of currentSelectors) {
                        outputLines.push(`${selector} {`);
                        outputLines.push(...block.declarations.map((decl) => '  ' + decl));
                        outputLines.push('}');
                    }
                } else {
                    // Output top-level declarations directly
                    outputLines.push(...block.declarations);
                }
            }

            // Process children blocks recursively
            for (const child of block.children) {
                generateCSS(child, currentSelectors);
            }
        }

        generateCSS(rootBlock);

        // Combine the output lines into a single string
        return outputLines.join('\n');
    }

    static loadFromFile(file: string): Promise<string> {
        if (!file.endsWith('.xcss')) {
            throw new Error('File must have a .xcss extension');
        }
        if (!fs.existsSync(file)) {
            throw new Error(`File '${file}' does not exist`);
        }

        return new Promise((resolve, reject) => {
            fs.readFile(file, 'utf8', (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    const cssOutput = XCSS.compile(data);
                    resolve(cssOutput);
                }
            });
        });
    }

    static async saveToFile(inputFile: string, outputFile: string): Promise<void> {
        // Validate file extensions
        if (!inputFile.endsWith('.xcss')) {
            throw new Error('Input file must have a .xcss extension');
        }
        if (!outputFile.endsWith('.css')) {
            throw new Error('Output file must have a .css extension');
        }
        // Check if the input file exists
        if (!fs.existsSync(inputFile)) {
            throw new Error(`Input file '${inputFile}' does not exist`);
        }
        try {
            // Read and compile the input file
            const cssOutput = await XCSS.loadFromFile(inputFile);
            // Write the compiled CSS to the output file
            fs.writeFileSync(outputFile, cssOutput);
        } catch (err: unknown) {
            if (err instanceof Error) {
                throw new Error(`Error processing files: ${err.message}`);
            } else {
                throw new Error('An unknown error occurred while processing files');
            }
        }
    }
}

export = XCSS;

index.js:
const XCSS = require('./xcss');

XCSS.saveToFile('style.xcss', 'style.css');