@@ -106,6 +106,40 @@ def html(self):
106106 f'width="{ self ["width" ]} " height="{ self ["height" ]} " class="jupyterlite_sphinx_raw_iframe"></iframe>'
107107 )
108108
109+ class _InTab (Element ):
110+ def __init__ (
111+ self ,
112+ rawsource = "" ,
113+ * children ,
114+ prefix = JUPYTERLITE_DIR ,
115+ notebook = None ,
116+ lite_options = {},
117+ ** attributes ,
118+ ):
119+ app_path = self .lite_app
120+ if notebook is not None :
121+ lite_options ["path" ] = notebook
122+ app_path = f"{ self .lite_app } { self .notebooks_path } "
123+
124+ options = "&" .join (
125+ [f"{ key } ={ quote (value )} " for key , value in lite_options .items ()]
126+ )
127+ self .lab_src = (
128+ f'{ prefix } /{ app_path } { f"?{ options } " if options else "" } '
129+ )
130+
131+ super ().__init__ (
132+ "" ,
133+ ** attributes ,
134+ )
135+
136+ def html (self ):
137+ return (
138+ '<button class="try_examples_button" '
139+ f"onclick=\" window.open('{ self .lab_src } ')\" >"
140+ "Open as a notebook</button>"
141+ )
142+
109143
110144class _LiteIframe (_PromptedIframe ):
111145 def __init__ (
@@ -164,6 +198,14 @@ class JupyterLiteIframe(_LiteIframe):
164198 lite_app = "lab/"
165199 notebooks_path = ""
166200
201+ class JupyterLiteTab (_InTab ):
202+ """Appended to the doctree by the JupyterliteDirective directive
203+
204+ Renders a button that opens a Notebook with JupyterLite in a new tab.
205+ """
206+
207+ lite_app = "lab/"
208+ notebooks_path = ""
167209
168210class NotebookLiteIframe (_LiteIframe ):
169211 """Appended to the doctree by the NotebookliteDirective directive
@@ -262,6 +304,7 @@ class _LiteDirective(SphinxDirective):
262304 "prompt" : directives .unchanged ,
263305 "prompt_color" : directives .unchanged ,
264306 "search_params" : directives .unchanged ,
307+ "new_tab" : directives .unchanged ,
265308 }
266309
267310 def run (self ):
@@ -273,6 +316,8 @@ def run(self):
273316
274317 search_params = search_params_parser (self .options .pop ("search_params" , False ))
275318
319+ new_tab = self .options .pop ("new_tab" , False )
320+
276321 source_location = os .path .dirname (self .get_source_info ()[0 ])
277322
278323 prefix = os .path .relpath (
@@ -299,6 +344,20 @@ def run(self):
299344 else :
300345 notebook_name = None
301346
347+ if new_tab :
348+ return [
349+ self .newtab_cls (
350+ prefix = prefix ,
351+ notebook = notebook_name ,
352+ width = width ,
353+ height = height ,
354+ prompt = prompt ,
355+ prompt_color = prompt_color ,
356+ search_params = search_params ,
357+ lite_options = self .options ,
358+ )
359+ ]
360+
302361 return [
303362 self .iframe_cls (
304363 prefix = prefix ,
@@ -320,6 +379,7 @@ class JupyterLiteDirective(_LiteDirective):
320379 """
321380
322381 iframe_cls = JupyterLiteIframe
382+ newtab_cls = JupyterLiteTab
323383
324384
325385class NotebookLiteDirective (_LiteDirective ):
@@ -694,6 +754,14 @@ def setup(app):
694754 text = (skip , None ),
695755 man = (skip , None ),
696756 )
757+ app .add_node (
758+ JupyterLiteTab ,
759+ html = (visit_element_html , None ),
760+ latex = (skip , None ),
761+ textinfo = (skip , None ),
762+ text = (skip , None ),
763+ man = (skip , None ),
764+ )
697765 app .add_directive ("jupyterlite" , JupyterLiteDirective )
698766
699767 # Initialize Replite directive
0 commit comments