index.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * Public client handbook (Markdown -> HTML via the vendored marked.js).
  5. *
  6. * Same shape as the two viewers inside the repository: an index plus one page
  7. * per document, reached as index.php?doc=KEY. In addition every source file of
  8. * the client package has its own page, index.php?code=PATH.
  9. *
  10. * Self-contained: no build step and no external requests. The pages are read
  11. * from client-package/ on each request, so they always match the repository.
  12. *
  13. * Agents do not read this rendering - the head of every page points at the
  14. * Markdown twin under llms.php; see the hint below.
  15. */
  16. require_once __DIR__ . "/inc/handbook.php";
  17. $pages = handbookPages();
  18. $docs = handbookPagesOfKind("doc");
  19. $code = handbookPagesOfKind("code");
  20. $requestedDoc = isset($_GET["doc"]) ? (string) $_GET["doc"] : "";
  21. $requestedCode = isset($_GET["code"]) ? (string) $_GET["code"] : "";
  22. $page = null;
  23. $markdown = null;
  24. $pageTitle = "Overview";
  25. $notFound = false;
  26. if ($requestedDoc !== "" || $requestedCode !== "") {
  27. $page = $requestedDoc !== ""
  28. ? handbookPage("doc", $requestedDoc)
  29. : handbookPage("code", $requestedCode);
  30. if ($page === null) {
  31. http_response_code(404);
  32. $pageTitle = "Not Found";
  33. $notFound = true;
  34. } else {
  35. $markdown = handbookPageMarkdown($page);
  36. $pageTitle = $page["title"];
  37. }
  38. }
  39. // Works both when client-docs/ is a subdirectory and when it is served as the
  40. // web root (php -S localhost:8080 -t client-docs), where dirname() yields "/".
  41. $baseHref = rtrim(str_replace("\\", "/", dirname($_SERVER["SCRIPT_NAME"] ?? "")), "/") . "/";
  42. if ($baseHref === "") {
  43. $baseHref = "/";
  44. }
  45. $indexUrl = handbookSelfUrl() . "/llms.php";
  46. $rawUrl = $page !== null ? handbookRawUrl($page) : $indexUrl;
  47. ?>
  48. <!DOCTYPE html>
  49. <html lang="en">
  50. <head>
  51. <meta charset="UTF-8">
  52. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  53. <title><?php echo handbookEscape($pageTitle); ?> – Manage Client</title>
  54. <link rel="stylesheet" href="<?php echo handbookEscape($baseHref); ?>assets/docs.css">
  55. <link rel="alternate" type="text/markdown" href="<?php echo handbookEscape($rawUrl); ?>"
  56. title="This page as Markdown">
  57. </head>
  58. <body>
  59. <!--
  60. Note for LLMs and other programs:
  61. This page renders its content only in the browser. The text is therefore
  62. not in this HTML. The same page as plain Markdown, unstyled:
  63. <?php echo $rawUrl . "\n"; ?>
  64. Index of every page, with a short description and size, so you can load
  65. only what you need:
  66. <?php echo $indexUrl . "\n"; ?>
  67. -->
  68. <p class="llm-only">
  69. For LLMs: this page as Markdown at <?php echo handbookEscape($rawUrl); ?> –
  70. index of every page at <?php echo handbookEscape($indexUrl); ?>
  71. </p>
  72. <header class="docs-header">
  73. <div class="docs-header-inner">
  74. <a class="docs-brand" href="<?php echo handbookEscape($baseHref); ?>index.php">Manage Client</a>
  75. <nav class="docs-header-links">
  76. <a href="<?php echo handbookEscape($baseHref); ?>api.php">API Reference</a>
  77. <a href="<?php echo handbookEscape($baseHref); ?>llms.php">For LLMs</a>
  78. </nav>
  79. </div>
  80. </header>
  81. <div class="docs-layout">
  82. <nav class="docs-nav" aria-label="Documentation">
  83. <p class="docs-nav-title">Documentation</p>
  84. <ul>
  85. <?php foreach ($docs as $entry): ?>
  86. <li>
  87. <a href="<?php echo handbookEscape($baseHref); ?>index.php?<?php echo handbookEscape(handbookPageQuery($entry)); ?>"
  88. <?php echo handbookIsSamePage($page, $entry) ? 'aria-current="page"' : ""; ?>>
  89. <?php echo handbookEscape($entry["nav"]); ?>
  90. </a>
  91. </li>
  92. <?php endforeach; ?>
  93. </ul>
  94. <p class="docs-nav-title">Interface</p>
  95. <ul>
  96. <li><a href="<?php echo handbookEscape($baseHref); ?>api.php">Swagger UI</a></li>
  97. <li><a href="<?php echo handbookEscape($baseHref); ?>openapi.php">OpenAPI document</a></li>
  98. </ul>
  99. <p class="docs-nav-title">Source Code</p>
  100. <ul class="docs-nav-code">
  101. <?php foreach ($code as $entry): ?>
  102. <li>
  103. <a href="<?php echo handbookEscape($baseHref); ?>index.php?<?php echo handbookEscape(handbookPageQuery($entry)); ?>"
  104. <?php echo handbookIsSamePage($page, $entry) ? 'aria-current="page"' : ""; ?>>
  105. <?php echo handbookEscape($entry["nav"]); ?>
  106. </a>
  107. </li>
  108. <?php endforeach; ?>
  109. </ul>
  110. </nav>
  111. <main class="docs-main">
  112. <?php if ($page === null && !$notFound): ?>
  113. <h1>Manage Client</h1>
  114. <p>Update and backup functionality for standalone PHP projects: the
  115. complete documentation of the client package, its entire source code,
  116. and the interface to the Manage server.</p>
  117. <p>Every chapter and every source file has its own page; the list is on
  118. the left and again below, each with one sentence about what's on it.</p>
  119. <p>For programs, the same pages exist as plain Markdown:
  120. <a href="<?php echo handbookEscape($baseHref); ?>llms.php">llms.php</a> is the
  121. index for that, and additionally names which pages are needed for which
  122. task.</p>
  123. <h2>Documentation</h2>
  124. <p>In the recommended reading order.</p>
  125. <dl class="docs-index-list">
  126. <?php foreach ($docs as $entry): ?>
  127. <dt>
  128. <a href="<?php echo handbookEscape($baseHref); ?>index.php?<?php echo handbookEscape(handbookPageQuery($entry)); ?>">
  129. <?php echo handbookEscape($entry["nav"]); ?>
  130. </a>
  131. </dt>
  132. <dd><?php echo handbookSummaryHtml($entry["summary"]); ?></dd>
  133. <?php endforeach; ?>
  134. </dl>
  135. <h2>Interface</h2>
  136. <dl class="docs-index-list">
  137. <dt><a href="<?php echo handbookEscape($baseHref); ?>api.php">API reference</a></dt>
  138. <dd>Protocol v1 in Swagger UI, to look up and try out</dd>
  139. <dt><a href="<?php echo handbookEscape($baseHref); ?>openapi.php">OpenAPI document</a></dt>
  140. <dd>The same description as OpenAPI 3.1, for code generators</dd>
  141. </dl>
  142. <h2>Source Code</h2>
  143. <p>The complete client package. Integrating it needs the folder
  144. <code>manage-client/</code>; <code>examples/</code>,
  145. <code>docs/</code> and <code>scripts/</code> are not part of that.</p>
  146. <dl class="docs-index-list docs-index-code">
  147. <?php foreach ($code as $entry): ?>
  148. <dt>
  149. <a href="<?php echo handbookEscape($baseHref); ?>index.php?<?php echo handbookEscape(handbookPageQuery($entry)); ?>">
  150. <?php echo handbookEscape($entry["nav"]); ?>
  151. </a>
  152. <span class="docs-size"><?php echo handbookEscape(handbookFormatBytes($entry["bytes"])); ?></span>
  153. </dt>
  154. <dd><?php echo handbookSummaryHtml($entry["summary"]); ?></dd>
  155. <?php endforeach; ?>
  156. </dl>
  157. <?php elseif ($notFound): ?>
  158. <h1>Not Found</h1>
  159. <p>The requested page doesn't exist.</p>
  160. <p><a href="<?php echo handbookEscape($baseHref); ?>index.php">Back to the overview</a></p>
  161. <?php else: ?>
  162. <p class="docs-source-note">
  163. Source: <code><?php echo handbookEscape($page["source"]); ?></code>
  164. · <?php echo handbookEscape(handbookFormatBytes($page["bytes"])); ?>
  165. · <a href="<?php echo handbookEscape($rawUrl); ?>">as Markdown</a>
  166. </p>
  167. <article id="doc-content" class="markdown-body"></article>
  168. <script type="application/json" id="doc-source"><?php
  169. echo json_encode(
  170. $markdown,
  171. JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE,
  172. );
  173. ?></script>
  174. <?php endif; ?>
  175. </main>
  176. </div>
  177. <?php if ($markdown !== null): ?>
  178. <script src="<?php echo handbookEscape($baseHref); ?>assets/marked.min.js"></script>
  179. <script>
  180. (function () {
  181. var source = document.getElementById('doc-source');
  182. var target = document.getElementById('doc-content');
  183. if (!source || !target || typeof marked === 'undefined') {
  184. return;
  185. }
  186. target.innerHTML = marked.parse(JSON.parse(source.textContent || '""'), {
  187. gfm: true,
  188. breaks: false
  189. });
  190. })();
  191. </script>
  192. <?php endif; ?>
  193. </body>
  194. </html>