private/Invoke-WpcPreProcessString.ps1

function Invoke-WpcPreProcessString {
    param(
        [string] $str,
        [System.Collections.IDictionary] $baseVars,
        [string] $repoRoot,
        [string] $sourceDir
    )

    $includeMatch = $WPC_INCLUDE_PATTERN.Match($str)
    if ($includeMatch.Success) {
        $rawArgs  = $includeMatch.Groups[1].Value
        $allArgs  = @(Split-WpcArgs -argsStr $rawArgs)

        if ($allArgs.Count -eq 0) {
            throw "include() requires at least a path argument."
        }

        $partialPath = Resolve-JaxRepoRootedPath -Path $allArgs[0] -RepoRoot $repoRoot -WorkingDir $sourceDir
        $partial     = Read-JaxYaml -Path $partialPath
        $kvArgs      = if ($allArgs.Count -gt 1) { $allArgs[1..($allArgs.Count - 1)] } else { @() }
        $localScope  = Build-IncludeScope -kvArgs $kvArgs -baseVars $baseVars

        $expanded = Expand-Placeholders -ht $partial -override $localScope -ignoreMissingPlaceholders -warningsAsVerbose
        return $expanded
    }

    $yamlFileMatch = $WPC_YAMLFILE_PATTERN.Match($str)
    if ($yamlFileMatch.Success) {
        $rawArgs  = $yamlFileMatch.Groups[1].Value
        $pipeline = $yamlFileMatch.Groups[2].Value
        $allArgs  = @(Split-WpcArgs -argsStr $rawArgs)

        if ($allArgs.Count -eq 0) {
            throw "yamlFile() requires at least a path argument."
        }

        $filePath  = $allArgs[0]
        $dottedKey = if ($allArgs.Count -gt 1) { $allArgs[1] } else { "" }

        $resolved  = Resolve-JaxRepoRootedPath -Path $filePath -RepoRoot $repoRoot -WorkingDir $sourceDir
        $yaml      = Read-JaxYaml -Path $resolved

        $value = if ([string]::IsNullOrWhiteSpace($dottedKey)) {
            $yaml
        } else {
            Get-PathFromHashtable -ht $yaml -path $dottedKey
        }

        if (-not [string]::IsNullOrWhiteSpace($pipeline)) {
            $value = Invoke-WpcPipeline -value $value -pipeline $pipeline
        }

        return $value
    }

    return $str
}