|
25 | 25 | class renderer_plugin_odt_page extends Doku_Renderer { |
26 | 26 | /** @var array store the table of contents */ |
27 | 27 | protected $toc = array(); |
| 28 | + /** @var array store the bookmarks */ |
| 29 | + protected $bookmarks = array(); |
28 | 30 | /** @var array store the table of contents */ |
29 | 31 | public $toc_settings = 'leader-sign=.;'; |
30 | 32 | /** @var export mode (scratch or ODT template) */ |
@@ -252,6 +254,8 @@ function document_start() { |
252 | 254 | header('Content-Type: application/vnd.oasis.opendocument.text'); |
253 | 255 | header('Content-Disposition: attachment; filename="'.$output_filename.'";'); |
254 | 256 | } |
| 257 | + |
| 258 | + $this->insert_bookmark($ID); |
255 | 259 | } |
256 | 260 |
|
257 | 261 | /** |
@@ -716,6 +720,18 @@ function p_close(){ |
716 | 720 | } |
717 | 721 | } |
718 | 722 |
|
| 723 | + /** |
| 724 | + * Insert a bookmark. |
| 725 | + * |
| 726 | + * @param string $id ID of the bookmark |
| 727 | + */ |
| 728 | + function insert_bookmark($id){ |
| 729 | + $this->p_open(); |
| 730 | + $this->doc .= '<text:bookmark text:name="'.$id.'"/>'; |
| 731 | + $this->p_close(); |
| 732 | + $this->bookmarks [] = $id; |
| 733 | + } |
| 734 | + |
719 | 735 | /** |
720 | 736 | * Render a heading |
721 | 737 | * |
@@ -1436,34 +1452,98 @@ function externallink($url, $name = NULL) { |
1436 | 1452 | */ |
1437 | 1453 | protected function insert_locallinks() { |
1438 | 1454 | $matches = array(); |
1439 | | - if ( preg_match('/<locallink>.+<\/locallink>/', $this->doc, $matches) === 1 ) { |
1440 | | - foreach ($matches as $match) { |
1441 | | - $text = substr ($match, 11); |
1442 | | - $text = str_replace ('</locallink>', '', $text); |
1443 | | - $page = str_replace (' ', '_', $text); |
1444 | | - |
1445 | | - $found = false; |
1446 | | - foreach ($this->toc as $item) { |
1447 | | - $params = explode (',', $item); |
1448 | | - if ( $page == $params [1] ) { |
| 1455 | + $position = 0; |
| 1456 | + $max = strlen ($this->doc); |
| 1457 | + $length = strlen ('<locallink>'); |
| 1458 | + $length_with_name = strlen ('<locallink name='); |
| 1459 | + while ( $position < $max ) { |
| 1460 | + $first = strpos ($this->doc, '<locallink', $position); |
| 1461 | + if ( $first === false ) { |
| 1462 | + break; |
| 1463 | + } |
| 1464 | + $end_first = strpos ($this->doc, '>', $first); |
| 1465 | + if ( $end_first === false ) { |
| 1466 | + break; |
| 1467 | + } |
| 1468 | + $second = strpos ($this->doc, '</locallink>', $end_first); |
| 1469 | + if ( $second === false ) { |
| 1470 | + break; |
| 1471 | + } |
| 1472 | + |
| 1473 | + // $match includes the whole tag '<locallink name="...">text</locallink>' |
| 1474 | + // The attribute 'name' is optional! |
| 1475 | + $match = substr ($this->doc, $first, $second - $first + $length + 1); |
| 1476 | + $text = substr ($match, $end_first-$first+1, -($length + 1)); |
| 1477 | + $page = str_replace (' ', '_', $text); |
| 1478 | + $opentag = substr ($match, 0, $end_first-$first); |
| 1479 | + $name = substr ($opentag, $length_with_name); |
| 1480 | + $name = trim ($name, '">'); |
| 1481 | + |
| 1482 | + $found = false; |
| 1483 | + foreach ($this->toc as $item) { |
| 1484 | + $params = explode (',', $item); |
| 1485 | + if ( $page == $params [1] ) { |
| 1486 | + $found = true; |
| 1487 | + $link = '<text:a xlink:type="simple" xlink:href="#'.$params [0].'">'; |
| 1488 | + $link .= $text; |
| 1489 | + $link .= '</text:a>'; |
| 1490 | + |
| 1491 | + $this->doc = str_replace ($match, $link, $this->doc); |
| 1492 | + $position = $first + strlen ($link); |
| 1493 | + } |
| 1494 | + } |
| 1495 | + |
| 1496 | + if ( $found == false ) { |
| 1497 | + // Nothing found yet, check the bookmarks too. |
| 1498 | + foreach ($this->bookmarks as $item) { |
| 1499 | + if ( $page == $item ) { |
1449 | 1500 | $found = true; |
1450 | | - $link = '<text:a xlink:type="simple" xlink:href="#'.$params [0].'">'; |
1451 | | - $link .= $text; |
| 1501 | + $link = '<text:a xlink:type="simple" xlink:href="#'.$item.'">'; |
| 1502 | + if ( !empty($name) ) { |
| 1503 | + $link .= $name; |
| 1504 | + } else { |
| 1505 | + $link .= $text; |
| 1506 | + } |
1452 | 1507 | $link .= '</text:a>'; |
1453 | 1508 |
|
1454 | 1509 | $this->doc = str_replace ($match, $link, $this->doc); |
| 1510 | + $position = $first + strlen ($link); |
1455 | 1511 | } |
1456 | 1512 | } |
| 1513 | + } |
1457 | 1514 |
|
1458 | | - if ( $found == false ) { |
| 1515 | + if ( $found == false ) { |
| 1516 | + // If we get here, then the referenced target was not found. |
| 1517 | + // There must be a bug manging the bookmarks or links! |
| 1518 | + // At least remove the locallink element and insert text. |
| 1519 | + if ( !empty($name) ) { |
| 1520 | + $this->doc = str_replace ($match, $name, $this->doc); |
| 1521 | + } else { |
1459 | 1522 | $this->doc = str_replace ($match, $text, $this->doc); |
1460 | 1523 | } |
| 1524 | + $position = $first + strlen ($text); |
1461 | 1525 | } |
1462 | 1526 | } |
1463 | 1527 | } |
1464 | 1528 |
|
1465 | 1529 | /** |
1466 | | - * Just print local links |
| 1530 | + * Insert local link placeholder with name. |
| 1531 | + * The reference will be resolved on calling insert_locallinks(); |
| 1532 | + * |
| 1533 | + * @fixme add image handling |
| 1534 | + * |
| 1535 | + * @param string $hash hash link identifier |
| 1536 | + * @param string $id name for the link (the reference) |
| 1537 | + * @param string $name text for the link (text inserted instead of reference) |
| 1538 | + */ |
| 1539 | + function locallink_with_name($hash, $id = NULL, $name = NULL){ |
| 1540 | + $id = $this->_getLinkTitle($id, $hash, $isImage); |
| 1541 | + $this->doc .= '<locallink name="'.$name.'">'.$id.'</locallink>'; |
| 1542 | + } |
| 1543 | + |
| 1544 | + /** |
| 1545 | + * Insert local link placeholder. |
| 1546 | + * The reference will be resolved on calling insert_locallinks(); |
1467 | 1547 | * |
1468 | 1548 | * @fixme add image handling |
1469 | 1549 | * |
|
0 commit comments