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,114 @@
1
+ require_relative './environment'
2
+
3
+ manual_setup
4
+
5
+ # Create a view for testing posts in the correct location for the web app
6
+ # First, clean up the old repo and create a new one in the right location
7
+ system("rm -rf ui/web/scriptorium-TEST")
8
+ @repo = Scriptorium::Repo.create("ui/web/scriptorium-TEST", testmode: true)
9
+ view = @repo.create_view("web-test", "Web App Test View", "Testing posts in the web interface")
10
+
11
+ puts "Creating posts for web app testing..."
12
+
13
+ # Create 45 posts with varied content
14
+ 45.times do |i|
15
+ # Create posts with different titles and content
16
+ title = case i % 5
17
+ when 0
18
+ "Technical Post #{i + 1}: Ruby Programming"
19
+ when 1
20
+ "Creative Post #{i + 1}: Writing and Art"
21
+ when 2
22
+ "Science Post #{i + 1}: Physics and Math"
23
+ when 3
24
+ "Philosophy Post #{i + 1}: Deep Thoughts"
25
+ else
26
+ "Misc Post #{i + 1}: Random Topics"
27
+ end
28
+
29
+ # Create varied body content
30
+ body = case i % 4
31
+ when 0
32
+ "This is a technical post about programming and software development. " +
33
+ "It covers various aspects of Ruby programming, including best practices, " +
34
+ "design patterns, and performance optimization techniques."
35
+ when 1
36
+ "A creative exploration of writing, art, and expression. " +
37
+ "This post delves into the creative process, inspiration, and " +
38
+ "the intersection of technology and creativity."
39
+ when 2
40
+ "An exploration of scientific concepts, from physics to mathematics. " +
41
+ "This post discusses fundamental principles, recent discoveries, " +
42
+ "and the beauty of scientific understanding."
43
+ else
44
+ "Philosophical musings on life, technology, and human nature. " +
45
+ "This post explores deep questions about consciousness, existence, " +
46
+ "and the meaning of it all."
47
+ end
48
+
49
+ # Add some code examples for syntax highlighting
50
+ if i % 3 == 0
51
+ body += "\n\n```ruby\n# Example Ruby code\ndef hello_world\n puts 'Hello, World!'\nend\n\nhello_world\n```"
52
+ end
53
+
54
+ # Create the post
55
+ post = @repo.create_post(title: title, body: body)
56
+
57
+ # Set publication dates spread across different days
58
+ # Use modulo to get valid dates (1-31 for January)
59
+ day = (i % 31) + 1
60
+ post.set_pubdate_with_seconds("2025-01-#{day.to_s.rjust(2, '0')}", i % 60)
61
+
62
+ # Generate the post
63
+ @repo.generate_post(post.id)
64
+
65
+ puts "Created post #{i + 1}: #{title}"
66
+ end
67
+
68
+ # Generate the front page for the view
69
+ view.generate_front_page
70
+
71
+ puts "\n" + "="*60
72
+ puts "POSTS CREATED SUCCESSFULLY!"
73
+ puts "="*60
74
+ puts "Created 45 posts in view 'web-test'"
75
+ puts "Posts have varied titles, content, and publication dates"
76
+ puts "Some posts include code examples for syntax highlighting"
77
+ puts "\nTo view in web app:"
78
+ puts "1. Start the web app: ./ui/web/bin/scriptorium-web start"
79
+ puts "2. Open browser to: http://localhost:4567"
80
+ puts "3. Select the 'web-test' view"
81
+ puts "4. Browse posts and test pagination"
82
+ puts "\nFiles generated in: test/scriptorium-TEST/views/web-test/output/"
83
+
84
+ instruct <<~EOS
85
+ Posts created successfully!
86
+
87
+ Next steps:
88
+ 1. Start the web app with: ./ui/web/bin/scriptorium-web start
89
+ 2. Open browser to http://localhost:4567
90
+ 3. Select 'web-test' view from the dropdown
91
+ 4. Browse the posts and test the interface
92
+
93
+ The posts include:
94
+ - 45 posts with varied content types
95
+ - Different publication dates (spread across 45 days)
96
+ - Code examples for syntax highlighting
97
+ - Varied titles and content themes
98
+
99
+ EOS
100
+
101
+ # Clean up webrick if it was started
102
+ begin
103
+ line = `ps | grep "ruby -run -e httpd" | grep -v grep`
104
+ if line.strip != ""
105
+ pid = line.split.first
106
+ pid2 = pid.to_i + 1
107
+ system("kill #{pid} #{pid2}")
108
+ puts "Cleaned up webrick server"
109
+ end
110
+ rescue => e
111
+ puts "No webrick server to clean up"
112
+ end
113
+
114
+ puts "\nManual test complete! You can now test the web app with these posts."
@@ -0,0 +1,129 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/scriptorium'
3
+ require_relative '../test_helpers'
4
+ require_relative '../web_test_helper'
5
+ require_relative '../support/preview_utils'
6
+ require 'fileutils'
7
+ require 'shellwords'
8
+
9
+ # Manual-inspection oriented preview tests
10
+ # - Does not enforce strict order
11
+ # - Prints absolute paths and preview URLs to inspect
12
+ # - Set MANUAL_KEEP=1 to skip teardown so artifacts remain
13
+
14
+ class PreviewManualTest < Minitest::Test
15
+ include TestHelpers
16
+ include WebTestHelper
17
+
18
+ def interactive_open(label:, paths: [], urls: [])
19
+ PreviewUtils.interactive_open(label: label, paths: paths, urls: urls)
20
+ end
21
+
22
+ def setup
23
+ # Use the web app's test repo location so preview routes see generated files
24
+ @repo_name = "ui/web/scriptorium-TEST"
25
+ @view_name = "manual_preview_view"
26
+
27
+ @api = Scriptorium::API.new
28
+ # Ensure a clean slate before creating the repo
29
+ begin
30
+ FileUtils.rm_rf(@repo_name)
31
+ backup_dir = File.join(File.dirname(@repo_name), 'backup-scriptorium-TEST')
32
+ FileUtils.rm_rf(backup_dir)
33
+ rescue => e
34
+ puts "[Manual] Warning: cleanup failed: #{e.message}"
35
+ end
36
+ @api.create_repo(@repo_name)
37
+ @api.open_repo(@repo_name)
38
+ @api.create_view(@view_name, "Manual Preview View")
39
+
40
+ # Ensure required UI/social icons are available in the view
41
+ begin
42
+ @api.copy_asset('icons/ui/back.png', from: 'gem', to: 'view', view: @view_name)
43
+ rescue => e
44
+ puts "[Manual] Warning: could not copy icons/ui/back.png from gem: #{e.message}"
45
+ end
46
+ begin
47
+ @api.copy_asset('icons/social/reddit.png', from: 'gem', to: 'view', view: @view_name)
48
+ rescue => e
49
+ puts "[Manual] Warning: could not copy icons/social/reddit.png from gem: #{e.message}"
50
+ end
51
+
52
+ # Seed some posts
53
+ @api.create_post("Manual Post A", "Blurb A")
54
+ @api.create_post("Manual Post B", "Blurb B")
55
+
56
+ # Configure post index (line break in date, enable pagination)
57
+ PreviewUtils.write_post_index_config(@repo_name, @view_name)
58
+
59
+ # Add an image and reference it in post 0001
60
+ # Use a real image so the browser can render it
61
+ sample_image = File.expand_path("test/assets/testbanner.jpg")
62
+ @api.upload_asset(sample_image, filename: 'manual.jpg')
63
+ PreviewUtils.reference_image_in_post(@repo_name, '0001', 'manual.jpg')
64
+
65
+ @api.generate_view(@view_name)
66
+ end
67
+
68
+ def teardown
69
+ return if ENV['MANUAL_KEEP'] == '1'
70
+ FileUtils.rm_rf(@repo_name)
71
+ end
72
+
73
+ # 100-series: Index preview
74
+ def test_100_preview_index_artifacts
75
+ base = File.expand_path(File.join(@repo_name, 'views', @view_name))
76
+ index_file = File.join(base, 'output', 'index.html')
77
+ post_index = File.join(base, 'output', 'post_index.html')
78
+ page1 = File.join(base, 'output', 'page1.html')
79
+
80
+ assert File.exist?(index_file), 'index.html missing'
81
+ assert File.exist?(post_index), 'post_index.html missing'
82
+ assert File.exist?(page1), 'page1.html missing'
83
+
84
+ puts "\n[Manual] Inspect artifacts (server-first). Files shown for reference:"
85
+ puts " URL : http://localhost:4567/preview/#{@view_name}/index.html"
86
+ puts " File: #{index_file}"
87
+ puts " File: #{post_index}"
88
+ puts " File: #{page1}"
89
+ # Restart server to ensure preview routes work
90
+ stop_web_server
91
+ start_web_server
92
+ # Open server URL only to avoid file:// CORS issues
93
+ interactive_open(label: 'index (server)', paths: [], urls: ["http://localhost:4567/preview/#{@view_name}/index.html"])
94
+ end
95
+
96
+ # 200-series: One post page and asset
97
+ def test_200_post_and_asset_reference
98
+ base = File.expand_path(File.join(@repo_name, 'views', @view_name))
99
+ meta = File.read(File.join(@repo_name, 'posts', '0001', 'meta.txt'))
100
+ slug = meta.lines.grep(/^post.slug\s+/).first.split.last
101
+ post_html = File.join(base, 'output', 'posts', slug)
102
+ asset_in_output = File.join(base, 'output', 'assets', 'manual.jpg')
103
+
104
+ assert File.exist?(post_html), 'Post HTML missing'
105
+ html = File.read(post_html)
106
+ assert_includes html, "<img src=../assets/manual.jpg", 'Expected relative asset path in post'
107
+
108
+ # Global asset copied to output for serving
109
+ assert File.exist?(asset_in_output), 'Expected asset copied to output/assets'
110
+
111
+ # Clarify exact image path and how the browser resolves it
112
+ img_src = html[/<img[^>]+src=([^\s>]+)/, 1]
113
+ resolved_img_path = File.expand_path(img_src, File.dirname(post_html)) if img_src
114
+
115
+ puts "\n[Manual] Inspect post and asset:"
116
+ puts " File: #{post_html}"
117
+ puts " File: #{asset_in_output}"
118
+ puts " IMG src (from HTML): #{img_src}"
119
+ puts " IMG resolves to : #{resolved_img_path}"
120
+ puts " URL : /preview/#{@view_name}/posts/#{slug}"
121
+ puts " URL : /preview/#{@view_name}/assets/manual.jpg"
122
+ # Restart server to ensure preview routes work
123
+ stop_web_server
124
+ start_web_server
125
+ # Open server URLs only; list local paths for reference
126
+ interactive_open(label: 'post (server)', paths: [], urls: ["http://localhost:4567/preview/#{@view_name}/posts/#{slug}"])
127
+ interactive_open(label: 'asset (server)', paths: [], urls: ["http://localhost:4567/preview/#{@view_name}/assets/manual.jpg"])
128
+ end
129
+ end
@@ -118,37 +118,37 @@ tests = [
118
118
  {
119
119
  title: "Perfect Image Background",
120
120
  subtitle: "Image test (8:1 aspect)",
121
- config: "back.image ../../assets/images/perfect.png",
121
+ config: "back.image ../../assets/images/perfect.png",
122
122
  description: "Perfect match: 8:1 aspect ratio image fits banner exactly - no cropping or scaling needed"
123
123
  },
124
124
  {
125
125
  title: "Wide Image Background",
126
126
  subtitle: "Image test (16:1 aspect)",
127
- config: "back.image ../../assets/images/wide.png",
127
+ config: "back.image ../../assets/images/wide.png",
128
128
  description: "Wide image (16:1) cropped to fit 8:1 banner - left/right edges removed, center preserved"
129
129
  },
130
130
  {
131
131
  title: "Tall Image Background",
132
132
  subtitle: "Image test (1:1 aspect)",
133
- config: "back.image ../../assets/images/tall.png",
133
+ config: "back.image ../../assets/images/tall.png",
134
134
  description: "Square image (1:1) cropped to fit 8:1 banner - top/bottom removed, center strip visible"
135
135
  },
136
136
  {
137
137
  title: "Very Tall Image Background",
138
138
  subtitle: "Image test (1:4 aspect)",
139
- config: "back.image ../../assets/images/very_tall.png",
139
+ config: "back.image ../../assets/images/very_tall.png",
140
140
  description: "Very tall image (1:4) heavily cropped - only narrow center strip visible, most content lost"
141
141
  },
142
142
  {
143
143
  title: "Very Wide Image Background",
144
144
  subtitle: "Image test (16:1 aspect)",
145
- config: "back.image ../../assets/images/very_wide.png",
145
+ config: "back.image ../../assets/images/very_wide.png",
146
146
  description: "Very wide image (16:1) heavily cropped - only narrow center strip visible, sides removed"
147
147
  },
148
148
  {
149
149
  title: "Small Image Background",
150
150
  subtitle: "Image test (low res, 8:1 aspect)",
151
- config: "back.image ../../assets/images/small.png",
151
+ config: "back.image ../../assets/images/small.png",
152
152
  description: "Small low-res image scaled up to fill banner - may appear pixelated but maintains aspect"
153
153
  },
154
154
  {
@@ -176,26 +176,26 @@ tests.each_with_index do |test, index|
176
176
  filename = "test#{page_num.to_s.rjust(2, '0')}.html"
177
177
 
178
178
  # Write config file for this test
179
- File.write(test_dir/"config.txt", test[:config])
179
+ File.write(test_dir/"svg.txt", test[:config])
180
180
 
181
181
  # Create banner
182
182
  require_relative '../../lib/scriptorium'
183
183
  Dir.chdir(test_dir) do
184
184
  banner = Scriptorium::BannerSVG.new(test[:title], test[:subtitle])
185
185
  banner.parse_header_svg
186
- svg_output = banner.generate_svg
186
+ svg_output = banner.get_svg
187
187
 
188
188
  # Check if this is an image background test
189
189
  image_path = nil
190
190
  if test[:config].include?("back.image")
191
191
  image_path = test[:config].match(/back\.image\s+(.+)/)&.[](1)
192
192
  # For the original image display, we need the path relative to the HTML file
193
- # The HTML is in test/manual/banner-tests/, and images are now in the same directory
194
- # So browser URL should be just the filename (relative to HTML file)
195
- display_path = image_path.gsub('../../assets/images/', '') if image_path
193
+ # The HTML is in test/manual/banner-tests/, and images are in test/assets/images/
194
+ # Convert ../../assets/images/... to /assets/images/... (absolute from web server root)
195
+ display_path = image_path.gsub('../../assets/images/', '/assets/images/') if image_path
196
196
 
197
- # Fix the SVG pattern path to use the correct relative path for the HTML file
198
- svg_output = svg_output.gsub('../../assets/images/', '')
197
+ # Fix the SVG pattern path to use the correct absolute path
198
+ svg_output = svg_output.gsub('../../assets/images/', '/assets/images/')
199
199
  end
200
200
 
201
201
  # Create standalone HTML page
@@ -229,7 +229,7 @@ tests.each_with_index do |test, index|
229
229
  </style>
230
230
  </head>
231
231
  <body>
232
- <div class="banner">
232
+ <div class="banner" id="header">
233
233
  #{svg_output}
234
234
  </div>
235
235
  <div class="content">
@@ -0,0 +1,115 @@
1
+ require_relative './environment'
2
+
3
+ manual_setup
4
+
5
+ # Create multiple views to test different banner integration scenarios
6
+ views = []
7
+
8
+ # Test 1: Simple banner in header
9
+ view1 = @repo.create_view("banner-simple", "Simple Banner Site", "A site with basic SVG banner in header")
10
+ File.open(view1.dir/:config/"layout.txt", "w") do |f|
11
+ f.puts "header"
12
+ f.puts "main"
13
+ end
14
+ view1.generate_empty_containers
15
+ File.open(view1.dir/:config/"header.txt", "w") do |f|
16
+ f.puts "banner svg"
17
+ end
18
+ view1.generate_front_page
19
+ views << view1
20
+
21
+ # Test 2: SVG debug test (header only)
22
+ view2 = @repo.create_view("svg-debug", "SVG Debug Test", "Testing SVG insertion")
23
+ File.open(view2.dir/:config/"layout.txt", "w") do |f|
24
+ f.puts "header"
25
+ end
26
+ view2.generate_empty_containers
27
+ File.open(view2.dir/:config/"header.txt", "w") do |f|
28
+ f.puts "banner_svg"
29
+ end
30
+ File.open(view2.dir/:config/"config.txt", "w") do |f|
31
+ f.puts "# Simple debug config"
32
+ f.puts "back.radial #FF0000 #0000FF"
33
+ f.puts "title.color #FFFFFF"
34
+ f.puts "subtitle.color #FFFF00"
35
+ f.puts "title.style bold"
36
+ f.puts "subtitle.style italic"
37
+ end
38
+ view2.generate_front_page
39
+ views << view2
40
+
41
+ # Test 3: Complex header with multiple elements
42
+ view3 = @repo.create_view("complex-header", "My Awesome Blog", "Exploring the Power of SVG Banners")
43
+ File.open(view3.dir/:config/"layout.txt", "w") do |f|
44
+ f.puts "header"
45
+ f.puts "main"
46
+ end
47
+ view3.generate_empty_containers
48
+ File.open(view3.dir/:config/"header.txt", "w") do |f|
49
+ f.puts "banner_svg"
50
+ f.puts "title"
51
+ f.puts "subtitle"
52
+ end
53
+ File.open(view3.dir/:config/"config.txt", "w") do |f|
54
+ f.puts "# Complex SVG Banner Configuration"
55
+ f.puts "# This exercises multiple features at once"
56
+ f.puts ""
57
+ f.puts "# Background: Radial gradient from purple to blue"
58
+ f.puts "back.radial #8B5CF6 #3B82F6"
59
+ f.puts ""
60
+ f.puts "# Custom aspect ratio (wider banner)"
61
+ f.puts "aspect 6.0"
62
+ f.puts ""
63
+ f.puts "# Custom font"
64
+ f.puts "text.font Georgia serif"
65
+ f.puts ""
66
+ f.puts "# Title styling: Bold, larger scale, custom color"
67
+ f.puts "title.scale 1.2"
68
+ f.puts "title.style bold"
69
+ f.puts "title.color #FFFFFF"
70
+ f.puts "title.align center"
71
+ f.puts ""
72
+ f.puts "# Subtitle styling: Italic, smaller scale, different color"
73
+ f.puts "subtitle.scale 0.6"
74
+ f.puts "subtitle.style italic"
75
+ f.puts "subtitle.color #E5E7EB"
76
+ f.puts "subtitle.align center"
77
+ f.puts ""
78
+ f.puts "# Custom positioning for both title and subtitle"
79
+ f.puts "title.xy 50% 45%"
80
+ f.puts "subtitle.xy 50% 75%"
81
+ end
82
+ view3.generate_front_page
83
+ views << view3
84
+
85
+ # Test 4: Empty header (placeholder test)
86
+ view4 = @repo.create_view("empty-header-test", "Empty Header Test", "Testing placeholder text")
87
+ File.open(view4.dir/:config/"layout.txt", "w") do |f|
88
+ f.puts "header"
89
+ f.puts "main"
90
+ end
91
+ view4.generate_empty_containers
92
+ File.open(view4.dir/:config/"header.txt", "w") do |f|
93
+ # Empty file - should trigger placeholder
94
+ end
95
+ view4.generate_front_page
96
+ views << view4
97
+
98
+ instruct <<~EOS
99
+ Banner Integration Tests
100
+
101
+ This test demonstrates different banner integration scenarios:
102
+
103
+ 1. banner-simple: Basic SVG banner in header with main content
104
+ 2. svg-debug: Header-only layout with red-to-blue radial gradient banner
105
+ 3. complex-header: Multiple header elements with sophisticated banner styling
106
+ 4. empty-header-test: Empty header to verify placeholder text behavior
107
+
108
+ Each view tests different aspects of banner integration:
109
+ - Simple banner insertion
110
+ - Header-only layouts
111
+ - Complex styling combinations
112
+ - Placeholder text handling
113
+ EOS
114
+
115
+ examine views
@@ -0,0 +1,87 @@
1
+ require_relative './environment'
2
+
3
+ manual_setup
4
+
5
+ # Create multiple views to test different radial gradient scenarios
6
+ views = []
7
+
8
+ # Test 1: Custom radial gradient with custom center and radius
9
+ view1 = @repo.create_view("radial-custom", "Custom Radial Test", "Testing custom radial gradient parameters")
10
+ File.open(view1.dir/:config/"layout.txt", "w") do |f|
11
+ f.puts "header"
12
+ end
13
+ view1.generate_empty_containers
14
+ File.open(view1.dir/:config/"header.txt", "w") do |f|
15
+ f.puts "banner_svg"
16
+ end
17
+ File.open(view1.dir/:config/"config.txt", "w") do |f|
18
+ f.puts "# Custom Radial Gradient Test"
19
+ f.puts "# Default: circular vignette (ar omitted, will use 1/aspect)"
20
+ f.puts "aspect 5.0"
21
+ f.puts "back.radial #FF6B6B #4ECDC4 75% 25% 60%"
22
+ f.puts ""
23
+ f.puts "# Custom: elliptical vignette (ar = 0.5, i.e. squished horizontally)"
24
+ f.puts "# Uncomment to test:"
25
+ f.puts "# back.radial #FF6B6B #4ECDC4 75% 25% 60% 0.5"
26
+ f.puts ""
27
+ f.puts "# Title styling"
28
+ f.puts "title.color #FFFFFF"
29
+ f.puts "title.style bold"
30
+ f.puts "title.align center"
31
+ f.puts ""
32
+ f.puts "# Subtitle styling"
33
+ f.puts "subtitle.color #FFFFFF"
34
+ f.puts "subtitle.style italic"
35
+ f.puts "subtitle.align center"
36
+ end
37
+ view1.generate_front_page
38
+ views << view1
39
+
40
+ # Test 2: Large radius radial gradient (soft vignette)
41
+ view2 = @repo.create_view("radial-large-radius", "Large Radius Radial Test", "Testing r > 100% for soft vignette")
42
+ File.open(view2.dir/:config/"layout.txt", "w") do |f|
43
+ f.puts "header"
44
+ end
45
+ view2.generate_empty_containers
46
+ File.open(view2.dir/:config/"header.txt", "w") do |f|
47
+ f.puts "banner_svg"
48
+ end
49
+ File.open(view2.dir/:config/"config.txt", "w") do |f|
50
+ f.puts "# Large Radius Radial Gradient Test"
51
+ f.puts "aspect 5.0"
52
+ f.puts "# r = 150% (soft vignette, gradient extends beyond banner)"
53
+ f.puts "back.radial #FF6B6B #4ECDC4 50% 50% 150%"
54
+ f.puts ""
55
+ f.puts "# Title styling"
56
+ f.puts "title.color #FFFFFF"
57
+ f.puts "title.style bold"
58
+ f.puts "title.align center"
59
+ f.puts ""
60
+ f.puts "# Subtitle styling"
61
+ f.puts "subtitle.color #FFFFFF"
62
+ f.puts "subtitle.style italic"
63
+ f.puts "subtitle.align center"
64
+ end
65
+ view2.generate_front_page
66
+ views << view2
67
+
68
+ instruct <<~EOS
69
+ Radial Gradient Banner Tests
70
+
71
+ This test demonstrates different radial gradient scenarios:
72
+
73
+ 1. radial-custom: Custom center position (75%, 25%) and radius (60%)
74
+ - Tests aspect-ratio compensation for circular vignettes
75
+ - Includes commented example for elliptical vignettes (ar=0.5)
76
+
77
+ 2. radial-large-radius: Large radius (150%) for soft vignette effect
78
+ - Tests gradients that extend beyond the banner boundaries
79
+ - Creates a very soft, subtle color transition
80
+
81
+ Both tests use:
82
+ - Wide aspect ratio (5.0) to test gradient behavior in non-square banners
83
+ - White text with bold title and italic subtitle
84
+ - Centered text alignment
85
+ EOS
86
+
87
+ examine views