Skip to content

Commit 4883295

Browse files
committed
Only delete empty paragraphs if they are really useless.
Paragraphs used for a pagebreak or changing page format may not be deleted. Fixes #58. To decide if an empty paragraph may be deleted or not the style-name is being checked. If the style name references a pagebreak style or a page format style, then the paragraph is not deleted. All style-names that prevent deletion of empty paragraphs are listed in the array $preventDeletetionStyles []. If further paragraph styles - which may not be deleted - are added in the future, then they just need to be added to the array to prevent unwanted deletion.
1 parent 9c12f1e commit 4883295

File tree

1 file changed

+74
-2
lines changed

1 file changed

+74
-2
lines changed

renderer/page.php

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class renderer_plugin_odt_page extends Doku_Renderer {
6969
protected $page = null;
7070
/** @var Array of used page styles. Will stay empty if only A4-portrait is used */
7171
protected $page_styles = array ();
72+
/** @var Array of paragraph style names that prevent an empty paragraph from being deleted */
73+
protected $preventDeletetionStyles = array ();
7274
/** @var refIDCount */
7375
protected $refIDCount = 0;
7476

@@ -341,17 +343,84 @@ public function setPageFormat ($format, $orientation, $margin_top=2, $margin_rig
341343
$style_name = $this->factory->createParagraphStyle($style_content, $properties);
342344
$this->autostyles [$style_name] = $style_content;
343345

346+
// Save paragraph style name in 'Do not delete array'!
347+
$this->preventDeletetionStyles [] = $style_name;
348+
344349
// Open paragraph with new style format
345350
$this->p_close();
346351
$this->p_open ($style_name);
347352
}
348353

354+
/**
355+
* This function deletes the useless elements. Right now, these are empty paragraphs
356+
* or paragraphs that only include whitespace.
357+
*
358+
* IMPORTANT:
359+
* Paragraphs can be used for pagebreaks/changing page format.
360+
* Such paragraphs may not be deleted!
361+
*/
362+
protected function deleteUselessElements() {
363+
$length_open = strlen ('<text:p>');
364+
$length_close = strlen ('</text:p>');
365+
$max = strlen ($this->doc);
366+
$pos = 0;
367+
368+
while ($pos < $max) {
369+
$start_open = strpos ($this->doc, '<text:p', $pos);
370+
if ( $start_open === false ) {
371+
break;
372+
}
373+
$start_close = strpos ($this->doc, '>', $start_open + $length_open);
374+
if ( $start_close === false ) {
375+
break;
376+
}
377+
$end = strpos ($this->doc, '</text:p>', $start_close + 1);
378+
if ( $end === false ) {
379+
break;
380+
}
381+
382+
$deleted = false;
383+
$length = $end - $start_open + $length_close;
384+
$content = substr ($this->doc, $start_close + 1, $end - ($start_close + 1));
385+
386+
if ( empty($content) || ctype_space ($content) ) {
387+
// Paragraph is empty or consists of whitespace only. Check style name.
388+
$style_start = strpos ($this->doc, '"', $start_open);
389+
if ( $style_start === false ) {
390+
// No '"' found??? Ignore this paragraph.
391+
break;
392+
}
393+
$style_end = strpos ($this->doc, '"', $style_start+1);
394+
if ( $style_end === false ) {
395+
// No '"' found??? Ignore this paragraph.
396+
break;
397+
}
398+
$style_name = substr ($this->doc, $style_start+1, $style_end - ($style_start+1));
399+
400+
// Only delete empty paragraph if not listed in 'Do not delete' array!
401+
if ( !in_array($style_name, $this->preventDeletetionStyles) )
402+
{
403+
$this->doc = substr_replace($this->doc, '', $start_open, $length);
404+
405+
$deleted = true;
406+
$max -= $length;
407+
$pos = $start_open;
408+
}
409+
}
410+
411+
if ( $deleted == false ) {
412+
$pos = $start_open + $length;
413+
}
414+
}
415+
}
416+
349417
/**
350418
* Completes the ODT file
351419
*/
352420
public function finalize_ODTfile() {
353-
// Delete paragraphs which only contain whitespace
354-
$this->doc = preg_replace('#<text:p[^>]*>\s*</text:p>#', '', $this->doc);
421+
// Delete paragraphs which only contain whitespace (but keep pagebreaks!)
422+
$this->deleteUselessElements();
423+
355424
// Build the document
356425
$this->docHandler->build($this->doc,
357426
$this->_odtAutoStyles(),
@@ -826,6 +895,9 @@ function linebreak() {
826895
protected function createPagebreakStyle() {
827896
if ( empty ($this->autostyles['pagebreak']) ) {
828897
$this->autostyles['pagebreak'] = '<style:style style:name="pagebreak" style:family="paragraph"><style:paragraph-properties fo:break-before="page"/></style:style>';
898+
899+
// Save paragraph style name in 'Do not delete array'!
900+
$this->preventDeletetionStyles [] = 'pagebreak';
829901
}
830902
}
831903

0 commit comments

Comments
 (0)