Powershell text / html templates containing loops

I know how to do a string replacement inside a text template, something simple like

text file

Hello ${name}

      

gorgeous

[string] $name = "World"
$template = Get-Content 'c:\temp\docs\template.txt'
$expanded = $ExecutionContext.InvokeCommand.ExpandString($template)
$expanded

      

Expected Result

Hello World

      


That's all well and good, but what if I need something more advanced?

text file

<div>title</div>
<ul>
    $(${points} | % { $_ })
</ul>

      

gorgeous

[string[]]$points = "First Point", "Second Point"
$template = Get-Content 'c:\temp\docs\template.txt' -force
$expanded = Invoke-Expression $template
$expanded

      

Expected Result

<div>title<div>
<ul>
    <li>First Point</li>
    <li>Second Point</li>
</ul>

      

What do I need to do to create loop templates inside a text file?


EDIT:

here the concept I will go over is about template.

<div class="container-fluid">
    <div class="page-header">
        <h1>${name}</h1>
        <p class="lead">${synopsis}</p>
    </div>
    <div class="row">
        <div class="col-md-12">
            <h2> Syntax </h2>
        </div>
        <pre>
<code>${syntax}</code>
        </pre>
    </div>
    <div class="col-md-12">
        <h2> Detailed Description </h2>
        <div>${description}</div>
    </div>
    {ifdef links}
    <div class="col-md-12">
        <h2> Related Commands </h2>
        <div>${links}</div>
    </div>
    {endif links}
    {ifdef parameters}
    <div class="col-md-12">
        <h2> Parameters </h2>
        <table>
            <tr>
                <th>Name</th>
                <th>Description</th>
                <th>Required?</th>
                <th>Pipeline Input</th>
                <th>Default Value</th>
            </tr>
            <tr>
                {foreach param in ${parameters}}
                <td>$($param.Name)</td>
                <td>$($param.Description)</td>
                <td>$(param.Required)</td>
                <td>$(param.PipelineInput)</td>
                <td>$(param.DefaultValue)</td>
                {endforeach}
            </tr>
        </table>
    </div>
    {endif parameters}
    {ifdef notes}
    <div class="col-md-12">
        <h2> Notes </h2>
        <div>${notes}</div>
    </div>
    {endif notes}
    {ifdef examples}
    <div class="col-md-12">
        <h2> Examples </h2>
        {foreach example in ${examples}}
        <h3> Example </h3>
        <pre>${example.code}</pre>
        <div>${example.remarks}</div>
        {endforeach}
    </div>
</div>

      

+3


source to share


1 answer


I'm really interested in a good answer to this, but I'll continue my suggestion in a comment. I'm sure you are capable of doing this yourself, but it might be helpful for someone.

If your file contains

<div>title</div>
<ul>
${list}
</ul>

      

Then we could do this to fill the list

$list = ("First Point", "Second Point" | ForEach-Object{"`t<li>$_</li>"}) -join "`r`n"
$template = Get-Content 'c:\temp\docs\template.txt' -raw
$ExecutionContext.InvokeCommand.ExpandString($template)

      

Yes, I know this is not exactly what you are asking, but it has a similar result.

Why don't you turn the whole file into code?

Disclaimer: I would like to point out that expanding strings and executing code from files are two different things. What if someone puts malicious code in your template file? You can blindly execute it. A realistic problem? Not. A possible disaster? May be.



I am updating a small part of your sample to validate the method. Yes, HTML is incorrect and sucks. It exists to show what I mean.

Sample file

'<div class="container-fluid">'
'    <div class="page-header">'
"        <h1>$name</h1>"
"        <p class=`"lead`">$synopsis</p>"
'    </div>'
'    <tr>'
foreach($param in $parameters){
"        <td>$($param.Name)</td>"
"        <td>$($param.Description)</td>"
}
'    </tr>'

      

I chose this snippet because you see a simple variable, a simple quoted variable, and a loop structure. I have single quotes on most of the strings, since they will just be sent as the standard output of the string. Thus, we use the following code:

$name = "Matt"
$synopsis ="Ughhh... stuff"
$parameters = 1,2 | Foreach-object{[pscustomobject]@{Name="$_ Factory";Description="$_ Apples"}}

$template = Get-Content 'c:\temp\docs\template.txt' -raw
Invoke-Expression $template

      

That the grid is the next, again terrible, conclusion.

<div class="container-fluid">
    <div class="page-header">
        <h1>Matt</h1>
        <p class="lead">Ughhh... stuff</p>
    </div>
    <tr>
        <td>1 Factory</td>
        <td>1 Apples</td>
        <td>2 Factory</td>
        <td>2 Apples</td>
    </tr>

      

+1


source







All Articles