mirror of
https://github.com/mfontanini/presenterm.git
synced 2025-05-05 15:32:58 +00:00
feat: allow letting pauses become new slides when exporting (#557)
Some checks failed
Deploy docs / build-and-deploy (push) Has been cancelled
Merge checks / Checks (push) Has been cancelled
Merge checks / Validate nix flake (push) Has been cancelled
Merge checks / Validate bat assets (push) Has been cancelled
Merge checks / Validate JSON schemas (push) Has been cancelled
Some checks failed
Deploy docs / build-and-deploy (push) Has been cancelled
Merge checks / Checks (push) Has been cancelled
Merge checks / Validate nix flake (push) Has been cancelled
Merge checks / Validate bat assets (push) Has been cancelled
Merge checks / Validate JSON schemas (push) Has been cancelled
This introduces the config property `export.pauses` which when defaults to `ignore` but when set to `new_slide` causes the PDF export to contain a new slide every time a pause is found. Closes #555
This commit is contained in:
commit
0c2f7ee945
@ -133,6 +133,14 @@
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pauses": {
|
||||
"description": "Whether pauses should create new slides.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PauseExportPolicy"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@ -495,6 +503,25 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"PauseExportPolicy": {
|
||||
"description": "The policy for pauses when exporting.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Whether to ignore pauses.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"ignore"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Create a new slide when a pause is found.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"new_slide"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"SlideTransitionConfig": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
@ -497,6 +497,22 @@ impl Default for SpeakerNotesConfig {
|
||||
pub struct ExportConfig {
|
||||
/// The dimensions to use for presentation exports.
|
||||
pub dimensions: Option<ExportDimensionsConfig>,
|
||||
|
||||
/// Whether pauses should create new slides.
|
||||
#[serde(default)]
|
||||
pub pauses: PauseExportPolicy,
|
||||
}
|
||||
|
||||
/// The policy for pauses when exporting.
|
||||
#[derive(Clone, Debug, Default, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields, rename_all = "snake_case")]
|
||||
pub enum PauseExportPolicy {
|
||||
/// Whether to ignore pauses.
|
||||
#[default]
|
||||
Ignore,
|
||||
|
||||
/// Create a new slide when a pause is found.
|
||||
NewSlide,
|
||||
}
|
||||
|
||||
/// The dimensions to use for presentation exports.
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
MarkdownParser, Resources,
|
||||
code::execute::SnippetExecutor,
|
||||
config::KeyBindingsConfig,
|
||||
config::{KeyBindingsConfig, PauseExportPolicy},
|
||||
export::pdf::PdfRender,
|
||||
markdown::{parse::ParseError, text_style::Color},
|
||||
presentation::{
|
||||
@ -81,10 +81,15 @@ impl<'a> Exporter<'a> {
|
||||
themes: Themes,
|
||||
mut options: PresentationBuilderOptions,
|
||||
mut dimensions: WindowSize,
|
||||
pause_policy: PauseExportPolicy,
|
||||
) -> Self {
|
||||
// We don't want dynamically highlighted code blocks.
|
||||
options.allow_mutations = false;
|
||||
options.theme_options.font_size_supported = true;
|
||||
options.pause_create_new_slide = match pause_policy {
|
||||
PauseExportPolicy::Ignore => false,
|
||||
PauseExportPolicy::NewSlide => true,
|
||||
};
|
||||
|
||||
// Make sure we have a 1:2 aspect ratio.
|
||||
let width = (0.5 * dimensions.columns as f64) / (dimensions.rows as f64 / dimensions.height as f64);
|
||||
@ -130,6 +135,7 @@ impl<'a> Exporter<'a> {
|
||||
let mut render = PdfRender::new(self.dimensions, output_directory);
|
||||
Self::log("waiting for images to be generated and code to be executed, if any...")?;
|
||||
Self::render_async_images(&mut presentation);
|
||||
|
||||
for (index, slide) in presentation.into_slides().into_iter().enumerate() {
|
||||
let index = index + 1;
|
||||
Self::log(&format!("processing slide {index}..."))?;
|
||||
|
@ -282,6 +282,7 @@ impl CoreComponents {
|
||||
theme_options: ThemeOptions { font_size_supported: TerminalEmulator::capabilities().font_size },
|
||||
pause_before_incremental_lists: config.defaults.incremental_lists.pause_before.unwrap_or(true),
|
||||
pause_after_incremental_lists: config.defaults.incremental_lists.pause_after.unwrap_or(true),
|
||||
pause_create_new_slide: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,6 +416,7 @@ fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
|
||||
themes,
|
||||
builder_options,
|
||||
dimensions,
|
||||
config.export.pauses,
|
||||
);
|
||||
let output_directory = match cli.export_temporary_path {
|
||||
Some(path) => OutputDirectory::external(path),
|
||||
|
@ -71,6 +71,7 @@ pub struct PresentationBuilderOptions {
|
||||
pub theme_options: ThemeOptions,
|
||||
pub pause_before_incremental_lists: bool,
|
||||
pub pause_after_incremental_lists: bool,
|
||||
pub pause_create_new_slide: bool,
|
||||
}
|
||||
|
||||
impl PresentationBuilderOptions {
|
||||
@ -111,6 +112,7 @@ impl Default for PresentationBuilderOptions {
|
||||
theme_options: ThemeOptions { font_size_supported: false },
|
||||
pause_before_incremental_lists: true,
|
||||
pause_after_incremental_lists: true,
|
||||
pause_create_new_slide: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -608,6 +610,12 @@ impl<'a> PresentationBuilder<'a> {
|
||||
}
|
||||
|
||||
fn push_pause(&mut self) {
|
||||
if self.options.pause_create_new_slide {
|
||||
let operations = self.chunk_operations.clone();
|
||||
self.terminate_slide();
|
||||
self.chunk_operations = operations;
|
||||
return;
|
||||
}
|
||||
self.slide_state.last_chunk_ended_in_list = matches!(self.slide_state.last_element, LastElement::List { .. });
|
||||
|
||||
let chunk_operations = mem::take(&mut self.chunk_operations);
|
||||
@ -1736,6 +1744,18 @@ theme:
|
||||
assert_eq!(slides[0].iter_chunks().count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pause_new_slide() {
|
||||
let elements = vec![
|
||||
MarkdownElement::Paragraph(vec![Line::from("hi")]),
|
||||
MarkdownElement::Comment { comment: "pause".into(), source_position: Default::default() },
|
||||
MarkdownElement::Paragraph(vec![Line::from("bye")]),
|
||||
];
|
||||
let options = PresentationBuilderOptions { pause_create_new_slide: true, ..Default::default() };
|
||||
let slides = build_presentation_with_options(elements, options).into_slides();
|
||||
assert_eq!(slides.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_slide() {
|
||||
let elements = vec![
|
||||
|
@ -298,7 +298,7 @@ impl Slide {
|
||||
self.current_chunk().reset_mutations();
|
||||
}
|
||||
|
||||
fn show_all_chunks(&mut self) {
|
||||
pub(crate) fn show_all_chunks(&mut self) {
|
||||
self.visible_chunks = self.chunks.len();
|
||||
for chunk in &self.chunks {
|
||||
chunk.apply_all_mutations();
|
||||
|
Loading…
x
Reference in New Issue
Block a user