diff --git a/.gitignore b/.gitignore index a984e33e..21093e09 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .hugo_build.lock __pycache__/ node_modules/ +/forum/import/ diff --git a/Makefile b/Makefile index eddd7b87..8844323c 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,10 @@ PAGEFIND ?= npx -y pagefind@1 DEPLOY_DIR ?= /run/user/$(shell id -u)/gvfs/smb-share:server=barbel-lescar,share=web/oldcomputers DEPLOY_URL ?= https://barbel.synology.me/oldcomputers/ -.PHONY: content build check serve deploy post +.PHONY: content build check serve deploy post forum-up forum-import forum-down content: ## regenerate content/ and static/media/ from the extraction repo - python3 $(OC)/scripts/05_hugo.py --target $(CURDIR) + python3 $(OC)/scripts/05_hugo.py --target $(CURDIR) $(if $(wildcard data/forum.json),--forum) build: ## build the site and its search index into $(BUILD)/ rm -rf $(BUILD) @@ -32,3 +32,17 @@ deploy: check ## build, check, and copy $(BUILD)/ to DEPLOY_DIR (served at DEPL mkdir -p "$(DEPLOY_DIR)" rsync -r --size-only --info=stats1 $(BUILD)/media/ "$(DEPLOY_DIR)/media/" rsync -rc --delete --exclude=/media/ --info=stats1 $(BUILD)/ "$(DEPLOY_DIR)/" + +# --- local test forum (Flarum in Docker, see forum/README.md) --- +FORUM = docker compose -f forum/docker-compose.yml +SITE_URL ?= http://localhost:1313 + +forum-up: ## start the test forum on http://localhost:8081 (admin / adminadmin) + $(FORUM) up -d --build + +forum-import: ## export the archived comments and import them into the test forum + python3 $(OC)/scripts/06_forum.py --target $(CURDIR) + $(FORUM) exec -T flarum php flarum oc:import /import/machines.json --site-url=$(SITE_URL) --map=/import/forum.json + +forum-down: ## stop the test forum (forum-db volume keeps its data) + $(FORUM) down diff --git a/README.md b/README.md index e83aeca8..405258ed 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Static rebuild of old-computers.com with [Hugo](https://gohugo.io/) (0.158 or ne | `static/media/` | generated (copied images and documents) | | `data/slugs.json` | generated, keeps URLs stable between runs — do not delete | | `content/post/` | written by hand: news posts, see below | +| `data/forum.json` | machine → forum thread map, written by the forum import (absent = no forum) | +| `forum/` | forum extension, local test stack, install notes | | `content/_index.md`, `layouts/`, `assets/`, `hugo.toml`, `tools/` | written by hand | | `build/`, `public/` | build output (`make build`, `hugo server`), not versioned | @@ -39,6 +41,14 @@ sends to `/search/`, where results can be filtered by section. Content pages are visitor-comments tabs are not. `hugo server` has no index: use `make build` and serve `build/` to try the search locally. +## Forum and comments + +A [Flarum](https://flarum.org/) forum can run next to the site and serve as its comment system: +with `params.forum.url` set in `hugo.toml`, the menu gets a Forum entry and the Comments tab of +each machine shows that machine's forum thread (archived comments first, new replies after). +With the url empty the site has no forum and shows the archived comments as static text. +Everything about the forum is in [`forum/README.md`](forum/README.md). + ## Usage make content # regenerate from ../oc (OC=path to use another location) diff --git a/assets/css/main.css b/assets/css/main.css index cba51ae4..ce219482 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -162,3 +162,5 @@ table { border-collapse: collapse; } .pager { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 24px 0 0; } .pager a, .pager .current { padding: 4px 10px; border: 1px solid var(--line); border-radius: 4px; text-decoration: none; background: var(--panel); } .pager .current { font-weight: 700; border-color: var(--accent); } + +.forum-thread { display: block; width: 100%; min-height: 400px; border: 0; } diff --git a/assets/js/iframeResizer.min.js b/assets/js/iframeResizer.min.js new file mode 100644 index 00000000..bd6c6422 --- /dev/null +++ b/assets/js/iframeResizer.min.js @@ -0,0 +1,21 @@ +/*! iFrame Resizer (iframeSizer.min.js ) - v4.4.5 - 2024-07-10 + * Desc: Force cross domain iframes to size to content. + * Requires: iframeResizer.contentWindow.min.js to be loaded into the target frame. + * Copyright: (c) 2024 David J. Bradshaw - dave@bradshaw.net + * License: MIT + */ +console.info(` +IFRAME-RESIZER + +Iframe-Resizer 5 is now available via the following two packages: + + * @iframe-resizer/parent + * @iframe-resizer/child + +Additionally their are also new versions of iframe-resizer for React, Vue, and jQuery. + +Version 5 of iframe-resizer has been extensively rewritten to use modern browser APIs, which has enabled significantly better performance and greater accuracy in the detection of content resizing events. + +Please see https://iframe-resizer.com/upgrade for more details. +`),function(d){var c,l,f,a,v,z,I,x,r,u,M,i,m,k;function g(){return window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver}function F(e,n,i){e.addEventListener(n,i,!1)}function B(e,n,i){e.removeEventListener(n,i,!1)}function w(e){return z+"["+(n="Host page: "+(e=e),n=window.top!==window.self?window.parentIFrame&&window.parentIFrame.getId?window.parentIFrame.getId()+": "+e:"Nested host page: "+e:n)+"]";var n}function t(e){return M[e]?M[e].log:f}function R(e,n){o("log",e,n,t(e))}function O(e,n){o("info",e,n,t(e))}function E(e,n){o("warn",e,n,!0)}function o(e,n,i,t){!0===t&&"object"==typeof window.console&&console[e](w(n),i)}function n(e){function i(){t("Height"),t("Width"),P(function(){H(w),C(b),u("onResized",w)},w,"init")}function n(){var e=p.slice(I).split(":"),n=e[1]?parseInt(e[1],10):0,i=M[e[0]]&&M[e[0]].iframe,t=getComputedStyle(i);return{iframe:i,id:e[0],height:n+function(e){if("border-box"!==e.boxSizing)return 0;var n=e.paddingTop?parseInt(e.paddingTop,10):0,e=e.paddingBottom?parseInt(e.paddingBottom,10):0;return n+e}(t)+function(e){if("border-box"!==e.boxSizing)return 0;var n=e.borderTopWidth?parseInt(e.borderTopWidth,10):0,e=e.borderBottomWidth?parseInt(e.borderBottomWidth,10):0;return n+e}(t),width:e[2],type:e[3]}}function t(e){var n=Number(M[b]["max"+e]),i=Number(M[b]["min"+e]),e=e.toLowerCase(),t=Number(w[e]);R(b,"Checking "+e+" is in range "+i+"-"+n),tM[r]["max"+e])throw new Error("Value for min"+e+" can not be greater than max"+e)}}function p(e,n){null===i&&(i=setTimeout(function(){i=null,e()},n))}function b(){"hidden"!==document.visibilityState&&(R("document","Trigger event: Visibility change"),p(function(){y("Tab Visible","resize")},16))}function y(i,t){Object.keys(M).forEach(function(e){var n;M[n=e]&&"parent"===M[n].resizeFrom&&M[n].autoResize&&!M[n].firstRun&&A(i,t,M[e].iframe,e)})}function q(){F(window,"message",n),F(window,"resize",function(){var e;R("window","Trigger event: "+(e="resize")),p(function(){y("Window "+e,"resize")},16)}),F(document,"visibilitychange",b),F(document,"-webkit-visibilitychange",b)}function e(){function t(e,n){if(n){if(!n.tagName)throw new TypeError("Object is not a valid DOM element");if("IFRAME"!==n.tagName.toUpperCase())throw new TypeError("Expected + {{ with resources.Get "js/iframeResizer.min.js" | fingerprint }} + + + {{ end }} + {{ else if eq $tab "comments" }}

Comments left by visitors of the original site. New comments are closed.