Skip to content

Commit

Permalink
[TASK] Improve AJAX version switcher to sort and group languages and …
Browse files Browse the repository at this point in the history
…links, document workflow (#583)
  • Loading branch information
garvinhicking authored May 28, 2024
1 parent 8b720b8 commit ccebffd
Show file tree
Hide file tree
Showing 20 changed files with 461 additions and 19 deletions.
113 changes: 113 additions & 0 deletions Documentation/Developer/AjaxVersions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
.. include:: /Includes.rst.txt

.. _AjaxVersions:

=====================
AJAX version switcher
=====================

Rendered documentation provides a version switcher on top of the
navigation.

For documentation deployed on `docs.typo3.org` clicking on the version
switcher will perform an AJAX API request that lists all available
versions and languages for the current documentation.

For local rendering however, there are two issues that will lead to
the version switcher not working properly:

* Rendered HTML files viewed via the `file:///` notation may not
execute any JavaScript due to security considerations/configuration
of your browser.
* When viewing HTML files via `localhost` or a `.ddev.site` webserver,
the AJAX call will fail due to `CORS <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`__
(Cross-Origin Resource Sharing) security restrictions.

Developers of the `render-guides` project may need to simulate menu rendering though.

For them, navigation can be proxied and simulated.

.. _AjaxVersions-proxy:

Making the proxy available
==========================

When using the DDEV integration to view the documentation, the DocumentRoot of the
DDEV webserver is set to `Documentation-GENERATED-temp`. This does not
contain active PHP files by default.

The file :file:`packages/typo3-docs-theme/assets/js/versions-proxy.php` in the
repository of this project (`<https://github.com/TYPO3-Documentation/render-guides>`)
can act as a simple proxy. You can copy or symlink that file into your `Documentation-GENERATED-temp`
directory, so that it is callable with a URL like:

.. code::
https://render-guides.ddev.site/versions-proxy.php?url=https://docs.typo3.org/m/typo3/tutorial-getting-started/12.4/en-us/Concepts/Index.html
The PHP proxy passes the URL parameter `url` on to the actual `docs.typo3.org` API endpoint,
and returns its output locally.

Once the proxy PHP file is in place, the default values of the rendering will take effect
already. See :ref:`AjaxVersions-data-attributes` on how to fine-tune this.

Details on how the version switcher is implemented
==================================================

Local rendering is automatically detected via the absence of an environment variable
`TYPO3AZUREEDGEURIVERSION` (see :ref:`deploy-azure-assets`).

This allows a Twig function `isRenderedForDeployment` (defined in
:file:`packages/typo3-docs-theme/src/Twig/TwigExtension.php` of this repository) to
conditionally generate output. The Twig template file
`packages/typo3-docs-theme/resources/template/structure/navigation/navigationHeader.html.twig`
makes use of that function to define some default HTML data-attributes for out-of-the-box
version witcher simulation, once the PHP proxy URL can be called without a 404 error.

The JavaScript is contained in :file:`packages/typo3-docs-theme/assets/js/versions.js` and
contains the code for parsing the JSON response of the API, and sorting the keys appropriately.
More details can be found inside the code comments of that file.

When changing this JavaScript, the assets must be rebuilt (:bash:`ddev npm-build`) and
documentation must be rendered with the built assets (:bash:`make docs`).

The JavaScript file also contains some logic to set names for known published translations.
If a static name is not available, it is resolved to the ISO-code (like "de-de"). The
TYPO3 Documentation team can not easily access active server-side code to get an automatic
list of languages.

.. _AjaxVersions-data-attributes:
Configuring HTML data-attributes
================================

The following data-attributes on the HTML element :html:`<div id="toc-version">` are available:

* `data-override-url-self` - This is a full URL starting with `https://docs.typo3.org` which
is used as the simulated page from which the version switching information is retrieved for.
For example, `https://docs.typo3.org/m/typo3/tutorial-getting-started/12.4/en-us/Concepts/Index.html`.

* `data-override-url-proxy` - Points to the full URI of the :ref:`AjaxVersions-proxy` PHP proxy.
This is called due to CORS reasons. The default of this attribute is set to
`https://render-guides.ddev.site/versions-proxy.php?url=`. Unless this file is manually
copied to this URL, the proxy will return a 404 failure and inform about the non-working
version switcher.

Seeing the simulated output
===========================

Once the PHP proxy is in place, open the rendered documentation HTML file in your DDEV/webserver
environment (not using a `file:///` syntax, because then JavaScript may unavailable), for example

.. code::
https://render-guides.ddev.site/Developer/AjaxVersions.html
You can then also use the browser's JavaScript console to manipulate the used URLs for
rendering, for example:

.. code::
document.getElementById('toc-version').setAttribute('data-override-url-self', 'https://docs.typo3.org/other/t3docs/render-guides/main/en-us/Developer/InterlinkInventories.html');
This must be performed before actually clicking the version switcher link, because
the remote AJAX request is only performed once and then never again without reloading the page.
1 change: 1 addition & 0 deletions Documentation/Developer/Building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ above, and then executes two composite steps:
Note that we only have one central Docker container image entrypoint that can
take arguments like `migrate` or `render` to trigger different actions.

.. _deploy-azure-assets:

GitHub workflow: deploy-azure-assets
------------------------------------
Expand Down
1 change: 1 addition & 0 deletions Documentation/Developer/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ and the GitHub pipelines, while internally only using :file:`Makefile` syntax.
Contributing
ThemeCustomization
InterlinkInventories
AjaxVersions


.. _phpDocumentor/guides: https://github.com/phpDocumentor/guides
2 changes: 2 additions & 0 deletions Documentation/guides.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
>
<project
title="Render guides"
version="main"
release="main"
copyright="Since 2023 TYPO3 Documentation Team and Contributors"
/>
<extension
Expand Down
41 changes: 41 additions & 0 deletions packages/typo3-docs-theme/assets/js/versions-proxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

# This is a Proxy file to request a URL from docs.typo.org
# and pass the result along to the local development.
# It is used for debugging the docs.typo3.org/services/versionsJson.php
# endpoint.
# Since no active PHP files are part of the local DDEV instance by default,
# you need to manually put that file into the document root:
# $> ln -s ../packages/typo3-docs-theme/assets/js/versions-proxy.php Documentation-GENERATED-temp/versions-proxy.php

$proxyUrl = 'https://docs.typo3.org/services/versionsJson.php?url=' . urlencode($_REQUEST['url']);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $proxyUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);

if (curl_errno($ch) || $response === false) {
header('404 Not Found');
echo 'cURL error: ' . curl_error($ch);
curl_close($ch);
exit();
}
$response = (string)$response;

$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
$body = substr($response, $header_size);
curl_close($ch);
http_response_code($http_code);
$headers_array = explode("\r\n", $headers);

foreach($headers_array as $header) {
if (!empty($header) && !preg_match('/^Transfer-Encoding:/i', $header) && !preg_match('/^Content-Length:/i', $header)) {
header($header);
}
}

echo $body;
Loading

0 comments on commit ccebffd

Please sign in to comment.