scriptorium 0.0.3 → 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 (353) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +324 -0
  3. data/README.md +3155 -1
  4. data/assets/.DS_Store +0 -0
  5. data/assets/README.md +44 -0
  6. data/assets/icons/social/reddit.png +0 -0
  7. data/assets/icons/social/x-logo.png +0 -0
  8. data/assets/icons/ui/.DS_Store +0 -0
  9. data/assets/icons/ui/back.png +0 -0
  10. data/assets/icons/ui/copy.png +0 -0
  11. data/assets/icons/ui/down.png +0 -0
  12. data/assets/icons/ui/end.png +0 -0
  13. data/assets/icons/ui/exit.png +0 -0
  14. data/assets/icons/ui/foo +10 -0
  15. data/assets/icons/ui/home.png +0 -0
  16. data/assets/icons/ui/left.png +0 -0
  17. data/assets/icons/ui/next.png +0 -0
  18. data/assets/icons/ui/right.png +0 -0
  19. data/assets/icons/ui/start.png +0 -0
  20. data/assets/icons/ui/up.png +0 -0
  21. data/assets/imagenotfound.jpg +0 -0
  22. data/assets/samples/placeholder.svg +9 -0
  23. data/assets/themes/standard/favicon.svg +6 -0
  24. data/bin/sblog +84 -5
  25. data/bin/scriptorium +1 -0
  26. data/doc/README.txt +6 -0
  27. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +94 -0
  28. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +2 -0
  29. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +45 -0
  30. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
  31. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
  32. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
  33. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +35 -0
  34. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +27 -0
  35. data/doc/anti-amnesia/20250807-213025.md +116 -0
  36. data/doc/anti-amnesia/20250901-211714-codemirror-integration-and-web-tests.md +172 -0
  37. data/doc/anti-amnesia/20250902-002402-backup-restore-system.md +126 -0
  38. data/doc/anti-amnesia/20250907-203339-backup-metadata-implementation.md +66 -0
  39. data/doc/banner_svg_config.md +114 -0
  40. data/doc/contrib.lt3 +8 -0
  41. data/doc/dependencies.md +281 -0
  42. data/doc/hacker.lt3 +5 -0
  43. data/doc/imported/0001-elixir-conf-2014/metadata.txt +7 -0
  44. data/doc/imported/0001-elixir-conf-2014/post.html +37 -0
  45. data/doc/imported/0001-elixir-conf-2014/source.lt3 +22 -0
  46. data/doc/imported/0002-programmers-and-word-processing/metadata.txt +7 -0
  47. data/doc/imported/0002-programmers-and-word-processing/post.html +192 -0
  48. data/doc/imported/0002-programmers-and-word-processing/source.lt3 +146 -0
  49. data/doc/imported/0003-how-to-turn-your-brain-sideways/metadata.txt +7 -0
  50. data/doc/imported/0003-how-to-turn-your-brain-sideways/post.html +60 -0
  51. data/doc/imported/0003-how-to-turn-your-brain-sideways/source.lt3 +40 -0
  52. data/doc/imported/0004-upcoming-lone-star-ruby-conference/metadata.txt +7 -0
  53. data/doc/imported/0004-upcoming-lone-star-ruby-conference/post.html +42 -0
  54. data/doc/imported/0004-upcoming-lone-star-ruby-conference/source.lt3 +24 -0
  55. data/doc/imported/0005-elixir-conf-2015-announced/metadata.txt +7 -0
  56. data/doc/imported/0005-elixir-conf-2015-announced/post.html +30 -0
  57. data/doc/imported/0005-elixir-conf-2015-announced/source.lt3 +16 -0
  58. data/doc/imported/0006-ruby-for-dinosaurs/metadata.txt +7 -0
  59. data/doc/imported/0006-ruby-for-dinosaurs/post.html +43 -0
  60. data/doc/imported/0006-ruby-for-dinosaurs/source.lt3 +27 -0
  61. data/doc/imported/0007-phoenix-isnt-rails/metadata.txt +7 -0
  62. data/doc/imported/0007-phoenix-isnt-rails/post.html +116 -0
  63. data/doc/imported/0007-phoenix-isnt-rails/source.lt3 +87 -0
  64. data/doc/imported/0008-concerning-the-term-monkeypatching/metadata.txt +7 -0
  65. data/doc/imported/0008-concerning-the-term-monkeypatching/post.html +129 -0
  66. data/doc/imported/0008-concerning-the-term-monkeypatching/source.lt3 +92 -0
  67. data/doc/imported/0009-announcement-coming-soon/metadata.txt +7 -0
  68. data/doc/imported/0009-announcement-coming-soon/post.html +33 -0
  69. data/doc/imported/0009-announcement-coming-soon/source.lt3 +19 -0
  70. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/metadata.txt +7 -0
  71. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/post.html +175 -0
  72. data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/source.lt3 +139 -0
  73. data/doc/imported/0011-computer-science-as-a-lost-art/metadata.txt +7 -0
  74. data/doc/imported/0011-computer-science-as-a-lost-art/post.html +139 -0
  75. data/doc/imported/0011-computer-science-as-a-lost-art/source.lt3 +104 -0
  76. data/doc/imported/0012-ruby-day-in-turin-italy/metadata.txt +7 -0
  77. data/doc/imported/0012-ruby-day-in-turin-italy/post.html +42 -0
  78. data/doc/imported/0012-ruby-day-in-turin-italy/source.lt3 +24 -0
  79. data/doc/imported/0013-rubyday-was-a-success/metadata.txt +7 -0
  80. data/doc/imported/0013-rubyday-was-a-success/post.html +44 -0
  81. data/doc/imported/0013-rubyday-was-a-success/source.lt3 +27 -0
  82. data/doc/imported/0014-working-on-the-blogging-software/metadata.txt +7 -0
  83. data/doc/imported/0014-working-on-the-blogging-software/post.html +63 -0
  84. data/doc/imported/0014-working-on-the-blogging-software/source.lt3 +41 -0
  85. data/doc/imported/0015-ok-its-not-really-a-lost-art/metadata.txt +7 -0
  86. data/doc/imported/0015-ok-its-not-really-a-lost-art/post.html +172 -0
  87. data/doc/imported/0015-ok-its-not-really-a-lost-art/source.lt3 +134 -0
  88. data/doc/imported/0016-an-in-operator-for-ruby/metadata.txt +7 -0
  89. data/doc/imported/0016-an-in-operator-for-ruby/post.html +155 -0
  90. data/doc/imported/0016-an-in-operator-for-ruby/source.lt3 +106 -0
  91. data/doc/imported/0017-the-forgotten-mathematician/metadata.txt +7 -0
  92. data/doc/imported/0017-the-forgotten-mathematician/post.html +161 -0
  93. data/doc/imported/0017-the-forgotten-mathematician/source.lt3 +119 -0
  94. data/doc/imported/0018-ruby-puns/metadata.txt +7 -0
  95. data/doc/imported/0018-ruby-puns/post.html +46 -0
  96. data/doc/imported/0018-ruby-puns/source.lt3 +28 -0
  97. data/doc/imported/0019-custom-exceptions-via-metaprogramming/metadata.txt +7 -0
  98. data/doc/imported/0019-custom-exceptions-via-metaprogramming/post.html +138 -0
  99. data/doc/imported/0019-custom-exceptions-via-metaprogramming/source.lt3 +101 -0
  100. data/doc/imported/0020-fffff/metadata.txt +7 -0
  101. data/doc/imported/0020-fffff/post.html +24 -0
  102. data/doc/imported/0020-fffff/source.lt3 +12 -0
  103. data/doc/imported/0021-trying-ror-yet-again/metadata.txt +7 -0
  104. data/doc/imported/0021-trying-ror-yet-again/post.html +26 -0
  105. data/doc/imported/0021-trying-ror-yet-again/source.lt3 +12 -0
  106. data/doc/imported/0023-doctor-sleep/metadata.txt +7 -0
  107. data/doc/imported/0023-doctor-sleep/post.html +63 -0
  108. data/doc/imported/0023-doctor-sleep/source.lt3 +44 -0
  109. data/doc/imported/0024-just-a-test/metadata.txt +7 -0
  110. data/doc/imported/0024-just-a-test/post.html +24 -0
  111. data/doc/imported/0024-just-a-test/source.lt3 +12 -0
  112. data/doc/imported/import_summary.txt +98 -0
  113. data/doc/livetext-informal-spec.txt +65 -0
  114. data/doc/myuserdoc/ch-0.lt3 +31 -0
  115. data/doc/myuserdoc/ch-1.lt3 +37 -0
  116. data/doc/myuserdoc/ch-10.lt3 +22 -0
  117. data/doc/myuserdoc/ch-2.lt3 +37 -0
  118. data/doc/myuserdoc/ch-3.lt3 +19 -0
  119. data/doc/myuserdoc/ch-4.lt3 +43 -0
  120. data/doc/myuserdoc/ch-5.lt3 +22 -0
  121. data/doc/myuserdoc/ch-6.lt3 +19 -0
  122. data/doc/myuserdoc/ch-7.lt3 +16 -0
  123. data/doc/myuserdoc/ch-8.lt3 +13 -0
  124. data/doc/myuserdoc/ch-9.lt3 +19 -0
  125. data/doc/myuserdoc/tweak.rb +18 -0
  126. data/doc/myuserdoc/userdoc-toc.txt +88 -0
  127. data/doc/old-posts/0001-elixir-conf-2014.lt3 +24 -0
  128. data/doc/old-posts/0002-programmers-and-word-processing.lt3 +150 -0
  129. data/doc/old-posts/0003-how-to-turn-your-brain-sideways.lt3 +43 -0
  130. data/doc/old-posts/0004-upcoming-lone-star-ruby-conference.lt3 +26 -0
  131. data/doc/old-posts/0005-elixir-conf-2015-announced.lt3 +17 -0
  132. data/doc/old-posts/0006-ruby-for-dinosaurs.lt3 +30 -0
  133. data/doc/old-posts/0007-phoenix-isnt-rails.lt3 +90 -0
  134. data/doc/old-posts/0008-concerning-the-term-monkeypatching.lt3 +105 -0
  135. data/doc/old-posts/0009-announcement-coming-soon.lt3 +20 -0
  136. data/doc/old-posts/0010-immutable-data-ditching-the-wax-tablet.lt3 +142 -0
  137. data/doc/old-posts/0011-computer-science-as-a-lost-art.lt3 +117 -0
  138. data/doc/old-posts/0012-ruby-day-in-turin-italy.lt3 +26 -0
  139. data/doc/old-posts/0013-rubyday-was-a-success.lt3 +28 -0
  140. data/doc/old-posts/0014-working-on-the-blogging-software.lt3 +42 -0
  141. data/doc/old-posts/0015-ok-its-not-really-a-lost-art.lt3 +137 -0
  142. data/doc/old-posts/0016-an-in-operator-for-ruby.lt3 +142 -0
  143. data/doc/old-posts/0017-the-forgotten-mathematician.lt3 +129 -0
  144. data/doc/old-posts/0018-ruby-puns.lt3 +31 -0
  145. data/doc/old-posts/0019-custom-exceptions-via-metaprogramming.lt3 +116 -0
  146. data/doc/old-posts/0021-trying-ror-yet-again.lt3 +35 -0
  147. data/doc/old-posts/0023-doctor-sleep.lt3 +43 -0
  148. data/doc/old-posts/0024-just-a-test.lt3 +12 -0
  149. data/doc/old-posts/0025-trying-another-post.lt3 +12 -0
  150. data/doc/old-repo +1 -0
  151. data/doc/reddit_credentials_template.json +8 -0
  152. data/doc/reddit_integration.md +207 -0
  153. data/doc/user.lt3 +35 -0
  154. data/doc/user_guide_section_1.md +137 -0
  155. data/doc/user_guide_section_10.md +515 -0
  156. data/doc/user_guide_section_11.md +708 -0
  157. data/doc/user_guide_section_2.md +233 -0
  158. data/doc/user_guide_section_3.md +5 -0
  159. data/doc/user_guide_section_4.md +221 -0
  160. data/doc/user_guide_section_5.md +243 -0
  161. data/doc/user_guide_section_6.md +147 -0
  162. data/doc/user_guide_section_7.md +311 -0
  163. data/doc/user_guide_section_8.md +224 -0
  164. data/doc/user_guide_section_9.md +375 -0
  165. data/lib/rouge/lexers/livetext.rb +74 -0
  166. data/lib/scriptorium/api.rb +2373 -0
  167. data/lib/scriptorium/banner_svg.rb +729 -0
  168. data/lib/scriptorium/contract.rb +34 -0
  169. data/lib/scriptorium/exceptions.rb +201 -1
  170. data/lib/scriptorium/helpers.rb +675 -0
  171. data/lib/scriptorium/post.rb +259 -0
  172. data/lib/scriptorium/reddit.rb +83 -0
  173. data/lib/scriptorium/repo.rb +938 -0
  174. data/lib/scriptorium/standard_files.rb +149 -0
  175. data/lib/scriptorium/support/bootstrap/css.txt +5 -0
  176. data/lib/scriptorium/support/bootstrap/js.txt +4 -0
  177. data/lib/scriptorium/support/common_js/clipboard.js +35 -0
  178. data/lib/scriptorium/support/common_js/content-loader.js +187 -0
  179. data/lib/scriptorium/support/common_js/navigation.js +52 -0
  180. data/lib/scriptorium/support/common_js/syntax-highlighting.js +27 -0
  181. data/lib/scriptorium/support/config/reddit.txt +10 -0
  182. data/lib/scriptorium/support/config/reddit_template.txt +17 -0
  183. data/lib/scriptorium/support/config/social.txt +8 -0
  184. data/lib/scriptorium/support/highlight/css.txt +2 -0
  185. data/lib/scriptorium/support/highlight/custom.css +119 -0
  186. data/lib/scriptorium/support/highlight/js.txt +1 -0
  187. data/lib/scriptorium/support/post_index/config.txt +15 -0
  188. data/lib/scriptorium/support/post_index/style.css +55 -0
  189. data/lib/scriptorium/support/templates/index_entry.lt3 +16 -0
  190. data/lib/scriptorium/support/templates/initial_post.lt3 +12 -0
  191. data/lib/scriptorium/support/templates/layout.txt +5 -0
  192. data/lib/scriptorium/support/templates/post.lt3 +104 -0
  193. data/lib/scriptorium/support/theme/footer.lt3 +2 -0
  194. data/lib/scriptorium/support/theme/header.lt3 +4 -0
  195. data/lib/scriptorium/support/theme/left.lt3 +3 -0
  196. data/lib/scriptorium/support/theme/main.lt3 +5 -0
  197. data/lib/scriptorium/support/theme/right.lt3 +3 -0
  198. data/lib/scriptorium/theme.rb +192 -0
  199. data/lib/scriptorium/version.rb +1 -1
  200. data/lib/scriptorium/view.rb +1021 -0
  201. data/lib/scriptorium/widgets/featured_posts.rb +149 -0
  202. data/lib/scriptorium/widgets/links.rb +112 -0
  203. data/lib/scriptorium/widgets/pages.rb +133 -0
  204. data/lib/scriptorium/widgets/widget.rb +133 -0
  205. data/lib/scriptorium.rb +38 -34
  206. data/lib/skeleton.rb +10 -1
  207. data/scriptorium.gemspec +17 -5
  208. data/test/README.md +69 -0
  209. data/test/WEB_INTEGRATION_README.md +196 -0
  210. data/test/all +83 -0
  211. data/test/api_demo.rb +99 -0
  212. data/test/assets/imagenotfound.jpg +0 -0
  213. data/test/assets/images/.DS_Store +0 -0
  214. data/test/assets/images/README.md +27 -0
  215. data/test/assets/images/odd_aspect.png +0 -0
  216. data/test/assets/images/perfect.png +0 -0
  217. data/test/assets/images/small.png +0 -0
  218. data/test/assets/images/tall.png +0 -0
  219. data/test/assets/images/very_tall.png +0 -0
  220. data/test/assets/images/very_wide.png +0 -0
  221. data/test/assets/images/wide.png +0 -0
  222. data/test/assets/testbanner.jpg +0 -0
  223. data/test/banner_svg/simple_helpers.rb +13 -0
  224. data/test/banner_svg/unit.rb +1000 -0
  225. data/test/config/deployment.txt +5 -0
  226. data/test/ed_test.rb +204 -0
  227. data/test/integration/cursor_banner_combinations.rb +193 -0
  228. data/test/integration/cursor_banner_features.rb +374 -0
  229. data/test/integration/integration_test.rb +326 -0
  230. data/test/integration/preview_flow_test.rb +94 -0
  231. data/test/livetext_plugin_test.rb +500 -0
  232. data/test/manual/asset_mgmt.rb +67 -0
  233. data/test/manual/banner-tests/index.html +45 -0
  234. data/test/manual/banner-tests/svg.txt +3 -0
  235. data/test/manual/banner-tests/test01.html +122 -0
  236. data/test/manual/banner-tests/test02.html +122 -0
  237. data/test/manual/banner-tests/test03.html +122 -0
  238. data/test/manual/banner-tests/test04.html +129 -0
  239. data/test/manual/banner-tests/test05.html +129 -0
  240. data/test/manual/banner-tests/test06.html +129 -0
  241. data/test/manual/banner-tests/test07.html +129 -0
  242. data/test/manual/banner-tests/test08.html +123 -0
  243. data/test/manual/banner-tests/test09.html +123 -0
  244. data/test/manual/banner-tests/test10.html +123 -0
  245. data/test/manual/banner-tests/test11.html +123 -0
  246. data/test/manual/banner-tests/test12.html +123 -0
  247. data/test/manual/banner-tests/test13.html +123 -0
  248. data/test/manual/banner-tests/test14.html +123 -0
  249. data/test/manual/banner-tests/test15.html +122 -0
  250. data/test/manual/banner-tests/test16.html +122 -0
  251. data/test/manual/banner-tests/test17.html +122 -0
  252. data/test/manual/banner-tests/test18.html +132 -0
  253. data/test/manual/banner-tests/test19.html +132 -0
  254. data/test/manual/banner-tests/test20.html +132 -0
  255. data/test/manual/banner-tests/test21.html +132 -0
  256. data/test/manual/banner-tests/test22.html +132 -0
  257. data/test/manual/banner-tests/test23.html +132 -0
  258. data/test/manual/banner-tests/test24.html +132 -0
  259. data/test/manual/banner-tests/test25.html +131 -0
  260. data/test/manual/banner_environment.rb +205 -0
  261. data/test/manual/codemirror_demo.html +773 -0
  262. data/test/manual/create_posts_for_web.rb +114 -0
  263. data/test/manual/environment.rb +67 -0
  264. data/test/manual/make_banner.rb +153 -0
  265. data/test/manual/preview_manual_test.rb +129 -0
  266. data/test/manual/sample_banner_config.txt +12 -0
  267. data/test/manual/test_advanced_widgets.rb +73 -0
  268. data/test/manual/test_banner_combinations.rb +120 -0
  269. data/test/manual/test_banner_features.rb +306 -0
  270. data/test/manual/test_banner_integration.rb +115 -0
  271. data/test/manual/test_banner_radial.rb +87 -0
  272. data/test/manual/test_basic_posts.rb +47 -0
  273. data/test/manual/test_layout_widgets.rb +40 -0
  274. data/test/manual/test_pagination.rb +24 -0
  275. data/test/manual/test_random_posts.rb +38 -0
  276. data/test/manual/test_syntax_highlighting.rb +167 -0
  277. data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
  278. data/test/rubytext/rubytext_demo_test.rb +42 -0
  279. data/test/rubytext/rubytext_testing_guide.md +277 -0
  280. data/test/run_automated_tests.rb +45 -0
  281. data/test/staging/.DS_Store +0 -0
  282. data/test/support/preview_utils.rb +88 -0
  283. data/test/syntax_highlighting_test.lt3 +124 -0
  284. data/test/test_gem_assets.rb +48 -0
  285. data/test/test_helpers.rb +240 -0
  286. data/test/tui_editor_integration_test.rb +296 -0
  287. data/test/tui_integration_test.rb +883 -0
  288. data/test/unit/api.rb +1776 -0
  289. data/test/unit/asset_management.rb +219 -0
  290. data/test/unit/backup_test.rb +451 -0
  291. data/test/unit/clipboard_test.rb +60 -0
  292. data/test/unit/contract_test.rb +69 -0
  293. data/test/unit/core.rb +1211 -0
  294. data/test/unit/deploy_config_test.rb +248 -0
  295. data/test/unit/deploy_test.rb +478 -0
  296. data/test/unit/edit_post_test.rb +168 -0
  297. data/test/unit/gem_asset_management.rb +183 -0
  298. data/test/unit/livetext_basic.rb +57 -0
  299. data/test/unit/livetext_compatibility.rb +82 -0
  300. data/test/unit/parse_cmd_test.rb +260 -0
  301. data/test/unit/permalink_copy_test.rb +211 -0
  302. data/test/unit/post.rb +309 -0
  303. data/test/unit/post_index_config_test.rb +258 -0
  304. data/test/unit/post_state_helpers_test.rb +137 -0
  305. data/test/unit/read_commented_file_test.rb +278 -0
  306. data/test/unit/reddit_test.rb +235 -0
  307. data/test/unit/repo.rb +569 -0
  308. data/test/unit/social_test.rb +366 -0
  309. data/test/unit/syntax_highlighting.rb +70 -0
  310. data/test/unit/theme_management_test.rb +91 -0
  311. data/test/unit/view.rb +498 -0
  312. data/test/unit/widgets.rb +669 -0
  313. data/test/web_integration_test.rb +231 -0
  314. data/test/web_test_helper.rb +218 -0
  315. data/test/web_workflow_test.rb +527 -0
  316. data/test/wizard_test.rb +123 -0
  317. data/ui/README.md +67 -0
  318. data/ui/common/lib/ui_common.rb +8 -0
  319. data/ui/rubytext/README.md +191 -0
  320. data/ui/rubytext/bin/scriptorium-rubytext +402 -0
  321. data/ui/rubytext/lib/rubytext_ui.rb +300 -0
  322. data/ui/tui/bin/scriptorium +1890 -0
  323. data/ui/tui/test/tui_test.rb +23 -0
  324. data/ui/web/app/app.rb +2600 -0
  325. data/ui/web/app/assets/livetext_mode.js +244 -0
  326. data/ui/web/app/error_helpers.rb +150 -0
  327. data/ui/web/app/views/advanced_config.erb +196 -0
  328. data/ui/web/app/views/asset_management.erb +645 -0
  329. data/ui/web/app/views/backup_management.erb +238 -0
  330. data/ui/web/app/views/banner_config.erb +200 -0
  331. data/ui/web/app/views/config_widget.erb +232 -0
  332. data/ui/web/app/views/configure_view.erb +401 -0
  333. data/ui/web/app/views/dashboard.erb +154 -0
  334. data/ui/web/app/views/deploy_config.erb +149 -0
  335. data/ui/web/app/views/edit_pages.erb +363 -0
  336. data/ui/web/app/views/edit_post.erb +175 -0
  337. data/ui/web/app/views/edit_theme.erb +73 -0
  338. data/ui/web/app/views/edit_theme_file.erb +74 -0
  339. data/ui/web/app/views/error_page.erb +29 -0
  340. data/ui/web/app/views/header_config.erb +155 -0
  341. data/ui/web/app/views/layout_config.erb +147 -0
  342. data/ui/web/app/views/navbar_config.erb +411 -0
  343. data/ui/web/app/views/theme_management.erb +130 -0
  344. data/ui/web/app/views/view_dashboard.erb +779 -0
  345. data/ui/web/app/views/widgets.erb +249 -0
  346. data/ui/web/bin/scriptorium-web +164 -0
  347. data/ui/web/test/web_basic_test.rb +38 -0
  348. data/ui/web/test_navbar.txt +7 -0
  349. data/ui/web/tmp/timing.log +17 -0
  350. data/ui/web/tmp/web_server.log +0 -0
  351. metadata +434 -8
  352. data/lib/scriptorium/engine.rb +0 -22
  353. data/test/engine/unit.rb +0 -44
@@ -0,0 +1,34 @@
1
+ module Scriptorium::Contract
2
+ def self.enabled?
3
+ !ENV['DBC_DISABLED']
4
+ end
5
+
6
+ def assume(condition = nil, message = nil, &block)
7
+ return unless Scriptorium::Contract.enabled?
8
+ if block_given?
9
+ result = instance_eval(&block)
10
+ raise "Precondition violated: #{message || 'block condition failed'}" unless result
11
+ else
12
+ raise "Precondition violated: #{message || condition}" unless condition
13
+ end
14
+ end
15
+
16
+ def verify(condition = nil, message = nil, &block)
17
+ return unless Scriptorium::Contract.enabled?
18
+ if block_given?
19
+ raise "Postcondition violated: #{message}" unless instance_eval(&block)
20
+ else
21
+ raise "Postcondition violated: #{message}" unless condition
22
+ end
23
+ end
24
+
25
+ def invariant(&block)
26
+ @invariants ||= []
27
+ @invariants << block
28
+ end
29
+
30
+ def check_invariants
31
+ return unless Scriptorium::Contract.enabled?
32
+ @invariants&.each { |invariant| raise "Invariant violated" unless instance_eval(&invariant) }
33
+ end
34
+ end
@@ -1,5 +1,205 @@
1
1
  module Scriptorium::Exceptions
2
2
 
3
- class TestModeOnly < Exception; end
3
+ def make_exception(sym, str, target_class = Object)
4
+ return if target_class.constants.include?(sym)
5
+ klass = sym
6
+ target_class.const_set(klass, StandardError)
7
+ define_method(sym) do |*args|
8
+ args = [] unless args.first
9
+ msg = str.dup
10
+ args.each.with_index {|arg, i| msg.sub!("%#{i+1}", arg.to_s) }
11
+ target_class.class_eval(klass.to_s).new(msg)
12
+ end
13
+ end
14
+
15
+ make_exception :TestModeOnly, "Test mode only"
16
+ make_exception :ViewDirAlreadyExists, "View directory already exists: %1"
17
+ make_exception :RepoDirAlreadyExists, "Repository directory already exists: %1"
18
+ make_exception :ViewDirDoesntExist, "View directory doesn't exist: %1"
19
+ make_exception :MoreThanOneResult, "More than one result found for: %1"
20
+ make_exception :CannotLookupView, "Cannot lookup view: %1"
21
+ make_exception :ThemeDoesntExist, "Theme doesn't exist: %1"
22
+ make_exception :ThemeFileNotFound, "Theme file not found: %1"
23
+ make_exception :LayoutHasUnknownTag, "Layout has unknown tag: %1"
24
+ make_exception :LayoutHasDuplicateTags, "Layout has duplicate tags: %1"
25
+ make_exception :LayoutFileMissing, "Layout file missing: %1"
26
+ make_exception :AssetNotFound, "Asset not found: %1"
27
+ make_exception :NoGemPath, "No gem path"
28
+
29
+ # Validation errors
30
+ make_exception :NilValueError, "Value is nil: %1"
31
+ make_exception :EmptyValueError, "Value is empty or whitespace-only: %1"
32
+ make_exception :InvalidFormatError, "Invalid format '%1': %2"
33
+
34
+ # Specific validation errors
35
+ make_exception :ViewNameNil, "Cannot create view: name is nil"
36
+ make_exception :ViewNameEmpty, "Cannot create view: name is empty or whitespace-only"
37
+ make_exception :ViewNameInvalid, "Cannot create view: invalid name '%1' (only alphanumeric, hyphen, and underscore allowed)"
38
+ make_exception :ViewTitleNil, "Cannot create view: title is nil"
39
+ make_exception :ViewTitleEmpty, "Cannot create view: title is empty or whitespace-only"
40
+ make_exception :ViewTargetNil, "Cannot lookup view: target is nil"
41
+ make_exception :ViewTargetEmpty, "Cannot lookup view: target is empty or whitespace-only"
42
+ make_exception :ViewTargetInvalid, "Cannot lookup view: invalid target '%1' (must be 'view' or 'post')"
43
+
44
+ make_exception :PostIdNil, "Cannot get post: id is nil"
45
+ make_exception :PostIdEmpty, "Cannot get post: id is empty or whitespace-only"
46
+ make_exception :PostIdInvalid, "Cannot get post: invalid id '%1' (must be numeric)"
47
+
48
+ make_exception :PostRepoNil, "Cannot create post: repo is nil"
49
+ make_exception :PostNumNil, "Cannot create post: num is nil"
50
+ make_exception :PostNumEmpty, "Cannot create post: num is empty or whitespace-only"
51
+ make_exception :PostNumInvalid, "Cannot create post: invalid num '%1' (must be numeric)"
52
+
53
+ make_exception :PubdateYmdNil, "Cannot set pubdate: ymd is nil"
54
+ make_exception :PubdateYmdEmpty, "Cannot set pubdate: ymd is empty or whitespace-only"
55
+ make_exception :PubdateInvalidFormat, "Cannot set pubdate: invalid date format '%1' (expected YYYY-MM-DD)"
56
+
57
+ make_exception :WidgetsArgNil, "Cannot build widgets: argument is nil"
58
+ make_exception :WidgetsArgEmpty, "Cannot build widgets: argument is empty or whitespace-only"
59
+ make_exception :WidgetNameNil, "Cannot build widget: widget name is nil or empty"
60
+ make_exception :WidgetNameInvalid, "Cannot build widget: invalid widget name '%1' (only alphanumeric and underscore allowed)"
61
+
62
+ # File/IO errors
63
+ make_exception :FileNotFoundError, "File not found: %1"
64
+ make_exception :PermissionDeniedError, "Permission denied: %1"
65
+ make_exception :DiskFullError, "Disk full: %1"
66
+ make_exception :DirectoryNotFoundError, "Directory not found: %1"
67
+
68
+ # Specific file/IO errors
69
+ make_exception :FilePathNil, "Cannot write file: file path is nil"
70
+ make_exception :FilePathEmpty, "Cannot write file: file path is empty or whitespace-only"
71
+ make_exception :FilePermissionDenied, "Cannot write file %1: permission denied (%2)"
72
+ make_exception :FileDiskFull, "Cannot write file %1: disk full (%2)"
73
+ make_exception :FileDirectoryNotFound, "Cannot write file %1: directory not found (%2)"
74
+ make_exception :CannotWriteFileError, "Cannot write file %1: %2"
75
+
76
+ make_exception :DirectoryPathNil, "Cannot create directory: directory path is nil"
77
+ make_exception :DirectoryPathEmpty, "Cannot create directory: directory path is empty or whitespace-only"
78
+ make_exception :DirectoryPermissionDenied, "Cannot create directory %1: permission denied (%2)"
79
+ make_exception :DirectoryParentNotFound, "Cannot create directory %1: parent directory not found (%2)"
80
+ make_exception :DirectoryDiskFull, "Cannot create directory %1: disk full (%2)"
81
+ make_exception :DirectoryError, "Cannot create directory %1: %2"
82
+
83
+ make_exception :ReadFilePathNil, "Cannot read file: file path is nil"
84
+ make_exception :ReadFilePathEmpty, "Cannot read file: file path is empty or whitespace-only"
85
+ make_exception :ReadFileNotFound, "Cannot read file %1: file not found (%2)"
86
+ make_exception :ReadFilePermissionDenied, "Cannot read file %1: permission denied (%2)"
87
+ make_exception :ReadFileError, "Cannot read file %1: %2"
88
+
89
+ make_exception :EditFilePathNil, "Cannot edit file: file path is nil"
90
+ make_exception :EditFilePathEmpty, "Cannot edit file: file path is empty or whitespace-only"
91
+
92
+ make_exception :RequirePathNil, "Cannot require %1: path is nil"
93
+ make_exception :RequirePathEmpty, "Cannot require %1: path is empty or whitespace-only"
94
+ make_exception :RequiredFileNotFound, "Required %1 not found: %2"
95
+ make_exception :InvalidType, "Invalid type: %1 (must be :file or :dir)"
96
+
97
+ # View errors
98
+ make_exception :CannotCreateView, "Cannot create view: %1"
99
+ make_exception :CannotBuildWidget, "Cannot build widget: %1"
100
+
101
+ # Post errors
102
+ make_exception :CannotCreatePost, "Cannot create post: %1"
103
+ make_exception :CannotGetPost, "Cannot get post: %1"
104
+ make_exception :PostAlreadyPublished, "Post %1 is already published"
105
+ make_exception :PostNotPublished, "Post %1 is not published"
106
+ make_exception :PostAlreadyDeployed, "Post %1 is already deployed"
107
+ make_exception :PostDeleted, "Post %1 is deleted"
108
+ make_exception :PostAlreadyDeleted, "Post %1 is already deleted"
109
+ make_exception :PostNotDeleted, "Post %1 is not deleted"
110
+ make_exception :PostNotDeployed, "Post %1 is not deployed"
111
+ make_exception :InvalidStateTransition, "Invalid state transition: %1"
112
+ make_exception :CannotSetPubdate, "Cannot set pubdate: %1"
113
+
114
+ # Banner SVG errors
115
+ make_exception :InvalidBackground, "Cannot handle background: %1"
116
+ make_exception :InvalidGradient, "Cannot handle gradient: %1"
117
+ make_exception :InvalidImage, "Cannot handle image: %1"
118
+ make_exception :InvalidAspect, "Cannot handle aspect: %1"
119
+ make_exception :InvalidFont, "Cannot handle font: %1"
120
+ make_exception :InvalidColor, "Cannot handle color: %1"
121
+ make_exception :InvalidAlign, "Cannot handle align: %1"
122
+ make_exception :InvalidXY, "Cannot handle xy: %1"
123
+
124
+ # Specific Banner SVG errors
125
+ make_exception :BackgroundNoArgs, "Cannot handle background: no arguments provided"
126
+ make_exception :BackgroundFirstArgNil, "Cannot handle background: first argument is nil"
127
+ make_exception :BackgroundFirstArgEmpty, "Cannot handle background: first argument is empty or whitespace-only"
128
+
129
+ make_exception :LinearGradientNoArgs, "Cannot handle linear gradient: no arguments provided"
130
+ make_exception :LinearGradientStartColorNil, "Cannot handle linear gradient: start color is nil or empty"
131
+ make_exception :LinearGradientArgEmpty, "Cannot handle linear gradient: argument %1 is empty or whitespace-only"
132
+
133
+ make_exception :RadialGradientNoArgs, "Cannot handle radial gradient: no arguments provided"
134
+ make_exception :RadialGradientStartColorNil, "Cannot handle radial gradient: start color is nil or empty"
135
+ make_exception :RadialGradientArgEmpty, "Cannot handle radial gradient: argument %1 is empty or whitespace-only"
136
+
137
+ make_exception :ImageBackgroundNoArgs, "Cannot handle image background: no arguments provided"
138
+ make_exception :ImageBackgroundFirstArgNil, "Cannot handle image background: first argument is nil"
139
+ make_exception :ImageBackgroundFirstArgEmpty, "Cannot handle image background: first argument is empty or whitespace-only"
140
+
141
+ make_exception :AspectNoArgs, "Cannot handle aspect: no arguments provided"
142
+ make_exception :AspectFirstArgNil, "Cannot handle aspect: first argument is nil"
143
+ make_exception :AspectFirstArgEmpty, "Cannot handle aspect: first argument is empty or whitespace-only"
144
+ make_exception :AspectInvalidValue, "Cannot handle aspect: invalid aspect value '%1' (must be numeric)"
145
+
146
+ make_exception :FontArgsNil, "Cannot handle font: arguments are nil"
147
+ make_exception :FontArgNil, "Cannot handle font: argument %1 is nil"
148
+ make_exception :FontArgEmpty, "Cannot handle font: argument %1 is empty or whitespace-only"
149
+
150
+ make_exception :TextColorNoArgs, "Cannot handle text color: no arguments provided"
151
+ make_exception :TextColorFirstArgNil, "Cannot handle text color: first argument is nil"
152
+ make_exception :TextColorFirstArgEmpty, "Cannot handle text color: first argument is empty or whitespace-only"
153
+
154
+ make_exception :XYWhichNil, "Cannot handle xy: which is nil"
155
+ make_exception :XYWhichEmpty, "Cannot handle xy: which is empty or whitespace-only"
156
+ make_exception :XYInvalidWhich, "Cannot handle xy: invalid which '%1' (must be 'title' or 'subtitle')"
157
+
158
+ make_exception :AlignNoArgs, "Cannot handle align: no arguments provided"
159
+ make_exception :AlignDirectionNil, "Cannot handle align: direction is nil or empty"
160
+ make_exception :AlignInvalidDirection, "Cannot handle align: invalid direction '%1' (must be 'left', 'center', or 'right')"
161
+ make_exception :AlignArgEmpty, "Cannot handle align: argument %1 is empty or whitespace-only"
162
+
163
+ make_exception :ColorNoArgs, "Cannot handle color: no arguments provided"
164
+ make_exception :ColorFirstArgNil, "Cannot handle color: first argument is nil"
165
+ make_exception :ColorFirstArgEmpty, "Cannot handle color: first argument is empty or whitespace-only"
166
+
167
+ # Command errors
168
+ make_exception :CommandFailed, "Command failed: %1"
169
+ make_exception :CannotExecuteCommand, "Cannot execute command: %1"
170
+
171
+ # Specific command errors
172
+ make_exception :CommandNil, "Cannot execute command: command is nil"
173
+ make_exception :CommandEmpty, "Cannot execute command: command is empty or whitespace-only"
174
+ make_exception :CommandFailedWithDesc, "Command failed%1: %2"
175
+
176
+ # Section/Output errors
177
+ make_exception :SectionOutputError, "Section output error: %1 (section: %2) - %3"
178
+ make_exception :WriteFrontPageError, "Failed to write front page: %1"
179
+
180
+ # Theme management errors
181
+ make_exception :ThemeNotFound, "Theme not found: %1"
182
+ make_exception :ThemeAlreadyExists, "Theme already exists: %1"
183
+ make_exception :ThemeNameInvalid, "Theme name must contain only letters, numbers, hyphens, and underscores: %1"
184
+
185
+ # Draft management errors
186
+ make_exception :DraftPathNil, "Draft path cannot be nil"
187
+ make_exception :DraftPathEmpty, "Draft path cannot be empty"
188
+ make_exception :DraftFileInvalid, "Not a valid draft file: %1"
189
+ make_exception :DraftFileNotFound, "Draft file not found: %1"
190
+
191
+ # Search/Query errors
192
+ make_exception :UnknownSearchField, "Unknown search field: %1"
193
+
194
+ # Deployment errors
195
+ make_exception :DeploymentNotReady, "View '%1' is not ready for deployment. Check status and configuration."
196
+ make_exception :DeploymentFieldsMissing, "Missing required deployment fields: %1"
197
+ make_exception :DeploymentFailed, "Deployment failed with exit code %1"
198
+
199
+ # Backup errors
200
+ make_exception :BackupNotFound, "Backup not found: %1"
201
+ make_exception :BackupCreationFailed, "Failed to create backup: %1"
202
+ make_exception :BackupRestoreFailed, "Failed to restore backup: %1"
203
+ make_exception :BackupDeleteFailed, "Failed to delete backup: %1"
4
204
 
5
205
  end