aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorC. Scott Ananian <cscott@cscott.net>2022-05-27 12:20:35 -0400
committerC. Scott Ananian <cscott@cscott.net>2022-07-21 15:29:11 -0400
commitcc798985225a58b1ea46d69ee9a2f5d7c7a8a4db (patch)
tree63fe2daa389f9e6ffb53aa8e03c05d0a6a776aed
parentdff8a1571e2d404df9cafcd3c8667d7b02734ecd (diff)
downloadmediawikicore-cc798985225a58b1ea46d69ee9a2f5d7c7a8a4db.tar.gz
mediawikicore-cc798985225a58b1ea46d69ee9a2f5d7c7a8a4db.zip
ParserOption/ParserOutput flag to suppress or hide the table of contents
There are two related issues here: first, when parsing non-wikitext pages for side effects (categories, etc) we want to ensure that any spurious `===` or `<h2>` on the page don't create nonsense "sections". We introduce a ParserOption to suppress the ToC in this case; a follow-up patch will set this parser option from the correct path in CodeContentHandler and its subclasses. [T307691] Second, modern skins can generate the ToC on-the-fly outside the content area, and need to be able to regenerate the ToC from API output when the page is edited. A ParserOutput flag is added to mirror the $enoughToc variable from the parser to indicate whether or not the ToC should be generated and/or updated after edit. (See I6cf76c870124c162dc1bcbc2f7e9ca0c5fdcd10e for parallel code to echo this value in ApiParse.) Bug: T294950 Bug: T307691 Change-Id: I35e199cca40c0e4359ac493e5806dcf4ae49321c
-rw-r--r--includes/parser/Parser.php21
-rw-r--r--includes/parser/ParserOptions.php26
-rw-r--r--includes/parser/ParserOutputFlags.php16
-rw-r--r--tests/parser/parserTests.txt216
4 files changed, 257 insertions, 22 deletions
diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php
index a3dd74340534..c0116d011313 100644
--- a/includes/parser/Parser.php
+++ b/includes/parser/Parser.php
@@ -4499,8 +4499,9 @@ class Parser {
$this->setOutputType( $oldType );
- # Never ever show TOC if no headers
- if ( $numVisible < 1 ) {
+ # Never ever show TOC if no headers (or suppressed)
+ $suppressToc = $this->mOptions->getSuppressTOC();
+ if ( $numVisible < 1 || $suppressToc ) {
$enoughToc = false;
}
@@ -4510,9 +4511,19 @@ class Parser {
}
$toc = Linker::tocList( $toc, $this->mOptions->getUserLangObj() );
$this->mOutput->setTOCHTML( $toc );
- }
-
- if ( $isMain ) {
+ } else {
+ // Record the fact that the TOC should not be shown. T294950
+ $this->mOutput->setOutputFlag( ParserOutputFlags::HIDE_TOC );
+ }
+
+ if ( $isMain && !$suppressToc ) {
+ // We generally output the section information via the API
+ // even if there isn't "enough" of a ToC to merit showing
+ // it -- but the "suppress TOC" parser option is set when
+ // any sections that might be found aren't "really there"
+ // (ie, JavaScript content that might have spurious === or
+ // <h2>: T307691) so we will *not* set section information
+ // in that case.
$this->mOutput->setSections( $tocraw );
}
diff --git a/includes/parser/ParserOptions.php b/includes/parser/ParserOptions.php
index b1000a750159..bc0427a2b38d 100644
--- a/includes/parser/ParserOptions.php
+++ b/includes/parser/ParserOptions.php
@@ -759,6 +759,31 @@ class ParserOptions {
}
/**
+ * Should the table of contents be suppressed?
+ * Used when parsing "code" pages (like JavaScript) as wikitext
+ * for backlink support and categories, but where we don't want
+ * other metadata generated (like the table of contents).
+ * @see T307691
+ * @since 1.39
+ * @return bool
+ */
+ public function getSuppressTOC() {
+ return $this->getOption( 'suppressTOC' );
+ }
+
+ /**
+ * Suppress generation of the table of contents.
+ * Used when parsing "code" pages (like JavaScript) as wikitext
+ * for backlink support and categories, but where we don't want
+ * other metadata generated (like the table of contents).
+ * @see T307691
+ * @since 1.39
+ */
+ public function setSuppressTOC() {
+ $this->setOption( 'suppressTOC', true );
+ }
+
+ /**
* If the wiki is configured to allow raw html ($wgRawHtml = true)
* is it allowed in the specific case of parsing this page.
*
@@ -1129,6 +1154,7 @@ class ParserOptions {
'interfaceMessage' => false,
'targetLanguage' => null,
'removeComments' => true,
+ 'suppressTOC' => false,
'enableLimitReport' => false,
'preSaveTransform' => true,
'isPreview' => false,
diff --git a/includes/parser/ParserOutputFlags.php b/includes/parser/ParserOutputFlags.php
index 70e206e79ad0..007083d589fb 100644
--- a/includes/parser/ParserOutputFlags.php
+++ b/includes/parser/ParserOutputFlags.php
@@ -50,11 +50,6 @@ class ParserOutputFlags {
public const NO_GALLERY = 'mw-NoGallery';
/**
- * @var string Used to suppress language conversion in ToC contents.
- */
- public const NO_TOC_CONVERSION = 'no-toc-conversion';
-
- /**
* @var string Whether OOUI should be enabled.
* @see \ParserOutput::getEnableOOUI()
* @see \ParserOutput::setEnableOOUI()
@@ -99,6 +94,16 @@ class ParserOutputFlags {
// These flags are stored in the ParserOutput::$mFlags array
/**
+ * @var string Hide the table of contents in the skin?
+ */
+ public const HIDE_TOC = 'hide-toc';
+
+ /**
+ * @var string Used to suppress language conversion in ToC contents.
+ */
+ public const NO_TOC_CONVERSION = 'no-toc-conversion';
+
+ /**
* @var string
*/
public const VARY_REVISION = 'vary-revision';
@@ -161,6 +166,7 @@ class ParserOutputFlags {
self::NO_INDEX_POLICY,
self::NEW_SECTION,
self::HIDE_NEW_SECTION,
+ self::HIDE_TOC,
self::PREVENT_CLICKJACKING,
self::VARY_REVISION,
self::VARY_REVISION_ID,
diff --git a/tests/parser/parserTests.txt b/tests/parser/parserTests.txt
index aff1ea258777..0a009bcc4f2a 100644
--- a/tests/parser/parserTests.txt
+++ b/tests/parser/parserTests.txt
@@ -11475,7 +11475,7 @@ showflags
!! html/*
<p>1337
</p>
-flags=vary-revision-id
+flags=hide-toc, vary-revision-id
!! end
!! test
@@ -11488,7 +11488,7 @@ showflags
!! html/*
<p>1337
</p>
-flags=vary-revision-id
+flags=hide-toc, vary-revision-id
!! end
!! test
@@ -11502,7 +11502,7 @@ showflags
!! html/*
<p>19700101000203
</p>
-flags=
+flags=hide-toc
!! end
!! test
@@ -11515,7 +11515,7 @@ showflags
!! html/*
<p>123
</p>
-flags=vary-revision-timestamp
+flags=hide-toc, vary-revision-timestamp
!! end
!! test
@@ -11529,7 +11529,7 @@ showflags
!! html/*
<p>127.0.0.1
</p>
-flags=vary-user
+flags=hide-toc, vary-user
!! end
!! test
@@ -11543,7 +11543,7 @@ showflags
!! html/*
<p>1337
</p>
-flags=vary-revision-id
+flags=hide-toc, vary-revision-id
!! end
!! test
@@ -11555,7 +11555,7 @@ showflags
{{REVISIONID:{{PAGENAME}}}}
!! html/*
-flags=vary-revision-id
+flags=hide-toc, vary-revision-id
!! end
!! test
@@ -11569,7 +11569,7 @@ showflags
!! html/*
<p>19700101000203
</p>
-flags=vary-revision-timestamp
+flags=hide-toc, vary-revision-timestamp
!! end
!! test
@@ -11583,7 +11583,7 @@ showflags
!! html/*
<p>1
</p>
-flags=vary-revision-timestamp
+flags=hide-toc, vary-revision-timestamp
!! end
!! test
@@ -11597,7 +11597,7 @@ showflags
!! html/*
<p>01
</p>
-flags=vary-revision-timestamp
+flags=hide-toc, vary-revision-timestamp
!! end
!! test
@@ -11611,7 +11611,7 @@ showflags
!! html/*
<p>1970
</p>
-flags=vary-revision-timestamp
+flags=hide-toc, vary-revision-timestamp
!! end
!! test
@@ -11625,7 +11625,7 @@ showflags
!! html/*
<p>25
</p>
-flags=vary-revision-sha1
+flags=hide-toc, vary-revision-sha1
!! end
!! test
@@ -16791,6 +16791,8 @@ Template:sections
!! test
Template with sections, __NOTOC__
+!! options
+showflags
!! wikitext
__NOTOC__
==Section 0==
@@ -16801,6 +16803,193 @@ __NOTOC__
<h3><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=T-1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=T-2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<h2><span class="mw-headline" id="Section_4">Section 4</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Section 4">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+flags=hide-toc
+!! end
+
+!! test
+T307691: hide-toc flag: no sections
+!! options
+showflags
+!! wikitext
+!! html
+
+flags=hide-toc
+!! end
+
+# You can't force a TOC if there aren't any sections
+!! test
+T307691: hide-toc flag: no sections, but __FORCETOC__
+!! options
+showflags
+!! wikitext
+__FORCETOC__
+!! html
+
+flags=hide-toc
+!! end
+
+# Placing a manual __TOC__ doesn't do anything if there aren't any sections
+!! test
+T307691: hide-toc flag: no sections, but __TOC__
+!! options
+showflags
+!! wikitext
+__TOC__
+!! html
+
+flags=hide-toc
+!! end
+
+!! test
+T307691: hide-toc flag: no sections, and __NOTOC__
+!! options
+showflags
+!! wikitext
+__NOTOC__
+!! html
+
+flags=hide-toc
+!! end
+
+!! test
+T307691: hide-toc flag: not "enough" sections
+!! options
+showflags
+!! wikitext
+== One ==
+!! html
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+flags=hide-toc
+!! end
+
+!! test
+T307691: hide-toc flag: not "enough" sections, but __FORCETOC__
+!! options
+showflags
+!! wikitext
+__FORCETOC__
+== One ==
+!! html
+<div id="toc" class="toc" role="navigation" aria-labelledby="mw-toc-heading"><input type="checkbox" role="button" id="toctogglecheckbox" class="toctogglecheckbox" style="display:none" /><div class="toctitle" lang="en" dir="ltr"><h2 id="mw-toc-heading">Contents</h2><span class="toctogglespan"><label class="toctogglelabel" for="toctogglecheckbox"></label></span></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#One"><span class="tocnumber">1</span> <span class="toctext">One</span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+flags=
+!! end
+
+!! test
+T307691: hide-toc flag: not "enough" sections, but __TOC__
+!! options
+showflags
+!! wikitext
+== One ==
+__TOC__
+!! html
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<div id="toc" class="toc" role="navigation" aria-labelledby="mw-toc-heading"><input type="checkbox" role="button" id="toctogglecheckbox" class="toctogglecheckbox" style="display:none" /><div class="toctitle" lang="en" dir="ltr"><h2 id="mw-toc-heading">Contents</h2><span class="toctogglespan"><label class="toctogglelabel" for="toctogglecheckbox"></label></span></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#One"><span class="tocnumber">1</span> <span class="toctext">One</span></a></li>
+</ul>
+</div>
+flags=
+!! end
+
+!! test
+T307691: hide-toc flag: not "enough" sections, and __NOTOC__
+!! options
+showflags
+!! wikitext
+__NOTOC__
+== One ==
+!! html
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+flags=hide-toc
+!! end
+
+!! test
+T307691: hide-toc flag: "enough" sections
+!! options
+showflags
+!! wikitext
+== One ==
+=== Two ===
+== Three ==
+=== Four ===
+!! html
+<div id="toc" class="toc" role="navigation" aria-labelledby="mw-toc-heading"><input type="checkbox" role="button" id="toctogglecheckbox" class="toctogglecheckbox" style="display:none" /><div class="toctitle" lang="en" dir="ltr"><h2 id="mw-toc-heading">Contents</h2><span class="toctogglespan"><label class="toctogglelabel" for="toctogglecheckbox"></label></span></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#One"><span class="tocnumber">1</span> <span class="toctext">One</span></a>
+<ul>
+<li class="toclevel-2 tocsection-2"><a href="#Two"><span class="tocnumber">1.1</span> <span class="toctext">Two</span></a></li>
+</ul>
+</li>
+<li class="toclevel-1 tocsection-3"><a href="#Three"><span class="tocnumber">2</span> <span class="toctext">Three</span></a>
+<ul>
+<li class="toclevel-2 tocsection-4"><a href="#Four"><span class="tocnumber">2.1</span> <span class="toctext">Four</span></a></li>
+</ul>
+</li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h3><span class="mw-headline" id="Two">Two</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Two">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+<h2><span class="mw-headline" id="Three">Three</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Three">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h3><span class="mw-headline" id="Four">Four</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Four">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+flags=
+!! end
+
+!! test
+T307691: hide-toc flag: "enough" sections and __FORCETOC__
+!! options
+showflags
+!! wikitext
+__FORCETOC__
+== One ==
+=== Two ===
+== Three ==
+=== Four ===
+!! html
+<div id="toc" class="toc" role="navigation" aria-labelledby="mw-toc-heading"><input type="checkbox" role="button" id="toctogglecheckbox" class="toctogglecheckbox" style="display:none" /><div class="toctitle" lang="en" dir="ltr"><h2 id="mw-toc-heading">Contents</h2><span class="toctogglespan"><label class="toctogglelabel" for="toctogglecheckbox"></label></span></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#One"><span class="tocnumber">1</span> <span class="toctext">One</span></a>
+<ul>
+<li class="toclevel-2 tocsection-2"><a href="#Two"><span class="tocnumber">1.1</span> <span class="toctext">Two</span></a></li>
+</ul>
+</li>
+<li class="toclevel-1 tocsection-3"><a href="#Three"><span class="tocnumber">2</span> <span class="toctext">Three</span></a>
+<ul>
+<li class="toclevel-2 tocsection-4"><a href="#Four"><span class="tocnumber">2.1</span> <span class="toctext">Four</span></a></li>
+</ul>
+</li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h3><span class="mw-headline" id="Two">Two</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Two">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+<h2><span class="mw-headline" id="Three">Three</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Three">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h3><span class="mw-headline" id="Four">Four</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Four">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+flags=
+!! end
+
+!! test
+T307691: hide-toc flag: "enough" sections and __NOTOC__
+!! options
+showflags
+!! wikitext
+__NOTOC__
+== One ==
+=== Two ===
+== Three ==
+=== Four ===
+!! html
+<h2><span class="mw-headline" id="One">One</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: One">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h3><span class="mw-headline" id="Two">Two</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Edit section: Two">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+<h2><span class="mw-headline" id="Three">Three</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Edit section: Three">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h3><span class="mw-headline" id="Four">Four</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Edit section: Four">edit</a><span class="mw-editsection-bracket">]</span></span></h3>
+flags=hide-toc
!! end
!! test
@@ -20423,12 +20612,15 @@ parsoid={ "modes": ["wt2html","html2html"], "normalizePhp": true }
!! test
__FORCETOC__ override
+!! options
+showflags
!! wikitext
__NEWSECTIONLINK__
__FORCETOC__
!! html/php
<p><br />
</p>
+flags=hide-toc
!! end
!! test