cfabric-browser 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. cfabric_browser-0.1.0/PKG-INFO +399 -0
  2. cfabric_browser-0.1.0/README.md +359 -0
  3. cfabric_browser-0.1.0/cfabric_browser/__init__.py +3 -0
  4. cfabric_browser-0.1.0/cfabric_browser/__main__.py +12 -0
  5. cfabric_browser-0.1.0/cfabric_browser/app.py +178 -0
  6. cfabric_browser-0.1.0/cfabric_browser/assistant/__init__.py +8 -0
  7. cfabric_browser-0.1.0/cfabric_browser/assistant/guides/bhsa.md +123 -0
  8. cfabric_browser-0.1.0/cfabric_browser/assistant/mcp.py +225 -0
  9. cfabric_browser-0.1.0/cfabric_browser/assistant/proposals.py +99 -0
  10. cfabric_browser-0.1.0/cfabric_browser/assistant/running.py +69 -0
  11. cfabric_browser-0.1.0/cfabric_browser/assistant/stdio.py +276 -0
  12. cfabric_browser-0.1.0/cfabric_browser/assistant/tools.py +243 -0
  13. cfabric_browser-0.1.0/cfabric_browser/books.py +107 -0
  14. cfabric_browser-0.1.0/cfabric_browser/cancel.py +84 -0
  15. cfabric_browser-0.1.0/cfabric_browser/cli.py +400 -0
  16. cfabric_browser-0.1.0/cfabric_browser/compare.py +644 -0
  17. cfabric_browser-0.1.0/cfabric_browser/concordance.py +322 -0
  18. cfabric_browser-0.1.0/cfabric_browser/corpora.py +631 -0
  19. cfabric_browser-0.1.0/cfabric_browser/dictionaries/__init__.py +1 -0
  20. cfabric_browser-0.1.0/cfabric_browser/dictionaries/bdb.py +216 -0
  21. cfabric_browser-0.1.0/cfabric_browser/dictionaries/build.py +672 -0
  22. cfabric_browser-0.1.0/cfabric_browser/dictionaries/corrections.yaml +43 -0
  23. cfabric_browser-0.1.0/cfabric_browser/dictionaries/joins.yaml +24 -0
  24. cfabric_browser-0.1.0/cfabric_browser/dictionaries/link.py +254 -0
  25. cfabric_browser-0.1.0/cfabric_browser/dictionaries/manage.py +134 -0
  26. cfabric_browser-0.1.0/cfabric_browser/dictionaries/sefaria.py +240 -0
  27. cfabric_browser-0.1.0/cfabric_browser/dictionaries/store.py +192 -0
  28. cfabric_browser-0.1.0/cfabric_browser/display/__init__.py +61 -0
  29. cfabric_browser-0.1.0/cfabric_browser/display/config.py +500 -0
  30. cfabric_browser-0.1.0/cfabric_browser/display/sections.py +158 -0
  31. cfabric_browser-0.1.0/cfabric_browser/display/tree.py +704 -0
  32. cfabric_browser-0.1.0/cfabric_browser/display_settings/DT-UCPH/sp.yaml +7 -0
  33. cfabric_browser-0.1.0/cfabric_browser/display_settings/DT-UCPH/sp@7.2.4.yaml +16 -0
  34. cfabric_browser-0.1.0/cfabric_browser/downloads.py +347 -0
  35. cfabric_browser-0.1.0/cfabric_browser/formats.py +53 -0
  36. cfabric_browser-0.1.0/cfabric_browser/guard.py +86 -0
  37. cfabric_browser-0.1.0/cfabric_browser/helpers.py +51 -0
  38. cfabric_browser-0.1.0/cfabric_browser/interfaces.py +49 -0
  39. cfabric_browser-0.1.0/cfabric_browser/interlinear.py +185 -0
  40. cfabric_browser-0.1.0/cfabric_browser/jobs.py +105 -0
  41. cfabric_browser-0.1.0/cfabric_browser/lexicon.py +225 -0
  42. cfabric_browser-0.1.0/cfabric_browser/net.py +104 -0
  43. cfabric_browser-0.1.0/cfabric_browser/queries.py +377 -0
  44. cfabric_browser-0.1.0/cfabric_browser/registry.py +183 -0
  45. cfabric_browser-0.1.0/cfabric_browser/routes/__init__.py +59 -0
  46. cfabric_browser-0.1.0/cfabric_browser/routes/common.py +234 -0
  47. cfabric_browser-0.1.0/cfabric_browser/routes/lexicon.py +146 -0
  48. cfabric_browser-0.1.0/cfabric_browser/routes/library.py +367 -0
  49. cfabric_browser-0.1.0/cfabric_browser/routes/parallel.py +249 -0
  50. cfabric_browser-0.1.0/cfabric_browser/routes/proposals.py +72 -0
  51. cfabric_browser-0.1.0/cfabric_browser/routes/reading.py +511 -0
  52. cfabric_browser-0.1.0/cfabric_browser/routes/search.py +530 -0
  53. cfabric_browser-0.1.0/cfabric_browser/static/assets/App-Dnb20mEJ.js +1 -0
  54. cfabric_browser-0.1.0/cfabric_browser/static/assets/BookView-Cz8ooLry.js +1 -0
  55. cfabric_browser-0.1.0/cfabric_browser/static/assets/ConcordanceApp-DAJGIi6L.js +1 -0
  56. cfabric_browser-0.1.0/cfabric_browser/static/assets/InterfaceMenu-C0115Vat.js +9 -0
  57. cfabric_browser-0.1.0/cfabric_browser/static/assets/InterfaceMenu-Dl65sCtJ.css +1 -0
  58. cfabric_browser-0.1.0/cfabric_browser/static/assets/InterlinearApp-B-znfkr9.js +1 -0
  59. cfabric_browser-0.1.0/cfabric_browser/static/assets/LexiconView-BVsZI_sa.js +1 -0
  60. cfabric_browser-0.1.0/cfabric_browser/static/assets/Library-BMUS5-nO.js +2 -0
  61. cfabric_browser-0.1.0/cfabric_browser/static/assets/Mark-CJT08VRv.js +1 -0
  62. cfabric_browser-0.1.0/cfabric_browser/static/assets/Navigate-BXzUyAFT.js +1 -0
  63. cfabric_browser-0.1.0/cfabric_browser/static/assets/ParallelApp-BSNAzyxT.js +2 -0
  64. cfabric_browser-0.1.0/cfabric_browser/static/assets/QueryEditor-DzhpEhTk.js +14 -0
  65. cfabric_browser-0.1.0/cfabric_browser/static/assets/ReaderApp-CcJS5D-d.js +1 -0
  66. cfabric_browser-0.1.0/cfabric_browser/static/assets/Search-BQulV0gk.js +1 -0
  67. cfabric_browser-0.1.0/cfabric_browser/static/assets/SearchView-CMq5k7Qs.js +6 -0
  68. cfabric_browser-0.1.0/cfabric_browser/static/assets/Texts-DSY6lKNw.js +1 -0
  69. cfabric_browser-0.1.0/cfabric_browser/static/assets/amiri-arabic-400-normal-C_1DQziU.woff +0 -0
  70. cfabric_browser-0.1.0/cfabric_browser/static/assets/amiri-arabic-400-normal-D0NIBXga.woff2 +0 -0
  71. cfabric_browser-0.1.0/cfabric_browser/static/assets/amiri-latin-400-normal-Bv6IM0kz.woff +0 -0
  72. cfabric_browser-0.1.0/cfabric_browser/static/assets/amiri-latin-400-normal-Czk41Rjn.woff2 +0 -0
  73. cfabric_browser-0.1.0/cfabric_browser/static/assets/amiri-latin-ext-400-normal-C9hoIjPx.woff2 +0 -0
  74. cfabric_browser-0.1.0/cfabric_browser/static/assets/amiri-latin-ext-400-normal-CGn-6a7O.woff +0 -0
  75. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-cyrillic-400-normal-2gl_A-Tn.woff +0 -0
  76. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-cyrillic-400-normal-BKY-Jqah.woff2 +0 -0
  77. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-cyrillic-ext-400-normal-B9Nl3F-2.woff +0 -0
  78. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-cyrillic-ext-400-normal-CJ4YKexy.woff2 +0 -0
  79. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-greek-400-normal-CYsP5XPD.woff +0 -0
  80. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-greek-400-normal-FlMNHri1.woff2 +0 -0
  81. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-greek-ext-400-normal-DOc93t8p.woff2 +0 -0
  82. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-greek-ext-400-normal-Vs3SB95H.woff +0 -0
  83. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-latin-400-normal-Bx4sytbw.woff2 +0 -0
  84. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-latin-400-normal-CBUjaU8k.woff +0 -0
  85. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-latin-ext-400-normal-B46t2ITS.woff +0 -0
  86. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-latin-ext-400-normal-BID1L8QP.woff2 +0 -0
  87. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-vietnamese-400-normal-C_3yQKPY.woff +0 -0
  88. cfabric_browser-0.1.0/cfabric_browser/static/assets/gentium-plus-vietnamese-400-normal-lfG8qd7w.woff2 +0 -0
  89. cfabric_browser-0.1.0/cfabric_browser/static/assets/index-CerWo5pG.css +1 -0
  90. cfabric_browser-0.1.0/cfabric_browser/static/assets/index-DcB4YcRU.js +50 -0
  91. cfabric_browser-0.1.0/cfabric_browser/static/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  92. cfabric_browser-0.1.0/cfabric_browser/static/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  93. cfabric_browser-0.1.0/cfabric_browser/static/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  94. cfabric_browser-0.1.0/cfabric_browser/static/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  95. cfabric_browser-0.1.0/cfabric_browser/static/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  96. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-sans-syriac-latin-400-normal-D2_119oK.woff2 +0 -0
  97. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-sans-syriac-latin-400-normal-DpW_KDWJ.woff +0 -0
  98. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-sans-syriac-latin-ext-400-normal-CKWjGUw2.woff2 +0 -0
  99. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-sans-syriac-latin-ext-400-normal-G7wAZA1M.woff +0 -0
  100. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-sans-syriac-syriac-400-normal-Bz33PzP0.woff +0 -0
  101. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-sans-syriac-syriac-400-normal-CWH9OPix.woff2 +0 -0
  102. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-hebrew-400-normal-jyUp5Tfv.woff +0 -0
  103. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-hebrew-400-normal-v_xU1ROG.woff2 +0 -0
  104. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-hebrew-600-normal-5Q1AJcd_.woff2 +0 -0
  105. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-hebrew-600-normal-BBqYD5TV.woff +0 -0
  106. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-400-normal-BWkL_LQQ.woff +0 -0
  107. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-400-normal-D22OmSTw.woff2 +0 -0
  108. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-600-normal-DUOQhjy6.woff2 +0 -0
  109. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-600-normal-fgAR10AF.woff +0 -0
  110. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-ext-400-normal-BiXgBxzW.woff2 +0 -0
  111. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-ext-400-normal-DPDY_J25.woff +0 -0
  112. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-ext-600-normal-D4x26vgI.woff +0 -0
  113. cfabric_browser-0.1.0/cfabric_browser/static/assets/noto-serif-hebrew-latin-ext-600-normal-DSAqAqQ_.woff2 +0 -0
  114. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-cyrillic-ext-wght-italic-y6hTrs-Y.woff2 +0 -0
  115. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-cyrillic-ext-wght-normal-DHTKMUil.woff2 +0 -0
  116. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-cyrillic-wght-italic-CRzqOTyj.woff2 +0 -0
  117. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-cyrillic-wght-normal-B1g8a0vD.woff2 +0 -0
  118. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-greek-wght-italic-CUp-f2uw.woff2 +0 -0
  119. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-greek-wght-normal-BpXpdlRW.woff2 +0 -0
  120. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-latin-ext-wght-italic-B_cmBfNX.woff2 +0 -0
  121. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-latin-ext-wght-normal-BVZ5su8S.woff2 +0 -0
  122. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-latin-wght-italic-B-rCj6ir.woff2 +0 -0
  123. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-latin-wght-normal-DMe4EKeb.woff2 +0 -0
  124. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-vietnamese-wght-italic-D3EGHrWW.woff2 +0 -0
  125. cfabric_browser-0.1.0/cfabric_browser/static/assets/source-serif-4-vietnamese-wght-normal-BsaNuasd.woff2 +0 -0
  126. cfabric_browser-0.1.0/cfabric_browser/static/assets/terms-DEvE2HBo.js +2 -0
  127. cfabric_browser-0.1.0/cfabric_browser/static/favicon.svg +4 -0
  128. cfabric_browser-0.1.0/cfabric_browser/static/guide/adding-texts.html +67 -0
  129. cfabric_browser-0.1.0/cfabric_browser/static/guide/asking-claude.html +127 -0
  130. cfabric_browser-0.1.0/cfabric_browser/static/guide/concordance.html +75 -0
  131. cfabric_browser-0.1.0/cfabric_browser/static/guide/datasets.html +142 -0
  132. cfabric_browser-0.1.0/cfabric_browser/static/guide/getting-started.html +146 -0
  133. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/bdb.png +0 -0
  134. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/collocations.png +0 -0
  135. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/concordance.png +0 -0
  136. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/differences.png +0 -0
  137. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/hover.png +0 -0
  138. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/inspector.png +0 -0
  139. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/interlinear.png +0 -0
  140. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/lexicon.png +0 -0
  141. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/library.png +0 -0
  142. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/menu.png +0 -0
  143. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/navigate.png +0 -0
  144. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/panes.png +0 -0
  145. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/parallel.png +0 -0
  146. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/proposal.png +0 -0
  147. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/reader-dark.png +0 -0
  148. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/reader.png +0 -0
  149. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/search-terms.png +0 -0
  150. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/search.png +0 -0
  151. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/statistics.png +0 -0
  152. cfabric_browser-0.1.0/cfabric_browser/static/guide/images/workspaces.png +0 -0
  153. cfabric_browser-0.1.0/cfabric_browser/static/guide/index.html +62 -0
  154. cfabric_browser-0.1.0/cfabric_browser/static/guide/interfaces.html +115 -0
  155. cfabric_browser-0.1.0/cfabric_browser/static/guide/notes-and-citing.html +74 -0
  156. cfabric_browser-0.1.0/cfabric_browser/static/guide/problems.html +71 -0
  157. cfabric_browser-0.1.0/cfabric_browser/static/guide/reading.html +105 -0
  158. cfabric_browser-0.1.0/cfabric_browser/static/guide/searching.html +223 -0
  159. cfabric_browser-0.1.0/cfabric_browser/static/guide/words.html +107 -0
  160. cfabric_browser-0.1.0/cfabric_browser/static/index.html +14 -0
  161. cfabric_browser-0.1.0/cfabric_browser/summary.py +202 -0
  162. cfabric_browser-0.1.0/cfabric_browser/translations/__init__.py +12 -0
  163. cfabric_browser-0.1.0/cfabric_browser/translations/build.py +505 -0
  164. cfabric_browser-0.1.0/cfabric_browser/translations/catalog.py +164 -0
  165. cfabric_browser-0.1.0/cfabric_browser/translations/hebrew_verses.json +41 -0
  166. cfabric_browser-0.1.0/cfabric_browser/translations/manage.py +123 -0
  167. cfabric_browser-0.1.0/cfabric_browser/window.py +81 -0
  168. cfabric_browser-0.1.0/cfabric_browser/witnesses.py +254 -0
  169. cfabric_browser-0.1.0/cfabric_browser/words.py +68 -0
  170. cfabric_browser-0.1.0/cfabric_browser/workers.py +627 -0
  171. cfabric_browser-0.1.0/cfabric_browser.egg-info/PKG-INFO +399 -0
  172. cfabric_browser-0.1.0/cfabric_browser.egg-info/SOURCES.txt +201 -0
  173. cfabric_browser-0.1.0/cfabric_browser.egg-info/dependency_links.txt +1 -0
  174. cfabric_browser-0.1.0/cfabric_browser.egg-info/entry_points.txt +3 -0
  175. cfabric_browser-0.1.0/cfabric_browser.egg-info/requires.txt +18 -0
  176. cfabric_browser-0.1.0/cfabric_browser.egg-info/top_level.txt +1 -0
  177. cfabric_browser-0.1.0/pyproject.toml +80 -0
  178. cfabric_browser-0.1.0/setup.cfg +4 -0
  179. cfabric_browser-0.1.0/tests/test_api.py +553 -0
  180. cfabric_browser-0.1.0/tests/test_ask_questions.py +102 -0
  181. cfabric_browser-0.1.0/tests/test_assistant.py +190 -0
  182. cfabric_browser-0.1.0/tests/test_assistant_mcp.py +305 -0
  183. cfabric_browser-0.1.0/tests/test_assistant_questions.py +83 -0
  184. cfabric_browser-0.1.0/tests/test_cancel.py +53 -0
  185. cfabric_browser-0.1.0/tests/test_compare.py +202 -0
  186. cfabric_browser-0.1.0/tests/test_concordance.py +201 -0
  187. cfabric_browser-0.1.0/tests/test_dictionaries.py +291 -0
  188. cfabric_browser-0.1.0/tests/test_dictionary_build.py +352 -0
  189. cfabric_browser-0.1.0/tests/test_dictionary_link.py +182 -0
  190. cfabric_browser-0.1.0/tests/test_display.py +374 -0
  191. cfabric_browser-0.1.0/tests/test_downloads.py +409 -0
  192. cfabric_browser-0.1.0/tests/test_formats.py +62 -0
  193. cfabric_browser-0.1.0/tests/test_guard.py +49 -0
  194. cfabric_browser-0.1.0/tests/test_interfaces.py +34 -0
  195. cfabric_browser-0.1.0/tests/test_interlinear.py +114 -0
  196. cfabric_browser-0.1.0/tests/test_lexicon.py +210 -0
  197. cfabric_browser-0.1.0/tests/test_multi.py +384 -0
  198. cfabric_browser-0.1.0/tests/test_parallel.py +211 -0
  199. cfabric_browser-0.1.0/tests/test_registry.py +87 -0
  200. cfabric_browser-0.1.0/tests/test_summary.py +137 -0
  201. cfabric_browser-0.1.0/tests/test_translations.py +432 -0
  202. cfabric_browser-0.1.0/tests/test_witnesses.py +336 -0
  203. cfabric_browser-0.1.0/tests/test_workers.py +170 -0
@@ -0,0 +1,399 @@
1
+ Metadata-Version: 2.4
2
+ Name: cfabric-browser
3
+ Version: 0.1.0
4
+ Summary: CACCHT Explorer, a graphical browser for Context-Fabric corpora: search, read and compare, offline
5
+ Author: Martijn Naaijer
6
+ License: MIT
7
+ Project-URL: Homepage, https://context-fabric.ai/docs/explorer
8
+ Project-URL: Documentation, https://caccht.github.io/explorer/
9
+ Project-URL: Changelog, https://github.com/Context-Fabric/context-fabric/blob/master/libs/explorer/CHANGELOG.md
10
+ Project-URL: Repository, https://github.com/Context-Fabric/context-fabric
11
+ Project-URL: Issues, https://github.com/Context-Fabric/context-fabric/issues
12
+ Keywords: context-fabric,text-fabric,hebrew bible,corpus,bhsa,dead sea scrolls
13
+ Classifier: Development Status :: 2 - Pre-Alpha
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Framework :: FastAPI
21
+ Classifier: Topic :: Religion
22
+ Classifier: Topic :: Text Processing :: Linguistic
23
+ Requires-Python: >=3.13
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: context-fabric>=0.5.7
26
+ Requires-Dist: cfabric-mcp>=0.1.9
27
+ Requires-Dist: fastapi>=0.115
28
+ Requires-Dist: uvicorn>=0.32.0
29
+ Requires-Dist: pyyaml>=6.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.0; extra == "dev"
32
+ Requires-Dist: httpx2>=2.0; extra == "dev"
33
+ Provides-Extra: window
34
+ Requires-Dist: pywebview>=5.0; extra == "window"
35
+ Requires-Dist: certifi; extra == "window"
36
+ Provides-Extra: build
37
+ Requires-Dist: pyinstaller>=6.10; extra == "build"
38
+ Requires-Dist: pywebview>=5.0; extra == "build"
39
+ Requires-Dist: certifi; extra == "build"
40
+
41
+ # CACCHT Explorer (cfabric-browser)
42
+
43
+ CACCHT Explorer is a graphical browser for [Context-Fabric](https://context-fabric.ai) corpora, the successor of the Text-Fabric browser. It runs on your own computer and works offline.
44
+
45
+ The package, its command and its module keep their technical names: `cfabric-browser` and `cfabric_browser`. The code is in `libs/explorer`.
46
+
47
+ It works with either Context-Fabric core: the Python one (`context-fabric` 0.5) and the Rust one (0.6), which searches several times faster. It uses only their public API.
48
+
49
+ > **Status: pre-alpha.** Reading, searching and inspecting work, also with several corpora side by side.
50
+
51
+ **Using the program** is explained in the user guide: [Guide to CACCHT Explorer](https://caccht.github.io/explorer/) on caccht.github.io, also built into the program at `/guide/` (written in `guide/`; see *The user guide* below). Most users have the standalone program from the [desktop pre-releases](https://github.com/Context-Fabric/context-fabric/releases). This README is for installing it with pip, its options, the API and development; [context-fabric.ai](https://context-fabric.ai/docs/explorer) has an overview for programmers.
52
+
53
+ ## Usage
54
+
55
+ It needs Python 3.13 or newer.
56
+
57
+ ```bash
58
+ pip install "cfabric-browser[window]"
59
+ cfabric-browser bhsa
60
+ ```
61
+
62
+ This also installs Context-Fabric (`context-fabric`) and its MCP tools (`cfabric-mcp`). `[window]` adds what `--window` needs (pywebview); without it the Explorer opens in your web browser. For the Rust core, which searches faster, install its release candidate as well: `pip install --pre "context-fabric==0.6.0rc1"`.
63
+
64
+ This opens the browser at <http://localhost:8107/>. The command is also installed as `caccht-explorer`, under the app's name; both do the same. Give several corpora to compare them, e.g. `cfabric-browser bhsa CenterBLC/LXX ETCBC/peshitta`; others can be opened from the browser with *Open a corpus*. Without corpora (`cfabric-browser`), the browser starts empty and shows that list straight away. You can give a corpus in several ways:
65
+
66
+ | Argument | Meaning |
67
+ |---|---|
68
+ | `bhsa`, `ETCBC/dss` | A corpus that Text-Fabric has downloaded or cloned, in `~/text-fabric-data/github` or `~/github` |
69
+ | `~/github/ETCBC/bhsa` | A repository in Text-Fabric layout (`tf/<version>/`); the version in its app config is used, otherwise the newest |
70
+ | `path/to/tf/2021` | A data directory with `.tf` files or a `.cfm` cache |
71
+ | `DT-UCPH/sp@7.2.4`, `sp@latest` | A specific version, or the newest on this computer (by default the version named in the corpus' app config) |
72
+ | `hebrew=…` | Any of the above, shown under the name `hebrew` |
73
+
74
+ Options:
75
+ - `--port`: default 8107.
76
+ - `--workers`: how many searches can run at once (default 2).
77
+ - `--timeout`: time limit per search in seconds (default 60).
78
+ - `--max-results`: results kept per search (default 500,000).
79
+ - `--no-open`: don't open a web browser.
80
+ - `--window` (`--no-window`): show the browser in a window of its own instead of a web browser (needs pywebview: `pip install cfabric-browser[window]`). Closing the window stops the server. Without `--port` it uses the first free port from 8107, so several windows can run at once. The window keeps its settings, search history and saved workspaces in `~/.cfabric/window`.
81
+ - `--ui NAME`: the interface to start in until the user chooses one: `panes` (the default), `parallel`, `reader`, `interlinear` or `concordance`. Permanently, and to leave interfaces out of the menu, in `~/.cfabric/browser.yaml`:
82
+
83
+ ```yaml
84
+ ui:
85
+ default: parallel
86
+ hide: [concordance]
87
+ ```
88
+
89
+ (`ui: parallel` alone also works.) See *Interfaces*.
90
+ - `--no-library`: don't let users open other corpora found on this computer. Then at least one corpus must be given.
91
+ - `--only ORG/REPO`: limit the *Open a corpus* list to these corpora (repeatable), e.g. for a test with a few corpora; others can't be opened from the browser either. Permanently: `library: only:` in `~/.cfabric/browser.yaml`.
92
+ - `--hide ORG/REPO`: leave a corpus out of the *Open a corpus* list (repeatable). To do this permanently, list them in `~/.cfabric/browser.yaml`:
93
+
94
+ ```yaml
95
+ library:
96
+ hide:
97
+ - CLARIAH/descartes-tf
98
+ ```
99
+
100
+ The list also shows copies of one corpus (same title, such as a fork) only once, keeping the one with the newest data.
101
+
102
+ The server listens on `127.0.0.1` only. Pass `--host` to change that, and only when you know what you're doing.
103
+
104
+ ## Downloading corpora
105
+
106
+ The BHSA (2021), the Samaritan Pentateuch (7.2.4) and the Dead Sea Scrolls (2.0.1) can be downloaded from the browser when they are not on this computer: *Open a corpus* lists them under *Can be downloaded*, with their size; *Download* gets one and opens it. From the command line:
107
+
108
+ ```bash
109
+ cfabric-browser download # the corpora that can be downloaded, and which are here
110
+ cfabric-browser download bhsa sp dss
111
+ ```
112
+
113
+ - They come from the corpora's own releases on GitHub, the same files Text-Fabric downloads, and each is checked against its checksum.
114
+ - They go where Text-Fabric keeps its downloads (`~/text-fabric-data/github`), in its layout and with its `__checkout__.txt` files, so Text-Fabric uses them too. A data folder that is already there is never overwritten.
115
+ - About 68 MB for the three (365 MB on disk). Right after downloading, each is opened and prepared once, which takes a few minutes for the BHSA and the DSS; after that it opens in a few seconds.
116
+ - With `--ask-downloads` (as the standalone program starts), the browser first offers the missing ones on a screen of their own, with one *Download* button; *Not now* is remembered.
117
+
118
+ ## Translations
119
+
120
+ Translations can be added as texts of their own, shown next to the Hebrew ones. The first is the **JPS 1917**, *The Holy Scriptures: A New Translation* of the Jewish Publication Society (1917). In *Open a corpus*, under *Translations*, *Add* downloads it from Sefaria's export (about 5 MB), prepares it in a few seconds and opens it; *Remove* deletes it again. From the command line:
121
+
122
+ ```bash
123
+ cfabric-browser add # the translations that can be added
124
+ cfabric-browser add jps1917
125
+ cfabric-browser remove jps1917
126
+ ```
127
+
128
+ - It is public domain in the United States, because it was published before 1931. Elsewhere that depends on the translators' dates; check the rules in your country.
129
+ - It becomes an ordinary corpus in `~/text-fabric-data/github/Context-Fabric/jps1917/tf/1917`, which Text-Fabric can also open: words (`text`, `trailer`, and `lower` for searching, as in `word lower=lord`), verses, chapters and books with the BHSA's English book names.
130
+ - Its verses follow the Hebrew numbering, as in the BHSA, so they line up verse by verse. In three places the 1917 print joins verses that the BHSA divides: the Ten Commandments in Exodus 20:13–16 and Deuteronomy 5:17–20, and Numbers 25:19 with 26:1. Those are divided as in the BHSA, and the feature `printed` on a verse keeps the print's number (for instance `20:14` on Exodus 20:17).
131
+ - A verse repeated in small type after the last verse of Malachi, Lamentations and Ecclesiastes, as read in the synagogue, is in the feature `note`.
132
+ - Building it checks the source: its title and licence, the number of chapters and verses per book, and that there is no markup other than those notes. When something differs, it stops and says where.
133
+ - The download is kept in `~/.cfabric/translations`, so adding it again needs no network. A translation that is open is removed when the browser starts again.
134
+
135
+ In the interfaces:
136
+ - *Parallel*, *Panes* and the Reader (also under *Parallels*): a text like the others, read from left to right. A note printed after a verse is shown dimmed after it, and a verse divided differently in the print says so (`(20:13 in the print)`).
137
+ - *Interlinear*: a translation can't be paired word by word with the Hebrew, so under *Under* (heading *Translations*) it comes as a line under each verse. It is not offered as the text shown word by word.
138
+ - *Concordance*: search in English, e.g. `word lower=lord`; sorting and collocations go by the word in lower case.
139
+ - *Differences*: translations are left out of the comparison.
140
+ - The card shown when hovering over a word stays away for English words, which have no gloss or morphology; a search term made from one uses `lower`.
141
+ - *Cite* names the 1917 edition and Sefaria's export.
142
+
143
+ ## Dictionaries
144
+
145
+ **BDB**, *A Hebrew and English Lexicon of the Old Testament* by Brown, Driver and Briggs (Oxford, 1906), can be added to the lexicon. A lexeme's page (BHSA) then has a tab *BDB* next to *Occurrences* with its entry:
146
+
147
+ - the text as Sefaria has it, its verses as links that open the passage, its references to other entries as links to them, and BDB's abbreviations explained when the mouse is on them;
148
+ - the neighbouring entries, the root family (the root and the words BDB derives from it, with links to their lexemes), Strong's and TWOT numbers, and a link to the entry on Sefaria;
149
+ - when a lexeme is linked to more than one entry, all of them, the main one first, and a note when the link is less sure.
150
+
151
+ Elsewhere:
152
+ - *Lexicon* list: *Find* also searches BDB's short definitions (*perish* finds אבד), each lexeme shows BDB's definition where it differs from the gloss, and the order *By root (BDB)* lists the lexemes under their root's letter in BDB's order, the words derived from a root indented under it.
153
+ - The card shown when hovering over a word and the inspector give BDB's entry of its lexeme; the inspector has *BDB entry*, which opens the lexicon at it. DSS words get it through the BHSA's lexeme, as they get their gloss.
154
+ - The Reader's *Lexicon* tab shows BDB's definitions; the Interlinear offers the line *BDB (its short definition)*.
155
+
156
+ The links from the BHSA's lexemes to the entries are made when the file is built: the words of each verse are aligned with the Open Scriptures Hebrew Bible, whose lemmas lead to BDB's entries, and checked against the verses BDB cites. The file is built once and published (about 5 MB, in `~/.cfabric/dictionaries/bdb`); in *Open a corpus*, under *Dictionaries*, *Add* downloads it and *Remove* deletes it. From the command line:
157
+
158
+ ```bash
159
+ cfabric-browser add bdb # download it
160
+ cfabric-browser add bdb FILE # a file built on this computer
161
+ cfabric-browser remove bdb
162
+ python -m cfabric_browser.dictionaries.build OUT # build it (walks Sefaria's API once, about 12,000 requests)
163
+ ```
164
+
165
+ The file is licensed under CC BY-NC 4.0, like the BHSA, the SP and the DSS. The text of BDB (1906) is in the public domain (Sefaria's is from a scan in the National Library of Israel), and Open Scriptures' data in it (ids, short definitions, Strong's and TWOT numbers, from its CC BY 4.0 lexicon) remains available under CC BY 4.0. The links to the BHSA's lexemes derive from the BHSA (CC BY-NC 4.0).
166
+
167
+ ## Interfaces
168
+
169
+ The browser has several interfaces, chosen in the menu at the right of the top bar (it shows the name of the one in use). Switching keeps the passage, the corpora, the search, the lexicon and the settings; what an interface cannot show is kept for the next one. The interface used last is remembered by the web browser (or the window); `--ui` only sets the one for a first start. *Choose which to offer…* in the menu leaves interfaces out of it, though never the one in use, nor both *Panes* and *Parallel*.
170
+
171
+ All five are built: *Panes*, *Parallel*, *Reader*, *Interlinear* and *Concordance*.
172
+
173
+ ### Reader
174
+
175
+ *Reader* (`/read/bhsa/Genesis/1?v=3&panel=parallels`) shows one text in a quiet, wide column.
176
+
177
+ - **Reading:**
178
+ - *Verses* gives a line per verse; *Running text* runs the verses on, with a new paragraph after each petuhah (פ) or setumah (ס) in the text.
179
+ - Scrolling goes on into the next chapters, and the address follows the chapter at the top.
180
+ - `‹ ›`, the arrow keys and the chapter name (for the books and chapters) work as in *Parallel*. The menu next to it chooses the text to read.
181
+ - **The panel:** clicking a verse marks it and opens the panel, on the right (on a phone, from the bottom). Clicking a word opens the panel at that word. Its tabs:
182
+ - *Parallels*: the verse in the other texts, chosen with *Texts*; the DSS per scroll; *Show differences* marks them, in the text read as well.
183
+ - *Words*: the words of the verse with gloss and morphology; click one for everything about it.
184
+ - *Lexicon*: the verse's lexemes with gloss and frequency. *All* opens the lexicon in *Parallel*.
185
+ - *Search*: a search for words like one of the verse's, opened in *Parallel*.
186
+ - *Notes*: your own note and bookmark (★) on the verse, and a list of all your notes. They are kept in this browser (or the program's window), never sent anywhere, and are included in exported workspaces.
187
+ - *Cite*, next to the chapter, cites the chapter, or the verse chosen.
188
+
189
+ - *Panes* (`/?c0=bhsa&ref0=Genesis+1&...`): up to four panes side by side, each with its own corpus, passage and view.
190
+ - *Parallel* (`/Genesis/1?texts=bhsa,sp,dss`): a slim top bar with the chapter (`‹ ›` and ←/→ for the neighbours, the chapter name for a drawer with the books and their chapters), and a column per corpus. *Texts* turns open corpora on and off, orders the columns, and adds more from the corpora on this computer; `–` on a column removes it. The chapters follow the BHSA's numbering, also when the BHSA is not shown (it is opened in the background when it is on this computer); without it, the first column's. Each row is a verse: verses are matched by book (through the book concordance), chapter and verse number, there is a row for every verse number in any of the texts, and a text that lacks a verse has an empty cell. A corpus read by biblical book (DSS) shows in each cell the text of every scroll that has the verse, labelled with the scroll. A corpus without the chapter keeps a narrow column marked *not in this corpus*.
191
+
192
+ Hovering over a word shows the same card as in *Panes*; clicking it opens the word panel on the left, with the same contents as the inspector and, for a BHSA word, *Lexicon entry*. *Lexicon* in the top bar (when a corpus with a lexicon is open) shows the lexicon instead of the chapter; a verse in it opens its chapter with that verse marked (`&v=26`; the lexicon is `&lexicon=bhsa&lx=…`). Its *Search* goes to the search in *Panes* for now.
193
+
194
+ *Differences* in the top bar (`&diff=1`) marks the words where the texts differ from the first column, with the same rules and colours as *Show differences* in *Panes*; each column header says how many words differ, and hovering over a marked word says from what. With MT, SP and the DSS shown, a DSS cell lists, for each place in that verse where MT and SP differ and a scroll preserves the text, which scrolls side with which.
195
+
196
+ *Search* in the top bar searches one of the shown texts (`&search=1&sc=bhsa&q=…&s=…`), in either of two ways:
197
+
198
+ - *Template* (the default): the query editor of *Panes*, starting from the template the terms make, if there are any.
199
+ - *Search terms*: click a word, then *Add as search term* in the word panel (adding one switches to *Search terms*). A term finds words with the features you tick (its transliterated lexeme, or else its lexeme, to start with; also part of speech, stem, tense, person, gender, number, state). Choose whether all terms must be in one verse, sentence, clause or phrase, and, for corpora with books, which books (by the book feature's own values: the BHSA's `book` says `Jesaia` where the list says Isaiah). The search template this makes is shown below.
200
+
201
+ Results are rows: the passage, then the verse the result lies in, in the searched text with the result's innermost nodes highlighted, and the same verse in the other texts (the DSS: per scroll); 25 per page. *Statistics*, *Download…* and *Cite* are as in *Panes*; clicking a passage opens its chapter at that verse. A shared link to a search the server no longer has runs it again.
202
+
203
+ The top bar also has *Display* (for the BHSA *Vocalized* or *Unvocalized* text, and what is shown; shared with *Panes*), *Workspaces* (a saved workspace remembers its interface: loading a parallel one from *Panes* switches over, and the other way round), *Cite* next to the chapter (a citation per shown text), and light or dark colours. On a phone the texts of a verse are shown below each other, each with its name.
204
+
205
+
206
+ ### Interlinear
207
+
208
+ *Interlinear* (`/interlinear/bhsa/Genesis/1?under=sp&struct=1`) opens with the BHSA, and shows each word as a small block with lines under it. The blocks run from right to left, so a verse reads as a sentence.
209
+
210
+ - **Lines** chooses the lines and their order. They are read by role, as on the hover card, so the SP and the DSS work too:
211
+ - the word;
212
+ - the transliteration of the lexeme (`BR>[`);
213
+ - the lexeme;
214
+ - the gloss;
215
+ - the part of speech;
216
+ - the morphology, in words;
217
+ - and any feature of the corpus (*Add a feature*).
218
+ - **Under** shows another text word by word under the words, with its differences marked. The SP under the BHSA, for example: words are matched on their consonants, as in the comparison, so a different word division still lines up.
219
+ - **Structure** groups the words in phrases, underlined with their function (`Pred`, `Subj`, `Objc`, …), and in clauses with their type (`WayX`, `xQtX`, …).
220
+ - **Practise** hides a line; click a word's **?** to see it, or use *Show all* and *Hide again*.
221
+ - **Colour** colours the words by part of speech, or the verbs by stem, with a legend.
222
+ - Clicking a word opens the word panel on the right.
223
+ - *Cite*, next to the chapter, cites the chapter, or the verse chosen.
224
+
225
+ A transliteration of the word as it sounds is not available yet: the BHSA's `phono` is a module of its own.
226
+
227
+ ### Concordance
228
+
229
+ *Concordance* (`/concordance/bhsa?q=…`) starts from a search: a template, or search terms made from words in the results (click a word, then *Add as search term*). The results come as lines (KWIC, key word in context): the hit in the middle and the words before and after it on either side, within the same book. Clicking a passage opens it in the *Reader*.
230
+
231
+ - **Sort by** the hit or a word before or after it (up to the third), by its form (consonants), lexeme or part of speech. Patterns show at once, such as what comes before HLK[.
232
+ - **Facets** on the left: book, part of speech, stem, tense, person, gender, number, state, language, each with counts. A click filters the lines, and the facets follow.
233
+ - **Above the lines:**
234
+ - the number of lines and of hits per 10,000 words;
235
+ - *Context* (3, 6 or 10 words);
236
+ - *One per verse*;
237
+ - *Sample* (a random 50 to 500; *another* draws again);
238
+ - *Download lines*: a TSV table of passage, before, hit and after, in the order and with the filters shown, at most 20,000.
239
+ - **Collocations:** the lexemes (or forms, or parts of speech) within 1 to 5 words of the hits, with their count there, their frequency in the corpus and their logDice score. logDice measures how typical a word is near the hit (at most 14).
240
+ - **Statistics:** as in the other interfaces.
241
+
242
+ *Cite* in the line with the number of results cites the search. On a phone the facets fold away behind *Filters*.
243
+
244
+ ## Queries
245
+
246
+ Queries use Text-Fabric's search template language, run by Context-Fabric's search engine. Queries written for the TF browser work unchanged and give the same results.
247
+
248
+ Problems in a template are reported per line. That includes problems inside quantifiers such as `/without/`, which the engine itself only logs, and then returns results as if the quantifier excluded nothing.
249
+
250
+ ## Asking in your own words
251
+
252
+ You can ask your own AI app (with your own subscription) for a search in plain language, for instance *all cases of >LHJM/ in the BHSA*. The model writes a search template, checks it with a small trial search, and sends it to the browser. There it appears above the search form, in Panes, Parallel and the Concordance, with your request, the template, the model's explanation and the trial's count: *Run* runs it, *Edit* puts it in the editor first, *Dismiss* drops it. Nothing runs by itself, and the results always come from the browser's own search, never from the model's text. Where a search came from stays with it: in its link, the workspace and the citation ("Proposed by Claude, 16 October 2026, for: …", with *(edited)* when you changed the template).
253
+
254
+ The browser serves its tools over MCP; the app connects to it while the browser runs:
255
+
256
+ - **Claude Code:** `claude mcp add --transport http context-fabric http://127.0.0.1:8107/mcp` (8107 is the browser's usual port; with `--port`, use that one). Or, whatever the port: `claude mcp add context-fabric -- cfabric-browser mcp`.
257
+ - **Claude Desktop:** install the extension `CACCHT-Explorer.mcpb` (from the release, or `python packaging/mcpb/pack.py`) by opening it, or in *Settings → Extensions*. Or add to `claude_desktop_config.json`: `"mcpServers": {"context-fabric": {"command": "cfabric-browser", "args": ["mcp"]}}` (the standalone program works too: its path, with `mcp`).
258
+ - **Antigravity CLI** (Google's successor of Gemini CLI): in `~/.gemini/config/mcp_config.json`, `"mcpServers": {"context-fabric": {"command": "cfabric-browser", "args": ["mcp"]}}`.
259
+ - **The ChatGPT desktop app and Codex** (Codex's app, CLI and IDE extension; they share `~/.codex/config.toml`; in the ChatGPT app perhaps only when working with Codex): in the desktop app *Settings → MCP servers → Add server*, *Streamable HTTP*, `http://127.0.0.1:8107/mcp`; or `codex mcp add context-fabric --url http://127.0.0.1:8107/mcp`. To have it start the browser, in `config.toml` under `[mcp_servers.context-fabric]`: `command = "cfabric-browser"` and `args = ["mcp"]` (the form may have no field for arguments, and the Mac program's path has a space). The first tool call may wait for the corpora to open: `tool_timeout_sec = 300` there (the default is 60). ChatGPT on the web and on phones can't reach a program on your computer.
260
+
261
+ `cfabric-browser mcp` passes each message on to the running browser (found in `~/.cfabric/running.json`, which the browser writes when it starts) and starts one if none runs. The tools: `list_corpora`, `corpus_guide`, `describe_corpus`, `list_features`, `describe_feature`, `search_syntax_guide`, `check_template`, `try_search` (the count up to 10,000 within 20 s and a few examples, with hints when there are none) and `propose_search`. `/mcp` only answers on 127.0.0.1 and refuses requests from web pages, so other sites in your web browser can't use it.
262
+
263
+ What you ask goes to the AI company of your app; the corpora stay on your computer, apart from the few examples the model sees in its trial searches.
264
+
265
+ How well an app does is measured with the 30 requests of `tests/data/bhsa-questions.yaml`: `python scripts/ask_questions.py claude` (or `codex`) sends each to the app without its interactive screen (`claude -p`, `codex exec`, on your own subscription), connected to a running browser with the BHSA open (`--url`, default port 8107), runs each proposal in full and compares its count with the question's. It prints a summary (proposed, right count, trials per request) and writes the rows as JSON lines. `--only 1,5` asks a few, `--model` chooses the model. Not in CI.
266
+
267
+ ## Words
268
+
269
+ Hovering over a word shows a card with its essentials: gloss, lexeme, transliteration, part of speech and morphology (stem, tense, person, gender, number, state, suffix), in words rather than codes, and, with *Show differences*, what it differs from. Each is read from the first feature of its role that has a value; values such as `NA` and `absent` are left out (`cfabric_browser/summary.py`). The DSS has its own analysis and the ETCBC's (features ending in `_etcbc`, as in the BHSA): the ETCBC's comes first (e.g. `sp_etcbc`, which tells prepositions and proper nouns apart), the DSS's own where the ETCBC has nothing. The DSS has no glosses: they come from the lexicon of another open corpus (the BHSA), by the word's ETCBC lexeme and language (`lex_etcbc`, `lang_etcbc`), marked `· bhsa`. Clicking a word opens the inspector with the same essentials, all other features (folded away; without empty values, and without the `g_` features unless asked for), its relations and what it lies in.
270
+
271
+ ## Lexicon
272
+
273
+ A corpus with lexeme nodes (`lex`) that have glosses, such as the BHSA, gets a third view besides *Read* and *Search*: *Lexicon*, after SHEBANQ's *Words* page.
274
+
275
+ - Lexemes per language (Hebrew, Aramaic) and first letter, in Hebrew alphabetical order (sin and shin as one letter), with their vocalised form, transliteration, gloss, part of speech and frequency.
276
+ - *Find* searches all letters at once, by Hebrew (with or without vowels), transliteration or gloss; lexemes can also be limited to a part of speech, and sorted by frequency.
277
+ - A lexeme shows every verse it occurs in, as running text with its words marked (a verse with several occurrences once, with `×2`), how often it occurs per book (choose a book to see only its verses), and links to search for it (`word lex=BR>[ language=Hebrew`) and to download its occurrences as TSV. Clicking a verse reads it; with *Sync passages*, the other panes follow.
278
+
279
+ The features used are, per role, the first one the corpus has: `lex`, `voc_lex_utf8` or `lex_utf8`, `gloss`, `sp`, `language`, `freq_lex` (otherwise the words are counted), `rank_lex` and `nametype` (`cfabric_browser/lexicon.py`).
280
+
281
+ ## Display settings
282
+
283
+ How a corpus is displayed comes from its Text-Fabric app configuration (`<repo>/app/config.yaml`). To adjust it without editing downloaded files, put the settings that differ in `~/.cfabric/display/<org>/<repo>.yaml`, or, for one version only, `<repo>@<version>.yaml`. These files use the same format as the app configuration and are layered over it. For example, `~/.cfabric/display/DT-UCPH/sp@7.2.4.yaml`:
284
+
285
+ ```yaml
286
+ typeDisplay:
287
+ word:
288
+ base: true
289
+ featuresBare: gloss
290
+ phrase:
291
+ label: '{typ} {function}'
292
+ phrase_atom:
293
+ hidden: true
294
+ ```
295
+
296
+ The browser comes with such files of its own, in `cfabric_browser/display_settings/`, for corpora whose app configuration lacks something it needs: for the SP, that words are the units to show, hover over and click (its slots are signs). Your own files in `~/.cfabric/display` are layered over those.
297
+
298
+ ## API
299
+
300
+ All functions of the interface are available as a JSON API; interactive documentation is at `/docs` while the browser runs. Where they overlap, the endpoints mirror the tools of `cfabric-mcp`, so that people and language models use the same operations.
301
+
302
+ | Endpoint | Purpose |
303
+ |---|---|
304
+ | `GET /api/corpora`, `GET /api/corpora/{c}` | Corpora and everything needed to work with one (types, sections, display settings) |
305
+ | `GET /api/corpora/{c}/features[/{f}]` | Features, with values and counts |
306
+ | `GET /api/corpora/{c}/sections?ref=` | The section tree, one level at a time |
307
+ | `GET /api/corpora/{c}/passage?ref=Genesis 1:1` | Render trees of a passage, with its section path and the previous and next passages |
308
+ | `GET /api/corpora/{c}/align?from=bhsa&ref=Genesis 1:1` | The corresponding passage in this corpus; `exact` is false when only the enclosing chapter exists |
309
+ | `GET /api/corpora/{c}/books` | For a corpus of manuscripts (DSS): the biblical books in it, with chapters, verses and scrolls |
310
+ | `GET /api/corpora/{c}/witnesses?ref=Genesis 1` | A chapter or verse in the book view: per verse, the text of each scroll that contains it |
311
+ | `GET /api/agreement?a=bhsa&aref=…&b=sp&bref=…&c=dss&cref=…` | At each place where `a` and `b` differ, which scrolls of `c` (book view) agree with `a`, with `b`, or with neither |
312
+ | `GET /api/compare?a=bhsa&aref=Genesis 1&b=sp&bref=Genesis 1` | Words that differ between two corresponding Hebrew passages, compared on their consonants verse by verse: `matres` (only matres lectionis) or `variant` |
313
+ | `GET /api/searches/{id}/parallel?offset=&limit=&texts=` | A page of results as parallel rows: each result's verse in the searched corpus, highlighted, and in `texts` |
314
+ | `GET /api/corpora/{c}/interlinear?ref=&features=&under=` | A passage word by word: per word its lines in words, the extra features, and its phrase and clause (with function and type); with `under`, another corpus' words aligned under them, with their differences |
315
+ | `GET /api/searches/{id}/kwic?offset=&limit=&left=&right=&sort=&filter=&per=&sample=&seed=&features=` | A page of the results as concordance lines: the hit and its context, sorted (`L1.text`, `hit.lex`, …), filtered by features of the hit (`vs:qal,book:Genesis`), one per verse, or sampled |
316
+ | `GET /api/searches/{id}/kwic/facets?feature=&filter=&per=` | How often each value of a feature of the hit occurs in the filtered results (`book`: in book order) |
317
+ | `GET /api/searches/{id}/collocations?feature=&window=&filter=&per=&min=&top=` | The values of a feature near the hits, with count, corpus frequency and logDice |
318
+ | `GET /api/parallel?lead=&ref=&texts=` | A chapter of `lead` (`Genesis 1`) in the corpora `texts`, as rows of verses with a cell per corpus (the DSS: per scroll), for the parallel interface |
319
+ | `GET /api/corpora/{c}/lexicon` | All lexemes of a corpus with a lexicon (BHSA), in alphabetical order per language; with BDB, `bdbShort`, `bdbOrder`, `bdbLetter`, `bdbRoot` per lexeme |
320
+ | `GET /api/corpora/{c}/lexicon/{n}` | One lexeme, with its number of verses, how often it occurs per book, and its entries in BDB (`bdb`, null when BDB hasn't been added) |
321
+ | `GET /api/corpora/{c}/lexicon/{n}/occurrences?offset=&limit=&book=` | A page of the verses it occurs in, as plain render trees with its words highlighted |
322
+ | `GET /api/corpora/{c}/lexicon/{n}/occurrences.tsv` | Every occurrence: section, word and verse text; `excel=true` for Excel |
323
+ | `GET /api/library`, `POST /api/corpora` | Corpora found on this computer; open one by its id (e.g. `ETCBC/dss`) |
324
+ | `GET /api/downloads[/{org}/{repo}]`, `POST`/`DELETE /api/downloads/{org}/{repo}` | Corpora that can be downloaded, whether they are here, and the progress of a download (`job`: download, unpack, prepare); start or cancel one |
325
+ | `GET /api/translations[/{t}]` | Translations that can be added, whether they are, and the progress of adding one (`job`) |
326
+ | `POST /api/translations/{t}`, `DELETE /api/translations/{t}` | Add a translation (download and build it, in the background), or remove it |
327
+ | `GET /api/proposals`, `GET /api/proposals/events` | Searches proposed by a language model, newest first; server-sent events whenever they change |
328
+ | `POST /api/proposals`, `POST /api/proposals/{id}` | Propose a search; mark one `run` or `dismissed` |
329
+ | `POST /mcp` | The tools for a language model, as an MCP server (Streamable HTTP, stateless); only on 127.0.0.1, not from web pages |
330
+ | `GET /api/dictionaries[/{d}]` | Dictionaries that can be added (BDB), whether they are, and the progress of adding one; one of them with its metadata and abbreviations |
331
+ | `POST /api/dictionaries/{d}`, `DELETE /api/dictionaries/{d}` | Download a dictionary (in the background), or remove it |
332
+ | `GET /api/dictionaries/{d}/entries/{id}?corpus=` | An entry: its text, neighbours and root family, with the lexemes of `corpus` linked to them and its verses as references there |
333
+ | `GET /api/corpora/{c}/nodes/{n}[/info]` | Render tree of a node; all its features, edges and surroundings |
334
+ | `GET /api/corpora/{c}/nodes/{n}/summary` | The essentials of a word, as on the card shown when hovering over it; `bdb`: its entries in BDB, by its lexeme (in the BHSA, also for the DSS) |
335
+ | `POST /api/corpora/{c}/check` | Check a template without searching |
336
+ | `POST /api/corpora/{c}/search` | Start a search (`{"template": …, "limit": …, "timeout": …}`) |
337
+ | `GET /api/searches/{id}[/events]` | Status, or a live event stream of it |
338
+ | `GET /api/searches/{id}/results` | A page of results (optionally with plain renderings) |
339
+ | `GET /api/searches/{id}/results/{i}` | One result in its context, highlighted |
340
+ | `GET /api/searches/{id}/stats/features?position=` | Features with values on one part of the results; which the template mentions, and which it leaves open |
341
+ | `GET /api/searches/{id}/stats/values?position=&feature=` | How often each value occurs there (distinct nodes) |
342
+ | `GET /api/searches/{id}/stats/sections?level=` | Results per book (0), chapter (1), ... in text order |
343
+ | `GET /api/searches/{id}/export.tsv` | All results, one row per result; features in the template become columns (write `sp*` to add one without narrowing the search); `extra=3:lex,gloss` adds columns for the third node; `excel=true` for Excel |
344
+ | `DELETE /api/searches/{id}` | Stop a search |
345
+
346
+ Display options are query parameters: `mode` (`pretty`/`plain`), `fmt` (only `text-orig-full` and, where the corpus has it, `text-orig-plain`; another format gives the default), `full`, `hide_types`, `hidden_types`, `base_types`, `condense_type`, `extra_features`, `lang`.
347
+
348
+ ## How it works
349
+
350
+ - Searches run in worker processes, so the interface stays responsive and searches can run in parallel. Because corpora are memory-mapped, the workers share most of their memory. A search that ignores its time limit or a stop request is ended by restarting its worker.
351
+ - Results stream in while the search runs. Once it has finished, they are put in canonical order.
352
+ - Displays are built by `cfabric_browser.display` (a port of Text-Fabric's displays without HTML) as structured render trees, which the interface draws. The corpus' Text-Fabric app configuration (`app/config.yaml`) is used as it is.
353
+
354
+ ## Development
355
+
356
+ The interface is a Vite + React + TypeScript app in `frontend/`. It is built into `cfabric_browser/static/`, which is not in git; the release workflow builds it before packaging.
357
+
358
+ ```bash
359
+ cd libs/explorer/frontend
360
+ npm install
361
+ npm run build # type-check and build into cfabric_browser/static
362
+ npm run dev # live-reloading interface on :5173, using a running cfabric-browser on :8107
363
+ ```
364
+
365
+ Fonts are bundled from npm (`@fontsource`), so the browser needs no internet. For Hebrew, Ezra SIL or SBL Hebrew are used when installed on the computer, otherwise the bundled Noto Serif Hebrew.
366
+
367
+ Tests: `pytest tests/` in `libs/explorer` (they start real search workers on a small fixture corpus).
368
+
369
+ ### The user guide
370
+
371
+ The guide for users is written in Markdown in `guide/`, one file per chapter (the order is `PAGES` in `frontend/scripts/guide.mjs`). `npm run build` makes it into pages in `cfabric_browser/static/guide/`, which the program serves at `/guide/`, so it works offline; *Guide to …* in the interface menu opens the page for the interface in use (`frontend/src/guide.ts`). `node scripts/guide.mjs --site DIR` also writes the pages for caccht.github.io into `DIR/explorer/`, in the style of that site's own pages. Links between chapters are written to the Markdown files (`words.md#bdb`); `npm test` checks that every link and every interface's page exist. The screenshots in `guide/images/` are made by `npm run screenshots -- http://127.0.0.1:8799` (`frontend/scripts/screenshots.mjs`, with playwright-core and the Chrome installed on the computer) from a running browser on the real corpora, started with a home folder that has only the corpora and BDB, so that they show what users see; the list of shots is `SHOTS` in that script, and `npm test` checks that the guide uses each of them. `npm test` also checks the guide's names of things in the program: every phrase in italics must be a text of the frontend, the guide's own pages or the server's messages (`…` stands for a value, `→` separates a menu from its item), unless it is in `NOT_LABELS` in `frontend/scripts/guide.test.mjs` (other programs' buttons, examples, glosses); so a renamed button fails the test until the guide follows. The plan: `../make_browser_context_fabric/documentation-plan.md` (outside the repository).
372
+
373
+ **Before each desktop release** (a `desktop-v*` tag):
374
+
375
+ 1. **The guide.** For every change users notice, update its chapter in `guide/` (a new button, a changed default, a new corpus or text), and `npm test` (names in the program, links, pictures).
376
+ 2. **The screenshots**, when the interface changed: start the browser on the real corpora with a home folder that holds only the corpora and BDB (a junction or link to `text-fabric-data`, and `.cfabric/dictionaries`), with `--only` for the corpora of `CORPORA` in `packaging/cfabric-browser.py`, then `npm run screenshots -- http://127.0.0.1:<port>`. Look at each picture before committing.
377
+ 3. **The release notes** (`packaging/RELEASE_NOTES.md`): what is new since the last release at the top, the downloads and how to start; the rest belongs in the guide.
378
+ 4. **caccht.github.io:** `node scripts/guide.mjs --site <clone of CACCHT/caccht.github.io>`, a pull request with the changed pages (and new chapters in its `sitemap.xml`), merged before the release, because the release notes link to it.
379
+ 5. **The checks of `browser-desktop.yml`** on all four builds, then the tag.
380
+
381
+
382
+ ### Standalone program
383
+
384
+ `packaging/cfabric-browser.spec` builds a program that runs without a Python installation (with PyInstaller; about 65 MB on Windows). It shows the browser in a window of its own (`--window`), without a console. Started without corpora, for example by double-clicking it, it offers the corpora on this computer, and first offers to download the BHSA, the SP and the DSS when they are missing (`--ask-downloads`). Build it in a separate virtual environment with normal, not editable, installs: PyInstaller does not find editable installs. On Windows, make that environment with a Python from python.org: PyInstaller cannot bundle the Microsoft Store Python.
385
+
386
+ ```bash
387
+ cd libs/explorer
388
+ (cd frontend && npm run build)
389
+ python -m venv build/env
390
+ build/env/Scripts/python -m pip install ../core ".[build]" # Linux/macOS: build/env/bin/python
391
+ build/env/Scripts/pyinstaller packaging/cfabric-browser.spec --noconfirm
392
+ dist/cfabric-browser/cfabric-browser bhsa
393
+ ```
394
+
395
+ Its entry point is `packaging/cfabric-browser.py`, which adds `--window` (`--no-window` overrides it), `--ui parallel` (the parallel interface on a first start), `--ask-downloads` and, for the test version, `--only` for the corpora in its `CORPORA` list (BHSA, SP, DSS and the JPS 1917); empty that list to offer all corpora. As it has no console, it writes its output and errors to `~/.cfabric/logs/cfabric-browser.log`, and on Windows shows a message when it cannot start. If no window toolkit is available (on Linux, pywebview needs GTK or Qt), it opens a web browser instead.
396
+
397
+ The program icons in `packaging/icons/` are drawn from the Context-Fabric mark (`frontend/public/favicon.svg`) by `packaging/make_icons.py` (needs Pillow); run it again when the mark changes.
398
+
399
+ `packaging/smoke-test.sh` starts a built program as a server with a small corpus and checks that the interface is served and that a search runs; it needs only bash and curl. `packaging/translation-test.sh` and `packaging/download-test.sh` start it with an empty home folder and add the JPS 1917 or download the SP (both over the network). The workflow `browser-desktop.yml` builds the program on Windows, macOS (Apple silicon and Intel, as `CACCHT Explorer.app`) and Linux, runs these three tests on each build (on macOS inside the app), runs the Windows build once more on a runner where no Python can be reached, and keeps the builds as artifacts for 14 days. The builds are not signed, so Windows SmartScreen and macOS Gatekeeper warn about them. Like `cfabric_browser/__main__.py` (`python -m cfabric_browser`), it calls `multiprocessing.freeze_support()` so that search workers start correctly in the frozen program.