scriptorium 0.6.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. checksums.yaml +4 -4
  2. data/assets/icons/social/reddit.png +0 -0
  3. data/assets/icons/social/x-logo.png +0 -0
  4. data/assets/imagenotfound.jpg +0 -0
  5. data/bin/sblog +84 -5
  6. data/bin/scriptorium +1 -0
  7. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +0 -1
  8. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +0 -29
  9. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +0 -19
  10. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +1 -1
  11. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +1 -1
  12. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +1 -1
  13. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +0 -10
  14. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +1 -4
  15. data/doc/anti-amnesia/20250901-211714-codemirror-integration-and-web-tests.md +172 -0
  16. data/doc/anti-amnesia/20250902-002402-backup-restore-system.md +126 -0
  17. data/doc/anti-amnesia/20250907-203339-backup-metadata-implementation.md +66 -0
  18. data/doc/imported/0001-elixir-conf-2014/metadata.txt +7 -0
  19. data/doc/imported/0001-elixir-conf-2014/post.html +37 -0
  20. data/doc/imported/0001-elixir-conf-2014/source.lt3 +22 -0
  21. data/doc/imported/0002-programmers-and-word-processing/metadata.txt +7 -0
  22. data/doc/imported/0002-programmers-and-word-processing/post.html +192 -0
  23. data/doc/imported/0002-programmers-and-word-processing/source.lt3 +146 -0
  24. data/doc/imported/0003-how-to-turn-your-brain-sideways/metadata.txt +7 -0
  25. data/doc/imported/0003-how-to-turn-your-brain-sideways/post.html +60 -0
  26. data/doc/imported/0003-how-to-turn-your-brain-sideways/source.lt3 +40 -0
  27. data/doc/imported/0004-upcoming-lone-star-ruby-conference/metadata.txt +7 -0
  28. data/doc/imported/0004-upcoming-lone-star-ruby-conference/post.html +42 -0
  29. data/doc/imported/0004-upcoming-lone-star-ruby-conference/source.lt3 +24 -0
  30. data/doc/imported/0005-elixir-conf-2015-announced/metadata.txt +7 -0
  31. data/doc/imported/0005-elixir-conf-2015-announced/post.html +30 -0
  32. data/doc/imported/0005-elixir-conf-2015-announced/source.lt3 +16 -0
  33. data/doc/imported/0006-ruby-for-dinosaurs/metadata.txt +7 -0
  34. data/doc/imported/0006-ruby-for-dinosaurs/post.html +43 -0
  35. data/doc/imported/0006-ruby-for-dinosaurs/source.lt3 +27 -0
  36. data/doc/imported/0007-phoenix-isnt-rails/metadata.txt +7 -0
  37. data/doc/imported/0007-phoenix-isnt-rails/post.html +116 -0
  38. data/doc/imported/0007-phoenix-isnt-rails/source.lt3 +87 -0
  39. data/doc/imported/0008-concerning-the-term-monkeypatching/metadata.txt +7 -0
  40. data/doc/imported/0008-concerning-the-term-monkeypatching/post.html +129 -0
  41. data/doc/imported/0008-concerning-the-term-monkeypatching/source.lt3 +92 -0
  42. data/doc/imported/0009-announcement-coming-soon/metadata.txt +7 -0
  43. data/doc/imported/0009-announcement-coming-soon/post.html +33 -0
  44. data/doc/imported/0009-announcement-coming-soon/source.lt3 +19 -0
  45. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/metadata.txt +7 -0
  46. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/post.html +175 -0
  47. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/source.lt3 +139 -0
  48. data/doc/imported/0011-computer-science-as-a-lost-art/metadata.txt +7 -0
  49. data/doc/imported/0011-computer-science-as-a-lost-art/post.html +139 -0
  50. data/doc/imported/0011-computer-science-as-a-lost-art/source.lt3 +104 -0
  51. data/doc/imported/0012-ruby-day-in-turin-italy/metadata.txt +7 -0
  52. data/doc/imported/0012-ruby-day-in-turin-italy/post.html +42 -0
  53. data/doc/imported/0012-ruby-day-in-turin-italy/source.lt3 +24 -0
  54. data/doc/imported/0013-rubyday-was-a-success/metadata.txt +7 -0
  55. data/doc/imported/0013-rubyday-was-a-success/post.html +44 -0
  56. data/doc/imported/0013-rubyday-was-a-success/source.lt3 +27 -0
  57. data/doc/imported/0014-working-on-the-blogging-software/metadata.txt +7 -0
  58. data/doc/imported/0014-working-on-the-blogging-software/post.html +63 -0
  59. data/doc/imported/0014-working-on-the-blogging-software/source.lt3 +41 -0
  60. data/doc/imported/0015-ok-its-not-really-a-lost-art/metadata.txt +7 -0
  61. data/doc/imported/0015-ok-its-not-really-a-lost-art/post.html +172 -0
  62. data/doc/imported/0015-ok-its-not-really-a-lost-art/source.lt3 +134 -0
  63. data/doc/imported/0016-an-in-operator-for-ruby/metadata.txt +7 -0
  64. data/doc/imported/0016-an-in-operator-for-ruby/post.html +155 -0
  65. data/doc/imported/0016-an-in-operator-for-ruby/source.lt3 +106 -0
  66. data/doc/imported/0017-the-forgotten-mathematician/metadata.txt +7 -0
  67. data/doc/imported/0017-the-forgotten-mathematician/post.html +161 -0
  68. data/doc/imported/0017-the-forgotten-mathematician/source.lt3 +119 -0
  69. data/doc/imported/0018-ruby-puns/metadata.txt +7 -0
  70. data/doc/imported/0018-ruby-puns/post.html +46 -0
  71. data/doc/imported/0018-ruby-puns/source.lt3 +28 -0
  72. data/doc/imported/0019-custom-exceptions-via-metaprogramming/metadata.txt +7 -0
  73. data/doc/imported/0019-custom-exceptions-via-metaprogramming/post.html +138 -0
  74. data/doc/imported/0019-custom-exceptions-via-metaprogramming/source.lt3 +101 -0
  75. data/doc/imported/0020-fffff/metadata.txt +7 -0
  76. data/doc/imported/0020-fffff/post.html +24 -0
  77. data/doc/imported/0020-fffff/source.lt3 +12 -0
  78. data/doc/imported/0021-trying-ror-yet-again/metadata.txt +7 -0
  79. data/doc/imported/0021-trying-ror-yet-again/post.html +26 -0
  80. data/doc/imported/0021-trying-ror-yet-again/source.lt3 +12 -0
  81. data/doc/imported/0023-doctor-sleep/metadata.txt +7 -0
  82. data/doc/imported/0023-doctor-sleep/post.html +63 -0
  83. data/doc/imported/0023-doctor-sleep/source.lt3 +44 -0
  84. data/doc/imported/0024-just-a-test/metadata.txt +7 -0
  85. data/doc/imported/0024-just-a-test/post.html +24 -0
  86. data/doc/imported/0024-just-a-test/source.lt3 +12 -0
  87. data/doc/imported/import_summary.txt +98 -0
  88. data/doc/livetext-informal-spec.txt +65 -0
  89. data/doc/myuserdoc/ch-0.lt3 +31 -0
  90. data/doc/myuserdoc/ch-1.lt3 +37 -0
  91. data/doc/myuserdoc/ch-10.lt3 +22 -0
  92. data/doc/myuserdoc/ch-2.lt3 +37 -0
  93. data/doc/myuserdoc/ch-3.lt3 +19 -0
  94. data/doc/myuserdoc/ch-4.lt3 +43 -0
  95. data/doc/myuserdoc/ch-5.lt3 +22 -0
  96. data/doc/myuserdoc/ch-6.lt3 +19 -0
  97. data/doc/myuserdoc/ch-7.lt3 +16 -0
  98. data/doc/myuserdoc/ch-8.lt3 +13 -0
  99. data/doc/myuserdoc/ch-9.lt3 +19 -0
  100. data/doc/myuserdoc/tweak.rb +18 -0
  101. data/doc/{userdoc-toc.txt → myuserdoc/userdoc-toc.txt} +27 -27
  102. data/doc/old-posts/0001-elixir-conf-2014.lt3 +24 -0
  103. data/doc/old-posts/0002-programmers-and-word-processing.lt3 +150 -0
  104. data/doc/old-posts/0003-how-to-turn-your-brain-sideways.lt3 +43 -0
  105. data/doc/old-posts/0004-upcoming-lone-star-ruby-conference.lt3 +26 -0
  106. data/doc/old-posts/0005-elixir-conf-2015-announced.lt3 +17 -0
  107. data/doc/old-posts/0006-ruby-for-dinosaurs.lt3 +30 -0
  108. data/doc/old-posts/0007-phoenix-isnt-rails.lt3 +90 -0
  109. data/doc/old-posts/0008-concerning-the-term-monkeypatching.lt3 +105 -0
  110. data/doc/old-posts/0009-announcement-coming-soon.lt3 +20 -0
  111. data/doc/old-posts/0010-immutable-data-ditching-the-wax-tablet.lt3 +142 -0
  112. data/doc/old-posts/0011-computer-science-as-a-lost-art.lt3 +117 -0
  113. data/doc/old-posts/0012-ruby-day-in-turin-italy.lt3 +26 -0
  114. data/doc/old-posts/0013-rubyday-was-a-success.lt3 +28 -0
  115. data/doc/old-posts/0014-working-on-the-blogging-software.lt3 +42 -0
  116. data/doc/old-posts/0015-ok-its-not-really-a-lost-art.lt3 +137 -0
  117. data/doc/old-posts/0016-an-in-operator-for-ruby.lt3 +142 -0
  118. data/doc/old-posts/0017-the-forgotten-mathematician.lt3 +129 -0
  119. data/doc/old-posts/0018-ruby-puns.lt3 +31 -0
  120. data/doc/old-posts/0019-custom-exceptions-via-metaprogramming.lt3 +116 -0
  121. data/doc/old-posts/0021-trying-ror-yet-again.lt3 +35 -0
  122. data/doc/old-posts/0023-doctor-sleep.lt3 +43 -0
  123. data/doc/old-posts/0024-just-a-test.lt3 +12 -0
  124. data/doc/old-posts/0025-trying-another-post.lt3 +12 -0
  125. data/doc/old-repo +1 -0
  126. data/doc/reddit_integration.md +2 -2
  127. data/doc/user.lt3 +0 -3
  128. data/lib/scriptorium/api.rb +1811 -78
  129. data/lib/scriptorium/banner_svg.rb +55 -68
  130. data/lib/scriptorium/contract.rb +3 -2
  131. data/lib/scriptorium/exceptions.rb +133 -102
  132. data/lib/scriptorium/helpers.rb +282 -82
  133. data/lib/scriptorium/post.rb +81 -17
  134. data/lib/scriptorium/reddit.rb +1 -1
  135. data/lib/scriptorium/repo.rb +478 -164
  136. data/lib/scriptorium/standard_files.rb +30 -396
  137. data/lib/scriptorium/support/common_js/clipboard.js +35 -0
  138. data/lib/scriptorium/support/common_js/content-loader.js +187 -0
  139. data/lib/scriptorium/support/common_js/navigation.js +52 -0
  140. data/lib/scriptorium/support/common_js/syntax-highlighting.js +27 -0
  141. data/lib/scriptorium/support/config/reddit_template.txt +17 -0
  142. data/{test/scriptorium-TEST-1754622690-146/views/sample → lib/scriptorium/support}/config/social.txt +1 -0
  143. data/lib/scriptorium/support/highlight/css.txt +2 -0
  144. data/lib/scriptorium/support/highlight/custom.css +119 -0
  145. data/lib/scriptorium/support/highlight/js.txt +1 -0
  146. data/lib/scriptorium/support/post_index/config.txt +15 -0
  147. data/lib/scriptorium/support/post_index/style.css +55 -0
  148. data/lib/scriptorium/support/templates/index_entry.lt3 +16 -0
  149. data/{test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 → lib/scriptorium/support/templates/initial_post.lt3} +5 -5
  150. data/lib/scriptorium/support/templates/post.lt3 +104 -0
  151. data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt → lib/scriptorium/support/theme/header.lt3} +1 -1
  152. data/lib/scriptorium/theme.rb +83 -70
  153. data/lib/scriptorium/version.rb +2 -2
  154. data/lib/scriptorium/view.rb +194 -149
  155. data/lib/scriptorium.rb +24 -1
  156. data/lib/skeleton.rb +4 -1
  157. data/scriptorium.gemspec +2 -1
  158. data/test/WEB_INTEGRATION_README.md +196 -0
  159. data/test/all +40 -0
  160. data/test/banner_svg/unit.rb +267 -35
  161. data/test/config/deployment.txt +5 -0
  162. data/test/integration/integration_test.rb +7 -7
  163. data/test/integration/preview_flow_test.rb +94 -0
  164. data/test/livetext_plugin_test.rb +453 -182
  165. data/test/manual/banner-tests/test01.html +82 -18
  166. data/test/manual/banner-tests/test02.html +82 -18
  167. data/test/manual/banner-tests/test03.html +82 -18
  168. data/test/manual/banner-tests/test04.html +89 -25
  169. data/test/manual/banner-tests/test05.html +89 -25
  170. data/test/manual/banner-tests/test06.html +89 -25
  171. data/test/manual/banner-tests/test07.html +89 -25
  172. data/test/manual/banner-tests/test08.html +82 -18
  173. data/test/manual/banner-tests/test09.html +82 -18
  174. data/test/manual/banner-tests/test10.html +82 -18
  175. data/test/manual/banner-tests/test11.html +82 -18
  176. data/test/manual/banner-tests/test12.html +82 -18
  177. data/test/manual/banner-tests/test13.html +82 -18
  178. data/test/manual/banner-tests/test14.html +82 -18
  179. data/test/manual/banner-tests/test15.html +82 -18
  180. data/test/manual/banner-tests/test16.html +82 -18
  181. data/test/manual/banner-tests/test17.html +82 -18
  182. data/test/manual/banner-tests/test18.html +90 -26
  183. data/test/manual/banner-tests/test19.html +90 -26
  184. data/test/manual/banner-tests/test20.html +90 -26
  185. data/test/manual/banner-tests/test21.html +90 -26
  186. data/test/manual/banner-tests/test22.html +90 -26
  187. data/test/manual/banner-tests/test23.html +90 -26
  188. data/test/manual/banner-tests/test24.html +90 -26
  189. data/test/manual/banner-tests/test25.html +89 -25
  190. data/test/manual/banner_environment.rb +15 -2
  191. data/test/manual/codemirror_demo.html +773 -0
  192. data/test/manual/create_posts_for_web.rb +114 -0
  193. data/test/manual/preview_manual_test.rb +129 -0
  194. data/test/manual/test_banner_features.rb +14 -14
  195. data/test/manual/test_banner_integration.rb +115 -0
  196. data/test/manual/test_banner_radial.rb +87 -0
  197. data/test/manual/test_syntax_highlighting.rb +60 -40
  198. data/test/support/preview_utils.rb +88 -0
  199. data/test/test_gem_assets.rb +48 -0
  200. data/test/test_helpers.rb +10 -0
  201. data/test/tui_editor_integration_test.rb +15 -15
  202. data/test/tui_integration_test.rb +687 -441
  203. data/test/unit/api.rb +757 -37
  204. data/test/unit/asset_management.rb +195 -221
  205. data/test/unit/backup_test.rb +451 -0
  206. data/test/unit/contract_test.rb +1 -23
  207. data/test/unit/core.rb +415 -61
  208. data/test/unit/deploy_config_test.rb +248 -0
  209. data/test/unit/deploy_test.rb +312 -21
  210. data/test/unit/edit_post_test.rb +168 -0
  211. data/test/unit/gem_asset_management.rb +36 -42
  212. data/test/unit/livetext_basic.rb +23 -35
  213. data/test/unit/livetext_compatibility.rb +7 -14
  214. data/test/unit/parse_cmd_test.rb +260 -0
  215. data/test/unit/{symlink_test.rb → permalink_copy_test.rb} +47 -49
  216. data/test/unit/post.rb +91 -26
  217. data/test/unit/post_index_config_test.rb +258 -0
  218. data/test/unit/post_state_helpers_test.rb +137 -0
  219. data/test/unit/read_commented_file_test.rb +8 -6
  220. data/test/unit/repo.rb +75 -54
  221. data/test/unit/social_test.rb +41 -44
  222. data/test/unit/syntax_highlighting.rb +70 -0
  223. data/test/unit/theme_management_test.rb +91 -0
  224. data/test/unit/view.rb +79 -12
  225. data/test/unit/widgets.rb +8 -8
  226. data/test/web_integration_test.rb +231 -0
  227. data/test/web_test_helper.rb +218 -0
  228. data/test/web_workflow_test.rb +527 -0
  229. data/ui/tui/bin/scriptorium +885 -415
  230. data/ui/web/app/app.rb +1398 -176
  231. data/ui/web/app/assets/livetext_mode.js +244 -0
  232. data/ui/web/app/error_helpers.rb +16 -16
  233. data/ui/web/app/views/advanced_config.erb +8 -2
  234. data/ui/web/app/views/asset_management.erb +56 -0
  235. data/ui/web/app/views/backup_management.erb +238 -0
  236. data/ui/web/app/views/config_widget.erb +232 -0
  237. data/ui/web/app/views/dashboard.erb +64 -72
  238. data/ui/web/app/views/deploy_config.erb +3 -0
  239. data/ui/web/app/views/edit_pages.erb +170 -2
  240. data/ui/web/app/views/edit_post.erb +130 -9
  241. data/ui/web/app/views/edit_theme.erb +73 -0
  242. data/ui/web/app/views/edit_theme_file.erb +74 -0
  243. data/ui/web/app/views/theme_management.erb +130 -0
  244. data/ui/web/app/views/view_dashboard.erb +666 -25
  245. data/ui/web/app/views/widgets.erb +249 -0
  246. data/ui/web/bin/scriptorium-web +35 -24
  247. data/ui/web/tmp/timing.log +17 -0
  248. data/ui/web/tmp/web_server.log +0 -5
  249. metadata +190 -116
  250. data/assets/back-icon.png +0 -0
  251. data/assets/icons/facebook.svg +0 -1
  252. data/assets/icons/github.svg +0 -1
  253. data/assets/icons/instagram.svg +0 -1
  254. data/assets/icons/reddit.svg +0 -1
  255. data/assets/icons/x.svg +0 -1
  256. data/assets/icons/youtube.svg +0 -1
  257. data/bin/scriptorium +0 -1511
  258. data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +0 -34
  259. data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +0 -50
  260. data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +0 -73
  261. data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +0 -70
  262. data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +0 -110
  263. data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +0 -73
  264. data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +0 -124
  265. data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +0 -46
  266. data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +0 -97
  267. data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +0 -211
  268. data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +0 -141
  269. data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +0 -211
  270. data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +0 -134
  271. data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +0 -41
  272. data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +0 -49
  273. data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +0 -46
  274. data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +0 -41
  275. data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +0 -41
  276. data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +0 -256
  277. data/lib/scriptorium/syntax_highlighter.rb +0 -234
  278. data/test/manual/deploy_symlink_demo.rb +0 -142
  279. data/test/manual/symlink_demo.rb +0 -117
  280. data/test/manual/test2.rb +0 -12
  281. data/test/manual/test_banner_from_file.rb +0 -150
  282. data/test/manual/test_banner_in_header.rb +0 -35
  283. data/test/manual/test_code_highlighting.rb +0 -68
  284. data/test/manual/test_complex_header.rb +0 -74
  285. data/test/manual/test_empty_header.rb +0 -32
  286. data/test/manual/test_radial_custom.rb +0 -58
  287. data/test/manual/test_radial_large_radius.rb +0 -52
  288. data/test/manual/test_svg_debug.rb +0 -47
  289. data/test/pages-demo/config/currentview.txt +0 -1
  290. data/test/pages-demo/views/demo/config/common.js +0 -57
  291. data/test/pages-demo/views/demo/config/footer.txt +0 -1
  292. data/test/pages-demo/views/demo/config/global-head.txt +0 -8
  293. data/test/pages-demo/views/demo/config/header.txt +0 -1
  294. data/test/pages-demo/views/demo/config/layout.txt +0 -1
  295. data/test/pages-demo/views/demo/config/left.txt +0 -1
  296. data/test/pages-demo/views/demo/config/main.txt +0 -1
  297. data/test/pages-demo/views/demo/config/right.txt +0 -1
  298. data/test/pages-demo/views/demo/config.txt +0 -3
  299. data/test/pages-demo/views/demo/output/panes/footer.html +0 -1
  300. data/test/pages-demo/views/demo/output/panes/header.html +0 -1
  301. data/test/pages-demo/views/demo/output/panes/left.html +0 -1
  302. data/test/pages-demo/views/demo/output/panes/main.html +0 -1
  303. data/test/pages-demo/views/demo/output/panes/right.html +0 -1
  304. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +0 -5
  305. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +0 -4
  306. data/test/scriptorium-TEST-1754622690-146/config/common.js +0 -57
  307. data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +0 -1
  308. data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +0 -9
  309. data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +0 -1
  310. data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +0 -4
  311. data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +0 -3
  312. data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +0 -8
  313. data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +0 -6
  314. data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +0 -1
  315. data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +0 -1
  316. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +0 -1
  317. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +0 -1
  318. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +0 -14
  319. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +0 -13
  320. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +0 -1
  321. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +0 -5
  322. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +0 -4
  323. data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +0 -57
  324. data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +0 -5
  325. data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +0 -2
  326. data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +0 -9
  327. data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +0 -4
  328. data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +0 -5
  329. data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +0 -3
  330. data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +0 -5
  331. data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +0 -3
  332. data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +0 -7
  333. data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +0 -3
  334. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +0 -3
  335. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +0 -3
  336. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +0 -3
  337. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +0 -3
  338. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +0 -3
  339. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +0 -1
  340. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +0 -1
  341. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +0 -1
  342. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +0 -1
  343. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +0 -1
  344. data/ui/web/tmp/web_server.pid +0 -1
  345. /data/{test/pages-demo/views/demo/config/bootstrap_css.txt → lib/scriptorium/support/bootstrap/css.txt} +0 -0
  346. /data/{test/pages-demo/views/demo/config/bootstrap_js.txt → lib/scriptorium/support/bootstrap/js.txt} +0 -0
  347. /data/{test/scriptorium-TEST-1754622690-146/views/sample → lib/scriptorium/support}/config/reddit.txt +0 -0
  348. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout → lib/scriptorium/support/templates}/layout.txt +0 -0
  349. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt → lib/scriptorium/support/theme/footer.lt3} +0 -0
  350. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt → lib/scriptorium/support/theme/left.lt3} +0 -0
  351. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt → lib/scriptorium/support/theme/main.lt3} +0 -0
  352. /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt → lib/scriptorium/support/theme/right.lt3} +0 -0
  353. /data/test/manual/banner-tests/{config.txt → svg.txt} +0 -0
  354. /data/test/manual/{test6.rb → test_advanced_widgets.rb} +0 -0
  355. /data/test/manual/{test1.rb → test_basic_posts.rb} +0 -0
  356. /data/test/manual/{test4.rb → test_layout_widgets.rb} +0 -0
  357. /data/test/manual/{test5.rb → test_pagination.rb} +0 -0
  358. /data/test/manual/{test3.rb → test_random_posts.rb} +0 -0
@@ -0,0 +1,168 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../../lib/scriptorium'
3
+ require_relative '../test_helpers'
4
+
5
+ class TestEditPost < Minitest::Test
6
+ include TestHelpers
7
+
8
+ def setup
9
+ @test_dir = "test/scriptorium-TEST"
10
+ FileUtils.rm_rf(@test_dir) if Dir.exist?(@test_dir)
11
+
12
+ @api = Scriptorium::API.new(testmode: true)
13
+ @api.create_repo(@test_dir)
14
+ @api.open_repo(@test_dir)
15
+ end
16
+
17
+ def teardown
18
+ FileUtils.rm_rf(@test_dir) if Dir.exist?(@test_dir)
19
+ end
20
+
21
+ def test_001_edit_post_no_changes
22
+ @api.create_view("test_view", "Test View")
23
+ post = @api.create_post("Test Post", "Test body")
24
+
25
+ # Initially unpublished and undeployed
26
+ refute @api.post_published?(post.id)
27
+ refute @api.post_deployed?(post.id)
28
+
29
+ # Mock the editor by not changing the file content
30
+ # (file content remains the same, so checksum will be identical)
31
+
32
+ # Call edit_post with mock (should detect no changes)
33
+ @api.edit_post(post.id, mock: true)
34
+
35
+ # State should remain unchanged
36
+ refute @api.post_published?(post.id)
37
+ refute @api.post_deployed?(post.id)
38
+ end
39
+
40
+ def test_002_edit_post_with_changes
41
+ @api.create_view("test_view", "Test View")
42
+ post = @api.create_post("Test Post", "Test body")
43
+
44
+ # Initially unpublished and undeployed
45
+ refute @api.post_published?(post.id)
46
+ refute @api.post_deployed?(post.id)
47
+
48
+ # Mock the editor by simulating a different checksum
49
+ @api.edit_post(post.id, mock: [:checksum, "different_checksum_for_testing"])
50
+
51
+ # State should remain unchanged since it was already unpublished/undeployed
52
+ refute @api.post_published?(post.id)
53
+ refute @api.post_deployed?(post.id)
54
+ end
55
+
56
+ def test_003_edit_post_published_post
57
+ @api.create_view("test_view", "Test View")
58
+ @api.repo.instance_variable_set(:@current_view, @api.repo.lookup_view("test_view"))
59
+
60
+ post = @api.create_post("Test Post", "Test body")
61
+
62
+ # Publish the post
63
+ @api.publish_post(post.id)
64
+ assert @api.post_published?(post.id)
65
+
66
+ # Mock the editor by simulating a different checksum
67
+ @api.edit_post(post.id, mock: [:checksum, "different_checksum_for_testing"])
68
+
69
+ # Post should now be unpublished
70
+ refute @api.post_published?(post.id)
71
+ end
72
+
73
+ def test_004_edit_post_deployed_post
74
+ @api.create_view("test_view", "Test View")
75
+ @api.repo.instance_variable_set(:@current_view, @api.repo.lookup_view("test_view"))
76
+
77
+ post = @api.create_post("Test Post", "Test body")
78
+
79
+ # Publish and deploy the post
80
+ @api.publish_post(post.id)
81
+ @api.mark_post_deployed(post.id)
82
+ assert @api.post_published?(post.id)
83
+ assert @api.post_deployed?(post.id)
84
+
85
+ # Mock the editor by simulating a different checksum
86
+ @api.edit_post(post.id, mock: [:checksum, "different_checksum_for_testing"])
87
+
88
+ # Post should now be unpublished and undeployed
89
+ refute @api.post_published?(post.id)
90
+ refute @api.post_deployed?(post.id)
91
+ end
92
+
93
+ def test_005_edit_post_multiple_views
94
+ @api.create_view("test_view", "Test View")
95
+ @api.create_view("other_view", "Other View")
96
+
97
+ post = @api.create_post("Test Post", "Test body", views: "test_view other_view")
98
+
99
+ # Publish in both views
100
+ @api.publish_post(post.id, "test_view")
101
+ @api.publish_post(post.id, "other_view")
102
+ @api.mark_post_deployed(post.id, "test_view")
103
+ @api.mark_post_deployed(post.id, "other_view")
104
+
105
+ assert @api.post_published?(post.id, "test_view")
106
+ assert @api.post_published?(post.id, "other_view")
107
+ assert @api.post_deployed?(post.id, "test_view")
108
+ assert @api.post_deployed?(post.id, "other_view")
109
+
110
+ # Mock the editor by simulating a different checksum
111
+ @api.edit_post(post.id, mock: [:checksum, "different_checksum_for_testing"])
112
+
113
+ # Post should now be unpublished and undeployed in both views
114
+
115
+ refute @api.post_published?(post.id, "test_view")
116
+ refute @api.post_published?(post.id, "other_view")
117
+ refute @api.post_deployed?(post.id, "test_view")
118
+ refute @api.post_deployed?(post.id, "other_view")
119
+ end
120
+
121
+ def test_006_edit_post_timestamp_change_only
122
+ @api.create_view("test_view", "Test View")
123
+ post = @api.create_post("Test Post", "Test body")
124
+
125
+ # Initially unpublished and undeployed
126
+ refute @api.post_published?(post.id)
127
+ refute @api.post_deployed?(post.id)
128
+
129
+ # Mock the editor by simulating no content changes (same checksum)
130
+ @api.edit_post(post.id, mock: [:checksum, Digest::MD5.file("#{@test_dir}/posts/#{post.num}/source.lt3").hexdigest])
131
+
132
+ # State should remain unchanged since content didn't change
133
+ refute @api.post_published?(post.id)
134
+ refute @api.post_deployed?(post.id)
135
+ end
136
+
137
+ def test_007_edit_post_missing_source
138
+ @api.create_view("test_view", "Test View")
139
+ post = @api.create_post("Test Post", "Test body")
140
+
141
+ # Remove source.lt3 to test error handling
142
+ source_path = "#{@test_dir}/posts/#{post.num}/source.lt3"
143
+ File.delete(source_path) if File.exist?(source_path)
144
+
145
+ # Ensure body.html exists
146
+ body_path = "#{@test_dir}/posts/#{post.num}/body.html"
147
+ assert File.exist?(body_path)
148
+
149
+ # Call edit_post should raise error since source.lt3 is missing
150
+ assert_raises(RuntimeError) do
151
+ @api.edit_post(post.id, mock: true)
152
+ end
153
+ end
154
+
155
+ def test_008_edit_post_deleted_post
156
+ @api.create_view("test_view", "Test View")
157
+ post = @api.create_post("Test Post", "Test body")
158
+
159
+ # Delete the post
160
+ @api.delete_post(post.id)
161
+ assert @api.post_deleted?(post.id)
162
+
163
+ # Try to edit deleted post
164
+ assert_raises(PostDeleted) do
165
+ @api.edit_post(post.id, mock: true)
166
+ end
167
+ end
168
+ end
@@ -46,6 +46,8 @@ class TestGemAssetManagement < Minitest::Test
46
46
  live = Livetext.customize(mix: "lt3scriptor", call: ".nopara", vars: @vars)
47
47
  body, vars = live.process(file: temp_file)
48
48
  vars = vars.to_h
49
+ # Strip paragraph tags for asset function tests
50
+ body = body.gsub(/^<p>\n?(.*?)\n?<\/p>$/m, '\1')
49
51
  return { vars: vars, body: body }
50
52
  rescue => e
51
53
  puts "Livetext error: #{e.message}"
@@ -59,11 +61,11 @@ class TestGemAssetManagement < Minitest::Test
59
61
 
60
62
  def test_001_gem_asset_discovery_in_development
61
63
  # Test that gem assets are found in development environment
62
- content = "$$asset[icons/ui/back-arrow.svg]"
64
+ content = "$$asset[icons/ui/back.png]"
63
65
  result = process_livetext(content)
64
66
 
65
67
  # Should find gem asset and return correct path
66
- assert_equal "assets/icons/ui/back-arrow.svg", result[:body].strip
68
+ assert_equal "assets/icons/ui/back.png", result[:body].strip
67
69
  end
68
70
 
69
71
  def test_002_gem_asset_discovery_in_production
@@ -82,7 +84,7 @@ class TestGemAssetManagement < Minitest::Test
82
84
  # Check for specific theme assets
83
85
  expected_theme_assets = [
84
86
  "standard/favicon.svg",
85
- "icons/ui/back-arrow.svg"
87
+ "icons/ui/back.png"
86
88
  ]
87
89
 
88
90
  expected_theme_assets.each do |asset|
@@ -111,57 +113,55 @@ class TestGemAssetManagement < Minitest::Test
111
113
 
112
114
  def test_005_gem_assets_in_search_hierarchy
113
115
  # Test that gem assets are found in the correct priority order
114
- content = "$$asset[icons/ui/back-arrow.svg]"
116
+ content = "$$asset[icons/ui/back.png]"
115
117
  result = process_livetext(content)
116
118
 
117
119
  # Should find gem asset and return correct path
118
- assert_equal "assets/icons/ui/back-arrow.svg", result[:body].strip
120
+ assert_equal "assets/icons/ui/back.png", result[:body].strip
119
121
  end
120
122
 
121
123
  def test_006_gem_assets_override_by_user_assets
122
124
  # Test that user assets override gem assets
123
125
  # Create a user asset with the same name as a gem asset
124
- user_asset_path = @repo.root/"assets"/"icons"/"ui"/"back-arrow.svg"
126
+ user_asset_path = @repo.root/"assets"/"icons"/"ui"/"back.png"
125
127
  FileUtils.mkdir_p(File.dirname(user_asset_path))
126
- File.write(user_asset_path, "User asset content")
128
+ write_file(user_asset_path, "User asset content")
127
129
 
128
- content = "$$asset[icons/ui/back-arrow.svg]"
130
+ content = "$$asset[icons/ui/back.png]"
129
131
  result = process_livetext(content)
130
132
 
131
133
  # Should find user asset first (higher priority)
132
- assert_equal "assets/icons/ui/back-arrow.svg", result[:body].strip
134
+ assert_equal "assets/icons/ui/back.png", result[:body].strip
133
135
  end
134
136
 
135
137
  def test_007_gem_asset_path_resolution
136
138
  # Test that gem asset paths are resolved correctly
137
- begin
138
- gem_spec = Gem.loaded_specs['scriptorium']
139
- if gem_spec
140
- # Production environment - gem is installed
141
- gem_assets_dir = "#{gem_spec.full_gem_path}/assets"
142
- assert Dir.exist?(gem_assets_dir), "Gem assets directory should exist"
143
-
144
- # Check for specific gem assets
145
- expected_gem_assets = [
146
- "icons/ui/back-arrow.svg",
147
- "samples/placeholder.svg",
148
- "themes/standard/favicon.svg"
149
- ]
150
-
151
- expected_gem_assets.each do |asset|
152
- asset_path = "#{gem_assets_dir}/#{asset}"
153
- assert File.exist?(asset_path), "Gem asset #{asset} should exist"
154
- end
155
- else
156
- # Development environment - use working path
157
- dev_assets_dir = File.expand_path("assets")
158
- assert Dir.exist?(dev_assets_dir), "Development assets directory should exist"
139
+ gem_spec = Gem.loaded_specs['scriptorium']
140
+ if gem_spec
141
+ # Production environment - gem is installed
142
+ gem_assets_dir = "#{gem_spec.full_gem_path}/assets"
143
+ assert Dir.exist?(gem_assets_dir), "Gem assets directory should exist"
144
+
145
+ # Check for specific gem assets
146
+ expected_gem_assets = [
147
+ "icons/ui/back.png",
148
+ "samples/placeholder.svg",
149
+ "themes/standard/favicon.svg"
150
+ ]
151
+
152
+ expected_gem_assets.each do |asset|
153
+ asset_path = "#{gem_assets_dir}/#{asset}"
154
+ assert File.exist?(asset_path), "Gem asset #{asset} should exist"
159
155
  end
160
- rescue => e
161
- # If gem lookup fails, that's expected in development
162
- dev_assets_dir = File.expand_path("assets")
156
+ else
157
+ # Development environment - use working path
158
+ dev_assets_dir = File.expand_path("assets")
163
159
  assert Dir.exist?(dev_assets_dir), "Development assets directory should exist"
164
160
  end
161
+ rescue => e
162
+ # If gem lookup fails, that's expected in development
163
+ dev_assets_dir = File.expand_path("assets")
164
+ assert Dir.exist?(dev_assets_dir), "Development assets directory should exist"
165
165
  end
166
166
 
167
167
  def test_008_gem_assets_not_copied_to_output
@@ -170,20 +170,14 @@ class TestGemAssetManagement < Minitest::Test
170
170
  output_assets_dir = @repo.root/"views"/"gem_asset_test_view"/"output"/"assets"
171
171
 
172
172
  # Generate a post that references gem assets
173
- draft_body = "$$asset[icons/ui/back-arrow.svg]"
173
+ draft_body = "$$asset[icons/ui/back.png]"
174
174
  name = @repo.create_draft(title: "Gem Asset Test", views: ["gem_asset_test_view"], body: draft_body)
175
175
  num = @repo.finish_draft(name)
176
176
  @repo.generate_post(num)
177
177
 
178
178
  # Check that gem assets are not copied to output
179
- gem_asset_in_output = output_assets_dir/"icons"/"ui"/"back-arrow.svg"
179
+ gem_asset_in_output = output_assets_dir/"icons"/"ui"/"back.png"
180
180
  refute File.exist?(gem_asset_in_output), "Gem assets should not be copied to output"
181
181
  end
182
182
 
183
- private
184
-
185
- def write_file(path, content)
186
- FileUtils.mkdir_p(File.dirname(path)) unless Dir.exist?(File.dirname(path))
187
- File.write(path, content)
188
- end
189
183
  end
@@ -9,15 +9,12 @@ class TestLivetextBasic < Minitest::Test
9
9
  # Test basic Livetext without any plugins
10
10
  content = "Simple text content"
11
11
 
12
- begin
13
- live = Livetext.customize(call: ".nopara")
14
- body, vars = live.process(text: content)
15
- assert_equal "Simple text content", body.strip
16
- assert vars.is_a?(Hash)
17
- puts "Basic Livetext processing works"
18
- rescue => e
19
- flunk "Basic Livetext processing failed: #{e.message}"
20
- end
12
+ live = Livetext.customize(call: ".nopara")
13
+ body, vars = live.process(text: content)
14
+ assert_equal "<p>\nSimple text content\n</p>", body.strip
15
+ assert vars.is_a?(Hash)
16
+ rescue => e
17
+ flunk "Basic Livetext processing failed: #{e.message}"
21
18
  end
22
19
 
23
20
  def test_002_livetext_with_simple_dot_commands
@@ -29,41 +26,32 @@ class TestLivetextBasic < Minitest::Test
29
26
  This is the body.
30
27
  CONTENT
31
28
 
32
- begin
33
- live = Livetext.customize(mix: "lt3scriptor", call: ".nopara")
34
- body, vars = live.process(text: content)
35
- assert_includes body, "This is the body"
36
- assert vars.is_a?(Hash)
37
- puts "Livetext with dot commands works"
38
- rescue => e
39
- flunk "Livetext with dot commands failed: #{e.message}"
40
- end
29
+ live = Livetext.customize(mix: "lt3scriptor", call: ".nopara")
30
+ body, vars = live.process(text: content)
31
+ assert_includes body, "This is the body"
32
+ assert vars.is_a?(Hash)
33
+ rescue => e
34
+ flunk "Livetext with dot commands failed: #{e.message}"
41
35
  end
42
36
 
43
37
  def test_003_livetext_plugin_loading
44
38
  # Test if the plugin can be loaded without processing
45
- begin
46
- live = Livetext.customize(mix: "lt3scriptor")
47
- assert live
48
- puts "Plugin loads successfully"
49
- rescue => e
50
- flunk "Plugin loading failed: #{e.message}"
51
- end
39
+ live = Livetext.customize(mix: "lt3scriptor")
40
+ assert live
41
+ rescue => e
42
+ flunk "Plugin loading failed: #{e.message}"
52
43
  end
53
44
 
54
45
  def test_004_livetext_plugin_processing_simple
55
46
  # Test if the plugin can process very simple content
56
47
  content = "Simple content"
57
48
 
58
- begin
59
- live = Livetext.customize(mix: "lt3scriptor", call: ".nopara")
60
- body, vars = live.process(text: content)
61
- assert body.is_a?(String)
62
- puts " Plugin processes simple content: #{body}"
63
- rescue => e
64
- puts "Plugin processing failed: #{e.message}"
65
- puts e.backtrace.first(3)
66
- skip "Plugin processing needs to be fixed"
67
- end
49
+ live = Livetext.customize(mix: "lt3scriptor", call: ".nopara")
50
+ body, vars = live.process(text: content)
51
+ assert body.is_a?(String)
52
+ rescue => e
53
+ puts " Plugin processing failed: #{e.message}"
54
+ puts e.backtrace.first(3)
55
+ skip "Plugin processing needs to be fixed"
68
56
  end
69
57
  end
@@ -13,9 +13,8 @@ class TestLivetextCompatibility < Minitest::Test
13
13
  live = Livetext.customize(call: ".nopara")
14
14
  body, vars = live.process(text: content)
15
15
  vars = vars.to_h
16
- assert_equal "Simple text content", body.strip
16
+ assert_equal "<p>\nSimple text content\n</p>", body.strip
17
17
  assert vars.is_a?(Hash)
18
- puts "✓ Basic Livetext processing works"
19
18
  rescue => e
20
19
  flunk "Basic Livetext processing failed: #{e.message}"
21
20
  end
@@ -31,12 +30,11 @@ class TestLivetextCompatibility < Minitest::Test
31
30
  CONTENT
32
31
 
33
32
  begin
34
- live = Livetext.customize(call: ".nopara")
33
+ live = Livetext.customize(mix: "lt3scriptor", call: ".nopara")
35
34
  body, vars = live.process(text: content)
36
35
  vars = vars.to_h
37
36
  assert_includes body, "This is the body"
38
37
  assert vars.is_a?(Hash)
39
- puts "✓ Livetext with dot commands works"
40
38
  rescue => e
41
39
  flunk "Livetext with dot commands failed: #{e.message}"
42
40
  end
@@ -44,13 +42,10 @@ class TestLivetextCompatibility < Minitest::Test
44
42
 
45
43
  def test_003_livetext_plugin_loading
46
44
  # Test if the plugin can be loaded without processing
47
- begin
48
- live = Livetext.customize(mix: "lt3scriptor")
49
- assert live
50
- puts "Plugin loaded successfully"
51
- rescue => e
52
- flunk "Plugin loading failed: #{e.message}"
53
- end
45
+ live = Livetext.customize(mix: "lt3scriptor")
46
+ assert live
47
+ rescue => e
48
+ flunk "Plugin loading failed: #{e.message}"
54
49
  end
55
50
 
56
51
  def test_004_livetext_plugin_processing
@@ -62,7 +57,6 @@ class TestLivetextCompatibility < Minitest::Test
62
57
  body, vars = live.process(text: content)
63
58
  vars = vars.to_h
64
59
  assert body.is_a?(String)
65
- puts "✓ Plugin processing succeeded: #{body}"
66
60
  rescue => e
67
61
  puts "✗ Plugin processing failed: #{e.message}"
68
62
  puts e.backtrace.first(3)
@@ -76,11 +70,10 @@ class TestLivetextCompatibility < Minitest::Test
76
70
 
77
71
  begin
78
72
  live = Livetext.customize(call: ".nopara")
79
- text, vars = live.process(content)
73
+ text, vars = live.process(text: content)
80
74
  vars = vars.to_h
81
75
  assert text.is_a?(String)
82
76
  assert vars.is_a?(Hash)
83
- puts "✓ Old Livetext API works"
84
77
  rescue => e
85
78
  puts "✗ Old Livetext API failed: #{e.message}"
86
79
  skip "Old API needs to be fixed"