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.
- checksums.yaml +4 -4
- data/assets/icons/social/reddit.png +0 -0
- data/assets/icons/social/x-logo.png +0 -0
- data/assets/imagenotfound.jpg +0 -0
- data/bin/sblog +84 -5
- data/bin/scriptorium +1 -0
- data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +0 -1
- data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +0 -29
- data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +0 -19
- data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +1 -1
- data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +1 -1
- data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +1 -1
- data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +0 -10
- data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +1 -4
- data/doc/anti-amnesia/20250901-211714-codemirror-integration-and-web-tests.md +172 -0
- data/doc/anti-amnesia/20250902-002402-backup-restore-system.md +126 -0
- data/doc/anti-amnesia/20250907-203339-backup-metadata-implementation.md +66 -0
- data/doc/imported/0001-elixir-conf-2014/metadata.txt +7 -0
- data/doc/imported/0001-elixir-conf-2014/post.html +37 -0
- data/doc/imported/0001-elixir-conf-2014/source.lt3 +22 -0
- data/doc/imported/0002-programmers-and-word-processing/metadata.txt +7 -0
- data/doc/imported/0002-programmers-and-word-processing/post.html +192 -0
- data/doc/imported/0002-programmers-and-word-processing/source.lt3 +146 -0
- data/doc/imported/0003-how-to-turn-your-brain-sideways/metadata.txt +7 -0
- data/doc/imported/0003-how-to-turn-your-brain-sideways/post.html +60 -0
- data/doc/imported/0003-how-to-turn-your-brain-sideways/source.lt3 +40 -0
- data/doc/imported/0004-upcoming-lone-star-ruby-conference/metadata.txt +7 -0
- data/doc/imported/0004-upcoming-lone-star-ruby-conference/post.html +42 -0
- data/doc/imported/0004-upcoming-lone-star-ruby-conference/source.lt3 +24 -0
- data/doc/imported/0005-elixir-conf-2015-announced/metadata.txt +7 -0
- data/doc/imported/0005-elixir-conf-2015-announced/post.html +30 -0
- data/doc/imported/0005-elixir-conf-2015-announced/source.lt3 +16 -0
- data/doc/imported/0006-ruby-for-dinosaurs/metadata.txt +7 -0
- data/doc/imported/0006-ruby-for-dinosaurs/post.html +43 -0
- data/doc/imported/0006-ruby-for-dinosaurs/source.lt3 +27 -0
- data/doc/imported/0007-phoenix-isnt-rails/metadata.txt +7 -0
- data/doc/imported/0007-phoenix-isnt-rails/post.html +116 -0
- data/doc/imported/0007-phoenix-isnt-rails/source.lt3 +87 -0
- data/doc/imported/0008-concerning-the-term-monkeypatching/metadata.txt +7 -0
- data/doc/imported/0008-concerning-the-term-monkeypatching/post.html +129 -0
- data/doc/imported/0008-concerning-the-term-monkeypatching/source.lt3 +92 -0
- data/doc/imported/0009-announcement-coming-soon/metadata.txt +7 -0
- data/doc/imported/0009-announcement-coming-soon/post.html +33 -0
- data/doc/imported/0009-announcement-coming-soon/source.lt3 +19 -0
- data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/metadata.txt +7 -0
- data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/post.html +175 -0
- data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/source.lt3 +139 -0
- data/doc/imported/0011-computer-science-as-a-lost-art/metadata.txt +7 -0
- data/doc/imported/0011-computer-science-as-a-lost-art/post.html +139 -0
- data/doc/imported/0011-computer-science-as-a-lost-art/source.lt3 +104 -0
- data/doc/imported/0012-ruby-day-in-turin-italy/metadata.txt +7 -0
- data/doc/imported/0012-ruby-day-in-turin-italy/post.html +42 -0
- data/doc/imported/0012-ruby-day-in-turin-italy/source.lt3 +24 -0
- data/doc/imported/0013-rubyday-was-a-success/metadata.txt +7 -0
- data/doc/imported/0013-rubyday-was-a-success/post.html +44 -0
- data/doc/imported/0013-rubyday-was-a-success/source.lt3 +27 -0
- data/doc/imported/0014-working-on-the-blogging-software/metadata.txt +7 -0
- data/doc/imported/0014-working-on-the-blogging-software/post.html +63 -0
- data/doc/imported/0014-working-on-the-blogging-software/source.lt3 +41 -0
- data/doc/imported/0015-ok-its-not-really-a-lost-art/metadata.txt +7 -0
- data/doc/imported/0015-ok-its-not-really-a-lost-art/post.html +172 -0
- data/doc/imported/0015-ok-its-not-really-a-lost-art/source.lt3 +134 -0
- data/doc/imported/0016-an-in-operator-for-ruby/metadata.txt +7 -0
- data/doc/imported/0016-an-in-operator-for-ruby/post.html +155 -0
- data/doc/imported/0016-an-in-operator-for-ruby/source.lt3 +106 -0
- data/doc/imported/0017-the-forgotten-mathematician/metadata.txt +7 -0
- data/doc/imported/0017-the-forgotten-mathematician/post.html +161 -0
- data/doc/imported/0017-the-forgotten-mathematician/source.lt3 +119 -0
- data/doc/imported/0018-ruby-puns/metadata.txt +7 -0
- data/doc/imported/0018-ruby-puns/post.html +46 -0
- data/doc/imported/0018-ruby-puns/source.lt3 +28 -0
- data/doc/imported/0019-custom-exceptions-via-metaprogramming/metadata.txt +7 -0
- data/doc/imported/0019-custom-exceptions-via-metaprogramming/post.html +138 -0
- data/doc/imported/0019-custom-exceptions-via-metaprogramming/source.lt3 +101 -0
- data/doc/imported/0020-fffff/metadata.txt +7 -0
- data/doc/imported/0020-fffff/post.html +24 -0
- data/doc/imported/0020-fffff/source.lt3 +12 -0
- data/doc/imported/0021-trying-ror-yet-again/metadata.txt +7 -0
- data/doc/imported/0021-trying-ror-yet-again/post.html +26 -0
- data/doc/imported/0021-trying-ror-yet-again/source.lt3 +12 -0
- data/doc/imported/0023-doctor-sleep/metadata.txt +7 -0
- data/doc/imported/0023-doctor-sleep/post.html +63 -0
- data/doc/imported/0023-doctor-sleep/source.lt3 +44 -0
- data/doc/imported/0024-just-a-test/metadata.txt +7 -0
- data/doc/imported/0024-just-a-test/post.html +24 -0
- data/doc/imported/0024-just-a-test/source.lt3 +12 -0
- data/doc/imported/import_summary.txt +98 -0
- data/doc/livetext-informal-spec.txt +65 -0
- data/doc/myuserdoc/ch-0.lt3 +31 -0
- data/doc/myuserdoc/ch-1.lt3 +37 -0
- data/doc/myuserdoc/ch-10.lt3 +22 -0
- data/doc/myuserdoc/ch-2.lt3 +37 -0
- data/doc/myuserdoc/ch-3.lt3 +19 -0
- data/doc/myuserdoc/ch-4.lt3 +43 -0
- data/doc/myuserdoc/ch-5.lt3 +22 -0
- data/doc/myuserdoc/ch-6.lt3 +19 -0
- data/doc/myuserdoc/ch-7.lt3 +16 -0
- data/doc/myuserdoc/ch-8.lt3 +13 -0
- data/doc/myuserdoc/ch-9.lt3 +19 -0
- data/doc/myuserdoc/tweak.rb +18 -0
- data/doc/{userdoc-toc.txt → myuserdoc/userdoc-toc.txt} +27 -27
- data/doc/old-posts/0001-elixir-conf-2014.lt3 +24 -0
- data/doc/old-posts/0002-programmers-and-word-processing.lt3 +150 -0
- data/doc/old-posts/0003-how-to-turn-your-brain-sideways.lt3 +43 -0
- data/doc/old-posts/0004-upcoming-lone-star-ruby-conference.lt3 +26 -0
- data/doc/old-posts/0005-elixir-conf-2015-announced.lt3 +17 -0
- data/doc/old-posts/0006-ruby-for-dinosaurs.lt3 +30 -0
- data/doc/old-posts/0007-phoenix-isnt-rails.lt3 +90 -0
- data/doc/old-posts/0008-concerning-the-term-monkeypatching.lt3 +105 -0
- data/doc/old-posts/0009-announcement-coming-soon.lt3 +20 -0
- data/doc/old-posts/0010-immutable-data-ditching-the-wax-tablet.lt3 +142 -0
- data/doc/old-posts/0011-computer-science-as-a-lost-art.lt3 +117 -0
- data/doc/old-posts/0012-ruby-day-in-turin-italy.lt3 +26 -0
- data/doc/old-posts/0013-rubyday-was-a-success.lt3 +28 -0
- data/doc/old-posts/0014-working-on-the-blogging-software.lt3 +42 -0
- data/doc/old-posts/0015-ok-its-not-really-a-lost-art.lt3 +137 -0
- data/doc/old-posts/0016-an-in-operator-for-ruby.lt3 +142 -0
- data/doc/old-posts/0017-the-forgotten-mathematician.lt3 +129 -0
- data/doc/old-posts/0018-ruby-puns.lt3 +31 -0
- data/doc/old-posts/0019-custom-exceptions-via-metaprogramming.lt3 +116 -0
- data/doc/old-posts/0021-trying-ror-yet-again.lt3 +35 -0
- data/doc/old-posts/0023-doctor-sleep.lt3 +43 -0
- data/doc/old-posts/0024-just-a-test.lt3 +12 -0
- data/doc/old-posts/0025-trying-another-post.lt3 +12 -0
- data/doc/old-repo +1 -0
- data/doc/reddit_integration.md +2 -2
- data/doc/user.lt3 +0 -3
- data/lib/scriptorium/api.rb +1811 -78
- data/lib/scriptorium/banner_svg.rb +55 -68
- data/lib/scriptorium/contract.rb +3 -2
- data/lib/scriptorium/exceptions.rb +133 -102
- data/lib/scriptorium/helpers.rb +282 -82
- data/lib/scriptorium/post.rb +81 -17
- data/lib/scriptorium/reddit.rb +1 -1
- data/lib/scriptorium/repo.rb +478 -164
- data/lib/scriptorium/standard_files.rb +30 -396
- data/lib/scriptorium/support/common_js/clipboard.js +35 -0
- data/lib/scriptorium/support/common_js/content-loader.js +187 -0
- data/lib/scriptorium/support/common_js/navigation.js +52 -0
- data/lib/scriptorium/support/common_js/syntax-highlighting.js +27 -0
- data/lib/scriptorium/support/config/reddit_template.txt +17 -0
- data/{test/scriptorium-TEST-1754622690-146/views/sample → lib/scriptorium/support}/config/social.txt +1 -0
- data/lib/scriptorium/support/highlight/css.txt +2 -0
- data/lib/scriptorium/support/highlight/custom.css +119 -0
- data/lib/scriptorium/support/highlight/js.txt +1 -0
- data/lib/scriptorium/support/post_index/config.txt +15 -0
- data/lib/scriptorium/support/post_index/style.css +55 -0
- data/lib/scriptorium/support/templates/index_entry.lt3 +16 -0
- data/{test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 → lib/scriptorium/support/templates/initial_post.lt3} +5 -5
- data/lib/scriptorium/support/templates/post.lt3 +104 -0
- data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt → lib/scriptorium/support/theme/header.lt3} +1 -1
- data/lib/scriptorium/theme.rb +83 -70
- data/lib/scriptorium/version.rb +2 -2
- data/lib/scriptorium/view.rb +194 -149
- data/lib/scriptorium.rb +24 -1
- data/lib/skeleton.rb +4 -1
- data/scriptorium.gemspec +2 -1
- data/test/WEB_INTEGRATION_README.md +196 -0
- data/test/all +40 -0
- data/test/banner_svg/unit.rb +267 -35
- data/test/config/deployment.txt +5 -0
- data/test/integration/integration_test.rb +7 -7
- data/test/integration/preview_flow_test.rb +94 -0
- data/test/livetext_plugin_test.rb +453 -182
- data/test/manual/banner-tests/test01.html +82 -18
- data/test/manual/banner-tests/test02.html +82 -18
- data/test/manual/banner-tests/test03.html +82 -18
- data/test/manual/banner-tests/test04.html +89 -25
- data/test/manual/banner-tests/test05.html +89 -25
- data/test/manual/banner-tests/test06.html +89 -25
- data/test/manual/banner-tests/test07.html +89 -25
- data/test/manual/banner-tests/test08.html +82 -18
- data/test/manual/banner-tests/test09.html +82 -18
- data/test/manual/banner-tests/test10.html +82 -18
- data/test/manual/banner-tests/test11.html +82 -18
- data/test/manual/banner-tests/test12.html +82 -18
- data/test/manual/banner-tests/test13.html +82 -18
- data/test/manual/banner-tests/test14.html +82 -18
- data/test/manual/banner-tests/test15.html +82 -18
- data/test/manual/banner-tests/test16.html +82 -18
- data/test/manual/banner-tests/test17.html +82 -18
- data/test/manual/banner-tests/test18.html +90 -26
- data/test/manual/banner-tests/test19.html +90 -26
- data/test/manual/banner-tests/test20.html +90 -26
- data/test/manual/banner-tests/test21.html +90 -26
- data/test/manual/banner-tests/test22.html +90 -26
- data/test/manual/banner-tests/test23.html +90 -26
- data/test/manual/banner-tests/test24.html +90 -26
- data/test/manual/banner-tests/test25.html +89 -25
- data/test/manual/banner_environment.rb +15 -2
- data/test/manual/codemirror_demo.html +773 -0
- data/test/manual/create_posts_for_web.rb +114 -0
- data/test/manual/preview_manual_test.rb +129 -0
- data/test/manual/test_banner_features.rb +14 -14
- data/test/manual/test_banner_integration.rb +115 -0
- data/test/manual/test_banner_radial.rb +87 -0
- data/test/manual/test_syntax_highlighting.rb +60 -40
- data/test/support/preview_utils.rb +88 -0
- data/test/test_gem_assets.rb +48 -0
- data/test/test_helpers.rb +10 -0
- data/test/tui_editor_integration_test.rb +15 -15
- data/test/tui_integration_test.rb +687 -441
- data/test/unit/api.rb +757 -37
- data/test/unit/asset_management.rb +195 -221
- data/test/unit/backup_test.rb +451 -0
- data/test/unit/contract_test.rb +1 -23
- data/test/unit/core.rb +415 -61
- data/test/unit/deploy_config_test.rb +248 -0
- data/test/unit/deploy_test.rb +312 -21
- data/test/unit/edit_post_test.rb +168 -0
- data/test/unit/gem_asset_management.rb +36 -42
- data/test/unit/livetext_basic.rb +23 -35
- data/test/unit/livetext_compatibility.rb +7 -14
- data/test/unit/parse_cmd_test.rb +260 -0
- data/test/unit/{symlink_test.rb → permalink_copy_test.rb} +47 -49
- data/test/unit/post.rb +91 -26
- data/test/unit/post_index_config_test.rb +258 -0
- data/test/unit/post_state_helpers_test.rb +137 -0
- data/test/unit/read_commented_file_test.rb +8 -6
- data/test/unit/repo.rb +75 -54
- data/test/unit/social_test.rb +41 -44
- data/test/unit/syntax_highlighting.rb +70 -0
- data/test/unit/theme_management_test.rb +91 -0
- data/test/unit/view.rb +79 -12
- data/test/unit/widgets.rb +8 -8
- data/test/web_integration_test.rb +231 -0
- data/test/web_test_helper.rb +218 -0
- data/test/web_workflow_test.rb +527 -0
- data/ui/tui/bin/scriptorium +885 -415
- data/ui/web/app/app.rb +1398 -176
- data/ui/web/app/assets/livetext_mode.js +244 -0
- data/ui/web/app/error_helpers.rb +16 -16
- data/ui/web/app/views/advanced_config.erb +8 -2
- data/ui/web/app/views/asset_management.erb +56 -0
- data/ui/web/app/views/backup_management.erb +238 -0
- data/ui/web/app/views/config_widget.erb +232 -0
- data/ui/web/app/views/dashboard.erb +64 -72
- data/ui/web/app/views/deploy_config.erb +3 -0
- data/ui/web/app/views/edit_pages.erb +170 -2
- data/ui/web/app/views/edit_post.erb +130 -9
- data/ui/web/app/views/edit_theme.erb +73 -0
- data/ui/web/app/views/edit_theme_file.erb +74 -0
- data/ui/web/app/views/theme_management.erb +130 -0
- data/ui/web/app/views/view_dashboard.erb +666 -25
- data/ui/web/app/views/widgets.erb +249 -0
- data/ui/web/bin/scriptorium-web +35 -24
- data/ui/web/tmp/timing.log +17 -0
- data/ui/web/tmp/web_server.log +0 -5
- metadata +190 -116
- data/assets/back-icon.png +0 -0
- data/assets/icons/facebook.svg +0 -1
- data/assets/icons/github.svg +0 -1
- data/assets/icons/instagram.svg +0 -1
- data/assets/icons/reddit.svg +0 -1
- data/assets/icons/x.svg +0 -1
- data/assets/icons/youtube.svg +0 -1
- data/bin/scriptorium +0 -1511
- data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +0 -34
- data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +0 -50
- data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +0 -73
- data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +0 -70
- data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +0 -110
- data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +0 -73
- data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +0 -124
- data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +0 -46
- data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +0 -97
- data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +0 -211
- data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +0 -141
- data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +0 -211
- data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +0 -134
- data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +0 -41
- data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +0 -49
- data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +0 -46
- data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +0 -41
- data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +0 -41
- data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +0 -256
- data/lib/scriptorium/syntax_highlighter.rb +0 -234
- data/test/manual/deploy_symlink_demo.rb +0 -142
- data/test/manual/symlink_demo.rb +0 -117
- data/test/manual/test2.rb +0 -12
- data/test/manual/test_banner_from_file.rb +0 -150
- data/test/manual/test_banner_in_header.rb +0 -35
- data/test/manual/test_code_highlighting.rb +0 -68
- data/test/manual/test_complex_header.rb +0 -74
- data/test/manual/test_empty_header.rb +0 -32
- data/test/manual/test_radial_custom.rb +0 -58
- data/test/manual/test_radial_large_radius.rb +0 -52
- data/test/manual/test_svg_debug.rb +0 -47
- data/test/pages-demo/config/currentview.txt +0 -1
- data/test/pages-demo/views/demo/config/common.js +0 -57
- data/test/pages-demo/views/demo/config/footer.txt +0 -1
- data/test/pages-demo/views/demo/config/global-head.txt +0 -8
- data/test/pages-demo/views/demo/config/header.txt +0 -1
- data/test/pages-demo/views/demo/config/layout.txt +0 -1
- data/test/pages-demo/views/demo/config/left.txt +0 -1
- data/test/pages-demo/views/demo/config/main.txt +0 -1
- data/test/pages-demo/views/demo/config/right.txt +0 -1
- data/test/pages-demo/views/demo/config.txt +0 -3
- data/test/pages-demo/views/demo/output/panes/footer.html +0 -1
- data/test/pages-demo/views/demo/output/panes/header.html +0 -1
- data/test/pages-demo/views/demo/output/panes/left.html +0 -1
- data/test/pages-demo/views/demo/output/panes/main.html +0 -1
- data/test/pages-demo/views/demo/output/panes/right.html +0 -1
- data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +0 -5
- data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +0 -4
- data/test/scriptorium-TEST-1754622690-146/config/common.js +0 -57
- data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +0 -1
- data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +0 -9
- data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +0 -1
- data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +0 -4
- data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +0 -3
- data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +0 -8
- data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +0 -6
- data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +0 -1
- data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +0 -1
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +0 -1
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +0 -1
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +0 -14
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +0 -13
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +0 -1
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +0 -5
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +0 -4
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +0 -57
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +0 -5
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +0 -2
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +0 -9
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +0 -4
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +0 -5
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +0 -5
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +0 -7
- data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +0 -3
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +0 -1
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +0 -1
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +0 -1
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +0 -1
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +0 -1
- data/ui/web/tmp/web_server.pid +0 -1
- /data/{test/pages-demo/views/demo/config/bootstrap_css.txt → lib/scriptorium/support/bootstrap/css.txt} +0 -0
- /data/{test/pages-demo/views/demo/config/bootstrap_js.txt → lib/scriptorium/support/bootstrap/js.txt} +0 -0
- /data/{test/scriptorium-TEST-1754622690-146/views/sample → lib/scriptorium/support}/config/reddit.txt +0 -0
- /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout → lib/scriptorium/support/templates}/layout.txt +0 -0
- /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt → lib/scriptorium/support/theme/footer.lt3} +0 -0
- /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt → lib/scriptorium/support/theme/left.lt3} +0 -0
- /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt → lib/scriptorium/support/theme/main.lt3} +0 -0
- /data/{test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt → lib/scriptorium/support/theme/right.lt3} +0 -0
- /data/test/manual/banner-tests/{config.txt → svg.txt} +0 -0
- /data/test/manual/{test6.rb → test_advanced_widgets.rb} +0 -0
- /data/test/manual/{test1.rb → test_basic_posts.rb} +0 -0
- /data/test/manual/{test4.rb → test_layout_widgets.rb} +0 -0
- /data/test/manual/{test5.rb → test_pagination.rb} +0 -0
- /data/test/manual/{test3.rb → test_random_posts.rb} +0 -0
@@ -1,234 +0,0 @@
|
|
1
|
-
require 'rouge'
|
2
|
-
|
3
|
-
module Scriptorium
|
4
|
-
class SyntaxHighlighter
|
5
|
-
# Default theme - can be customized
|
6
|
-
DEFAULT_THEME = {
|
7
|
-
'keyword' => 'color: #07a; font-weight: bold;',
|
8
|
-
'string' => 'color: #690;',
|
9
|
-
'comment' => 'color: #708090; font-style: italic;',
|
10
|
-
'function' => 'color: #dd4a68;',
|
11
|
-
'number' => 'color: #905;',
|
12
|
-
'symbol' => 'color: #905;',
|
13
|
-
'operator' => 'color: #9a6e3a;',
|
14
|
-
'class-name' => 'color: #dd4a68;',
|
15
|
-
'regex' => 'color: #e90;',
|
16
|
-
'variable' => 'color: #e90;',
|
17
|
-
'interpolation' => 'color: #690;', # same as string
|
18
|
-
'error' => 'color: #d73a49; font-weight: bold;',
|
19
|
-
'whitespace' => 'color: transparent;',
|
20
|
-
'other' => 'color: #24292e;'
|
21
|
-
}
|
22
|
-
|
23
|
-
def initialize(theme = nil)
|
24
|
-
@theme = theme || DEFAULT_THEME
|
25
|
-
@formatter = Rouge::Formatters::HTML.new
|
26
|
-
end
|
27
|
-
|
28
|
-
# Highlight code with language detection
|
29
|
-
def highlight(code, language = nil)
|
30
|
-
return escape_html(code) if language.nil? || language.empty?
|
31
|
-
|
32
|
-
language = language.downcase.strip
|
33
|
-
|
34
|
-
# Map common language names to Rouge lexers
|
35
|
-
lexer_name = map_language(language)
|
36
|
-
return escape_html(code) unless lexer_name
|
37
|
-
|
38
|
-
begin
|
39
|
-
lexer = Rouge::Lexer.find(lexer_name)
|
40
|
-
puts "DEBUG: Found lexer: #{lexer.class}"
|
41
|
-
highlighted = @formatter.format(lexer.lex(code))
|
42
|
-
puts "DEBUG: Rouge output length: #{highlighted.length}"
|
43
|
-
puts "DEBUG: Raw Rouge output (first 500 chars): #{highlighted[0..500]}"
|
44
|
-
puts "DEBUG: HTML contains <div>: #{highlighted.include?('<div')}"
|
45
|
-
puts "DEBUG: HTML contains <br>: #{highlighted.include?('<br')}"
|
46
|
-
puts "DEBUG: HTML contains \\n: #{highlighted.include?("\n")}"
|
47
|
-
|
48
|
-
# Massage the output to use our CSS classes
|
49
|
-
massage_output(highlighted, language)
|
50
|
-
rescue => e
|
51
|
-
# Fallback to escaped HTML if highlighting fails
|
52
|
-
puts "DEBUG: Rouge highlighting failed for #{language}: #{e.message}"
|
53
|
-
puts "DEBUG: Backtrace: #{e.backtrace.first(3).join(', ')}"
|
54
|
-
escape_html(code)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Generate CSS for the theme
|
59
|
-
def generate_css
|
60
|
-
css = []
|
61
|
-
css << "/* Syntax highlighting styles */"
|
62
|
-
css << "pre {"
|
63
|
-
css << " background: #f5f5f5;"
|
64
|
-
css << " padding: 15px;"
|
65
|
-
css << " border-radius: 5px;"
|
66
|
-
css << " overflow-x: auto;"
|
67
|
-
css << "}"
|
68
|
-
css << ""
|
69
|
-
css << "pre code {"
|
70
|
-
css << " font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace;"
|
71
|
-
css << " font-size: 14px;"
|
72
|
-
css << "}"
|
73
|
-
css << ""
|
74
|
-
css << "/* Override Bootstrap height constraints for syntax highlighting */"
|
75
|
-
css << "pre code[class*=\"language-\"] {"
|
76
|
-
css << " height: auto !important;"
|
77
|
-
css << " max-height: none !important;"
|
78
|
-
css << " min-height: auto !important;"
|
79
|
-
css << " overflow: visible !important;"
|
80
|
-
css << "}"
|
81
|
-
css << ""
|
82
|
-
css << "pre:has(code[class*=\"language-\"]) {"
|
83
|
-
css << " height: auto !important;"
|
84
|
-
css << " max-height: none !important;"
|
85
|
-
css << " min-height: auto !important;"
|
86
|
-
css << " overflow: visible !important;"
|
87
|
-
css << "}"
|
88
|
-
|
89
|
-
@theme.each do |token, style|
|
90
|
-
css << ".token.#{token} { #{style} }"
|
91
|
-
end
|
92
|
-
|
93
|
-
css.join("\n")
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
# Map common language names to Rouge lexer names
|
99
|
-
def map_language(language)
|
100
|
-
language_map = {
|
101
|
-
'ruby' => 'ruby',
|
102
|
-
'rb' => 'ruby',
|
103
|
-
'javascript' => 'javascript',
|
104
|
-
'js' => 'javascript',
|
105
|
-
'elixir' => 'elixir',
|
106
|
-
'python' => 'python',
|
107
|
-
'py' => 'python',
|
108
|
-
'html' => 'html',
|
109
|
-
'css' => 'css',
|
110
|
-
'sql' => 'sql',
|
111
|
-
'bash' => 'bash',
|
112
|
-
'shell' => 'bash',
|
113
|
-
'sh' => 'bash',
|
114
|
-
'yaml' => 'yaml',
|
115
|
-
'yml' => 'yaml',
|
116
|
-
'json' => 'json',
|
117
|
-
'xml' => 'xml',
|
118
|
-
'markdown' => 'markdown',
|
119
|
-
'md' => 'markdown',
|
120
|
-
'go' => 'go',
|
121
|
-
'rust' => 'rust',
|
122
|
-
'java' => 'java',
|
123
|
-
'cpp' => 'cpp',
|
124
|
-
'c' => 'c',
|
125
|
-
'csharp' => 'csharp',
|
126
|
-
'cs' => 'csharp',
|
127
|
-
'php' => 'php',
|
128
|
-
'r' => 'r',
|
129
|
-
'scala' => 'scala',
|
130
|
-
'swift' => 'swift',
|
131
|
-
'kotlin' => 'kotlin',
|
132
|
-
'dart' => 'dart'
|
133
|
-
}
|
134
|
-
|
135
|
-
language_map[language]
|
136
|
-
end
|
137
|
-
|
138
|
-
# Massage Rouge output to use our CSS classes
|
139
|
-
def massage_output(html, language)
|
140
|
-
# Rouge outputs classes like 'k' for keyword, 's' for string, etc.
|
141
|
-
# We want to map these to our semantic class names
|
142
|
-
class_mapping = {
|
143
|
-
'k' => 'keyword', # keyword
|
144
|
-
's' => 'string', # string
|
145
|
-
'c' => 'comment', # comment
|
146
|
-
'f' => 'function', # function
|
147
|
-
'n' => 'number', # number
|
148
|
-
'o' => 'operator', # operator
|
149
|
-
'c1' => 'comment', # comment
|
150
|
-
's1' => 'string', # string
|
151
|
-
's2' => 'string', # string
|
152
|
-
'nb' => 'function', # function name
|
153
|
-
'na' => 'function', # function argument
|
154
|
-
'nc' => 'class-name', # class name
|
155
|
-
'nd' => 'function', # function definition
|
156
|
-
'ne' => 'variable', # variable
|
157
|
-
'nf' => 'function', # function
|
158
|
-
'ni' => 'variable', # variable
|
159
|
-
'nl' => 'number', # number literal
|
160
|
-
'nn' => 'class-name', # class name
|
161
|
-
'no' => 'constant', # constant
|
162
|
-
'nt' => 'tag', # tag name
|
163
|
-
'nv' => 'variable', # variable
|
164
|
-
'ow' => 'operator', # operator
|
165
|
-
'p' => 'punctuation', # punctuation
|
166
|
-
'pi' => 'doctype', # doctype
|
167
|
-
# JavaScript-specific mappings
|
168
|
-
'kd' => 'keyword', # keyword declaration (function, var, etc.)
|
169
|
-
'nx' => 'variable', # variable name
|
170
|
-
'dl' => 'string', # string delimiter
|
171
|
-
'cm' => 'comment', # comment
|
172
|
-
'cp' => 'comment', # comment
|
173
|
-
'cs' => 'comment', # comment
|
174
|
-
'ge' => 'comment', # comment
|
175
|
-
'gh' => 'comment', # comment
|
176
|
-
'gp' => 'comment', # comment
|
177
|
-
'gs' => 'comment', # comment
|
178
|
-
'gu' => 'comment', # comment
|
179
|
-
'il' => 'number', # number literal
|
180
|
-
'm' => 'number', # number
|
181
|
-
'mf' => 'number', # number
|
182
|
-
'mh' => 'number', # number
|
183
|
-
'mi' => 'number', # number
|
184
|
-
'mo' => 'number', # number
|
185
|
-
'sb' => 'string', # string
|
186
|
-
'sc' => 'string', # string
|
187
|
-
'sd' => 'string', # string
|
188
|
-
'se' => 'string', # string
|
189
|
-
'sh' => 'string', # string
|
190
|
-
'si' => 'string', # string
|
191
|
-
'sr' => 'string', # string
|
192
|
-
'ss' => 'string', # string
|
193
|
-
'vi' => 'variable', # instance variable (@name)
|
194
|
-
'vc' => 'variable', # class variable (@@name)
|
195
|
-
'vg' => 'variable', # global variable ($name)
|
196
|
-
'bp' => 'variable', # built-in pseudo
|
197
|
-
'err' => 'error', # error
|
198
|
-
'w' => 'whitespace', # whitespace
|
199
|
-
'x' => 'other', # other
|
200
|
-
'kc' => 'constant' # constant (true, false, null)
|
201
|
-
}
|
202
|
-
|
203
|
-
# Replace Rouge's short class names with our semantic names
|
204
|
-
class_mapping.each do |rouge_class, semantic_class|
|
205
|
-
html.gsub!(/class="#{rouge_class}"/, "class=\"token #{semantic_class}\"")
|
206
|
-
html.gsub!(/class='#{rouge_class}'/, "class='token #{semantic_class}'")
|
207
|
-
end
|
208
|
-
|
209
|
-
# Add 'token' class to all spans that don't have it
|
210
|
-
html.gsub!(/<span class="([^"]*?)">/, '<span class="token \1">')
|
211
|
-
html.gsub!(/<span class='([^']*?)'>/, "<span class='token \\1'>")
|
212
|
-
|
213
|
-
# Clean up duplicate 'token token' classes
|
214
|
-
html.gsub!(/class="token token ([^"]*)"/, 'class="token \1"')
|
215
|
-
html.gsub!(/class='token token ([^']*)'/, "class='token \\1'")
|
216
|
-
|
217
|
-
html
|
218
|
-
end
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
# Simple HTML escaping
|
223
|
-
def escape_html(text)
|
224
|
-
text.to_s
|
225
|
-
.gsub('&', '&')
|
226
|
-
.gsub('<', '<')
|
227
|
-
.gsub('>', '>')
|
228
|
-
.gsub('"', '"')
|
229
|
-
.gsub("'", ''')
|
230
|
-
end
|
231
|
-
|
232
|
-
|
233
|
-
end
|
234
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Manual test script to demonstrate deployment with symlinks
|
4
|
-
# Run with: ruby test/manual/deploy_symlink_demo.rb
|
5
|
-
|
6
|
-
require_relative '../../lib/scriptorium'
|
7
|
-
require_relative '../test_helpers'
|
8
|
-
|
9
|
-
class DeploySymlinkDemo
|
10
|
-
include Scriptorium::Helpers
|
11
|
-
include TestHelpers
|
12
|
-
|
13
|
-
def run
|
14
|
-
puts "=== Deployment with Symlinks Demo ==="
|
15
|
-
puts
|
16
|
-
|
17
|
-
# Create test repository
|
18
|
-
puts "1. Creating test repository..."
|
19
|
-
@repo = Scriptorium::Repo.create("test/scriptorium-TEST", testmode: true)
|
20
|
-
@view = @repo.create_view("demo_view", "Demo View", "A demo view for deployment")
|
21
|
-
puts " ✓ Created repository and view"
|
22
|
-
puts
|
23
|
-
|
24
|
-
# Create a test post
|
25
|
-
puts "2. Creating test post..."
|
26
|
-
post_title = "Deployment Test Post with Symlinks"
|
27
|
-
post_body = "This post tests deployment with symlinks."
|
28
|
-
|
29
|
-
draft_name = @repo.create_draft(title: post_title, body: post_body)
|
30
|
-
post_num = @repo.finish_draft(draft_name)
|
31
|
-
puts " ✓ Created post ##{post_num}: #{post_title}"
|
32
|
-
puts
|
33
|
-
|
34
|
-
# Generate the post
|
35
|
-
puts "3. Generating post..."
|
36
|
-
@repo.generate_post(post_num)
|
37
|
-
puts " ✓ Generated post"
|
38
|
-
puts
|
39
|
-
|
40
|
-
# Check the files
|
41
|
-
puts "4. Checking generated files..."
|
42
|
-
|
43
|
-
numbered_slug = slugify(post_num, post_title) + ".html"
|
44
|
-
clean_slug = clean_slugify(post_title) + ".html"
|
45
|
-
|
46
|
-
numbered_path = @view.dir/:output/:permalink/numbered_slug
|
47
|
-
clean_symlink_path = @view.dir/:output/:permalink/clean_slug
|
48
|
-
|
49
|
-
puts " Numbered file: #{numbered_path}"
|
50
|
-
puts " Clean symlink: #{clean_symlink_path}"
|
51
|
-
puts
|
52
|
-
|
53
|
-
# Verify files exist
|
54
|
-
if File.exist?(numbered_path)
|
55
|
-
puts " ✓ Numbered file exists"
|
56
|
-
else
|
57
|
-
puts " ✗ Numbered file missing"
|
58
|
-
end
|
59
|
-
|
60
|
-
if File.exist?(clean_symlink_path)
|
61
|
-
puts " ✓ Clean symlink exists"
|
62
|
-
else
|
63
|
-
puts " ✗ Clean symlink missing"
|
64
|
-
end
|
65
|
-
|
66
|
-
if File.symlink?(clean_symlink_path)
|
67
|
-
puts " ✓ Clean symlink is actually a symlink"
|
68
|
-
symlink_target = File.readlink(clean_symlink_path)
|
69
|
-
puts " ✓ Symlink points to: #{symlink_target}"
|
70
|
-
else
|
71
|
-
puts " ✗ Clean symlink is not a symlink"
|
72
|
-
end
|
73
|
-
puts
|
74
|
-
|
75
|
-
# Test deployment simulation
|
76
|
-
puts "5. Testing deployment simulation..."
|
77
|
-
|
78
|
-
# Create a test deployment directory
|
79
|
-
test_deploy_dir = "test/deploy-test"
|
80
|
-
FileUtils.rm_rf(test_deploy_dir) if Dir.exist?(test_deploy_dir)
|
81
|
-
FileUtils.mkdir_p(test_deploy_dir)
|
82
|
-
|
83
|
-
# Simulate rsync command with symlink preservation
|
84
|
-
output_dir = @view.dir/:output
|
85
|
-
rsync_cmd = "rsync -r -z -l #{output_dir}/ #{test_deploy_dir}/"
|
86
|
-
puts " Simulating: #{rsync_cmd}"
|
87
|
-
|
88
|
-
# Actually copy files (simulating rsync)
|
89
|
-
FileUtils.cp_r("#{output_dir}/.", test_deploy_dir)
|
90
|
-
|
91
|
-
# Check if symlinks were preserved
|
92
|
-
deployed_symlink = "#{test_deploy_dir}/permalink/#{clean_slug}"
|
93
|
-
deployed_target = "#{test_deploy_dir}/permalink/#{numbered_slug}"
|
94
|
-
|
95
|
-
if File.exist?(deployed_symlink)
|
96
|
-
puts " ✓ Symlink exists in deployment directory"
|
97
|
-
|
98
|
-
if File.symlink?(deployed_symlink)
|
99
|
-
puts " ✓ Symlink is preserved in deployment"
|
100
|
-
deployed_target_readlink = File.readlink(deployed_symlink)
|
101
|
-
puts " ✓ Deployed symlink points to: #{deployed_target_readlink}"
|
102
|
-
|
103
|
-
if File.exist?(deployed_target)
|
104
|
-
puts " ✓ Symlink target exists in deployment"
|
105
|
-
else
|
106
|
-
puts " ✗ Symlink target missing in deployment"
|
107
|
-
end
|
108
|
-
else
|
109
|
-
puts " ✗ Symlink was not preserved (copied as file)"
|
110
|
-
end
|
111
|
-
else
|
112
|
-
puts " ✗ Symlink missing in deployment directory"
|
113
|
-
end
|
114
|
-
puts
|
115
|
-
|
116
|
-
# Show deployment structure
|
117
|
-
puts "6. Deployment directory structure:"
|
118
|
-
if Dir.exist?(test_deploy_dir)
|
119
|
-
Dir.glob("#{test_deploy_dir}/**/*").sort.each do |file|
|
120
|
-
relative_path = file.sub("#{test_deploy_dir}/", "")
|
121
|
-
if File.symlink?(file)
|
122
|
-
target = File.readlink(file)
|
123
|
-
puts " #{relative_path} -> #{target} (symlink)"
|
124
|
-
elsif File.directory?(file)
|
125
|
-
puts " #{relative_path}/ (directory)"
|
126
|
-
else
|
127
|
-
puts " #{relative_path} (file)"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
puts
|
132
|
-
|
133
|
-
puts "=== Demo Complete ==="
|
134
|
-
puts
|
135
|
-
puts "To clean up, run: rm -rf test/scriptorium-TEST test/deploy-test"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
if __FILE__ == $0
|
140
|
-
demo = DeploySymlinkDemo.new
|
141
|
-
demo.run
|
142
|
-
end
|
data/test/manual/symlink_demo.rb
DELETED
@@ -1,117 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# Manual test script to demonstrate symlink functionality
|
4
|
-
# Run with: ruby test/manual/symlink_demo.rb
|
5
|
-
|
6
|
-
require_relative '../../lib/scriptorium'
|
7
|
-
require_relative '../test_helpers'
|
8
|
-
|
9
|
-
class SymlinkDemo
|
10
|
-
include Scriptorium::Helpers
|
11
|
-
include TestHelpers
|
12
|
-
|
13
|
-
def run
|
14
|
-
puts "=== Symlink Functionality Demo ==="
|
15
|
-
puts
|
16
|
-
|
17
|
-
# Create test repository
|
18
|
-
puts "1. Creating test repository..."
|
19
|
-
@repo = Scriptorium::Repo.create("test/scriptorium-TEST", testmode: true)
|
20
|
-
@view = @repo.create_view("demo_view", "Demo View", "A demo view for symlinks")
|
21
|
-
puts " ✓ Created repository and view"
|
22
|
-
puts
|
23
|
-
|
24
|
-
# Create a test post
|
25
|
-
puts "2. Creating test post..."
|
26
|
-
post_title = "My First Test Post with Special Characters: & < > \" ' !"
|
27
|
-
post_body = "This is the body of my test post. It contains some content."
|
28
|
-
|
29
|
-
draft_name = @repo.create_draft(title: post_title, body: post_body)
|
30
|
-
post_num = @repo.finish_draft(draft_name)
|
31
|
-
puts " ✓ Created post ##{post_num}: #{post_title}"
|
32
|
-
puts
|
33
|
-
|
34
|
-
# Generate the post
|
35
|
-
puts "3. Generating post..."
|
36
|
-
@repo.generate_post(post_num)
|
37
|
-
puts " ✓ Generated post"
|
38
|
-
puts
|
39
|
-
|
40
|
-
# Check the files
|
41
|
-
puts "4. Checking generated files..."
|
42
|
-
|
43
|
-
numbered_slug = slugify(post_num, post_title) + ".html"
|
44
|
-
clean_slug = clean_slugify(post_title) + ".html"
|
45
|
-
|
46
|
-
numbered_path = @view.dir/:output/:permalink/numbered_slug
|
47
|
-
clean_symlink_path = @view.dir/:output/:permalink/clean_slug
|
48
|
-
|
49
|
-
puts " Numbered file: #{numbered_path}"
|
50
|
-
puts " Clean symlink: #{clean_symlink_path}"
|
51
|
-
puts
|
52
|
-
|
53
|
-
# Verify files exist
|
54
|
-
if File.exist?(numbered_path)
|
55
|
-
puts " ✓ Numbered file exists"
|
56
|
-
else
|
57
|
-
puts " ✗ Numbered file missing"
|
58
|
-
end
|
59
|
-
|
60
|
-
if File.exist?(clean_symlink_path)
|
61
|
-
puts " ✓ Clean symlink exists"
|
62
|
-
else
|
63
|
-
puts " ✗ Clean symlink missing"
|
64
|
-
end
|
65
|
-
|
66
|
-
if File.symlink?(clean_symlink_path)
|
67
|
-
puts " ✓ Clean symlink is actually a symlink"
|
68
|
-
symlink_target = File.readlink(clean_symlink_path)
|
69
|
-
puts " ✓ Symlink points to: #{symlink_target}"
|
70
|
-
else
|
71
|
-
puts " ✗ Clean symlink is not a symlink"
|
72
|
-
end
|
73
|
-
puts
|
74
|
-
|
75
|
-
# Show the URLs
|
76
|
-
puts "5. Generated URLs:"
|
77
|
-
puts " Numbered URL: /permalink/#{numbered_slug}"
|
78
|
-
puts " Clean URL: /permalink/#{clean_slug}"
|
79
|
-
puts
|
80
|
-
|
81
|
-
# Test the symlink
|
82
|
-
puts "6. Testing symlink..."
|
83
|
-
if File.symlink?(clean_symlink_path)
|
84
|
-
symlink_target = File.readlink(clean_symlink_path)
|
85
|
-
if symlink_target == numbered_slug
|
86
|
-
puts " ✓ Symlink correctly points to numbered file"
|
87
|
-
else
|
88
|
-
puts " ✗ Symlink points to wrong target: #{symlink_target}"
|
89
|
-
end
|
90
|
-
else
|
91
|
-
puts " ✗ Clean symlink is not a symlink"
|
92
|
-
end
|
93
|
-
puts
|
94
|
-
|
95
|
-
# Show file contents
|
96
|
-
puts "7. File contents:"
|
97
|
-
if File.exist?(numbered_path)
|
98
|
-
content = File.read(numbered_path)
|
99
|
-
puts " Numbered file size: #{content.length} bytes"
|
100
|
-
puts " Contains 'Back to Blog' link: #{content.include?('Back to Blog') ? 'Yes' : 'No'}"
|
101
|
-
end
|
102
|
-
|
103
|
-
if File.exist?(clean_symlink_path) && File.symlink?(clean_symlink_path)
|
104
|
-
puts " Clean symlink: points to #{File.readlink(clean_symlink_path)}"
|
105
|
-
end
|
106
|
-
puts
|
107
|
-
|
108
|
-
puts "=== Demo Complete ==="
|
109
|
-
puts
|
110
|
-
puts "To clean up, run: rm -rf test/scriptorium-TEST"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
if __FILE__ == $0
|
115
|
-
demo = SymlinkDemo.new
|
116
|
-
demo.run
|
117
|
-
end
|
data/test/manual/test2.rb
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require_relative '../../lib/scriptorium'
|
4
|
-
|
5
|
-
include Scriptorium::Helpers
|
6
|
-
|
7
|
-
# Simple banner test from configuration file
|
8
|
-
def test_banner_from_file(config_file, output_file = nil)
|
9
|
-
# Default output file if not specified
|
10
|
-
output_file ||= "banner_output.html"
|
11
|
-
|
12
|
-
# Read the configuration file
|
13
|
-
unless File.exist?(config_file)
|
14
|
-
puts "Error: Configuration file '#{config_file}' not found"
|
15
|
-
exit 1
|
16
|
-
end
|
17
|
-
|
18
|
-
# Use the read_commented_file helper to read the config
|
19
|
-
config_lines = read_commented_file(config_file)
|
20
|
-
config_content = File.read(config_file) # Keep original for display
|
21
|
-
|
22
|
-
puts "Read configuration from: #{config_file}"
|
23
|
-
puts "Found #{config_lines.length} configuration lines (comments removed)"
|
24
|
-
|
25
|
-
# Create banner with default title/subtitle
|
26
|
-
banner = Scriptorium::BannerSVG.new("Test Banner", "Generated from config file")
|
27
|
-
|
28
|
-
# Write config to temporary file for banner to read
|
29
|
-
temp_config = "temp_banner_config.txt"
|
30
|
-
File.write(temp_config, config_content)
|
31
|
-
|
32
|
-
# Parse and generate the banner
|
33
|
-
banner.parse_header_svg
|
34
|
-
svg_output = banner.generate_svg
|
35
|
-
|
36
|
-
# Clean up temp config file
|
37
|
-
File.delete(temp_config) if File.exist?(temp_config)
|
38
|
-
|
39
|
-
# Create HTML output
|
40
|
-
html_content = <<~HTML
|
41
|
-
<!DOCTYPE html>
|
42
|
-
<html>
|
43
|
-
<head>
|
44
|
-
<title>Banner Test - #{File.basename(config_file)}</title>
|
45
|
-
<style>
|
46
|
-
body {
|
47
|
-
font-family: Arial, sans-serif;
|
48
|
-
margin: 0;
|
49
|
-
padding: 20px;
|
50
|
-
background: #f5f5f5;
|
51
|
-
}
|
52
|
-
.banner {
|
53
|
-
width: 100%;
|
54
|
-
max-width: 800px;
|
55
|
-
margin: 0 auto 20px auto;
|
56
|
-
border: 2px solid #007cba;
|
57
|
-
border-radius: 8px;
|
58
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
59
|
-
}
|
60
|
-
.config {
|
61
|
-
background: white;
|
62
|
-
padding: 20px;
|
63
|
-
margin: 20px auto;
|
64
|
-
max-width: 800px;
|
65
|
-
border-radius: 8px;
|
66
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
67
|
-
}
|
68
|
-
.config h3 {
|
69
|
-
margin-top: 0;
|
70
|
-
color: #333;
|
71
|
-
}
|
72
|
-
.config pre {
|
73
|
-
background: #f8f9fa;
|
74
|
-
padding: 15px;
|
75
|
-
border-radius: 4px;
|
76
|
-
overflow-x: auto;
|
77
|
-
font-family: monospace;
|
78
|
-
font-size: 12px;
|
79
|
-
}
|
80
|
-
.info {
|
81
|
-
background: white;
|
82
|
-
padding: 20px;
|
83
|
-
margin: 20px auto;
|
84
|
-
max-width: 800px;
|
85
|
-
border-radius: 8px;
|
86
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
87
|
-
}
|
88
|
-
.processed-config {
|
89
|
-
background: #e8f4fd;
|
90
|
-
padding: 15px;
|
91
|
-
margin: 10px 0;
|
92
|
-
border-radius: 4px;
|
93
|
-
font-family: monospace;
|
94
|
-
font-size: 12px;
|
95
|
-
}
|
96
|
-
</style>
|
97
|
-
</head>
|
98
|
-
<body>
|
99
|
-
<div class="banner">
|
100
|
-
#{svg_output}
|
101
|
-
</div>
|
102
|
-
|
103
|
-
<div class="info">
|
104
|
-
<h3>Banner Information</h3>
|
105
|
-
<p><strong>Configuration file:</strong> #{config_file}</p>
|
106
|
-
<p><strong>Output file:</strong> #{output_file}</p>
|
107
|
-
<p><strong>Generated:</strong> #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}</p>
|
108
|
-
<p><strong>Configuration lines processed:</strong> #{config_lines.length}</p>
|
109
|
-
</div>
|
110
|
-
|
111
|
-
<div class="config">
|
112
|
-
<h3>Configuration Used (with comments)</h3>
|
113
|
-
<pre>#{config_content}</pre>
|
114
|
-
|
115
|
-
<h3>Processed Configuration (comments removed)</h3>
|
116
|
-
<div class="processed-config">
|
117
|
-
#{config_lines.map { |line| line.empty? ? "# (empty line)" : line }.join("\n")}
|
118
|
-
</div>
|
119
|
-
</div>
|
120
|
-
</body>
|
121
|
-
</html>
|
122
|
-
HTML
|
123
|
-
|
124
|
-
# Write the HTML file
|
125
|
-
File.write(output_file, html_content)
|
126
|
-
puts "Generated banner HTML: #{output_file}"
|
127
|
-
|
128
|
-
# Open in browser if on macOS
|
129
|
-
if RUBY_PLATFORM.include?('darwin')
|
130
|
-
puts "Opening in browser..."
|
131
|
-
system("open #{output_file}")
|
132
|
-
else
|
133
|
-
puts "Open #{output_file} in your browser to view the banner"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# Main execution
|
138
|
-
if ARGV.empty?
|
139
|
-
puts "Usage: ruby test_banner_from_file.rb <config_file> [output_file]"
|
140
|
-
puts ""
|
141
|
-
puts "Example:"
|
142
|
-
puts " ruby test_banner_from_file.rb my_banner_config.txt"
|
143
|
-
puts " ruby test_banner_from_file.rb my_banner_config.txt custom_output.html"
|
144
|
-
exit 1
|
145
|
-
end
|
146
|
-
|
147
|
-
config_file = ARGV[0]
|
148
|
-
output_file = ARGV[1] # Optional
|
149
|
-
|
150
|
-
test_banner_from_file(config_file, output_file)
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require_relative './environment'
|
2
|
-
|
3
|
-
manual_setup
|
4
|
-
|
5
|
-
# Create a simple view
|
6
|
-
view = @repo.create_view("banner-test", "My Banner Site", "A site with SVG banner in header")
|
7
|
-
|
8
|
-
# Set up layout with header
|
9
|
-
File.open(view.dir/:config/"layout.txt", "w") do |f|
|
10
|
-
f.puts "header"
|
11
|
-
f.puts "main"
|
12
|
-
end
|
13
|
-
|
14
|
-
# Generate the empty containers
|
15
|
-
view.generate_empty_containers
|
16
|
-
|
17
|
-
# Configure the header to include the SVG banner
|
18
|
-
File.open(view.dir/:config/"header.txt", "w") do |f|
|
19
|
-
f.puts "banner svg"
|
20
|
-
end
|
21
|
-
|
22
|
-
# Generate the front page
|
23
|
-
view.generate_front_page
|
24
|
-
|
25
|
-
instruct <<~EOS
|
26
|
-
This test shows how to insert an SVG banner into the header.
|
27
|
-
|
28
|
-
The header.txt contains:
|
29
|
-
- banner svg (inserts the SVG banner)
|
30
|
-
|
31
|
-
The SVG banner will appear at the top of the header.
|
32
|
-
The banner automatically uses the view's title and subtitle as its content.
|
33
|
-
EOS
|
34
|
-
|
35
|
-
examine view
|