From 5846feb0118ffcdf3090ad9e0b9ae54b4e546a2b Mon Sep 17 00:00:00 2001 From: Emir Ayar Date: Mon, 12 Jan 2026 13:21:40 +0100 Subject: [PATCH] feat: add --slide-visibility and --skip-hidden options for hidden slide handling --- pptx2md/__main__.py | 10 ++++++++++ pptx2md/outputter.py | 13 +++++++++++++ pptx2md/parser.py | 15 +++++++++++++-- pptx2md/types.py | 14 ++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/pptx2md/__main__.py b/pptx2md/__main__.py index 2f5d592..6db0b64 100644 --- a/pptx2md/__main__.py +++ b/pptx2md/__main__.py @@ -54,6 +54,14 @@ def parse_args() -> ConversionConfig: "--keep-similar-titles", action="store_true", help="keep similar titles (allow for repeated slide titles - One or more - Add (cont.) to the title)") + arg_parser.add_argument( + "--slide-visibility", + action="store_true", + help="show slide visibility status () in the output") + arg_parser.add_argument( + "--skip-hidden", + action="store_true", + help="skip hidden slides in the output (preserves original slide numbering)") args = arg_parser.parse_args() @@ -81,6 +89,8 @@ def parse_args() -> ConversionConfig: min_block_size=args.min_block_size, page=args.page, keep_similar_titles=args.keep_similar_titles, + slide_visibility=args.slide_visibility, + skip_hidden=args.skip_hidden, ) diff --git a/pptx2md/outputter.py b/pptx2md/outputter.py index 3beadd6..ce84fd8 100644 --- a/pptx2md/outputter.py +++ b/pptx2md/outputter.py @@ -36,6 +36,10 @@ def output(self, presentation_data: ParsedPresentation): last_element = None last_title = None for slide_idx, slide in enumerate(presentation_data.slides): + # Add slide visibility comment if enabled + if self.config.slide_visibility: + self.put_slide_visibility(slide.is_hidden) + all_elements = [] if slide.type == SlideType.General: all_elements = slide.elements @@ -84,6 +88,11 @@ def output(self, presentation_data: ParsedPresentation): def put_header(self): pass + def put_slide_visibility(self, is_hidden: bool): + """Output slide visibility status comment.""" + status = 'hidden' if is_hidden else 'visible' + self.ofile.write(f'\n') + def put_title(self, text, level): pass @@ -336,6 +345,10 @@ def put_elements(elements: List[SlideElement]): last_element = element for slide_idx, slide in enumerate(presentation_data.slides): + # Add slide visibility comment if enabled + if self.config.slide_visibility: + self.put_slide_visibility(slide.is_hidden) + if slide.type == SlideType.General: put_elements(slide.elements) elif slide.type == SlideType.MultiColumn: diff --git a/pptx2md/parser.py b/pptx2md/parser.py index edcc10a..6220f95 100644 --- a/pptx2md/parser.py +++ b/pptx2md/parser.py @@ -244,6 +244,15 @@ def parse(config: ConversionConfig, prs: Presentation) -> ParsedPresentation: for idx, slide in enumerate(tqdm(prs.slides, desc='Converting slides')): if config.page is not None and idx + 1 != config.page: continue + + # Check if slide is hidden + show_attr = slide._element.get('show') + is_hidden = show_attr == '0' + + # Skip hidden slides if configured + if config.skip_hidden and is_hidden: + continue + shapes = [] try: shapes = sorted(ungroup_shapes(slide.shapes), key=attrgetter('top', 'left')) @@ -258,14 +267,16 @@ def parse(config: ConversionConfig, prs: Presentation) -> ParsedPresentation: logger.warning('failed to print all bad shapes.') if not config.try_multi_column: - result_slide = GeneralSlide(elements=process_shapes(config, shapes, idx + 1)) + result_slide = GeneralSlide(elements=process_shapes(config, shapes, idx + 1), is_hidden=is_hidden, original_index=idx + 1) else: multi_column_slide = get_multi_column_slide_if_present( prs, slide, partial(process_shapes, config=config, slide_id=idx + 1)) if multi_column_slide: result_slide = multi_column_slide + result_slide.is_hidden = is_hidden + result_slide.original_index = idx + 1 else: - result_slide = GeneralSlide(elements=process_shapes(config, shapes, idx + 1)) + result_slide = GeneralSlide(elements=process_shapes(config, shapes, idx + 1), is_hidden=is_hidden, original_index=idx + 1) if not config.disable_notes and slide.has_notes_slide: text = slide.notes_slide.notes_text_frame.text diff --git a/pptx2md/types.py b/pptx2md/types.py index 0de9e4f..63c2079 100644 --- a/pptx2md/types.py +++ b/pptx2md/types.py @@ -81,6 +81,12 @@ class ConversionConfig(BaseModel): keep_similar_titles: bool = False """Keep similar titles (allow for repeated slide titles - One or more - Add (cont.) to the title)""" + slide_visibility: bool = False + """Show slide visibility status () in the output""" + + skip_hidden: bool = False + """Skip hidden slides in the output (preserves original slide numbering)""" + class ElementType(str, Enum): Title = "Title" @@ -158,12 +164,20 @@ class MultiColumnSlide(BaseModel): preface: List[SlideElement] columns: List[SlideElement] notes: List[str] = [] + is_hidden: bool = False + """Whether this slide is hidden in the presentation""" + original_index: int = 0 + """Original 1-based slide index in the presentation""" class GeneralSlide(BaseModel): type: SlideType = SlideType.General elements: List[SlideElement] notes: List[str] = [] + is_hidden: bool = False + """Whether this slide is hidden in the presentation""" + original_index: int = 0 + """Original 1-based slide index in the presentation""" Slide = Union[GeneralSlide, MultiColumnSlide]