module.html 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>模块开发与测试指南 - Animal.js</title>
  7. <link rel="stylesheet" href="demo.css">
  8. <style>
  9. .md-wrap {
  10. background: #0e0e0e;
  11. border: 1px solid #1e1e1e;
  12. border-radius: 10px;
  13. overflow: hidden;
  14. box-shadow: 0 10px 40px rgba(0,0,0,0.25);
  15. }
  16. .md-head {
  17. display: flex;
  18. align-items: center;
  19. justify-content: space-between;
  20. gap: 12px;
  21. padding: 12px 16px;
  22. border-bottom: 1px solid #222;
  23. background: rgba(255,255,255,0.02);
  24. }
  25. .md-title {
  26. color: var(--orange);
  27. font-weight: 700;
  28. font-size: 13px;
  29. }
  30. .md-actions {
  31. display: inline-flex;
  32. gap: 10px;
  33. align-items: center;
  34. }
  35. .md-actions button {
  36. appearance: none;
  37. background: rgba(255,255,255,0.02);
  38. border: 1px solid #2a2a2a;
  39. color: #cfcfcf;
  40. padding: 6px 10px;
  41. border-radius: 999px;
  42. font-size: 12px;
  43. font-weight: 700;
  44. cursor: pointer;
  45. }
  46. .md-actions button:hover {
  47. border-color: var(--orange);
  48. color: var(--orange);
  49. }
  50. pre.md {
  51. margin: 0;
  52. padding: 18px 18px 22px;
  53. white-space: pre-wrap;
  54. word-break: break-word;
  55. line-height: 1.65;
  56. color: #cfcfcf;
  57. font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  58. font-size: 13px;
  59. background: #0b0b0b;
  60. max-height: calc(100vh - 210px);
  61. overflow: auto;
  62. }
  63. .hint {
  64. color: #8a8a8a;
  65. font-size: 12px;
  66. margin: 0;
  67. padding: 0 18px 16px;
  68. }
  69. </style>
  70. </head>
  71. <body>
  72. <div class="container">
  73. <div class="page-top">
  74. <div class="crumb">DEVELOPER › MODULE</div>
  75. <div class="since">WORKFLOW</div>
  76. </div>
  77. <h1>模块开发与测试指南</h1>
  78. <p class="description">
  79. 这个页面会直接读取 <code class="inline">doc/module.md</code> 的内容(原样显示)。<br>
  80. 你可以在编辑器里继续完善它,然后回来刷新这里查看最新版本。
  81. </p>
  82. <div class="md-wrap">
  83. <div class="md-head">
  84. <div class="md-title">doc/module.md</div>
  85. <div class="md-actions">
  86. <button type="button" onclick="reloadMd()">刷新</button>
  87. <button type="button" onclick="copyMd()">复制全文</button>
  88. </div>
  89. </div>
  90. <pre id="md" class="md">Loading…</pre>
  91. <p class="hint">提示:这是一份“开发用”总指导文档;具体示例页仍在各个模块里。</p>
  92. </div>
  93. <div class="doc-nav" aria-label="Previous and next navigation">
  94. <a href="#" onclick="goPrev(); return false;">
  95. <span>
  96. <span class="nav-label">Previous</span><br>
  97. <span id="prev-title" class="nav-title">—</span>
  98. </span>
  99. <span aria-hidden="true">←</span>
  100. </a>
  101. <div id="nav-center" class="nav-center">Developer</div>
  102. <a href="#" onclick="goNext(); return false;">
  103. <span>
  104. <span class="nav-label">Next</span><br>
  105. <span id="next-title" class="nav-title">—</span>
  106. </span>
  107. <span aria-hidden="true">→</span>
  108. </a>
  109. </div>
  110. </div>
  111. <div id="toast" class="toast" role="status" aria-live="polite"></div>
  112. <script>
  113. const CURRENT = 'module.html';
  114. function showToast(msg) {
  115. const el = document.getElementById('toast');
  116. if (!el) return;
  117. el.textContent = msg;
  118. el.classList.add('show');
  119. clearTimeout(el._t);
  120. el._t = setTimeout(() => el.classList.remove('show'), 900);
  121. }
  122. async function reloadMd() {
  123. const el = document.getElementById('md');
  124. if (!el) return;
  125. el.textContent = 'Loading…';
  126. try {
  127. const res = await fetch('module.md', { cache: 'no-store' });
  128. const txt = await res.text();
  129. el.textContent = txt || '(empty)';
  130. } catch (e) {
  131. el.textContent = 'Failed to load doc/module.md\n\n' + (e && e.message ? e.message : String(e));
  132. }
  133. syncPrevNext();
  134. }
  135. async function copyMd() {
  136. const el = document.getElementById('md');
  137. const text = el ? el.textContent : '';
  138. if (!text) return;
  139. try {
  140. await navigator.clipboard.writeText(text);
  141. showToast('Copied');
  142. } catch (e) {
  143. showToast('Copy failed');
  144. }
  145. }
  146. function syncPrevNext() {
  147. try {
  148. const pn = window.parent?.docGetPrevNext?.(CURRENT);
  149. const prevEl = document.getElementById('prev-title');
  150. const nextEl = document.getElementById('next-title');
  151. const centerEl = document.getElementById('nav-center');
  152. if (pn?.current && centerEl) centerEl.textContent = pn.current.group || 'Developer';
  153. if (prevEl) prevEl.textContent = pn?.prev?.title || '—';
  154. if (nextEl) nextEl.textContent = pn?.next?.title || '—';
  155. } catch {}
  156. }
  157. function goPrev() { window.parent?.docNavigatePrev?.(CURRENT); }
  158. function goNext() { window.parent?.docNavigateNext?.(CURRENT); }
  159. // Sync middle list selection when loaded inside doc/index.html
  160. try { window.parent?.setMiddleActive?.(CURRENT); } catch {}
  161. reloadMd();
  162. </script>
  163. </body>
  164. </html>