scriptorium 0.0.3 → 0.6.1

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 (292) 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/back-icon.png +0 -0
  7. data/assets/icons/facebook.svg +1 -0
  8. data/assets/icons/github.svg +1 -0
  9. data/assets/icons/instagram.svg +1 -0
  10. data/assets/icons/reddit.svg +1 -0
  11. data/assets/icons/ui/.DS_Store +0 -0
  12. data/assets/icons/ui/back.png +0 -0
  13. data/assets/icons/ui/copy.png +0 -0
  14. data/assets/icons/ui/down.png +0 -0
  15. data/assets/icons/ui/end.png +0 -0
  16. data/assets/icons/ui/exit.png +0 -0
  17. data/assets/icons/ui/foo +10 -0
  18. data/assets/icons/ui/home.png +0 -0
  19. data/assets/icons/ui/left.png +0 -0
  20. data/assets/icons/ui/next.png +0 -0
  21. data/assets/icons/ui/right.png +0 -0
  22. data/assets/icons/ui/start.png +0 -0
  23. data/assets/icons/ui/up.png +0 -0
  24. data/assets/icons/x.svg +1 -0
  25. data/assets/icons/youtube.svg +1 -0
  26. data/assets/samples/placeholder.svg +9 -0
  27. data/assets/themes/standard/favicon.svg +6 -0
  28. data/bin/scriptorium +1511 -0
  29. data/doc/README.txt +6 -0
  30. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +95 -0
  31. data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +34 -0
  32. data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +50 -0
  33. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +31 -0
  34. data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +73 -0
  35. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +64 -0
  36. data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +70 -0
  37. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
  38. data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +110 -0
  39. data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +73 -0
  40. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
  41. data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +124 -0
  42. data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +46 -0
  43. data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +97 -0
  44. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
  45. data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +211 -0
  46. data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +141 -0
  47. data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +211 -0
  48. data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +134 -0
  49. data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +41 -0
  50. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +45 -0
  51. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +30 -0
  52. data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +49 -0
  53. data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +46 -0
  54. data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +41 -0
  55. data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +41 -0
  56. data/doc/anti-amnesia/20250807-213025.md +116 -0
  57. data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +256 -0
  58. data/doc/banner_svg_config.md +114 -0
  59. data/doc/contrib.lt3 +8 -0
  60. data/doc/dependencies.md +281 -0
  61. data/doc/hacker.lt3 +5 -0
  62. data/doc/reddit_credentials_template.json +8 -0
  63. data/doc/reddit_integration.md +207 -0
  64. data/doc/user.lt3 +38 -0
  65. data/doc/user_guide_section_1.md +137 -0
  66. data/doc/user_guide_section_10.md +515 -0
  67. data/doc/user_guide_section_11.md +708 -0
  68. data/doc/user_guide_section_2.md +233 -0
  69. data/doc/user_guide_section_3.md +5 -0
  70. data/doc/user_guide_section_4.md +221 -0
  71. data/doc/user_guide_section_5.md +243 -0
  72. data/doc/user_guide_section_6.md +147 -0
  73. data/doc/user_guide_section_7.md +311 -0
  74. data/doc/user_guide_section_8.md +224 -0
  75. data/doc/user_guide_section_9.md +375 -0
  76. data/doc/userdoc-toc.txt +88 -0
  77. data/lib/rouge/lexers/livetext.rb +74 -0
  78. data/lib/scriptorium/api.rb +640 -0
  79. data/lib/scriptorium/banner_svg.rb +742 -0
  80. data/lib/scriptorium/contract.rb +33 -0
  81. data/lib/scriptorium/exceptions.rb +170 -1
  82. data/lib/scriptorium/helpers.rb +475 -0
  83. data/lib/scriptorium/post.rb +195 -0
  84. data/lib/scriptorium/reddit.rb +83 -0
  85. data/lib/scriptorium/repo.rb +624 -0
  86. data/lib/scriptorium/standard_files.rb +515 -0
  87. data/lib/scriptorium/syntax_highlighter.rb +234 -0
  88. data/lib/scriptorium/theme.rb +179 -0
  89. data/lib/scriptorium/version.rb +2 -2
  90. data/lib/scriptorium/view.rb +976 -0
  91. data/lib/scriptorium/widgets/featured_posts.rb +149 -0
  92. data/lib/scriptorium/widgets/links.rb +112 -0
  93. data/lib/scriptorium/widgets/pages.rb +133 -0
  94. data/lib/scriptorium/widgets/widget.rb +133 -0
  95. data/lib/scriptorium.rb +21 -40
  96. data/lib/skeleton.rb +8 -2
  97. data/scriptorium.gemspec +15 -4
  98. data/test/README.md +69 -0
  99. data/test/all +43 -0
  100. data/test/api_demo.rb +99 -0
  101. data/test/assets/imagenotfound.jpg +0 -0
  102. data/test/assets/images/.DS_Store +0 -0
  103. data/test/assets/images/README.md +27 -0
  104. data/test/assets/images/odd_aspect.png +0 -0
  105. data/test/assets/images/perfect.png +0 -0
  106. data/test/assets/images/small.png +0 -0
  107. data/test/assets/images/tall.png +0 -0
  108. data/test/assets/images/very_tall.png +0 -0
  109. data/test/assets/images/very_wide.png +0 -0
  110. data/test/assets/images/wide.png +0 -0
  111. data/test/assets/testbanner.jpg +0 -0
  112. data/test/banner_svg/simple_helpers.rb +13 -0
  113. data/test/banner_svg/unit.rb +768 -0
  114. data/test/ed_test.rb +204 -0
  115. data/test/integration/cursor_banner_combinations.rb +193 -0
  116. data/test/integration/cursor_banner_features.rb +374 -0
  117. data/test/integration/integration_test.rb +326 -0
  118. data/test/livetext_plugin_test.rb +229 -0
  119. data/test/manual/asset_mgmt.rb +67 -0
  120. data/test/manual/banner-tests/config.txt +3 -0
  121. data/test/manual/banner-tests/index.html +45 -0
  122. data/test/manual/banner-tests/test01.html +58 -0
  123. data/test/manual/banner-tests/test02.html +58 -0
  124. data/test/manual/banner-tests/test03.html +58 -0
  125. data/test/manual/banner-tests/test04.html +65 -0
  126. data/test/manual/banner-tests/test05.html +65 -0
  127. data/test/manual/banner-tests/test06.html +65 -0
  128. data/test/manual/banner-tests/test07.html +65 -0
  129. data/test/manual/banner-tests/test08.html +59 -0
  130. data/test/manual/banner-tests/test09.html +59 -0
  131. data/test/manual/banner-tests/test10.html +59 -0
  132. data/test/manual/banner-tests/test11.html +59 -0
  133. data/test/manual/banner-tests/test12.html +59 -0
  134. data/test/manual/banner-tests/test13.html +59 -0
  135. data/test/manual/banner-tests/test14.html +59 -0
  136. data/test/manual/banner-tests/test15.html +58 -0
  137. data/test/manual/banner-tests/test16.html +58 -0
  138. data/test/manual/banner-tests/test17.html +58 -0
  139. data/test/manual/banner-tests/test18.html +68 -0
  140. data/test/manual/banner-tests/test19.html +68 -0
  141. data/test/manual/banner-tests/test20.html +68 -0
  142. data/test/manual/banner-tests/test21.html +68 -0
  143. data/test/manual/banner-tests/test22.html +68 -0
  144. data/test/manual/banner-tests/test23.html +68 -0
  145. data/test/manual/banner-tests/test24.html +68 -0
  146. data/test/manual/banner-tests/test25.html +67 -0
  147. data/test/manual/banner_environment.rb +192 -0
  148. data/test/manual/deploy_symlink_demo.rb +142 -0
  149. data/test/manual/environment.rb +67 -0
  150. data/test/manual/make_banner.rb +153 -0
  151. data/test/manual/sample_banner_config.txt +12 -0
  152. data/test/manual/symlink_demo.rb +117 -0
  153. data/test/manual/test1.rb +47 -0
  154. data/test/manual/test2.rb +12 -0
  155. data/test/manual/test3.rb +38 -0
  156. data/test/manual/test4.rb +40 -0
  157. data/test/manual/test5.rb +24 -0
  158. data/test/manual/test6.rb +73 -0
  159. data/test/manual/test_banner_combinations.rb +120 -0
  160. data/test/manual/test_banner_features.rb +306 -0
  161. data/test/manual/test_banner_from_file.rb +150 -0
  162. data/test/manual/test_banner_in_header.rb +35 -0
  163. data/test/manual/test_code_highlighting.rb +68 -0
  164. data/test/manual/test_complex_header.rb +74 -0
  165. data/test/manual/test_empty_header.rb +32 -0
  166. data/test/manual/test_radial_custom.rb +58 -0
  167. data/test/manual/test_radial_large_radius.rb +52 -0
  168. data/test/manual/test_svg_debug.rb +47 -0
  169. data/test/manual/test_syntax_highlighting.rb +147 -0
  170. data/test/pages-demo/config/currentview.txt +1 -0
  171. data/test/pages-demo/views/demo/config/bootstrap_css.txt +5 -0
  172. data/test/pages-demo/views/demo/config/bootstrap_js.txt +4 -0
  173. data/test/pages-demo/views/demo/config/common.js +57 -0
  174. data/test/pages-demo/views/demo/config/footer.txt +1 -0
  175. data/test/pages-demo/views/demo/config/global-head.txt +8 -0
  176. data/test/pages-demo/views/demo/config/header.txt +1 -0
  177. data/test/pages-demo/views/demo/config/layout.txt +1 -0
  178. data/test/pages-demo/views/demo/config/left.txt +1 -0
  179. data/test/pages-demo/views/demo/config/main.txt +1 -0
  180. data/test/pages-demo/views/demo/config/right.txt +1 -0
  181. data/test/pages-demo/views/demo/config.txt +3 -0
  182. data/test/pages-demo/views/demo/output/panes/footer.html +1 -0
  183. data/test/pages-demo/views/demo/output/panes/header.html +1 -0
  184. data/test/pages-demo/views/demo/output/panes/left.html +1 -0
  185. data/test/pages-demo/views/demo/output/panes/main.html +1 -0
  186. data/test/pages-demo/views/demo/output/panes/right.html +1 -0
  187. data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
  188. data/test/rubytext/rubytext_demo_test.rb +42 -0
  189. data/test/rubytext/rubytext_testing_guide.md +277 -0
  190. data/test/run_automated_tests.rb +45 -0
  191. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +5 -0
  192. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +4 -0
  193. data/test/scriptorium-TEST-1754622690-146/config/common.js +57 -0
  194. data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +1 -0
  195. data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +9 -0
  196. data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +1 -0
  197. data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +4 -0
  198. data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +3 -0
  199. data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +8 -0
  200. data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +6 -0
  201. data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +1 -0
  202. data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +1 -0
  203. data/test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 +12 -0
  204. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt +2 -0
  205. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt +4 -0
  206. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt +3 -0
  207. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt +5 -0
  208. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt +3 -0
  209. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +1 -0
  210. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/layout.txt +5 -0
  211. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +1 -0
  212. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +14 -0
  213. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +13 -0
  214. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +1 -0
  215. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +5 -0
  216. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +4 -0
  217. data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +57 -0
  218. data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +5 -0
  219. data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +2 -0
  220. data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +9 -0
  221. data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +4 -0
  222. data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +5 -0
  223. data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +3 -0
  224. data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +5 -0
  225. data/test/scriptorium-TEST-1754622690-146/views/sample/config/reddit.txt +10 -0
  226. data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +3 -0
  227. data/test/scriptorium-TEST-1754622690-146/views/sample/config/social.txt +7 -0
  228. data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +7 -0
  229. data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +3 -0
  230. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +3 -0
  231. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +3 -0
  232. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +3 -0
  233. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +3 -0
  234. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +3 -0
  235. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +1 -0
  236. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +1 -0
  237. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +1 -0
  238. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +1 -0
  239. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +1 -0
  240. data/test/staging/.DS_Store +0 -0
  241. data/test/syntax_highlighting_test.lt3 +124 -0
  242. data/test/test_helpers.rb +230 -0
  243. data/test/tui_editor_integration_test.rb +296 -0
  244. data/test/tui_integration_test.rb +637 -0
  245. data/test/unit/api.rb +1056 -0
  246. data/test/unit/asset_management.rb +245 -0
  247. data/test/unit/clipboard_test.rb +60 -0
  248. data/test/unit/contract_test.rb +91 -0
  249. data/test/unit/core.rb +857 -0
  250. data/test/unit/deploy_test.rb +187 -0
  251. data/test/unit/gem_asset_management.rb +189 -0
  252. data/test/unit/livetext_basic.rb +69 -0
  253. data/test/unit/livetext_compatibility.rb +89 -0
  254. data/test/unit/post.rb +244 -0
  255. data/test/unit/read_commented_file_test.rb +276 -0
  256. data/test/unit/reddit_test.rb +235 -0
  257. data/test/unit/repo.rb +548 -0
  258. data/test/unit/social_test.rb +369 -0
  259. data/test/unit/symlink_test.rb +213 -0
  260. data/test/unit/view.rb +431 -0
  261. data/test/unit/widgets.rb +669 -0
  262. data/test/wizard_test.rb +123 -0
  263. data/ui/README.md +67 -0
  264. data/ui/common/lib/ui_common.rb +8 -0
  265. data/ui/rubytext/README.md +191 -0
  266. data/ui/rubytext/bin/scriptorium-rubytext +402 -0
  267. data/ui/rubytext/lib/rubytext_ui.rb +300 -0
  268. data/ui/tui/bin/scriptorium +1420 -0
  269. data/ui/tui/test/tui_test.rb +23 -0
  270. data/ui/web/app/app.rb +1378 -0
  271. data/ui/web/app/error_helpers.rb +150 -0
  272. data/ui/web/app/views/advanced_config.erb +190 -0
  273. data/ui/web/app/views/asset_management.erb +589 -0
  274. data/ui/web/app/views/banner_config.erb +200 -0
  275. data/ui/web/app/views/configure_view.erb +401 -0
  276. data/ui/web/app/views/dashboard.erb +162 -0
  277. data/ui/web/app/views/deploy_config.erb +146 -0
  278. data/ui/web/app/views/edit_pages.erb +195 -0
  279. data/ui/web/app/views/edit_post.erb +54 -0
  280. data/ui/web/app/views/error_page.erb +29 -0
  281. data/ui/web/app/views/header_config.erb +155 -0
  282. data/ui/web/app/views/layout_config.erb +147 -0
  283. data/ui/web/app/views/navbar_config.erb +411 -0
  284. data/ui/web/app/views/view_dashboard.erb +138 -0
  285. data/ui/web/bin/scriptorium-web +153 -0
  286. data/ui/web/test/web_basic_test.rb +38 -0
  287. data/ui/web/test_navbar.txt +7 -0
  288. data/ui/web/tmp/web_server.log +5 -0
  289. data/ui/web/tmp/web_server.pid +1 -0
  290. metadata +359 -7
  291. data/lib/scriptorium/engine.rb +0 -22
  292. data/test/engine/unit.rb +0 -44
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+
5
+ require_relative '../../lib/scriptorium'
6
+ require_relative '../test_helpers'
7
+
8
+ class TestDeploy < Minitest::Test
9
+ include Scriptorium::Exceptions
10
+ include Scriptorium::Helpers
11
+ include TestHelpers
12
+
13
+ def setup
14
+ @repo = Scriptorium::Repo.create("test/scriptorium-TEST", testmode: true)
15
+ @view = @repo.create_view("testview", "Test View", "Test Subtitle")
16
+ end
17
+
18
+ def teardown
19
+ system("rm -rf test/scriptorium-TEST")
20
+ end
21
+
22
+ def test_001_deploy_config_file_creation
23
+ # Test that deploy.txt can be created and read
24
+ deploy_file = @view.dir/:config/"deploy.txt"
25
+ write_file(deploy_file, "user@example.com:/var/www/html/")
26
+
27
+ assert File.exist?(deploy_file), "Deploy config file should exist"
28
+ content = read_file(deploy_file)
29
+ assert_equal "user@example.com:/var/www/html/", content.strip
30
+ end
31
+
32
+ def test_002_deploy_config_validation
33
+ # Test various deploy config formats
34
+ deploy_file = @view.dir/:config/"deploy.txt"
35
+
36
+ # Valid formats
37
+ valid_configs = [
38
+ "user@server:/path/",
39
+ "user@server.com:/var/www/html/",
40
+ "deploy@mysite.com:/home/deploy/public_html/"
41
+ ]
42
+
43
+ valid_configs.each do |config|
44
+ write_file(deploy_file, config)
45
+ content = read_file(deploy_file).strip
46
+ assert_equal config, content, "Should read config: #{config}"
47
+ end
48
+ end
49
+
50
+ def test_003_deploy_requires_output_directory
51
+ # Test that deployment requires output directory to exist
52
+ deploy_file = @view.dir/:config/"deploy.txt"
53
+ write_file(deploy_file, "user@server:/path/")
54
+
55
+ # Output directory should exist after view creation (created by make_tree)
56
+ output_dir = @view.dir/:output
57
+ assert Dir.exist?(output_dir), "Output directory should exist after view creation"
58
+ end
59
+
60
+ def test_004_deploy_rsync_command_format
61
+ # Test that the rsync command format is correct
62
+ deploy_config = "user@server:/var/www/html/"
63
+ output_dir = @view.dir/:output
64
+ make_dir(output_dir)
65
+
66
+ # Expected rsync command format
67
+ expected_cmd = "rsync -r -z #{output_dir}/ #{deploy_config}/"
68
+
69
+ # This is the format used in the TUI
70
+ actual_cmd = "rsync -r -z #{output_dir}/ #{deploy_config}/"
71
+
72
+ assert_equal expected_cmd, actual_cmd, "Rsync command format should match"
73
+ end
74
+
75
+ def test_005_deploy_with_sample_content
76
+ # Test deployment with actual content
77
+ deploy_file = @view.dir/:config/"deploy.txt"
78
+ write_file(deploy_file, "user@server:/path/")
79
+
80
+ # Create output directory and some content
81
+ output_dir = @view.dir/:output
82
+ make_dir(output_dir)
83
+ make_dir(output_dir/:posts)
84
+ make_dir(output_dir/:permalink)
85
+
86
+ # Create a sample file
87
+ sample_file = output_dir/"index.html"
88
+ write_file(sample_file, "<html><body>Test content</body></html>")
89
+
90
+ assert File.exist?(sample_file), "Sample file should exist"
91
+ assert Dir.exist?(output_dir/:posts), "Posts directory should exist"
92
+ assert Dir.exist?(output_dir/:permalink), "Permalink directory should exist"
93
+ end
94
+
95
+ def test_006_deploy_marker_file_creation
96
+ # Test that deployment creates a marker file
97
+ output_dir = @view.dir/:output
98
+
99
+ # Simulate deployment marker creation
100
+ marker_content = "Deployed: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
101
+ marker_file = output_dir/"last-deployed.txt"
102
+ write_file(marker_file, marker_content)
103
+
104
+ assert File.exist?(marker_file), "Deployment marker file should exist"
105
+ content = read_file(marker_file)
106
+ assert content.start_with?("Deployed:"), "Marker file should start with 'Deployed:'"
107
+ end
108
+
109
+ def test_007_deploy_with_symlinks
110
+ # Test that deployment handles symlinks correctly
111
+ output_dir = @view.dir/:output
112
+ make_dir(output_dir/:permalink)
113
+
114
+ # Create a test symlink
115
+ target_file = output_dir/:permalink/"0001-test-post.html"
116
+ symlink_file = output_dir/:permalink/"test-post.html"
117
+
118
+ # Create the target file
119
+ write_file(target_file, "<html><body>Test post</body></html>")
120
+
121
+ # Create the symlink
122
+ File.symlink("0001-test-post.html", symlink_file)
123
+
124
+ # Verify symlink exists
125
+ assert File.exist?(symlink_file), "Symlink should exist"
126
+ assert File.symlink?(symlink_file), "Should be a symlink"
127
+
128
+ # Test that rsync command includes symlink preservation
129
+ expected_cmd = "rsync -r -z -l #{output_dir}/ user@server:/path/"
130
+ actual_cmd = "rsync -r -z -l #{output_dir}/ user@server:/path/"
131
+
132
+ assert_equal expected_cmd, actual_cmd, "Rsync command should preserve symlinks"
133
+ end
134
+
135
+ def test_008_deploy_symlink_target_verification
136
+ # Test that symlink targets are accessible after deployment
137
+ output_dir = @view.dir/:output
138
+ make_dir(output_dir/:permalink)
139
+
140
+ # Create a test symlink with target
141
+ target_file = output_dir/:permalink/"0001-another-post.html"
142
+ symlink_file = output_dir/:permalink/"another-post.html"
143
+
144
+ # Create the target file
145
+ write_file(target_file, "<html><body>Another test post</body></html>")
146
+
147
+ # Create the symlink
148
+ File.symlink("0001-another-post.html", symlink_file)
149
+
150
+ # Verify symlink points to existing target
151
+ assert File.exist?(symlink_file), "Symlink should exist"
152
+ assert File.symlink?(symlink_file), "Should be a symlink"
153
+
154
+ symlink_target = File.readlink(symlink_file)
155
+ target_path = output_dir/:permalink/symlink_target
156
+
157
+ assert File.exist?(target_path), "Symlink target should exist"
158
+ assert_equal "0001-another-post.html", symlink_target, "Symlink should point to correct target"
159
+ end
160
+
161
+ def test_009_domain_extraction_from_deploy_config
162
+ # Test domain extraction from various deploy config formats
163
+ test_cases = [
164
+ ["user@example.com:/var/www/html/", "example.com"],
165
+ ["deploy@mysite.com:/home/deploy/public_html/", "mysite.com"],
166
+ ["admin@blog.example.org:/srv/www/", "blog.example.org"]
167
+ ]
168
+
169
+ test_cases.each do |config, expected_domain|
170
+ # Simulate the domain extraction logic
171
+ domain = nil
172
+ if config =~ /@([^:]+):/
173
+ domain = $1
174
+ end
175
+
176
+ assert_equal expected_domain, domain, "Should extract domain from: #{config}"
177
+ end
178
+ end
179
+
180
+ def test_010_deploy_verification_url_format
181
+ # Test that verification URL is correctly formatted
182
+ domain = "example.com"
183
+ expected_url = "https://#{domain}/last-deployed.txt"
184
+
185
+ assert_equal "https://example.com/last-deployed.txt", expected_url, "Verification URL should be correctly formatted"
186
+ end
187
+ end
@@ -0,0 +1,189 @@
1
+ # Test file for gem asset management functionality
2
+ # Tests asset management when Scriptorium is installed as a gem
3
+
4
+ require 'minitest/autorun'
5
+ require_relative '../../lib/scriptorium'
6
+ require_relative '../test_helpers'
7
+ require_relative '../../lt3scriptor'
8
+ require 'fileutils'
9
+
10
+ class TestGemAssetManagement < Minitest::Test
11
+ include Scriptorium::Helpers
12
+ include TestHelpers
13
+
14
+ def setup
15
+ @test_dir = "test/gem_asset_management_test"
16
+ FileUtils.rm_rf(@test_dir) if File.exist?(@test_dir)
17
+ FileUtils.mkdir_p(@test_dir)
18
+ Scriptorium::Repo.testing = true
19
+
20
+ # Create test repository with unique view name
21
+ @repo = create_test_repo
22
+ @repo.create_view("gem_asset_test_view", "Testing gem assets")
23
+
24
+ # Set up LiveText variables for testing
25
+ setup_livetext_vars
26
+ end
27
+
28
+ def teardown
29
+ FileUtils.rm_rf(@test_dir) if File.exist?(@test_dir)
30
+ # Also clean up the test repository
31
+ FileUtils.rm_rf("test/scriptorium-TEST") if File.exist?("test/scriptorium-TEST")
32
+ end
33
+
34
+ def setup_livetext_vars
35
+ # Set up LiveText variables for testing
36
+ @vars = { View: "gem_asset_test_view", "post.id": "0001" }
37
+ end
38
+
39
+ def process_livetext(content)
40
+ # Create a temporary file with the content
41
+ temp_file = "#{@test_dir}/temp_livetext.lt3"
42
+ write_file(temp_file, content)
43
+
44
+ # Process with Livetext using the plugin
45
+ begin
46
+ live = Livetext.customize(mix: "lt3scriptor", call: ".nopara", vars: @vars)
47
+ body, vars = live.process(file: temp_file)
48
+ vars = vars.to_h
49
+ return { vars: vars, body: body }
50
+ rescue => e
51
+ puts "Livetext error: #{e.message}"
52
+ puts "Backtrace: #{e.backtrace.first}"
53
+ return { error: e.message, backtrace: e.backtrace.first }
54
+ ensure
55
+ # Clean up
56
+ File.delete(temp_file) if File.exist?(temp_file)
57
+ end
58
+ end
59
+
60
+ def test_001_gem_asset_discovery_in_development
61
+ # Test that gem assets are found in development environment
62
+ content = "$$asset[icons/ui/back-arrow.svg]"
63
+ result = process_livetext(content)
64
+
65
+ # Should find gem asset and return correct path
66
+ assert_equal "assets/icons/ui/back-arrow.svg", result[:body].strip
67
+ end
68
+
69
+ def test_002_gem_asset_discovery_in_production
70
+ # Test that gem assets are found in production environment
71
+ # This would require simulating a gem installation
72
+ skip "Requires gem installation simulation"
73
+ end
74
+
75
+ def test_003_gem_assets_copied_to_theme_during_repo_creation
76
+ # Test that theme-specific gem assets are copied during repo creation
77
+ theme_assets_dir = @repo.root/"themes"/"standard"/"assets"
78
+
79
+ # Check that theme assets were copied
80
+ assert Dir.exist?(theme_assets_dir), "Theme assets directory should exist"
81
+
82
+ # Check for specific theme assets
83
+ expected_theme_assets = [
84
+ "standard/favicon.svg",
85
+ "icons/ui/back-arrow.svg"
86
+ ]
87
+
88
+ expected_theme_assets.each do |asset|
89
+ asset_path = theme_assets_dir/asset
90
+ assert File.exist?(asset_path), "Theme asset #{asset} should be copied"
91
+ end
92
+ end
93
+
94
+ def test_004_gem_assets_copied_to_library_during_repo_creation
95
+ # Test that application-wide gem assets are copied to library
96
+ library_dir = @repo.root/"assets"/"library"
97
+
98
+ # Check that library directory exists
99
+ assert Dir.exist?(library_dir), "Library directory should exist"
100
+
101
+ # Check for specific library assets
102
+ expected_library_assets = [
103
+ "placeholder.svg"
104
+ ]
105
+
106
+ expected_library_assets.each do |asset|
107
+ asset_path = library_dir/asset
108
+ assert File.exist?(asset_path), "Library asset #{asset} should be copied"
109
+ end
110
+ end
111
+
112
+ def test_005_gem_assets_in_search_hierarchy
113
+ # Test that gem assets are found in the correct priority order
114
+ content = "$$asset[icons/ui/back-arrow.svg]"
115
+ result = process_livetext(content)
116
+
117
+ # Should find gem asset and return correct path
118
+ assert_equal "assets/icons/ui/back-arrow.svg", result[:body].strip
119
+ end
120
+
121
+ def test_006_gem_assets_override_by_user_assets
122
+ # Test that user assets override gem assets
123
+ # Create a user asset with the same name as a gem asset
124
+ user_asset_path = @repo.root/"assets"/"icons"/"ui"/"back-arrow.svg"
125
+ FileUtils.mkdir_p(File.dirname(user_asset_path))
126
+ File.write(user_asset_path, "User asset content")
127
+
128
+ content = "$$asset[icons/ui/back-arrow.svg]"
129
+ result = process_livetext(content)
130
+
131
+ # Should find user asset first (higher priority)
132
+ assert_equal "assets/icons/ui/back-arrow.svg", result[:body].strip
133
+ end
134
+
135
+ def test_007_gem_asset_path_resolution
136
+ # 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"
159
+ end
160
+ rescue => e
161
+ # If gem lookup fails, that's expected in development
162
+ dev_assets_dir = File.expand_path("assets")
163
+ assert Dir.exist?(dev_assets_dir), "Development assets directory should exist"
164
+ end
165
+ end
166
+
167
+ def test_008_gem_assets_not_copied_to_output
168
+ # Test that gem assets are not copied to output directory during generation
169
+ # (they should only be referenced)
170
+ output_assets_dir = @repo.root/"views"/"gem_asset_test_view"/"output"/"assets"
171
+
172
+ # Generate a post that references gem assets
173
+ draft_body = "$$asset[icons/ui/back-arrow.svg]"
174
+ name = @repo.create_draft(title: "Gem Asset Test", views: ["gem_asset_test_view"], body: draft_body)
175
+ num = @repo.finish_draft(name)
176
+ @repo.generate_post(num)
177
+
178
+ # Check that gem assets are not copied to output
179
+ gem_asset_in_output = output_assets_dir/"icons"/"ui"/"back-arrow.svg"
180
+ refute File.exist?(gem_asset_in_output), "Gem assets should not be copied to output"
181
+ end
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
+ end
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+ require 'livetext'
5
+
6
+ class TestLivetextBasic < Minitest::Test
7
+
8
+ def test_001_basic_livetext_processing
9
+ # Test basic Livetext without any plugins
10
+ content = "Simple text content"
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
21
+ end
22
+
23
+ def test_002_livetext_with_simple_dot_commands
24
+ # Test Livetext with simple dot commands
25
+ content = <<~CONTENT
26
+ .title Test Post
27
+ .views sample
28
+
29
+ This is the body.
30
+ CONTENT
31
+
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
41
+ end
42
+
43
+ def test_003_livetext_plugin_loading
44
+ # 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
52
+ end
53
+
54
+ def test_004_livetext_plugin_processing_simple
55
+ # Test if the plugin can process very simple content
56
+ content = "Simple content"
57
+
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
68
+ end
69
+ end
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+ require 'livetext'
5
+
6
+ class TestLivetextCompatibility < Minitest::Test
7
+
8
+ def test_001_basic_livetext_processing
9
+ # Test basic Livetext without any plugins
10
+ content = "Simple text content"
11
+
12
+ begin
13
+ live = Livetext.customize(call: ".nopara")
14
+ body, vars = live.process(text: content)
15
+ vars = vars.to_h
16
+ assert_equal "Simple text content", body.strip
17
+ assert vars.is_a?(Hash)
18
+ puts "✓ Basic Livetext processing works"
19
+ rescue => e
20
+ flunk "Basic Livetext processing failed: #{e.message}"
21
+ end
22
+ end
23
+
24
+ def test_002_livetext_with_simple_dot_commands
25
+ # Test Livetext with simple dot commands
26
+ content = <<~CONTENT
27
+ .title Test Post
28
+ .views sample
29
+
30
+ This is the body.
31
+ CONTENT
32
+
33
+ begin
34
+ live = Livetext.customize(call: ".nopara")
35
+ body, vars = live.process(text: content)
36
+ vars = vars.to_h
37
+ assert_includes body, "This is the body"
38
+ assert vars.is_a?(Hash)
39
+ puts "✓ Livetext with dot commands works"
40
+ rescue => e
41
+ flunk "Livetext with dot commands failed: #{e.message}"
42
+ end
43
+ end
44
+
45
+ def test_003_livetext_plugin_loading
46
+ # 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
54
+ end
55
+
56
+ def test_004_livetext_plugin_processing
57
+ # Test if the plugin can process simple content
58
+ content = "Simple content with $$asset[test.png]"
59
+
60
+ begin
61
+ live = Livetext.customize(mix: "lt3scriptor", call: ".nopara")
62
+ body, vars = live.process(text: content)
63
+ vars = vars.to_h
64
+ assert body.is_a?(String)
65
+ puts "✓ Plugin processing succeeded: #{body}"
66
+ rescue => e
67
+ puts "✗ Plugin processing failed: #{e.message}"
68
+ puts e.backtrace.first(3)
69
+ skip "Plugin processing needs to be fixed"
70
+ end
71
+ end
72
+
73
+ def test_005_livetext_old_api
74
+ # Test the old Livetext API
75
+ content = "Simple content"
76
+
77
+ begin
78
+ live = Livetext.customize(call: ".nopara")
79
+ text, vars = live.process(content)
80
+ vars = vars.to_h
81
+ assert text.is_a?(String)
82
+ assert vars.is_a?(Hash)
83
+ puts "✓ Old Livetext API works"
84
+ rescue => e
85
+ puts "✗ Old Livetext API failed: #{e.message}"
86
+ skip "Old API needs to be fixed"
87
+ end
88
+ end
89
+ end