Skip to content

Commit

Permalink
Move whitespace formatting to generic XHTML format (#95)
Browse files Browse the repository at this point in the history
Co-authored-by: haszi <[email protected]>
  • Loading branch information
haszi and haszi authored Feb 13, 2024
1 parent 2f71e8e commit 27e3bc3
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 24 deletions.
36 changes: 36 additions & 0 deletions phpdotnet/phd/Package/Generic/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -2088,6 +2088,42 @@ public function format_keycombo($open, $name, $attrs, $props) {
return '</kbd>';
}

public function format_whitespace($whitespace, $elementStack, $currentDepth) {
/* The following if is to skip unnecessary whitespaces in the parameter list */
if (
in_array($elementStack[$currentDepth - 1], ['methodsynopsis', 'constructorsynopsis', 'destructorsynopsis'], true)
&& (in_array($elementStack[$currentDepth] ?? "", ["methodname", "methodparam", "type", "void"], true)
|| count($elementStack) === $currentDepth)
) {
return false;
}

/* The following if is to skip whitespace before closing semicolon after property/class constant */
if ($elementStack[$currentDepth - 1] === "fieldsynopsis" && (in_array($elementStack[$currentDepth], ["varname", "initializer"], true))) {
return false;
}

/*
TODO: add trim() in type_text handling method and remove the below
as it doesn't work due to XMLReader including all whitespace
inside the tag in the text
hence no separate significant whitespace here
*/
/* The following if is to skip whitespace inside type elements */
if ($elementStack[$currentDepth - 1] === "type") {
return false;
}

/* The following if is to skip unnecessary whitespaces in the implements list */
if (
($elementStack[$currentDepth - 1] === 'classsynopsisinfo' && $elementStack[$currentDepth] === 'oointerface') ||
($elementStack[$currentDepth - 1] === 'oointerface' && $elementStack[$currentDepth] === 'interfacename')
) {
return false;
}

return $whitespace;
}

}

Expand Down
32 changes: 8 additions & 24 deletions phpdotnet/phd/Render.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,33 +176,17 @@ public function execute(Reader $r) { /* {{{ */
case \XMLReader::WHITESPACE: /* {{{ */
case \XMLReader::SIGNIFICANT_WHITESPACE:

/* The following if is to skip unnecessary whitespaces in the parameter list */
if (in_array($this->STACK[$r->depth - 1], ['methodsynopsis', 'constructorsynopsis', 'destructorsynopsis'], true) &&
in_array($this->STACK[$r->depth] ?? "", ["methodname", "methodparam", "type", "void"], true)
) {
break;
}

/* The following if is to skip whitespace before closing semicolon after property/class constant */
if ($this->STACK[$r->depth - 1] === "fieldsynopsis" && (in_array($this->STACK[$r->depth], ["varname", "initializer"], true))) {
break;
}
$retval = $r->value;
foreach($this as $format) {

/* The following if is to skip whitespace inside type elements */
if ($this->STACK[$r->depth - 1] === "type") {
break;
}
if (method_exists($format, 'format_whitespace')) {
$retval = $format->format_whitespace($retval, $this->STACK, $r->depth);

/* The following if is to skip unnecessary whitespaces in the implements list */
if (
($this->STACK[$r->depth - 1] === 'classsynopsisinfo' && $this->STACK[$r->depth] === 'oointerface') ||
($this->STACK[$r->depth - 1] === 'oointerface' && $this->STACK[$r->depth] === 'interfacename')
) {
break;
}
if ($retval === false) {
continue;
}
}

$retval = $r->value;
foreach($this as $format) {
$format->appendData($retval);
}
break;
Expand Down
59 changes: 59 additions & 0 deletions tests/xhtml/data/whitespace_formatting_001.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<chapter xml:id="whitespace-formatting-001">

<section>
<para>1. Function/method with whitespace between name, parameters and return types</para>
<methodsynopsis>
<type class="union"><type>int</type><type>float</type><type>false</type></type>
<methodname>function_name</methodname>
<methodparam><type class="union"><type>iterable</type><type>resource</type><type>callable</type><type>null</type></type><parameter>option</parameter></methodparam>
</methodsynopsis>
</section>

<section>
<para>2. Constructor with whitespace between name, parameters and return types</para>
<constructorsynopsis>
<modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname>
<methodparam><type class="union"><type>iterable</type><type>resource</type><type>callable</type><type>null</type></type><parameter>option</parameter></methodparam>
<void/>
</constructorsynopsis>
</section>

<section>
<para>3. Destructor with whitespace between name, parameters and return types</para>
<destructorsynopsis>
<modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname>
<methodparam><type class="union"><type>iterable</type><type>resource</type><type>callable</type><type>null</type></type><parameter>option</parameter></methodparam>
<void/>
</destructorsynopsis>
</section>

<section>
<para>4. Class constant with whitespace after varname and initializer</para>
<fieldsynopsis>
<modifier>const</modifier>
<type>int</type>
<varname>CONSTANT_NAME</varname>
<initializer>1</initializer>
</fieldsynopsis>
</section>

<section>
<para>5. Implements list with whitespace</para>
<classsynopsisinfo>
<ooclass>
<classname>SomeClass</classname>
</ooclass>
<oointerface>
<interfacename>FirstInterface</interfacename>
</oointerface>
<oointerface>
<interfacename>SecondInterface</interfacename>
</oointerface>
<oointerface>
<interfacename>ThirdInterface</interfacename>
</oointerface>
</classsynopsisinfo>
</section>

</chapter>
76 changes: 76 additions & 0 deletions tests/xhtml/whitespace_formatting_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
--TEST--
Whitespace formatting 001
--FILE--
<?php
namespace phpdotnet\phd;

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

$formatclass = "TestChunkedXHTML";
$xml_file = __DIR__ . "/data/whitespace_formatting_001.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();
?>
--EXPECT--
Filename: whitespace-formatting-001.html
Content:
<div id="whitespace-formatting-001" class="chapter">

<div class="section">
<p class="para">1. Function/method with whitespace between name, parameters and return types</p>
<div class="methodsynopsis dc-description"><span class="type"><span class="type">int</span><span class="type">float</span><span class="type">false</span></span> <span class="methodname">function_name</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>)</div>

</div>

<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>

<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>

<div class="section">
<p class="para">4. Class constant with whitespace after varname and initializer</p>
<div class="fieldsynopsis">
<span class="modifier">const</span>
<span class="type">int</span>
<var class="fieldsynopsis_varname">CONSTANT_NAME</var><span class="initializer"> = 1</span>;</div>

</div>

<div class="section">
<p class="para">5. Implements list with whitespace</p>
<div class="classsynopsisinfo">
<span class="ooclass">
<span class="modifier">class</span> SomeClass
</span>
<span class="oointerface"><span class="modifier">implements</span>
FirstInterface</span><span class="oointerface">, SecondInterface</span><span class="oointerface">, ThirdInterface</span> {</div>
</div>

</div>

0 comments on commit 27e3bc3

Please sign in to comment.