@@ -4937,6 +4937,212 @@ if (($this.'.Duration' -is [TimeSpan]) -and $this.PathAnimation) {
49374937}
49384938 </SetScriptBlock >
49394939 </ScriptProperty >
4940+ <ScriptProperty >
4941+ <Name >Element</Name >
4942+ <GetScriptBlock >
4943+ < #
4944+ .SYNOPSIS
4945+ Gets a Turtle as an Element
4946+ .DESCRIPTION
4947+ We can treat any Turtle as any arbitrary markup element.
4948+
4949+ To do this, all we need to do is set an element name, and, optionally, add some attributes or children.
4950+ .EXAMPLE
4951+ # Any bareword can become the name of an element, as long as it is not a method name
4952+ turtle element div element
4953+ .EXAMPLE
4954+ # We can provide anything that will cast to XML as an element
4955+ turtle element '< div/> ' element
4956+ .EXAMPLE
4957+ # We can provide an element and attributes
4958+ turtle element '< div class='myClass' /> ' element
4959+ .EXAMPLE
4960+ # We can put a turtle inside of an aribtrary element
4961+ turtle SpiderWeb element '< div /> '
4962+ #>
4963+
4964+ # If we have set an element name
4965+ if ($this.'.Element'.ElementName) {
4966+
4967+ # make this little filter to recursively turn the element back into XML
4968+ filter toElement {
4969+ $in = $_
4970+ # If the input was a dictionary with an element name
4971+ if ($in -is [Collections.IDictionary] -and $in.ElementName) {
4972+ # start the markup
4973+ "< $($in.ElementName)$(
4974+ # and pop in any element attributes
4975+ foreach ($attributeCollection in 'attr','attribute','attributes') {
4976+ if (-not $in.$attributeCollection) { continue }
4977+ if ($in.$attributeCollection -is [Collections.IDictionary]) {
4978+ foreach ($attributeName in $in.$attributeCollection.Keys) {
4979+ if ($attributeName -match '/') { continue }
4980+ ' ', $attributeName,"='",$in.$attributeCollection[$attributeName],"'" -join ''
4981+ }
4982+ } elseif ($in.$attributeCollection -is [string]) {
4983+ $in.$attributeCollection
4984+ }
4985+ break
4986+ }
4987+ )> $(
4988+ # Now include any child elements
4989+ if ($this.Steps -or $this.Text) {
4990+ $this.SVG.OuterXml
4991+ }
4992+ @(foreach ($childCollection in 'child','ChildNodes','Children','Content') {
4993+ if (-not $in.$childCollection) {
4994+ continue
4995+ }
4996+ foreach ($child in $in.$childCollection) {
4997+ # strings are directly included
4998+ if ($child -is [string]) {
4999+ $child
5000+ } elseif ($child -is [xml] -or $child -is [xml.xmlElement]) {
5001+ # xml elements will embed themselves
5002+ $child.OuterXml
5003+ } elseif ($child -is [Collections.IDictionary] -and $child.ElementName) {
5004+ # and dictionaries with an element name will recurisvely call ourselves.
5005+ $child | & $MyInvocation.MyCommand.ScriptBlock
5006+ } else {
5007+ # Any other input will be stringified
5008+ "$child"
5009+ }
5010+ }
5011+ break
5012+ }) -join ([Environment]::NewLine)
5013+ )< /$($in.ElementName)> "
5014+ }
5015+ if ($_ -is [string]) {
5016+ $_
5017+ }
5018+ }
5019+
5020+ $elementMarkup = $this.'.Element' | toElement
5021+ $elementXml = $elementMarkup -as [xml]
5022+ if ($elementXml) {
5023+ $elementXml
5024+ } else {
5025+ $elementMarkup
5026+ }
5027+ return
5028+ }
5029+ else {
5030+ return $this.SVG
5031+ }
5032+
5033+ return
5034+
5035+ </GetScriptBlock >
5036+ <SetScriptBlock >
5037+ < #
5038+ .SYNOPSIS
5039+ Sets the Turtle element
5040+ .DESCRIPTION
5041+ Sets the Turtle to an arbitrary element.
5042+
5043+ This lets us write web pages and xml entirely in turtle.
5044+ .EXAMPLE
5045+ # Any bareword can become the name of an element, as long as it is not a method name
5046+ turtle element div element
5047+ .EXAMPLE
5048+ # We can provide anything that will cast to XML as an element
5049+ turtle element '< div/> ' element
5050+ .EXAMPLE
5051+ # We can provide an element and attributes
5052+ turtle element '< div class='myClass' /> ' element
5053+ .EXAMPLE
5054+ # We can put a turtle inside of an aribtrary element
5055+ turtle SpiderWeb element '< div /> '
5056+ #>
5057+
5058+ param()
5059+
5060+ if (-not $this.'.Element') {
5061+ $this | Add-Member NoteProperty '.Element' -Value ([Ordered]@{
5062+ ElementName=''
5063+ Attribute=$this.Attribute
5064+ Children=@()
5065+ })
5066+ }
5067+
5068+ $unrolledArgs = $args |. {process { $_ }}
5069+
5070+ foreach ($element in $unrolledArgs){
5071+ if ($element -is [string] -and
5072+ (-not ($element -as [xml])) -and
5073+ $element -notmatch '\s'
5074+ ) {
5075+ $this.'.Element'.ElementName = $Element
5076+ continue
5077+ }
5078+
5079+ if ($element -is [xml] -or $Element -as [xml]) {
5080+ if ($Element -isnot [xml]) {
5081+ $element = $Element -as [xml]
5082+ }
5083+ $this.'.Element'.ElementName = $Element.ChildNodes[0].LocalName
5084+ foreach ($attribute in $element.ChildNodes[0].Attributes) {
5085+ $this.'.Element'.Attribute[$attribute.Name] = $attribute.Value
5086+ }
5087+ foreach ($grandchild in $element.ChildNodes[0].ChildNodes) {
5088+ $this.'.Element'.Children += $grandchild
5089+ }
5090+ continue
5091+ }
5092+
5093+ if ($element -is [Collections.IDictionary]) {
5094+ $elementKeys = 'ElementName','Name','E'
5095+ foreach ($potentialName in $elementKeys) {
5096+ if ($element.$potentialName) {
5097+ $this.'.Element'.ElementName = $element.$potentialName
5098+ break
5099+ }
5100+ }
5101+ $attributeKeys = 'Attribute', 'Attributes', 'A'
5102+ foreach ($potentialAttributeName in $attributeKeys) {
5103+ if ($element.$potentialAttributeName -is [Collections.IDictionary] -and
5104+ $element.$potentialAttributeName.Count) {
5105+ foreach ($attributeName in $element.$potentialAttributeName.Keys) {
5106+ $this.'.Element'.Attribute[$attributeName] = $element.$potentialAttributeName[$attributeName]
5107+ }
5108+ break
5109+ }
5110+ }
5111+ $childKeys = 'Child', 'Children', 'ChildNodes','Content', 'C'
5112+
5113+ foreach ($potentialChildrenName in $childKeys) {
5114+ $children = $element.$potentialChildrenName
5115+ if (-not $children) { continue }
5116+ $this.'.Element'.Children += $children
5117+ break
5118+ }
5119+
5120+ $specialKeys = @(
5121+ $elementKeys
5122+ $attributeKeys
5123+ $childKeys
5124+ )
5125+
5126+ foreach ($elementKey in $element.Keys) {
5127+ if ($elementKey -in $specialKeys) { continue }
5128+ $elementValue = $element[$elementKey]
5129+ if ($elementValue -is [ValueType] -or (
5130+ $elementValue -is [string] -and $elementValue -notmatch '[\r\n]'
5131+ )) {
5132+ $this.'.Element'.Attribute[$elementKey] = $elementValue
5133+ }
5134+ }
5135+ continue
5136+ }
5137+
5138+ if ($elementName) {
5139+
5140+ }
5141+ }
5142+
5143+
5144+ </SetScriptBlock >
5145+ </ScriptProperty >
49405146 <ScriptProperty >
49415147 <Name >Fill</Name >
49425148 <GetScriptBlock >
0 commit comments