Bible.com iframe specific styles

Adds a class to html if bible.com is in an iframe. Adjusts font size of parallel versions to fit the left column.

当前为 2025-05-16 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Bible.com iframe specific styles
  3. // @namespace Violentmonkey Scripts
  4. // @match https://www.bible.com/*
  5. // @grant none
  6. // @version 1.6
  7. // @author Aiuanyu x Gemini
  8. // @description Adds a class to html if bible.com is in an iframe. Adjusts font size of parallel versions to fit the left column.
  9. // @description:zh-TW 當 bible.com 在 iframe 裡時,給 <html> 加個 class。調整並列版本个字體大小,讓佇左邊个欄位內看起來較好。
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. if (window.self !== window.top) {
  16. document.documentElement.classList.add('is-in-iframe');
  17. console.log('Bible.com is in an iframe, added class "is-in-iframe" to <html>');
  18.  
  19. // 當 iframe 內容載入完成後,嘗試調整並列版本个字體大小
  20. window.addEventListener('load', function () {
  21. // 等待所有字體載入完成
  22. document.fonts.ready.then(function () {
  23. console.log('All fonts loaded, attempting to adjust font size.');
  24. adjustParallelFontSize();
  25. }).catch(function (error) {
  26. console.warn('Font loading error or timeout, proceeding with font adjustment anyway:', error);
  27. adjustParallelFontSize(); // 若字體載入失敗或超時,還是嘗試執行
  28. });
  29. });
  30.  
  31. } else {
  32. console.log('Bible.com is top level window.');
  33. }
  34.  
  35. function adjustParallelFontSize() {
  36. try {
  37. const params = new URLSearchParams(window.location.search);
  38. const parallelVersionId = params.get('parallel');
  39.  
  40. if (!parallelVersionId) {
  41. console.log('No parallel version ID found in URL, skipping font adjustment.');
  42. return;
  43. }
  44.  
  45. // 取得左欄主要版本个 ID
  46. const pathSegments = window.location.pathname.match(/\/bible\/(\d+)\//);
  47. if (!pathSegments || !pathSegments[1]) {
  48. console.log('Could not extract main version ID from path, skipping font adjustment.');
  49. return;
  50. }
  51. const mainVersionId = pathSegments[1];
  52.  
  53. const leftDataVidSelector = `[data-vid="${mainVersionId}"]`;
  54. const rightDataVidSelector = `[data-vid="${parallelVersionId}"]`;
  55.  
  56. console.log('Attempting to adjust font for right column selector:', rightDataVidSelector, 'against left column selector:', leftDataVidSelector);
  57.  
  58. // 找出並列閱讀个主要容器 (根據先前个 HTML 結構)
  59. // 這選擇器可能愛根據 bible.com 實際个 HTML 結構微調
  60. // 你个 CSS userstyle 用 div.grid.grid-cols-1.md\:grid-cols-2,所以𠊎等也用共樣个
  61. const parallelContainer = document.querySelector('div.grid.md\\:grid-cols-2, div.grid.grid-cols-1.md\\:grid-cols-2');
  62. if (!parallelContainer) {
  63. // 嘗試一個較通用个選擇器,假使上面該隻無效
  64. // parallelContainer = document.querySelector('div[class*="md:grid-cols-2"]'); // 這較闊,可能愛小心
  65. // if (!parallelContainer) {
  66. console.log('Parallel container (e.g., div.grid.md:grid-cols-2) not found.');
  67. return;
  68. }
  69.  
  70. const columns = Array.from(parallelContainer.children).filter(el => getComputedStyle(el).display !== 'none');
  71. if (columns.length < 2) {
  72. console.log('Less than two visible columns found in parallel container.');
  73. return;
  74. }
  75.  
  76. const leftColumnEl = columns[0];
  77. const rightColumnEl = columns[1];
  78.  
  79. // 在左欄裡肚尋找主要版本个內容元素 (使用 data-vid)
  80. const leftVersionDiv = leftColumnEl.querySelector(leftDataVidSelector);
  81. if (!leftVersionDiv) {
  82. console.log(`Content div for left version (${leftDataVidSelector}) not found in the left column.`);
  83. return;
  84. }
  85.  
  86. // 在右欄裡肚尋找並列版本个內容元素 (使用 data-vid)
  87. // 這也是等一下要調整字體大小的目標元素
  88. const rightVersionDiv = rightColumnEl.querySelector(rightDataVidSelector);
  89. if (!rightVersionDiv) {
  90. console.log(`Content div for right version (${rightDataVidSelector}) not found in the right column.`);
  91. return;
  92. }
  93.  
  94. console.log('Found leftVersionDiv:', leftVersionDiv, 'Found rightVersionDiv:', rightVersionDiv);
  95.  
  96. // 使用 requestAnimationFrame 來確保 DOM 操作和測量是在瀏覽器準備好繪製下一幀之前進行
  97. requestAnimationFrame(() => {
  98. // 開始調整字體
  99. let currentFontSize = 90; // 初始字體大小
  100. rightVersionDiv.style.fontSize = currentFontSize + '%';
  101.  
  102. // 強制瀏覽器重繪以取得正確个初始高度
  103. leftVersionDiv.offsetHeight;
  104. rightVersionDiv.offsetHeight;
  105.  
  106. let leftHeight = leftVersionDiv.offsetHeight;
  107. let rightHeight = rightVersionDiv.offsetHeight; // 獲取初始高度
  108.  
  109. console.log(`Initial check at ${currentFontSize}%: Right height ${rightHeight}px, Left height ${leftHeight}px`);
  110.  
  111. // 如果初始字體大小就已經讓右邊內容不比左邊長,就不用調整了
  112. if (rightHeight <= leftHeight) {
  113. console.log('Initial font size ' + currentFontSize + '% is sufficient or shorter.');
  114. return;
  115. }
  116.  
  117. // 如果初始字體大小讓右邊內容比左邊長,就開始縮小字體
  118. // 預設使用最小个測試字體 (50%),假使所有測試過个字體都還係分右邊太長。
  119. let bestFitFontSize = 50;
  120. let foundOptimalAdjustment = false;
  121.  
  122. for (let testSize = currentFontSize - 1; testSize >= 50; testSize--) { // 從比初始值小1%開始,最細到 50%
  123. rightVersionDiv.style.fontSize = testSize + '%';
  124. rightHeight = rightVersionDiv.offsetHeight; // 每次改變字體大小後,重新獲取高度 (強制 reflow)
  125.  
  126. if (rightHeight > leftHeight) {
  127. // 這隻 testSize 還係分右邊太長,繼續試較細个字體。
  128. // 假使這係迴圈最後一次 (testSize == 50) 而且還係太長,
  129. // bestFitFontSize 會維持在 50%。
  130. } else {
  131. // 這隻 testSize 分右邊內容變到毋比左邊長了 (<=)。
  132. // 照你个要求,𠊎等愛用前一隻字體大細 (testSize + 1),
  133. // 因為該隻字體大細會分右邊「略略仔長過左邊」。
  134. bestFitFontSize = testSize + 1;
  135. foundOptimalAdjustment = true;
  136. console.log(`Right content became shorter/equal at ${testSize}% (height ${rightHeight}px). Applying previous size ${bestFitFontSize}% which was slightly taller.`);
  137. break; // 尋到臨界點了,跳出迴圈
  138. }
  139. }
  140.  
  141. if (!foundOptimalAdjustment && currentFontSize > 50) {
  142. // 假使迴圈跑完,foundOptimalAdjustment 還係 false,
  143. // 表示從 (currentFontSize - 1) 到 50% 所有字體都還係分右邊太長。
  144. // 在這情況下,bestFitFontSize 已經係 50%。
  145. console.log(`All tested font sizes from ${currentFontSize - 1}% down to 50% still made right content taller. Using smallest tested size: 50%.`);
  146. }
  147.  
  148. // 迴圈結束後,將字體設定為決定好个大小
  149. rightVersionDiv.style.fontSize = bestFitFontSize + '%';
  150. // 為著準確記錄最終狀態,重新量一次高度
  151. const finalRightHeight = rightVersionDiv.offsetHeight;
  152. console.log('Final adjusted font size for ' + rightDataVidSelector + ' is ' + bestFitFontSize + '%. Final Right content: ' + finalRightHeight + 'px, Left content: ' + leftHeight + 'px');
  153. });
  154. } catch (error) {
  155. console.error('Error during font adjustment:', error);
  156. }
  157. }
  158. })();