@@ -7134,6 +7134,68 @@ if (-not $this.'.style') {
71347134 $this | Add-Member NoteProperty '.style' @() -Force
71357135}
71367136
7137+ $keyframe = $this.Keyframe
7138+ $myVariables = $this.Variable
7139+ $cssTypePattern = '^(?< type> \< [\w-].+?\> )[\:\=]?'
7140+ $myCssVariables = foreach ($variableKey in $myVariables.Keys -match '^--') {
7141+ $variableValue = $myVariables[$variableKey]
7142+ if ($variableValue -match $cssTypePattern) {
7143+ $variableValue = $variableValue -replace $cssTypePattern
7144+ "@property $variableKey { syntax: '$(
7145+ [Security.SecurityElement]::Escape($matches.type)
7146+ )'; initial-value: $($variableValue -replace $cssTypePattern)}"
7147+ }
7148+ "$variableKey",':', $variableValue -join ''
7149+ }
7150+ $styleElementParts = @(
7151+ if ($myCssVariables) {
7152+ "#$($this.id)-path, #$($this.id)-text {"
7153+ ($myCssVariables -join (';' + [Environment]::NewLine + (' ' * 4)))
7154+ "}"
7155+ }
7156+ foreach ($keyframeName in $keyframe.Keys) {
7157+ $keyframeKeyframes = $keyframe[$keyframeName]
7158+ "@keyframes $keyframeName {"
7159+ foreach ($percent in $keyframeKeyframes.Keys) {
7160+ " $percent {"
7161+ $props = $keyframeKeyframes[$percent]
7162+ foreach ($prop in $props.Keys) {
7163+ $value = $props.$prop
7164+ " ${prop}: $value;"
7165+ }
7166+ " }"
7167+ }
7168+ "}"
7169+ ".$keyframeName {"
7170+ " animation-name: $keyframeName;"
7171+ " animation-duration: $($this.Duration.TotalSeconds)s;"
7172+ " animation-iteration-count: infinite;"
7173+ "}"
7174+ }
7175+ if ($this.'.Style') {
7176+ "$($this.'.Style' -join (';' + [Environment]::NewLine))"
7177+ }
7178+ )
7179+
7180+ if ($styleElementParts) {
7181+ # Style elements are one of the only places where we can be reasonably certain there will not be child elements
7182+ try {
7183+ # so if we have an error with unescaped content
7184+ return [xml]@("< style> "
7185+ $styleElementParts -join [Environment]::NewLine
7186+ "< /style> ")
7187+ } catch {
7188+ # catch it and escape the content
7189+ return [xml]@(
7190+ "< style> "
7191+ [Security.SecurityElement]::Escape($styleElementParts -join [Environment]::NewLine)
7192+ "< /style> "
7193+ )
7194+ }
7195+ } else {
7196+ return ''
7197+ }
7198+
71377199return $this.'.style'
71387200 </GetScriptBlock >
71397201 <SetScriptBlock >
@@ -7146,15 +7208,79 @@ return $this.'.style'
71467208 These styles will be declared in a `< style> ` element, just beneath a Turtle's `< svg> `
71477209.EXAMPLE
71487210 turtle style '.myClass { color: #4488ff}' style
7211+ .EXAMPLE
7212+ turtle style abc
7213+ .EXAMPLE
7214+ turtle style "@import url('https://fonts.googleapis.com/css?family=Abel')" text 'Hello World' textattribute @{'font-family'='Abel';'font-size'='3em'} fill 'red' save ./t.png show
71497215#>
71507216param(
7151- [PSObject]
7217+ [PSObject[] ]
71527218$Style
71537219)
71547220
7155- $styleList = $this.Style
7156- $styleList += $style
7157- $this | Add-Member NoteProperty '.style' $styleList -Force
7221+ filter toCss {
7222+ # Capture the input,
7223+ $in = $_
7224+ # know myself,
7225+ $mySelf = $MyInvocation.MyCommand.ScriptBlock
7226+ # and determine our depth
7227+ $depth = 0
7228+ # (with a little callstack peeking).
7229+ foreach ($frame in Get-PSCallStack) {
7230+ if ($frame.InvocationInfo.MyCommand.ScriptBlock -eq $mySelf) {
7231+ $depth++
7232+ }
7233+ }
7234+ # Always substract one so we don't indent the root.
7235+ $depth--
7236+
7237+ if ($in -is [string]) {
7238+ $in # Directly output strings
7239+ } elseif ($in -is [Collections.IDictionary]) {
7240+ # Join dictionaries by semicolons and indentation
7241+ ($in.GetEnumerator() | & $mySelf) -join (
7242+ ';' + [Environment]::NewLine + (' ' * 2 * $depth)
7243+ )
7244+ } elseif ($in.Key -and $in.Value) {
7245+ # Key/value pairs containing dictionaries
7246+ if ($in.Value -is [Collections.IDictionary]) {
7247+ # become `selector { rules }`
7248+ (
7249+ "$($in.Key) {", (
7250+ (' ' * 2) + ($in.Value | & $mySelf)
7251+ ) -join (
7252+ [Environment]::NewLine + (' ' * 2 * $depth)
7253+ )
7254+ ) + (
7255+ [Environment]::NewLine + (' ' * 2 * ($depth - 1))
7256+ ) + '}'
7257+ }
7258+ elseif ($in.Value -is [TimeSpan]) {
7259+ "$($in.Key):$($in.Value.TotalSeconds)s"
7260+ }
7261+ else {
7262+ # Other key/value pairs are placed inline
7263+ "$($in.Key):$($in.Value)"
7264+ }
7265+ }
7266+ elseif ($in -is [PSObject]) {
7267+ # turn non-dictionaries into dictionaries
7268+ $inDictionary = [Ordered]@{}
7269+ foreach ($property in $in.psobject.properties) {
7270+ $inDictionary[$property.Name] = $in.($property.Name)
7271+ }
7272+ if ($inDictionary.Count) {
7273+ # and recurse.
7274+ $inDictionary | & $mySelf
7275+ }
7276+ }
7277+ }
7278+
7279+ if (-not $this.'.style') {
7280+ $this | Add-Member NoteProperty '.style' @() -Force
7281+ }
7282+ $this.'.style' += $style |toCss
7283+
71587284
71597285 </SetScriptBlock >
71607286 </ScriptProperty >
@@ -7215,33 +7341,11 @@ $svgElement = @(
72157341 "< /defs> "
72167342 }
72177343
7218- if ($this.Keyframe.Count -or $this.Style) {
7219- $keyframe = $this.Keyframe
7220- "< style> "
7221- @(foreach ($keyframeName in $keyframe.Keys) {
7222- $keyframeKeyframes = $keyframe[$keyframeName]
7223- "@keyframes $keyframeName {"
7224- foreach ($percent in $keyframeKeyframes.Keys) {
7225- " $percent {"
7226- $props = $keyframeKeyframes[$percent]
7227- foreach ($prop in $props.Keys) {
7228- $value = $props.$prop
7229- " ${prop}: $value;"
7230- }
7231- " }"
7232- }
7233- "}"
7234- ".$keyframeName {"
7235- " animation-name: $keyframeName;"
7236- " animation-duration: $($this.Duration.TotalSeconds)s;"
7237- " animation-iteration-count: infinite;"
7238- "}"
7239- }) -join [Environment]::NewLine
7240- if ($this.Style) {
7241- "$($this.Style -join (';' + [Environment]::NewLine))"
7242- }
7243- "< /style> "
7244- }
7344+ $style = $this.Style
7345+ if ($style -is [xml]) {
7346+ $style.OuterXml
7347+ }
7348+
72457349
72467350 # Declare any SVG animations
72477351 if ($this.SVGAnimation) {$this.SVGAnimation}
0 commit comments