From af2928d62b3645f984371d0d919e799351d65679 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 10:37:52 +0800 Subject: [PATCH 1/9] Upgrade PHP Parser and TNT Search libraries --- classes/PHPApiParser.php | 2 +- composer.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/classes/PHPApiParser.php b/classes/PHPApiParser.php index a4f34d8..c4272b8 100644 --- a/classes/PHPApiParser.php +++ b/classes/PHPApiParser.php @@ -104,7 +104,7 @@ public function __construct(string $basePath, array|string $sourcePaths = [], ar public function parse(): void { // Create parser and node finder - $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); + $parser = (new ParserFactory)->createForHostVersion(); $nodeFinder = new NodeFinder; // Add name resolver diff --git a/composer.json b/composer.json index a403e09..fba9e1e 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,8 @@ "require": { "php": ">=7.2.9", "composer/installers": "~1.0", - "nikic/php-parser": "^4.11.0", - "phpdocumentor/reflection-docblock": "^5.2.2" + "nikic/php-parser": "^5.6.0", + "phpdocumentor/reflection-docblock": "^5.6.2" }, "extra": { "installer-name": "docs", From 492ef605fe96ad037da131a0004e824b6657a122 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 10:38:09 +0800 Subject: [PATCH 2/9] Update PHPUnit tests and resolve deprecations --- .gitignore | 3 +- phpunit.xml.dist | 39 +++++------ tests/classes/ApiParserTest.php | 23 +++--- tests/classes/BaseDocumentationTest.php | 93 ++++++++----------------- tests/classes/DocsManagerTest.php | 21 ++---- 5 files changed, 67 insertions(+), 112 deletions(-) diff --git a/.gitignore b/.gitignore index 2526679..392937a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ composer.lock -vendor +vendor/ .phpunit.result.cache +.phpunit.cache/ coverage.xml .DS_Store diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f06746c..dedebc4 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,25 +1,22 @@ - - - ./tests - - - - - - classes - Plugin.php - - + + + ./tests + + + + + classes + Plugin.php + + diff --git a/tests/classes/ApiParserTest.php b/tests/classes/ApiParserTest.php index 82c27a8..675cd82 100644 --- a/tests/classes/ApiParserTest.php +++ b/tests/classes/ApiParserTest.php @@ -1,12 +1,15 @@ -assertCount(7, $this->apiParser->getPaths()); @@ -44,10 +44,7 @@ public function testGetPaths() ], $filenames); } - /** - * @covers \Winter\Docs\Classes\PHPApiParser::parse() - * @testdox can parse all PHP files and present the schema in an array. - */ + #[TestDox('can parse all PHP files and present the schema in an array..')] public function testParse() { $this->apiParser->parse(); diff --git a/tests/classes/BaseDocumentationTest.php b/tests/classes/BaseDocumentationTest.php index 2a452f4..eb72a96 100644 --- a/tests/classes/BaseDocumentationTest.php +++ b/tests/classes/BaseDocumentationTest.php @@ -2,53 +2,46 @@ namespace Winter\Docs\Tests\Classes; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; use System\Tests\Bootstrap\TestCase; +use Winter\Docs\Classes\BaseDocumentation; use Winter\Storm\Exception\ApplicationException; -/** - * @covers \Winter\Docs\Classes\BaseDocumentation - * @testdox The Base Documentation abstract (\Winter\Docs\Classes\BaseDocumentation) - */ +#[CoversClass(\Winter\Docs\Classes\BaseDocumentation::class)] +#[TestDox('The Base Documentation abstract (\Winter\Docs\Classes\BaseDocumentation)')] class BaseDocumentationTest extends TestCase { - /** - * @covers \Winter\Docs\Classes\BaseDocumentation::download() - * @covers \Winter\Docs\Classes\BaseDocumentation::isDownloaded() - * @testdox can download a remote documentation ZIP file and indicate that it is downloaded. - */ + #[TestDox('can download a remote documentation ZIP file and indicate that it is downloaded.')] public function testDownload(): void { - $doc = $this->getMockForAbstractClass( - 'Winter\Docs\Classes\BaseDocumentation', - [ + $doc = $this->getMockBuilder(BaseDocumentation::class) + ->setConstructorArgs([ 'Winter.Docs.Test', [ 'name' => 'Winter Docs Test', - 'type' => 'user', + 'type' => 'md', 'source' => 'remote', 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/main.zip', 'zipFolder' => 'docs-main', - ] - ] - ); + ], + ]) + ->onlyMethods(['process', 'getPageList']) + ->getMock(); $doc->download(); $this->assertFileExists($doc->getDownloadPath('archive.zip')); $this->assertTrue($doc->isDownloaded()); } - /** - * @covers \Winter\Docs\Classes\BaseDocumentation::download() - * @testdox will throw an exception if the documentation URL is invalid when downloading. - */ + #[TestDox('will throw an exception if the documentation URL is invalid when downloading.')] public function testDownloadInvalidUrl(): void { $this->expectException(ApplicationException::class); $this->expectExceptionMessageMatches('/Could not retrieve the documentation/i'); - $doc = $this->getMockForAbstractClass( - 'Winter\Docs\Classes\BaseDocumentation', - [ + $doc = $this->getMockBuilder(BaseDocumentation::class) + ->setConstructorArgs([ 'Winter.Docs.Test', [ 'name' => 'Winter Docs Test', @@ -56,62 +49,36 @@ public function testDownloadInvalidUrl(): void 'source' => 'remote', 'url' => 'https://wintercms.com/missing/docs.zip', 'zipFolder' => 'docs-main', - ] - ] - ); + ], + ]) + ->onlyMethods(['process', 'getPageList']) + ->getMock(); $doc->download(); } - /** - * @covers \Winter\Docs\Classes\BaseDocumentation::extract() - * @testdox can extract a downloaded docs ZIP file. - */ - public function testExtract(): void + #[TestDox('can extract a downloaded docs ZIP file and clean-up afterwards.')] + public function testExtractAndCleanUp(): void { - $doc = $this->getMockForAbstractClass( - 'Winter\Docs\Classes\BaseDocumentation', - [ + $doc = $this->getMockBuilder(BaseDocumentation::class) + ->setConstructorArgs([ 'Winter.Docs.Test', [ 'name' => 'Winter Docs Test', 'type' => 'md', 'source' => 'remote', - 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/develop.zip', - 'zipFolder' => 'docs-develop', - ] - ] - ); + 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/main.zip', + 'zipFolder' => 'docs-main', + ], + ]) + ->onlyMethods(['process', 'getPageList']) + ->getMock(); $doc->download(); $doc->extract(); $this->assertDirectoryExists($doc->getDownloadPath('collated')); $this->assertFileExists($doc->getDownloadPath('collated/snowboard/introduction.md')); - } - -/** - * @covers \Winter\Docs\Classes\BaseDocumentation::cleanupDownload() - * @testdox can clean up downloaded and extracted assets. - */ - public function testCleanupDownload(): void - { - $doc = $this->getMockForAbstractClass( - 'Winter\Docs\Classes\BaseDocumentation', - [ - 'Winter.Docs.Test', - [ - 'name' => 'Winter Docs Test', - 'type' => 'md', - 'source' => 'remote', - 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/develop.zip', - 'zipFolder' => 'docs-develop', - ] - ] - ); - - $doc->download(); - $doc->extract(); // Re-download the file $doc->download(); diff --git a/tests/classes/DocsManagerTest.php b/tests/classes/DocsManagerTest.php index 5881168..981bba4 100644 --- a/tests/classes/DocsManagerTest.php +++ b/tests/classes/DocsManagerTest.php @@ -2,14 +2,15 @@ namespace Winter\Docs\Tests\Classes; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\TestDox; use System\Tests\Bootstrap\PluginTestCase; use System\Classes\PluginManager; use Winter\Docs\Classes\DocsManager; -/** - * @covers \Winter\Docs\Classes\DocsManager - * @testdox The Documentation Manager (\Winter\Docs\Classes\DocsManager) - */ + +#[CoversClass(\Winter\Docs\Classes\DocsManager::class)] +#[TestDox('The Documentation Manager (\Winter\Docs\Classes\DocsManager)')] class DocsManagerTest extends PluginTestCase { protected $docsManager; @@ -33,10 +34,7 @@ public function setUp(): void $this->docsManager = DocsManager::instance(); } - /** - * @covers \Winter\Docs\Classes\DocsManager::makeIdentifier() - * @testdox can make valid identifiers for docs. - */ + #[TestDox('can make valid identifiers for docs.')] public function testMakeIdentifier() { $this->assertEquals( @@ -60,12 +58,7 @@ public function testMakeIdentifier() ); } - /** - * @covers \Winter\Docs\Classes\DocsManager::addDocumentation() - * @covers \Winter\Docs\Classes\DocsManager::removeDocumentation() - * @covers \Winter\Docs\Classes\DocsManager::hasDocumentation() - * @testdox can manually add and remove documentation. - */ + #[TestDox('can manually add and remove documentation.')] public function testAddDocumentation() { $this->assertFalse($this->docsManager->hasDocumentation('Docs.Test', 'user')); From 5cbdfa6a589877590544182fc02ce52462a94030 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 02:42:28 +0000 Subject: [PATCH 3/9] Update Github action --- .github/workflows/tests.yaml | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 84c0f3e..09e450e 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -14,36 +14,19 @@ jobs: max-parallel: 4 matrix: operatingSystem: [ubuntu-latest] - phpVersion: ['8.1', '8.2', '8.3'] + phpVersion: ['8.2', '8.3', '8.4'] fail-fast: false - env: - extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip concurrency: - group: ${{ github.ref }}-${{ github.workflow }}-${{ matrix.operatingSystem }}-${{ matrix.phpVersion }} + group: tests-${{ github.ref }}-${{ github.workflow }}-${{ matrix.operatingSystem }}-${{ matrix.phpVersion }} cancel-in-progress: true steps: - - name: Checkout Winter CMS - uses: actions/checkout@v4 - with: - repository: wintercms/winter - ref: develop - - - name: Checkout Winter Docs plugin - uses: actions/checkout@v4 - with: - path: plugins/winter/docs - - - name: Install PHP - uses: shivammathur/setup-php@v2 + - name: Setup Winter CMS + uses: wintercms/setup-winter-action@v1 with: php-version: ${{ matrix.phpVersion }} - tools: composer:v2 - extensions: ${{ env.extensions }} - - - name: Install Composer dependencies - run: | - sed -i 's|plugins/myauthor/\*/composer.json|plugins/*/*/composer.json|g' composer.json - composer install --no-interaction --no-progress --no-scripts + winter-ref: wip/1.3 + plugin-author: winter + plugin-name: docs - name: Run tests run: php artisan winter:test -p Winter.Docs From f3649c26f05279959bda48c0f9c28fc091b9a981 Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 02:55:52 +0000 Subject: [PATCH 4/9] Fix and simplify test, add some error checking --- classes/BaseDocumentation.php | 11 ++++- tests/classes/BaseDocumentationTest.php | 56 +++++++++---------------- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/classes/BaseDocumentation.php b/classes/BaseDocumentation.php index 1e94753..c0e715d 100644 --- a/classes/BaseDocumentation.php +++ b/classes/BaseDocumentation.php @@ -345,7 +345,16 @@ public function extract(): void } } - $zip->extractTo($this->getDownloadPath('extracted'), $toExtract); + if (!$zip->extractTo($this->getDownloadPath('extracted'), $toExtract)) { + throw new ApplicationException( + sprintf( + 'Could not extract the documentation for "%s" from the remote source "%s" - %s', + $this->identifier, + $this->source, + $zip->getStatusString() + ) + ); + } // Move remaining files into location $extractPath = $this->getDownloadPath('extracted/' . $this->zipFolder); diff --git a/tests/classes/BaseDocumentationTest.php b/tests/classes/BaseDocumentationTest.php index eb72a96..2c89e3d 100644 --- a/tests/classes/BaseDocumentationTest.php +++ b/tests/classes/BaseDocumentationTest.php @@ -12,8 +12,8 @@ #[TestDox('The Base Documentation abstract (\Winter\Docs\Classes\BaseDocumentation)')] class BaseDocumentationTest extends TestCase { - #[TestDox('can download a remote documentation ZIP file and indicate that it is downloaded.')] - public function testDownload(): void + #[TestDox('can download, extract a downloaded docs ZIP file and clean-up afterwards.')] + public function testDownloadExtractAndCleanUp(): void { $doc = $this->getMockBuilder(BaseDocumentation::class) ->setConstructorArgs([ @@ -22,16 +22,31 @@ public function testDownload(): void 'name' => 'Winter Docs Test', 'type' => 'md', 'source' => 'remote', - 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/main.zip', - 'zipFolder' => 'docs-main', + 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/develop.zip', + 'zipFolder' => 'docs-develop', ], ]) ->onlyMethods(['process', 'getPageList']) ->getMock(); $doc->download(); + $this->assertFileExists($doc->getDownloadPath('archive.zip')); $this->assertTrue($doc->isDownloaded()); + + $doc->extract(); + + $this->assertDirectoryExists($doc->getDownloadPath('collated')); + $this->assertFileExists($doc->getDownloadPath('collated/snowboard/introduction.md')); + + // Re-download the file + $doc->download(); + + // Clean up + $doc->cleanupDownload(); + + $this->assertFileDoesNotExist($doc->getDownloadPath('archive.zip')); + $this->assertDirectoryDoesNotExist($doc->getDownloadPath('extracted')); } #[TestDox('will throw an exception if the documentation URL is invalid when downloading.')] @@ -56,37 +71,4 @@ public function testDownloadInvalidUrl(): void $doc->download(); } - - #[TestDox('can extract a downloaded docs ZIP file and clean-up afterwards.')] - public function testExtractAndCleanUp(): void - { - $doc = $this->getMockBuilder(BaseDocumentation::class) - ->setConstructorArgs([ - 'Winter.Docs.Test', - [ - 'name' => 'Winter Docs Test', - 'type' => 'md', - 'source' => 'remote', - 'url' => 'https://github.com/wintercms/docs/archive/refs/heads/main.zip', - 'zipFolder' => 'docs-main', - ], - ]) - ->onlyMethods(['process', 'getPageList']) - ->getMock(); - - $doc->download(); - $doc->extract(); - - $this->assertDirectoryExists($doc->getDownloadPath('collated')); - $this->assertFileExists($doc->getDownloadPath('collated/snowboard/introduction.md')); - - // Re-download the file - $doc->download(); - - // Clean up - $doc->cleanupDownload(); - - $this->assertFileDoesNotExist($doc->getDownloadPath('archive.zip')); - $this->assertDirectoryDoesNotExist($doc->getDownloadPath('extracted')); - } } From 01221811061281e4df15353d03777cad3cf840af Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 04:33:48 +0000 Subject: [PATCH 5/9] Minor tweaks --- classes/PHPApiDocumentation.php | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/classes/PHPApiDocumentation.php b/classes/PHPApiDocumentation.php index 360734d..249fb9e 100644 --- a/classes/PHPApiDocumentation.php +++ b/classes/PHPApiDocumentation.php @@ -2,10 +2,10 @@ namespace Winter\Docs\Classes; -use File; use Illuminate\Support\Facades\App; use Twig\TemplateWrapper; use Winter\Storm\Exception\ApplicationException; +use Winter\Storm\Support\Facades\File; /** * PHP API Documentation instance. @@ -32,6 +32,11 @@ class PHPApiDocumentation extends BaseDocumentation */ protected string $template; + /** + * Path to the Twig template for rendering event API docs. + */ + protected string $eventTemplate; + /** * Prepared template for rendering API docs. */ @@ -167,12 +172,24 @@ protected function processClassLevel(PHPApiParser $parser, array $classMap, arra 'title' => $key, ]; + try { + $rendered = $this->preparedTemplate->render([ + 'class' => $class, + ]); + } catch (\Throwable $e) { + throw new ApplicationException( + sprintf( + 'An error occurred while rendering the API documentation for class "%s": %s', + $class['name'], + $e->getMessage() + ) + ); + } + // Create docs $this->getStorageDisk()->put( $this->getProcessedPath(ltrim($baseNamespace . '/' . $key . '.htm')), - $this->prependFrontMatter($class, $this->preparedTemplate->render([ - 'class' => $class, - ])) + $this->prependFrontMatter($class, $rendered) ); $nav[] = $navItem; From c986cfccbbb015039e7b98206c239a19bb89623e Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 04:34:42 +0000 Subject: [PATCH 6/9] Update default API page template to include all information from Nabu theme, but none of the styling --- views/api-doc.twig | 580 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 539 insertions(+), 41 deletions(-) diff --git a/views/api-doc.twig b/views/api-doc.twig index 12eebf2..6a329ac 100644 --- a/views/api-doc.twig +++ b/views/api-doc.twig @@ -1,4 +1,18 @@ {% endif %} + {% if class.extendedBy %} +
  • + + Extended by + +
  • + {% endif %} + {% if class.implementedBy %} +
  • + + Implemented by + +
  • + {% endif %} + {% if class.usedBy %} +
  • + + Used by + +
  • + {% endif %} -
    +

    {{ class.name }} -

    - -
    - {% if class.final %} - - final - - {% else %} - - abstract - - {% endif %} - - - class - - - - {{ class.name }} - - - {% if class.extends %} - - extends - - - - {{ class.extends }} - - {% endif %} -
    + {% if class.docs.summary %}
    @@ -113,8 +132,487 @@
    {% endif %} + + {%- if class.final -%} + final + {%- elseif class.abstract -%} + abstract + {%- endif %} {{ class.type }} {{ class.namespace }}\{{ class.name -}} + + {%- if class.extends.class %}{{ "\n" }}extends {{class.extends.class }}{% endif -%} + + {%- if class.implements %}{{ "\n" }}implements {% endif -%} + {%- for interface in class.implements %}{{ "\n" }} {{ interface.class }}{% if not loop.last %},{% endif%}{% endfor -%} + + {% if class.docs.body %}
    {{ class.docs.body | raw }}
    {% endif %} + +{% if class.extends %} +

    + # + Extends +

    + + + + + + + + + + + + + + +
    ClassDescription
    + + {{ class.extends.name }} + + + {{ class.extends.summary | raw }} +
    +{% endif %} + +{% if class.traits %} +

    + # + Traits +

    + + + + + + + + + + {% for trait in class.traits %} + + + + + {% endfor %} + +
    TraitDescription
    + + {{ trait.name }} + + + {{ trait.summary | raw }} +
    +{% endif %} + +{% if class.constants %} +

    + # + Constants +

    + + + + + + + + + + + + {% for constant in class.constants %} + + + + + + + {% endfor %} + +
    ConstantTypeValueDescription
    + {{ constant.name }} + + {% if constant.type.definition == 'reference' and constant.type.type.linked %} + + {{ constant.type.type.name }} + + {% elseif constant.type.definition == 'reference' %} + {{ constant.type.type.name }} + {% else %} + {{ constant.type.type }} + {% endif %} + + {{ constant.value }} + + {{ constant.docs.summary | raw }} +
    +{% endif %} + +{% if class.properties %} +

    + # + Properties +

    + + {% for property in class.properties %} +

    + # + + {% if property.inherited %} + + inherited + + {% endif %} + + + {{ property.visibility }} + + + {% if property.static %} + + static + + {% endif %} + + ${{ property.name }} + + + : + {% if property.type.definition == 'union' %} + {% for type in property.type.types %} + {% if not loop.first %} + | + {% endif %} + {% if type.definition == 'reference' and type.type.linked %} + + {{- type.type.name -}} + + {% elseif type.definition == 'reference' %} + {{ type.type.name }} + {% else %} + {{ type.type }} + {% endif %} + {% endfor %} + {% else %} + {% if property.type.definition == 'reference' and property.type.type.linked %} + + {{- property.type.type.name -}} + + {% elseif property.type.definition == 'reference' %} + {{ property.type.type.name }} + {% else %} + {{ property.type.type }} + {% endif %} + {% endif %} + {% if property.default %} + + = {{ property.default }} + + {% endif %} + +

    + + {% if property.inherited %} + + {% endif %} + +
    + {{ property.docs.summary | raw }} + + {{ property.docs.body | raw }} +
    + {% endfor %} +{% endif %} + +{% if class.methods %} +

    + # + Methods +

    + + {% for method in class.methods %} +

    + # + + {% if method.inherited %} + + inherited + + {% endif %} + + + {{ method.visibility }} + + + {% if method.static %} + + static + + {% endif %} + {% if method.final %} + + final + + {% endif %} + + {{ method.name }} + ( + {%- if method.params|length > 0 -%} + + {%- for param in method.params -%} + {%- if param.type.definition == 'union' -%} + {%- for type in param.type.types -%} + {%- if not loop.first %} | {% endif -%} + {%- if type.definition == 'reference' and type.type.linked -%} + + {{- type.type.name -}} + + {%- elseif type.definition == 'reference'-%} + {{ type.type.name }} + {%- else -%} + {{ type.type }} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {%- if param.type.definition == 'reference' and param.type.type.linked -%} + + {{- param.type.type.name -}} + + {%- elseif param.type.definition == 'reference' -%} + {{ param.type.type.name }} + {%- elseif param.type.definition == 'scalar' and param.type.type != 'mixed' -%} + {{ param.type.type }} + {%- endif -%} + {%- endif -%} + {%- if param.type.definition != 'scalar' or param.type.type != 'mixed' %} {% endif -%} + ${{ param.name }} + + {%- if param.default %} = {{ param.default }}{% endif -%} + {%- if not loop.last %}, {% endif -%} + {%- endfor -%} + + {%- endif -%} + ) + + {% if method.returns.type.definition != 'scalar' or method.returns.type.type != 'mixed' %} + : {%- if method.returns.type.definition == 'union' -%} + {%- for type in method.returns.type.types -%} + {%- if not loop.first %} | {% endif -%} + {%- if type.definition == 'reference' and type.type.linked -%} + + {{- type.type.name -}} + + {%- elseif type.definition == 'reference'-%} + {{ type.type.name }} + {%- else -%} + {{ type.type }} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {%- if method.returns.type.definition == 'reference' and method.returns.type.type.linked -%} + + {{- method.returns.type.type.name -}} + + {%- elseif method.returns.type.definition == 'reference' -%} + {{ method.returns.type.type.name }} + {%- elseif method.returns.type.definition == 'scalar' -%} + {{ method.returns.type.type }} + {%- endif -%} + {%- endif -%} + {% endif %} +

    + + {% if method.inherited %} + + {% endif %} + +
    + {{ method.docs.summary | raw }} + + {{ method.docs.body | raw }} + + {% if method.params|length > 0 %} + Parameters + + + + + + + + + + + {% for param in method.params %} + + + + + + {% endfor %} + +
    PropertyTypeDescription
    + ${{ param.name }} + + {%- if param.type.definition == 'union' -%} + {%- for type in param.type.types -%} + {%- if not loop.first %} | {% endif -%} + {%- if type.definition == 'reference' and type.type.linked -%} + + {{- type.type.name -}} + + {%- elseif type.definition == 'reference'-%} + {{ type.type.name }} + {%- else -%} + {{ type.type }} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {%- if param.type.definition == 'reference' and param.type.type.linked -%} + + {{- param.type.type.name -}} + + {%- elseif param.type.definition == 'reference' -%} + {{ param.type.type.name }} + {%- elseif param.type.definition == 'scalar' -%} + {{ param.type.type }} + {%- endif -%} + {%- endif -%} + + {{ param.summary | raw }} +
    + {% endif %} + + Returns + +
    + {%- if method.returns.type.definition == 'union' -%} + {%- for type in method.returns.type.types -%} + {%- if not loop.first %} | {% endif -%} + {%- if type.definition == 'reference' and type.type.linked -%} + + {{- type.type.name -}} + + {%- elseif type.definition == 'reference'-%} + {{ type.type.name }} + {%- else -%} + {{ type.type }} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {%- if method.returns.type.definition == 'reference' and method.returns.type.type.linked -%} + + {{- method.returns.type.type.name -}} + + {%- elseif method.returns.type.definition == 'reference' -%} + {{ method.returns.type.type.name }} + {%- elseif method.returns.type.definition == 'scalar' -%} + {{ method.returns.type.type }} + {%- endif -%} + {%- endif -%} +
    +
    + {{ method.docs.return.summary | raw }} +
    +
    + {% endfor %} +{% endif %} + +{% if class.extendedBy %} +

    + # + Extended by +

    + + + + + + + + + + {% for extendedBy in class.extendedBy %} + + + + + {% endfor %} + +
    ClassDescription
    + + {{ extendedBy.name }} + + {{ extendedBy.summary | raw }}
    +{% endif %} + +{% if class.implementedBy %} +

    + # + Implemented by +

    + + + + + + + + + + {% for implementedBy in class.implementedBy %} + + + + + {% endfor %} + +
    ClassDescription
    + + {{ implementedBy.name }} + + {{ implementedBy.summary | raw }}
    +{% endif %} + +{% if class.usedBy %} +

    + # + Used by +

    + + + + + + + + + + {% for usedBy in class.usedBy %} + + + + + {% endfor %} + +
    ClassDescription
    + + {{ usedBy.name }} + + {{ usedBy.summary | raw }}
    +{% endif %} \ No newline at end of file From ae395c5ab75ccbb36de94ed6a68de1d5d1ac617b Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Sun, 27 Jul 2025 21:38:06 -0700 Subject: [PATCH 7/9] Update views/api-doc.twig --- views/api-doc.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/api-doc.twig b/views/api-doc.twig index 6a329ac..abb0912 100644 --- a/views/api-doc.twig +++ b/views/api-doc.twig @@ -615,4 +615,4 @@ {% endfor %} -{% endif %} \ No newline at end of file +{% endif %} From 7fab5eacf8e5faf00b299da1f53fda8095d5758e Mon Sep 17 00:00:00 2001 From: Luke Towers Date: Sun, 27 Jul 2025 21:39:14 -0700 Subject: [PATCH 8/9] Update version.yaml --- updates/version.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/updates/version.yaml b/updates/version.yaml index 83bf9d3..04a3261 100644 --- a/updates/version.yaml +++ b/updates/version.yaml @@ -1,2 +1,3 @@ "1.0.0": Initial version of the Winter Docs plugin. "1.0.1": Allow processing of documentation through job queue. +"1.1.0": "Support Winter v1.3" From a4c6aed0f1f802db5e8a3d4fa28a214fd09e589d Mon Sep 17 00:00:00 2001 From: Ben Thomson Date: Mon, 28 Jul 2025 12:54:54 +0800 Subject: [PATCH 9/9] Update updates/version.yaml --- updates/version.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/updates/version.yaml b/updates/version.yaml index 04a3261..d577554 100644 --- a/updates/version.yaml +++ b/updates/version.yaml @@ -1,3 +1,3 @@ "1.0.0": Initial version of the Winter Docs plugin. "1.0.1": Allow processing of documentation through job queue. -"1.1.0": "Support Winter v1.3" +"2.0.0": "Support Winter v1.3"