@@ -9,13 +9,10 @@ import { resourcePath } from "../resources.ts";
99
1010import { languages } from "./base.ts" ;
1111
12- import {
13- jupyterCellWithOptions ,
14- jupyterFromFile ,
15- jupyterToMarkdown ,
16- } from "../jupyter/jupyter.ts" ;
12+ import { jupyterFromFile , jupyterToMarkdown } from "../jupyter/jupyter.ts" ;
1713
1814import {
15+ kCellLabel ,
1916 kFigDpi ,
2017 kFigFormat ,
2118 kFigPos ,
@@ -33,13 +30,11 @@ import { RenderContext, RenderFlags } from "../../command/render/types.ts";
3330import {
3431 JupyterAssets ,
3532 JupyterCell ,
36- JupyterNotebook ,
33+ JupyterCellOutput ,
3734} from "../jupyter/types.ts" ;
3835
3936import { dirname , extname } from "path/mod.ts" ;
4037
41- const kLabel = "label" ;
42-
4338export interface NotebookAddress {
4439 path : string ;
4540 ids ?: string [ ] ;
@@ -99,60 +94,19 @@ export function parseNotebookPath(path: string): NotebookAddress | undefined {
9994 }
10095}
10196
102- export function notebookForAddress (
103- nbAddress : NotebookAddress ,
104- filter ?: ( cell : JupyterCell ) => JupyterCell ,
105- ) {
106- try {
107- const nb = jupyterFromFile ( nbAddress . path ) ;
108-
109- if ( nbAddress . ids ) {
110- // If cellIds are present, filter the notebook to only include
111- // those cells (cellIds can eiher be an explicitly set cellId, a label in the
112- // cell metadata, or a tag on a cell that matches an id)
113- const theCells = nbAddress . ids . map ( ( id ) => {
114- const cell = cellForId ( id , nb ) ;
115- if ( cell === undefined ) {
116- throw new Error (
117- `The cell ${ id } does not exist in notebook` ,
118- ) ;
119- } else {
120- return cell ;
121- }
122- } ) ;
123- nb . cells = theCells ;
124- } else if ( nbAddress . indexes ) {
125- // Filter and sort based upon cell index
126- nb . cells = nbAddress . indexes . map ( ( idx ) => {
127- if ( idx < 0 || idx >= nb . cells . length ) {
128- throw new Error (
129- `The cell index ${ idx } isn't within the range of cells` ,
130- ) ;
131- }
132- return nb . cells [ idx ] ;
133- } ) ;
134- }
135-
136- // If there is a cell filter, apply it
137- if ( filter ) {
138- nb . cells = nb . cells . map ( filter ) ;
139- }
140-
141- return nb ;
142- } catch ( ex ) {
143- throw new Error (
144- `Failed to read notebook ${ nbAddress . path } \n${ ex . message || "" } ` ,
145- ex ,
146- ) ;
147- }
148- }
149-
15097export async function notebookMarkdown (
151- notebook : JupyterNotebook ,
98+ nbAddress : NotebookAddress ,
15299 assets : JupyterAssets ,
153100 context : RenderContext ,
154101 flags : RenderFlags ,
102+ filter ?: ( cell : JupyterCell ) => JupyterCell ,
155103) {
104+ // Read and filter notebook
105+ const notebook = jupyterFromFile ( nbAddress . path ) ;
106+ if ( filter ) {
107+ notebook . cells = notebook . cells . map ( filter ) ;
108+ }
109+
156110 const format = context . format ;
157111 const executeOptions = {
158112 target : context . target ,
@@ -187,36 +141,56 @@ export async function notebookMarkdown(
187141 figPos : format . render [ kFigPos ] ,
188142 } ,
189143 ) ;
190- if ( result ) {
191- return result . markdown ;
144+
145+ if ( nbAddress . ids ) {
146+ // If cellIds are present, filter the notebook to only include
147+ // those cells (cellIds can eiher be an explicitly set cellId, a label in the
148+ // cell metadata, or a tag on a cell that matches an id)
149+ const theCells = nbAddress . ids . map ( ( id ) => {
150+ const cell = cellForId ( id , result . cellOutputs ) ;
151+ if ( cell === undefined ) {
152+ throw new Error (
153+ `The cell ${ id } does not exist in notebook` ,
154+ ) ;
155+ } else {
156+ return cell ;
157+ }
158+ } ) ;
159+ return theCells . map ( ( cell ) => cell . markdown ) . join ( "" ) ;
160+ } else if ( nbAddress . indexes ) {
161+ // Filter and sort based upon cell index
162+ const theCells = nbAddress . indexes . map ( ( idx ) => {
163+ if ( idx < 0 || idx >= result . cellOutputs . length ) {
164+ throw new Error (
165+ `The cell index ${ idx } isn't within the range of cells` ,
166+ ) ;
167+ }
168+ return result . cellOutputs [ idx ] ;
169+ } ) ;
170+ return theCells . map ( ( cell ) => cell . markdown ) . join ( "" ) ;
192171 } else {
193- return undefined ;
172+ return result . cellOutputs . map ( ( cell ) => cell . markdown ) . join ( "" ) ;
194173 }
195174}
196175
197- function cellForId ( id : string , nb : JupyterNotebook ) {
198- for ( const cell of nb . cells ) {
176+ function cellForId ( id : string , cells : JupyterCellOutput [ ] ) {
177+ for ( const cell of cells ) {
199178 // cellId can either by a literal cell Id, or a tag with that value
200179 const hasId = cell . id ? id === cell . id : false ;
201180 if ( hasId ) {
202181 // It's an ID
203182 return cell ;
204183 } else {
205- // Check for label in options
206- const cellWithOptions = jupyterCellWithOptions (
207- nb . metadata . kernelspec . language . toLowerCase ( ) ,
208- cell ,
209- ) ;
210- const hasLabel = cellWithOptions . options [ kLabel ]
211- ? id === cellWithOptions . options [ kLabel ]
184+ const hasLabel = cell . options && cell . options [ kCellLabel ]
185+ ? id === cell . options [ kCellLabel ]
212186 : false ;
213187
214188 if ( hasLabel ) {
215189 // It matches a label
216190 return cell ;
217191 } else {
218192 // Check tags
219- const hasTag = cell . metadata . tags
193+ const hasTag = cell . metadata && cell . metadata . tags
220194 ? cell . metadata . tags . find ( ( tag ) => id === tag ) !==
221195 undefined
222196 : false ;
@@ -228,38 +202,6 @@ function cellForId(id: string, nb: JupyterNotebook) {
228202 }
229203}
230204
231- function cellInIdList ( ids : string [ ] , cell : JupyterCell , nb : JupyterNotebook ) {
232- // cellId can either by a literal cell Id, or a tag with that value
233- const hasId = cell . id ? ids . includes ( cell . id ) : false ;
234- if ( hasId ) {
235- // It's an ID
236- return true ;
237- } else {
238- // Check for label in options
239- const cellWithOptions = jupyterCellWithOptions (
240- nb . metadata . kernelspec . language . toLowerCase ( ) ,
241- cell ,
242- ) ;
243- const hasLabel = cellWithOptions . options [ kLabel ]
244- ? ids . includes ( cellWithOptions . options [ kLabel ] )
245- : false ;
246-
247- if ( hasLabel ) {
248- // It matches a label
249- return cell ;
250- } else {
251- // Check tags
252- const hasTag = cell . metadata . tags
253- ? cell . metadata . tags . find ( ( tag ) => ids . includes ( tag ) ) !==
254- undefined
255- : false ;
256- if ( hasTag ) {
257- return cell ;
258- }
259- }
260- }
261- }
262-
263205const resolveCellIds = ( hash ?: string ) => {
264206 if ( hash && hash . indexOf ( "," ) > 0 ) {
265207 return hash . split ( "," ) ;
0 commit comments