Skip to content

Commit d0f9056

Browse files
committed
GH Actions/publish-wiki: auto-generate table of contents
This commit adds steps to the workflow to auto-generate a GitHub wiki compatible table of contents in most wiki pages. This reduces the risk of a TOC being out-of-date or containing incorrectly formatted links, as well as reduces the maintenance burden. This action uses the `doctoc` pages to generate the table of contents and this can be tested locally using the same steps as used in the GH Actions workflow: ``` npm install -g doctoc cp -v -a wiki _wiki doctoc ./_wiki/ --github --maxlevel 4 --update-only doctoc ./_wiki/Version-4.0-User-Upgrade-Guide.md --github --maxlevel 3 --update-only ``` * The files are copied to a `_wiki` directory - which is `.gitignore`d - before pre-processing to reduce the risk of the source files being accidentally updated (and committed), which would undo the automation. * The `--github` flag puts the TOC generation in GitHub compatible mode. * The `--update-only` flag means that only markdown files containing the `<!-- START doctoc -->` and `<!-- END doctoc -->` markers will be updated and files without those markers will be left alone. * By default, the TOC will contain all headers up to the indicated `--maxlevel`. For the V 4.0 Dev upgrade guide, this looked weird, what with some "Upgrading" headers being at level 4 and some at level 5. To mitigate this, a couple of headers have been turned into "bold phrases" instead. Along the same lines, for the V 4.0 User upgrade guide, the level 4 headers were always "Upgrading". Those belong with their parent heading and IMO do not need to be separately called out in the TOC, which explains the second call to `doctoc` to overrule the TOC for that file specifically with a `--maxlevel 3` setting. To allow contributors to review the resulting pre-processed wiki files, the files are uploaded as an artifact when a PR dry-run is being executed and a comment is posted on the PR requesting the contributor to review the pre-processed files. Ref: * https://github.com/thlorenz/doctoc
1 parent eacb69a commit d0f9056

13 files changed

+80
-204
lines changed

.github/workflows/publish-wiki.yml

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,53 @@ jobs:
3131
permissions:
3232
# Needed for the commit to the wiki.
3333
contents: write
34+
# Needed for the PR comment.
35+
pull-requests: write
3436

3537
steps:
3638
- name: Checkout code
3739
uses: actions/checkout@v4
3840

41+
- name: Install DocToc table of contents generator
42+
run: npm install -g doctoc
43+
44+
- name: Copy wiki files to temporary location
45+
shell: bash
46+
run: cp -v -a wiki _wiki
47+
48+
- name: Update tables of contents
49+
run: doctoc ./_wiki/ --github --maxlevel 4 --update-only
50+
51+
- name: Re-run tables of contents with different settings for specific file
52+
run: doctoc ./_wiki/Version-4.0-User-Upgrade-Guide.md --github --maxlevel 3 --update-only
53+
54+
# Retention is normally 90 days, but this artifact is only to help with reviewing PRs,
55+
# especially when new output blocks are added or the (workflow) code for existing ones
56+
# is updated. All in all, no need to keep the artifact for more than a few days.
57+
- name: "[PR only] Upload the preprocessed wiki files as an artifact"
58+
if: ${{ github.event_name == 'pull_request' }}
59+
id: artifact
60+
uses: actions/upload-artifact@v4
61+
with:
62+
name: wiki-files
63+
path: ./_wiki
64+
if-no-files-found: error
65+
retention-days: 10
66+
67+
- name: "[PR only] Post comment to review artifact"
68+
if: ${{ github.event_name == 'pull_request' }}
69+
uses: mshick/add-pr-comment@v2
70+
with:
71+
repo-token: ${{ secrets.COMMENT_ON_PRS_TOKEN }}
72+
message: |
73+
Thank you for your PR.
74+
A dry-run has been executed on your PR, executing all markdown pre-processing for the wiki files.
75+
76+
Please review the resulting final markdown files via the [created artifact](${{ steps.artifact.outputs.artifact-url }}).
77+
This is especially important when adding new pages.
78+
79+
_N.B.: the above link will automatically be updated when this PR is updated._
80+
3981
- name: Check GitHub Git Operations status
4082
uses: crazy-max/ghaction-github-status@v4
4183
with:
@@ -47,7 +89,7 @@ jobs:
4789
COMMIT_MSG: ${{ github.event.head_commit.message }}
4890
with:
4991
strategy: 'clone'
50-
path: 'wiki/'
92+
path: '_wiki/'
5193
commit-message: ${{ env.COMMIT_MSG }}
5294
# repository: PHPCSStandards/PHP_CodeSniffer
5395
# token: ${{ secrets.PHPCS_PUSH_TO_WIKI_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_wiki/

wiki/About-Standards-for-PHP_CodeSniffer.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
## Table of contents
22

3-
* [A Project ruleset or a standard ?](#a-project-ruleset-or-a-standard-)
4-
* [How does PHP_CodeSniffer determine which standard or ruleset to apply ?](#how-does-php_codesniffer-determine-which-standard-or-ruleset-to-apply-)
5-
* [About standards](#about-standards)
6-
* [Creating an external standard for PHP_CodeSniffer](#creating-an-external-standard-for-php_codesniffer)
7-
* [Creating new rules](#creating-new-rules)
8-
* [Naming conventions](#naming-conventions)
9-
* [1. Directory structure](#1-directory-structure)
10-
* [2. Sniff file name](#2-sniff-file-name)
11-
* [3. Namespace and class name](#3-namespace-and-class-name)
12-
* [Examples](#examples)
3+
<!-- START doctoc -->
4+
<!-- END doctoc -->
135

146
***
157

wiki/Advanced-Usage.md

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,7 @@
11
## Table of contents
22

3-
* [Specifying Valid File Extensions](#specifying-valid-file-extensions)
4-
* [Ignoring Files and Folders](#ignoring-files-and-folders)
5-
* [Ignoring Parts of a File](#ignoring-parts-of-a-file)
6-
* [Limiting Results to Specific Sniffs](#limiting-results-to-specific-sniffs)
7-
* [Filtering Errors and Warnings Based on Severity](#filtering-errors-and-warnings-based-on-severity)
8-
* [Replacing Tabs with Spaces](#replacing-tabs-with-spaces)
9-
* [Specifying an Encoding](#specifying-an-encoding)
10-
* [Using a Bootstrap File](#using-a-bootstrap-file)
11-
* [Using a Default Configuration File](#using-a-default-configuration-file)
12-
* [Specifying php.ini Settings](#specifying-phpini-settings)
13-
* [Setting Configuration Options](#setting-configuration-options)
14-
* [Deleting Configuration Options](#deleting-configuration-options)
15-
* [Viewing Configuration Options](#viewing-configuration-options)
16-
* [Printing Verbose Tokeniser Output](#printing-verbose-tokeniser-output)
17-
* [The Scope Map](#the-scope-map)
18-
* [The Level Map](#the-level-map)
19-
* [Printing Verbose Token Processing Output](#printing-verbose-token-processing-output)
20-
* [Quieting Output](#quieting-output)
21-
* [Understanding the Exit Codes](#understanding-the-exit-codes)
3+
<!-- START doctoc -->
4+
<!-- END doctoc -->
225

236
***
247

wiki/Coding-Standard-Tutorial.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ In this tutorial, we will create a new coding standard with a single sniff. Our
22

33
Sniffs need to follow [strict directory layout and naming conventions](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki/About-Standards-for-PHP_CodeSniffer#naming-conventions).
44

5+
## Table of contents
6+
7+
<!-- START doctoc -->
8+
<!-- END doctoc -->
9+
10+
***
11+
512
## Creating the Coding Standard Directory
613

714
All sniffs in PHP_CodeSniffer must belong to a coding standard. A coding standard is a directory with a specific sub-directory structure and a `ruleset.xml` file, so creating a standard is straight-forward.

wiki/Configuration-Options.md

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,7 @@
11
## Table of contents
22

3-
* [Setting the default coding standard](#setting-the-default-coding-standard)
4-
* [Setting the default report format](#setting-the-default-report-format)
5-
* [Hiding warnings by default](#hiding-warnings-by-default)
6-
* [Showing progress by default](#showing-progress-by-default)
7-
* [Using colors in output by default](#using-colors-in-output-by-default)
8-
* [Changing the default severity levels](#changing-the-default-severity-levels)
9-
* [Setting the default report width](#setting-the-default-report-width)
10-
* [Setting the default encoding](#setting-the-default-encoding)
11-
* [Setting the default tab width](#setting-the-default-tab-width)
12-
* [Setting the installed standard paths](#setting-the-installed-standard-paths)
13-
* [Setting the PHP version](#setting-the-php-version)
14-
* [Ignoring errors when generating the exit code](#ignoring-errors-when-generating-the-exit-code)
15-
* [Ignoring warnings when generating the exit code](#ignoring-warnings-when-generating-the-exit-code)
16-
* [Ignoring non-auto-fixable issues when generating the exit code (PHP_CodeSniffer >= 4.0.0)](#ignoring-non-auto-fixable-issues-when-generating-the-exit-code-php_codesniffer--400)
17-
* Setting tool paths
18-
* [CSSLint](#setting-the-path-to-csslint)
19-
* [Google Closure Linter](#setting-the-path-to-the-google-closure-linter)
20-
* [PHP](#setting-the-path-to-php)
21-
* [JSHint](#setting-the-path-to-jshint)
22-
* [JSLint](#setting-the-path-to-jslint)
23-
* [JavaScript Lint](#setting-the-path-to-javascript-lint)
24-
* [Zend Code Analyzer](#setting-the-path-to-the-zend-code-analyzer)
3+
<!-- START doctoc -->
4+
<!-- END doctoc -->
255

266
***
277

wiki/Customisable-Sniff-Properties.md

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,8 @@ For more information about changing sniff behaviour by customising your ruleset,
44

55
## Table of contents
66

7-
* [Generic Sniffs](#generic-sniffs)
8-
* [Generic.Arrays.ArrayIndent](#genericarraysarrayindent)
9-
* [Generic.CodeAnalysis.UnusedFunctionParameter](#genericcodeanalysisunusedfunctionparameter)
10-
* [Generic.ControlStructures.InlineControlStructure](#genericcontrolstructuresinlinecontrolstructure)
11-
* [Generic.Debug.ClosureLinter](#genericdebugclosurelinter)
12-
* [Generic.Debug.ESLint](#genericdebugeslint)
13-
* [Generic.Files.LineEndings](#genericfileslineendings)
14-
* [Generic.Files.LineLength](#genericfileslinelength)
15-
* [Generic.Formatting.MultipleStatementAlignment](#genericformattingmultiplestatementalignment)
16-
* [Generic.Formatting.SpaceAfterCast](#genericformattingspaceaftercast)
17-
* [Generic.Formatting.SpaceAfterNot](#genericformattingspaceafternot)
18-
* [Generic.Functions.OpeningFunctionBraceBsdAllman](#genericfunctionsopeningfunctionbracebsdallman)
19-
* [Generic.Functions.OpeningFunctionBraceKernighanRitchie](#genericfunctionsopeningfunctionbracekernighanritchie)
20-
* [Generic.Metrics.CyclomaticComplexity](#genericmetricscyclomaticcomplexity)
21-
* [Generic.Metrics.NestingLevel](#genericmetricsnestinglevel)
22-
* [Generic.NamingConventions.CamelCapsFunctionName](#genericnamingconventionscamelcapsfunctionname)
23-
* [Generic.PHP.ForbiddenFunctions](#genericphpforbiddenfunctions)
24-
* [Generic.PHP.NoSilencedErrors](#genericphpnosilencederrors)
25-
* [Generic.Strings.UnnecessaryStringConcat](#genericstringsunnecessarystringconcat)
26-
* [Generic.WhiteSpace.ArbitraryParenthesesSpacing](#genericwhitespacearbitraryparenthesesspacing)
27-
* [Generic.WhiteSpace.ScopeIndent](#genericwhitespacescopeindent)
28-
* [Generic.WhiteSpace.SpreadOperatorSpacingAfter](#genericwhitespacespreadoperatorspacingafter)
29-
* [PEAR Sniffs](#pear-sniffs)
30-
* [PEAR.Commenting.FunctionComment](#pearcommentingfunctioncomment)
31-
* [PEAR.ControlStructures.ControlSignature](#pearcontrolstructurescontrolsignature)
32-
* [PEAR.ControlStructures.MultiLineCondition](#pearcontrolstructuresmultilinecondition)
33-
* [PEAR.Formatting.MultiLineAssignment](#pearformattingmultilineassignment)
34-
* [PEAR.Functions.FunctionCallSignature](#pearfunctionsfunctioncallsignature)
35-
* [PEAR.Functions.FunctionDeclaration](#pearfunctionsfunctiondeclaration)
36-
* [PEAR.WhiteSpace.ObjectOperatorIndent](#pearwhitespaceobjectoperatorindent)
37-
* [PEAR.WhiteSpace.ScopeClosingBrace](#pearwhitespacescopeclosingbrace)
38-
* [PEAR.WhiteSpace.ScopeIndent](#pearwhitespacescopeindent)
39-
* [PSR2 Sniffs](#psr2-sniffs)
40-
* [PSR2.Classes.ClassDeclaration](#psr2classesclassdeclaration)
41-
* [PSR2.ControlStructures.ControlStructureSpacing](#psr2controlstructurescontrolstructurespacing)
42-
* [PSR2.ControlStructures.SwitchDeclaration](#psr2controlstructuresswitchdeclaration)
43-
* [PSR2.Methods.FunctionCallSignature](#psr2methodsfunctioncallsignature)
44-
* [PSR12 Sniffs](#psr12-sniffs)
45-
* [PSR12.Classes.AnonClassDeclaration](#psr12classesanonclassdeclaration)
46-
* [PSR12.ControlStructures.BooleanOperatorPlacement](#psr12controlstructuresbooleanoperatorplacement)
47-
* [PSR12.ControlStructures.ControlStructureSpacing](#psr12controlstructurescontrolstructurespacing)
48-
* [PSR12.Namespaces.CompoundNamespaceDepth](#psr12namespacescompoundnamespacedepth)
49-
* [PSR12.Operators.OperatorSpacing](#psr12operatorsoperatorspacing)
50-
* [Squiz Sniffs](#squiz-sniffs)
51-
* [Squiz.Classes.ClassDeclaration](#squizclassesclassdeclaration)
52-
* [Squiz.Commenting.FunctionComment](#squizcommentingfunctioncomment)
53-
* [Squiz.Commenting.LongConditionClosingComment](#squizcommentinglongconditionclosingcomment)
54-
* [Squiz.ControlStructures.ControlSignature](#squizcontrolstructurescontrolsignature)
55-
* [Squiz.ControlStructures.ForEachLoopDeclaration](#squizcontrolstructuresforeachloopdeclaration)
56-
* [Squiz.ControlStructures.ForLoopDeclaration](#squizcontrolstructuresforloopdeclaration)
57-
* [Squiz.ControlStructures.SwitchDeclaration](#squizcontrolstructuresswitchdeclaration)
58-
* [Squiz.CSS.ForbiddenStyles](#squizcssforbiddenstyles)
59-
* [Squiz.CSS.Indentation](#squizcssindentation)
60-
* [Squiz.Functions.FunctionDeclaration](#squizfunctionsfunctiondeclaration)
61-
* [Squiz.Functions.FunctionDeclarationArgumentSpacing](#squizfunctionsfunctiondeclarationargumentspacing)
62-
* [Squiz.PHP.CommentedOutCode](#squizphpcommentedoutcode)
63-
* [Squiz.PHP.DiscouragedFunctions](#squizphpdiscouragedfunctions)
64-
* [Squiz.PHP.ForbiddenFunctions](#squizphpforbiddenfunctions)
65-
* [Squiz.Strings.ConcatenationSpacing](#squizstringsconcatenationspacing)
66-
* [Squiz.WhiteSpace.FunctionSpacing](#squizwhitespacefunctionspacing)
67-
* [Squiz.WhiteSpace.MemberVarSpacing](#squizwhitespacemembervarspacing)
68-
* [Squiz.WhiteSpace.ObjectOperatorSpacing](#squizwhitespaceobjectoperatorspacing)
69-
* [Squiz.WhiteSpace.OperatorSpacing](#squizwhitespaceoperatorspacing)
70-
* [Squiz.WhiteSpace.SuperfluousWhitespace](#squizwhitespacesuperfluouswhitespace)
7+
<!-- START doctoc -->
8+
<!-- END doctoc -->
719

7210
***
7311

wiki/FAQ.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
## Table of contents
22

3-
* [Does PHP_CodeSniffer perform any code coverage or unit testing?](#does-php_codesniffer-perform-any-code-coverage-or-unit-testing)
4-
* [My code is fine! Why do I need PHP_CodeSniffer?](#my-code-is-fine-why-do-i-need-php_codesniffer)
5-
* [Does PHP_CodeSniffer parse my code to ensure it will execute?](#does-php_codesniffer-parse-my-code-to-ensure-it-will-execute)
6-
* [I don't agree with your coding standards! Can I make PHP_CodeSniffer enforce my own?](#i-dont-agree-with-your-coding-standards-can-i-make-php_codesniffer-enforce-my-own)
7-
* [How come PHP_CodeSniffer reported errors, I fixed them, now I get even more?](#how-come-php_codesniffer-reported-errors-i-fixed-them-now-i-get-even-more)
8-
* [What does PHP_CodeSniffer use to tokenize my code?](#what-does-php_codesniffer-use-to-tokenize-my-code)
3+
<!-- START doctoc -->
4+
<!-- END doctoc -->
95

106
***
117

wiki/Fixing-Errors-Automatically.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
## Table of contents
22

3-
* [About Automatic Fixing](#about-automatic-fixing)
4-
* [Using the PHP Code Beautifier and Fixer](#using-the-php-code-beautifier-and-fixer)
5-
* [Viewing Debug Information](#viewing-debug-information)
3+
<!-- START doctoc -->
4+
<!-- END doctoc -->
65

76
***
87

wiki/Usage.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
## Table of contents
22

3-
* [Getting Help from the Command Line](#getting-help-from-the-command-line)
4-
* [Checking Files and Folders](#checking-files-and-folders)
5-
* [Printing a Summary Report](#printing-a-summary-report)
6-
* [Printing Progress Information](#printing-progress-information)
7-
* [Specifying a Coding Standard](#specifying-a-coding-standard)
8-
* [Printing a List of Installed Coding Standards](#printing-a-list-of-installed-coding-standards)
9-
* [Listing Sniffs Inside a Coding Standard](#listing-sniffs-inside-a-coding-standard)
3+
<!-- START doctoc -->
4+
<!-- END doctoc -->
105

116
***
127

0 commit comments

Comments
 (0)