Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement simplelist attributes #96

Merged
merged 5 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading