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.
- checksums.yaml +4 -4
- data/README.lt3 +324 -0
- data/README.md +3155 -1
- data/assets/.DS_Store +0 -0
- data/assets/README.md +44 -0
- data/assets/back-icon.png +0 -0
- data/assets/icons/facebook.svg +1 -0
- data/assets/icons/github.svg +1 -0
- data/assets/icons/instagram.svg +1 -0
- data/assets/icons/reddit.svg +1 -0
- data/assets/icons/ui/.DS_Store +0 -0
- data/assets/icons/ui/back.png +0 -0
- data/assets/icons/ui/copy.png +0 -0
- data/assets/icons/ui/down.png +0 -0
- data/assets/icons/ui/end.png +0 -0
- data/assets/icons/ui/exit.png +0 -0
- data/assets/icons/ui/foo +10 -0
- data/assets/icons/ui/home.png +0 -0
- data/assets/icons/ui/left.png +0 -0
- data/assets/icons/ui/next.png +0 -0
- data/assets/icons/ui/right.png +0 -0
- data/assets/icons/ui/start.png +0 -0
- data/assets/icons/ui/up.png +0 -0
- data/assets/icons/x.svg +1 -0
- data/assets/icons/youtube.svg +1 -0
- data/assets/samples/placeholder.svg +9 -0
- data/assets/themes/standard/favicon.svg +6 -0
- data/bin/scriptorium +1511 -0
- data/doc/README.txt +6 -0
- data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +95 -0
- data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +34 -0
- data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +50 -0
- data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +31 -0
- data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +73 -0
- data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +64 -0
- data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +70 -0
- data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
- data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +110 -0
- data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +73 -0
- data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
- data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +124 -0
- data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +46 -0
- data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +97 -0
- data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
- data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +211 -0
- data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +141 -0
- data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +211 -0
- data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +134 -0
- data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +41 -0
- data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +45 -0
- data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +30 -0
- data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +49 -0
- data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +46 -0
- data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +41 -0
- data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +41 -0
- data/doc/anti-amnesia/20250807-213025.md +116 -0
- data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +256 -0
- data/doc/banner_svg_config.md +114 -0
- data/doc/contrib.lt3 +8 -0
- data/doc/dependencies.md +281 -0
- data/doc/hacker.lt3 +5 -0
- data/doc/reddit_credentials_template.json +8 -0
- data/doc/reddit_integration.md +207 -0
- data/doc/user.lt3 +38 -0
- data/doc/user_guide_section_1.md +137 -0
- data/doc/user_guide_section_10.md +515 -0
- data/doc/user_guide_section_11.md +708 -0
- data/doc/user_guide_section_2.md +233 -0
- data/doc/user_guide_section_3.md +5 -0
- data/doc/user_guide_section_4.md +221 -0
- data/doc/user_guide_section_5.md +243 -0
- data/doc/user_guide_section_6.md +147 -0
- data/doc/user_guide_section_7.md +311 -0
- data/doc/user_guide_section_8.md +224 -0
- data/doc/user_guide_section_9.md +375 -0
- data/doc/userdoc-toc.txt +88 -0
- data/lib/rouge/lexers/livetext.rb +74 -0
- data/lib/scriptorium/api.rb +640 -0
- data/lib/scriptorium/banner_svg.rb +742 -0
- data/lib/scriptorium/contract.rb +33 -0
- data/lib/scriptorium/exceptions.rb +170 -1
- data/lib/scriptorium/helpers.rb +475 -0
- data/lib/scriptorium/post.rb +195 -0
- data/lib/scriptorium/reddit.rb +83 -0
- data/lib/scriptorium/repo.rb +624 -0
- data/lib/scriptorium/standard_files.rb +515 -0
- data/lib/scriptorium/syntax_highlighter.rb +234 -0
- data/lib/scriptorium/theme.rb +179 -0
- data/lib/scriptorium/version.rb +2 -2
- data/lib/scriptorium/view.rb +976 -0
- data/lib/scriptorium/widgets/featured_posts.rb +149 -0
- data/lib/scriptorium/widgets/links.rb +112 -0
- data/lib/scriptorium/widgets/pages.rb +133 -0
- data/lib/scriptorium/widgets/widget.rb +133 -0
- data/lib/scriptorium.rb +21 -40
- data/lib/skeleton.rb +8 -2
- data/scriptorium.gemspec +15 -4
- data/test/README.md +69 -0
- data/test/all +43 -0
- data/test/api_demo.rb +99 -0
- data/test/assets/imagenotfound.jpg +0 -0
- data/test/assets/images/.DS_Store +0 -0
- data/test/assets/images/README.md +27 -0
- data/test/assets/images/odd_aspect.png +0 -0
- data/test/assets/images/perfect.png +0 -0
- data/test/assets/images/small.png +0 -0
- data/test/assets/images/tall.png +0 -0
- data/test/assets/images/very_tall.png +0 -0
- data/test/assets/images/very_wide.png +0 -0
- data/test/assets/images/wide.png +0 -0
- data/test/assets/testbanner.jpg +0 -0
- data/test/banner_svg/simple_helpers.rb +13 -0
- data/test/banner_svg/unit.rb +768 -0
- data/test/ed_test.rb +204 -0
- data/test/integration/cursor_banner_combinations.rb +193 -0
- data/test/integration/cursor_banner_features.rb +374 -0
- data/test/integration/integration_test.rb +326 -0
- data/test/livetext_plugin_test.rb +229 -0
- data/test/manual/asset_mgmt.rb +67 -0
- data/test/manual/banner-tests/config.txt +3 -0
- data/test/manual/banner-tests/index.html +45 -0
- data/test/manual/banner-tests/test01.html +58 -0
- data/test/manual/banner-tests/test02.html +58 -0
- data/test/manual/banner-tests/test03.html +58 -0
- data/test/manual/banner-tests/test04.html +65 -0
- data/test/manual/banner-tests/test05.html +65 -0
- data/test/manual/banner-tests/test06.html +65 -0
- data/test/manual/banner-tests/test07.html +65 -0
- data/test/manual/banner-tests/test08.html +59 -0
- data/test/manual/banner-tests/test09.html +59 -0
- data/test/manual/banner-tests/test10.html +59 -0
- data/test/manual/banner-tests/test11.html +59 -0
- data/test/manual/banner-tests/test12.html +59 -0
- data/test/manual/banner-tests/test13.html +59 -0
- data/test/manual/banner-tests/test14.html +59 -0
- data/test/manual/banner-tests/test15.html +58 -0
- data/test/manual/banner-tests/test16.html +58 -0
- data/test/manual/banner-tests/test17.html +58 -0
- data/test/manual/banner-tests/test18.html +68 -0
- data/test/manual/banner-tests/test19.html +68 -0
- data/test/manual/banner-tests/test20.html +68 -0
- data/test/manual/banner-tests/test21.html +68 -0
- data/test/manual/banner-tests/test22.html +68 -0
- data/test/manual/banner-tests/test23.html +68 -0
- data/test/manual/banner-tests/test24.html +68 -0
- data/test/manual/banner-tests/test25.html +67 -0
- data/test/manual/banner_environment.rb +192 -0
- data/test/manual/deploy_symlink_demo.rb +142 -0
- data/test/manual/environment.rb +67 -0
- data/test/manual/make_banner.rb +153 -0
- data/test/manual/sample_banner_config.txt +12 -0
- data/test/manual/symlink_demo.rb +117 -0
- data/test/manual/test1.rb +47 -0
- data/test/manual/test2.rb +12 -0
- data/test/manual/test3.rb +38 -0
- data/test/manual/test4.rb +40 -0
- data/test/manual/test5.rb +24 -0
- data/test/manual/test6.rb +73 -0
- data/test/manual/test_banner_combinations.rb +120 -0
- data/test/manual/test_banner_features.rb +306 -0
- data/test/manual/test_banner_from_file.rb +150 -0
- data/test/manual/test_banner_in_header.rb +35 -0
- data/test/manual/test_code_highlighting.rb +68 -0
- data/test/manual/test_complex_header.rb +74 -0
- data/test/manual/test_empty_header.rb +32 -0
- data/test/manual/test_radial_custom.rb +58 -0
- data/test/manual/test_radial_large_radius.rb +52 -0
- data/test/manual/test_svg_debug.rb +47 -0
- data/test/manual/test_syntax_highlighting.rb +147 -0
- data/test/pages-demo/config/currentview.txt +1 -0
- data/test/pages-demo/views/demo/config/bootstrap_css.txt +5 -0
- data/test/pages-demo/views/demo/config/bootstrap_js.txt +4 -0
- data/test/pages-demo/views/demo/config/common.js +57 -0
- data/test/pages-demo/views/demo/config/footer.txt +1 -0
- data/test/pages-demo/views/demo/config/global-head.txt +8 -0
- data/test/pages-demo/views/demo/config/header.txt +1 -0
- data/test/pages-demo/views/demo/config/layout.txt +1 -0
- data/test/pages-demo/views/demo/config/left.txt +1 -0
- data/test/pages-demo/views/demo/config/main.txt +1 -0
- data/test/pages-demo/views/demo/config/right.txt +1 -0
- data/test/pages-demo/views/demo/config.txt +3 -0
- data/test/pages-demo/views/demo/output/panes/footer.html +1 -0
- data/test/pages-demo/views/demo/output/panes/header.html +1 -0
- data/test/pages-demo/views/demo/output/panes/left.html +1 -0
- data/test/pages-demo/views/demo/output/panes/main.html +1 -0
- data/test/pages-demo/views/demo/output/panes/right.html +1 -0
- data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
- data/test/rubytext/rubytext_demo_test.rb +42 -0
- data/test/rubytext/rubytext_testing_guide.md +277 -0
- data/test/run_automated_tests.rb +45 -0
- data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/config/common.js +57 -0
- data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +9 -0
- data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +4 -0
- data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +8 -0
- data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +6 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 +12 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt +2 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/layout.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +14 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +13 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +57 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +2 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +9 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/reddit.txt +10 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/social.txt +7 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +7 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +1 -0
- data/test/staging/.DS_Store +0 -0
- data/test/syntax_highlighting_test.lt3 +124 -0
- data/test/test_helpers.rb +230 -0
- data/test/tui_editor_integration_test.rb +296 -0
- data/test/tui_integration_test.rb +637 -0
- data/test/unit/api.rb +1056 -0
- data/test/unit/asset_management.rb +245 -0
- data/test/unit/clipboard_test.rb +60 -0
- data/test/unit/contract_test.rb +91 -0
- data/test/unit/core.rb +857 -0
- data/test/unit/deploy_test.rb +187 -0
- data/test/unit/gem_asset_management.rb +189 -0
- data/test/unit/livetext_basic.rb +69 -0
- data/test/unit/livetext_compatibility.rb +89 -0
- data/test/unit/post.rb +244 -0
- data/test/unit/read_commented_file_test.rb +276 -0
- data/test/unit/reddit_test.rb +235 -0
- data/test/unit/repo.rb +548 -0
- data/test/unit/social_test.rb +369 -0
- data/test/unit/symlink_test.rb +213 -0
- data/test/unit/view.rb +431 -0
- data/test/unit/widgets.rb +669 -0
- data/test/wizard_test.rb +123 -0
- data/ui/README.md +67 -0
- data/ui/common/lib/ui_common.rb +8 -0
- data/ui/rubytext/README.md +191 -0
- data/ui/rubytext/bin/scriptorium-rubytext +402 -0
- data/ui/rubytext/lib/rubytext_ui.rb +300 -0
- data/ui/tui/bin/scriptorium +1420 -0
- data/ui/tui/test/tui_test.rb +23 -0
- data/ui/web/app/app.rb +1378 -0
- data/ui/web/app/error_helpers.rb +150 -0
- data/ui/web/app/views/advanced_config.erb +190 -0
- data/ui/web/app/views/asset_management.erb +589 -0
- data/ui/web/app/views/banner_config.erb +200 -0
- data/ui/web/app/views/configure_view.erb +401 -0
- data/ui/web/app/views/dashboard.erb +162 -0
- data/ui/web/app/views/deploy_config.erb +146 -0
- data/ui/web/app/views/edit_pages.erb +195 -0
- data/ui/web/app/views/edit_post.erb +54 -0
- data/ui/web/app/views/error_page.erb +29 -0
- data/ui/web/app/views/header_config.erb +155 -0
- data/ui/web/app/views/layout_config.erb +147 -0
- data/ui/web/app/views/navbar_config.erb +411 -0
- data/ui/web/app/views/view_dashboard.erb +138 -0
- data/ui/web/bin/scriptorium-web +153 -0
- data/ui/web/test/web_basic_test.rb +38 -0
- data/ui/web/test_navbar.txt +7 -0
- data/ui/web/tmp/web_server.log +5 -0
- data/ui/web/tmp/web_server.pid +1 -0
- metadata +359 -7
- data/lib/scriptorium/engine.rb +0 -22
- data/test/engine/unit.rb +0 -44
@@ -0,0 +1,515 @@
|
|
1
|
+
class Scriptorium::StandardFiles
|
2
|
+
|
3
|
+
# This class generates standard file content for new posts, views, etc.
|
4
|
+
|
5
|
+
include Scriptorium::Helpers
|
6
|
+
|
7
|
+
def initialize # remove?
|
8
|
+
end
|
9
|
+
|
10
|
+
def html_head_content(view = nil)
|
11
|
+
line1global = "# This global file supplies the default values for all views."
|
12
|
+
line2view = "# This view-specific file supplies the default values for this view."
|
13
|
+
line1 = view ? line2view : line1global
|
14
|
+
str = <<~EOS
|
15
|
+
#{line1}
|
16
|
+
# title is omitted - filled in at generation
|
17
|
+
charset UTF-8
|
18
|
+
desc A blog powered by Scriptorium. This is default text intended to be changed by the user.
|
19
|
+
viewport width=device-width initial-scale=1.0
|
20
|
+
robots index follow
|
21
|
+
javascript # See common.js
|
22
|
+
bootstrap # See bootstrap.txt
|
23
|
+
social # See social.txt for configuration
|
24
|
+
EOS
|
25
|
+
end
|
26
|
+
|
27
|
+
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
|
+
}
|
50
|
+
|
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
|
186
|
+
end
|
187
|
+
|
188
|
+
|
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
|
+
|
199
|
+
def bootstrap_js
|
200
|
+
<<~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
|
205
|
+
EOS
|
206
|
+
end
|
207
|
+
|
208
|
+
def available_widgets
|
209
|
+
<<~EOS
|
210
|
+
links
|
211
|
+
pages
|
212
|
+
featuredposts
|
213
|
+
EOS
|
214
|
+
end
|
215
|
+
|
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
|
+
|
243
|
+
def initial_post(mode = :filled, num: "0", title: nil, blurb: nil, views: nil,
|
244
|
+
tags: nil, body: nil)
|
245
|
+
# FIXME - screwed up?
|
246
|
+
title ||= "ADD TITLE HERE"
|
247
|
+
blurb ||= "ADD BLURB HERE"
|
248
|
+
views ||= %w[sample]
|
249
|
+
tags ||= %w[sample tags]
|
250
|
+
body ||= "BEGIN HERE..."
|
251
|
+
|
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
|
267
|
+
|
268
|
+
return str if mode == :raw
|
269
|
+
mytags = tags
|
270
|
+
mytags = tags.join(", ") if tags.is_a?(Array)
|
271
|
+
str2 = str % {num: d4(num.to_i), created: ymdhms, title: title, blurb: blurb,
|
272
|
+
views: views.join(" "), tags: mytags}
|
273
|
+
return str2
|
274
|
+
end
|
275
|
+
|
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
|
+
def initial_post_metadata(num: "0", title: nil, blurb: nil, views: nil, tags: nil)
|
297
|
+
title ||= "ADD TITLE HERE"
|
298
|
+
blurb ||= "ADD BLURB HERE"
|
299
|
+
views ||= %w[sample]
|
300
|
+
tags ||= %w[sample tags]
|
301
|
+
|
302
|
+
mytags = tags
|
303
|
+
mytags = tags.join(", ") if tags.is_a?(Array)
|
304
|
+
|
305
|
+
<<~EOS
|
306
|
+
post.id #{d4(num.to_i)}
|
307
|
+
post.created #{ymdhms}
|
308
|
+
post.published no
|
309
|
+
post.deployed no
|
310
|
+
post.title #{title}
|
311
|
+
post.blurb #{blurb}
|
312
|
+
post.views #{views.join(" ")}
|
313
|
+
post.tags #{mytags}
|
314
|
+
EOS
|
315
|
+
end
|
316
|
+
|
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
|
460
|
+
end
|
461
|
+
|
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
|
470
|
+
end
|
471
|
+
|
472
|
+
def svg_txt
|
473
|
+
<<~EOS
|
474
|
+
aspect 7.0
|
475
|
+
text.font verdana
|
476
|
+
title.color #cccccc
|
477
|
+
subtitle.color #cccccc
|
478
|
+
text.justify left
|
479
|
+
|
480
|
+
title.scale 0.7
|
481
|
+
subtitle.scale 0.3
|
482
|
+
|
483
|
+
title.style bold
|
484
|
+
subtitle.style bold italic
|
485
|
+
title.xy 15 60
|
486
|
+
subtitle.xy 15 85
|
487
|
+
|
488
|
+
back.linear #0000cc #000077 lr
|
489
|
+
|
490
|
+
|
491
|
+
EOS
|
492
|
+
end
|
493
|
+
|
494
|
+
def deploy_text
|
495
|
+
<<~EOS
|
496
|
+
user root
|
497
|
+
server %{domain}
|
498
|
+
docroot /var/www/html
|
499
|
+
path %{view}
|
500
|
+
proto https
|
501
|
+
EOS
|
502
|
+
end
|
503
|
+
|
504
|
+
def status_txt
|
505
|
+
<<~EOS
|
506
|
+
header n
|
507
|
+
banner n
|
508
|
+
navbar n
|
509
|
+
left n
|
510
|
+
right n
|
511
|
+
pages n
|
512
|
+
deploy n
|
513
|
+
EOS
|
514
|
+
end
|
515
|
+
end
|