Skip to content

Commit

Permalink
Implement simplelist attributes (#96)
Browse files Browse the repository at this point in the history
Co-authored-by: haszi <haszika80@gmail.com>
Co-authored-by: Gina Peter Banyard <girgias@php.net>
  • Loading branch information
3 people authored Feb 20, 2024
1 parent 45cffd6 commit 5362fde
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 15 deletions.
141 changes: 137 additions & 4 deletions phpdotnet/phd/Package/Generic/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'methodparam' => 'format_methodparam',
'methodsynopsis' => 'format_methodsynopsis',
'methodname' => 'format_methodname',
'member' => 'li',
'member' => 'format_member',
'modifier' => 'span',
'note' => 'format_note',
'orgname' => 'span',
Expand Down Expand Up @@ -269,7 +269,7 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'setindex' => 'format_chunk',
'shortaffil' => 'format_suppressed_tags',
'sidebar' => 'format_note',
'simplelist' => 'format_itemizedlist', /* FIXME: simplelists has few attributes that need to be implemented */
'simplelist' => 'format_simplelist',
'simplesect' => 'div',
'simpara' => array(
/* DEFAULT */ 'p',
Expand Down Expand Up @@ -446,6 +446,7 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'literal' => 'format_literal_text',
'email' => 'format_email_text',
'titleabbrev' => 'format_suppressed_text',
'member' => 'format_member_text',
);

/** @var array */
Expand Down Expand Up @@ -501,6 +502,11 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
"varlistentry" => array(
"listitems" => array(),
),
"simplelist" => array(
"members" => array(),
"type" => null,
"columns" => null,
),
);

protected $pihandlers = array(
Expand Down Expand Up @@ -2040,6 +2046,126 @@ public function format_itemizedlist($open, $name, $attrs, $props) {
return '</ul>';
}

public function format_simplelist($open, $name, $attrs, $props) {
if ($open) {
$this->cchunk["simplelist"]["type"] = $attrs[Reader::XMLNS_DOCBOOK]["type"] ?? "";
$this->cchunk["simplelist"]["columns"] = $attrs[Reader::XMLNS_DOCBOOK]["columns"] ?? 1;

if ($this->cchunk["simplelist"]["columns"] < 1) {
$this->cchunk["simplelist"]["columns"] = 1;
}

if ($this->cchunk["simplelist"]["type"] === "inline") {
return '<span class="' . $name . '">';
}

if ($this->cchunk["simplelist"]["type"] === "vert"
|| $this->cchunk["simplelist"]["type"] === "horiz") {
return '<table class="' . $name . '">' . "\n" . $this->indent($props["depth"] + 1) . "<tbody>\n";
}

return '<ul class="' . $name . '">';
}

$list = match ($this->cchunk["simplelist"]["type"]) {
"inline" => $this->simplelist_format_inline(),
"horiz" => $this->simplelist_format_horizontal($props["depth"])
. $this->indent($props["depth"] + 1) . "</tbody>\n"
. $this->indent($props["depth"]) . "</table>",
"vert" => $this->simplelist_format_vertical($props["depth"])
. $this->indent($props["depth"] + 1) . "</tbody>\n"
. $this->indent($props["depth"]) . "</table>",
default => "</ul>",
};

$this->cchunk["simplelist"] = $this->dchunk["simplelist"];

return $list;
}

private function indent($depth): string {
return $depth > 0 ? str_repeat(' ', $depth) : '';
}

private function simplelist_format_inline() {
return implode(", ", $this->cchunk["simplelist"]["members"]) . '</span>';
}

private function simplelist_format_horizontal($depth) {
return $this->chunkReduceTable(
$this->processTabular(
$this->cchunk["simplelist"]["members"],
$this->cchunk["simplelist"]["columns"],
$depth),
$this->cchunk["simplelist"]["columns"],
$depth
);
}

/** Return formatted rows */
private function chunkReduceTable(array $members, int $cols, int $depth): string
{
$trPadding = $this->indent($depth + 2);
return array_reduce(
array_chunk(
$members,
$cols,
),
fn (string $carry, array $entry) => $carry . $trPadding . "<tr>\n" . implode('', $entry) . $trPadding . "</tr>\n",
''
);
}

/** Pads $members so that number of members = columns x rows */
private function processTabular(array $members, int $cols, int $depth): array
{
$tdPadding = $this->indent($depth + 3);
return array_map(
fn (string $member) => $tdPadding . "<td>$member</td>\n",
/** The padding is done by getting the additive modular inverse which is
* ``-\count($members) % $cols`` but because PHP gives us the mod in negative we need to
* add $cols back to get the positive
*/
[...$members, ...array_fill(0, (-\count($members) % $cols) + $cols, '')]
);
}

private function simplelist_format_vertical($depth) {
$members = $this->processTabular(
$this->cchunk["simplelist"]["members"],
$this->cchunk["simplelist"]["columns"],
$depth
);
// Sort elements so that we get each correct element for the rows to display vertically
uksort(
$members,
fn (int $l, int $r) => $l % $this->cchunk["simplelist"]["columns"] <=> $r % $this->cchunk["simplelist"]["columns"]
);
return $this->chunkReduceTable($members, $this->cchunk["simplelist"]["columns"], $depth);
}

public function format_member($open, $name, $attrs, $props) {
if ($this->cchunk["simplelist"]["type"] === "inline"
|| $this->cchunk["simplelist"]["type"] === "vert"
|| $this->cchunk["simplelist"]["type"] === "horiz") {
return '';
}
if ($open) {
return '<li>';
}
return '</li>';
}

public function format_member_text($value, $tag) {
if ($this->cchunk["simplelist"]["type"] === "inline"
|| $this->cchunk["simplelist"]["type"] === "vert"
|| $this->cchunk["simplelist"]["type"] === "horiz") {
$this->cchunk["simplelist"]["members"][] = $value;
return '';
}
return $value;
}

public function format_orderedlist($open, $name, $attrs, $props) {
if ($open) {
$numeration = "1";
Expand Down Expand Up @@ -2115,6 +2241,15 @@ public function format_whitespace($whitespace, $elementStack, $currentDepth) {
return false;
}

if (
$elementStack[$currentDepth - 1] === "simplelist"
&& ($this->cchunk["simplelist"]["type"] === "inline"
|| $this->cchunk["simplelist"]["type"] === "vert"
|| $this->cchunk["simplelist"]["type"] === "horiz")
) {
return false;
}

/* The following if is to skip unnecessary whitespaces in the implements list */
if (
($elementStack[$currentDepth - 1] === 'classsynopsisinfo' && $elementStack[$currentDepth] === 'oointerface') ||
Expand All @@ -2127,5 +2262,3 @@ public function format_whitespace($whitespace, $elementStack, $currentDepth) {
}

}


3 changes: 0 additions & 3 deletions phpdotnet/phd/Render.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,3 @@ public function execute(Reader $r) { /* {{{ */
} /* }}} */

}



3 changes: 1 addition & 2 deletions tests/php/type_rendering_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ Content:

<div class="section">
<p class="para">1. Function/method with no return type</p>
<div class="methodsynopsis dc-description">
<span class="methodname"><strong>function_name</strong></span>()</div>
<div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>()</div>

</div>

Expand Down
3 changes: 1 addition & 2 deletions tests/php/type_rendering_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ Content:

<div class="section">
<p class="para">1. Function/method with no parameters</p>
<div class="methodsynopsis dc-description">
<span class="methodname"><strong>function_name</strong></span>()</div>
<div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>()</div>

</div>

Expand Down
3 changes: 1 addition & 2 deletions tests/php/type_rendering_003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ Content:

<div class="section">
<p class="para">1. Constructor with no parameters, no return type</p>
<div class="constructorsynopsis dc-description">
<span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>()</div>
<div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>()</div>

</div>

Expand Down
56 changes: 56 additions & 0 deletions tests/xhtml/data/simplelist.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<chapter xml:id="simpelist" xmlns="http://docbook.org/ns/docbook">

<section>
<para>1. Simplelist with no type</para>
<simplelist>
<member>First</member>
<member>Second</member>
<member>Third</member>
<member>Fourth</member>
<member>Fifth</member>
<member>Sixth</member>
<member>Seventh</member>
</simplelist>
</section>

<section>
<para>2. Simplelist with "inline" type</para>
<simplelist type="inline">
<member>First</member>
<member>Second</member>
<member>Third</member>
<member>Fourth</member>
<member>Fifth</member>
<member>Sixth</member>
<member>Seventh</member>
</simplelist>
</section>

<section>
<para>3. Simplelist with "vert" type, 3 columns</para>
<simplelist type="vert" columns="3">
<member>First</member>
<member>Second</member>
<member>Third</member>
<member>Fourth</member>
<member>Fifth</member>
<member>Sixth</member>
<member>Seventh</member>
</simplelist>
</section>

<section>
<para>4. Simplelist with "horiz" type, 4 columns</para>
<simplelist type="horiz" columns="4">
<member>First</member>
<member>Second</member>
<member>Third</member>
<member>Fourth</member>
<member>Fifth</member>
<member>Sixth</member>
<member>Seventh</member>
</simplelist>
</section>

</chapter>
100 changes: 100 additions & 0 deletions tests/xhtml/simplelist_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
--TEST--
Simplelist rendering 001 - Types and columns
--FILE--
<?php
namespace phpdotnet\phd;

require_once __DIR__ . "/../setup.php";
require_once __DIR__ . "/TestChunkedXHTML.php";

$formatclass = "TestChunkedXHTML";
$xml_file = __DIR__ . "/data/simplelist.xml";

$opts = array(
"index" => true,
"xml_root" => dirname($xml_file),
"xml_file" => $xml_file,
"output_dir" => __DIR__ . "/output/",
);

$extra = array(
"lang_dir" => __PHDDIR__ . "phpdotnet/phd/data/langs/",
"phpweb_version_filename" => dirname($xml_file) . '/version.xml',
"phpweb_acronym_filename" => dirname($xml_file) . '/acronyms.xml',
);

$render = new TestRender($formatclass, $opts, $extra);

if (Index::requireIndexing() && !file_exists($opts["output_dir"])) {
mkdir($opts["output_dir"], 0755);
}

$render->run();
?>
--EXPECTF--
Filename: simpelist.html
Content:
<div id="simpelist" class="chapter">

<div class="section">
<p class="para">1. Simplelist with no type</p>
<ul class="simplelist">
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
<li>Fifth</li>
<li>Sixth</li>
<li>Seventh</li>
</ul>
</div>

<div class="section">
<p class="para">2. Simplelist with &quot;inline&quot; type</p>
<span class="simplelist">First, Second, Third, Fourth, Fifth, Sixth, Seventh</span>
</div>

<div class="section">
<p class="para">3. Simplelist with &quot;vert&quot; type, 3 columns</p>
<table class="simplelist">
<tbody>
<tr>
<td>First</td>
<td>Fourth</td>
<td>Seventh</td>
</tr>
<tr>
<td>Second</td>
<td>Fifth</td>
<td></td>
</tr>
<tr>
<td>Third</td>
<td>Sixth</td>
<td></td>
</tr>
</tbody>
</table>
</div>

<div class="section">
<p class="para">4. Simplelist with &quot;horiz&quot; type, 4 columns</p>
<table class="simplelist">
<tbody>
<tr>
<td>First</td>
<td>Second</td>
<td>Third</td>
<td>Fourth</td>
</tr>
<tr>
<td>Fifth</td>
<td>Sixth</td>
<td>Seventh</td>
<td></td>
</tr>
</tbody>
</table>
</div>

</div>
4 changes: 2 additions & 2 deletions tests/xhtml/whitespace_formatting_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ Content:

<div class="section">
<p class="para">2. Constructor with whitespace between name, parameters and return types</p>
<div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname">ClassName::__construct</span>(<span class="methodparam"><span class="type"><span class="type">iterable</span><span class="type">resource</span><span class="type">callable</span><span class="type">null</span></span> <code class="parameter">$option</code></span><span class="type"><span class="type void">void</span></span>)</div>
<div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname">ClassName::__construct</span>(<span class="methodparam"><span class="type"><span class="type">iterable</span><span class="type">resource</span><span class="type">callable</span><span class="type">null</span></span> <code class="parameter">$option</code></span><span class="type"><a href="language.types.void.html" class="type void">void</a></span>)</div>

</div>

<div class="section">
<p class="para">3. Destructor with whitespace between name, parameters and return types</p>
<div class="destructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname">ClassName::__construct</span>(<span class="methodparam"><span class="type"><span class="type">iterable</span><span class="type">resource</span><span class="type">callable</span><span class="type">null</span></span> <code class="parameter">$option</code></span><span class="type"><span class="type void">void</span></span>)</div>
<div class="destructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname">ClassName::__construct</span>(<span class="methodparam"><span class="type"><span class="type">iterable</span><span class="type">resource</span><span class="type">callable</span><span class="type">null</span></span> <code class="parameter">$option</code></span><span class="type"><a href="language.types.void.html" class="type void">void</a></span>)</div>

</div>

Expand Down

0 comments on commit 5362fde

Please sign in to comment.