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
@@ -1,234 +0,0 @@
1
- require 'rouge'
2
-
3
- module Scriptorium
4
- class SyntaxHighlighter
5
- # Default theme - can be customized
6
- DEFAULT_THEME = {
7
- 'keyword' => 'color: #07a; font-weight: bold;',
8
- 'string' => 'color: #690;',
9
- 'comment' => 'color: #708090; font-style: italic;',
10
- 'function' => 'color: #dd4a68;',
11
- 'number' => 'color: #905;',
12
- 'symbol' => 'color: #905;',
13
- 'operator' => 'color: #9a6e3a;',
14
- 'class-name' => 'color: #dd4a68;',
15
- 'regex' => 'color: #e90;',
16
- 'variable' => 'color: #e90;',
17
- 'interpolation' => 'color: #690;', # same as string
18
- 'error' => 'color: #d73a49; font-weight: bold;',
19
- 'whitespace' => 'color: transparent;',
20
- 'other' => 'color: #24292e;'
21
- }
22
-
23
- def initialize(theme = nil)
24
- @theme = theme || DEFAULT_THEME
25
- @formatter = Rouge::Formatters::HTML.new
26
- end
27
-
28
- # Highlight code with language detection
29
- def highlight(code, language = nil)
30
- return escape_html(code) if language.nil? || language.empty?
31
-
32
- language = language.downcase.strip
33
-
34
- # Map common language names to Rouge lexers
35
- lexer_name = map_language(language)
36
- return escape_html(code) unless lexer_name
37
-
38
- begin
39
- lexer = Rouge::Lexer.find(lexer_name)
40
- puts "DEBUG: Found lexer: #{lexer.class}"
41
- highlighted = @formatter.format(lexer.lex(code))
42
- puts "DEBUG: Rouge output length: #{highlighted.length}"
43
- puts "DEBUG: Raw Rouge output (first 500 chars): #{highlighted[0..500]}"
44
- puts "DEBUG: HTML contains <div>: #{highlighted.include?('<div')}"
45
- puts "DEBUG: HTML contains <br>: #{highlighted.include?('<br')}"
46
- puts "DEBUG: HTML contains \\n: #{highlighted.include?("\n")}"
47
-
48
- # Massage the output to use our CSS classes
49
- massage_output(highlighted, language)
50
- rescue => e
51
- # Fallback to escaped HTML if highlighting fails
52
- puts "DEBUG: Rouge highlighting failed for #{language}: #{e.message}"
53
- puts "DEBUG: Backtrace: #{e.backtrace.first(3).join(', ')}"
54
- escape_html(code)
55
- end
56
- end
57
-
58
- # Generate CSS for the theme
59
- def generate_css
60
- css = []
61
- css << "/* Syntax highlighting styles */"
62
- css << "pre {"
63
- css << " background: #f5f5f5;"
64
- css << " padding: 15px;"
65
- css << " border-radius: 5px;"
66
- css << " overflow-x: auto;"
67
- css << "}"
68
- css << ""
69
- css << "pre code {"
70
- css << " font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace;"
71
- css << " font-size: 14px;"
72
- css << "}"
73
- css << ""
74
- css << "/* Override Bootstrap height constraints for syntax highlighting */"
75
- css << "pre code[class*=\"language-\"] {"
76
- css << " height: auto !important;"
77
- css << " max-height: none !important;"
78
- css << " min-height: auto !important;"
79
- css << " overflow: visible !important;"
80
- css << "}"
81
- css << ""
82
- css << "pre:has(code[class*=\"language-\"]) {"
83
- css << " height: auto !important;"
84
- css << " max-height: none !important;"
85
- css << " min-height: auto !important;"
86
- css << " overflow: visible !important;"
87
- css << "}"
88
-
89
- @theme.each do |token, style|
90
- css << ".token.#{token} { #{style} }"
91
- end
92
-
93
- css.join("\n")
94
- end
95
-
96
- private
97
-
98
- # Map common language names to Rouge lexer names
99
- def map_language(language)
100
- language_map = {
101
- 'ruby' => 'ruby',
102
- 'rb' => 'ruby',
103
- 'javascript' => 'javascript',
104
- 'js' => 'javascript',
105
- 'elixir' => 'elixir',
106
- 'python' => 'python',
107
- 'py' => 'python',
108
- 'html' => 'html',
109
- 'css' => 'css',
110
- 'sql' => 'sql',
111
- 'bash' => 'bash',
112
- 'shell' => 'bash',
113
- 'sh' => 'bash',
114
- 'yaml' => 'yaml',
115
- 'yml' => 'yaml',
116
- 'json' => 'json',
117
- 'xml' => 'xml',
118
- 'markdown' => 'markdown',
119
- 'md' => 'markdown',
120
- 'go' => 'go',
121
- 'rust' => 'rust',
122
- 'java' => 'java',
123
- 'cpp' => 'cpp',
124
- 'c' => 'c',
125
- 'csharp' => 'csharp',
126
- 'cs' => 'csharp',
127
- 'php' => 'php',
128
- 'r' => 'r',
129
- 'scala' => 'scala',
130
- 'swift' => 'swift',
131
- 'kotlin' => 'kotlin',
132
- 'dart' => 'dart'
133
- }
134
-
135
- language_map[language]
136
- end
137
-
138
- # Massage Rouge output to use our CSS classes
139
- def massage_output(html, language)
140
- # Rouge outputs classes like 'k' for keyword, 's' for string, etc.
141
- # We want to map these to our semantic class names
142
- class_mapping = {
143
- 'k' => 'keyword', # keyword
144
- 's' => 'string', # string
145
- 'c' => 'comment', # comment
146
- 'f' => 'function', # function
147
- 'n' => 'number', # number
148
- 'o' => 'operator', # operator
149
- 'c1' => 'comment', # comment
150
- 's1' => 'string', # string
151
- 's2' => 'string', # string
152
- 'nb' => 'function', # function name
153
- 'na' => 'function', # function argument
154
- 'nc' => 'class-name', # class name
155
- 'nd' => 'function', # function definition
156
- 'ne' => 'variable', # variable
157
- 'nf' => 'function', # function
158
- 'ni' => 'variable', # variable
159
- 'nl' => 'number', # number literal
160
- 'nn' => 'class-name', # class name
161
- 'no' => 'constant', # constant
162
- 'nt' => 'tag', # tag name
163
- 'nv' => 'variable', # variable
164
- 'ow' => 'operator', # operator
165
- 'p' => 'punctuation', # punctuation
166
- 'pi' => 'doctype', # doctype
167
- # JavaScript-specific mappings
168
- 'kd' => 'keyword', # keyword declaration (function, var, etc.)
169
- 'nx' => 'variable', # variable name
170
- 'dl' => 'string', # string delimiter
171
- 'cm' => 'comment', # comment
172
- 'cp' => 'comment', # comment
173
- 'cs' => 'comment', # comment
174
- 'ge' => 'comment', # comment
175
- 'gh' => 'comment', # comment
176
- 'gp' => 'comment', # comment
177
- 'gs' => 'comment', # comment
178
- 'gu' => 'comment', # comment
179
- 'il' => 'number', # number literal
180
- 'm' => 'number', # number
181
- 'mf' => 'number', # number
182
- 'mh' => 'number', # number
183
- 'mi' => 'number', # number
184
- 'mo' => 'number', # number
185
- 'sb' => 'string', # string
186
- 'sc' => 'string', # string
187
- 'sd' => 'string', # string
188
- 'se' => 'string', # string
189
- 'sh' => 'string', # string
190
- 'si' => 'string', # string
191
- 'sr' => 'string', # string
192
- 'ss' => 'string', # string
193
- 'vi' => 'variable', # instance variable (@name)
194
- 'vc' => 'variable', # class variable (@@name)
195
- 'vg' => 'variable', # global variable ($name)
196
- 'bp' => 'variable', # built-in pseudo
197
- 'err' => 'error', # error
198
- 'w' => 'whitespace', # whitespace
199
- 'x' => 'other', # other
200
- 'kc' => 'constant' # constant (true, false, null)
201
- }
202
-
203
- # Replace Rouge's short class names with our semantic names
204
- class_mapping.each do |rouge_class, semantic_class|
205
- html.gsub!(/class="#{rouge_class}"/, "class=\"token #{semantic_class}\"")
206
- html.gsub!(/class='#{rouge_class}'/, "class='token #{semantic_class}'")
207
- end
208
-
209
- # Add 'token' class to all spans that don't have it
210
- html.gsub!(/<span class="([^"]*?)">/, '<span class="token \1">')
211
- html.gsub!(/<span class='([^']*?)'>/, "<span class='token \\1'>")
212
-
213
- # Clean up duplicate 'token token' classes
214
- html.gsub!(/class="token token ([^"]*)"/, 'class="token \1"')
215
- html.gsub!(/class='token token ([^']*)'/, "class='token \\1'")
216
-
217
- html
218
- end
219
-
220
-
221
-
222
- # Simple HTML escaping
223
- def escape_html(text)
224
- text.to_s
225
- .gsub('&', '&amp;')
226
- .gsub('<', '&lt;')
227
- .gsub('>', '&gt;')
228
- .gsub('"', '&quot;')
229
- .gsub("'", '&#39;')
230
- end
231
-
232
-
233
- end
234
- end
@@ -1,142 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Manual test script to demonstrate deployment with symlinks
4
- # Run with: ruby test/manual/deploy_symlink_demo.rb
5
-
6
- require_relative '../../lib/scriptorium'
7
- require_relative '../test_helpers'
8
-
9
- class DeploySymlinkDemo
10
- include Scriptorium::Helpers
11
- include TestHelpers
12
-
13
- def run
14
- puts "=== Deployment with Symlinks Demo ==="
15
- puts
16
-
17
- # Create test repository
18
- puts "1. Creating test repository..."
19
- @repo = Scriptorium::Repo.create("test/scriptorium-TEST", testmode: true)
20
- @view = @repo.create_view("demo_view", "Demo View", "A demo view for deployment")
21
- puts " ✓ Created repository and view"
22
- puts
23
-
24
- # Create a test post
25
- puts "2. Creating test post..."
26
- post_title = "Deployment Test Post with Symlinks"
27
- post_body = "This post tests deployment with symlinks."
28
-
29
- draft_name = @repo.create_draft(title: post_title, body: post_body)
30
- post_num = @repo.finish_draft(draft_name)
31
- puts " ✓ Created post ##{post_num}: #{post_title}"
32
- puts
33
-
34
- # Generate the post
35
- puts "3. Generating post..."
36
- @repo.generate_post(post_num)
37
- puts " ✓ Generated post"
38
- puts
39
-
40
- # Check the files
41
- puts "4. Checking generated files..."
42
-
43
- numbered_slug = slugify(post_num, post_title) + ".html"
44
- clean_slug = clean_slugify(post_title) + ".html"
45
-
46
- numbered_path = @view.dir/:output/:permalink/numbered_slug
47
- clean_symlink_path = @view.dir/:output/:permalink/clean_slug
48
-
49
- puts " Numbered file: #{numbered_path}"
50
- puts " Clean symlink: #{clean_symlink_path}"
51
- puts
52
-
53
- # Verify files exist
54
- if File.exist?(numbered_path)
55
- puts " ✓ Numbered file exists"
56
- else
57
- puts " ✗ Numbered file missing"
58
- end
59
-
60
- if File.exist?(clean_symlink_path)
61
- puts " ✓ Clean symlink exists"
62
- else
63
- puts " ✗ Clean symlink missing"
64
- end
65
-
66
- if File.symlink?(clean_symlink_path)
67
- puts " ✓ Clean symlink is actually a symlink"
68
- symlink_target = File.readlink(clean_symlink_path)
69
- puts " ✓ Symlink points to: #{symlink_target}"
70
- else
71
- puts " ✗ Clean symlink is not a symlink"
72
- end
73
- puts
74
-
75
- # Test deployment simulation
76
- puts "5. Testing deployment simulation..."
77
-
78
- # Create a test deployment directory
79
- test_deploy_dir = "test/deploy-test"
80
- FileUtils.rm_rf(test_deploy_dir) if Dir.exist?(test_deploy_dir)
81
- FileUtils.mkdir_p(test_deploy_dir)
82
-
83
- # Simulate rsync command with symlink preservation
84
- output_dir = @view.dir/:output
85
- rsync_cmd = "rsync -r -z -l #{output_dir}/ #{test_deploy_dir}/"
86
- puts " Simulating: #{rsync_cmd}"
87
-
88
- # Actually copy files (simulating rsync)
89
- FileUtils.cp_r("#{output_dir}/.", test_deploy_dir)
90
-
91
- # Check if symlinks were preserved
92
- deployed_symlink = "#{test_deploy_dir}/permalink/#{clean_slug}"
93
- deployed_target = "#{test_deploy_dir}/permalink/#{numbered_slug}"
94
-
95
- if File.exist?(deployed_symlink)
96
- puts " ✓ Symlink exists in deployment directory"
97
-
98
- if File.symlink?(deployed_symlink)
99
- puts " ✓ Symlink is preserved in deployment"
100
- deployed_target_readlink = File.readlink(deployed_symlink)
101
- puts " ✓ Deployed symlink points to: #{deployed_target_readlink}"
102
-
103
- if File.exist?(deployed_target)
104
- puts " ✓ Symlink target exists in deployment"
105
- else
106
- puts " ✗ Symlink target missing in deployment"
107
- end
108
- else
109
- puts " ✗ Symlink was not preserved (copied as file)"
110
- end
111
- else
112
- puts " ✗ Symlink missing in deployment directory"
113
- end
114
- puts
115
-
116
- # Show deployment structure
117
- puts "6. Deployment directory structure:"
118
- if Dir.exist?(test_deploy_dir)
119
- Dir.glob("#{test_deploy_dir}/**/*").sort.each do |file|
120
- relative_path = file.sub("#{test_deploy_dir}/", "")
121
- if File.symlink?(file)
122
- target = File.readlink(file)
123
- puts " #{relative_path} -> #{target} (symlink)"
124
- elsif File.directory?(file)
125
- puts " #{relative_path}/ (directory)"
126
- else
127
- puts " #{relative_path} (file)"
128
- end
129
- end
130
- end
131
- puts
132
-
133
- puts "=== Demo Complete ==="
134
- puts
135
- puts "To clean up, run: rm -rf test/scriptorium-TEST test/deploy-test"
136
- end
137
- end
138
-
139
- if __FILE__ == $0
140
- demo = DeploySymlinkDemo.new
141
- demo.run
142
- end
@@ -1,117 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # Manual test script to demonstrate symlink functionality
4
- # Run with: ruby test/manual/symlink_demo.rb
5
-
6
- require_relative '../../lib/scriptorium'
7
- require_relative '../test_helpers'
8
-
9
- class SymlinkDemo
10
- include Scriptorium::Helpers
11
- include TestHelpers
12
-
13
- def run
14
- puts "=== Symlink Functionality Demo ==="
15
- puts
16
-
17
- # Create test repository
18
- puts "1. Creating test repository..."
19
- @repo = Scriptorium::Repo.create("test/scriptorium-TEST", testmode: true)
20
- @view = @repo.create_view("demo_view", "Demo View", "A demo view for symlinks")
21
- puts " ✓ Created repository and view"
22
- puts
23
-
24
- # Create a test post
25
- puts "2. Creating test post..."
26
- post_title = "My First Test Post with Special Characters: & < > \" ' !"
27
- post_body = "This is the body of my test post. It contains some content."
28
-
29
- draft_name = @repo.create_draft(title: post_title, body: post_body)
30
- post_num = @repo.finish_draft(draft_name)
31
- puts " ✓ Created post ##{post_num}: #{post_title}"
32
- puts
33
-
34
- # Generate the post
35
- puts "3. Generating post..."
36
- @repo.generate_post(post_num)
37
- puts " ✓ Generated post"
38
- puts
39
-
40
- # Check the files
41
- puts "4. Checking generated files..."
42
-
43
- numbered_slug = slugify(post_num, post_title) + ".html"
44
- clean_slug = clean_slugify(post_title) + ".html"
45
-
46
- numbered_path = @view.dir/:output/:permalink/numbered_slug
47
- clean_symlink_path = @view.dir/:output/:permalink/clean_slug
48
-
49
- puts " Numbered file: #{numbered_path}"
50
- puts " Clean symlink: #{clean_symlink_path}"
51
- puts
52
-
53
- # Verify files exist
54
- if File.exist?(numbered_path)
55
- puts " ✓ Numbered file exists"
56
- else
57
- puts " ✗ Numbered file missing"
58
- end
59
-
60
- if File.exist?(clean_symlink_path)
61
- puts " ✓ Clean symlink exists"
62
- else
63
- puts " ✗ Clean symlink missing"
64
- end
65
-
66
- if File.symlink?(clean_symlink_path)
67
- puts " ✓ Clean symlink is actually a symlink"
68
- symlink_target = File.readlink(clean_symlink_path)
69
- puts " ✓ Symlink points to: #{symlink_target}"
70
- else
71
- puts " ✗ Clean symlink is not a symlink"
72
- end
73
- puts
74
-
75
- # Show the URLs
76
- puts "5. Generated URLs:"
77
- puts " Numbered URL: /permalink/#{numbered_slug}"
78
- puts " Clean URL: /permalink/#{clean_slug}"
79
- puts
80
-
81
- # Test the symlink
82
- puts "6. Testing symlink..."
83
- if File.symlink?(clean_symlink_path)
84
- symlink_target = File.readlink(clean_symlink_path)
85
- if symlink_target == numbered_slug
86
- puts " ✓ Symlink correctly points to numbered file"
87
- else
88
- puts " ✗ Symlink points to wrong target: #{symlink_target}"
89
- end
90
- else
91
- puts " ✗ Clean symlink is not a symlink"
92
- end
93
- puts
94
-
95
- # Show file contents
96
- puts "7. File contents:"
97
- if File.exist?(numbered_path)
98
- content = File.read(numbered_path)
99
- puts " Numbered file size: #{content.length} bytes"
100
- puts " Contains 'Back to Blog' link: #{content.include?('Back to Blog') ? 'Yes' : 'No'}"
101
- end
102
-
103
- if File.exist?(clean_symlink_path) && File.symlink?(clean_symlink_path)
104
- puts " Clean symlink: points to #{File.readlink(clean_symlink_path)}"
105
- end
106
- puts
107
-
108
- puts "=== Demo Complete ==="
109
- puts
110
- puts "To clean up, run: rm -rf test/scriptorium-TEST"
111
- end
112
- end
113
-
114
- if __FILE__ == $0
115
- demo = SymlinkDemo.new
116
- demo.run
117
- end
data/test/manual/test2.rb DELETED
@@ -1,12 +0,0 @@
1
- require_relative "./environment"
2
-
3
- manual_setup
4
-
5
- create_3_views
6
- @repo.generate_front_page("blog1")
7
-
8
- instruct <<~EOS
9
- Do we still need this test??
10
- EOS
11
-
12
- examine("blog1")
@@ -1,150 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require_relative '../../lib/scriptorium'
4
-
5
- include Scriptorium::Helpers
6
-
7
- # Simple banner test from configuration file
8
- def test_banner_from_file(config_file, output_file = nil)
9
- # Default output file if not specified
10
- output_file ||= "banner_output.html"
11
-
12
- # Read the configuration file
13
- unless File.exist?(config_file)
14
- puts "Error: Configuration file '#{config_file}' not found"
15
- exit 1
16
- end
17
-
18
- # Use the read_commented_file helper to read the config
19
- config_lines = read_commented_file(config_file)
20
- config_content = File.read(config_file) # Keep original for display
21
-
22
- puts "Read configuration from: #{config_file}"
23
- puts "Found #{config_lines.length} configuration lines (comments removed)"
24
-
25
- # Create banner with default title/subtitle
26
- banner = Scriptorium::BannerSVG.new("Test Banner", "Generated from config file")
27
-
28
- # Write config to temporary file for banner to read
29
- temp_config = "temp_banner_config.txt"
30
- File.write(temp_config, config_content)
31
-
32
- # Parse and generate the banner
33
- banner.parse_header_svg
34
- svg_output = banner.generate_svg
35
-
36
- # Clean up temp config file
37
- File.delete(temp_config) if File.exist?(temp_config)
38
-
39
- # Create HTML output
40
- html_content = <<~HTML
41
- <!DOCTYPE html>
42
- <html>
43
- <head>
44
- <title>Banner Test - #{File.basename(config_file)}</title>
45
- <style>
46
- body {
47
- font-family: Arial, sans-serif;
48
- margin: 0;
49
- padding: 20px;
50
- background: #f5f5f5;
51
- }
52
- .banner {
53
- width: 100%;
54
- max-width: 800px;
55
- margin: 0 auto 20px auto;
56
- border: 2px solid #007cba;
57
- border-radius: 8px;
58
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
59
- }
60
- .config {
61
- background: white;
62
- padding: 20px;
63
- margin: 20px auto;
64
- max-width: 800px;
65
- border-radius: 8px;
66
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
67
- }
68
- .config h3 {
69
- margin-top: 0;
70
- color: #333;
71
- }
72
- .config pre {
73
- background: #f8f9fa;
74
- padding: 15px;
75
- border-radius: 4px;
76
- overflow-x: auto;
77
- font-family: monospace;
78
- font-size: 12px;
79
- }
80
- .info {
81
- background: white;
82
- padding: 20px;
83
- margin: 20px auto;
84
- max-width: 800px;
85
- border-radius: 8px;
86
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
87
- }
88
- .processed-config {
89
- background: #e8f4fd;
90
- padding: 15px;
91
- margin: 10px 0;
92
- border-radius: 4px;
93
- font-family: monospace;
94
- font-size: 12px;
95
- }
96
- </style>
97
- </head>
98
- <body>
99
- <div class="banner">
100
- #{svg_output}
101
- </div>
102
-
103
- <div class="info">
104
- <h3>Banner Information</h3>
105
- <p><strong>Configuration file:</strong> #{config_file}</p>
106
- <p><strong>Output file:</strong> #{output_file}</p>
107
- <p><strong>Generated:</strong> #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}</p>
108
- <p><strong>Configuration lines processed:</strong> #{config_lines.length}</p>
109
- </div>
110
-
111
- <div class="config">
112
- <h3>Configuration Used (with comments)</h3>
113
- <pre>#{config_content}</pre>
114
-
115
- <h3>Processed Configuration (comments removed)</h3>
116
- <div class="processed-config">
117
- #{config_lines.map { |line| line.empty? ? "# (empty line)" : line }.join("\n")}
118
- </div>
119
- </div>
120
- </body>
121
- </html>
122
- HTML
123
-
124
- # Write the HTML file
125
- File.write(output_file, html_content)
126
- puts "Generated banner HTML: #{output_file}"
127
-
128
- # Open in browser if on macOS
129
- if RUBY_PLATFORM.include?('darwin')
130
- puts "Opening in browser..."
131
- system("open #{output_file}")
132
- else
133
- puts "Open #{output_file} in your browser to view the banner"
134
- end
135
- end
136
-
137
- # Main execution
138
- if ARGV.empty?
139
- puts "Usage: ruby test_banner_from_file.rb <config_file> [output_file]"
140
- puts ""
141
- puts "Example:"
142
- puts " ruby test_banner_from_file.rb my_banner_config.txt"
143
- puts " ruby test_banner_from_file.rb my_banner_config.txt custom_output.html"
144
- exit 1
145
- end
146
-
147
- config_file = ARGV[0]
148
- output_file = ARGV[1] # Optional
149
-
150
- test_banner_from_file(config_file, output_file)
@@ -1,35 +0,0 @@
1
- require_relative './environment'
2
-
3
- manual_setup
4
-
5
- # Create a simple view
6
- view = @repo.create_view("banner-test", "My Banner Site", "A site with SVG banner in header")
7
-
8
- # Set up layout with header
9
- File.open(view.dir/:config/"layout.txt", "w") do |f|
10
- f.puts "header"
11
- f.puts "main"
12
- end
13
-
14
- # Generate the empty containers
15
- view.generate_empty_containers
16
-
17
- # Configure the header to include the SVG banner
18
- File.open(view.dir/:config/"header.txt", "w") do |f|
19
- f.puts "banner svg"
20
- end
21
-
22
- # Generate the front page
23
- view.generate_front_page
24
-
25
- instruct <<~EOS
26
- This test shows how to insert an SVG banner into the header.
27
-
28
- The header.txt contains:
29
- - banner svg (inserts the SVG banner)
30
-
31
- The SVG banner will appear at the top of the header.
32
- The banner automatically uses the view's title and subtitle as its content.
33
- EOS
34
-
35
- examine view