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
@@ -21,187 +21,28 @@ class Scriptorium::StandardFiles
21
21
  javascript # See common.js
22
22
  bootstrap # See bootstrap.txt
23
23
  social # See social.txt for configuration
24
+ highlight # See highlight_css.txt for syntax highlighting
25
+ highlight_custom # Custom CSS overrides for Highlight.js
24
26
  EOS
27
+ str
25
28
  end
26
29
 
27
30
  def common_js
28
- <<~EOS
29
- // Handle the back button (or JavaScript history.go(-1))
30
- window.onpopstate = function(event) {
31
- console.log('onpopstate event:', event); // Log the event object
32
- if (event.state && event.state.slug) {
33
- console.log('Navigating to slug:', event.state.slug); // Log the slug
34
- load_main(event.state.slug); // Load the post for the previous history state
35
- }
36
- };
37
-
38
- // Initialize with the front page when navigating via the back button or similar
39
- window.onload = function() {
40
- // Check if the URL has a post parameter and load it automatically
41
- const urlParams = new URLSearchParams(window.location.search);
42
- const postParam = urlParams.get('post');
43
-
44
- if (postParam) {
45
- // URL has a post parameter, load the post content
46
- console.log('Auto-loading post from URL parameter:', postParam);
47
- load_main('index.html?post=' + postParam);
48
- return;
49
- }
31
+ files = [
32
+ 'common_js/navigation.js',
33
+ 'common_js/content-loader.js',
34
+ 'common_js/syntax-highlighting.js',
35
+ 'common_js/clipboard.js'
36
+ ]
50
37
 
51
- // Check if the initial state exists, if not, set it
52
- if (!history.state) {
53
- // Don't try to load post_index.html if there are no posts
54
- // The "No posts yet!" message is already in the main container
55
- history.replaceState({ slug: "index.html" }, "", "index.html");
56
- }
57
-
58
-
59
- };
60
-
61
- // Load the main content and other page containers (header, footer, left, right)
62
- function load_main(slug) {
63
- // Get all container elements (header, footer, left, right, and main)
64
- const contentDiv = document.getElementById("main");
65
- const headerDiv = document.querySelector("header");
66
- const footerDiv = document.querySelector("footer");
67
- const leftDiv = document.querySelector(".left");
68
- const rightDiv = document.querySelector(".right");
69
- console.log('Loading main with slug:', slug); // Log the slug
70
-
71
- // Check if this is a post parameter request
72
- if (slug.includes('?post=')) {
73
- const postSlug = slug.split('?post=')[1];
74
- console.log('Loading post:', postSlug);
75
-
76
- // Load the post content - add .html extension if it's missing
77
- const postFile = postSlug.endsWith('.html') ? postSlug : postSlug + '.html';
78
- fetch('posts/' + postFile)
79
- .then(response => {
80
- if (response.ok) {
81
- return response.text();
82
- } else {
83
- console.error('Failed to load post:', response.status);
84
- return 'Post not found';
85
- }
86
- })
87
- .then(content => {
88
- contentDiv.innerHTML = content;
89
- history.pushState({slug: 'index.html?post=' + postSlug}, "", 'index.html?post=' + postSlug);
90
- })
91
- .catch(error => {
92
- console.log("Error loading post:", error);
93
- contentDiv.innerHTML = 'Error loading post';
94
- });
95
- return;
96
- }
97
-
98
- // Check if this is a static page request (pages/, assets/, etc.)
99
- if (slug.startsWith('pages/') || slug.startsWith('assets/') || slug.includes('/')) {
100
- console.log('Loading static page:', slug);
101
- // Simple approach: always go back to index.html directory and fetch from there
102
- fetch(slug)
103
- .then(response => {
104
- if (response.ok) {
105
- return response.text();
106
- } else {
107
- console.error('Failed to load static page:', response.status);
108
- return 'Page not found';
109
- }
110
- })
111
- .then(content => {
112
- contentDiv.innerHTML = content;
113
- // Don't change the URL for static pages to avoid path resolution issues
114
- history.pushState({slug: slug}, "", window.location.pathname);
115
- })
116
- .catch(error => {
117
- console.log("Error loading static page:", error);
118
- contentDiv.innerHTML = 'Error loading page';
119
- });
120
- return;
121
- }
122
-
123
- fetch(slug)
124
- .then(response => {
125
- if (response.ok) {
126
- console.log('Response is ok');
127
- return response.text();
128
- } else {
129
- console.error('Failed to load:', response.status); // Log the failed response
130
- }
131
- })
132
- .then(content => {
133
- console.log('Loaded content into div'); // Log successful content insertion
134
-
135
- // Now, reload the content into the respective containers:
136
- // Main section
137
- contentDiv.innerHTML = content;
138
-
139
- // Re-insert header, footer, left, and right (if necessary)
140
- // If you want the static layout to be kept, you can preserve these parts
141
- // with additional logic or predefined structure (here it's assumed
142
- // that header/footer/left/right are already statically included).
143
-
144
- // You can also replace the other parts (left, right, header, footer) if needed.
145
- history.pushState({slug: slug}, "", slug); // Update browser history
146
-
147
-
148
- })
149
- .catch(error => {
150
- console.log("Error loading content:", error); // Log any errors during fetch
151
- });
152
- }
153
-
154
- // Copy permalink to clipboard functionality
155
- function copyPermalinkToClipboard() {
156
- // Get the current post slug from the URL or construct it
157
- const currentUrl = window.location.href;
158
- let permalinkUrl;
159
-
160
- if (currentUrl.includes('?post=')) {
161
- // We're on the main blog page, construct the permalink URL
162
- const postSlug = currentUrl.split('?post=')[1];
163
- const baseUrl = window.location.origin + window.location.pathname.replace(/\/[^\/]*$/, '');
164
- permalinkUrl = baseUrl + '/permalink/' + postSlug;
165
- } else {
166
- // We're already on a permalink page, use current URL
167
- permalinkUrl = currentUrl;
168
- }
169
-
170
- navigator.clipboard.writeText(permalinkUrl).then(function() {
171
- // Change button text temporarily to show success
172
- const button = event.target;
173
- const originalText = button.textContent;
174
- button.textContent = 'Copied!';
175
- button.style.background = '#28a745';
176
- setTimeout(function() {
177
- button.textContent = originalText;
178
- button.style.background = '#007bff';
179
- }, 2000);
180
- }).catch(function(err) {
181
- console.error('Failed to copy: ', err);
182
- alert('Failed to copy link to clipboard');
183
- });
184
- }
185
- EOS
38
+ files.map { |file| support_data(file) }.join("\n\n")
186
39
  end
187
40
 
188
41
 
189
- def bootstrap_css
190
- <<~EOS
191
- href https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
192
- rel stylesheet
193
- # integrity has a problem - compute instead?
194
- # integrity sha384-KyZXEJ04F5o1v7V5b7ZMjGhGjxA8yQmBfvZwzI1r+0gEv+9KnQIMJxWwzD0u8nZ7
195
- # crossorigin anonymous
196
- EOS
197
- end
198
42
 
199
- def bootstrap_js
43
+ def highlight_ruby_js
200
44
  <<~EOS
201
- src https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js
202
- # integrity has a problem - compute instead?
203
- # integrity sha384-pzjw8f+ua7Kw1TIq0+v5+GZkR6P/6v03cI0myXcJU22Hc5p5BY5/X93HmaJXjm4C
204
- crossorigin anonymous
45
+ src https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/ruby.min.js
205
46
  EOS
206
47
  end
207
48
 
@@ -213,32 +54,6 @@ class Scriptorium::StandardFiles
213
54
  EOS
214
55
  end
215
56
 
216
- def social_config
217
- <<~EOS
218
- # Available platforms: facebook twitter linkedin reddit
219
- # List one platform per line to enable social meta tags
220
- facebook
221
- twitter
222
-
223
- # Note: No Facebook App ID or Twitter username required for basic meta tags
224
- # These are only needed if you want to add social sharing buttons later
225
- EOS
226
- end
227
-
228
- def reddit_config
229
- <<~EOS
230
- # Reddit sharing button configuration
231
- # Set to true to show Reddit share button on posts
232
- button true
233
-
234
- # Optional: specify a subreddit for direct posting
235
- # Leave empty or omit to let users choose subreddit
236
- subreddit
237
-
238
- # Optional: custom hover text (defaults to "Share on Reddit" or "Share on [subreddit]")
239
- hover_text
240
- EOS
241
- end
242
57
 
243
58
  def initial_post(mode = :filled, num: "0", title: nil, blurb: nil, views: nil,
244
59
  tags: nil, body: nil)
@@ -249,50 +64,16 @@ class Scriptorium::StandardFiles
249
64
  tags ||= %w[sample tags]
250
65
  body ||= "BEGIN HERE..."
251
66
 
252
- str =
253
- <<~EOS
254
- . Initial file created by StandardFiles#post_template(num)
255
-
256
- .id %{num}
257
- .created %{created}
258
-
259
- .title %{title}
260
- .blurb %{blurb}
261
-
262
- .views %{views}
263
- .tags %{tags}
264
-
265
- #{body}
266
- EOS
67
+ str = support_data('templates/initial_post.lt3')
267
68
 
268
69
  return str if mode == :raw
269
70
  mytags = tags
270
71
  mytags = tags.join(", ") if tags.is_a?(Array)
271
72
  str2 = str % {num: d4(num.to_i), created: ymdhms, title: title, blurb: blurb,
272
- views: views.join(" "), tags: mytags}
73
+ views: views.join(" "), tags: mytags, body: body}
273
74
  return str2
274
75
  end
275
76
 
276
- def initial_post_content(title: nil, blurb: nil, views: nil, tags: nil, body: nil)
277
- title ||= "ADD TITLE HERE"
278
- blurb ||= "ADD BLURB HERE"
279
- views ||= %w[sample]
280
- tags ||= %w[sample tags]
281
- body ||= "BEGIN HERE..."
282
-
283
- mytags = tags
284
- mytags = tags.join(", ") if tags.is_a?(Array)
285
-
286
- <<~EOS
287
- .title #{title}
288
- .blurb #{blurb}
289
- .views #{views.join(" ")}
290
- .tags #{mytags}
291
-
292
- #{body}
293
- EOS
294
- end
295
-
296
77
  def initial_post_metadata(num: "0", title: nil, blurb: nil, views: nil, tags: nil)
297
78
  title ||= "ADD TITLE HERE"
298
79
  blurb ||= "ADD BLURB HERE"
@@ -314,159 +95,12 @@ class Scriptorium::StandardFiles
314
95
  EOS
315
96
  end
316
97
 
317
- def post_template(theme)
318
- str = <<~EOS
319
- <!-- theme: #{theme} -->
320
-
321
- <div align='right'><a style="text-decoration: none" href="index.html">
322
- <img src="assets/back-icon.png" width=24 height=24 alt="Go to Index"></img></a>
323
- </div>
324
- <div style="display: flex; justify-content: space-between; align-items: baseline;">
325
- <span style="text-align: left; font-size: 1.5em;">%{post.title}</span>
326
- <span style="text-align: right; font-size: 0.9em;">%{reddit_button}%{post.pubdate}</span>
327
- </div>
328
- <hr>
329
- %{post.body}
330
- <hr>
331
- <div style="text-align: right; font-size: 0.8em;">%{post.tags}</div>
332
- <div style="text-align: center; margin-top: 20px;">
333
- <button onclick="copyPermalinkToClipboard()" style="padding: 8px 16px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">Copy link</button>
334
- </div>
335
- EOS
336
- end
337
-
338
- def layout_text
339
- <<~EOS
340
- header # Top (banner? title? navbar? etc.)
341
- left 15% # Left sidebar, 15% width
342
- main # Main (center) container - posts/etc.
343
- right 15% # Right sidebar, 15% width
344
- footer # Footer (copyright? mail? social media? etc.)
345
- EOS
346
- end
347
-
348
- def post_index_style # Not really a file
349
- <<~EOS
350
- <style>
351
- body { font-family: verdana }
352
-
353
- .recent-title a {
354
- color: #010101;
355
- font-family: verdana;
356
- font-size: 28px;
357
- float: right;
358
- display: inline-block;
359
- text-align: top;
360
- text-decoration: none;
361
- }
362
-
363
- .recent-title a:hover {
364
- text-decoration: none;
365
- }
366
-
367
- .recent-title-text a {
368
- color: #0101a1;
369
- font-family: verdana;
370
- font-size: 22px;
371
- display: block;
372
- text-decoration: none;
373
- }
374
-
375
- .recent-title-text a:hover {
376
- text-decoration: none;
377
- }
378
-
379
- .recent-date {
380
- color: #9a9a9a;
381
- font-family: verdana;
382
- font-size: 15px;
383
- display: block;
384
- float: left;
385
- text-align: top;
386
- }
387
-
388
- .mydrop {
389
- color: #444444;
390
- float: left;
391
- text-align: top;
392
- # font-family: Verdana;
393
- font-size: 38px;
394
- line-height: 38px;
395
- # padding-top: 0px;
396
- padding-right: 8px;
397
- padding-left: 3px;
398
- }
399
-
400
- .thumbnail img {
401
- max-height: 100%;
402
- max-width: 100%;
403
- }
404
- </style>
405
- EOS
406
- end
407
-
408
- # <!-- posts/%{post.slug}" -->
409
-
410
- def index_entry
411
- # Note the use of %% to escape the % in the flex-basis attribute!
412
- <<~EOS
413
- <div class="index-entry" style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px;">
414
- <!-- Left Side: Date (right aligned) -->
415
- <div style="text-align: right; font-size: 0.7em; flex-basis: 10%%; padding-top: 3px;">
416
- <div>%{post.pubdate.month} %{post.pubdate.day}</div>
417
- <div>%{post.pubdate.year}</div>
418
- </div>
419
- <!-- Right Side: Title and Blurb (left aligned) -->
420
- <div style="font-size: 1.2em; margin-left: 10px; flex-grow: 1; padding-top: 0;">
421
- <div><a href="javascript:void(0)"
422
- style="text-decoration: none;"
423
- onclick="load_main('index.html?post=%{post.slug}')">%{post.title}</a></div>
424
- <div style="font-size: 0.9em;">%{post.blurb}</div>
425
- </div>
426
- </div>
427
- EOS
428
- end
429
-
430
- def theme_header # Add theme name to these files??
431
- <<~EOS
432
- # <!-- Section: header -->
433
- # Contents of header
434
- # (may include banner, title, navbar, ...)
435
- title
436
- EOS
437
- end
438
-
439
- def theme_footer
440
- <<~EOS
441
- # <!-- Section: footer -->
442
- # Contents of footer
443
- EOS
444
- end
445
-
446
- def theme_left
447
- <<~EOS
448
- # <!-- Section: left -->
449
- # Contents of left sidebar
450
- # (may be widgets or whatever)
451
- EOS
452
- end
453
-
454
- def theme_right
455
- <<~EOS
456
- # <!-- Section: right -->
457
- # Contents of right sidebar
458
- # (may be widgets or whatever)
459
- EOS
98
+ def support_data(relative_path)
99
+ read_file(support_file(relative_path))
460
100
  end
461
101
 
462
- def theme_main
463
- <<~EOS
464
- # <!-- Section: main -->
465
- # Contents of center pane
466
- # This may be empty, as it is "usually" populated
467
- # by Javascript (list of recent posts, content from
468
- # a widget, or whatever)
469
- EOS
102
+ def post_template
103
+ support_data('templates/post.lt3')
470
104
  end
471
105
 
472
106
  def svg_txt
@@ -477,13 +111,13 @@ class Scriptorium::StandardFiles
477
111
  subtitle.color #cccccc
478
112
  text.justify left
479
113
 
480
- title.scale 0.7
481
- subtitle.scale 0.3
114
+ title.scale 0.8
115
+ subtitle.scale 0.4
482
116
 
483
117
  title.style bold
484
118
  subtitle.style bold italic
485
- title.xy 15 60
486
- subtitle.xy 15 85
119
+ title.xy 5 50
120
+ subtitle.xy 5 75
487
121
 
488
122
  back.linear #0000cc #000077 lr
489
123
 
@@ -503,13 +137,13 @@ class Scriptorium::StandardFiles
503
137
 
504
138
  def status_txt
505
139
  <<~EOS
506
- header n
507
- banner n
508
- navbar n
509
- left n
510
- right n
511
- pages n
512
- deploy n
140
+ header n
141
+ banner n
142
+ navbar n
143
+ left n
144
+ right n
145
+ pages n
146
+ deploy n
513
147
  EOS
514
148
  end
515
- end
149
+ end
@@ -0,0 +1,35 @@
1
+ // Copy permalink to clipboard functionality
2
+ function copyPermalinkToClipboard(button) {
3
+ // Get the current post slug from the URL or construct it
4
+ const currentUrl = window.location.href;
5
+ let permalinkUrl;
6
+
7
+ if (currentUrl.includes('?post=')) {
8
+ // We're on the main blog page, construct the permalink URL
9
+ const postSlug = currentUrl.split('?post=')[1];
10
+ // const baseUrl = window.location.origin + window.location.pathname.replace(/\\[^\\/]*$/, '');
11
+ const parts = window.location.pathname.split('/');
12
+ parts.pop();
13
+ const baseUrl = window.location.origin + parts.join('/') + '/';
14
+ permalinkUrl = baseUrl + 'permalink/' + postSlug;
15
+ } else {
16
+ // We're already on a permalink page, use current URL
17
+ permalinkUrl = currentUrl;
18
+ }
19
+
20
+ navigator.clipboard.writeText(permalinkUrl).then(function() {
21
+ // Change button text temporarily to show success
22
+ const btn = button || document.activeElement || document.querySelector('button[onclick*="copyPermalinkToClipboard"]');
23
+ if (!btn) { return; }
24
+ const originalText = btn.textContent;
25
+ btn.textContent = 'Copied!';
26
+ btn.style.background = '#28a745';
27
+ setTimeout(function() {
28
+ btn.textContent = originalText;
29
+ btn.style.background = '#007bff';
30
+ }, 2000);
31
+ }).catch(function(err) {
32
+ console.error('Failed to copy: ', err);
33
+ alert('Failed to copy link to clipboard');
34
+ });
35
+ }