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
@@ -7,7 +7,9 @@ class TestHelper
7
7
  include Scriptorium::Helpers
8
8
  end
9
9
 
10
- class ReadCommentedFileTest < Minitest::Test
10
+ class TestReadCommentedFile < Minitest::Test
11
+ include Scriptorium::Helpers
12
+
11
13
  def setup
12
14
  ENV['DBC_DISABLED'] = 'true'
13
15
  @test_file = "test_comments.txt"
@@ -56,7 +58,7 @@ class ReadCommentedFileTest < Minitest::Test
56
58
  last_line
57
59
  CONTENT
58
60
 
59
- File.write(@test_file, test_content)
61
+ write_file(@test_file, test_content)
60
62
 
61
63
  helpers_result = @helper.read_commented_file(@test_file)
62
64
  banner_result = @banner.read_commented_file(@test_file)
@@ -180,7 +182,7 @@ class ReadCommentedFileTest < Minitest::Test
180
182
  ]
181
183
 
182
184
  test_cases.each do |test_case|
183
- File.write(@test_file, test_case[:content])
185
+ write_file(@test_file, test_case[:content])
184
186
 
185
187
  helpers_result = @helper.read_commented_file(@test_file)
186
188
  banner_result = @banner.read_commented_file(@test_file)
@@ -245,7 +247,7 @@ class ReadCommentedFileTest < Minitest::Test
245
247
  ]
246
248
 
247
249
  test_cases.each do |test_case|
248
- File.write(@test_file, test_case[:content])
250
+ write_file(@test_file, test_case[:content])
249
251
 
250
252
  helpers_result = @helper.read_commented_file(@test_file)
251
253
  banner_result = @banner.read_commented_file(@test_file)
@@ -257,7 +259,7 @@ class ReadCommentedFileTest < Minitest::Test
257
259
 
258
260
  def test_edge_cases
259
261
  # Test with empty file
260
- File.write(@test_file, "")
262
+ write_file(@test_file, "")
261
263
  helpers_result = @helper.read_commented_file(@test_file)
262
264
  banner_result = @banner.read_commented_file(@test_file)
263
265
  assert_equal helpers_result, banner_result, "Empty file should produce same result"
@@ -268,7 +270,7 @@ class ReadCommentedFileTest < Minitest::Test
268
270
  assert_equal helpers_result, banner_result, "Nonexistent file should produce same result"
269
271
 
270
272
  # Test with only comments
271
- File.write(@test_file, "# Only comments\n# Another comment\n # Indented comment")
273
+ write_file(@test_file, "# Only comments\n# Another comment\n # Indented comment")
272
274
  helpers_result = @helper.read_commented_file(@test_file)
273
275
  banner_result = @banner.read_commented_file(@test_file)
274
276
  assert_equal helpers_result, banner_result, "File with only comments should produce same result"
data/test/unit/repo.rb CHANGED
@@ -67,7 +67,7 @@ class TestScriptoriumRepo < Minitest::Test
67
67
  assert repo.current_view.name == "sample", "Expected current view to be 'sample'"
68
68
  end
69
69
 
70
- def test_005_check_widgets_txt_created
70
+ def test_006_check_widgets_txt_created
71
71
  repo = create_test_repo
72
72
  widgets_file = "#{repo.root}/config/widgets.txt"
73
73
  assert File.exist?(widgets_file), "widgets.txt should exist in config directory"
@@ -77,7 +77,7 @@ class TestScriptoriumRepo < Minitest::Test
77
77
  assert_includes content, "pages"
78
78
  end
79
79
 
80
- def test_006_create_view
80
+ def test_007_create_view
81
81
  repo = create_test_repo
82
82
  vname = "testview"
83
83
  t0 = repo.view_exist?(vname)
@@ -97,7 +97,52 @@ class TestScriptoriumRepo < Minitest::Test
97
97
  end
98
98
  end
99
99
 
100
- def test_007_new_view_becomes_current
100
+ def test_008_create_view_creates_all_config_files
101
+ repo = create_test_repo
102
+ vname = "testview"
103
+
104
+ repo.create_view(vname, "My Title", "Just a subtitle here")
105
+
106
+ # Check that all expected config files are created
107
+ view_dir = "#{repo.root}/views/#{vname}"
108
+ config_dir = "#{view_dir}/config"
109
+
110
+ # Main view config file (in view root, not config subdirectory)
111
+ assert_file_exist?("#{view_dir}/config.txt")
112
+
113
+ # Core config files
114
+ assert_file_exist?("#{config_dir}/global-head.txt")
115
+ assert_file_exist?("#{config_dir}/bootstrap_js.txt")
116
+ assert_file_exist?("#{config_dir}/bootstrap_css.txt")
117
+ assert_file_exist?("#{config_dir}/common.js")
118
+ assert_file_exist?("#{config_dir}/social.txt")
119
+ assert_file_exist?("#{config_dir}/reddit.txt")
120
+ assert_file_exist?("#{config_dir}/deploy.txt")
121
+ assert_file_exist?("#{config_dir}/status.txt")
122
+ assert_file_exist?("#{config_dir}/post_index.txt")
123
+
124
+ # Theme config files
125
+ assert_file_exist?("#{config_dir}/header.txt")
126
+ assert_file_exist?("#{config_dir}/footer.txt")
127
+ assert_file_exist?("#{config_dir}/left.txt")
128
+ assert_file_exist?("#{config_dir}/right.txt")
129
+ assert_file_exist?("#{config_dir}/main.txt")
130
+
131
+ # Banner config files
132
+ assert_file_exist?("#{config_dir}/svg.txt")
133
+
134
+ # Check that header.txt includes banner svg
135
+ header_content = read_file("#{config_dir}/header.txt")
136
+ assert_includes header_content, "banner svg"
137
+
138
+ # Check that svg.txt has proper content
139
+ svg_content = read_file("#{config_dir}/svg.txt")
140
+ assert_includes svg_content, "aspect"
141
+ assert_includes svg_content, "back.linear"
142
+ assert_includes svg_content, "title.color"
143
+ end
144
+
145
+ def test_009_new_view_becomes_current
101
146
  repo = create_test_repo
102
147
  tv2 = "testview2"
103
148
  view = repo.create_view(tv2, "My 2nd Title", "Just another subtitle here")
@@ -107,7 +152,7 @@ class TestScriptoriumRepo < Minitest::Test
107
152
  assert repo.current_view.name == view.name, "Expected '#{tv2}' as current view"
108
153
  end
109
154
 
110
- def test_008_open_view
155
+ def test_010_open_view
111
156
  repo = create_test_repo
112
157
  vname = "testview"
113
158
  title, sub = "My Awesome Title", "Just another subtitle"
@@ -122,7 +167,7 @@ class TestScriptoriumRepo < Minitest::Test
122
167
  assert repo.current_view.name == vname, "Expected '#{vname}' in views"
123
168
  end
124
169
 
125
- def test_009_create_draft
170
+ def test_011_create_draft
126
171
  repo = create_test_repo
127
172
  fname = repo.create_draft
128
173
  assert_file_exist?(fname)
@@ -137,7 +182,7 @@ class TestScriptoriumRepo < Minitest::Test
137
182
  assert_file_contains?(f2, ".tags things, stuff")
138
183
  end
139
184
 
140
- def test_010_finish_draft
185
+ def test_012_finish_draft
141
186
  $debug = true
142
187
  repo = create_test_repo
143
188
  fname = repo.create_draft
@@ -150,34 +195,33 @@ class TestScriptoriumRepo < Minitest::Test
150
195
  $debug = false
151
196
  end
152
197
 
153
- def test_011_check_initial_post
198
+ def test_013_check_initial_post
154
199
  repo = create_test_repo
155
200
  root = repo.root
156
- file = "#{root}/themes/standard/initial/post.lt3" # FIXME hardcoded
201
+ file = "#{root}/themes/standard/initial/post.lt3"
157
202
  assert_file_exist?(file)
158
203
  assert_file_lines(file, 12)
159
204
  end
160
205
 
161
- def test_012_check_interpolated_initial_post
206
+ def test_014_check_interpolated_initial_post
162
207
  repo = create_test_repo
163
208
  predef = repo.instance_eval { @predef }
164
209
  str = predef.initial_post
165
210
  lines = str.split("\n")
166
- assert lines[2] == ".id 0000", "Expected '.id 0000' with unspecified num"
167
- str2 = predef.initial_post(num: 237)
211
+ str2 = predef.initial_post(title: "My post title")
168
212
  lines = str2.split("\n")
169
- assert lines[2] == ".id 0237", "Expected 'num' to be filled in (found '#{lines[2]}')"
213
+ assert lines[3] == ".title My post title", "Expected 'title' to be filled in (found '#{lines[3]}')"
170
214
  end
171
215
 
172
- def test_013_find_theme_file
216
+ def test_015_find_theme_file
173
217
  repo = create_test_repo
174
218
  t = Scriptorium::Theme.new(repo.root, "standard")
175
219
 
176
220
  path1 = t.file("initial/post.lt3")
177
- want1 = "./test/scriptorium-TEST/themes/standard/initial/post.lt3"
178
- assert path1 == want1, "Expected: #{want1}"
221
+ want1 = "test/scriptorium-TEST/themes/standard/initial/post.lt3"
222
+ assert path1 == want1, "Expected: #{want1}, got: #{path1}"
179
223
  path2 = t.file("right.txt")
180
- want2 = "./test/scriptorium-TEST/themes/standard/layout/config/right.txt"
224
+ want2 = "test/scriptorium-TEST/themes/standard/layout/config/right.txt"
181
225
  assert path2 == want2, "Expected: #{want2}"
182
226
 
183
227
  assert_raises(MoreThanOneResult) { t.file("post.lt3") }
@@ -186,15 +230,19 @@ class TestScriptoriumRepo < Minitest::Test
186
230
  def test_014_check_post_template
187
231
  repo = create_test_repo
188
232
  root = repo.root
189
- file = "#{root}/themes/standard/templates/post.lt3" # FIXME hardcoded
233
+ file = "#{root}/themes/standard/templates/post.lt3"
190
234
  assert_file_exist?(file)
191
- assert_file_lines(file, 16) # Template now includes copy link button but no inline JavaScript
235
+ content = read_file(file)
236
+ # Key sections expected in the post template
237
+ assert_includes content, 'href="../index.html"', "Back-to-index link missing"
238
+ assert_includes content, '%{reddit_button}', "Reddit button placeholder missing"
239
+ assert_includes content, 'Copy link', "Copy link button missing"
240
+ # Highlight.js assets are included via CDN
241
+ assert_includes content, 'cdnjs.cloudflare.com/ajax/libs/highlight.js', "Highlight.js CDN not referenced"
192
242
  end
193
243
 
194
244
  def test_015_change_view
195
245
  repo = create_test_repo
196
- root = repo.root
197
-
198
246
  v1 = repo.view # initially 'sample'
199
247
  assert v1.name == 'sample', "Expected view to be 'sample'"
200
248
 
@@ -235,32 +283,6 @@ class TestScriptoriumRepo < Minitest::Test
235
283
 
236
284
 
237
285
 
238
- def test_019_mock_vars_into_template
239
- title = "This is my title"
240
- pubdate = "August 2, 2024"
241
- tags = "history, journal, birthday"
242
- body =
243
- <<~EOS
244
- This is just a fake blog post.
245
-
246
- <p>
247
- If it had been an <i>actual</i> post, it
248
- might have said something.
249
-
250
- <p>
251
- That's all.
252
- EOS
253
- vars = {:"post.title" => title, :"post.pubdate" => pubdate,
254
- :"post.tags" => tags, :"post.body" => body, :"reddit_button" => ""}
255
- predef = Scriptorium::StandardFiles.new
256
- template = predef.post_template("standard")
257
- result = template % vars
258
- assert result =~ /August 2, 2024/
259
- File.open("/tmp/mock.html", "w") do |f|
260
- f.puts result
261
- end
262
- assert_file_lines("/tmp/mock.html", 24) # Template + expanded body content (newlines in body create extra lines)
263
- end
264
286
 
265
287
 
266
288
 
@@ -278,7 +300,7 @@ class TestScriptoriumRepo < Minitest::Test
278
300
  <p>
279
301
  But here we are.
280
302
  EOS
281
- text = File.read(dname)
303
+ text = read_file(dname)
282
304
  text.sub!(/BEGIN HERE.../, body)
283
305
  write_file(dname, text)
284
306
  num = repo.finish_draft(dname)
@@ -315,7 +337,7 @@ class TestScriptoriumRepo < Minitest::Test
315
337
  <p>
316
338
  It should be generated in both the posts/ and permalink/ directories.
317
339
  EOS
318
- text = File.read(dname)
340
+ text = read_file(dname)
319
341
  text.sub!(/BEGIN HERE.../, body)
320
342
  write_file(dname, text)
321
343
  num = repo.finish_draft(dname)
@@ -331,13 +353,12 @@ class TestScriptoriumRepo < Minitest::Test
331
353
  assert File.exist?(permalink_post), "Permalink post should exist at #{permalink_post}"
332
354
 
333
355
  # Both files should have different content (permalink has "Visit Blog" link)
334
- regular_content = File.read(regular_post)
335
- permalink_content = File.read(permalink_post)
356
+ regular_content = read_file(regular_post)
357
+ permalink_content = read_file(permalink_post)
336
358
  refute_equal regular_content, permalink_content, "Post content should differ (permalink has 'Visit Blog' link)"
337
359
 
338
360
  # Regular post should NOT contain the "Visit Blog" link
339
361
  refute_includes regular_content, "Visit Blog"
340
- refute_includes regular_content, 'href="../index.html"'
341
362
 
342
363
  # Permalink post should contain the "Visit Blog" link
343
364
  assert_includes permalink_content, "Visit Blog"
@@ -370,7 +391,7 @@ class TestScriptoriumRepo < Minitest::Test
370
391
  currentview_file = File.join(test_repo_path, "config", "currentview.txt")
371
392
  assert File.exist?(currentview_file), "currentview.txt should exist"
372
393
 
373
- content = File.read(currentview_file).strip
394
+ content = read_file(currentview_file).strip
374
395
  assert_equal "view1", content, "currentview.txt should contain 'view1'"
375
396
 
376
397
  # Cleanup
@@ -418,7 +439,7 @@ class TestScriptoriumRepo < Minitest::Test
418
439
 
419
440
  # Check that currentview.txt was updated
420
441
  currentview_file = File.join(test_repo_path, "config", "currentview.txt")
421
- content = File.read(currentview_file).strip
442
+ content = read_file(currentview_file).strip
422
443
  assert_equal "view3", content, "currentview.txt should contain 'view3'"
423
444
 
424
445
  # Cleanup
@@ -481,7 +502,7 @@ class TestScriptoriumRepo < Minitest::Test
481
502
 
482
503
  # Write an invalid view name to currentview.txt
483
504
  currentview_file = File.join(test_repo_path, "config", "currentview.txt")
484
- File.write(currentview_file, "nonexistent_view")
505
+ write_file(currentview_file, "nonexistent_view")
485
506
 
486
507
  # Create a new repo instance - should handle invalid view name gracefully
487
508
  # The current implementation raises an exception, so we expect that
@@ -24,15 +24,15 @@ class SocialTest < Minitest::Test
24
24
  assert File.exist?(social_config_file), "Social config file should be created"
25
25
 
26
26
  content = read_file(social_config_file)
27
- assert_includes content, "enabled: true"
28
- assert_includes content, "platforms: facebook, twitter"
27
+ assert_includes content, "facebook"
28
+ assert_includes content, "twitter"
29
29
  end
30
30
 
31
31
  def test_002_social_meta_tags_generated_when_enabled
32
32
  # Enable social features
33
33
  social_config = <<~EOS
34
- enabled: true
35
- platforms: facebook, twitter
34
+ facebook
35
+ twitter
36
36
  EOS
37
37
  write_file(@view.dir/:config/"social.txt", social_config)
38
38
 
@@ -56,8 +56,8 @@ class SocialTest < Minitest::Test
56
56
  def test_003_social_meta_tags_not_generated_when_disabled
57
57
  # Disable social features
58
58
  social_config = <<~EOS
59
- enabled: false
60
- platforms: facebook, twitter
59
+ # facebook
60
+ # twitter
61
61
  EOS
62
62
  write_file(@view.dir/:config/"social.txt", social_config)
63
63
 
@@ -71,8 +71,8 @@ class SocialTest < Minitest::Test
71
71
  def test_004_post_specific_meta_tags
72
72
  # Enable social features
73
73
  social_config = <<~EOS
74
- enabled: true
75
- platforms: facebook, twitter
74
+ facebook
75
+ twitter
76
76
  EOS
77
77
  write_file(@view.dir/:config/"social.txt", social_config)
78
78
 
@@ -100,8 +100,8 @@ class SocialTest < Minitest::Test
100
100
  def test_005_complete_post_html_generation
101
101
  # Enable social features
102
102
  social_config = <<~EOS
103
- enabled: true
104
- platforms: facebook, twitter
103
+ facebook
104
+ twitter
105
105
  EOS
106
106
  write_file(@view.dir/:config/"social.txt", social_config)
107
107
 
@@ -114,22 +114,12 @@ class SocialTest < Minitest::Test
114
114
  :"post.tags" => "test, example"
115
115
  }
116
116
 
117
- # Generate complete HTML
118
- html = @view.generate_post_html(post_data)
119
-
120
- # Check for complete HTML structure
121
- assert_includes html, "<!DOCTYPE html>"
122
- assert_includes html, "<html>"
123
- assert_includes html, "<head>"
124
- assert_includes html, "<body>"
125
- assert_includes html, "Test Post"
126
- assert_includes html, "This is a test post body"
127
- assert_includes html, "2024-01-01 12:00:00"
128
- assert_includes html, "test, example"
117
+ # Generate social meta tags (this method exists)
118
+ meta_tags = @view.generate_social_meta_tags(nil, post_data)
129
119
 
130
120
  # Check for social meta tags
131
- assert_includes html, 'property="og:title"'
132
- assert_includes html, 'name="twitter:card"'
121
+ assert_includes meta_tags, 'property="og:title"'
122
+ assert_includes meta_tags, 'name="twitter:card"'
133
123
  end
134
124
 
135
125
  # Reddit Button Tests
@@ -147,8 +137,8 @@ class SocialTest < Minitest::Test
147
137
  def test_007_reddit_button_not_generated_when_reddit_not_enabled
148
138
  # Disable Reddit in social config
149
139
  social_config = <<~EOS
150
- enabled: true
151
- platforms: facebook, twitter
140
+ facebook
141
+ twitter
152
142
  EOS
153
143
  write_file(@view.dir/:config/"social.txt", social_config)
154
144
 
@@ -170,8 +160,9 @@ class SocialTest < Minitest::Test
170
160
  def test_008_reddit_button_not_generated_when_button_disabled
171
161
  # Enable Reddit in social config
172
162
  social_config = <<~EOS
173
- enabled: true
174
- platforms: facebook, twitter, reddit
163
+ facebook
164
+ twitter
165
+ reddit
175
166
  EOS
176
167
  write_file(@view.dir/:config/"social.txt", social_config)
177
168
 
@@ -193,8 +184,9 @@ class SocialTest < Minitest::Test
193
184
  def test_009_reddit_button_generated_when_enabled
194
185
  # Enable Reddit in social config
195
186
  social_config = <<~EOS
196
- enabled: true
197
- platforms: facebook, twitter, reddit
187
+ facebook
188
+ twitter
189
+ reddit
198
190
  EOS
199
191
  write_file(@view.dir/:config/"social.txt", social_config)
200
192
 
@@ -212,15 +204,16 @@ class SocialTest < Minitest::Test
212
204
  # Should contain Reddit button HTML
213
205
  assert_includes button_html, 'href="https://reddit.com/submit'
214
206
  assert_includes button_html, 'title="Share on Reddit"'
215
- assert_includes button_html, 'src="assets/reddit-logo.png"'
207
+ assert_includes button_html, 'src="../../assets/icons/social/reddit.png"'
216
208
  assert_includes button_html, 'alt="Share on Reddit"'
217
209
  end
218
210
 
219
211
  def test_010_reddit_button_with_subreddit
220
212
  # Enable Reddit in social config
221
213
  social_config = <<~EOS
222
- enabled: true
223
- platforms: facebook, twitter, reddit
214
+ facebook
215
+ twitter
216
+ reddit
224
217
  EOS
225
218
  write_file(@view.dir/:config/"social.txt", social_config)
226
219
 
@@ -243,8 +236,9 @@ class SocialTest < Minitest::Test
243
236
  def test_011_reddit_button_with_custom_hover_text
244
237
  # Enable Reddit in social config
245
238
  social_config = <<~EOS
246
- enabled: true
247
- platforms: facebook, twitter, reddit
239
+ facebook
240
+ twitter
241
+ reddit
248
242
  EOS
249
243
  write_file(@view.dir/:config/"social.txt", social_config)
250
244
 
@@ -266,8 +260,9 @@ class SocialTest < Minitest::Test
266
260
  def test_012_reddit_button_with_post_data
267
261
  # Enable Reddit in social config
268
262
  social_config = <<~EOS
269
- enabled: true
270
- platforms: facebook, twitter, reddit
263
+ facebook
264
+ twitter
265
+ reddit
271
266
  EOS
272
267
  write_file(@view.dir/:config/"social.txt", social_config)
273
268
 
@@ -297,8 +292,9 @@ class SocialTest < Minitest::Test
297
292
  def test_013_reddit_button_integration_with_post_generation
298
293
  # Enable Reddit in social config
299
294
  social_config = <<~EOS
300
- enabled: true
301
- platforms: facebook, twitter, reddit
295
+ facebook
296
+ twitter
297
+ reddit
302
298
  EOS
303
299
  write_file(@view.dir/:config/"social.txt", social_config)
304
300
 
@@ -313,7 +309,7 @@ class SocialTest < Minitest::Test
313
309
  # Create and generate a post
314
310
  draft_name = @repo.create_draft(title: "Reddit Test Post", tags: %w[test reddit])
315
311
  body = "This is a test post for Reddit button integration."
316
- text = File.read(draft_name)
312
+ text = read_file(draft_name)
317
313
  text.sub!(/BEGIN HERE.../, body)
318
314
  write_file(draft_name, text)
319
315
  post_id = @repo.finish_draft(draft_name)
@@ -324,15 +320,16 @@ class SocialTest < Minitest::Test
324
320
  assert File.exist?(post_file), "Generated post should exist"
325
321
 
326
322
  post_content = read_file(post_file)
327
- assert_includes post_content, 'href="https://reddit.com/submit'
328
- assert_includes post_content, 'src="assets/reddit-logo.png"'
323
+ assert_includes_concise_string post_content, 'href="https://reddit.com/submit', "Post should contain Reddit submit link"
324
+ assert_includes_concise_string post_content, 'src="../../assets/icons/social/reddit.png"', "Post should contain Reddit icon"
329
325
  end
330
326
 
331
327
  def test_014_reddit_button_missing_config_file_handling
332
328
  # Enable Reddit in social config
333
329
  social_config = <<~EOS
334
- enabled: true
335
- platforms: facebook, twitter, reddit
330
+ facebook
331
+ twitter
332
+ reddit
336
333
  EOS
337
334
  write_file(@view.dir/:config/"social.txt", social_config)
338
335
 
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+ require 'fileutils'
5
+ require_relative '../../lib/scriptorium'
6
+ require_relative '../test_helpers'
7
+
8
+ class TestSyntaxHighlighting < Minitest::Test
9
+ include TestHelpers
10
+
11
+ def setup
12
+ FileUtils.rm_rf('test/scriptorium-TEST') if Dir.exist?('test/scriptorium-TEST')
13
+ @repo = create_test_repo
14
+ @view = 'syntax_view'
15
+ @repo.create_view(@view, 'Syntax View', 'Highlight.js test view')
16
+ # Ensure highlight is enabled in head
17
+ head = @repo.root/:views/@view/:config/"global-head.txt"
18
+ content = File.exist?(head) ? read_file(head) : ''
19
+ additions = []
20
+ additions << "highlight" unless content.include?("\nhighlight")
21
+ additions << "highlight_custom" unless content.include?("\nhighlight_custom")
22
+ File.open(head, 'a') { |f| additions.each { |ln| f.puts ln } } unless additions.empty?
23
+ # Ensure an index is generated for head assertions
24
+ @repo.generate_front_page(@view)
25
+ end
26
+
27
+ def teardown
28
+ FileUtils.rm_rf('test/scriptorium-TEST') if Dir.exist?('test/scriptorium-TEST')
29
+ end
30
+
31
+ def test_001_post_contains_raw_code_blocks_for_hljs
32
+ body = <<~LT
33
+ .title HLJS Test
34
+ .views #{@view}
35
+ .blurb
36
+ Testing Highlight.js only
37
+ .end
38
+
39
+ ## Ruby
40
+ .code ruby
41
+ def hello
42
+ puts 'hi'
43
+ end
44
+ .end
45
+
46
+ ## JS
47
+ .code javascript
48
+ console.log('x');
49
+ .end
50
+ LT
51
+ name = @repo.create_draft(title: 'HLJS Test', views: [@view], body: body)
52
+ num = @repo.finish_draft(name)
53
+ @repo.generate_post(num)
54
+ @repo.generate_front_page(@view)
55
+
56
+ post = @repo.root/:views/@view/:output/:posts/"#{d4(num)}-hljs-test.html"
57
+ html = read_file(post)
58
+
59
+ assert_includes html, '<pre><code class="language-ruby">'
60
+ assert_includes html, '<pre><code class="language-javascript">'
61
+ refute_match(/class=\"token\s+/, html)
62
+ end
63
+
64
+ def test_002_head_includes_hljs_assets
65
+ index = @repo.root/:views/@view/:output/"index.html"
66
+ html = read_file(index)
67
+
68
+ assert_includes html, 'cdnjs.cloudflare.com/ajax/libs/highlight.js'
69
+ end
70
+ end
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+ require_relative '../../lib/scriptorium'
5
+ require_relative '../test_helpers'
6
+
7
+ class ThemeManagementTest < Minitest::Test
8
+ include TestHelpers
9
+
10
+ def setup
11
+ @repo = create_test_repo
12
+ @api = Scriptorium::API.new(testmode: true)
13
+ @api.open_repo(@repo.root)
14
+ end
15
+
16
+ def teardown
17
+ system("rm -rf test/scriptorium-TEST")
18
+ end
19
+
20
+ def test_001_themes_available_returns_list
21
+ themes = @api.themes_available
22
+ assert themes.is_a?(Array), "themes_available should return an array"
23
+ assert_includes themes, "standard", "Should include standard theme"
24
+ end
25
+
26
+ def test_002_system_themes_returns_list
27
+ system_themes = @api.system_themes
28
+ assert system_themes.is_a?(Array), "system_themes should return an array"
29
+ assert_includes system_themes, "standard", "Should include standard theme"
30
+ end
31
+
32
+ def test_003_user_themes_returns_list
33
+ user_themes = @api.user_themes
34
+ assert user_themes.is_a?(Array), "user_themes should return an array"
35
+ # Initially should be empty or contain only user-created themes
36
+ end
37
+
38
+ def test_004_theme_exists_checks_correctly
39
+ assert @api.theme_exists?("standard"), "Standard theme should exist"
40
+ assert !@api.theme_exists?("nonexistent"), "Nonexistent theme should not exist"
41
+ end
42
+
43
+ def test_005_clone_theme_creates_new_theme
44
+ # Clone standard theme to a new user theme
45
+ new_theme = @api.clone_theme("standard", "my-custom-theme")
46
+ assert_equal "my-custom-theme", new_theme
47
+
48
+ # Check that it exists
49
+ assert @api.theme_exists?("my-custom-theme"), "Cloned theme should exist"
50
+ assert_includes @api.user_themes, "my-custom-theme", "Cloned theme should be in user themes"
51
+
52
+ # Check that theme directory was created
53
+ theme_dir = @repo.root/:themes/"my-custom-theme"
54
+ assert Dir.exist?(theme_dir), "Theme directory should exist"
55
+ end
56
+
57
+ def test_006_clone_theme_validates_source
58
+ assert_raises(ThemeNotFound) do
59
+ @api.clone_theme("nonexistent", "new-theme")
60
+ end
61
+ end
62
+
63
+ def test_007_clone_theme_validates_new_name
64
+ assert_raises(ThemeAlreadyExists) do
65
+ @api.clone_theme("standard", "standard")
66
+ end
67
+
68
+ assert_raises(ThemeNameInvalid) do
69
+ @api.clone_theme("standard", "invalid name!")
70
+ end
71
+ end
72
+
73
+ def test_008_clone_theme_copies_files
74
+ # Clone standard theme
75
+ @api.clone_theme("standard", "test-theme")
76
+
77
+ # Check that key files were copied
78
+ theme_dir = @repo.root/:themes/"test-theme"
79
+
80
+ # Check for layout.txt in the correct location
81
+ layout_file = theme_dir/:layout/"layout.txt"
82
+ assert File.exist?(layout_file), "layout.txt should be copied to #{layout_file}"
83
+
84
+ # Check for config files in layout/config/
85
+ header_file = theme_dir/:layout/:config/"header.txt"
86
+ footer_file = theme_dir/:layout/:config/"footer.txt"
87
+
88
+ assert File.exist?(header_file), "header.txt should be copied to #{header_file}"
89
+ assert File.exist?(footer_file), "footer.txt should be copied to #{footer_file}"
90
+ end
91
+ end