mirror of
https://github.com/php/phd.git
synced 2026-03-23 22:52:05 +01:00
2525 lines
93 KiB
PHP
2525 lines
93 KiB
PHP
<?php
|
|
namespace phpdotnet\phd;
|
|
|
|
abstract class Package_Generic_XHTML extends Format_Abstract_XHTML {
|
|
private $myelementmap = array( /* {{{ */
|
|
'abstract' => 'div', /* Docbook-xsl prints "abstract"... */
|
|
'abbrev' => 'abbr',
|
|
'acronym' => 'acronym',
|
|
'affiliation' => 'format_suppressed_tags',
|
|
'alt' => 'format_suppressed_tags',
|
|
'arg' => 'format_suppressed_tags',
|
|
'article' => 'format_container_chunk_top',
|
|
'author' => array(
|
|
/* DEFAULT */ 'format_author',
|
|
'authorgroup' => 'format_authorgroup_author',
|
|
),
|
|
'authorgroup' => 'div',
|
|
'authorinitials' => 'format_entry',
|
|
'appendix' => 'format_container_chunk_top',
|
|
'application' => 'span',
|
|
'blockquote' => 'blockquote',
|
|
'bibliography' => array(
|
|
/* DEFAULT */ 'format_div',
|
|
'article' => 'format_chunk',
|
|
'book' => 'format_chunk',
|
|
'part' => 'format_chunk',
|
|
),
|
|
'book' => 'format_container_chunk_top',
|
|
'caption' => 'format_caption',
|
|
'chapter' => 'format_container_chunk_top',
|
|
'citetitle' => 'em',
|
|
'cmdsynopsis' => 'format_cmdsynopsis',
|
|
'co' => 'format_co',
|
|
'colophon' => 'format_chunk',
|
|
'copyright' => 'format_copyright',
|
|
'date' => array(
|
|
/* DEFAULT */ 'p',
|
|
'revision' => 'format_entry',
|
|
),
|
|
'editor' => 'format_editor',
|
|
'edition' => 'format_suppressed_tags',
|
|
'email' => 'format_suppressed_tags',
|
|
'errortext' => 'code',
|
|
'firstname' => 'format_name',
|
|
'footnote' => 'format_footnote',
|
|
'footnoteref' => 'format_footnoteref',
|
|
'funcdef' => 'format_suppressed_tags',
|
|
'funcsynopsis' => 'div',
|
|
'funcsynopsisinfo' => 'pre',
|
|
'function' => 'span',
|
|
'funcprototype' => 'code',
|
|
'surname' => 'format_name',
|
|
'othername' => 'format_name',
|
|
'optional' => 'span',
|
|
'honorific' => 'span',
|
|
'glossary' => array(
|
|
/* DEFAULT */ 'format_div',
|
|
'article' => 'format_chunk',
|
|
'book' => 'format_chunk',
|
|
'part' => 'format_chunk',
|
|
),
|
|
'calloutlist' => 'format_calloutlist',
|
|
'callout' => 'format_callout',
|
|
'caution' => 'format_admonition',
|
|
'citation' => 'format_citation',
|
|
'citerefentry' => 'span',
|
|
'code' => 'code',
|
|
'collab' => 'span',
|
|
'collabname' => 'span',
|
|
'contrib' => 'format_suppressed_tags',
|
|
'colspec' => 'format_colspec',
|
|
'command' => 'strong',
|
|
'computeroutput' => 'span',
|
|
/* FIXME: This is one crazy stupid workaround for footnotes */
|
|
'constant' => array(
|
|
/* DEFAULT */ 'format_constant',
|
|
'para' => array(
|
|
/* DEFAULT */ 'format_constant',
|
|
'footnote' => 'format_footnote_constant',
|
|
),
|
|
),
|
|
'constructorsynopsis' => 'format_methodsynopsis',
|
|
'destructorsynopsis' => 'format_methodsynopsis',
|
|
'emphasis' => 'format_emphasis',
|
|
'entry' => array (
|
|
/* DEFAULT */ 'format_entry',
|
|
'row' => array(
|
|
/* DEFAULT */ 'format_entry',
|
|
'thead' => 'format_th_entry',
|
|
'tfoot' => 'format_th_entry',
|
|
'tbody' => 'format_entry',
|
|
),
|
|
),
|
|
'envar' => 'var',
|
|
'errortype' => 'span',
|
|
'errorcode' => 'span',
|
|
'example' => 'format_example',
|
|
'formalpara' => 'p',
|
|
'fieldsynopsis' => array(
|
|
/* DEFAULT */ 'format_fieldsynopsis',
|
|
'entry' => 'format_div',
|
|
),
|
|
'figure' => 'div',
|
|
'filename' => 'var',
|
|
'glossentry' => 'li',
|
|
'glossdef' => 'p',
|
|
'glosslist' => 'format_itemizedlist',
|
|
'glossterm' => 'span',
|
|
'holder' => 'span',
|
|
'imageobject' => 'format_div',
|
|
'imagedata' => 'format_imagedata',
|
|
'important' => 'format_admonition',
|
|
'index' => array(
|
|
/* DEFAULT */ 'format_div',
|
|
'article' => 'format_chunk',
|
|
'book' => 'format_chunk',
|
|
'part' => 'format_chunk',
|
|
),
|
|
'info' => array(
|
|
/* DEFAULT */ 'format_div',
|
|
'note' => 'span',
|
|
),
|
|
'informalexample' => 'format_div',
|
|
'informaltable' => 'format_table',
|
|
'indexdiv' => 'format_dl',
|
|
'indexentry' => 'dd',
|
|
'initializer' => 'format_initializer',
|
|
'itemizedlist' => 'format_itemizedlist',
|
|
'keycap' => 'format_keycap',
|
|
'keycombo' => 'format_keycombo',
|
|
'legalnotice' => 'format_chunk',
|
|
'listitem' => array(
|
|
/* DEFAULT */ 'li',
|
|
'varlistentry' => 'format_varlistentry_listitem',
|
|
),
|
|
'literal' => 'format_literal',
|
|
'literallayout' => 'pre',
|
|
'link' => 'format_link',
|
|
'manvolnum' => 'format_manvolnum',
|
|
'inlinemediaobject' => 'format_mediaobject',
|
|
'mediaobject' => 'format_mediaobject',
|
|
'methodparam' => 'format_methodparam',
|
|
'methodsynopsis' => 'format_methodsynopsis',
|
|
'methodname' => 'format_methodname',
|
|
'member' => 'format_member',
|
|
'modifier' => array(
|
|
/* DEFAULT */ 'format_modifier',
|
|
'methodparam' => 'format_methodparam_modifier',
|
|
),
|
|
'note' => 'format_note',
|
|
'orgname' => 'span',
|
|
'othercredit' => 'format_div',
|
|
/** Class Synopsis related tags */
|
|
'classsynopsis' => 'format_classsynopsis',
|
|
'classsynopsisinfo' => 'format_classsynopsisinfo',
|
|
'ooclass' => array(
|
|
/* DEFAULT */ 'span',
|
|
'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
|
|
),
|
|
'ooexception' => [
|
|
/* DEFAULT */ 'span',
|
|
'classsynopsis' => 'format_classsynopsis_generic_oo_tag',
|
|
],
|
|
'oointerface' => array(
|
|
/* DEFAULT */ 'span',
|
|
'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',
|
|
),
|
|
),
|
|
/** Enum synopsis related */
|
|
'enumsynopsis' => 'format_enumsynopsis',
|
|
'enumname' => [
|
|
/* DEFAULT */ 'span',
|
|
'enumsynopsis' => 'format_enumsynopsis_enumname'
|
|
],
|
|
'enumitem' => 'format_enumitem',
|
|
'enumidentifier' => 'format_enumidentifier',
|
|
'enumvalue' => 'format_enumvalue',
|
|
'enumitemdescription' => 'format_enumitemdescription',
|
|
'option' => 'format_option',
|
|
'orderedlist' => 'format_orderedlist',
|
|
'para' => array(
|
|
/* DEFAULT */ 'p',
|
|
'example' => 'format_example_content',
|
|
'footnote' => 'format_footnote_para',
|
|
'refsect1' => 'format_refsect1_para',
|
|
'question' => 'format_suppressed_tags',
|
|
),
|
|
'paramdef' => 'format_suppressed_tags',
|
|
'parameter' => array(
|
|
/* DEFAULT */ 'format_parameter',
|
|
'methodparam' => 'format_methodparam_parameter',
|
|
),
|
|
'part' => 'format_container_chunk_top',
|
|
'partintro' => 'format_div',
|
|
'personname' => 'format_personname',
|
|
'personblurb' => 'format_div',
|
|
'phrase' => 'span',
|
|
'preface' => 'format_chunk',
|
|
'printhistory' => 'format_div',
|
|
'primaryie' => 'format_suppressed_tags',
|
|
'procedure' => 'format_procedure',
|
|
'productname' => 'span',
|
|
'programlisting' => 'format_programlisting',
|
|
'prompt' => 'span',
|
|
'propname' => 'span',
|
|
'property' => array(
|
|
/* DEFAULT */ 'span',
|
|
'classsynopsisinfo' => 'format_varname',
|
|
),
|
|
'proptype' => 'span',
|
|
'pubdate' => 'format_div', /* Docbook-XSL prints "published" */
|
|
'refentry' => 'format_chunk',
|
|
'refentrytitle' => 'span',
|
|
'refpurpose' => 'p',
|
|
'reference' => 'format_container_chunk_below',
|
|
'refsect1' => 'format_refsect',
|
|
'refsect2' => 'format_refsect',
|
|
'refsect3' => 'format_refsect',
|
|
'refsynopsisdiv' => 'div',
|
|
'refname' => 'h1',
|
|
'refnamediv' => 'div',
|
|
'releaseinfo' => 'div',
|
|
'replaceable' => array(
|
|
/* DEFAULT */ 'span',
|
|
'constant' => 'format_replaceable',
|
|
),
|
|
'revhistory' => 'format_table',
|
|
'revision' => 'format_row',
|
|
'revremark' => 'format_entry',
|
|
'row' => 'format_row',
|
|
'screen' => 'format_screen',
|
|
'screenshot' => 'format_div',
|
|
'sect1' => 'format_chunk',
|
|
'sect2' => 'div',
|
|
'sect3' => 'div',
|
|
'sect4' => 'div',
|
|
'sect5' => 'div',
|
|
'section' => array(
|
|
/* DEFAULT */ 'div',
|
|
'sect1' => 'format_section_chunk',
|
|
'chapter' => 'format_section_chunk',
|
|
'appendix' => 'format_section_chunk',
|
|
'article' => 'format_section_chunk',
|
|
'part' => 'format_section_chunk',
|
|
'reference' => 'format_section_chunk',
|
|
'refentry' => 'format_section_chunk',
|
|
'index' => 'format_section_chunk',
|
|
'bibliography' => 'format_section_chunk',
|
|
'glossary' => 'format_section_chunk',
|
|
'colopone' => 'format_section_chunk',
|
|
'book' => 'format_section_chunk',
|
|
'set' => 'format_section_chunk',
|
|
'setindex' => 'format_section_chunk',
|
|
'legalnotice' => 'format_section_chunk',
|
|
),
|
|
'seg' => 'format_seg',
|
|
'segmentedlist' => 'format_segmentedlist',
|
|
'seglistitem' => 'format_seglistitem',
|
|
'segtitle' => 'format_suppressed_tags',
|
|
'set' => 'format_container_chunk_top',
|
|
'setindex' => 'format_chunk',
|
|
'shortaffil' => 'format_suppressed_tags',
|
|
'sidebar' => 'format_note',
|
|
'simplelist' => 'format_simplelist',
|
|
'simplesect' => 'div',
|
|
'simpara' => array(
|
|
/* DEFAULT */ 'p',
|
|
'note' => 'span',
|
|
'listitem' => 'span',
|
|
'entry' => 'span',
|
|
'example' => 'format_example_content',
|
|
),
|
|
'spanspec' => 'format_suppressed_tags',
|
|
'step' => 'format_step',
|
|
'superscript' => 'sup',
|
|
'subscript' => 'sub',
|
|
'systemitem' => 'format_systemitem',
|
|
'symbol' => 'span',
|
|
'synopsis' => 'pre',
|
|
'tag' => 'code',
|
|
'table' => 'format_table',
|
|
'firstterm' => 'format_term',
|
|
'term' => array(
|
|
/* DEFAULT */ 'format_term',
|
|
'varlistentry' => 'format_varlistentry_term'
|
|
),
|
|
'tfoot' => 'format_th',
|
|
'tbody' => 'format_tbody',
|
|
'td' => 'format_th',
|
|
'th' => 'format_th',
|
|
'thead' => 'format_th',
|
|
'tgroup' => 'format_tgroup',
|
|
'tip' => 'format_admonition',
|
|
'title' => array(
|
|
/* DEFAULT */ 'h1',
|
|
'example' => 'format_example_title',
|
|
'formalpara' => 'h5',
|
|
'info' => array(
|
|
/* DEFAULT */ 'h1',
|
|
'example' => 'format_example_title',
|
|
'note' => 'format_note_title',
|
|
'table' => 'format_table_title',
|
|
'informaltable' => 'format_table_title',
|
|
|
|
'article' => 'format_container_chunk_top_title',
|
|
'appendix' => 'format_container_chunk_top_title',
|
|
'book' => 'format_container_chunk_top_title',
|
|
'chapter' => 'format_container_chunk_top_title',
|
|
'part' => 'format_container_chunk_top_title',
|
|
'set' => 'format_container_chunk_top_title',
|
|
|
|
),
|
|
'indexdiv' => 'dt',
|
|
'legalnotice' => 'h4',
|
|
'note' => 'format_note_title',
|
|
'phd:toc' => 'strong',
|
|
'procedure' => 'strong',
|
|
'refsect1' => 'h3',
|
|
'refsect2' => 'h4',
|
|
'refsect3' => 'h5',
|
|
'section' => 'h2',
|
|
'sect1' => 'h2',
|
|
'sect2' => 'h3',
|
|
'sect3' => 'h4',
|
|
'sect4' => 'h5',
|
|
'segmentedlist' => 'format_table_title',
|
|
'table' => 'format_table_title',
|
|
'variablelist' => 'format_variablelist_title',
|
|
'article' => 'format_container_chunk_top_title',
|
|
'appendix' => 'format_container_chunk_top_title',
|
|
'book' => 'format_container_chunk_top_title',
|
|
'chapter' => 'format_container_chunk_top_title',
|
|
'part' => 'format_container_chunk_top_title',
|
|
'set' => 'format_container_chunk_top_title',
|
|
),
|
|
'titleabbrev' => 'format_suppressed_tags',
|
|
'token' => 'code',
|
|
'tr' => 'format_row',
|
|
'trademark' => 'format_trademark',
|
|
'type' => 'span',
|
|
'userinput' => 'format_userinput',
|
|
'uri' => 'code',
|
|
'variablelist' => 'format_variablelist',
|
|
'varlistentry' => 'format_varlistentry',
|
|
'varname' => array(
|
|
/* DEFAULT */ 'var',
|
|
'fieldsynopsis' => 'format_fieldsynopsis_varname',
|
|
),
|
|
'void' => 'format_void',
|
|
'warning' => 'format_admonition',
|
|
'xref' => 'format_xref',
|
|
'year' => 'span',
|
|
'quote' => 'q',
|
|
'qandaset' => 'format_qandaset',
|
|
'qandaentry' => 'dl',
|
|
'question' => array(
|
|
/* DEFAULT */ 'format_question',
|
|
'questions' => 'format_phd_question', // From the PhD namespace
|
|
),
|
|
'questions' => 'ol', // From the PhD namespace
|
|
'answer' => 'dd',
|
|
|
|
//phpdoc: implemented in the PHP Package
|
|
'phpdoc:classref' => 'format_suppressed_tags',
|
|
'phpdoc:exception' => 'format_suppressed_tags',
|
|
'phpdoc:exceptionref' => 'format_suppressed_tags',
|
|
'phpdoc:varentry' => 'format_suppressed_tags',
|
|
|
|
//phd
|
|
'phd:toc' => 'format_phd_toc',
|
|
|
|
); /* }}} */
|
|
|
|
private $mytextmap = array(
|
|
'segtitle' => 'format_segtitle_text',
|
|
'affiliation' => 'format_suppressed_text',
|
|
'contrib' => 'format_suppressed_text',
|
|
'shortaffil' => 'format_suppressed_text',
|
|
'edition' => 'format_suppressed_text',
|
|
|
|
'programlisting' => 'format_programlisting_text',
|
|
'screen' => 'format_screen_text',
|
|
'alt' => 'format_alt_text',
|
|
'modifier' => array(
|
|
/* DEFAULT */ false,
|
|
'fieldsynopsis' => 'format_fieldsynopsis_modifier_text',
|
|
'methodparam' => 'format_modifier_text',
|
|
'methodsynopsis' => 'format_modifier_text',
|
|
'constructorsynopsis' => 'format_modifier_text',
|
|
'ooclass' => 'format_modifier_text',
|
|
'ooexception' => 'format_modifier_text',
|
|
'oointerface' => 'format_modifier_text',
|
|
),
|
|
'replaceable' => array(
|
|
/* DEFAULT */ false,
|
|
'constant' => 'format_suppressed_text',
|
|
),
|
|
/** 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(
|
|
/* DEFAULT */ false,
|
|
'classsynopsis' => 'format_classsynopsis_methodsynopsis_methodname_text',
|
|
),
|
|
'methodsynopsis' => array(
|
|
/* DEFAULT */ false,
|
|
'classsynopsis' => 'format_classsynopsis_methodsynopsis_methodname_text',
|
|
),
|
|
'destructorsynopsis' => array(
|
|
/* DEFAULT */ false,
|
|
'classsynopsis' => 'format_classsynopsis_methodsynopsis_methodname_text',
|
|
),
|
|
),
|
|
'para' => array(
|
|
/* DEFAULT */ false,
|
|
'footnote' => 'format_footnote_para_text',
|
|
),
|
|
'property' => [
|
|
/* DEFAULT */ 'format_property_text',
|
|
],
|
|
/* FIXME: This is one crazy stupid workaround for footnotes */
|
|
'constant' => array(
|
|
/* DEFAULT */ 'format_constant_text',
|
|
'para' => array(
|
|
/* DEFAULT */ 'format_constant_text',
|
|
'footnote' => 'format_footnote_constant_text',
|
|
),
|
|
),
|
|
'literal' => 'format_literal_text',
|
|
'email' => 'format_email_text',
|
|
'titleabbrev' => 'format_suppressed_text',
|
|
'member' => 'format_member_text',
|
|
);
|
|
|
|
/** @var array */
|
|
protected $TOC_WRITTEN = [];
|
|
|
|
/** @var string */
|
|
protected $CURRENT_LANG = "";
|
|
|
|
/** @var string */
|
|
protected $CURRENT_CHUNK = "";
|
|
|
|
/* Current Chunk variables */
|
|
protected $cchunk = array();
|
|
/* Default Chunk variables */
|
|
private $dchunk = array(
|
|
"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,
|
|
),
|
|
"examples" => 0,
|
|
"fieldsynopsis" => array(
|
|
"modifier" => "public",
|
|
),
|
|
"methodsynopsis" => array(
|
|
"returntypes" => array(),
|
|
"type_separator" => array(),
|
|
"type_separator_stack" => array(),
|
|
),
|
|
"co" => 0,
|
|
"callouts" => 0,
|
|
"segmentedlist" => array(
|
|
"segtitleclosed" => false,
|
|
"segtitleopened" => false,
|
|
),
|
|
"table" => false,
|
|
"procedure" => false,
|
|
"mediaobject" => array(
|
|
"alt" => false,
|
|
),
|
|
"footnote" => array(
|
|
),
|
|
"tablefootnotes" => array(
|
|
),
|
|
"chunk_id" => null,
|
|
"varlistentry" => array(
|
|
"listitems" => array(),
|
|
),
|
|
"simplelist" => array(
|
|
"members" => array(),
|
|
"type" => null,
|
|
"columns" => null,
|
|
),
|
|
);
|
|
|
|
protected $pihandlers = array(
|
|
'dbhtml' => 'PI_DBHTMLHandler',
|
|
'dbtimestamp' => 'PI_DBHTMLHandler',
|
|
);
|
|
|
|
protected $stylesheets = array();
|
|
protected $isSectionChunk = array();
|
|
protected $params = array();
|
|
|
|
protected int $exampleCounter = 0;
|
|
|
|
public function __construct(
|
|
Config $config,
|
|
OutputHandler $outputHandler
|
|
) {
|
|
parent::__construct($config, $outputHandler);
|
|
$this->registerPIHandlers($this->pihandlers);
|
|
$this->setExt($this->config->ext === null ? ".html" : $this->config->ext);
|
|
}
|
|
|
|
public function getDefaultElementMap() {
|
|
return $this->myelementmap;
|
|
}
|
|
|
|
public function getDefaultTextMap() {
|
|
return $this->mytextmap;
|
|
}
|
|
|
|
public function getChunkInfo() {
|
|
return $this->cchunk;
|
|
}
|
|
|
|
public function getDefaultChunkInfo() {
|
|
return $this->dchunk;
|
|
}
|
|
|
|
protected function createTOC($id, $name, $props, $depth = 1, $header = true) {
|
|
if (!$this->getChildren($id) || $depth == 0) {
|
|
return "";
|
|
}
|
|
$toc = '';
|
|
if ($header) {
|
|
$toc .= $this->getTocHeader($props);
|
|
}
|
|
$toc .= "<ul class=\"chunklist chunklist_$name\">\n";
|
|
foreach ($this->getChildren($id) as $child) {
|
|
$isLDesc = null;
|
|
$isSDesc = null;
|
|
$long = $this->getLongDescription($child, $isLDesc);
|
|
$short = $this->getShortDescription($child, $isSDesc);
|
|
$link = $this->createLink($child);
|
|
|
|
$list = "";
|
|
if ($depth > 1 ) {
|
|
$list = $this->createTOC($child, $name, $props, $depth -1, false);
|
|
}
|
|
if ($isLDesc && $isSDesc) {
|
|
$toc .= '<li><a href="' . $link . '">' . $short . '</a> — ' . $long . $list . "</li>\n";
|
|
} else {
|
|
$toc .= '<li><a href="' . $link . '">' . $long . '</a>' . $list . "</li>\n";
|
|
}
|
|
}
|
|
$toc .= "</ul>\n";
|
|
return $toc;
|
|
}
|
|
|
|
protected function getTocHeader($props)
|
|
{
|
|
return '<strong>' . $this->autogen('toc', $props['lang']) . '</strong>';
|
|
}
|
|
|
|
/**
|
|
* Handle a <phd:toc> tag.
|
|
*/
|
|
function format_phd_toc($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<div class="phd-toc">';
|
|
}
|
|
return $this->createToc(
|
|
$attrs[Reader::XMLNS_PHD]['element'],
|
|
'phd-toc',
|
|
$props,
|
|
isset($attrs[Reader::XMLNS_PHD]['toc-depth'])
|
|
? (int)$attrs[Reader::XMLNS_PHD]['toc-depth'] : 1,
|
|
false
|
|
) . "</div>\n";
|
|
}
|
|
|
|
public function createLink($for, &$desc = null, $type = Format::SDESC) {
|
|
$retval = null;
|
|
if (isset($this->indexes[$for])) {
|
|
$rsl = $this->indexes[$for];
|
|
$retval = $rsl["filename"] . $this->ext;
|
|
if ($rsl["filename"] != $rsl["docbook_id"]) {
|
|
$retval .= '#' . $rsl["docbook_id"];
|
|
}
|
|
$desc = $rsl["sdesc"] ?: $rsl["ldesc"];
|
|
}
|
|
return $retval;
|
|
}
|
|
|
|
protected function createCSSLinks() {
|
|
$cssLinks = '';
|
|
foreach ((array)$this->stylesheets as $css) {
|
|
if ($this->isChunked()) {
|
|
$cssLinks .= "<link media=\"all\" rel=\"stylesheet\" type=\"text/css\" href=\"styles/".$css."\" />\n";
|
|
} else {
|
|
$cssLinks .= "<style type=\"text/css\">\n" . $css . "\n</style>\n";
|
|
}
|
|
}
|
|
return $cssLinks;
|
|
}
|
|
|
|
protected function fetchStylesheet($name = null) {
|
|
if (!$this->isChunked()) {
|
|
foreach ((array)$this->config->css as $css) {
|
|
if ($style = file_get_contents($css)) {
|
|
$this->stylesheets[] = $style;
|
|
} else {
|
|
trigger_error(vsprintf("Stylesheet %s not fetched.", [$css]), E_USER_WARNING);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
$stylesDir = $this->getOutputDir();
|
|
if (!$stylesDir) {
|
|
$stylesDir = $this->config->outputDir;
|
|
}
|
|
$stylesDir .= 'styles/';
|
|
if (file_exists($stylesDir)) {
|
|
if (!is_dir($stylesDir)) {
|
|
trigger_error("The styles/ directory is a file?", E_USER_ERROR);
|
|
}
|
|
} else {
|
|
if (!mkdir($stylesDir, 0777, true)) {
|
|
trigger_error("Can't create the styles/ directory.", E_USER_ERROR);
|
|
}
|
|
}
|
|
foreach ((array)$this->config->css as $css) {
|
|
$basename = basename($css);
|
|
$dest = md5(substr($css, 0, -strlen($basename))) . '-' . $basename;
|
|
if (@copy($css, $stylesDir . $dest)) {
|
|
$this->stylesheets[] = $dest;
|
|
} else {
|
|
trigger_error(vsprintf('Impossible to copy the %s file.', [$css]), E_USER_WARNING);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Functions format_* */
|
|
public function format_suppressed_tags($open, $name, $attrs, $props) {
|
|
/* Ignore it */
|
|
return "";
|
|
}
|
|
public function format_suppressed_text($value, $tag) {
|
|
/* Suppress any content */
|
|
return "";
|
|
}
|
|
|
|
public function format_link($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$link = $class = $content = "";
|
|
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["linkend"])) {
|
|
$link = $this->createLink($attrs[Reader::XMLNS_DOCBOOK]["linkend"]);
|
|
}
|
|
elseif (isset($attrs[Reader::XMLNS_XLINK]["href"])) {
|
|
$link = $attrs[Reader::XMLNS_XLINK]["href"];
|
|
$class = " external";
|
|
$content = "» ";
|
|
}
|
|
if ($props["empty"]) {
|
|
$content .= $link ."</a>";
|
|
}
|
|
|
|
return '<a href="' . $link . '" class="' . $name . $class . '">' . $content;
|
|
}
|
|
return "</a>";
|
|
}
|
|
|
|
public function format_xref($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$desc = "";
|
|
$link = $this->createLink($attrs[Reader::XMLNS_DOCBOOK]["linkend"], $desc);
|
|
|
|
$ret = '<a href="' .$link. '" class="' .$name. '">' .$desc;
|
|
|
|
if ($props["empty"]) {
|
|
return $ret. "</a>";
|
|
}
|
|
return $ret;
|
|
}
|
|
return "</a>";
|
|
}
|
|
|
|
public function format_option($open, $name, $attrs) {
|
|
if ($open) {
|
|
if(!isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$attrs[Reader::XMLNS_DOCBOOK]["role"] = "unknown";
|
|
}
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
|
|
return '<strong class="' . $name . ' ' . $this->getRole() . '">';
|
|
}
|
|
$this->popRole();
|
|
return "</strong>";
|
|
}
|
|
|
|
public function format_literal($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"] ?? null);
|
|
return '<code class="literal">';
|
|
}
|
|
$this->popRole();
|
|
return '</code>';
|
|
}
|
|
|
|
public function format_literal_text($value, $tag) {
|
|
switch ($this->getRole()) {
|
|
case 'infdec':
|
|
$value = (string) (float)$value;
|
|
$p = strpos($value, '.');
|
|
$str = substr($value, 0, $p + 1);
|
|
$str .= '<span style="text-decoration: overline;">';
|
|
$str .= substr($value, $p + 1);
|
|
$str .= '</span>';
|
|
return $str;
|
|
default:
|
|
return $this->TEXT($value);
|
|
}
|
|
}
|
|
|
|
public function format_copyright($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<div class="'.$name.'">© ';
|
|
}
|
|
return '</div>';
|
|
}
|
|
|
|
public function format_author($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<div class="' .$name. ' vcard">';
|
|
}
|
|
return "</div>";
|
|
}
|
|
|
|
public function format_personname($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<span class="' .$name. ' fn">';
|
|
}
|
|
return "</span>";
|
|
}
|
|
|
|
public function format_name($open, $name, $attrs) {
|
|
if ($open) {
|
|
$class = "";
|
|
switch($name) {
|
|
case "firstname":
|
|
$class = " given-name";
|
|
break;
|
|
|
|
case "surname":
|
|
$class = " family-name";
|
|
break;
|
|
|
|
case "othername":
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
/* We might want to add support for other roles */
|
|
switch($attrs[Reader::XMLNS_DOCBOOK]["role"]) {
|
|
case "nickname":
|
|
$class = " nickname";
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return ' <span class="' . $name . $class . '">';
|
|
}
|
|
return '</span> ';
|
|
}
|
|
|
|
public function format_container_chunk_top($open, $name, $attrs, $props) {
|
|
$this->cchunk = $this->dchunk;
|
|
$this->cchunk["name"] = $name;
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
} else {
|
|
$id = uniqid("phd");
|
|
}
|
|
|
|
if ($open) {
|
|
$this->CURRENT_CHUNK = $id;
|
|
$this->notify(Render::CHUNK, Render::OPEN);
|
|
|
|
return '<div id="' .$id. '" class="' .$name. '">';
|
|
}
|
|
|
|
$this->CURRENT_CHUNK = $id;
|
|
$this->notify(Render::CHUNK, Render::CLOSE);
|
|
$toc = "";
|
|
if (!in_array($id, $this->TOC_WRITTEN)) {
|
|
$toc = $this->createTOC($id, $name, $props);
|
|
}
|
|
|
|
return $toc."</div>";
|
|
}
|
|
public function format_container_chunk_top_title($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<h1>';
|
|
}
|
|
|
|
$id = $this->CURRENT_CHUNK;
|
|
|
|
$toc = $this->createTOC($id, $name, $props, 2);
|
|
|
|
$this->TOC_WRITTEN[] = $id;
|
|
|
|
return '</h1>'.$toc;
|
|
}
|
|
public function format_container_chunk_below($open, $name, $attrs, $props) {
|
|
$this->cchunk = $this->dchunk;
|
|
$this->cchunk["name"] = $name;
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
} else {
|
|
/* FIXME: This will obviously not exist in the db.. */
|
|
$id = uniqid("phd");
|
|
}
|
|
|
|
if ($open) {
|
|
$this->CURRENT_CHUNK = $id;
|
|
$this->notify(Render::CHUNK, Render::OPEN);
|
|
|
|
return '<div id="' .$attrs[Reader::XMLNS_XML]["id"]. '" class="' .$name. '">';
|
|
}
|
|
|
|
$toc = '<ol>';
|
|
if (!in_array($id, $this->TOC_WRITTEN)) {
|
|
$toc = $this->createTOC($id, $name, $props);
|
|
}
|
|
$toc .= "</ol>\n";
|
|
|
|
$this->CURRENT_CHUNK = $id;
|
|
$this->notify(Render::CHUNK, Render::CLOSE);
|
|
return $toc . '</div>';
|
|
}
|
|
public function format_exception_chunk($open, $name, $attrs, $props) {
|
|
return $this->format_container_chunk_below($open, "reference", $attrs, $props);
|
|
}
|
|
public function format_section_chunk($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if (!isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$this->isSectionChunk[] = false;
|
|
return $this->transformFromMap($open, "div", $name, $attrs, $props);
|
|
}
|
|
$this->isSectionChunk[] = true;
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
if (array_pop($this->isSectionChunk)) {
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
return $this->transformFromMap($open, "div", $name, $attrs, $props);
|
|
}
|
|
public function format_chunk($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$this->cchunk = $this->dchunk;
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
} else {
|
|
$id = uniqid("phd");
|
|
}
|
|
|
|
$class = $name;
|
|
if ($name === "refentry") {
|
|
//$class .= " -rel-posting";
|
|
}
|
|
|
|
$this->CURRENT_CHUNK = $id;
|
|
$this->CURRENT_LANG = $props["lang"];
|
|
|
|
$this->notify(Render::CHUNK, Render::OPEN);
|
|
return '<div id="' .$id. '" class="' .$class. '">';
|
|
}
|
|
$this->notify(Render::CHUNK, Render::CLOSE);
|
|
|
|
$str = "";
|
|
foreach ($this->cchunk["footnote"] as $k => $note) {
|
|
$str .= '<div class="footnote">';
|
|
$str .= '<a name="fnid' .$note["id"]. '" href="#fn' .$note["id"]. '"><sup>[' .($k + 1). ']</sup></a>';
|
|
$str .= $note["str"];
|
|
$str .= "</div>\n";
|
|
}
|
|
$this->cchunk = $this->dchunk;
|
|
|
|
return $str. "</div>";
|
|
}
|
|
public function format_refsect1_para($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
switch ($props["sibling"]) {
|
|
case "methodsynopsis":
|
|
case "constructorsynopsis":
|
|
case "destructorsynopsis":
|
|
return '<p class="'.$name.' rdfs-comment">';
|
|
break;
|
|
|
|
default:
|
|
return '<p class="'.$name.'">';
|
|
}
|
|
|
|
}
|
|
return '</p>';
|
|
}
|
|
public function format_refsect($open, $name, $attrs) {
|
|
static $role = 0;
|
|
|
|
if ($open) {
|
|
if(!isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$attrs[Reader::XMLNS_DOCBOOK]["role"] = "unknown-" . ++$role;
|
|
}
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
|
|
|
|
if (isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
}
|
|
else {
|
|
$id = $name. "-" . $this->CURRENT_CHUNK . "-" . $this->getRole();
|
|
}
|
|
|
|
return '<div class="' .$name.' ' .$this->getRole(). '" id="' . $id . '">';
|
|
}
|
|
$this->popRole();
|
|
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) {
|
|
return '<span class="' . $name . '">';
|
|
}
|
|
|
|
if ($this->cchunk["classsynopsisinfo"]["implements"] === false) {
|
|
$this->cchunk["classsynopsisinfo"]["implements"] = true;
|
|
if ($this->cchunk["classsynopsis"]["interface"]) {
|
|
return '<span class="'.$name.'"><span class="modifier">extends</span> ';
|
|
}
|
|
|
|
return '<span class="'.$name.'"><span class="modifier">implements</span> ';
|
|
}
|
|
|
|
return '<span class="'.$name.'">, ';
|
|
}
|
|
|
|
return "</span>";
|
|
}
|
|
|
|
public function format_classsynopsisinfo_ooclass_classname($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
if ($this->cchunk["classsynopsisinfo"]["ooclass"] === false) {
|
|
$this->cchunk["classsynopsisinfo"]["ooclass"] = true;
|
|
if ($this->cchunk["classsynopsis"]["interface"]) {
|
|
return '<span class="modifier">interface</span> ';
|
|
}
|
|
|
|
return '<span class="modifier">class</span> ';
|
|
}
|
|
|
|
return ' ';
|
|
}
|
|
|
|
if ($this->cchunk["classsynopsisinfo"]["ooclass"] === true) {
|
|
$this->cchunk["classsynopsisinfo"]["ooclass"] = null;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
public function format_classsynopsisinfo_oointerface_interfacename($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
if ($this->cchunk["classsynopsisinfo"]["ooclass"] === false) {
|
|
$this->cchunk["classsynopsisinfo"]["ooclass"] = true;
|
|
return '<span class="modifier">interface</span> ';
|
|
}
|
|
|
|
return ' ';
|
|
}
|
|
|
|
if ($this->cchunk["classsynopsisinfo"]["ooclass"] === true) {
|
|
$this->cchunk["classsynopsisinfo"]["ooclass"] = null;
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
public function format_classsynopsisinfo($open, $name, $attrs)
|
|
{
|
|
$this->cchunk["classsynopsisinfo"] = $this->dchunk["classsynopsisinfo"];
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"]) && $attrs[Reader::XMLNS_DOCBOOK]["role"] == "comment") {
|
|
return '<div class="'.$name.' classsynopsisinfo_comment">/* ';
|
|
}
|
|
|
|
return '<div class="'.$name.'">';
|
|
}
|
|
|
|
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>';
|
|
}
|
|
|
|
/** 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) {
|
|
/* 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 '<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.'">';
|
|
}
|
|
|
|
/* 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>";
|
|
}
|
|
|
|
/* 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) {
|
|
$value = $this->TEXT($value);
|
|
if ($this->cchunk["classsynopsis"]["classname"] === false) {
|
|
return $value;
|
|
}
|
|
if (strpos($value, '::')) {
|
|
$explode = '::';
|
|
} elseif (strpos($value, '->')) {
|
|
$explode = '->';
|
|
} elseif (strpos($value, '->')) {
|
|
$explode = '->';
|
|
} else {
|
|
return $value;
|
|
}
|
|
|
|
list($class, $method) = explode($explode, $value);
|
|
if ($class !== $this->cchunk["classsynopsis"]["classname"]) {
|
|
return $value;
|
|
}
|
|
return $method;
|
|
}
|
|
|
|
public function format_enumsynopsis($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
//return '<div class="enumsynopsis">';
|
|
return '<div class="classsynopsis"><div class="classsynopsisinfo">';
|
|
} else {
|
|
return '}</div>';
|
|
}
|
|
}
|
|
public function format_enumsynopsis_enumname($open, $name, $attrs, $props): string {
|
|
if ($open) {
|
|
/** Actual enum name in bold */
|
|
return '<span class="modifier">enum</span> <strong class="classname">';
|
|
//return '<span class="modifier">enum</span> <strong class="enumname">';
|
|
}
|
|
//return "</strong><br/>{<br/>";
|
|
return "</strong><br/>{</div>";
|
|
}
|
|
public function format_enumitem($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<div class="fieldsynopsis">';
|
|
}
|
|
return '</div>';
|
|
}
|
|
public function format_enumidentifier($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return ' <span class="modifier">case</span> <span class="classname">';
|
|
}
|
|
return '</span>';
|
|
}
|
|
public function format_enumvalue($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return ' = ';
|
|
}
|
|
return '';
|
|
}
|
|
public function format_enumitemdescription($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '; //';
|
|
}
|
|
return "<br><br>";
|
|
}
|
|
|
|
public function format_emphasis($open, $name, $attrs)
|
|
{
|
|
$name = "em";
|
|
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['role'])) {
|
|
$role = $attrs[Reader::XMLNS_DOCBOOK]['role'];
|
|
if ( $role == "strong" || $role == "bold" ) {
|
|
$name = "strong";
|
|
}
|
|
}
|
|
|
|
if ($open) {
|
|
return "<{$name}>";
|
|
} else {
|
|
return "</{$name}>";
|
|
}
|
|
}
|
|
|
|
public function format_fieldsynopsis($open, $name, $attrs) {
|
|
$this->cchunk["fieldsynopsis"] = $this->dchunk["fieldsynopsis"];
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
|
|
}
|
|
return '<div class="'.$name.'">';
|
|
}
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$this->popRole();
|
|
}
|
|
return ";</div>\n";
|
|
}
|
|
|
|
public function format_fieldsynopsis_modifier_text($value, $tag) {
|
|
if ($this->getRole() === "attribute") {
|
|
$attribute = trim(strtolower($value), "#[]\\");
|
|
$href = Format::getFilename("class.$attribute");
|
|
if ($href) {
|
|
return '<a href="' . $href . $this->getExt() . '">' .$value. '</a> ';
|
|
}
|
|
return false;
|
|
}
|
|
$this->cchunk["fieldsynopsis"]["modifier"] = trim($value);
|
|
return $this->TEXT($value);
|
|
}
|
|
|
|
public function format_modifier($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
|
|
return '<span class="' . $this->getRole() . '">';
|
|
}
|
|
return '<span class="modifier">';
|
|
}
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
if ($attrs[Reader::XMLNS_DOCBOOK]["role"] === "attribute") {
|
|
return '</span><br>';
|
|
}
|
|
$this->popRole();
|
|
}
|
|
return '</span>';
|
|
}
|
|
|
|
public function format_methodparam_modifier($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
|
|
return '<span class="' . $this->getRole() . '">';
|
|
}
|
|
return '<span class="modifier">';
|
|
}
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$this->popRole();
|
|
}
|
|
return '</span>';
|
|
}
|
|
|
|
public function format_modifier_text($value, $tag) {
|
|
if ($this->getRole() === "attribute") {
|
|
$attribute = trim(strtolower($value), "#[]\\");
|
|
$href = Format::getFilename("class.$attribute");
|
|
if ($href) {
|
|
return '<a href="' . $href . $this->getExt() . '">' .$value. '</a> ';
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function format_methodsynopsis($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
|
|
$this->params = array(
|
|
"count" => 0,
|
|
"opt" => false,
|
|
"init" => false,
|
|
"content" => "",
|
|
"ellipsis" => '',
|
|
"paramCount" => substr_count($props["innerXml"], "<methodparam")
|
|
);
|
|
|
|
$id = (isset($attrs[Reader::XMLNS_XML]["id"]) ? ' id="'.$attrs[Reader::XMLNS_XML]["id"].'"' : '');
|
|
return '<div class="'.$name.' dc-description"'.$id.'>';
|
|
}
|
|
|
|
$content = "";
|
|
if ($this->params["paramCount"] > 3) {
|
|
$content .= "<br>";
|
|
}
|
|
|
|
$content .= ")";
|
|
|
|
$content .= "</div>\n";
|
|
|
|
return $content;
|
|
}
|
|
|
|
public function format_methodparam_parameter($open, $name, $attrs, $props)
|
|
{
|
|
if ($props["empty"]) {
|
|
return '';
|
|
}
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
return ' <code class="parameter reference">&' . $this->params["ellipsis"] . '$';
|
|
}
|
|
return ' <code class="parameter">' . $this->params["ellipsis"] . '$';
|
|
}
|
|
return "</code>";
|
|
}
|
|
|
|
public function format_initializer($open, $name, $attrs) {
|
|
if ($open) {
|
|
$this->params["init"] = true;
|
|
return '<span class="'.$name.'"> = ';
|
|
}
|
|
return '</span>';
|
|
}
|
|
public function format_parameter($open, $name, $attrs, $props)
|
|
{
|
|
if ($props["empty"]) {
|
|
return '';
|
|
}
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
return '<code class="parameter reference">&';
|
|
}
|
|
return '<code class="parameter">';
|
|
}
|
|
return "</code>";
|
|
}
|
|
|
|
public function format_void($open, $name, $attrs, $props) {
|
|
if (isset($props['sibling']) && $props['sibling'] == 'methodname') {
|
|
return '(';
|
|
} else {
|
|
return '<span class="type"><a href="language.types.void' . $this->getExt() . '" class="type void">void</a></span>';
|
|
}
|
|
}
|
|
|
|
public function format_methodparam($open, $name, $attrs) {
|
|
if ($open) {
|
|
$content = '';
|
|
if ($this->params["count"] === 0) {
|
|
$content .= "(";
|
|
if ($this->params["paramCount"] > 3) {
|
|
$content .= "<br> ";
|
|
}
|
|
}
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["choice"]) && $attrs[Reader::XMLNS_DOCBOOK]["choice"] == "opt") {
|
|
$this->params["opt"] = true;
|
|
} else {
|
|
$this->params["opt"] = false;
|
|
}
|
|
if ($this->params["count"]) {
|
|
$content .= ",";
|
|
if ($this->params["paramCount"] > 3) {
|
|
$content .= "<br> ";
|
|
} else {
|
|
$content .= " ";
|
|
}
|
|
}
|
|
$content .= '<span class="methodparam">';
|
|
++$this->params["count"];
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["rep"]) && $attrs[Reader::XMLNS_DOCBOOK]["rep"] == "repeat") {
|
|
$this->params["ellipsis"] = '...';
|
|
} else {
|
|
$this->params["ellipsis"] = '';
|
|
}
|
|
return $content;
|
|
}
|
|
if ($this->params["opt"] && !$this->params["init"]) {
|
|
return '<span class="initializer"> = ?</span></span>';
|
|
}
|
|
$this->params["init"] = false;
|
|
return "</span>";
|
|
}
|
|
|
|
public function format_methodname($open, $name, $attr) {
|
|
if ($open) {
|
|
return ' <span class="' .$name. '">';
|
|
}
|
|
return '</span>';
|
|
}
|
|
|
|
public function format_varname($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<var class="'.$name.'">$';
|
|
}
|
|
return "</var>";
|
|
}
|
|
public function format_fieldsynopsis_varname($open, $name, $attrs) {
|
|
if ($open) {
|
|
if ($this->cchunk["fieldsynopsis"]["modifier"] === "const") {
|
|
return '<var class="fieldsynopsis_varname">';
|
|
}
|
|
return '<var class="'.$name.'">$';
|
|
}
|
|
return '</var>';
|
|
}
|
|
|
|
public function format_footnoteref($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$linkend = $attrs[Reader::XMLNS_DOCBOOK]["linkend"];
|
|
foreach($this->cchunk["footnote"] as $k => $note) {
|
|
if ($note["id"] === $linkend) {
|
|
return '<a href="#fnid' .$note["id"]. '"><sup>[' .($k + 1). ']</sup></a>';
|
|
}
|
|
}
|
|
trigger_error("footnoteref ID '$linkend' not found", E_USER_WARNING);
|
|
return "";
|
|
}
|
|
}
|
|
public function format_footnote($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$count = count($this->cchunk["footnote"]);
|
|
$noteid = isset($attrs[Reader::XMLNS_XML]["id"]) ? $attrs[Reader::XMLNS_XML]["id"] : $count + 1;
|
|
$note = array("id" => $noteid, "str" => "");
|
|
$this->cchunk["footnote"][$count] = $note;
|
|
if ($this->cchunk["table"]) {
|
|
$this->cchunk["tablefootnotes"][$count] = $noteid;
|
|
}
|
|
return '<a href="#fnid' .$noteid. '" name="fn'.$noteid.'"><sup>[' .($count + 1). ']</sup></a>';
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/* {{{ FIXME: These are crazy workarounds :( */
|
|
public function format_footnote_constant($open, $name, $attrs, $props) {
|
|
$k = count($this->cchunk["footnote"]) - 1;
|
|
$this->cchunk["footnote"][$k]["str"] .= self::format_constant($open, $name, $attrs, $props);
|
|
return "";
|
|
}
|
|
public function format_footnote_constant_text($value, $tag) {
|
|
$k = count($this->cchunk["footnote"]) - 1;
|
|
$this->cchunk["footnote"][$k]["str"] .= $value;
|
|
return "";
|
|
}
|
|
public function format_footnote_para($open, $name, $attrs, $props) {
|
|
$k = count($this->cchunk["footnote"]) - 1;
|
|
if ($open) {
|
|
$this->cchunk["footnote"][$k]["str"] .= '<span class="para footnote">';
|
|
return "";
|
|
}
|
|
|
|
$this->cchunk["footnote"][$k]["str"] .= "</span>";
|
|
return "";
|
|
}
|
|
public function format_footnote_para_text($value, $tag) {
|
|
$k = count($this->cchunk["footnote"]) - 1;
|
|
$this->cchunk["footnote"][$k]["str"] .= $value;
|
|
return "";
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
public function format_co($open, $name, $attrs, $props) {
|
|
if (($open || $props["empty"]) && isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$co = ++$this->cchunk["co"];
|
|
return '<a name="'.$attrs[Reader::XMLNS_XML]["id"].'" id="'.$attrs[Reader::XMLNS_XML]["id"].'">' .str_repeat("*", $co) .'</a>';
|
|
}
|
|
/* Suppress closing tag if any */
|
|
return "";
|
|
}
|
|
public function format_calloutlist($open, $name, $attrs) {
|
|
if ($open) {
|
|
$this->cchunk["callouts"] = 0;
|
|
return '<table>';
|
|
}
|
|
return '</table>';
|
|
}
|
|
public function format_callout($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<tr><td><a href="#'.$attrs[Reader::XMLNS_DOCBOOK]["arearefs"].'">' .str_repeat("*", ++$this->cchunk["callouts"]). '</a></td><td>';
|
|
}
|
|
return "</td></tr>\n";
|
|
}
|
|
|
|
public function format_manvolnum($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<span class="'.$name.'">(';
|
|
}
|
|
return ")</span>";
|
|
}
|
|
public function format_segmentedlist($open, $name, $attrs) {
|
|
$this->cchunk["segmentedlist"] = $this->dchunk["segmentedlist"];
|
|
if ($open) {
|
|
return '<table class="'.$name.'">';
|
|
}
|
|
return '</tbody></table>';
|
|
}
|
|
public function format_segtitle_text($value, $tag) {
|
|
$html = '';
|
|
if (!$this->cchunk["segmentedlist"]["segtitleopened"]) {
|
|
$html .= '<thead><tr>';
|
|
}
|
|
$html .= '<th>'.$this->TEXT($value).'</th>';
|
|
$this->cchunk["segmentedlist"]["segtitleopened"] = true;
|
|
|
|
// Don't close the row; we'll have to do that in the first seglistitem.
|
|
return $html;
|
|
}
|
|
public function format_seglistitem($open, $name, $attrs) {
|
|
if ($open) {
|
|
$html = '';
|
|
|
|
if (!$this->cchunk["segmentedlist"]["segtitleclosed"]) {
|
|
$html .= '</tr></thead><tbody>';
|
|
$this->cchunk["segmentedlist"]["segtitleclosed"] = true;
|
|
}
|
|
|
|
$html .= '<tr class="'.$name.'">';
|
|
return $html;
|
|
}
|
|
return '</tr>';
|
|
}
|
|
public function format_seg($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<td class="seg">';
|
|
}
|
|
return '</td>';
|
|
}
|
|
public function format_procedure($open, $name, $attrs) {
|
|
$this->cchunk["procedure"] = false;
|
|
if ($open) {
|
|
return '<div class="'.$name.'">';
|
|
}
|
|
return '</ol></div>';
|
|
}
|
|
public function format_step($open, $name, $attrs) {
|
|
if ($open) {
|
|
$ret = "";
|
|
if ($this->cchunk["procedure"] === false) {
|
|
$this->cchunk["procedure"] = true;
|
|
$ret = '<ol type="1">';
|
|
}
|
|
return $ret . "<li>";
|
|
}
|
|
return '</li>';
|
|
}
|
|
public function format_variablelist($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["role"])) {
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"]);
|
|
}
|
|
$classStr = $headerStr = $idStr = '';
|
|
if (isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$idStr = ' id="' . $attrs[Reader::XMLNS_XML]["id"] . '"';
|
|
}
|
|
if ($this->getRole() === 'constant_list') {
|
|
$tagName = 'table';
|
|
$classStr = ' class="doctable table"';
|
|
$headerStr = "\n" . $this->indent($props["depth"] + 1) . "<tr>\n"
|
|
. $this->indent($props["depth"] + 2) . "<th>"
|
|
. $this->autogen('Constants', $props['lang']) . "</th>\n"
|
|
. $this->indent($props["depth"] + 2) . "<th>"
|
|
. $this->autogen('Description', $props['lang']) . "</th>\n"
|
|
. $this->indent($props["depth"] + 1) . "</tr>";
|
|
} else {
|
|
$tagName = 'dl';
|
|
}
|
|
return '<' . $tagName . $idStr . $classStr . '>' . $headerStr;
|
|
}
|
|
$tagName = ($this->getRole() === 'constant_list') ? 'table' : 'dl';
|
|
$this->popRole();
|
|
return "</" . $tagName . ">";
|
|
}
|
|
public function format_varlistentry($open, $name, $attrs) {
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$this->cchunk['varlistentry']['id'] = $attrs[Reader::XMLNS_XML]["id"];
|
|
} else {
|
|
unset($this->cchunk['varlistentry']['id']);
|
|
}
|
|
return ($this->getRole() === 'constant_list') ? '<tr>' : '';
|
|
}
|
|
return ($this->getRole() === 'constant_list') ? '</tr>' : '';
|
|
}
|
|
public function format_varlistentry_term($open, $name, $attrs, $props) {
|
|
$tagName = ($this->getRole() === 'constant_list') ? 'td' : 'dt';
|
|
if ($open) {
|
|
if (isset($this->cchunk['varlistentry']['id'])) {
|
|
$id = $this->cchunk['varlistentry']['id'];
|
|
unset($this->cchunk['varlistentry']['id']);
|
|
return '<' . $tagName . ' id="' . $id . '">';
|
|
} else {
|
|
return "<" . $tagName . ">";
|
|
}
|
|
}
|
|
return "</" . $tagName . ">";
|
|
}
|
|
public function format_varlistentry_listitem($open, $name, $attrs) {
|
|
$tagName = ($this->getRole() === 'constant_list') ? 'td' : 'dd';
|
|
if ($open) {
|
|
return "<" . $tagName . ">";
|
|
}
|
|
return "</" . $tagName . ">";
|
|
}
|
|
public function format_term($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if ($props["sibling"] == $name) {
|
|
return '<br /><span class="' .$name. '">';
|
|
}
|
|
return '<span class="' .$name. '">';
|
|
}
|
|
return "</span>";
|
|
}
|
|
public function format_trademark($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<span class=' .$name. '">';
|
|
}
|
|
return '®</span>';
|
|
}
|
|
public function format_userinput($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<strong class="' .$name. '"><code>';
|
|
}
|
|
return "</code></strong>";
|
|
}
|
|
public function format_systemitem($open, $name, $attrs) {
|
|
if ($open) {
|
|
$val = isset($attrs[Reader::XMLNS_DOCBOOK]["role"]) ? $attrs[Reader::XMLNS_DOCBOOK]["role"] : null;
|
|
switch($val) {
|
|
case "directive":
|
|
/* FIXME: Different roles should probably be handled differently */
|
|
default:
|
|
return '<code class="systemitem ' .$name. '">';
|
|
}
|
|
}
|
|
return "</code>";
|
|
}
|
|
public function format_example_content($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<div class="example-contents"><p>';
|
|
}
|
|
return "</p></div>";
|
|
}
|
|
public function format_programlisting($open, $name, $attrs) {
|
|
if ($open) {
|
|
$this->pushRole($attrs[Reader::XMLNS_DOCBOOK]["role"] ?? null);
|
|
return '<div class="example-contents">';
|
|
}
|
|
$this->popRole();
|
|
return "</div>\n";
|
|
}
|
|
public function format_programlisting_text($value, $tag) {
|
|
return $this->CDATA($value);
|
|
}
|
|
public function format_screen($open, $name, $attrs) {
|
|
if ($open) {
|
|
if ($this->getRole() !== "examples"
|
|
&& $this->getRole() !== "description"
|
|
&& $this->getRole() !== "notes"
|
|
&& $this->getRole() !== "returnvalues"
|
|
&& $this->getRole() !== "parameters") {
|
|
$this->pushRole('');
|
|
}
|
|
return '<div class="example-contents ' .$name. '">';
|
|
}
|
|
if ($this->getRole() !== "examples"
|
|
&& $this->getRole() !== "description"
|
|
&& $this->getRole() !== "notes"
|
|
&& $this->getRole() !== "returnvalues"
|
|
&& $this->getRole() !== "parameters") {
|
|
$this->popRole();
|
|
}
|
|
return '</div>';
|
|
}
|
|
public function format_constant($open, $name, $attrs, $props)
|
|
{
|
|
if ($open) {
|
|
if (str_contains($props["innerXml"], '<replaceable')) {
|
|
$this->pushRole("constant_group");
|
|
$this->cchunk["constant"] = $props["innerXml"];
|
|
}
|
|
return "<strong><code>";
|
|
}
|
|
|
|
if ($this->getRole() === "constant_group") {
|
|
$this->popRole();
|
|
|
|
$value = str_replace(
|
|
["<replaceable xmlns=\"http://docbook.org/ns/docbook\">", "</replaceable>"],
|
|
["<span class=\"replaceable\">", "</span>"],
|
|
strip_tags($this->cchunk["constant"], "<replaceable>")
|
|
);
|
|
|
|
$link = $this->createReplaceableConstantLink(strip_tags($this->cchunk["constant"], "<replaceable>"));
|
|
$this->cchunk["constant"] = "";
|
|
|
|
if ($link === "") {
|
|
return $value . '</code></strong>';
|
|
}
|
|
|
|
return '<a href="' . $link . '">' . $value . '</a></code></strong>';
|
|
}
|
|
return "</code></strong>";
|
|
}
|
|
|
|
/**
|
|
* Creates a link to the first constant in the index
|
|
* that matches the pattern of a constant containing a <replaceable> tag
|
|
* or returns an empty string if no match was found.
|
|
*
|
|
* This works only with one set of <replaceable> tags in a constant
|
|
* e.g. CURLE_<replaceable>*</replaceable> or DOM_<replaceable>*</replaceable>_NODE
|
|
*/
|
|
private function createReplaceableConstantLink(string $constant): string {
|
|
$pattern = "/" . preg_replace(
|
|
"/<replaceable.*<\/replaceable>/",
|
|
".*",
|
|
str_replace(
|
|
".",
|
|
"\.",
|
|
$this->convertConstantNameToId($constant)
|
|
)
|
|
) ."/";
|
|
|
|
$matchingConstantId = "";
|
|
foreach ($this->indexes as $index) {
|
|
if (preg_match($pattern, $index["docbook_id"])) {
|
|
$matchingConstantId = $index["docbook_id"];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $matchingConstantId === "" ? "" : $this->createLink($matchingConstantId);
|
|
}
|
|
|
|
private function convertConstantNameToId(string $constantName): string {
|
|
$tempLinkValue = str_replace(
|
|
array("\\", "_"),
|
|
array("-", "-"),
|
|
trim($this->normalizeFQN($constantName), "_")
|
|
);
|
|
|
|
if (str_contains($constantName, '::')) {
|
|
// class constant
|
|
list($extensionAndClass, $constant) = explode("::", $tempLinkValue);
|
|
$normalizedLinkFormat = $extensionAndClass . ".constants." . trim($constant, "-");
|
|
} else {
|
|
$normalizedLinkFormat = 'constant.' . $tempLinkValue;
|
|
}
|
|
|
|
return $normalizedLinkFormat;
|
|
}
|
|
|
|
public function format_constant_text($value, $tag) {
|
|
if ($this->getRole() === "constant_group") {
|
|
return "";
|
|
}
|
|
|
|
$normalizedLinkFormat = $this->convertConstantNameToId($value);
|
|
|
|
$link = $this->createLink($normalizedLinkFormat);
|
|
|
|
if ($link === null) {
|
|
return $value;
|
|
}
|
|
|
|
return '<a href="' . $link . '">' . $value . '</a>';
|
|
}
|
|
public function format_replaceable($open, $name, $attrs, $props) {
|
|
if ($this->getRole() === "constant_group") {
|
|
return "";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function format_property_text($value, $tag) {
|
|
if (! str_contains($value, '::')) {
|
|
return $value;
|
|
}
|
|
|
|
$tempLinkValue = str_replace(
|
|
["\\", "_", "$"],
|
|
["-", "-", ""],
|
|
trim($this->normalizeFQN($value), "_")
|
|
);
|
|
|
|
list($extensionAndClass, $property) = explode("::", $tempLinkValue);
|
|
$normalizedLinkFormat = $extensionAndClass . ".props." . trim($property, "-");
|
|
|
|
$link = $this->createLink($normalizedLinkFormat);
|
|
|
|
if ($link === null || $link === "") {
|
|
return $value;
|
|
}
|
|
|
|
return '<a href="' . $link . '">' . $value . '</a>';
|
|
}
|
|
|
|
protected function normalizeFQN(string $fqn): string {
|
|
return \ltrim(\strtolower($fqn), "\\");
|
|
}
|
|
|
|
public function admonition_title($title, $lang)
|
|
{
|
|
return '<strong class="' .(strtolower($title)). '">' .($this->autogen($title, $lang)). '</strong>';
|
|
}
|
|
public function format_admonition($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<div class="'. $name. '">' .$this->admonition_title($name, $props["lang"]);
|
|
}
|
|
return "</div>";
|
|
}
|
|
public function format_authorgroup_author($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if ($props["sibling"] !== $name) {
|
|
return '<div class="'.$name.' vcard">' .$this->admonition_title("by", $props["lang"]). ':<br />';
|
|
}
|
|
return '<div class="'.$name.' vcard">';
|
|
}
|
|
return "</div>\n";
|
|
}
|
|
public function format_editor($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<div class="editor vcard">' .$this->admonition_title("editedby", $props["lang"]). ': ';
|
|
}
|
|
return "</div>\n";
|
|
}
|
|
public function format_note($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<blockquote class="note"><p>'.$this->admonition_title("note", $props["lang"]). ': ';
|
|
}
|
|
return "</p></blockquote>";
|
|
}
|
|
public function format_note_title($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
return '<strong>';
|
|
}
|
|
return '</strong><br />';
|
|
}
|
|
public function format_example($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
++$this->exampleCounter;
|
|
if (isset($props["id"])) {
|
|
return '<div class="' . $name . '" id="' . $props["id"] . '">';
|
|
}
|
|
return '<div class="' . $name . '" id="' . $this->getGeneratedExampleId($this->exampleCounter - 1) . '">';
|
|
}
|
|
return '</div>';
|
|
}
|
|
public function format_example_title($open, $name, $attrs, $props)
|
|
{
|
|
if ($props["empty"]) {
|
|
return "";
|
|
}
|
|
if ($open) {
|
|
return "<p><strong>" . ($this->autogen('example', $props['lang'])
|
|
. (isset($this->cchunk["examples"]) ? ++$this->cchunk["examples"] : "")) . " ";
|
|
}
|
|
return "</strong></p>";
|
|
}
|
|
public function format_table_title($open, $name, $attrs, $props)
|
|
{
|
|
if ($props["empty"]) {
|
|
return "";
|
|
}
|
|
if ($open) {
|
|
return "<caption><strong>";
|
|
}
|
|
return "</strong></caption>";
|
|
}
|
|
public function format_variablelist_title($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return ($this->getRole() === 'constant_list') ? "<caption><strong>" : "<strong>";
|
|
}
|
|
return ($this->getRole() === 'constant_list') ? "</strong></caption>" : "</strong>";
|
|
}
|
|
|
|
public function format_mediaobject($open, $name, $attrs) {
|
|
$this->cchunk["mediaobject"] = $this->dchunk["mediaobject"];
|
|
if ($open) {
|
|
return '<div class="'.$name.'">';
|
|
}
|
|
return '</div>';
|
|
}
|
|
public function format_alt_text($value, $tag) {
|
|
$this->cchunk["mediaobject"]["alt"] = $value;
|
|
}
|
|
public function format_imagedata($open, $name, $attrs) {
|
|
$file = $attrs[Reader::XMLNS_DOCBOOK]["fileref"];
|
|
if ($newpath = $this->mediamanager->handleFile($file)) {
|
|
$curfile = $this->mediamanager->findFile($file);
|
|
$width = isset($attrs[Reader::XMLNS_DOCBOOK]["width"]) ? 'width="' . $attrs[Reader::XMLNS_DOCBOOK]["width"] . '"' : '';
|
|
$height = isset($attrs[Reader::XMLNS_DOCBOOK]["depth"]) ? 'height="' . $attrs[Reader::XMLNS_DOCBOOK]["depth"] . '"' : '';
|
|
$alt = 'alt="' . ($this->cchunk["mediaobject"]["alt"] !== false ? $this->cchunk["mediaobject"]["alt"] : basename($file)) . '"';
|
|
|
|
// Generate height and width when none are supplied.
|
|
if ($curfile && '' === $width . $height) {
|
|
list(,,,$dimensions,,,,) = getimagesize($curfile);
|
|
} else {
|
|
$dimensions = $width . ' ' . $height;
|
|
}
|
|
|
|
// Generate warnings when only 1 dimension supplied or alt is not supplied.
|
|
if (!$width xor !$height) {
|
|
$this->outputHandler->v('Missing %s attribute for %s', (!$width ? 'width' : 'height'), $file, VERBOSE_MISSING_ATTRIBUTES);
|
|
}
|
|
if (false === $this->cchunk["mediaobject"]["alt"]) {
|
|
$this->outputHandler->v('Missing alt attribute for %s', $file, VERBOSE_MISSING_ATTRIBUTES);
|
|
}
|
|
|
|
return '<img src="' . $newpath . '" ' . $alt . ' ' . $dimensions . ' />';
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
public function format_table($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$this->cchunk["table"] = true;
|
|
// Initialize an empty tgroup in case we never process such element
|
|
Format::tgroup(array());
|
|
$idstr = '';
|
|
if (isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$idstr = ' id="' . $attrs[Reader::XMLNS_XML]["id"] . '"';
|
|
}
|
|
return '<table' . $idstr . ' class="doctable ' .$name. '">';
|
|
}
|
|
$this->cchunk["table"] = false;
|
|
$str = "";
|
|
if (isset($this->cchunk["tablefootnotes"]) && $this->cchunk["tablefootnotes"]) {
|
|
$opts = array(Reader::XMLNS_DOCBOOK => array());
|
|
|
|
$str = $this->format_tbody(true, "footnote", $opts);
|
|
$str .= $this->format_row(true, "footnote", $opts);
|
|
$str .= $this->format_entry(true, "footnote", $opts, $props+array("colspan" => $this->getColCount()));
|
|
|
|
foreach ($this->cchunk["tablefootnotes"] as $k => $noteid) {
|
|
$str .= '<div class="footnote">';
|
|
$str .= '<a name="fnid' .$noteid. '" href="#fn' .$noteid .'"><sup>[' .($k + 1). ']</sup></a>' .$this->cchunk["footnote"][$k]["str"];
|
|
unset($this->cchunk["footnote"][$k]);
|
|
$str .= "</div>\n";
|
|
|
|
}
|
|
$str .= $this->format_entry(false, "footnote", $opts, $props);
|
|
$str .= $this->format_row(false, "footnote", $opts);
|
|
$str .= $this->format_tbody(false, "footnote", $opts);
|
|
|
|
$this->cchunk["tablefootnotes"] = $this->dchunk["tablefootnotes"];
|
|
}
|
|
return "$str</table>\n";
|
|
}
|
|
public function format_tgroup($open, $name, $attrs) {
|
|
if ($open) {
|
|
Format::tgroup($attrs[Reader::XMLNS_DOCBOOK]);
|
|
return '';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
private static function parse_table_entry_attributes($attrs)
|
|
{
|
|
$style = array();
|
|
$retval = '';
|
|
if (!empty($attrs['align'])) {
|
|
if ('char' != $attrs['align']) {
|
|
$style[] = 'text-align: ' . $attrs['align'];
|
|
} elseif (isset($attrs['char'])) {
|
|
// There's no analogue in CSS, but as this stuff isn't supported
|
|
// in any browser, it is unlikely to appear in DocBook anyway
|
|
$retval .= ' align="char" char="'
|
|
. htmlspecialchars($attrs["char"], ENT_QUOTES) . '"';
|
|
if (isset($attrs['charoff'])) {
|
|
$retval .= ' charoff="'
|
|
. htmlspecialchars($attrs["charoff"], ENT_QUOTES) . '"';
|
|
}
|
|
}
|
|
}
|
|
if (isset($attrs["valign"])) {
|
|
$style[] = 'vertical-align: ' . $attrs["valign"];
|
|
}
|
|
if (isset($attrs["colwidth"])) {
|
|
if (preg_match('/^\\d+\\*$/', $attrs['colwidth'])) {
|
|
// relative_length measure has no analogue in CSS and is
|
|
// unsupported in browsers, leave as is
|
|
$retval .= ' width="' . $attrs['colwidth'] . '"';
|
|
} else {
|
|
// probably fixed width, use inline styles
|
|
$style[] = 'width: ' . $attrs['colwidth'];
|
|
}
|
|
}
|
|
return $retval . (empty($style) ? '' : ' style="' . implode('; ', $style) . ';"');
|
|
}
|
|
|
|
public function format_colspec($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
$str = self::parse_table_entry_attributes(Format::colspec($attrs[Reader::XMLNS_DOCBOOK]));
|
|
return '<col' . $str . ' />';
|
|
}
|
|
/* noop */
|
|
}
|
|
|
|
public function format_th($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['valign'])) {
|
|
return '<' . $name . ' style="vertical-align: '
|
|
. $attrs[Reader::XMLNS_DOCBOOK]['valign'] . ';">';
|
|
} else {
|
|
return '<' . $name . '>';
|
|
}
|
|
}
|
|
return "</$name>\n";
|
|
}
|
|
|
|
public function format_tbody($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['valign'])) {
|
|
return '<tbody class="' . $name . '" style="vertical-align: '
|
|
. $attrs[Reader::XMLNS_DOCBOOK]['valign'] . ';">';
|
|
} else {
|
|
return '<tbody class="' . $name . '">';
|
|
}
|
|
}
|
|
return "</tbody>";
|
|
}
|
|
|
|
public function format_row($open, $name, $attrs)
|
|
{
|
|
if ($open) {
|
|
$idstr = '';
|
|
if (isset($attrs[Reader::XMLNS_XML]['id'])) {
|
|
$idstr = ' id="'. $attrs[Reader::XMLNS_XML]['id']. '"';
|
|
}
|
|
Format::initRow();
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['valign'])) {
|
|
return '<tr' . $idstr . ' style="vertical-align: '
|
|
. $attrs[Reader::XMLNS_DOCBOOK]['valign'] . ';">';
|
|
} else {
|
|
return '<tr' . $idstr . '>';
|
|
}
|
|
}
|
|
return "</tr>\n";
|
|
}
|
|
|
|
public function format_th_entry($open, $name, $attrs, $props) {
|
|
if ($props["empty"]) {
|
|
return '<th class="empty"> </th>';
|
|
}
|
|
if ($open) {
|
|
$colspan = Format::colspan($attrs[Reader::XMLNS_DOCBOOK]);
|
|
if ($colspan == 1) {
|
|
return '<th>';
|
|
} else {
|
|
return '<th colspan="' .((int)$colspan). '">';
|
|
}
|
|
}
|
|
return '</th>';
|
|
}
|
|
public function format_entry($open, $name, $attrs, $props) {
|
|
if ($props["empty"]) {
|
|
return '<td class="empty"> </td>';
|
|
}
|
|
if ($open) {
|
|
$dbattrs = (array)Format::getColspec($attrs[Reader::XMLNS_DOCBOOK]);
|
|
|
|
$retval = "";
|
|
if (isset($dbattrs["colname"])) {
|
|
for($i=Format::getEntryOffset($dbattrs); $i>0; --$i) {
|
|
$retval .= '<td class="empty"> </td>';
|
|
}
|
|
}
|
|
|
|
/*
|
|
* "colspan" is *not* an standard prop, only used to overwrite the
|
|
* colspan for <footnote>s in tables
|
|
*/
|
|
if (isset($props["colspan"])) {
|
|
$colspan = $props["colspan"];
|
|
} else {
|
|
$colspan = Format::colspan($dbattrs);
|
|
}
|
|
|
|
$rowspan = Format::rowspan($dbattrs);
|
|
$moreattrs = self::parse_table_entry_attributes($dbattrs);
|
|
|
|
$sColspan = $colspan == 1 ? '' : ' colspan="' .((int)$colspan) . '"';
|
|
$sRowspan = $rowspan == 1 ? '' : ' rowspan="' .((int)$rowspan). '"';
|
|
return $retval. '<td' . $sColspan . $sRowspan . $moreattrs. '>';
|
|
}
|
|
return "</td>";
|
|
}
|
|
public function format_qandaset($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$xml = "<qandaset>" . $props["innerXml"] . "</qandaset>";
|
|
$doc = new \DOMDocument;
|
|
$doc->loadXml($xml);
|
|
|
|
$xp = new \DOMXPath($doc);
|
|
$xp->registerNamespace("db", Reader::XMLNS_DOCBOOK);
|
|
|
|
$questions = $xp->query("//db:qandaentry/db:question");
|
|
|
|
$retval = '<div class="qandaset"><ol class="qandaset_questions">';
|
|
foreach($questions as $node) {
|
|
$id = $xp->evaluate("ancestor::db:qandaentry", $node)->item(0)->getAttributeNs(Reader::XMLNS_XML, "id");
|
|
|
|
/* FIXME: No ID? How can we create an anchor for it then? */
|
|
if (!$id) {
|
|
$id = uniqid("phd");
|
|
}
|
|
|
|
$retval .= '<li><a href="#'.$id.'">'.htmlentities($node->textContent, ENT_QUOTES, "UTF-8").'</a></li>';
|
|
}
|
|
$retval .= "</ol></div>";
|
|
return $retval;
|
|
}
|
|
}
|
|
public function format_question($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<dt><strong>';
|
|
}
|
|
return '</strong></dt>';
|
|
}
|
|
public function format_phd_question($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$href = $this->createLink($attrs[Reader::XMLNS_XML]["id"]);
|
|
return '<li><a href="' .$href. '">';
|
|
}
|
|
return '</a></li>';
|
|
}
|
|
|
|
public function format_citation($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '[<span class="citation">';
|
|
}
|
|
return '</span>]';
|
|
}
|
|
|
|
public function format_email_text($value) {
|
|
return '<<a href="mailto:' . $value . '">' . $value . '</a>>';
|
|
}
|
|
|
|
public function format_bold_paragraph($open, $name, $attrs, $props)
|
|
{
|
|
if ($props["empty"]) {
|
|
return "";
|
|
}
|
|
if ($open) {
|
|
return "<p><strong>";
|
|
}
|
|
return "</strong></p>";
|
|
}
|
|
|
|
/**
|
|
* Functions from the old XHTMLPhDFormat
|
|
*/
|
|
public function format_legalnotice_chunk($open, $name, $attrs) {
|
|
if ($open) {
|
|
return '<div id="legalnotice">';
|
|
}
|
|
return "</div>\n";
|
|
}
|
|
|
|
public function format_div($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<div class="' . $name . '">';
|
|
}
|
|
return '</div>';
|
|
}
|
|
|
|
public function format_screen_text($value, $tag) {
|
|
return nl2br($this->TEXT($value));
|
|
}
|
|
|
|
/**
|
|
* Renders a <tag class=""> tag.
|
|
*
|
|
* @return string HTML code
|
|
*/
|
|
public function format_tag($open, $name, $attrs, $props) {
|
|
static $arFixes = array(
|
|
'attribute' => array('', ''),
|
|
'attvalue' => array('"', '"'),
|
|
'comment' => array('<!--', '-->'),
|
|
'element' => array('', ''),
|
|
'emptytag' => array('<', '/>'),
|
|
'endtag' => array('</', '>'),
|
|
'genentity' => array('&', ';'),
|
|
'localname' => array('', ''),
|
|
'namespace' => array('', ''),
|
|
'numcharref' => array('&#', ';'),
|
|
'paramentity' => array('%', ';'),
|
|
'pi' => array('<?', '?>'),
|
|
'prefix' => array('', ''),
|
|
'starttag' => array('<', '>'),
|
|
'xmlpi' => array('<?', '?>'),
|
|
);
|
|
if ($props['empty']) {
|
|
return '';
|
|
}
|
|
|
|
$class = 'starttag';
|
|
if (isset($attrs['class'])) {
|
|
$class = $attrs['class'];
|
|
}
|
|
|
|
if (!isset($arFixes[$class])) {
|
|
trigger_error('Unknown tag class "' . $class . '"', E_USER_WARNING);
|
|
$class = 'starttag';
|
|
}
|
|
if (!$open) {
|
|
return $arFixes[$class][1] . '</code>';
|
|
}
|
|
|
|
return '<code>' . $arFixes[$class][0];
|
|
}
|
|
|
|
public function format_dl($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<dl class="' . $name . '">';
|
|
}
|
|
return '</dl>';
|
|
}
|
|
|
|
public function format_itemizedlist($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
return '<ul class="' . $name . '">';
|
|
}
|
|
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") {
|
|
$this->appendToBuffer = $open;
|
|
if (! $open) {
|
|
$this->cchunk["simplelist"]["members"][] = $this->buffer;
|
|
}
|
|
$this->buffer = '';
|
|
return '';
|
|
}
|
|
if ($open) {
|
|
return '<li>';
|
|
}
|
|
return '</li>';
|
|
}
|
|
|
|
public function format_member_text($value, $tag) {
|
|
return $value;
|
|
}
|
|
|
|
public function format_orderedlist($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$numeration = "1";
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["numeration"])) {
|
|
switch($attrs[Reader::XMLNS_DOCBOOK]["numeration"]) {
|
|
case "upperalpha":
|
|
$numeration = "A";
|
|
break;
|
|
case "loweralpha":
|
|
$numeration = "a";
|
|
break;
|
|
case "upperroman":
|
|
$numeration = "I";
|
|
break;
|
|
case "lowerroman":
|
|
$numeration = "i";
|
|
break;
|
|
}
|
|
}
|
|
return '<ol type="' .$numeration. '">';
|
|
}
|
|
return '</ol>';
|
|
}
|
|
|
|
/* Support for key inputs is coded like junk */
|
|
public function format_keycap($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$content = '';
|
|
if ($props['sibling']) {
|
|
$content = '+';
|
|
}
|
|
return $content . '<kbd class="' . $name . '">';
|
|
}
|
|
return '</kbd>';
|
|
}
|
|
|
|
public function format_keycombo($open, $name, $attrs, $props) {
|
|
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]["action"])) {
|
|
if ($attrs[Reader::XMLNS_DOCBOOK]["action"] !== "simul") {
|
|
trigger_error(vsprintf('No support for keycombo action = %s', [$attrs[Reader::XMLNS_DOCBOOK]["action"]]), E_USER_WARNING);
|
|
}
|
|
}
|
|
if ($open) {
|
|
return '<kbd class="' . $name . '">';
|
|
}
|
|
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;
|
|
}
|
|
|
|
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') ||
|
|
($elementStack[$currentDepth - 1] === 'oointerface' && $elementStack[$currentDepth] === 'interfacename')
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
return $whitespace;
|
|
}
|
|
|
|
public function format_caption($open, $name, $attrs, $props) {
|
|
return $open ? '<div class="caption">' : '</div>';
|
|
}
|
|
}
|