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

Add support for rendering more logical classsynopsis markup #77

Merged
merged 2 commits into from
Jul 26, 2023
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
227 changes: 189 additions & 38 deletions phpdotnet/phd/Package/Generic/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,6 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'caution' => 'format_admonition',
'citation' => 'format_citation',
'citerefentry' => 'span',
'classname' => array(
/* DEFAULT */ 'span',
'ooclass' => array(
/* DEFAULT */ 'strong',
'classsynopsisinfo' => 'format_classsynopsisinfo_ooclass_classname',
),
),
'classsynopsis' => 'format_classsynopsis',
'classsynopsisinfo' => 'format_classsynopsisinfo',
'code' => 'code',
'collab' => 'span',
'collabname' => 'span',
Expand Down Expand Up @@ -157,22 +148,45 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
'note' => 'format_note',
'orgname' => 'span',
'othercredit' => 'format_div',
/** Class Synopsis related tags */
'classsynopsis' => 'format_classsynopsis',
'classsynopsisinfo' => 'format_classsynopsisinfo',
'ooclass' => array(
/* DEFAULT */ 'span',
'classsynopsis' => 'format_div',
'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
),
'ooexception' => [
/* DEFAULT */ 'span',
'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
],
'oointerface' => array(
/* DEFAULT */ 'span',
'classsynopsisinfo' => 'format_classsynopsisinfo_oointerface',
'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
'classsynopsisinfo' => 'format_classsynopsisinfo_oointerface',
),
'classname' => [
/* DEFAULT */ 'span',
'ooclass' => [
/* DEFAULT */ 'span',
'classsynopsis' => 'format_classsynopsis_ooclass_classname',
'classsynopsisinfo' => 'format_classsynopsisinfo_ooclass_classname',
],
],
'exceptionname' => [
/* DEFAULT */ 'span',
'ooexception' => [
/* DEFAULT */ 'span',
'classsynopsis' => 'format_classsynopsis_ooclass_classname',
],
],
'interfacename' => array(
/* DEFAULT */ 'span',
'oointerface' => array(
/* DEFAULT */ 'span',
'classsynopsis' => 'format_classsynopsis_oointerface_interfacename',
'classsynopsisinfo' => 'format_classsynopsisinfo_oointerface_interfacename',
),
),
'exceptionname' => 'span',
'option' => 'format_option',
'orderedlist' => 'format_orderedlist',
'para' => array(
Expand Down Expand Up @@ -379,13 +393,29 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
/* DEFAULT */ false,
'fieldsynopsis' => 'format_fieldsynopsis_modifier_text',
),
'classname' => array(
/* DEFAULT */ false,
'ooclass' => array(
/** Those are used to retrieve the class/interface name to be able to remove it from method names */
'classname' => [
/* DEFAULT */ false,
'ooclass' => [
/* DEFAULT */ false,
/** This is also used by the legacy display to not display the class name at all */
'classsynopsis' => 'format_classsynopsis_ooclass_classname_text',
),
),
]
],
'exceptionname' => [
/* DEFAULT */ false,
'ooexception' => [
/* DEFAULT */ false,
'classsynopsis' => 'format_classsynopsis_oo_name_text',
]
],
'interfacename' => [
/* DEFAULT */ false,
'oointerface' => [
/* DEFAULT */ false,
'classsynopsis' => 'format_classsynopsis_oo_name_text',
]
],
'methodname' => array(
/* DEFAULT */ false,
'constructorsynopsis' => array(
Expand Down Expand Up @@ -422,11 +452,14 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
protected $cchunk = array();
/* Default Chunk variables */
private $dchunk = array(
"classsynopsis" => array(
"close" => false,
"classname" => false,
"interface" => false, // bool: true when in interface
),
"classsynopsis" => [
"close" => false,
"classname" => false,
"interface" => false, // bool: true when in interface
"ooclass" => false,
"oointerface" => false,
"legacy" => true, // legacy rendering
],
"classsynopsisinfo" => array(
"implements" => false,
"ooclass" => false,
Expand Down Expand Up @@ -896,6 +929,7 @@ public function format_refsect($open, $name, $attrs) {
return "</div>\n";
}

/** Legacy rendering functions for class synopsis tags that wraps the definition in a class synopsis info tag */
public function format_classsynopsisinfo_oointerface($open, $name, $attrs) {
if ($open) {
if ($this->cchunk["classsynopsisinfo"]["ooclass"] === false) {
Expand Down Expand Up @@ -971,29 +1005,150 @@ public function format_classsynopsisinfo($open, $name, $attrs)
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"]) && $attrs[Reader::XMLNS_DOCBOOK]["role"] == "comment") {
return ' */</div>';
}

assert($this->cchunk["classsynopsis"]["legacy"] === true);
$this->cchunk["classsynopsis"]["close"] = true;
return ' {</div>';
}

public function format_classsynopsis($open, $name, $attrs) {
/** This method is common between both legacy and new rendering for setting up the classname in the current chunk */
public function format_classsynopsis_ooclass_classname_text($value, $tag) {
/** If this is not defined this is the first ooclass/oointerface/ooexception and thus needs to
* set the class name to be able to remove it from the methods
*/
if (!$this->cchunk["classsynopsis"]["classname"]) {
$this->cchunk["classsynopsis"]["classname"] = $value;
}
// Do not render outside ooclass class name in legacy rendering.
if ($this->cchunk["classsynopsis"]["legacy"]) {
return '';
}
return $this->TEXT($value);
}

/** Class synopsis rendering for new/better markup */
public function format_classsynopsis_oo_name_text($value, $tag) {
/** If this is not defined this is the first ooclass/oointerface/ooexception and thus needs to
* set the class name to be able to remove it from the methods
*/
if (!$this->cchunk["classsynopsis"]["classname"]) {
$this->cchunk["classsynopsis"]["classname"] = $value;
}
return $this->TEXT($value);
}

public function format_classsynopsis_oointerface_interfacename($open, $name, $attrs, $props)
{
if ($this->cchunk["classsynopsis"]["legacy"] === true) {
return $this->transformFromMap($open, 'strong', $name, $attrs, $props);
}

if ($open) {
// Think this just needs to be set on open and it will persist
// Will remove comment after review
if (
isset($attrs[Reader::XMLNS_DOCBOOK]["class"]) &&
$attrs[Reader::XMLNS_DOCBOOK]["class"] == "interface"
) {
$this->cchunk["classsynopsis"]["interface"] = true;
/* If there has been a class prior this means that we are the first implementing interface
* thus mark the oointerface as already been rendered as the primary tag */
if ($this->cchunk["classsynopsis"]["ooclass"] === true) {
$this->cchunk["classsynopsis"]["oointerface"] = true;
}
/** Actual interface name in bold */
if ($this->cchunk["classsynopsis"]["oointerface"] === false) {

return '<div class="'.$name.'">';
return '<span class="modifier">interface</span> ' . $this->transformFromMap($open, 'strong', $name, $attrs, $props);
}
/* Whitespace for next word */
return ' ';
}
/** Actual interface name in bold */
if ($this->cchunk["classsynopsis"]["oointerface"] === false) {
$this->cchunk["classsynopsis"]["oointerface"] = true;
return '</strong>';
}
/** We don't wrap extended interface in a tag */
if ($this->cchunk["classsynopsis"]['nb_list'] > 1) {
return ',';
}
return '';
}

public function format_classsynopsis_ooclass_classname($open, $name, $attrs, $props)
{
if ($this->cchunk["classsynopsis"]["legacy"] === true) {
return $this->transformFromMap($open, 'strong', $name, $attrs, $props);
}

if ($open) {
/** Actual class name in bold */
if ($this->cchunk["classsynopsis"]["ooclass"] === false) {
/** We force the name: parameter to 'classname' to not break CSS expectations for exceptionanme tags */
return '<span class="modifier">class</span> ' . $this->transformFromMap($open, 'strong', 'classname', $attrs, $props);
}
/* Whitespace for next word */
return ' ';
}
/** Actual class name in bold */
if ($this->cchunk["classsynopsis"]["ooclass"] === false) {
$this->cchunk["classsynopsis"]["ooclass"] = true;
return '</strong>';
}
/** We don't wrap extended class in a tag */
return '';
}

public function format_classsynopsis_generic_oo_tag($open, $name, $attrs, $props)
{
if ($this->cchunk["classsynopsis"]["legacy"] === true) {
return $this->transformFromMap($open, 'span', $name, $attrs, $props);
}

/* Close list of classes + interfaces by "opening" class def with { */
if (!$open) {
if (--$this->cchunk["classsynopsis"]['nb_list'] === 0) {
return ' {</div>';
}
}
return '';
}

public function format_classsynopsis($open, $name, $attrs, $props) {
$this->cchunk["classsynopsis"] = $this->dchunk["classsynopsis"];

/** Legacy presentation does not use the class attribute */
$this->cchunk["classsynopsis"]['legacy'] = !isset($attrs[Reader::XMLNS_DOCBOOK]["class"]);

if ($this->cchunk["classsynopsis"]['legacy']) {
if ($open) {
// Think this just needs to be set on open and it will persist
// Will remove comment after review
if (
isset($attrs[Reader::XMLNS_DOCBOOK]["class"]) &&
$attrs[Reader::XMLNS_DOCBOOK]["class"] == "interface"
) {
$this->cchunk["classsynopsis"]["interface"] = true;
}

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

if ($this->cchunk["classsynopsis"]["close"] === true) {
$this->cchunk["classsynopsis"]["close"] = false;
/* Just always force the ending } to close the class as an opening { should always be present
if ($this->cchunk["classsynopsis"]["close"] === true) {
$this->cchunk["classsynopsis"]["close"] = false;
return "}</div>";
}
return "</div>";
*/
return "}</div>";
}
return "</div>";

/* New rendering for more sensible markup:
* We open a fake classsynopsisinfo div to not break the CSS expectations */
if ($open) {
$occurrences = substr_count($props['innerXml'], '</ooclass>')
+ substr_count($props['innerXml'], '</oointerface>')
+ substr_count($props['innerXml'], '</ooexception>');
$this->cchunk["classsynopsis"]['nb_list'] = $occurrences;
return '<div class="classsynopsis"><div class="classsynopsisinfo">';
} else {
return '}</div>';
}
}

public function format_classsynopsis_methodsynopsis_methodname_text($value, $tag) {
Expand All @@ -1018,10 +1173,6 @@ public function format_classsynopsis_methodsynopsis_methodname_text($value, $tag
return $method;
}

public function format_classsynopsis_ooclass_classname_text($value, $tag) {
$this->cchunk["classsynopsis"]["classname"] = $value;
return $this->TEXT($value);
}

public function format_fieldsynopsis($open, $name, $attrs) {
$this->cchunk["fieldsynopsis"] = $this->dchunk["fieldsynopsis"];
Expand Down
50 changes: 33 additions & 17 deletions phpdotnet/phd/Package/PHP/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML {
'appendix' => 'format_container_chunk',
'article' => 'format_container_chunk',
'book' => 'format_root_chunk',
'classname' => array(
/* DEFAULT */ 'span',
'ooclass' => array(
/* DEFAULT */ 'format_suppressed_tags',
'classsynopsisinfo' => 'format_classsynopsisinfo_ooclass_classname',
),
),
Comment on lines -10 to -16
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, this is useless, as it duplicated the same information from the generic XHTML format.

'chapter' => 'format_container_chunk',
'colophon' => 'format_chunk',
'function' => 'format_function',
Expand Down Expand Up @@ -90,15 +83,29 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML {
private $mytextmap = array(
'acronym' => 'format_acronym_text',
'function' => 'format_function_text',
'interfacename' => 'format_classname_text',
'exceptionname' => 'format_classname_text',
'classname' => array(
/* DEFAULT */ 'format_classname_text',
'ooclass' => array(
/* DEFAULT */ 'format_classname_text',
/** Those are used to retrieve the class/interface name to be able to remove it from method names */
'classname' => [
/* DEFAULT */ 'format_classname_text',
'ooclass' => [
/* DEFAULT */ 'format_classname_text',
/** This is also used by the legacy display to not display the class name at all */
'classsynopsis' => 'format_classsynopsis_ooclass_classname_text',
),
),
]
],
'exceptionname' => [
/* DEFAULT */ 'format_classname_text',
'ooexception' => [
/* DEFAULT */ 'format_classname_text',
'classsynopsis' => 'format_classsynopsis_oo_name_text',
]
],
'interfacename' => [
/* DEFAULT */ 'format_classname_text',
'oointerface' => [
/* DEFAULT */ 'format_classname_text',
'classsynopsis' => 'format_classsynopsis_oo_name_text',
]
],
'methodname' => array(
/* DEFAULT */ 'format_function_text',
'constructorsynopsis' => array(
Expand Down Expand Up @@ -708,8 +715,17 @@ public function format_grep_classname_text($value, $tag) {
}

public function format_classsynopsis_ooclass_classname_text($value, $tag) {
/* intentionally not return the value, it will be printed out by <methodname> "soon" */
parent::format_classsynopsis_ooclass_classname_text($value, $tag);
$content = parent::format_classsynopsis_ooclass_classname_text($value, $tag);
/** Legacy behaviour for crappy markup */
if ($content === '') {
return '';
}
return $this->format_classname_text($content, $tag);
}

public function format_classsynopsis_oo_name_text($value, $tag) {
$content = parent::format_classsynopsis_oo_name_text($value, $tag);
return $this->format_classname_text($content, $tag);
}

public function format_classname_text($value, $tag) {
Expand Down
10 changes: 7 additions & 3 deletions phpdotnet/phd/Render.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,12 @@ public function execute(Reader $r) { /* {{{ */

$innerXml = "";
if (
($open && $r->name === "type") ||
($open && in_array($r->name, ["methodsynopsis", "constructorsynopsis", "destructorsynopsis"], true))
$open &&
(
$r->name === "type" ||
$r->name === "classsynopsis" ||
in_array($r->name, ["methodsynopsis", "constructorsynopsis", "destructorsynopsis"], true)
)
) {
$innerXml = $r->readInnerXml();
}
Expand Down Expand Up @@ -113,7 +117,7 @@ public function execute(Reader $r) { /* {{{ */
continue;
}

if (strncmp($tag ?? '', "format_", 7) !== 0) {
if (/* !($tag instanceof \Closure) && */ !str_starts_with($tag ?? '', "format_")) {
$data = $format->transformFromMap($open, $tag, $name, $attrs, $props);
} else {
$data = $format->{$tag}($open, $name, $attrs, $props);
Expand Down