@@ -309,122 +309,150 @@ def _create_yaml_header(self) -> str:
309309 A formatted YAML header string customized for the specified output format.
310310 """
311311 # Base YAML header with title
312- yaml_header = f"""---
313- title: { self .report .title }
314- fig-align: center
315- execute:
316- echo: false
317- output: asis
318- jupyter: python3
319- format:"""
320-
312+ yaml_header = textwrap .dedent (
313+ f"""\
314+ ---
315+ title: { self .report .title }
316+ fig-align: center
317+ execute:
318+ echo: false
319+ output: asis
320+ jupyter: python3
321+ format:"""
322+ )
321323 # Define format-specific YAML configurations
322324 format_configs = {
323- r .ReportType .HTML : """
324- html:
325- toc: true
326- toc-location: left
327- toc-depth: 3
328- page-layout: full
329- self-contained: true
330- include-in-header:
331- text: |
332- <style type="text/css">
333- .footer {
334- position: relative;
335- left: 0;
336- width: 100%;
337- text-align: center;
338- margin-top: 20px;
339- }
340- </style>
341- include-after-body:
342- text: |
343- <footer class="footer">
344- This report was generated with
345- <a href="https://github.com/Multiomics-Analytics-Group/vuegen" target="_blank">
346- <img src="https://raw.githubusercontent.com/Multiomics-Analytics-Group/vuegen/main/docs/images/vuegen_logo.svg" alt="VueGen" width="65px">
347- </a>
348- | Copyright 2025 <a href="https://github.com/Multiomics-Analytics-Group" target="_blank">Multiomics Network Analytics Group (MoNA)</a>
349- </footer>""" ,
350- r .ReportType .PDF : """
351- pdf:
352- toc: false
353- fig-align: center
354- margin:
355- - bottom=40mm
356- include-in-header:
357- text: |
358- \\ usepackage{scrlayer-scrpage}
359- \\ usepackage{hyperref}
360- \\ clearpairofpagestyles
361- \\ lofoot{This report was generated with \\ href{https://github.com/Multiomics-Analytics-Group/vuegen}{VueGen} | \\ copyright{} 2025 \\ href{https://github.com/Multiomics-Analytics-Group}{Multiomics Network Analytics Group}}
362- \\ rofoot{\\ pagemark}""" ,
363- r .ReportType .DOCX : """
364- docx:
365- toc: false""" ,
366- r .ReportType .ODT : """
367- odt:
368- toc: false""" ,
369- r .ReportType .REVEALJS : """
370- revealjs:
371- toc: false
372- smaller: true
373- controls: true
374- navigation-mode: vertical
375- controls-layout: bottom-right
376- output-file: quarto_report_revealjs.html
377- include-in-header:
378- text: |
379- <style type="text/css">
380- .footer {
381- position: fixed;
382- left: 0;
383- bottom: 0;
384- width: 100%;
385- text-align: center;
386- }
387- </style>
388- include-after-body:
389- text: |
390- <footer class="footer">
391- This report was generated with
392- <a href="https://github.com/Multiomics-Analytics-Group/vuegen" target="_blank">
393- <img src="https://raw.githubusercontent.com/Multiomics-Analytics-Group/vuegen/main/docs/images/vuegen_logo.svg" alt="VueGen" width="65px">
394- </a>
395- | Copyright 2025 <a href="https://github.com/Multiomics-Analytics-Group" target="_blank">Multiomics Network Analytics Group (MoNA)</a>
396- </footer>""" ,
397- r .ReportType .PPTX : """
398- pptx:
399- toc: false
400- output: true""" ,
401- r .ReportType .JUPYTER : """
402- html:
403- toc: true
404- toc-location: left
405- toc-depth: 3
406- page-layout: full
407- self-contained: true
408- include-in-header:
409- text: |
410- <style type="text/css">
411- .footer {
412- position: relative;
413- left: 0;
414- width: 100%;
415- text-align: center;
416- margin-top: 20px;
417- }
418- </style>
419- include-after-body:
420- text: |
421- <footer class="footer">
422- This report was generated with
423- <a href="https://github.com/Multiomics-Analytics-Group/vuegen" target="_blank">
424- <img src="../docs/images/vuegen_logo.svg" alt="VueGen" width="65px">
425- </a>
426- | Copyright 2025 <a href="https://github.com/Multiomics-Analytics-Group" target="_blank">Multiomics Network Analytics Group (MoNA)</a>
427- </footer>""" ,
325+ r .ReportType .HTML : textwrap .dedent (
326+ """
327+ html:
328+ toc: true
329+ toc-location: left
330+ toc-depth: 3
331+ page-layout: full
332+ self-contained: true
333+ include-in-header:
334+ text: |
335+ <style type="text/css">
336+ .footer {
337+ position: relative;
338+ left: 0;
339+ width: 100%;
340+ text-align: center;
341+ margin-top: 20px;
342+ }
343+ </style>
344+ include-after-body:
345+ text: |
346+ <footer class="footer">
347+ This report was generated with
348+ <a href="https://github.com/Multiomics-Analytics-Group/vuegen" target="_blank">
349+ <img src="https://raw.githubusercontent.com/Multiomics-Analytics-Group/vuegen/main/docs/images/vuegen_logo.svg" alt="VueGen" width="65px">
350+ </a>
351+ | Copyright 2025 <a href="https://github.com/Multiomics-Analytics-Group" target="_blank">Multiomics Network Analytics Group (MoNA)</a>
352+ </footer>"""
353+ ),
354+ r .ReportType .PDF : textwrap .indent (
355+ textwrap .dedent (
356+ """
357+ pdf:
358+ toc: false
359+ fig-align: center
360+ margin:
361+ - bottom=40mm
362+ include-in-header:
363+ text: |
364+ \\ usepackage{scrlayer-scrpage}
365+ \\ usepackage{hyperref}
366+ \\ clearpairofpagestyles
367+ \\ lofoot{This report was generated with \\ href{https://github.com/Multiomics-Analytics-Group/vuegen}{VueGen} | \\ copyright{} 2025 \\ href{https://github.com/Multiomics-Analytics-Group}{Multiomics Network Analytics Group}}
368+ \\ rofoot{\\ pagemark}"""
369+ ),
370+ " " ,
371+ ),
372+ r .ReportType .DOCX : textwrap .indent (
373+ textwrap .dedent (
374+ """
375+ docx:
376+ toc: false"""
377+ ),
378+ " " ,
379+ ),
380+ r .ReportType .ODT : textwrap .indent (
381+ textwrap .dedent (
382+ """
383+ odt:
384+ toc: false"""
385+ ),
386+ " " ,
387+ ),
388+ r .ReportType .REVEALJS : textwrap .dedent (
389+ """
390+ revealjs:
391+ toc: false
392+ smaller: true
393+ controls: true
394+ navigation-mode: vertical
395+ controls-layout: bottom-right
396+ output-file: quarto_report_revealjs.html
397+ include-in-header:
398+ text: |
399+ <style type="text/css">
400+ .footer {
401+ position: fixed;
402+ left: 0;
403+ bottom: 0;
404+ width: 100%;
405+ text-align: center;
406+ }
407+ </style>
408+ include-after-body:
409+ text: |
410+ <footer class="footer">
411+ This report was generated with
412+ <a href="https://github.com/Multiomics-Analytics-Group/vuegen" target="_blank">
413+ <img src="https://raw.githubusercontent.com/Multiomics-Analytics-Group/vuegen/main/docs/images/vuegen_logo.svg" alt="VueGen" width="65px">
414+ </a>
415+ | Copyright 2025 <a href="https://github.com/Multiomics-Analytics-Group" target="_blank">Multiomics Network Analytics Group (MoNA)</a>
416+ </footer>"""
417+ ),
418+ r .ReportType .PPTX : textwrap .indent (
419+ textwrap .dedent (
420+ """
421+ pptx:
422+ toc: false
423+ output: true"""
424+ ),
425+ " " ,
426+ ),
427+ r .ReportType .JUPYTER : textwrap .dedent (
428+ """
429+ html:
430+ toc: true
431+ toc-location: left
432+ toc-depth: 3
433+ page-layout: full
434+ self-contained: true
435+ include-in-header:
436+ text: |
437+ <style type="text/css">
438+ .footer {
439+ position: relative;
440+ left: 0;
441+ width: 100%;
442+ text-align: center;
443+ margin-top: 20px;
444+ }
445+ </style>
446+ include-after-body:
447+ text: |
448+ <footer class="footer">
449+ This report was generated with
450+ <a href="https://github.com/Multiomics-Analytics-Group/vuegen" target="_blank">
451+ <img src="../docs/images/vuegen_logo.svg" alt="VueGen" width="65px">
452+ </a>
453+ | Copyright 2025 <a href="https://github.com/Multiomics-Analytics-Group" target="_blank">Multiomics Network Analytics Group (MoNA)</a>
454+ </footer>"""
455+ ),
428456 }
429457 # Create a key based on the report type and format
430458 key = self .report_type
@@ -632,41 +660,57 @@ def _generate_plot_code(self, plot, output_file="") -> str:
632660 The generated plot code as a string.
633661 """
634662 # Initialize plot code with common structure
635- plot_code = f"""```{{python}}
636- #| label: '{ plot .title } { plot .id } '
637- #| fig-cap: ""
638- """
663+ plot_code = textwrap .dedent (
664+ f"""
665+ ```{{python}}
666+ #| label: '{ plot .title } { plot .id } '
667+ #| fig-cap: ""
668+ """
669+ )
639670 # If the file path is a URL, generate code to fetch content via requests
640671 if is_url (plot .file_path ):
641- plot_code += f"""
642- response = requests.get('{ plot .file_path } ')
643- response.raise_for_status()
644- plot_json = response.text\n """
672+ plot_code += textwrap .dedent (
673+ f"""
674+ response = requests.get('{ plot .file_path } ')
675+ response.raise_for_status()
676+ plot_json = response.text
677+ """
678+ )
645679 else : # If it's a local file
646680 plot_rel_path = get_relative_file_path (
647681 plot .file_path , relative_to = self .output_dir
648682 ).as_posix ()
649- plot_code += f"""
683+ plot_code += textwrap .dedent (
684+ f"""
650685with open(report_dir /'{ plot_rel_path } ', 'r') as plot_file:
651- plot_json = json.load(plot_file)\n """
686+ plot_json = json.load(plot_file)
687+ """
688+ )
652689 # Add specific code for each visualization tool
653690 if plot .plot_type == r .PlotType .PLOTLY :
654- plot_code += """
655- # Keep only 'data' and 'layout' sections
656- plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}\n
657- # Remove 'frame' section in 'data'
658- plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]\n
659- # Convert JSON to string
660- plot_json_str = json.dumps(plot_json)\n
661- # Create the plotly plot
662- fig_plotly = pio.from_json(plot_json_str)
663- fig_plotly.update_layout(autosize=False, width=950, height=400, margin=dict(b=50, t=50, l=50, r=50))\n """
691+ plot_code += textwrap .dedent (
692+ """
693+ # Keep only 'data' and 'layout' sections
694+ plot_json = {key: plot_json[key] for key in plot_json if key in ['data', 'layout']}\n
695+ # Remove 'frame' section in 'data'
696+ plot_json['data'] = [{k: v for k, v in entry.items() if k != 'frame'} for entry in plot_json.get('data', [])]\n
697+ # Convert JSON to string
698+ plot_json_str = json.dumps(plot_json)\n
699+ # Create the plotly plot
700+ fig_plotly = pio.from_json(plot_json_str)
701+ fig_plotly.update_layout(autosize=False, width=950, height=400, margin=dict(b=50, t=50, l=50, r=50))
702+ """
703+ )
664704 elif plot .plot_type == r .PlotType .ALTAIR :
665- plot_code += """
666- # Convert JSON to string
667- plot_json_str = json.dumps(plot_json)\n
668- # Create the plotly plot
669- fig_altair = alt.Chart.from_json(plot_json_str).properties(width=900, height=370)\n """
705+ plot_code += textwrap .dedent (
706+ """
707+ # Convert JSON to string
708+ plot_json_str = json.dumps(plot_json)
709+
710+ # Create the altair plot
711+ fig_altair = alt.Chart.from_json(plot_json_str).properties(width=900, height=370)
712+ """
713+ )
670714 elif plot .plot_type == r .PlotType .INTERACTIVE_NETWORK :
671715 # Generate the HTML embedding for interactive networks
672716 if is_url (plot .file_path ) and plot .file_path .endswith (".html" ):
@@ -677,10 +721,13 @@ def _generate_plot_code(self, plot, output_file="") -> str:
677721 )
678722
679723 # Embed the HTML file in an iframe
680- plot_code = f"""
681- <div style="text-align: center;">
682- <iframe src="{ iframe_src } " alt="{ plot .title } plot" width="800px" height="630px"></iframe>
683- </div>\n """
724+ plot_code = textwrap .dedent (
725+ f"""
726+ <div style="text-align: center;">
727+ <iframe src="{ iframe_src } " alt="{ plot .title } plot" width="800px" height="630px"></iframe>
728+ </div>
729+ """
730+ )
684731 return plot_code
685732
686733 def _generate_dataframe_content (self , dataframe ) -> List [str ]:
@@ -942,10 +989,14 @@ def _generate_html_content(self, html) -> List[str]:
942989 html_file_path = get_relative_file_path (
943990 html .file_path , relative_to = self .output_dir
944991 )
945- iframe_code = f"""
946- <div style="text-align: center;">
947- <iframe src="{ html_file_path .as_posix ()} " alt="{ html .title } " width="950px" height="530px"></iframe>
948- </div>\n """
992+ iframe_code = textwrap .dedent (
993+ f"""
994+ <div style="text-align: center;">
995+ <iframe src="{ html_file_path .as_posix ()} " alt="{ html .title } "
996+ width="950px" height="530px"></iframe>
997+ </div>
998+ """
999+ )
9491000 html_content .append (iframe_code )
9501001
9511002 except Exception as e :
0 commit comments