-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathGetNotebookContent.ps1
132 lines (123 loc) · 5.93 KB
/
GetNotebookContent.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
function Get-NotebookContent {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Justification="Test doesn't understand -begin script blocks. ")]
<#
.SYNOPSIS
Get-NotebookContents reads the contents of a Jupyter Notebooks
.Example
Get-NotebookContent .\samplenotebook\Chapter01code.ipynb
NoteBookName Type Source
------------ ---- ------
Chapter01code.ipynb markdown ## Code for chapter 1 PowerShell in Action third edition
Chapter01code.ipynb markdown ## Introduction
Chapter01code.ipynb code 'Hello world.'
Chapter01code.ipynb code Get-ChildItem -Path $env:windir\*.log | Select-String -List error | Format-Table Path,L...
Chapter01code.ipynb code ([xml] [System.Net.WebClient]::new().DownloadString('http://blogs.msdn.com/powershell/r...
Chapter01code.ipynb markdown ## 1.2 PowerShell example code
Chapter01code.ipynb code Get-ChildItem -Path C:\somefile.txt
.Example
Get-Notebook .\samplenotebook\*sharp*|Get-NotebookContent
NoteBookName Type Source
------------ ---- ------
csharp.ipynb code {Console.Write("hello world")}
fsharp.ipynb code {printfn "hello world"}
#>
[cmdletbinding(DefaultParameterSetName="MarkdownAndCode")]
param(
[Parameter(ValueFromPipelineByPropertyName,Position=0)]
[alias('FullName','NoteBookFullName')]
$Path,
[parameter(ParameterSetName='JustCode')]
[alias('NoMarkdown')]
[Switch]$JustCode,
[parameter(ParameterSetName='JustMarkdown')]
[alias('NoCode')]
[Switch]$JustMarkdown,
[Switch]$PassThru,
[Switch]$IncludeOutput
)
process {
#allow Path to contain more than one item, if any are wild cards call the function recursively.
foreach ($p in $Path) {
if ([System.Uri]::IsWellFormedUriString($p, [System.UriKind]::Absolute)) {
$r = Invoke-RestMethod $p
}
elseif (Test-Path $p -ErrorAction SilentlyContinue) {
if ((Resolve-Path $p).count -gt 1) {
[void]$PSBoundParameters.Remove('Path')
Get-ChildItem $p | Get-NotebookContent @PSBoundParameters
continue
}
else {
$r = Get-Content $p | ConvertFrom-Json
}
}
if ($PassThru) { return $r}
elseif ($JustCode) { $cellType = 'code' }
elseif ($JustMarkdown) { $cellType = 'markdown' }
else { $cellType = '.' }
$cellnumber = 0
foreach ($cell in $r.cells) {
$cellnumber += 1
if ($null -ne $cellType -and $cell.'cell_type' -notmatch $cellType) {
continue
}
$IsParameterCell = $false
if ($cell.metadata.tags) {
if ($null -ne ($cell.metadata.tags -eq 'parameters')) {
$IsParameterCell = $true
}
}
if ($cell.metadata.dotnet_interactive) {
$Language = switch ($cell.metadata.dotnet_interactive.language) {
'sql' { 'SQL' }
'pwsh' { 'PowerShell' }
'fsharp' { 'F#' }
'csharp' { 'C#' }
'html' { 'html'}
Default { 'C#' }
}
$Language += ' (.NET Interactive)'
}
elseif ($cell.'cell_type' -match 'code') {
$Language = $r.metadata.kernelspec.language
if ($r.metadata.kernelspec.display_name -match '^\.NET\s*\(') {$Language += ' (.NET Interactive)'}
}
elseif ($cell.'cell_type' -match 'code') {
$Language = 'markdown'
}
$cellObj = [Ordered]@{
Cell = $cellNumber
NoteBookName = Split-Path -Leaf $p
Type = $cell.'cell_type'
IsParameterCell = $IsParameterCell
Language = $Language
Source = -join $cell.source
}
if ($IncludeOutput) {
# There may be one or many outputs. For each output
# either a single string if has a .text field containing a string or array of strings
# or a hash table if it has a .data field containing .mime-type = "Content"
$cellObj['Output'] = foreach ($o in $cell.outputs) {
if ($o.text -join "") {$o.text -join " `r`n" }
elseif ($o.data) {
$o.data.psobject.properties | foreach-object -Begin {$hash=@{}} -Process {$hash[$_.name] =$_.value} -end {$hash}
}
}
#merge the text generated by .NET Interactive in VS code - every output will be a hash table with a text/plain entry. Others do the same with Text/HTML
if ( $cellObj.Output.where({$_ -is [hashtable]}) -and -not #if some are hashtables and none are not hashtables
$cellObj.Output.where({$_ -isnot [hashtable]}) ){
if ($cellObj.Output.where({ $_.containskey('text/html')}) -and -not #if some have text/html and none don't.
$cellObj.Output.where({-not $_.containskey('text/html')}) ) {
$cellObj['HtmlOutput'] = $cellObj.output.'text/html' -join "<br />`n" #Add an HTML Output field
}
if ($cellObj.Output.where({ $_.containskey('text/plain')}) -and -not #if some have text/plain and none don't.
$cellObj.Output.where({-not $_.containskey('text/plain')}) ) {
$cellObj.Output = -join $cellobj.output.'text/plain' #Merge plain text into the output field
}
}
}
[PSCustomObject]$cellObj
}
}
}
}