Skip to content
Open
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
20 changes: 20 additions & 0 deletions phpdotnet/phd/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,26 @@ public function rowspan($attrs) {
}
/* }}} */

/**
* Trim whitespace from a tag value and emit a warning if whitespace was found.
*
* @param string $value The value to trim
* @param string $tagName The name of the tag for the warning message
*
* @return string The trimmed value
*/
public static function trimValue(string $value, string $tagName): string
{
$trimmed = trim($value);
if ($trimmed !== $value) {
trigger_error(
"Whitespace found in <$tagName> tag content, this should be fixed in the XML source",
E_USER_WARNING,
);
}
return $trimmed;
}

/**
* Highlight (color) the given piece of source code
*
Expand Down
1 change: 1 addition & 0 deletions phpdotnet/phd/Package/PEAR/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,7 @@ public function format_refname_text($value, $tag)

public function format_function_text($value)
{
$value = Format::trimValue($value, 'function');
return $this->TEXT($value.'()');
}

Expand Down
10 changes: 9 additions & 1 deletion phpdotnet/phd/Package/PHP/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,14 @@ public function format_fieldsynopsis_varname($open, $name, $attrs) {
}

public function format_varname_text($value, $tag) {
$value = Format::trimValue($value, $tag);
$var = $value;
if (($pos = strpos($value, "[")) !== false) {
$var = substr($value, 0, $pos);
}
if (($filename = $this->getVarnameLink($var)) !== null && !in_array($var, $this->cchunk["refname"])) {
$href = $this->chunked ? $filename.$this->ext : "#$filename";
return '<var class="varname"><a href="'.$href.'" class="classname">' .$value. '</a></var>';
return '<var class="varname"><a href="'.$href.'" class="varname">' .$value. '</a></var>';
}
return '<var class="varname">' .$value. '</var>';

Expand Down Expand Up @@ -678,6 +679,7 @@ public function format_type_methodparam_text($type, $tagname) {
}

public function format_type_text($type, $tagname) {
$type = Format::trimValue($type, $tagname);
$t = strtr($this->normalizeFQN($type), ["_" => "-", "\\" => "-"]);

switch($t) {
Expand Down Expand Up @@ -805,6 +807,7 @@ public function format_acronym_text($value, $tag) {
}

public function format_classsynopsis_fieldsynopsis_varname_text($value, $tag) {
$value = Format::trimValue($value, $tag);
if ($this->cchunk["classsynopsis"]["classname"]) {
if (strpos($value, "::") === false && strpos($value, "->") === false) {
$value = $this->cchunk["classsynopsis"]["classname"] . "->" . $value;
Expand All @@ -815,6 +818,7 @@ public function format_classsynopsis_fieldsynopsis_varname_text($value, $tag) {
return $this->format_varname_text($display_value, $tag);
}
public function format_classsynopsis_methodsynopsis_methodname_text($value, $tag) {
$value = Format::trimValue($value, $tag);
if ($this->cchunk["classsynopsis"]["classname"]) {
if (strpos($value, "::") === false && strpos($value, "->") === false) {
$value = $this->cchunk["classsynopsis"]["classname"] . "::" . $value;
Expand Down Expand Up @@ -845,6 +849,8 @@ public function format_function_text($value, $tag, $display_value = null) {
return $this->TEXT($value);
}

$value = Format::trimValue($value, $tag);

static $non_functions = array(
"echo" => true, "print" => true,
"include" => true, "include_once" => true,
Expand Down Expand Up @@ -907,6 +913,7 @@ public function format_classsynopsis_oo_name_text($value, $tag) {
}

public function format_classname_text($value, $tag) {
$value = Format::trimValue($value, $tag);
if (($filename = $this->getClassnameLink($this->normalizeFQN($value))) !== null && $this->cchunk["class_name_ref"] !== strtolower($value)) {
$href = $this->chunked ? $filename.$this->ext : "#$filename";
return '<a href="'.$href. '" class="' .$tag. '">' .$value. '</a>';
Expand All @@ -915,6 +922,7 @@ public function format_classname_text($value, $tag) {
}

public function format_enumidentifier_text($value, $tag) {
$value = Format::trimValue($value, $tag);
if (!str_contains($value, '::')) {
return $value;
}
Expand Down
40 changes: 40 additions & 0 deletions tests/package/php/data/whitespace_in_tags_link_rendering.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="whitespace_in_tags_link_rendering" xmlns="http://docbook.org/ns/docbook">

<section>
<para>1. Function with leading/trailing whitespace</para>
<para>
<function>
strlen
</function>
</para>
</section>

<section>
<para>2. Methodname with leading/trailing whitespace</para>
<para>
<methodname>
Extension\Namespace\Classname::existingMethodName
</methodname>
</para>
</section>

<section>
<para>3. Classname with leading/trailing whitespace</para>
<para>
<classname>
Extension\Namespace\Existing_Class
</classname>
</para>
</section>

<section>
<para>4. Varname with leading/trailing whitespace</para>
<para>
<varname>
_SERVER
</varname>
</para>
</section>

</chapter>
99 changes: 99 additions & 0 deletions tests/package/php/whitespace_in_tags_link_rendering.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
--TEST--
GH-80 Whitespace in function/method/class tags should not break link resolution
--FILE--
<?php
namespace phpdotnet\phd;

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

$config->xmlFile = __DIR__ . "/data/whitespace_in_tags_link_rendering.xml";

$indices = [
[
"docbook_id" => "function.strlen",
"filename" => "function.strlen",
],
[
"docbook_id" => "class.extension-namespace-existing-class",
"filename" => "extensionname.classpage",
"element" => "phpdoc:classref",
],
[
"docbook_id" => "extension-namespace-classname.existingmethodname",
"filename" => "extension-namespace-classname.methodpage",
],
[
"docbook_id" => "reserved.variables.server",
"filename" => "reserved.variables.server",
],
];

$format = new TestPHPChunkedXHTML($config, $outputHandler);

foreach ($indices as $index) {
$format->SQLiteIndex(
null, // $context,
null, // $index,
$index["docbook_id"] ?? "", // $id,
$index["filename"] ?? "", // $filename,
$index["parent_id"] ?? "", // $parent,
$index["sdesc"] ?? "", // $sdesc,
$index["ldesc"] ?? "", // $ldesc,
$index["element"] ?? "", // $element,
$index["previous"] ?? "", // $previous,
$index["next"] ?? "", // $next,
$index["chunk"] ?? 0, // $chunk
);
}

$format->addRefname("function.strlen", "strlen");
$format->addClassname("class.extension-namespace-existing-class", "extension\\namespace\\existing_class");
$format->addRefname("extension-namespace-classname.methodpage", "extension\\namespace\\classname::existingmethodname");
$format->addVarname("reserved.variables.server", "_SERVER");

$render = new TestRender(new Reader($outputHandler), $config, $format);

$render->run();
?>
--EXPECTF--
%s
Whitespace found in <function> tag content, this should be fixed in the XML source
%s
Whitespace found in <methodname> tag content, this should be fixed in the XML source
%s
Whitespace found in <classname> tag content, this should be fixed in the XML source
%s
Whitespace found in <varname> tag content, this should be fixed in the XML source
Filename: whitespace_in_tags_link_rendering.html
Content:
<div id="whitespace_in_tags_link_rendering" class="chapter">

<div class="section">
<p class="para">1. Function with leading/trailing whitespace</p>
<p class="para">
<span class="function"><a href="function.strlen.html" class="function">strlen()</a></span>
</p>
</div>

<div class="section">
<p class="para">2. Methodname with leading/trailing whitespace</p>
<p class="para">
<span class="methodname"><a href="extension-namespace-classname.methodpage.html" class="methodname">Extension\Namespace\Classname::existingMethodName()</a></span>
</p>
</div>

<div class="section">
<p class="para">3. Classname with leading/trailing whitespace</p>
<p class="para">
<span class="classname"><a href="class.extension-namespace-existing-class.html" class="classname">Extension\Namespace\Existing_Class</a></span>
</p>
</div>

<div class="section">
<p class="para">4. Varname with leading/trailing whitespace</p>
<p class="para">
<var class="varname"><a href="reserved.variables.server.html" class="varname">_SERVER</a></var>
</p>
</div>

</div>