scriptorium 0.0.2 → 0.6.1

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 (290) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +324 -0
  3. data/README.md +3155 -1
  4. data/assets/.DS_Store +0 -0
  5. data/assets/README.md +44 -0
  6. data/assets/back-icon.png +0 -0
  7. data/assets/icons/facebook.svg +1 -0
  8. data/assets/icons/github.svg +1 -0
  9. data/assets/icons/instagram.svg +1 -0
  10. data/assets/icons/reddit.svg +1 -0
  11. data/assets/icons/ui/.DS_Store +0 -0
  12. data/assets/icons/ui/back.png +0 -0
  13. data/assets/icons/ui/copy.png +0 -0
  14. data/assets/icons/ui/down.png +0 -0
  15. data/assets/icons/ui/end.png +0 -0
  16. data/assets/icons/ui/exit.png +0 -0
  17. data/assets/icons/ui/foo +10 -0
  18. data/assets/icons/ui/home.png +0 -0
  19. data/assets/icons/ui/left.png +0 -0
  20. data/assets/icons/ui/next.png +0 -0
  21. data/assets/icons/ui/right.png +0 -0
  22. data/assets/icons/ui/start.png +0 -0
  23. data/assets/icons/ui/up.png +0 -0
  24. data/assets/icons/x.svg +1 -0
  25. data/assets/icons/youtube.svg +1 -0
  26. data/assets/samples/placeholder.svg +9 -0
  27. data/assets/themes/standard/favicon.svg +6 -0
  28. data/bin/scriptorium +1511 -0
  29. data/doc/README.txt +6 -0
  30. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +95 -0
  31. data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +34 -0
  32. data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +50 -0
  33. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +31 -0
  34. data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +73 -0
  35. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +64 -0
  36. data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +70 -0
  37. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
  38. data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +110 -0
  39. data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +73 -0
  40. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
  41. data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +124 -0
  42. data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +46 -0
  43. data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +97 -0
  44. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
  45. data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +211 -0
  46. data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +141 -0
  47. data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +211 -0
  48. data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +134 -0
  49. data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +41 -0
  50. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +45 -0
  51. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +30 -0
  52. data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +49 -0
  53. data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +46 -0
  54. data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +41 -0
  55. data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +41 -0
  56. data/doc/anti-amnesia/20250807-213025.md +116 -0
  57. data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +256 -0
  58. data/doc/banner_svg_config.md +114 -0
  59. data/doc/contrib.lt3 +8 -0
  60. data/doc/dependencies.md +281 -0
  61. data/doc/hacker.lt3 +5 -0
  62. data/doc/reddit_credentials_template.json +8 -0
  63. data/doc/reddit_integration.md +207 -0
  64. data/doc/user.lt3 +38 -0
  65. data/doc/user_guide_section_1.md +137 -0
  66. data/doc/user_guide_section_10.md +515 -0
  67. data/doc/user_guide_section_11.md +708 -0
  68. data/doc/user_guide_section_2.md +233 -0
  69. data/doc/user_guide_section_3.md +5 -0
  70. data/doc/user_guide_section_4.md +221 -0
  71. data/doc/user_guide_section_5.md +243 -0
  72. data/doc/user_guide_section_6.md +147 -0
  73. data/doc/user_guide_section_7.md +311 -0
  74. data/doc/user_guide_section_8.md +224 -0
  75. data/doc/user_guide_section_9.md +375 -0
  76. data/doc/userdoc-toc.txt +88 -0
  77. data/lib/rouge/lexers/livetext.rb +74 -0
  78. data/lib/scriptorium/api.rb +640 -0
  79. data/lib/scriptorium/banner_svg.rb +742 -0
  80. data/lib/scriptorium/contract.rb +33 -0
  81. data/lib/scriptorium/exceptions.rb +174 -0
  82. data/lib/scriptorium/helpers.rb +475 -0
  83. data/lib/scriptorium/post.rb +195 -0
  84. data/lib/scriptorium/reddit.rb +83 -0
  85. data/lib/scriptorium/repo.rb +624 -0
  86. data/lib/scriptorium/standard_files.rb +515 -0
  87. data/lib/scriptorium/syntax_highlighter.rb +234 -0
  88. data/lib/scriptorium/theme.rb +179 -0
  89. data/lib/scriptorium/version.rb +2 -2
  90. data/lib/scriptorium/view.rb +976 -0
  91. data/lib/scriptorium/widgets/featured_posts.rb +149 -0
  92. data/lib/scriptorium/widgets/links.rb +112 -0
  93. data/lib/scriptorium/widgets/pages.rb +133 -0
  94. data/lib/scriptorium/widgets/widget.rb +133 -0
  95. data/lib/scriptorium.rb +22 -9
  96. data/lib/skeleton.rb +11 -2
  97. data/scriptorium.gemspec +15 -4
  98. data/test/README.md +69 -0
  99. data/test/all +43 -0
  100. data/test/api_demo.rb +99 -0
  101. data/test/assets/imagenotfound.jpg +0 -0
  102. data/test/assets/images/.DS_Store +0 -0
  103. data/test/assets/images/README.md +27 -0
  104. data/test/assets/images/odd_aspect.png +0 -0
  105. data/test/assets/images/perfect.png +0 -0
  106. data/test/assets/images/small.png +0 -0
  107. data/test/assets/images/tall.png +0 -0
  108. data/test/assets/images/very_tall.png +0 -0
  109. data/test/assets/images/very_wide.png +0 -0
  110. data/test/assets/images/wide.png +0 -0
  111. data/test/assets/testbanner.jpg +0 -0
  112. data/test/banner_svg/simple_helpers.rb +13 -0
  113. data/test/banner_svg/unit.rb +768 -0
  114. data/test/ed_test.rb +204 -0
  115. data/test/integration/cursor_banner_combinations.rb +193 -0
  116. data/test/integration/cursor_banner_features.rb +374 -0
  117. data/test/integration/integration_test.rb +326 -0
  118. data/test/livetext_plugin_test.rb +229 -0
  119. data/test/manual/asset_mgmt.rb +67 -0
  120. data/test/manual/banner-tests/config.txt +3 -0
  121. data/test/manual/banner-tests/index.html +45 -0
  122. data/test/manual/banner-tests/test01.html +58 -0
  123. data/test/manual/banner-tests/test02.html +58 -0
  124. data/test/manual/banner-tests/test03.html +58 -0
  125. data/test/manual/banner-tests/test04.html +65 -0
  126. data/test/manual/banner-tests/test05.html +65 -0
  127. data/test/manual/banner-tests/test06.html +65 -0
  128. data/test/manual/banner-tests/test07.html +65 -0
  129. data/test/manual/banner-tests/test08.html +59 -0
  130. data/test/manual/banner-tests/test09.html +59 -0
  131. data/test/manual/banner-tests/test10.html +59 -0
  132. data/test/manual/banner-tests/test11.html +59 -0
  133. data/test/manual/banner-tests/test12.html +59 -0
  134. data/test/manual/banner-tests/test13.html +59 -0
  135. data/test/manual/banner-tests/test14.html +59 -0
  136. data/test/manual/banner-tests/test15.html +58 -0
  137. data/test/manual/banner-tests/test16.html +58 -0
  138. data/test/manual/banner-tests/test17.html +58 -0
  139. data/test/manual/banner-tests/test18.html +68 -0
  140. data/test/manual/banner-tests/test19.html +68 -0
  141. data/test/manual/banner-tests/test20.html +68 -0
  142. data/test/manual/banner-tests/test21.html +68 -0
  143. data/test/manual/banner-tests/test22.html +68 -0
  144. data/test/manual/banner-tests/test23.html +68 -0
  145. data/test/manual/banner-tests/test24.html +68 -0
  146. data/test/manual/banner-tests/test25.html +67 -0
  147. data/test/manual/banner_environment.rb +192 -0
  148. data/test/manual/deploy_symlink_demo.rb +142 -0
  149. data/test/manual/environment.rb +67 -0
  150. data/test/manual/make_banner.rb +153 -0
  151. data/test/manual/sample_banner_config.txt +12 -0
  152. data/test/manual/symlink_demo.rb +117 -0
  153. data/test/manual/test1.rb +47 -0
  154. data/test/manual/test2.rb +12 -0
  155. data/test/manual/test3.rb +38 -0
  156. data/test/manual/test4.rb +40 -0
  157. data/test/manual/test5.rb +24 -0
  158. data/test/manual/test6.rb +73 -0
  159. data/test/manual/test_banner_combinations.rb +120 -0
  160. data/test/manual/test_banner_features.rb +306 -0
  161. data/test/manual/test_banner_from_file.rb +150 -0
  162. data/test/manual/test_banner_in_header.rb +35 -0
  163. data/test/manual/test_code_highlighting.rb +68 -0
  164. data/test/manual/test_complex_header.rb +74 -0
  165. data/test/manual/test_empty_header.rb +32 -0
  166. data/test/manual/test_radial_custom.rb +58 -0
  167. data/test/manual/test_radial_large_radius.rb +52 -0
  168. data/test/manual/test_svg_debug.rb +47 -0
  169. data/test/manual/test_syntax_highlighting.rb +147 -0
  170. data/test/pages-demo/config/currentview.txt +1 -0
  171. data/test/pages-demo/views/demo/config/bootstrap_css.txt +5 -0
  172. data/test/pages-demo/views/demo/config/bootstrap_js.txt +4 -0
  173. data/test/pages-demo/views/demo/config/common.js +57 -0
  174. data/test/pages-demo/views/demo/config/footer.txt +1 -0
  175. data/test/pages-demo/views/demo/config/global-head.txt +8 -0
  176. data/test/pages-demo/views/demo/config/header.txt +1 -0
  177. data/test/pages-demo/views/demo/config/layout.txt +1 -0
  178. data/test/pages-demo/views/demo/config/left.txt +1 -0
  179. data/test/pages-demo/views/demo/config/main.txt +1 -0
  180. data/test/pages-demo/views/demo/config/right.txt +1 -0
  181. data/test/pages-demo/views/demo/config.txt +3 -0
  182. data/test/pages-demo/views/demo/output/panes/footer.html +1 -0
  183. data/test/pages-demo/views/demo/output/panes/header.html +1 -0
  184. data/test/pages-demo/views/demo/output/panes/left.html +1 -0
  185. data/test/pages-demo/views/demo/output/panes/main.html +1 -0
  186. data/test/pages-demo/views/demo/output/panes/right.html +1 -0
  187. data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
  188. data/test/rubytext/rubytext_demo_test.rb +42 -0
  189. data/test/rubytext/rubytext_testing_guide.md +277 -0
  190. data/test/run_automated_tests.rb +45 -0
  191. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +5 -0
  192. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +4 -0
  193. data/test/scriptorium-TEST-1754622690-146/config/common.js +57 -0
  194. data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +1 -0
  195. data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +9 -0
  196. data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +1 -0
  197. data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +4 -0
  198. data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +3 -0
  199. data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +8 -0
  200. data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +6 -0
  201. data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +1 -0
  202. data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +1 -0
  203. data/test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 +12 -0
  204. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt +2 -0
  205. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt +4 -0
  206. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt +3 -0
  207. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt +5 -0
  208. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt +3 -0
  209. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +1 -0
  210. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/layout.txt +5 -0
  211. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +1 -0
  212. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +14 -0
  213. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +13 -0
  214. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +1 -0
  215. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +5 -0
  216. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +4 -0
  217. data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +57 -0
  218. data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +5 -0
  219. data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +2 -0
  220. data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +9 -0
  221. data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +4 -0
  222. data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +5 -0
  223. data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +3 -0
  224. data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +5 -0
  225. data/test/scriptorium-TEST-1754622690-146/views/sample/config/reddit.txt +10 -0
  226. data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +3 -0
  227. data/test/scriptorium-TEST-1754622690-146/views/sample/config/social.txt +7 -0
  228. data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +7 -0
  229. data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +3 -0
  230. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +3 -0
  231. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +3 -0
  232. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +3 -0
  233. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +3 -0
  234. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +3 -0
  235. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +1 -0
  236. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +1 -0
  237. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +1 -0
  238. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +1 -0
  239. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +1 -0
  240. data/test/staging/.DS_Store +0 -0
  241. data/test/syntax_highlighting_test.lt3 +124 -0
  242. data/test/test_helpers.rb +230 -0
  243. data/test/tui_editor_integration_test.rb +296 -0
  244. data/test/tui_integration_test.rb +637 -0
  245. data/test/unit/api.rb +1056 -0
  246. data/test/unit/asset_management.rb +245 -0
  247. data/test/unit/clipboard_test.rb +60 -0
  248. data/test/unit/contract_test.rb +91 -0
  249. data/test/unit/core.rb +857 -0
  250. data/test/unit/deploy_test.rb +187 -0
  251. data/test/unit/gem_asset_management.rb +189 -0
  252. data/test/unit/livetext_basic.rb +69 -0
  253. data/test/unit/livetext_compatibility.rb +89 -0
  254. data/test/unit/post.rb +244 -0
  255. data/test/unit/read_commented_file_test.rb +276 -0
  256. data/test/unit/reddit_test.rb +235 -0
  257. data/test/unit/repo.rb +548 -0
  258. data/test/unit/social_test.rb +369 -0
  259. data/test/unit/symlink_test.rb +213 -0
  260. data/test/unit/view.rb +431 -0
  261. data/test/unit/widgets.rb +669 -0
  262. data/test/wizard_test.rb +123 -0
  263. data/ui/README.md +67 -0
  264. data/ui/common/lib/ui_common.rb +8 -0
  265. data/ui/rubytext/README.md +191 -0
  266. data/ui/rubytext/bin/scriptorium-rubytext +402 -0
  267. data/ui/rubytext/lib/rubytext_ui.rb +300 -0
  268. data/ui/tui/bin/scriptorium +1420 -0
  269. data/ui/tui/test/tui_test.rb +23 -0
  270. data/ui/web/app/app.rb +1378 -0
  271. data/ui/web/app/error_helpers.rb +150 -0
  272. data/ui/web/app/views/advanced_config.erb +190 -0
  273. data/ui/web/app/views/asset_management.erb +589 -0
  274. data/ui/web/app/views/banner_config.erb +200 -0
  275. data/ui/web/app/views/configure_view.erb +401 -0
  276. data/ui/web/app/views/dashboard.erb +162 -0
  277. data/ui/web/app/views/deploy_config.erb +146 -0
  278. data/ui/web/app/views/edit_pages.erb +195 -0
  279. data/ui/web/app/views/edit_post.erb +54 -0
  280. data/ui/web/app/views/error_page.erb +29 -0
  281. data/ui/web/app/views/header_config.erb +155 -0
  282. data/ui/web/app/views/layout_config.erb +147 -0
  283. data/ui/web/app/views/navbar_config.erb +411 -0
  284. data/ui/web/app/views/view_dashboard.erb +138 -0
  285. data/ui/web/bin/scriptorium-web +153 -0
  286. data/ui/web/test/web_basic_test.rb +38 -0
  287. data/ui/web/test_navbar.txt +7 -0
  288. data/ui/web/tmp/web_server.log +5 -0
  289. data/ui/web/tmp/web_server.pid +1 -0
  290. metadata +360 -5
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'open3'
4
+ require 'timeout'
5
+ require 'minitest/autorun'
6
+ require_relative '../lib/scriptorium'
7
+
8
+ class WizardTest < Minitest::Test
9
+ def setup
10
+ @test_repo_path = "scriptorium-TEST"
11
+ cleanup_test_repo
12
+ end
13
+
14
+ def teardown
15
+ cleanup_test_repo
16
+ end
17
+
18
+ def test_001_wizard_first_view_flow
19
+ # Test the wizard flow for creating the first view
20
+ # This should create a new repository and set up the first view
21
+
22
+ # Ensure clean start
23
+ cleanup_test_repo
24
+
25
+ # Run the wizard
26
+ result = system("echo -e 'y\n4\nn' | ruby bin/scriptorium")
27
+ assert result, "Wizard should complete successfully"
28
+
29
+ # Verify repository was created
30
+ assert Dir.exist?(TEST_REPO_PATH), "Repository should be created"
31
+
32
+ # Verify sample view was created
33
+ sample_view_path = File.join(TEST_REPO_PATH, "views", "sample")
34
+ assert Dir.exist?(sample_view_path), "Sample view should be created"
35
+
36
+ # Verify config files were created
37
+ config_path = File.join(TEST_REPO_PATH, "config")
38
+ assert Dir.exist?(config_path), "Config directory should be created"
39
+
40
+ # Verify current view is set
41
+ current_view_file = File.join(config_path, "currentview.txt")
42
+ assert File.exist?(current_view_file), "Current view file should be created"
43
+ assert_equal "sample", File.read(current_view_file).strip, "Current view should be 'sample'"
44
+ end
45
+
46
+ def test_002_wizard_method_exists
47
+ # Test that the wizard method exists and can be called
48
+ # This is a basic smoke test to ensure the wizard is available
49
+
50
+ # Load the scriptorium binary to access the wizard method
51
+ load 'bin/scriptorium'
52
+
53
+ # The wizard method should be available in the TUI class
54
+ assert defined?(TUI), "TUI class should be defined"
55
+ assert TUI.instance_methods.include?(:wizard), "TUI should have wizard method"
56
+ end
57
+
58
+ def test_003_wizard_with_new_repo
59
+ # Test wizard behavior when creating a completely new repository
60
+ # This tests the full wizard flow including repository creation
61
+
62
+ # Ensure clean start
63
+ cleanup_test_repo
64
+
65
+ # Create a new API instance to simulate fresh start
66
+ api = Scriptorium::API.new(testmode: true)
67
+
68
+ # Verify no repository exists initially
69
+ refute Dir.exist?(TEST_REPO_PATH), "Repository should not exist initially"
70
+
71
+ # Run wizard with new repo creation
72
+ result = system("echo -e 'y\n4\ny\ntestview\nTest View\nTest Subtitle\nn\nn\nn\nn\nn' | ruby bin/scriptorium")
73
+ assert result, "Wizard should complete successfully with new repo"
74
+
75
+ # Verify repository was created
76
+ assert Dir.exist?(TEST_REPO_PATH), "Repository should be created"
77
+
78
+ # Verify test view was created
79
+ test_view_path = File.join(TEST_REPO_PATH, "views", "testview")
80
+ assert Dir.exist?(test_view_path), "Test view should be created"
81
+
82
+ # Verify view config
83
+ view_config = File.join(test_view_path, "config.txt")
84
+ assert File.exist?(view_config), "View config should be created"
85
+ config_content = File.read(view_config)
86
+ assert_includes config_content, "title Test View", "View title should be set"
87
+ assert_includes config_content, "subtitle Test Subtitle", "View subtitle should be set"
88
+ end
89
+
90
+ def await_output(stdout, expected_str, timeout_secs = 10)
91
+ buffer = ""
92
+ start_time = Time.now
93
+
94
+ loop do
95
+ if Time.now - start_time > timeout_secs
96
+ raise "Timeout waiting for '#{expected_str}'. Buffer: #{buffer.inspect}"
97
+ end
98
+
99
+ begin
100
+ chunk = stdout.read_nonblock(1000)
101
+ buffer += chunk
102
+ puts "Buffer: #{buffer.inspect}"
103
+
104
+ if buffer.include?(expected_str)
105
+ puts "Found expected string: #{expected_str.inspect}"
106
+ return buffer
107
+ end
108
+ rescue IO::EAGAINWaitReadable, IO::EWOULDBLOCKWaitReadable
109
+ sleep 0.1
110
+ rescue EOFError
111
+ raise "EOF reached while waiting for '#{expected_str}'. Buffer: #{buffer.inspect}"
112
+ end
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def cleanup_test_repo
119
+ if Dir.exist?(@test_repo_path)
120
+ FileUtils.rm_rf(@test_repo_path)
121
+ end
122
+ end
123
+ end
data/ui/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Scriptorium UI Directory
2
+
3
+ This directory contains all user interface implementations for Scriptorium.
4
+
5
+ ## Structure
6
+
7
+ ```
8
+ ui/
9
+ ├── tui/ # Terminal User Interface
10
+ │ ├── bin/scriptorium # TUI executable
11
+ │ ├── lib/ # TUI-specific code
12
+ │ └── test/ # TUI-specific tests
13
+ ├── web/ # Web User Interface (future)
14
+ │ ├── app/ # Web app code
15
+ │ ├── public/ # Static assets
16
+ │ └── test/ # Web-specific tests
17
+ └── common/ # Shared UI utilities
18
+ ├── lib/ # Common UI libraries
19
+ └── test/ # Common UI tests
20
+ ```
21
+
22
+ ## TUI (Terminal User Interface)
23
+
24
+ The current TUI implementation provides a command-line interface for Scriptorium.
25
+
26
+ - **Location**: `ui/tui/bin/scriptorium`
27
+ - **Features**: Interactive commands, view management, post creation, deployment
28
+ - **Dependencies**: Readline (optional), core Scriptorium library
29
+
30
+ ## Web UI (Future)
31
+
32
+ Planned web interface for Scriptorium.
33
+
34
+ - **Status**: Not yet implemented
35
+ - **Planned Features**: Web-based post editing, view management, real-time preview
36
+ - **Technology**: To be determined (Sinatra, Rails, or other framework)
37
+
38
+ ## Common Utilities
39
+
40
+ Shared code that can be used by multiple UI implementations.
41
+
42
+ - **Location**: `ui/common/lib/`
43
+ - **Purpose**: API wrappers, validation, common UI patterns
44
+ - **Usage**: Imported by TUI, Web UI, and future interfaces
45
+
46
+ ## Development
47
+
48
+ ### Adding a new UI
49
+
50
+ 1. Create a new directory under `ui/`
51
+ 2. Follow the established structure (bin/, lib/, test/)
52
+ 3. Import common utilities from `ui/common/lib/`
53
+ 4. Update the gemspec to include the new UI files
54
+
55
+ ### Testing
56
+
57
+ Each UI has its own test directory for UI-specific tests. Common functionality is tested in `ui/common/test/`.
58
+
59
+ ### Dependencies
60
+
61
+ - **TUI**: Minimal dependencies, uses core Scriptorium library
62
+ - **Web UI**: Will have additional web framework dependencies
63
+ - **Common**: No additional dependencies beyond core Scriptorium
64
+
65
+ ## Migration Notes
66
+
67
+ The TUI was moved from `bin/scriptorium` to `ui/tui/bin/scriptorium` to better organize the codebase and prepare for multiple UI implementations.
@@ -0,0 +1,8 @@
1
+ # Common UI utilities that can be shared between different interfaces
2
+ module Scriptorium
3
+ module UI
4
+ module Common
5
+ # Shared utilities for all UI implementations
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,191 @@
1
+ # Scriptorium RubyText UI
2
+
3
+ ## Overview
4
+
5
+ The RubyText UI brings back the sophisticated interactive interface from Runeblog, providing a middle ground between the simple TUI and the web app. It offers:
6
+
7
+ - **Rich interactive menus** - File selection, configuration, widget management
8
+ - **Context-aware interface** - Shows current view, status, and available actions
9
+ - **Direct file editing** - Integrated editor support with syntax highlighting
10
+ - **Visual feedback** - Colors, bold text, clear screens, progress indicators
11
+ - **Widget management** - Manage pages, links, navbar, and other widgets
12
+ - **Real-time preview** - Live preview of changes as you make them
13
+
14
+ ## Architecture
15
+
16
+ ### Core Components
17
+
18
+ 1. **Main Interface** (`ui/rubytext/bin/scriptorium-rubytext`)
19
+ - Entry point with auto-discovery and setup
20
+ - Context display and command processing
21
+ - Error handling and recovery
22
+
23
+ 2. **Menu System** (`ui/rubytext/lib/menus.rb`)
24
+ - Interactive menus for file selection
25
+ - Configuration management
26
+ - Widget management interfaces
27
+
28
+ 3. **REPL System** (`ui/rubytext/lib/repl.rb`)
29
+ - Command processing and execution
30
+ - Context management
31
+ - Help system and documentation
32
+
33
+ 4. **Editor Integration** (`ui/rubytext/lib/editor.rb`)
34
+ - Direct file editing with syntax highlighting
35
+ - Editor selection and configuration
36
+ - File validation and error handling
37
+
38
+ 5. **Widget Management** (`ui/rubytext/lib/widgets.rb`)
39
+ - Page management
40
+ - Link management
41
+ - Navbar configuration
42
+ - Asset management
43
+
44
+ ## Key Features
45
+
46
+ ### Interactive Menus
47
+
48
+ ```ruby
49
+ # File selection menu
50
+ files = Dir.glob("*.rb")
51
+ num, selected = STDSCR.menu(title: "Select file:", items: files)
52
+ edit_file(selected) if selected
53
+
54
+ # Configuration menu
55
+ config_items = {
56
+ "General Settings" => "config/general.txt",
57
+ "View Settings" => "config/view.txt",
58
+ "Theme Settings" => "config/theme.txt"
59
+ }
60
+ num, target = STDSCR.menu(title: "Edit configuration:", items: config_items)
61
+ edit_file(target) if target
62
+ ```
63
+
64
+ ### Context-Aware Interface
65
+
66
+ ```ruby
67
+ # Shows current context in prompt
68
+ def display_context
69
+ view_name = @repo.current_view&.name || "No view"
70
+ print fx("[#{view_name}] ", Red, :bold)
71
+ end
72
+ ```
73
+
74
+ ### Direct File Editing
75
+
76
+ ```ruby
77
+ # Integrated editor with syntax highlighting
78
+ def edit_file(file, editor: nil)
79
+ editor ||= @repo.config.editor || "vim"
80
+ system("#{editor} #{file}")
81
+ refresh_screen
82
+ end
83
+ ```
84
+
85
+ ### Widget Management
86
+
87
+ ```ruby
88
+ # Manage pages widget
89
+ def manage_pages
90
+ pages_dir = @view.dir/"pages"
91
+ files = Dir.glob("#{pages_dir}/*.html")
92
+
93
+ menu_items = files.map { |f| File.basename(f) } + ["[New Page]"]
94
+ num, selected = STDSCR.menu(title: "Manage Pages:", items: menu_items)
95
+
96
+ case selected
97
+ when "[New Page]"
98
+ create_new_page
99
+ else
100
+ edit_page(selected)
101
+ end
102
+ end
103
+ ```
104
+
105
+ ## Implementation Plan
106
+
107
+ ### Phase 1: Core Interface
108
+ - [ ] Basic RubyText integration
109
+ - [ ] Context display and command processing
110
+ - [ ] Simple menu system
111
+ - [ ] File editing integration
112
+
113
+ ### Phase 2: Rich Menus
114
+ - [ ] Interactive file selection
115
+ - [ ] Configuration management
116
+ - [ ] Widget management interfaces
117
+ - [ ] Help system
118
+
119
+ ### Phase 3: Advanced Features
120
+ - [ ] Real-time preview
121
+ - [ ] Asset management
122
+ - [ ] Deployment integration
123
+ - [ ] Performance optimization
124
+
125
+ ## Usage Examples
126
+
127
+ ### Basic Usage
128
+
129
+ ```bash
130
+ # Start RubyText UI
131
+ scriptorium-rubytext
132
+
133
+ # Context-aware prompt
134
+ [sample] help # Show help
135
+ [sample] new post # Create new post
136
+ [sample] list posts # List posts in current view
137
+ [sample] config # Edit configuration
138
+ [sample] manage pages # Manage pages widget
139
+ ```
140
+
141
+ ### Interactive Menus
142
+
143
+ ```
144
+ Select file:
145
+ 1. config/general.txt
146
+ 2. config/view.txt
147
+ 3. config/theme.txt
148
+ 4. [Cancel]
149
+
150
+ Enter choice (1-4): 2
151
+ ```
152
+
153
+ ### Widget Management
154
+
155
+ ```
156
+ Manage Pages:
157
+ 1. about.html
158
+ 2. contact.html
159
+ 3. [New Page]
160
+ 4. [Cancel]
161
+
162
+ Enter choice (1-4): 3
163
+ ```
164
+
165
+ ## Benefits Over Current TUI
166
+
167
+ 1. **More Interactive** - Rich menus vs. command-line only
168
+ 2. **Better Visual Feedback** - Colors, bold text, clear screens
169
+ 3. **Direct File Editing** - Integrated editor support
170
+ 4. **Widget Management** - Visual management of pages, links, etc.
171
+ 5. **Context Awareness** - Always shows current view and status
172
+ 6. **Error Recovery** - Better error handling and recovery
173
+
174
+ ## Benefits Over Web App
175
+
176
+ 1. **Lighter Weight** - No web server, no browser needed
177
+ 2. **Faster** - Direct file system access
178
+ 3. **SSH Friendly** - Works over SSH connections
179
+ 4. **Offline** - No internet connection required
180
+ 5. **Familiar** - Terminal-based interface for command-line users
181
+
182
+ ## Dependencies
183
+
184
+ - `rubytext` gem - Curses-based UI framework
185
+ - `scriptorium` core - Core Scriptorium functionality
186
+ - `livetext` - Content processing and generation
187
+
188
+ ## Testing
189
+
190
+ See `test/rubytext/` for comprehensive testing strategy and implementation.
191
+