scriptorium 0.6.1 → 0.7.2

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 (358) hide show
  1. checksums.yaml +4 -4
  2. data/assets/icons/social/reddit.png +0 -0
  3. data/assets/icons/social/x-logo.png +0 -0
  4. data/assets/imagenotfound.jpg +0 -0
  5. data/bin/sblog +84 -5
  6. data/bin/scriptorium +1 -0
  7. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +0 -1
  8. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +0 -29
  9. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +0 -19
  10. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +1 -1
  11. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +1 -1
  12. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +1 -1
  13. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +0 -10
  14. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +1 -4
  15. data/doc/anti-amnesia/20250901-211714-codemirror-integration-and-web-tests.md +172 -0
  16. data/doc/anti-amnesia/20250902-002402-backup-restore-system.md +126 -0
  17. data/doc/anti-amnesia/20250907-203339-backup-metadata-implementation.md +66 -0
  18. data/doc/imported/0001-elixir-conf-2014/metadata.txt +7 -0
  19. data/doc/imported/0001-elixir-conf-2014/post.html +37 -0
  20. data/doc/imported/0001-elixir-conf-2014/source.lt3 +22 -0
  21. data/doc/imported/0002-programmers-and-word-processing/metadata.txt +7 -0
  22. data/doc/imported/0002-programmers-and-word-processing/post.html +192 -0
  23. data/doc/imported/0002-programmers-and-word-processing/source.lt3 +146 -0
  24. data/doc/imported/0003-how-to-turn-your-brain-sideways/metadata.txt +7 -0
  25. data/doc/imported/0003-how-to-turn-your-brain-sideways/post.html +60 -0
  26. data/doc/imported/0003-how-to-turn-your-brain-sideways/source.lt3 +40 -0
  27. data/doc/imported/0004-upcoming-lone-star-ruby-conference/metadata.txt +7 -0
  28. data/doc/imported/0004-upcoming-lone-star-ruby-conference/post.html +42 -0
  29. data/doc/imported/0004-upcoming-lone-star-ruby-conference/source.lt3 +24 -0
  30. data/doc/imported/0005-elixir-conf-2015-announced/metadata.txt +7 -0
  31. data/doc/imported/0005-elixir-conf-2015-announced/post.html +30 -0
  32. data/doc/imported/0005-elixir-conf-2015-announced/source.lt3 +16 -0
  33. data/doc/imported/0006-ruby-for-dinosaurs/metadata.txt +7 -0
  34. data/doc/imported/0006-ruby-for-dinosaurs/post.html +43 -0
  35. data/doc/imported/0006-ruby-for-dinosaurs/source.lt3 +27 -0
  36. data/doc/imported/0007-phoenix-isnt-rails/metadata.txt +7 -0
  37. data/doc/imported/0007-phoenix-isnt-rails/post.html +116 -0
  38. data/doc/imported/0007-phoenix-isnt-rails/source.lt3 +87 -0
  39. data/doc/imported/0008-concerning-the-term-monkeypatching/metadata.txt +7 -0
  40. data/doc/imported/0008-concerning-the-term-monkeypatching/post.html +129 -0
  41. data/doc/imported/0008-concerning-the-term-monkeypatching/source.lt3 +92 -0
  42. data/doc/imported/0009-announcement-coming-soon/metadata.txt +7 -0
  43. data/doc/imported/0009-announcement-coming-soon/post.html +33 -0
  44. data/doc/imported/0009-announcement-coming-soon/source.lt3 +19 -0
  45. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/metadata.txt +7 -0
  46. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/post.html +175 -0
  47. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/source.lt3 +139 -0
  48. data/doc/imported/0011-computer-science-as-a-lost-art/metadata.txt +7 -0
  49. data/doc/imported/0011-computer-science-as-a-lost-art/post.html +139 -0
  50. data/doc/imported/0011-computer-science-as-a-lost-art/source.lt3 +104 -0
  51. data/doc/imported/0012-ruby-day-in-turin-italy/metadata.txt +7 -0
  52. data/doc/imported/0012-ruby-day-in-turin-italy/post.html +42 -0
  53. data/doc/imported/0012-ruby-day-in-turin-italy/source.lt3 +24 -0
  54. data/doc/imported/0013-rubyday-was-a-success/metadata.txt +7 -0
  55. data/doc/imported/0013-rubyday-was-a-success/post.html +44 -0
  56. data/doc/imported/0013-rubyday-was-a-success/source.lt3 +27 -0
  57. data/doc/imported/0014-working-on-the-blogging-software/metadata.txt +7 -0
  58. data/doc/imported/0014-working-on-the-blogging-software/post.html +63 -0
  59. data/doc/imported/0014-working-on-the-blogging-software/source.lt3 +41 -0
  60. data/doc/imported/0015-ok-its-not-really-a-lost-art/metadata.txt +7 -0
  61. data/doc/imported/0015-ok-its-not-really-a-lost-art/post.html +172 -0
  62. data/doc/imported/0015-ok-its-not-really-a-lost-art/source.lt3 +134 -0
  63. data/doc/imported/0016-an-in-operator-for-ruby/metadata.txt +7 -0
  64. data/doc/imported/0016-an-in-operator-for-ruby/post.html +155 -0
  65. data/doc/imported/0016-an-in-operator-for-ruby/source.lt3 +106 -0
  66. data/doc/imported/0017-the-forgotten-mathematician/metadata.txt +7 -0
  67. data/doc/imported/0017-the-forgotten-mathematician/post.html +161 -0
  68. data/doc/imported/0017-the-forgotten-mathematician/source.lt3 +119 -0
  69. data/doc/imported/0018-ruby-puns/metadata.txt +7 -0
  70. data/doc/imported/0018-ruby-puns/post.html +46 -0
  71. data/doc/imported/0018-ruby-puns/source.lt3 +28 -0
  72. data/doc/imported/0019-custom-exceptions-via-metaprogramming/metadata.txt +7 -0
  73. data/doc/imported/0019-custom-exceptions-via-metaprogramming/post.html +138 -0
  74. data/doc/imported/0019-custom-exceptions-via-metaprogramming/source.lt3 +101 -0
  75. data/doc/imported/0020-fffff/metadata.txt +7 -0
  76. data/doc/imported/0020-fffff/post.html +24 -0
  77. data/doc/imported/0020-fffff/source.lt3 +12 -0
  78. data/doc/imported/0021-trying-ror-yet-again/metadata.txt +7 -0
  79. data/doc/imported/0021-trying-ror-yet-again/post.html +26 -0
  80. data/doc/imported/0021-trying-ror-yet-again/source.lt3 +12 -0
  81. data/doc/imported/0023-doctor-sleep/metadata.txt +7 -0
  82. data/doc/imported/0023-doctor-sleep/post.html +63 -0
  83. data/doc/imported/0023-doctor-sleep/source.lt3 +44 -0
  84. data/doc/imported/0024-just-a-test/metadata.txt +7 -0
  85. data/doc/imported/0024-just-a-test/post.html +24 -0
  86. data/doc/imported/0024-just-a-test/source.lt3 +12 -0
  87. data/doc/imported/import_summary.txt +98 -0
  88. data/doc/livetext-informal-spec.txt +65 -0
  89. data/doc/myuserdoc/ch-0.lt3 +31 -0
  90. data/doc/myuserdoc/ch-1.lt3 +37 -0
  91. data/doc/myuserdoc/ch-10.lt3 +22 -0
  92. data/doc/myuserdoc/ch-2.lt3 +37 -0
  93. data/doc/myuserdoc/ch-3.lt3 +19 -0
  94. data/doc/myuserdoc/ch-4.lt3 +43 -0
  95. data/doc/myuserdoc/ch-5.lt3 +22 -0
  96. data/doc/myuserdoc/ch-6.lt3 +19 -0
  97. data/doc/myuserdoc/ch-7.lt3 +16 -0
  98. data/doc/myuserdoc/ch-8.lt3 +13 -0
  99. data/doc/myuserdoc/ch-9.lt3 +19 -0
  100. data/doc/myuserdoc/tweak.rb +18 -0
  101. data/doc/{userdoc-toc.txt → myuserdoc/userdoc-toc.txt} +27 -27
  102. data/doc/old-posts/0001-elixir-conf-2014.lt3 +24 -0
  103. data/doc/old-posts/0002-programmers-and-word-processing.lt3 +150 -0
  104. data/doc/old-posts/0003-how-to-turn-your-brain-sideways.lt3 +43 -0
  105. data/doc/old-posts/0004-upcoming-lone-star-ruby-conference.lt3 +26 -0
  106. data/doc/old-posts/0005-elixir-conf-2015-announced.lt3 +17 -0
  107. data/doc/old-posts/0006-ruby-for-dinosaurs.lt3 +30 -0
  108. data/doc/old-posts/0007-phoenix-isnt-rails.lt3 +90 -0
  109. data/doc/old-posts/0008-concerning-the-term-monkeypatching.lt3 +105 -0
  110. data/doc/old-posts/0009-announcement-coming-soon.lt3 +20 -0
  111. data/doc/old-posts/0010-immutable-data-ditching-the-wax-tablet.lt3 +142 -0
  112. data/doc/old-posts/0011-computer-science-as-a-lost-art.lt3 +117 -0
  113. data/doc/old-posts/0012-ruby-day-in-turin-italy.lt3 +26 -0
  114. data/doc/old-posts/0013-rubyday-was-a-success.lt3 +28 -0
  115. data/doc/old-posts/0014-working-on-the-blogging-software.lt3 +42 -0
  116. data/doc/old-posts/0015-ok-its-not-really-a-lost-art.lt3 +137 -0
  117. data/doc/old-posts/0016-an-in-operator-for-ruby.lt3 +142 -0
  118. data/doc/old-posts/0017-the-forgotten-mathematician.lt3 +129 -0
  119. data/doc/old-posts/0018-ruby-puns.lt3 +31 -0
  120. data/doc/old-posts/0019-custom-exceptions-via-metaprogramming.lt3 +116 -0
  121. data/doc/old-posts/0021-trying-ror-yet-again.lt3 +35 -0
  122. data/doc/old-posts/0023-doctor-sleep.lt3 +43 -0
  123. data/doc/old-posts/0024-just-a-test.lt3 +12 -0
  124. data/doc/old-posts/0025-trying-another-post.lt3 +12 -0
  125. data/doc/old-repo +1 -0
  126. data/doc/reddit_integration.md +2 -2
  127. data/doc/user.lt3 +0 -3
  128. data/lib/scriptorium/api.rb +1811 -78
  129. data/lib/scriptorium/banner_svg.rb +55 -68
  130. data/lib/scriptorium/contract.rb +3 -2
  131. data/lib/scriptorium/exceptions.rb +133 -102
  132. data/lib/scriptorium/helpers.rb +282 -82
  133. data/lib/scriptorium/post.rb +81 -17
  134. data/lib/scriptorium/reddit.rb +1 -1
  135. data/lib/scriptorium/repo.rb +478 -164
  136. data/lib/scriptorium/standard_files.rb +30 -396
  137. data/lib/scriptorium/support/common_js/clipboard.js +35 -0
  138. data/lib/scriptorium/support/common_js/content-loader.js +187 -0
  139. data/lib/scriptorium/support/common_js/navigation.js +52 -0
  140. data/lib/scriptorium/support/common_js/syntax-highlighting.js +27 -0
  141. data/lib/scriptorium/support/config/reddit_template.txt +17 -0
  142. data/{test/scriptorium-TEST-1754622690-146/views/sample → lib/scriptorium/support}/config/social.txt +1 -0
  143. data/lib/scriptorium/support/highlight/css.txt +2 -0
  144. data/lib/scriptorium/support/highlight/custom.css +119 -0
  145. data/lib/scriptorium/support/highlight/js.txt +1 -0
  146. data/lib/scriptorium/support/post_index/config.txt +15 -0
  147. data/lib/scriptorium/support/post_index/style.css +55 -0
  148. data/lib/scriptorium/support/templates/index_entry.lt3 +16 -0
  149. data/{test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 → lib/scriptorium/support/templates/initial_post.lt3} +5 -5
  150. data/lib/scriptorium/support/templates/post.lt3 +104 -0
  151. data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt → lib/scriptorium/support/theme/header.lt3} +1 -1
  152. data/lib/scriptorium/theme.rb +83 -70
  153. data/lib/scriptorium/version.rb +2 -2
  154. data/lib/scriptorium/view.rb +194 -149
  155. data/lib/scriptorium.rb +24 -1
  156. data/lib/skeleton.rb +4 -1
  157. data/scriptorium.gemspec +2 -1
  158. data/test/WEB_INTEGRATION_README.md +196 -0
  159. data/test/all +40 -0
  160. data/test/banner_svg/unit.rb +267 -35
  161. data/test/config/deployment.txt +5 -0
  162. data/test/integration/integration_test.rb +7 -7
  163. data/test/integration/preview_flow_test.rb +94 -0
  164. data/test/livetext_plugin_test.rb +453 -182
  165. data/test/manual/banner-tests/test01.html +82 -18
  166. data/test/manual/banner-tests/test02.html +82 -18
  167. data/test/manual/banner-tests/test03.html +82 -18
  168. data/test/manual/banner-tests/test04.html +89 -25
  169. data/test/manual/banner-tests/test05.html +89 -25
  170. data/test/manual/banner-tests/test06.html +89 -25
  171. data/test/manual/banner-tests/test07.html +89 -25
  172. data/test/manual/banner-tests/test08.html +82 -18
  173. data/test/manual/banner-tests/test09.html +82 -18
  174. data/test/manual/banner-tests/test10.html +82 -18
  175. data/test/manual/banner-tests/test11.html +82 -18
  176. data/test/manual/banner-tests/test12.html +82 -18
  177. data/test/manual/banner-tests/test13.html +82 -18
  178. data/test/manual/banner-tests/test14.html +82 -18
  179. data/test/manual/banner-tests/test15.html +82 -18
  180. data/test/manual/banner-tests/test16.html +82 -18
  181. data/test/manual/banner-tests/test17.html +82 -18
  182. data/test/manual/banner-tests/test18.html +90 -26
  183. data/test/manual/banner-tests/test19.html +90 -26
  184. data/test/manual/banner-tests/test20.html +90 -26
  185. data/test/manual/banner-tests/test21.html +90 -26
  186. data/test/manual/banner-tests/test22.html +90 -26
  187. data/test/manual/banner-tests/test23.html +90 -26
  188. data/test/manual/banner-tests/test24.html +90 -26
  189. data/test/manual/banner-tests/test25.html +89 -25
  190. data/test/manual/banner_environment.rb +15 -2
  191. data/test/manual/codemirror_demo.html +773 -0
  192. data/test/manual/create_posts_for_web.rb +114 -0
  193. data/test/manual/preview_manual_test.rb +129 -0
  194. data/test/manual/test_banner_features.rb +14 -14
  195. data/test/manual/test_banner_integration.rb +115 -0
  196. data/test/manual/test_banner_radial.rb +87 -0
  197. data/test/manual/test_syntax_highlighting.rb +60 -40
  198. data/test/support/preview_utils.rb +88 -0
  199. data/test/test_gem_assets.rb +48 -0
  200. data/test/test_helpers.rb +10 -0
  201. data/test/tui_editor_integration_test.rb +15 -15
  202. data/test/tui_integration_test.rb +687 -441
  203. data/test/unit/api.rb +757 -37
  204. data/test/unit/asset_management.rb +195 -221
  205. data/test/unit/backup_test.rb +451 -0
  206. data/test/unit/contract_test.rb +1 -23
  207. data/test/unit/core.rb +415 -61
  208. data/test/unit/deploy_config_test.rb +248 -0
  209. data/test/unit/deploy_test.rb +312 -21
  210. data/test/unit/edit_post_test.rb +168 -0
  211. data/test/unit/gem_asset_management.rb +36 -42
  212. data/test/unit/livetext_basic.rb +23 -35
  213. data/test/unit/livetext_compatibility.rb +7 -14
  214. data/test/unit/parse_cmd_test.rb +260 -0
  215. data/test/unit/{symlink_test.rb → permalink_copy_test.rb} +47 -49
  216. data/test/unit/post.rb +91 -26
  217. data/test/unit/post_index_config_test.rb +258 -0
  218. data/test/unit/post_state_helpers_test.rb +137 -0
  219. data/test/unit/read_commented_file_test.rb +8 -6
  220. data/test/unit/repo.rb +75 -54
  221. data/test/unit/social_test.rb +41 -44
  222. data/test/unit/syntax_highlighting.rb +70 -0
  223. data/test/unit/theme_management_test.rb +91 -0
  224. data/test/unit/view.rb +79 -12
  225. data/test/unit/widgets.rb +8 -8
  226. data/test/web_integration_test.rb +231 -0
  227. data/test/web_test_helper.rb +218 -0
  228. data/test/web_workflow_test.rb +527 -0
  229. data/ui/tui/bin/scriptorium +885 -415
  230. data/ui/web/app/app.rb +1398 -176
  231. data/ui/web/app/assets/livetext_mode.js +244 -0
  232. data/ui/web/app/error_helpers.rb +16 -16
  233. data/ui/web/app/views/advanced_config.erb +8 -2
  234. data/ui/web/app/views/asset_management.erb +56 -0
  235. data/ui/web/app/views/backup_management.erb +238 -0
  236. data/ui/web/app/views/config_widget.erb +232 -0
  237. data/ui/web/app/views/dashboard.erb +64 -72
  238. data/ui/web/app/views/deploy_config.erb +3 -0
  239. data/ui/web/app/views/edit_pages.erb +170 -2
  240. data/ui/web/app/views/edit_post.erb +130 -9
  241. data/ui/web/app/views/edit_theme.erb +73 -0
  242. data/ui/web/app/views/edit_theme_file.erb +74 -0
  243. data/ui/web/app/views/theme_management.erb +130 -0
  244. data/ui/web/app/views/view_dashboard.erb +666 -25
  245. data/ui/web/app/views/widgets.erb +249 -0
  246. data/ui/web/bin/scriptorium-web +35 -24
  247. data/ui/web/tmp/timing.log +17 -0
  248. data/ui/web/tmp/web_server.log +0 -5
  249. metadata +190 -116
  250. data/assets/back-icon.png +0 -0
  251. data/assets/icons/facebook.svg +0 -1
  252. data/assets/icons/github.svg +0 -1
  253. data/assets/icons/instagram.svg +0 -1
  254. data/assets/icons/reddit.svg +0 -1
  255. data/assets/icons/x.svg +0 -1
  256. data/assets/icons/youtube.svg +0 -1
  257. data/bin/scriptorium +0 -1511
  258. data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +0 -34
  259. data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +0 -50
  260. data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +0 -73
  261. data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +0 -70
  262. data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +0 -110
  263. data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +0 -73
  264. data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +0 -124
  265. data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +0 -46
  266. data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +0 -97
  267. data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +0 -211
  268. data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +0 -141
  269. data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +0 -211
  270. data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +0 -134
  271. data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +0 -41
  272. data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +0 -49
  273. data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +0 -46
  274. data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +0 -41
  275. data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +0 -41
  276. data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +0 -256
  277. data/lib/scriptorium/syntax_highlighter.rb +0 -234
  278. data/test/manual/deploy_symlink_demo.rb +0 -142
  279. data/test/manual/symlink_demo.rb +0 -117
  280. data/test/manual/test2.rb +0 -12
  281. data/test/manual/test_banner_from_file.rb +0 -150
  282. data/test/manual/test_banner_in_header.rb +0 -35
  283. data/test/manual/test_code_highlighting.rb +0 -68
  284. data/test/manual/test_complex_header.rb +0 -74
  285. data/test/manual/test_empty_header.rb +0 -32
  286. data/test/manual/test_radial_custom.rb +0 -58
  287. data/test/manual/test_radial_large_radius.rb +0 -52
  288. data/test/manual/test_svg_debug.rb +0 -47
  289. data/test/pages-demo/config/currentview.txt +0 -1
  290. data/test/pages-demo/views/demo/config/common.js +0 -57
  291. data/test/pages-demo/views/demo/config/footer.txt +0 -1
  292. data/test/pages-demo/views/demo/config/global-head.txt +0 -8
  293. data/test/pages-demo/views/demo/config/header.txt +0 -1
  294. data/test/pages-demo/views/demo/config/layout.txt +0 -1
  295. data/test/pages-demo/views/demo/config/left.txt +0 -1
  296. data/test/pages-demo/views/demo/config/main.txt +0 -1
  297. data/test/pages-demo/views/demo/config/right.txt +0 -1
  298. data/test/pages-demo/views/demo/config.txt +0 -3
  299. data/test/pages-demo/views/demo/output/panes/footer.html +0 -1
  300. data/test/pages-demo/views/demo/output/panes/header.html +0 -1
  301. data/test/pages-demo/views/demo/output/panes/left.html +0 -1
  302. data/test/pages-demo/views/demo/output/panes/main.html +0 -1
  303. data/test/pages-demo/views/demo/output/panes/right.html +0 -1
  304. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +0 -5
  305. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +0 -4
  306. data/test/scriptorium-TEST-1754622690-146/config/common.js +0 -57
  307. data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +0 -1
  308. data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +0 -9
  309. data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +0 -1
  310. data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +0 -4
  311. data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +0 -3
  312. data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +0 -8
  313. data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +0 -6
  314. data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +0 -1
  315. data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +0 -1
  316. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +0 -1
  317. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +0 -1
  318. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +0 -14
  319. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +0 -13
  320. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +0 -1
  321. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +0 -5
  322. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +0 -4
  323. data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +0 -57
  324. data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +0 -5
  325. data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +0 -2
  326. data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +0 -9
  327. data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +0 -4
  328. data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +0 -5
  329. data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +0 -3
  330. data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +0 -5
  331. data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +0 -3
  332. data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +0 -7
  333. data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +0 -3
  334. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +0 -3
  335. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +0 -3
  336. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +0 -3
  337. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +0 -3
  338. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +0 -3
  339. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +0 -1
  340. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +0 -1
  341. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +0 -1
  342. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +0 -1
  343. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +0 -1
  344. data/ui/web/tmp/web_server.pid +0 -1
  345. /data/{test/pages-demo/views/demo/config/bootstrap_css.txt → lib/scriptorium/support/bootstrap/css.txt} +0 -0
  346. /data/{test/pages-demo/views/demo/config/bootstrap_js.txt → lib/scriptorium/support/bootstrap/js.txt} +0 -0
  347. /data/{test/scriptorium-TEST-1754622690-146/views/sample → lib/scriptorium/support}/config/reddit.txt +0 -0
  348. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout → lib/scriptorium/support/templates}/layout.txt +0 -0
  349. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt → lib/scriptorium/support/theme/footer.lt3} +0 -0
  350. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt → lib/scriptorium/support/theme/left.lt3} +0 -0
  351. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt → lib/scriptorium/support/theme/main.lt3} +0 -0
  352. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt → lib/scriptorium/support/theme/right.lt3} +0 -0
  353. /data/test/manual/banner-tests/{config.txt → svg.txt} +0 -0
  354. /data/test/manual/{test6.rb → test_advanced_widgets.rb} +0 -0
  355. /data/test/manual/{test1.rb → test_basic_posts.rb} +0 -0
  356. /data/test/manual/{test4.rb → test_layout_widgets.rb} +0 -0
  357. /data/test/manual/{test5.rb → test_pagination.rb} +0 -0
  358. /data/test/manual/{test3.rb → test_random_posts.rb} +0 -0
@@ -0,0 +1,249 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Widget Management - Scriptorium</title>
5
+ <style>
6
+ body {
7
+ font-family: Arial, sans-serif;
8
+ margin: 0;
9
+ padding: 20px;
10
+ background-color: #f5f5f5;
11
+ }
12
+ .container {
13
+ max-width: 1200px;
14
+ margin: 0 auto;
15
+ background: white;
16
+ border-radius: 8px;
17
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
18
+ overflow: hidden;
19
+ }
20
+ .header {
21
+ background: #007bff;
22
+ color: white;
23
+ padding: 20px;
24
+ }
25
+ .header h1 {
26
+ margin: 0;
27
+ font-size: 24px;
28
+ }
29
+ .content {
30
+ padding: 20px;
31
+ }
32
+ .message {
33
+ padding: 10px;
34
+ border-radius: 4px;
35
+ margin-bottom: 20px;
36
+ }
37
+ .message.success {
38
+ background: #d4edda;
39
+ color: #155724;
40
+ border: 1px solid #c3e6cb;
41
+ }
42
+ .message.error {
43
+ background: #f8d7da;
44
+ color: #721c24;
45
+ border: 1px solid #f5c6cb;
46
+ }
47
+ .section {
48
+ margin-bottom: 30px;
49
+ border: 1px solid #ddd;
50
+ border-radius: 6px;
51
+ overflow: hidden;
52
+ }
53
+ .section-header {
54
+ background: #f8f9fa;
55
+ padding: 15px 20px;
56
+ border-bottom: 1px solid #ddd;
57
+ font-weight: bold;
58
+ font-size: 18px;
59
+ }
60
+ .section-content {
61
+ padding: 20px;
62
+ }
63
+ .btn {
64
+ padding: 8px 16px;
65
+ border: none;
66
+ border-radius: 4px;
67
+ cursor: pointer;
68
+ font-size: 14px;
69
+ margin-right: 10px;
70
+ text-decoration: none;
71
+ display: inline-block;
72
+ }
73
+ .btn-primary {
74
+ background: #007bff;
75
+ color: white;
76
+ }
77
+ .btn-primary:hover {
78
+ background: #0056b3;
79
+ }
80
+ .btn-secondary {
81
+ background: #6c757d;
82
+ color: white;
83
+ }
84
+ .btn-secondary:hover {
85
+ background: #545b62;
86
+ }
87
+ .btn-danger {
88
+ background: #dc3545;
89
+ color: white;
90
+ }
91
+ .btn-danger:hover {
92
+ background: #c82333;
93
+ }
94
+ .btn-sm {
95
+ padding: 4px 8px;
96
+ font-size: 12px;
97
+ }
98
+ .widget-grid {
99
+ display: grid;
100
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
101
+ gap: 20px;
102
+ margin-top: 20px;
103
+ }
104
+ .widget-card {
105
+ border: 1px solid #ddd;
106
+ border-radius: 6px;
107
+ padding: 15px;
108
+ background: white;
109
+ }
110
+ .widget-card.configured {
111
+ border-color: #28a745;
112
+ background-color: #f8fff9;
113
+ }
114
+ .widget-card h4 {
115
+ margin: 0 0 10px 0;
116
+ color: #333;
117
+ }
118
+ .widget-status {
119
+ font-size: 12px;
120
+ margin-bottom: 10px;
121
+ }
122
+ .widget-status.configured {
123
+ color: #28a745;
124
+ }
125
+ .widget-status.available {
126
+ color: #6c757d;
127
+ }
128
+ .add-widget-form {
129
+ background: #f8f9fa;
130
+ padding: 15px;
131
+ border-radius: 6px;
132
+ margin-bottom: 20px;
133
+ }
134
+ .add-widget-form form {
135
+ display: flex;
136
+ gap: 10px;
137
+ align-items: end;
138
+ }
139
+ .add-widget-form select, .add-widget-form input[type="text"] {
140
+ padding: 8px;
141
+ border: 1px solid #ddd;
142
+ border-radius: 4px;
143
+ }
144
+ .back-link {
145
+ margin-bottom: 20px;
146
+ }
147
+ </style>
148
+ </head>
149
+ <body>
150
+ <div class="container">
151
+ <div class="header">
152
+ <h1>Widget Management</h1>
153
+ </div>
154
+
155
+ <div class="content">
156
+ <div class="back-link">
157
+ <a href="/view/<%= @current_view.name %>" class="btn btn-secondary">← Back to View Dashboard</a>
158
+ </div>
159
+
160
+ <% if @error %>
161
+ <div class="message error">
162
+ <strong>Error:</strong> <%= @error %>
163
+ </div>
164
+ <% end %>
165
+
166
+ <% if @message %>
167
+ <div class="message success">
168
+ <strong>Success:</strong> <%= @message %>
169
+ </div>
170
+ <% end %>
171
+
172
+ <div class="section">
173
+ <div class="section-header">
174
+ Add New Widget
175
+ </div>
176
+ <div class="section-content">
177
+ <div class="add-widget-form">
178
+ <form method="post" action="/add_widget">
179
+ <select name="widget_name" required>
180
+ <option value="">Select a widget...</option>
181
+ <% @available_widgets.each do |widget| %>
182
+ <% unless @configured_widgets.include?(widget) %>
183
+ <option value="<%= widget %>"><%= widget.capitalize %></option>
184
+ <% end %>
185
+ <% end %>
186
+ </select>
187
+ <button type="submit" class="btn btn-primary">Add Widget</button>
188
+ </form>
189
+ </div>
190
+ <p><em>Note: Widgets will be added to the first available left or right container in your layout.</em></p>
191
+ </div>
192
+ </div>
193
+
194
+ <div class="section">
195
+ <div class="section-header">
196
+ Widgets for <%= @current_view.name %>
197
+ </div>
198
+ <div class="section-content">
199
+ <% if @configured_widgets.empty? %>
200
+ <p>No widgets configured yet. Use the form above to add your first widget.</p>
201
+ <% else %>
202
+ <div class="widget-grid">
203
+ <% @configured_widgets.each do |widget| %>
204
+ <div class="widget-card configured">
205
+ <h4><%= widget.capitalize %> Widget</h4>
206
+ <div class="widget-status configured">✓ Configured</div>
207
+ <% if @widget_containers[widget] %>
208
+ <div style="font-size: 12px; color: #666; margin-bottom: 10px;">
209
+ Container: <strong><%= @widget_containers[widget] %></strong>
210
+ </div>
211
+ <% end %>
212
+ <div>
213
+ <a href="/config_widget/<%= widget %>" class="btn btn-primary btn-sm">Configure</a>
214
+ <form method="post" action="/remove_widget" style="display: inline;">
215
+ <input type="hidden" name="widget_name" value="<%= widget %>">
216
+ <button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to remove this widget?')">Remove</button>
217
+ </form>
218
+ </div>
219
+ </div>
220
+ <% end %>
221
+ </div>
222
+ <% end %>
223
+ </div>
224
+ </div>
225
+
226
+ <div class="section">
227
+ <div class="section-header">
228
+ Available Widgets
229
+ </div>
230
+ <div class="section-content">
231
+ <p>The following widget types are available in Scriptorium:</p>
232
+ <ul>
233
+ <% @available_widgets.each do |widget| %>
234
+ <li>
235
+ <strong><%= widget.capitalize %></strong>
236
+ <% if @configured_widgets.include?(widget) %>
237
+ <span style="color: #28a745;">✓ Already configured</span>
238
+ <% else %>
239
+ <span style="color: #6c757d;">Available to add</span>
240
+ <% end %>
241
+ </li>
242
+ <% end %>
243
+ </ul>
244
+ </div>
245
+ </div>
246
+ </div>
247
+ </div>
248
+ </body>
249
+ </html>
@@ -1,20 +1,34 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # rbenv hack to ensure correct Ruby version
4
+ ENV['PATH'] = "#{ENV['HOME']}/.rbenv/shims:#{ENV['PATH']}"
5
+ ENV['RBENV_VERSION'] = '3.2.3'
6
+
3
7
  require 'optparse'
4
8
  require 'json'
5
9
  require 'net/http'
6
10
  require 'uri'
7
11
  require 'fileutils'
12
+ require_relative '../../../lib/scriptorium'
13
+
8
14
 
9
15
  class ScriptoriumWebServer
10
16
  def initialize
11
17
  @port = 4567
12
- @pid_file = File.join(__dir__, '..', 'tmp', 'web_server.pid')
13
- @log_file = File.join(__dir__, '..', 'tmp', 'web_server.log')
18
+ @pid_file = __dir__/"../tmp/web_server.pid"
19
+ @log_file = __dir__/"../tmp/web_server.log"
20
+
21
+ # Parse command line arguments for test mode
22
+ @testing = ARGV.include?('--test')
23
+
24
+ # Remove --test from ARGV so it doesn't interfere with other processing
25
+ ARGV.delete('--test')
26
+
27
+ # Web server initialized with test mode: #{@testing}
14
28
  end
15
29
 
16
30
  def start
17
- system("kill -9 $(lsof -ti:4567)")
31
+ system("kill -9 $(lsof -ti:4567) 2>/dev/null")
18
32
  if running?
19
33
  puts "Server is already running on port #{@port}"
20
34
  return
@@ -24,7 +38,11 @@ class ScriptoriumWebServer
24
38
  FileUtils.mkdir_p(File.dirname(@pid_file))
25
39
 
26
40
  # Start the server in background
27
- cmd = "cd #{File.dirname(__dir__)} && ruby app/app.rb"
41
+ cmd = "cd #{__dir__}/.. && ruby app/app.rb"
42
+ if @testing
43
+ cmd += " --test"
44
+ end
45
+
28
46
  pid = Process.spawn(cmd,
29
47
  out: @log_file,
30
48
  err: @log_file,
@@ -33,17 +51,11 @@ class ScriptoriumWebServer
33
51
  # Save PID
34
52
  File.write(@pid_file, pid.to_s)
35
53
 
36
- puts "Starting Scriptorium Web UI on port #{@port}..."
37
- puts "PID: #{pid}"
38
- puts "Log: #{@log_file}"
39
-
40
54
  # Wait a moment and check if it started successfully
41
55
  sleep 2
42
- if running?
43
- puts "✅ Server started successfully!"
44
- puts "Visit: http://localhost:#{@port}"
45
- else
56
+ unless running?
46
57
  puts "❌ Server failed to start. Check logs: #{@log_file}"
58
+ exit 1
47
59
  end
48
60
  end
49
61
 
@@ -51,33 +63,24 @@ class ScriptoriumWebServer
51
63
  system("rm #@log_file")
52
64
  system("touch #@log_file")
53
65
  unless File.exist?(@pid_file)
54
- puts "Server is not running"
55
66
  return
56
67
  end
57
68
 
58
69
  pid = File.read(@pid_file).strip.to_i
59
- puts "Stopping server (PID: #{pid})..."
60
70
 
61
71
  begin
62
72
  Process.kill('TERM', pid)
63
73
  Process.wait(pid)
64
- puts "✅ Server stopped"
65
- rescue Errno::ESRCH
66
- puts "Server process not found"
67
- rescue Errno::ECHILD
68
- puts "Server process already ended"
74
+ rescue Errno::ESRCH, Errno::ECHILD
75
+ # Server already stopped
69
76
  ensure
70
77
  File.delete(@pid_file) if File.exist?(@pid_file)
71
78
  end
72
- system("kill -9 $(lsof -ti:4567)")
79
+ system("kill -9 $(lsof -ti:4567) 2>/dev/null")
73
80
  end
74
81
 
75
82
  def status
76
83
  if running?
77
- pid = File.read(@pid_file).strip
78
- puts "✅ Server is running (PID: #{pid})"
79
- puts "URL: http://localhost:#{@port}"
80
-
81
84
  # Try to get JSON status
82
85
  begin
83
86
  response = Net::HTTP.get_response(URI("http://localhost:#{@port}/status"))
@@ -125,6 +128,10 @@ OptionParser.new do |opts|
125
128
  opts.on("-p", "--port PORT", Integer, "Port number (default: 4567)") do |port|
126
129
  options[:port] = port
127
130
  end
131
+
132
+ opts.on("--test", "Use test repository (scriptorium-TEST)") do
133
+ options[:test] = true
134
+ end
128
135
  end.parse!
129
136
 
130
137
  # Get command
@@ -133,6 +140,10 @@ command = ARGV.first || 'status'
133
140
  # Create server instance
134
141
  server = ScriptoriumWebServer.new
135
142
  server.instance_variable_set(:@port, options[:port]) if options[:port]
143
+ server.instance_variable_set(:@testing, options[:test]) if options[:test]
144
+
145
+ # Launcher options: #{options.inspect}
146
+ # Server testing mode: #{server.instance_variable_get(:@testing)}
136
147
 
137
148
  # Execute command
138
149
  case command
@@ -0,0 +1,17 @@
1
+ {"ts":"2025-09-19T02:38:50Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.3000001907348633,"href":"http://localhost:4567/preview/computing/index.html"}}
2
+ {"ts":"2025-09-19T02:45:50Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.2999997138977051,"href":"http://localhost:4567/preview/computing/index.html"}}
3
+ {"ts":"2025-09-19T02:53:09Z","label":"server_generate_view","route":"/preview","view":"computing","ms":2632.339}
4
+ {"ts":"2025-09-19T02:53:12Z","label":"server_generate_view","route":"/preview/:view_name/index.html","view":"computing","ms":2862.597}
5
+ {"ts":"2025-09-19T02:53:13Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.2999997138977051,"href":"http://localhost:4567/preview/computing/index.html"}}
6
+ {"ts":"2025-09-19T03:05:59Z","label":"server_generate_view","route":"/preview","view":"computing","ms":2960.1440000000002}
7
+ {"ts":"2025-09-19T03:06:02Z","label":"server_generate_view","route":"/preview/:view_name/index.html","view":"computing","ms":2725.7259999999997}
8
+ {"ts":"2025-09-19T03:06:02Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.2999997138977051,"href":"http://localhost:4567/preview/computing/index.html"}}
9
+ {"ts":"2025-09-19T03:09:16Z","label":"server_generate_view","route":"/preview","view":"computing","ms":3297.264}
10
+ {"ts":"2025-09-19T03:09:20Z","label":"server_generate_view","route":"/preview/:view_name/index.html","view":"computing","ms":3389.914}
11
+ {"ts":"2025-09-19T03:09:20Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.20000028610229492,"href":"http://localhost:4567/preview/computing/index.html"}}
12
+ {"ts":"2025-09-19T03:09:32Z","label":"server_generate_view","route":"/preview","view":"computing","ms":3087.198}
13
+ {"ts":"2025-09-19T03:09:36Z","label":"server_generate_view","route":"/preview/:view_name/index.html","view":"computing","ms":3658.665}
14
+ {"ts":"2025-09-19T03:09:36Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.3000001907348633,"href":"http://localhost:4567/preview/computing/index.html"}}
15
+ {"ts":"2025-09-19T03:15:27Z","label":"server_generate_view","route":"/preview","view":"computing","ms":2712.335}
16
+ {"ts":"2025-09-19T03:15:30Z","label":"server_generate_view","route":"/preview/:view_name/index.html","view":"computing","ms":2674.076}
17
+ {"ts":"2025-09-19T03:15:30Z","ip":"127.0.0.1","ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","path":"/debug/timing","data":{"label":"preview_onload","ms":0.3000001907348633,"href":"http://localhost:4567/preview/computing/index.html"}}
@@ -1,5 +0,0 @@
1
- Ignoring http_parser.rb-0.6.0 because its extensions are not built. Try: gem pristine http_parser.rb --version 0.6.0
2
- Ignoring unf_ext-0.0.8.2 because its extensions are not built. Try: gem pristine unf_ext --version 0.0.8.2
3
- /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- sinatra (LoadError)
4
- from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
5
- from app/app.rb:3:in `<main>'