Skip to content

Commit

Permalink
Enable nested roles (#103)
Browse files Browse the repository at this point in the history
* Enable nested roles

Refactor role to be an array instead of a string to allow nesting of roles.
Use the indent method to format constant list tables.
Add tests for regular, table formatted and nested role containing variablelists.

* Make role property private

Add methods to push, pop and get role, and use these for all role accesses.
Make underlying $role array private.
Add comment on $role array being a LIFO stack.

---------

Co-authored-by: haszi <haszika80@gmail.com>
  • Loading branch information
haszi and haszi authored Feb 24, 2024
1 parent 09504b8 commit 3718f2f
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 57 deletions.
21 changes: 16 additions & 5 deletions phpdotnet/phd/Format/Abstract/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
namespace phpdotnet\phd;

abstract class Format_Abstract_XHTML extends Format {
public $role = false;

/** @var array<?string> Last In First Out stack of roles */
private array $role = [];

/* XHTMLPhDFormat */
protected $openPara = 0;
Expand Down Expand Up @@ -39,14 +41,14 @@ public function UNDEF($open, $name, $attrs, $props) {
}

public function CDATA($str) {
switch($this->role) {
switch($this->getRole()) {
case '':
return '<div class="cdata"><pre>'
. htmlspecialchars($str, ENT_QUOTES, "UTF-8")
. '</pre></div>';
default:
return '<div class="' . $this->role . 'code">'
. $this->highlight(trim($str), $this->role, 'xhtml')
return '<div class="' . $this->getRole() . 'code">'
. $this->highlight(trim($str), $this->getRole(), 'xhtml')
. '</div>';
}
}
Expand Down Expand Up @@ -123,6 +125,15 @@ public function restorePara() {
}
}

}
protected function pushRole(?string $role): void {
$this->role[] = $role;
}

protected function getRole(): ?string {
return end($this->role);
}

protected function popRole(): ?string {
return array_pop($this->role);
}
}
70 changes: 33 additions & 37 deletions phpdotnet/phd/Package/Generic/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -705,29 +705,25 @@ public function format_option($open, $name, $attrs) {
if(!isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
$attrs[Reader::XMLNS_DOCBOOK]["role"] = "unknown";
}
$this->role = $role = $attrs[Reader::XMLNS_DOCBOOK]["role"];
return '<strong class="' .$name.' ' .$role. '">';
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
return '<strong class="' . $name . ' ' . $this->getRole() . '">';
}
$this->role = null;
$this->popRole();
return "</strong>";
}

public function format_literal($open, $name, $attrs)
{
if ($open) {
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
$this->role = $attrs[Reader::XMLNS_DOCBOOK]["role"];
} else {
$this->role = false;
}
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"] ?? null);
return '<code class="literal">';
}
$this->role = false;
$this->popRole();
return '</code>';
}

public function format_literal_text($value, $tag) {
switch ($this->role) {
switch ($this->getRole()) {
case 'infdec':
$value = (float)$value;
$p = strpos($value, '.');
Expand Down Expand Up @@ -930,18 +926,18 @@ public function format_refsect($open, $name, $attrs) {
if(!isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
$attrs[Reader::XMLNS_DOCBOOK]["role"] = "unknown-" . ++$role;
}
$this->role = $role = $attrs[Reader::XMLNS_DOCBOOK]["role"];
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);

if (isset($attrs[Reader::XMLNS_XML]["id"])) {
$id = $attrs[Reader::XMLNS_XML]["id"];
}
else {
$id = $name. "-" . $this->CURRENT_CHUNK . "-" . $role;
$id = $name. "-" . $this->CURRENT_CHUNK . "-" . $this->getRole();
}

return '<div class="' .$name.' ' .$role. '" id="' . $id . '">';
return '<div class="' .$name.' ' .$this->getRole(). '" id="' . $id . '">';
}
$this->role = null;
$this->popRole();
return "</div>\n";
}

Expand Down Expand Up @@ -1495,24 +1491,29 @@ public function format_step($open, $name, $attrs) {
public function format_variablelist($open, $name, $attrs, $props) {
if ($open) {
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
$this->role = $attrs[Reader::XMLNS_DOCBOOK]["role"];
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
}
$classStr = $headerStr = $idStr = '';
if (isset($attrs[Reader::XMLNS_XML]["id"])) {
$idStr = ' id="' . $attrs[Reader::XMLNS_XML]["id"] . '"';
}
if ($this->role === 'constant_list') {
if ($this->getRole() === 'constant_list') {
$tagName = 'table';
$classStr = ' class="doctable table"';
$headerStr = "\n<tr>\n<th>" . $this->autogen('Constants', $props['lang']) . "</th>\n<th>" . $this->autogen('Description', $props['lang']) . "</th>\n</tr>";
$headerStr = "\n" . $this->indent($props["depth"] + 1) . "<tr>\n"
. $this->indent($props["depth"] + 2) . "<th>"
. $this->autogen('Constants', $props['lang']) . "</th>\n"
. $this->indent($props["depth"] + 2) . "<th>"
. $this->autogen('Description', $props['lang']) . "</th>\n"
. $this->indent($props["depth"] + 1) . "</tr>";
} else {
$tagName = 'dl';
}
return '<' . $tagName . $idStr . $classStr . '>' . $headerStr;
}
$tagName = ($this->role === 'constant_list') ? 'table' : 'dl';
$this->role = false;
return "</" . $tagName . ">\n";
$tagName = ($this->getRole() === 'constant_list') ? 'table' : 'dl';
$this->popRole();
return "</" . $tagName . ">";
}
public function format_varlistentry($open, $name, $attrs) {
if ($open) {
Expand All @@ -1521,29 +1522,29 @@ public function format_varlistentry($open, $name, $attrs) {
} else {
unset($this->cchunk['varlistentry']['id']);
}
return ($this->role === 'constant_list') ? '<tr>' : '';
return ($this->getRole() === 'constant_list') ? '<tr>' : '';
}
return ($this->role === 'constant_list') ? '</tr>' : '';
return ($this->getRole() === 'constant_list') ? '</tr>' : '';
}
public function format_varlistentry_term($open, $name, $attrs, $props) {
$tagName = ($this->role === 'constant_list') ? 'td' : 'dt';
$tagName = ($this->getRole() === 'constant_list') ? 'td' : 'dt';
if ($open) {
if (isset($this->cchunk['varlistentry']['id'])) {
$id = $this->cchunk['varlistentry']['id'];
unset($this->cchunk['varlistentry']['id']);
return '<' . $tagName . ' id="' . $id . '">';
} else {
return "<" . $tagName . ">\n";
return "<" . $tagName . ">";
}
}
return "</" . $tagName . ">\n";
return "</" . $tagName . ">";
}
public function format_varlistentry_listitem($open, $name, $attrs) {
$tagName = ($this->role === 'constant_list') ? 'td' : 'dd';
$tagName = ($this->getRole() === 'constant_list') ? 'td' : 'dd';
if ($open) {
return "<" . $tagName . ">\n";
return "<" . $tagName . ">";
}
return "</" . $tagName . ">\n";
return "</" . $tagName . ">";
}
public function format_term($open, $name, $attrs, $props) {
if ($open) {
Expand Down Expand Up @@ -1586,15 +1587,10 @@ public function format_example_content($open, $name, $attrs) {
}
public function format_programlisting($open, $name, $attrs) {
if ($open) {
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
$this->role = $attrs[Reader::XMLNS_DOCBOOK]["role"];
} else {
$this->role = false;
}

$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"] ?? null);
return '<div class="example-contents">';
}
$this->role = false;
$this->popRole();
return "</div>\n";
}
public function format_programlisting_text($value, $tag) {
Expand Down Expand Up @@ -1704,9 +1700,9 @@ public function format_table_title($open, $name, $attrs, $props)
}
public function format_variablelist_title($open, $name, $attrs, $props) {
if ($open) {
return ($this->role === 'constant_list') ? "<caption><strong>" : "<strong>";
return ($this->getRole() === 'constant_list') ? "<caption><strong>" : "<strong>";
}
return ($this->role === 'constant_list') ? "</strong></caption>" : "</strong>";
return ($this->getRole() === 'constant_list') ? "</strong></caption>" : "</strong>";
}

public function format_mediaobject($open, $name, $attrs) {
Expand Down
24 changes: 10 additions & 14 deletions phpdotnet/phd/Package/PEAR/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -683,16 +683,12 @@ public function format_programlisting($open, $name, $attrs)
{
if ($open) {
$this->trim = true;
if (isset($attrs[Reader::XMLNS_DOCBOOK]['role'])) {
$this->role = $attrs[Reader::XMLNS_DOCBOOK]['role'];
} else {
$this->role = '';
}
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]['role'] ?? '');

return '<div class="'. ($this->role ? $this->role . 'code' : 'programlisting')
return '<div class="'. ($this->getRole() ? $this->getRole() . 'code' : 'programlisting')
. '">';
}
$this->role = false;
$this->popRole();
$this->trim = false;

return '</div>';
Expand All @@ -710,7 +706,7 @@ public function format_programlisting($open, $name, $attrs)
*/
public function format_programlisting_text($value, $tag)
{
switch($this->role) {
switch($this->getRole()) {
case 'php':
if (strrpos($value, '<?php') || strrpos($value, '?>')) {
return $this->highlight(trim($value), 'php', 'xhtml');
Expand All @@ -719,7 +715,7 @@ public function format_programlisting_text($value, $tag)
}
break;
default:
return $this->highlight(trim($value), $this->role, 'xhtml');
return $this->highlight(trim($value), $this->getRole(), 'xhtml');
}
}

Expand Down Expand Up @@ -760,26 +756,26 @@ public function CDATA($str)
if ($this->trim) {
$str = rtrim($str);
}
if (!$this->role) {
if (!$this->getRole()) {
return str_replace(
array("\n", ' '), array('<br/>', '&nbsp;'),
htmlspecialchars($str, ENT_QUOTES, 'UTF-8')
);
}

switch ($this->role) {
switch ($this->getRole()) {
case 'php':
if (strrpos($str, '<?php') || strrpos($str, '?>')) {
$str = $this->highlight(trim($str), $this->role, 'xhtml');
$str = $this->highlight(trim($str), $this->getRole(), 'xhtml');
} else {
$str = $this->highlight("<?php\n" . trim($str) . "\n?>", $this->role, 'xhtml');
$str = $this->highlight("<?php\n" . trim($str) . "\n?>", $this->getRole(), 'xhtml');
}
break;
case '':
$str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
break;
default:
$str = $this->highlight($str, $this->role, 'xhtml');
$str = $this->highlight($str, $this->getRole(), 'xhtml');
break;
}

Expand Down
2 changes: 1 addition & 1 deletion phpdotnet/phd/Package/PHP/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -843,7 +843,7 @@ public function format_function_text($value, $tag, $display_value = null) {
if ($filename !== null) {
if ($this->CURRENT_ID !== $filename) {
$rel = $desc = "";
if ($this->role == "seealso") {
if ($this->getRole() === "seealso") {
$rel = ' rel="rdfs-seeAlso"';
$desc = " - " . Format::getLongDescription($filename);
}
Expand Down
40 changes: 40 additions & 0 deletions tests/php/data/variablelist_rendering_001.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<chapter xml:id="variablelist-rendering">

<section>
<para>1. Variablelist with no role</para>
<variablelist>
<varlistentry xml:id="constant.variablelist-test-constant">
<term><constant>VARIABLELIST_TEST_CONSTANT</constant></term>
<listitem>
<simpara>
Description of constant
</simpara>
</listitem>
</varlistentry>
</variablelist>
</section>

<section>
<para>2. Variablelist with role="constant_list"</para>
<variablelist role="constant_list">
<varlistentry xml:id="constant.variablelist-test-constant-in-constant-list">
<term><constant>VARIABLELIST_TEST_CONSTANT_IN_CONSTANT_LIST</constant></term>
<listitem>
<simpara>
<literal>literal</literal> will add its own "role"
</simpara>
</listitem>
</varlistentry>
<varlistentry xml:id="constant.variablelist-test-constant-in-constant-list2">
<term><constant>VARIABLELIST_TEST_CONSTANT_IN_CONSTANT_LIST2</constant></term>
<listitem>
<simpara>
Role should have not been overwritten by literal
</simpara>
</listitem>
</varlistentry>
</variablelist>
</section>

</chapter>
Loading

0 comments on commit 3718f2f

Please sign in to comment.